diff --git a/site/.gitignore b/site/.gitignore new file mode 100644 index 0000000..de4d1f0 --- /dev/null +++ b/site/.gitignore @@ -0,0 +1,2 @@ +dist +node_modules diff --git a/site/index.html b/site/index.html new file mode 100644 index 0000000..424e8ab --- /dev/null +++ b/site/index.html @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + Gadget Code — Self-Hosted Agentic Engineering Platform + + + + Skip to content + +
+ + + diff --git a/site/package-lock.json b/site/package-lock.json new file mode 100644 index 0000000..a7505b8 --- /dev/null +++ b/site/package-lock.json @@ -0,0 +1,1648 @@ +{ + "name": "gadget-landing-site", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "gadget-landing-site", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@react-three/fiber": "^9.6.1", + "react": "^19.2.5", + "react-dom": "^19.2.5", + "three": "^0.184.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4.2.4", + "@types/react": "^19.2.14", + "@types/react-dom": "^19.2.3", + "@types/three": "^0.184.0", + "@vitejs/plugin-react": "^6.0.1", + "postcss": "^8.5.10", + "tailwindcss": "^4.2.4", + "typescript": "^5.8.3", + "vite": "^8.0.10" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@dimforge/rapier3d-compat": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz", + "integrity": "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", + "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.129.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.129.0.tgz", + "integrity": "sha512-3oz8m3FGdr2nDXVqmFUw7jolKliC4MoyXYIG2c7gpjBnzUWQpUGIYcXYKxTdTi+N2jusvt610ckTMkxdwHkYEg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@react-three/fiber": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-9.6.1.tgz", + "integrity": "sha512-zF0rsKcVYpcJwbFEnv2HkHX9cvOEgsfQo/X8lwmR2dn13S4qEQJXir9fxf5js2LQFoXqxOY7MDkOkYx2uZ4gSg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.17.8", + "@types/webxr": "*", + "base64-js": "^1.5.1", + "buffer": "^6.0.3", + "its-fine": "^2.0.0", + "react-use-measure": "^2.1.7", + "scheduler": "^0.27.0", + "suspend-react": "^0.1.3", + "use-sync-external-store": "^1.4.0", + "zustand": "^5.0.3" + }, + "peerDependencies": { + "expo": ">=43.0", + "expo-asset": ">=8.4", + "expo-file-system": ">=11.0", + "expo-gl": ">=11.0", + "react": ">=19 <19.3", + "react-dom": ">=19 <19.3", + "react-native": ">=0.78", + "three": ">=0.156" + }, + "peerDependenciesMeta": { + "expo": { + "optional": true + }, + "expo-asset": { + "optional": true + }, + "expo-file-system": { + "optional": true + }, + "expo-gl": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0.tgz", + "integrity": "sha512-TWMZnRLMe63C2Lhyicviu7ZHaU4kxa6PS3rofvc9GmcvptzNN11BcfQ4Sl7MwTOsisQoa2keB/EBdNCAnUo8vA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0.tgz", + "integrity": "sha512-6XcD+8k0gPVItNagEw78/qqcBDwKcwDYS8V2hRmVsfUSIrd8cWe/CBvRDI5toqFyPfj+FJr6t8U6Xj2P2prEew==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0.tgz", + "integrity": "sha512-iN/tWVXRQDWvmZlKdceP1Dwug9GDpEymhb9p4xnEe6zvCg5lFmzVljl+1qR1NVx3yfGpr2Na+CuLmv5IU8uzfQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0.tgz", + "integrity": "sha512-jjQMDvvwSOuhOwMszD/klSOjyWMM3zI64hWTj9KT5x4MxRbZAf+7vLQ6qouRhtsLVFHr3f0ILaJAfgENPiQdAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0.tgz", + "integrity": "sha512-d//Dtg2x6/m3mbV64yUGNnDGNZaDGRpDLLNGerHQUVObuNaIQaaDp25yUiqGXtHEXX+NP2d0wAlmKgpYgIAJ2A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0.tgz", + "integrity": "sha512-n7Ofp0mx+aB2cC+Sdy5YtMnXtY9lchnHbY+3Yt0uq9JsWQExf4f5Whu0tK0R8Jdc9S6RchTHjIFY7uc92puOVQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0.tgz", + "integrity": "sha512-EIVjy2cgd7uuMMo94FVkBp7F6DhcZAUwNURkSG3RwUmvAXR6s0ISxM81U+IydcZByPG0pZIHsf1b6kTxoFDgJA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0.tgz", + "integrity": "sha512-JEwwOPcwTLAcpDQlqSmjEmfs63xJnSiUNIGvLcDLUHCWK4XowpS/7c7tUsUH6uT/ct6bMUTdXKfI8967FYj6mg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0.tgz", + "integrity": "sha512-0wjCFhLrihtAubnT9iA0N++0pSV0z5Hg7tNGdNJ4RFaINceHadoF+kiFGyY1qSSNVIAZtLotG8Ju1bgDPkjnFA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0.tgz", + "integrity": "sha512-Dfn7iak9BcMMePxcoJfpSbWqnEyrp/dRF63/8qW/eHBdOZov6x5aShLLEYGYdIeSJ6vMLK/XCVB+lGIxm41bQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0.tgz", + "integrity": "sha512-5/utzzDmD/pD/bmuaUcbTf/sZYy0aztwIVlfpoW1fTjCZ0BaPOMVWGZL1zvgxyi7ZIVYWlxKONHmSbHuiOh8Jw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0.tgz", + "integrity": "sha512-ouJs8VcUomfLfpbUECqFMRqdV4x6aeAK3MA4m6vTrJJjKyWTV5KnxZx7Jd9G+GlDaQQxubcba00x16OyJ1meig==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0.tgz", + "integrity": "sha512-E+oHKGiDA+lsKMmFtffDDw91EryDT7uJocrIuCHqhm6bCTM6xFK+3gaCkYOHfPwQr0cCNarSM2xaELoQDz9jJg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0.tgz", + "integrity": "sha512-yYK02n8Rngo+gbm1y6G0+7jk1sJ/2Wt7K0me0Y7k/ErBpyf+LJ2gFpqWVTcRV1rUepBlQRmpgWkTQCiiwrK0Ow==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0.tgz", + "integrity": "sha512-14bpChMahXRRXiTwahSl+zzHPW6qQTXtkMuJBFlbo+pqSAews2d4BdCSHfrJ/MBsCZtpmTafsY+1QhBzitcmdg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.7", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.7.tgz", + "integrity": "sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tailwindcss/node": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.0.tgz", + "integrity": "sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.21.0", + "jiti": "^2.6.1", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.0" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.0.tgz", + "integrity": "sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.0", + "@tailwindcss/oxide-darwin-arm64": "4.3.0", + "@tailwindcss/oxide-darwin-x64": "4.3.0", + "@tailwindcss/oxide-freebsd-x64": "4.3.0", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.0", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.0", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.0", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.0", + "@tailwindcss/oxide-linux-x64-musl": "4.3.0", + "@tailwindcss/oxide-wasm32-wasi": "4.3.0", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.0", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.0" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.0.tgz", + "integrity": "sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.0.tgz", + "integrity": "sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.0.tgz", + "integrity": "sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.0.tgz", + "integrity": "sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.0.tgz", + "integrity": "sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.0.tgz", + "integrity": "sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.0.tgz", + "integrity": "sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.0.tgz", + "integrity": "sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.0.tgz", + "integrity": "sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.0.tgz", + "integrity": "sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==", + "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.10.0", + "@emnapi/runtime": "^1.10.0", + "@emnapi/wasi-threads": "^1.2.1", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.0.tgz", + "integrity": "sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.0.tgz", + "integrity": "sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.0.tgz", + "integrity": "sha512-Jm05Tjx+9yCLGv5qw1c+84Psds8MnyrEQYCB+FFk2lgGiUjlRqdxke4mVTuYrj2xnVZqKim2Apr5ySuQRYAw/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.3.0", + "@tailwindcss/oxide": "4.3.0", + "postcss": "^8.5.10", + "tailwindcss": "4.3.0" + } + }, + "node_modules/@tweenjs/tween.js": { + "version": "23.1.3", + "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz", + "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", + "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/react-reconciler": { + "version": "0.28.9", + "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.9.tgz", + "integrity": "sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/stats.js": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.4.tgz", + "integrity": "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/three": { + "version": "0.184.1", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.184.1.tgz", + "integrity": "sha512-6q4VdiqVsrTRqmk62/BnlcAvIrnDM0zf2ZDVKI5kZiniWrSaOHaQzmbp+BNzoggc/8tgW412pL//wZIxu2PPTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@dimforge/rapier3d-compat": "~0.12.0", + "@tweenjs/tween.js": "~23.1.3", + "@types/stats.js": "*", + "@types/webxr": ">=0.5.17", + "fflate": "~0.8.2", + "meshoptimizer": "~1.1.1" + } + }, + "node_modules/@types/webxr": { + "version": "0.5.24", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz", + "integrity": "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==", + "license": "MIT" + }, + "node_modules/@vitejs/plugin-react": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.1.tgz", + "integrity": "sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "1.0.0-rc.7" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", + "babel-plugin-react-compiler": "^1.0.0", + "vite": "^8.0.0" + }, + "peerDependenciesMeta": { + "@rolldown/plugin-babel": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + } + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.21.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.3.tgz", + "integrity": "sha512-QyL119InA+XXEkNLNTPCXPugSvOfhwv0JOlGNzvxs0hZaiHLNvXSpudUWsOlsXGWJh8G6ckCScEkVHfX3kw/2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "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/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "dev": true, + "license": "MIT" + }, + "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/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/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/its-fine": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/its-fine/-/its-fine-2.0.0.tgz", + "integrity": "sha512-KLViCmWx94zOvpLwSlsx6yOCeMhZYaxrJV87Po5k/FoZzcPSahvK5qJ7fYhS61sZi5ikmh2S3Hz55A2l3U69ng==", + "license": "MIT", + "dependencies": { + "@types/react-reconciler": "^0.28.9" + }, + "peerDependencies": { + "react": "^19.0.0" + } + }, + "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/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/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/meshoptimizer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-1.1.1.tgz", + "integrity": "sha512-oRFNWJRDA/WTrVj7NWvqa5HqE1t9MYDj2VaWirQCzCCrAd2GHrqR/sQezCxiWATPNlKTcRaPRHPJwIRoPBAp5g==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "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/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "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.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/react": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", + "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", + "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.6" + } + }, + "node_modules/react-use-measure": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.7.tgz", + "integrity": "sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.13", + "react-dom": ">=16.13" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/rolldown": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0.tgz", + "integrity": "sha512-yD986aXDESFGS95spT1LAv0jssywP4npMEjmMHyN2/5+eE8qQJUype2AaKkRiLgBgyD0LFlubwAht7VmY8rGoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.129.0", + "@rolldown/pluginutils": "1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0", + "@rolldown/binding-darwin-arm64": "1.0.0", + "@rolldown/binding-darwin-x64": "1.0.0", + "@rolldown/binding-freebsd-x64": "1.0.0", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0", + "@rolldown/binding-linux-arm64-gnu": "1.0.0", + "@rolldown/binding-linux-arm64-musl": "1.0.0", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0", + "@rolldown/binding-linux-s390x-gnu": "1.0.0", + "@rolldown/binding-linux-x64-gnu": "1.0.0", + "@rolldown/binding-linux-x64-musl": "1.0.0", + "@rolldown/binding-openharmony-arm64": "1.0.0", + "@rolldown/binding-wasm32-wasi": "1.0.0", + "@rolldown/binding-win32-arm64-msvc": "1.0.0", + "@rolldown/binding-win32-x64-msvc": "1.0.0" + } + }, + "node_modules/rolldown/node_modules/@rolldown/pluginutils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0.tgz", + "integrity": "sha512-aKs/3GSWyV0mrhNmt/96/Z3yczC3yvrzYATCiCXQebBsGyYzjNdUphRVLeJQ67ySKVXRfMxt2lm12pmXvbPFQQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/suspend-react": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/suspend-react/-/suspend-react-0.1.3.tgz", + "integrity": "sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ==", + "license": "MIT", + "peerDependencies": { + "react": ">=17.0" + } + }, + "node_modules/tailwindcss": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.0.tgz", + "integrity": "sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==", + "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/three": { + "version": "0.184.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.184.0.tgz", + "integrity": "sha512-wtTRjG92pM5eUg/KuUnHsqSAlPM296brTOcLgMRqEeylYTh/CdtvKUvCyyCQTzFuStieWxvZb8mVTMvdPyUpxg==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/vite": { + "version": "8.0.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.12.tgz", + "integrity": "sha512-w2dDofOWv2QB09ZITZBsvKTVAlYvPR4IAmrY/v0ir9KvLs0xybR7i48wxhM1/oyBWO34wPns+bPGw5ZrZqDpZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.14", + "rolldown": "1.0.0", + "tinyglobby": "^0.2.16" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.18", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/zustand": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.13.tgz", + "integrity": "sha512-efI2tVaVQPqtOh114loML/Z80Y4NP3yc+Ff0fYiZJPauNeWZeIp/bRFD7I9bfmCOYBh/PHxlglQ9+wvlwnPikQ==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + } + } +} diff --git a/site/package.json b/site/package.json new file mode 100644 index 0000000..0beb988 --- /dev/null +++ b/site/package.json @@ -0,0 +1,31 @@ +{ + "name": "gadget-landing-site", + "version": "1.0.0", + "description": "Gadget Code and Gadget — Landing Page", + "type": "module", + "scripts": { + "dev": "vite", + "typecheck": "tsc --noEmit", + "build": "tsc --noEmit && vite build", + "preview": "vite preview" + }, + "author": "Robert Colbert ", + "license": "Apache-2.0", + "dependencies": { + "@react-three/fiber": "^9.6.1", + "react": "^19.2.5", + "react-dom": "^19.2.5", + "three": "^0.184.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4.2.4", + "@types/react": "^19.2.14", + "@types/react-dom": "^19.2.3", + "@types/three": "^0.184.0", + "@vitejs/plugin-react": "^6.0.1", + "postcss": "^8.5.10", + "tailwindcss": "^4.2.4", + "typescript": "^5.8.3", + "vite": "^8.0.10" + } +} diff --git a/site/postcss.config.js b/site/postcss.config.js new file mode 100644 index 0000000..a34a3d5 --- /dev/null +++ b/site/postcss.config.js @@ -0,0 +1,5 @@ +export default { + plugins: { + '@tailwindcss/postcss': {}, + }, +}; diff --git a/site/public/favicon.png b/site/public/favicon.png new file mode 100644 index 0000000..da67231 Binary files /dev/null and b/site/public/favicon.png differ diff --git a/site/public/icon.png b/site/public/icon.png new file mode 100644 index 0000000..bac45f0 Binary files /dev/null and b/site/public/icon.png differ diff --git a/site/public/web-app.png b/site/public/web-app.png new file mode 100644 index 0000000..8894cbd Binary files /dev/null and b/site/public/web-app.png differ diff --git a/site/src/App.tsx b/site/src/App.tsx new file mode 100644 index 0000000..9cd4e38 --- /dev/null +++ b/site/src/App.tsx @@ -0,0 +1,39 @@ +import { useState, useEffect } from 'react'; +import Header from './components/Header'; +import Hero from './components/Hero'; +import ProblemSection from './components/ProblemSection'; +import GadgetCodeSection from './components/GadgetCodeSection'; +import GadgetSection from './components/GadgetSection'; +import BuiltWithSection from './components/BuiltWithSection'; +import GetStartedSection from './components/GetStartedSection'; +import Footer from './components/Footer'; + +export default function App() { + const [scrolled, setScrolled] = useState(false); + + useEffect(() => { + const onScroll = () => setScrolled(window.scrollY > 50); + window.addEventListener('scroll', onScroll, { passive: true }); + return () => window.removeEventListener('scroll', onScroll); + }, []); + + return ( +
+
+
+ +
+ +
+ +
+ +
+ +
+ +
+
+
+ ); +} diff --git a/site/src/components/BuiltWithSection.tsx b/site/src/components/BuiltWithSection.tsx new file mode 100644 index 0000000..9f4dac9 --- /dev/null +++ b/site/src/components/BuiltWithSection.tsx @@ -0,0 +1,63 @@ +export default function BuiltWithSection() { + return ( +
+
+ {/* Section Header */} +
+ + CREDIBILITY + +

+ We Ship Our Own Dogfood +

+
+ + {/* Narrative */} +
+ {/* Status bar accent */} +
+
+ + PRODUCTION VERIFIED + +
+ +

+ Gadget — the browser extension and web app — was built using Gadget Code. + Every feature, every line, every agent-assisted commit. The AI agent + participated in development across all five workspace modes: Inspect, + Station, Update, Agent, and Agent+. +

+ +

+ This isn't a demo project or a proof-of-concept. It's a production + platform that ships production software. The same guardrails, observability, + and agent-first architecture that we're offering to you are what we use + every day to build our own products. +

+ +

+ We don't ship anything we wouldn't use ourselves. Gadget Code built Gadget. + Gadget proves Gadget Code works. +

+ + {/* Visual data strip */} +
+
+ 5 + WORKSPACE MODES +
+
+ 100% + AGENT PARTICIPATION +
+
+ 0 + THIRD-PARTY TRUST REQ +
+
+
+
+
+ ); +} diff --git a/site/src/components/Footer.tsx b/site/src/components/Footer.tsx new file mode 100644 index 0000000..be2527b --- /dev/null +++ b/site/src/components/Footer.tsx @@ -0,0 +1,53 @@ +export default function Footer() { + return ( + + ); +} diff --git a/site/src/components/GadgetCodeSection.tsx b/site/src/components/GadgetCodeSection.tsx new file mode 100644 index 0000000..e5d526c --- /dev/null +++ b/site/src/components/GadgetCodeSection.tsx @@ -0,0 +1,102 @@ +const FEATURES = [ + { + title: 'Agents Are Native', + description: + 'The agent is built into the platform, not duct-taped onto a text editor. It participates in defined modes with explicit boundaries — not as an afterthought extension.', + icon: '⬡', + }, + { + title: 'Full Observability', + description: + 'Every tool call, file operation, and reasoning step is visible in real-time. No black boxes. No surprises. You see what the agent is doing, always.', + icon: '◉', + }, + { + title: 'Workspace Guardrails', + description: + 'Mode-based workspace locking prevents destructive concurrent operations. The agent can\'t edit files you\'re editing. You can\'t delete directories the agent is working in.', + icon: '◧', + }, + { + title: 'Your Infrastructure', + description: + 'Self-hosted. No telemetry. No data harvesting. Your code never leaves your network. Zero third-party trust required. Deploy on your terms.', + icon: '⬢', + }, + { + title: 'Open Source', + description: + 'Apache 2.0 license. Fork it. Own it. Extend it. No vendor lock-in, no seat licenses, no enterprise tiers. The code is yours.', + icon: '⟐', + }, + { + title: 'Choose Your Compute', + description: + 'Ollama, OpenAI, Gab AI, or any OpenAI-compatible API. Route different models to different tasks. Your agents, your compute, your choice.', + icon: '⬡', + }, +]; + +export default function GadgetCodeSection() { + return ( +
+
+ {/* Section Header */} +
+ + SOLUTION + +

+ Engineering, Not Vibes +

+

+ Gadget Code is a self-hosted, open source Agentic Engineering Platform. + The AI agent isn't a bolt-on extension — it's a first-class participant + with guardrails, audit trails, and full observability. +

+
+ + {/* Feature Grid */} +
+ {FEATURES.map((feature) => ( +
+ {/* Icon + Title */} +
+ {feature.icon} +

+ {feature.title.toUpperCase()} +

+
+ + {/* Description */} +

+ {feature.description} +

+
+ ))} +
+ + {/* CTA */} +
+ + GET THE SOURCE CODE + + + + +

+ Free & Open Source · Apache 2.0 · No account required +

+
+
+
+ ); +} diff --git a/site/src/components/GadgetGrid.tsx b/site/src/components/GadgetGrid.tsx new file mode 100644 index 0000000..5d4b423 --- /dev/null +++ b/site/src/components/GadgetGrid.tsx @@ -0,0 +1,444 @@ +// @ts-nocheck +import { useRef, useMemo, useEffect } from 'react'; +import { Canvas, useFrame, useThree } from '@react-three/fiber'; +import * as THREE from 'three'; + +const BOARD_SIZE = 200; +const GRID_DIVISIONS = 16; +const JUNCTION_SPACING = BOARD_SIZE / GRID_DIVISIONS; +const HALF_BOARD = BOARD_SIZE / 2; +const ORB_COUNT = 20; +const PULSE_COUNT = 10; + +interface Junction { + x: number; + z: number; + connections: number[]; +} + +interface Trace { + start: number; + end: number; +} + +interface ParticleData { + pos: THREE.Vector3; + target: THREE.Vector3; + junctionIndex: number; + targetJunctionIndex: number; + progress: number; + speed: number; + type: 'orb' | 'pulse'; +} + +function seededRandom(seed: number): () => number { + let s = seed; + return () => { + s = (s * 9301 + 49297) % 233280; + return s / 233280; + }; +} + +function createGlowTexture(color: string): THREE.CanvasTexture { + const canvas = document.createElement('canvas'); + canvas.width = 64; + canvas.height = 64; + const ctx = canvas.getContext('2d')!; + + const gradient = ctx.createRadialGradient(32, 32, 0, 32, 32, 32); + gradient.addColorStop(0, color); + gradient.addColorStop(0.3, color.replace(')', ', 0.8)').replace('rgb', 'rgba')); + gradient.addColorStop(0.6, color.replace(')', ', 0.3)').replace('rgb', 'rgba')); + gradient.addColorStop(1, 'rgba(0,0,0,0)'); + + ctx.fillStyle = gradient; + ctx.fillRect(0, 0, 64, 64); + + return new THREE.CanvasTexture(canvas); +} + +function generateBoardData() { + const rand = seededRandom(42); + const junctions: Junction[] = []; + const indexMap: Map = new Map(); + + for (let gx = 0; gx <= GRID_DIVISIONS; gx++) { + for (let gz = 0; gz <= GRID_DIVISIONS; gz++) { + const x = -HALF_BOARD + gx * JUNCTION_SPACING; + const z = -HALF_BOARD + gz * JUNCTION_SPACING; + const idx = junctions.length; + junctions.push({ x, z, connections: [] }); + indexMap.set(`${gx},${gz}`, idx); + } + } + + for (let gx = 0; gx <= GRID_DIVISIONS; gx++) { + for (let gz = 0; gz <= GRID_DIVISIONS; gz++) { + const idx = indexMap.get(`${gx},${gz}`); + if (idx === undefined) continue; + + if (gx < GRID_DIVISIONS) { + const rightIdx = indexMap.get(`${gx + 1},${gz}`); + if (rightIdx !== undefined) { + junctions[idx].connections.push(rightIdx); + junctions[rightIdx].connections.push(idx); + } + } + + if (gz < GRID_DIVISIONS) { + const downIdx = indexMap.get(`${gx},${gz + 1}`); + if (downIdx !== undefined) { + junctions[idx].connections.push(downIdx); + junctions[downIdx].connections.push(idx); + } + } + + if (gx < GRID_DIVISIONS && gz < GRID_DIVISIONS && rand() > 0.85) { + const diagIdx = indexMap.get(`${gx + 1},${gz + 1}`); + if (diagIdx !== undefined) { + junctions[idx].connections.push(diagIdx); + junctions[diagIdx].connections.push(idx); + } + } + } + } + + const traceSet = new Set(); + const traces: Trace[] = []; + for (const j of junctions) { + const jIdx = junctions.indexOf(j); + for (const c of j.connections) { + const key = j.x < junctions[c].x || (j.x === junctions[c].x && j.z <= junctions[c].z) + ? `${jIdx},${c}` + : `${c},${jIdx}`; + if (!traceSet.has(key)) { + traceSet.add(key); + traces.push({ start: jIdx, end: c }); + } + } + } + + const chips: Array<{ x: number; z: number; width: number; depth: number }> = []; + const usedIndices = new Set(); + for (let i = 0; i < 22; i++) { + let attempts = 0; + while (attempts < 50) { + const idx = Math.floor(rand() * junctions.length); + if (!usedIndices.has(idx) && junctions[idx].connections.length >= 2) { + usedIndices.add(idx); + chips.push({ + x: junctions[idx].x, + z: junctions[idx].z, + width: 5 + rand() * 7, + depth: 5 + rand() * 7, + }); + break; + } + attempts++; + } + } + + const capacitors: Array<{ x: number; z: number; radius: number; height: number }> = []; + for (let i = 0; i < 45; i++) { + const idx = Math.floor(rand() * junctions.length); + capacitors.push({ + x: junctions[idx].x + (rand() - 0.5) * 3, + z: junctions[idx].z + (rand() - 0.5) * 3, + radius: 0.35 + rand() * 0.45, + height: 1.2 + rand() * 2.2, + }); + } + + const ics: Array<{ x: number; z: number; width: number; depth: number }> = []; + const icCandidates = junctions.filter(j => j.connections.length > 2); + for (let i = 0; i < Math.min(16, icCandidates.length); i++) { + const j = icCandidates[i]; + ics.push({ + x: j.x, + z: j.z, + width: 10 + rand() * 6, + depth: 6 + rand() * 4, + }); + } + + return { junctions, traces, chips, capacitors, ics }; +} + +function TraceLines({ traces, junctions }: { traces: Trace[]; junctions: Junction[] }) { + const geometry = useMemo(() => { + const positions: number[] = []; + for (const t of traces) { + const start = junctions[t.start]; + const end = junctions[t.end]; + positions.push(start.x, 0.1, start.z); + positions.push(end.x, 0.1, end.z); + } + const geo = new THREE.BufferGeometry(); + geo.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3)); + return geo; + }, [traces, junctions]); + + return ( + + + + ); +} + +function Chips({ chips }: { chips: Array<{ x: number; z: number; width: number; depth: number }> }) { + return ( + + {chips.map((chip, i) => ( + + + + + + + + + + {[-1, 1].map((side) => + Array.from({ length: Math.floor(chip.width / 1.2) }).map((_, pi) => ( + + + + + )) + )} + {[-1, 1].map((side) => + Array.from({ length: Math.floor(chip.depth / 1.2) }).map((_, pi) => ( + + + + + )) + )} + + ))} + + ); +} + +function Capacitors({ capacitors }: { capacitors: Array<{ x: number; z: number; radius: number; height: number }> }) { + return ( + + {capacitors.map((cap, i) => ( + + + + + ))} + + ); +} + +function ICs({ ics }: { ics: Array<{ x: number; z: number; width: number; depth: number }> }) { + return ( + + {ics.map((ic, i) => ( + + + + + + + + + + + ))} + + ); +} + +function ParticleSystem({ junctions }: { junctions: Junction[] }) { + const orbRefs = useRef<(THREE.Mesh | null)[]>([]); + const pulseRefs = useRef<(THREE.Mesh | null)[]>([]); + const particles = useRef([]); + const initialized = useRef(false); + const glowTexture = useMemo(() => createGlowTexture('rgb(0, 255, 68)'), []); + const pulseGlowTexture = useMemo(() => createGlowTexture('rgb(0, 255, 255)'), []); + + useEffect(() => { + if (initialized.current) return; + initialized.current = true; + + const rand = seededRandom(Date.now()); + const initial: ParticleData[] = []; + + for (let i = 0; i < ORB_COUNT; i++) { + const idx = Math.floor(rand() * junctions.length); + const conn = junctions[idx].connections; + const target = conn.length > 0 ? conn[Math.floor(rand() * conn.length)] : idx; + initial.push({ + pos: new THREE.Vector3(junctions[idx].x, 0.4, junctions[idx].z), + target: new THREE.Vector3(junctions[target].x, 0.4, junctions[target].z), + junctionIndex: idx, + targetJunctionIndex: target, + progress: rand(), + speed: 0.002 + rand() * 0.003, + type: 'orb', + }); + } + + for (let i = 0; i < PULSE_COUNT; i++) { + const idx = Math.floor(rand() * junctions.length); + const conn = junctions[idx].connections; + const target = conn.length > 0 ? conn[Math.floor(rand() * conn.length)] : idx; + initial.push({ + pos: new THREE.Vector3(junctions[idx].x, 0.4, junctions[idx].z), + target: new THREE.Vector3(junctions[target].x, 0.4, junctions[target].z), + junctionIndex: idx, + targetJunctionIndex: target, + progress: rand(), + speed: 0.01 + rand() * 0.015, + type: 'pulse', + }); + } + + particles.current = initial; + }, [junctions]); + + useFrame(() => { + const p = particles.current; + if (!p.length) return; + + for (let i = 0; i < p.length; i++) { + const particle = p[i]; + particle.progress += particle.speed; + + if (particle.progress >= 1) { + const conn = junctions[particle.junctionIndex].connections; + if (conn.length > 0) { + particle.junctionIndex = particle.targetJunctionIndex; + const nextConn = junctions[particle.targetJunctionIndex].connections.filter(c => c !== particle.junctionIndex); + particle.targetJunctionIndex = nextConn.length > 0 + ? nextConn[Math.floor(Math.random() * nextConn.length)] + : conn[Math.floor(Math.random() * conn.length)]; + particle.progress = 0; + particle.target.set( + junctions[particle.targetJunctionIndex].x, + 0.4, + junctions[particle.targetJunctionIndex].z + ); + } else { + particle.progress = 0; + } + } + + const startJ = junctions[particle.junctionIndex]; + particle.pos.x = startJ.x + (particle.target.x - startJ.x) * particle.progress; + particle.pos.z = startJ.z + (particle.target.z - startJ.z) * particle.progress; + particle.pos.y = 0.4 + Math.sin(particle.progress * Math.PI) * 0.6; + + if (particle.type === 'orb') { + const mesh = orbRefs.current[i]; + if (mesh) { + mesh.position.copy(particle.pos); + } + } else { + const mesh = pulseRefs.current[i - ORB_COUNT]; + if (mesh) { + mesh.position.copy(particle.pos); + const scale = 1 - Math.abs(particle.progress - 0.5) * 2; + mesh.scale.setScalar(0.4 + scale * 0.6); + (mesh.material as THREE.MeshStandardMaterial).emissiveIntensity = 2 + scale * 4; + } + } + } + }); + + return ( + + {Array.from({ length: ORB_COUNT }).map((_, i) => ( + { orbRefs.current[i] = el; }} + > + + + + ))} + {Array.from({ length: PULSE_COUNT }).map((_, i) => ( + { pulseRefs.current[i] = el; }} + rotation={[-Math.PI / 2, 0, 0]} + > + + + + ))} + + ); +} + +function CameraDrift() { + const { camera } = useThree(); + const timeRef = useRef(0); + + useFrame((_, delta) => { + timeRef.current += delta; + const t = timeRef.current; + + camera.position.x = Math.sin(t * 0.05) * 3; + camera.position.y = 80 + Math.sin(t * 0.07) * 2.5; + camera.position.z = Math.cos(t * 0.04) * 5; + + camera.lookAt(0, 0, 0); + }); + + return null; +} + +function Scene() { + const boardData = useMemo(() => generateBoardData(), []); + + return ( + <> + + + + + + + + + + + + + + + + + + ); +} + +export default function GadgetGrid() { + return ( +
+ + + +
+ ); +} diff --git a/site/src/components/GadgetSection.tsx b/site/src/components/GadgetSection.tsx new file mode 100644 index 0000000..a76c982 --- /dev/null +++ b/site/src/components/GadgetSection.tsx @@ -0,0 +1,131 @@ +export default function GadgetSection() { + return ( +
+
+ {/* Section Header */} +
+ + PRODUCT + +

+ Gadget: AI Where You Work +

+

+ An agentic sidebar for your browser and a personal knowledge engine. + Gadget understands context, performs actions, and keeps your information + connected and actionable. +

+
+ + {/* Two Sub-Sections */} +
+ {/* Browser Extension */} +
+
+
+ + + + + + +
+

+ BROWSER EXTENSION +

+
+ +

+ An agentic sidebar integrated into your browsing. Gadget understands + the page you're on and can perform actions on your behalf — research, + form-filling, summarization, and more. It's AI that works where you + already are. +

+ +
+
+ + Context-aware: understands the page you're on +
+
+ + Agentic: performs actions on your behalf +
+
+ + Works in Chrome, Firefox, and Edge +
+
+ + {/* Installation Instructions */} +
+

+ INSTALLATION +

+
+
+ Chrome / Chromium: +

Settings → Extensions → Enable Developer Mode → Load Unpacked → Select extension directory

+
+
+ Firefox: +

about:debugging → This Firefox → Load Temporary Add-on → Select manifest.json from extension directory

+
+
+ Microsoft Edge: +

edge://extensions → Enable Developer Mode → Load Unpacked → Select extension directory

+
+
+
+
+ + {/* Web App */} +
+
+
+ + + + +
+

+ WEB APP +

+
+ +

+ Your personal knowledge engine. Chat with your information, meetings, + documents, and notes. Persistent, searchable, and actionable. Gadget + connects what you know to what you need. +

+ +
+
+ + Chat with your documents and meetings +
+
+ + Persistent, searchable knowledge base +
+
+ + Actions, not just answers +
+
+ + {/* "Built with Gadget Code" badge */} +
+
+
+ + BUILT WITH GADGET CODE + +
+
+
+
+
+
+ ); +} diff --git a/site/src/components/GetStartedSection.tsx b/site/src/components/GetStartedSection.tsx new file mode 100644 index 0000000..afd4d59 --- /dev/null +++ b/site/src/components/GetStartedSection.tsx @@ -0,0 +1,137 @@ +export default function GetStartedSection() { + return ( +
+
+ {/* Section Header */} +
+ + ACCESS + +

+ Get Started +

+
+ + {/* Two Columns */} +
+ {/* Gadget Code (Free) */} +
+ {/* Status header */} +
+
+ + FREE & OPEN SOURCE + +
+ +

+ Gadget Code +

+ +

+ Apache 2.0 License +

+

+ No account. No payment. No telemetry. No vendor lock-in. +

+ + {/* Requirements */} +
+
+ + Self-hosted on your server +
+
+ + MongoDB + Redis + Node.js 22+ +
+
+ + Deploy in minutes +
+
+ + {/* CTAs */} + + GET THE SOURCE CODE + + + INSTALLATION GUIDE + +
+ + {/* Gadget (Subscription) */} +
+ {/* Animated accent line */} +
+ + {/* Status header */} +
+
+ + SUBSCRIPTION + +
+ +

+ Gadget +

+ +

+ AI in Your Browser +

+

+ Subscription-based. Cancel anytime. Pay-as-you-go metered use also available. +

+ + {/* Features */} +
+
+ + Agentic browser sidebar +
+
+ + Personal knowledge engine web app +
+
+ + Chrome, Firefox, and Edge support +
+
+ + {/* CTAs */} + + SUBSCRIBE NOW + + + LEARN MORE + + + {/* "Built with" badge */} +
+
+ + BUILT WITH GADGET CODE + +
+
+
+
+
+ ); +} diff --git a/site/src/components/Header.tsx b/site/src/components/Header.tsx new file mode 100644 index 0000000..ff851d1 --- /dev/null +++ b/site/src/components/Header.tsx @@ -0,0 +1,132 @@ +import { useState, useEffect } from 'react'; + +interface HeaderProps { + scrolled: boolean; +} + +const NAV_LINKS = [ + { label: 'Why Gadget Code', href: '#why' }, + { label: 'Gadget Code', href: '#gadget-code' }, + { label: 'Gadget', href: '#gadget' }, + { label: 'Get Started', href: '#get-started' }, +]; + +export default function Header({ scrolled }: HeaderProps) { + const [mobileOpen, setMobileOpen] = useState(false); + + // Close mobile menu on resize + useEffect(() => { + const onResize = () => { + if (window.innerWidth >= 768) setMobileOpen(false); + }; + window.addEventListener('resize', onResize); + return () => window.removeEventListener('resize', onResize); + }, []); + + return ( +
+
+ {/* Logo / Brand */} + + Gadget Code + + GADGET CODE + + + + {/* Desktop Navigation */} + + + {/* Desktop CTAs */} + + + {/* Mobile menu toggle */} + +
+ + {/* Mobile Navigation */} + {mobileOpen && ( + + )} +
+ ); +} diff --git a/site/src/components/Hero.tsx b/site/src/components/Hero.tsx new file mode 100644 index 0000000..fd00134 --- /dev/null +++ b/site/src/components/Hero.tsx @@ -0,0 +1,106 @@ +import { useState, useEffect, useRef } from 'react'; +import GadgetGrid from './GadgetGrid'; +import { isWebGLAvailable } from '../lib/webgl-detect'; + +export default function Hero() { + const [webgl, setWebgl] = useState(true); + const [visible, setVisible] = useState(false); + const containerRef = useRef(null); + + useEffect(() => { + setWebgl(isWebGLAvailable()); + // Trigger entrance animation after mount + requestAnimationFrame(() => setVisible(true)); + }, []); + + return ( +
+ {/* ThreeJS Background */} + {webgl ? ( + + ) : ( +
+ )} + + {/* Scan line overlay for fallback and subtle depth */} + {!webgl && ( +
+ )} + + {/* Dark overlay for text readability */} +
+ + {/* Content */} +
+ {/* Status indicator */} +
+
+ + SYSTEMS ONLINE + +
+ + {/* App icon */} + Gadget Code + + {/* Tagline */} +

+ Self-Hosted Agentic Engineering +

+ + {/* Subtext */} +

+ The platform where AI agents and humans build software together — + on your infrastructure, under your control. +

+ + {/* CTAs */} + + + {/* Scroll indicator */} +
+ SCROLL + + + +
+
+
+ ); +} diff --git a/site/src/components/ProblemSection.tsx b/site/src/components/ProblemSection.tsx new file mode 100644 index 0000000..5d25ab9 --- /dev/null +++ b/site/src/components/ProblemSection.tsx @@ -0,0 +1,112 @@ +export default function ProblemSection() { + return ( +
+
+ {/* Section Header */} +
+ + ASSESSMENT + +

+ The Platforms Are Failing +

+

+ The tools you depend on to build software are breaking — and the + companies behind them chose AI hype over platform reliability. +

+
+ + {/* Problem Cards */} +
+ {/* GitHub */} +
+
+
+

+ The Platform You Can't Trust +

+
+ +

+ GitHub's uptime has plummeted to ~90%. + A silent merge queue bug deleted committed code across 2,092 pull requests. + CVE-2026-3854 let anyone execute arbitrary code on GitHub's servers via a + standard git push. +

+ +
    +
  • + + 12-hour cascading failure, 5 separate outages (Feb 9) +
  • +
  • + + Redis misconfiguration: 95% of Actions workflows delayed +
  • +
  • + + Codespaces 90% auth failure across EU, Asia, AU +
  • +
  • + + Elasticsearch collapse: global search and PRs down for hours +
  • +
  • + + Ghostty, Zig, tldraw, curl — tier-one projects have fled +
  • +
+ +

+ Your source code deserves better. +

+
+ + {/* VS Code */} +
+
+
+

+ The IDE That Forgot Developers +

+
+ +

+ VS Code is leaking 40GB+ of RAM on + idle. Microsoft forced "Co-authored-by: Copilot" into + your commits — even for code you wrote yourself. RCE vulnerabilities + hit 125 million extension installs. +

+ +
    +
  • + + Copilot metadata hijack: forced AI attribution on human code +
  • +
  • + + Language server leak: 40GB+ RAM on idle configurations +
  • +
  • + + Claude Code extension: 23.2GB RAM out of the box +
  • +
  • + + March 2026 marketplace update broke core extension abstractions +
  • +
  • + + 125M-install RCE: Live Server, Code Runner, and more +
  • +
+ +

+ The IDE chose AI hype over your workflow. +

+
+
+
+
+ ); +} diff --git a/site/src/index.css b/site/src/index.css new file mode 100644 index 0000000..47c40cc --- /dev/null +++ b/site/src/index.css @@ -0,0 +1,154 @@ +@import "tailwindcss"; + +@theme { + --color-brand: #c20600; + --color-brand-light: #e01000; + --color-bg-primary: #0a0a0a; + --color-bg-secondary: #121212; + --color-bg-tertiary: #1a1a1a; + --color-bg-elevated: #202020; + --color-text-primary: #d4d4d4; + --color-text-secondary: #a3a3a3; + --color-text-muted: #737373; + --color-border-subtle: #1a1a1a; + --color-border-default: #2a2a2a; + --color-border-highlight: #3a3a3a; + --color-green-glow: #00ff44; + --color-cyan-glow: #00ffff; + + --font-mono: "Fira Code", "Courier New", Courier, monospace; + --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + + --spacing-header: 48px; +} + +* { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; + scroll-padding-top: 64px; +} + +body { + margin: 0; + font-family: var(--font-sans); + background-color: var(--color-bg-primary); + color: var(--color-text-primary); + line-height: 1.5; + font-size: 14px; + overflow-x: hidden; +} + +#root { + min-height: 100vh; + display: flex; + flex-direction: column; +} + +a { + text-decoration: none; + color: inherit; +} + +button { + cursor: pointer; + font-family: inherit; + font-size: inherit; +} + +/* ── Scrollbar ─────────────────────────────────────────────── */ +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + background: var(--color-bg-secondary); +} + +::-webkit-scrollbar-thumb { + background: var(--color-border-default); +} + +::-webkit-scrollbar-thumb:hover { + background: var(--color-border-highlight); +} + +/* ── Animations ─────────────────────────────────────────────── */ +@keyframes pulse-glow { + 0%, 100% { opacity: 0.6; } + 50% { opacity: 1; } +} + +@keyframes scan-line { + 0% { transform: translateY(-100%); } + 100% { transform: translateY(100vh); } +} + +@keyframes data-stream { + 0% { background-position: 0% 0%; } + 100% { background-position: 0% 100%; } +} + +@keyframes fade-in-up { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes status-blink { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.3; } +} + +.animate-pulse-glow { + animation: pulse-glow 3s ease-in-out infinite; +} + +.animate-fade-in-up { + animation: fade-in-up 0.6s ease-out forwards; +} + +.status-indicator { + animation: status-blink 2s ease-in-out infinite; +} + +/* Reduce motion for accessibility */ +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} + +/* ── Section Dividers ──────────────────────────────────────── */ +.section-divider { + height: 1px; + background: linear-gradient( + 90deg, + transparent 0%, + var(--color-border-default) 20%, + var(--color-brand) 50%, + var(--color-border-default) 80%, + transparent 100% + ); +} + +/* ── Feature Card Hover ────────────────────────────────────── */ +.feature-card { + transition: border-color 0.2s ease, background-color 0.2s ease; +} + +.feature-card:hover { + border-color: var(--color-border-highlight); + background-color: var(--color-bg-tertiary); +} diff --git a/site/src/lib/webgl-detect.ts b/site/src/lib/webgl-detect.ts new file mode 100644 index 0000000..5a122c8 --- /dev/null +++ b/site/src/lib/webgl-detect.ts @@ -0,0 +1,13 @@ +export function isWebGLAvailable(): boolean { + try { + const canvas = document.createElement('canvas'); + const gl = canvas.getContext('webgl2') || canvas.getContext('webgl'); + return gl !== null && gl !== undefined; + } catch { + return false; + } +} + +export function prefersReducedMotion(): boolean { + return window.matchMedia('(prefers-reduced-motion: reduce)').matches; +} diff --git a/site/src/main.tsx b/site/src/main.tsx new file mode 100644 index 0000000..2339d59 --- /dev/null +++ b/site/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/site/tailwind.config.js b/site/tailwind.config.js new file mode 100644 index 0000000..d7a76eb --- /dev/null +++ b/site/tailwind.config.js @@ -0,0 +1,61 @@ +import type { Config } from 'tailwindcss'; + +export default { + content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'], + theme: { + extend: { + colors: { + brand: '#c20600', + 'bg-primary': '#0a0a0a', + 'bg-secondary': '#121212', + 'bg-tertiary': '#1a1a1a', + 'bg-elevated': '#202020', + 'text-primary': '#d4d4d4', + 'text-secondary': '#a3a3a3', + 'text-muted': '#737373', + 'border-subtle': '#1a1a1a', + 'border-default': '#2a2a2a', + 'border-highlight': '#3a3a3a', + }, + fontFamily: { + mono: ['Courier New', 'Courier', 'monospace'], + sans: ['-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'sans-serif'], + }, + spacing: { + 'header': '48px', + 'status': '32px', + }, + animation: { + 'pulse-slow': 'pulse-slow 3s ease-in-out infinite', + 'fade-in': 'fade-in 0.6s ease-out forwards', + 'fade-in-up': 'fade-in-up 0.6s ease-out forwards', + 'glow': 'glow 2s ease-in-out infinite', + 'data-flow': 'data-flow 1.5s ease-in-out infinite', + }, + keyframes: { + 'pulse-slow': { + '0%, 100%': { opacity: '0.4' }, + '50%': { opacity: '1' }, + }, + 'fade-in': { + '0%': { opacity: '0' }, + '100%': { opacity: '1' }, + }, + 'fade-in-up': { + '0%': { opacity: '0', transform: 'translateY(12px)' }, + '100%': { opacity: '1', transform: 'translateY(0)' }, + }, + 'glow': { + '0%, 100%': { boxShadow: '0 0 4px #c2060060' }, + '50%': { boxShadow: '0 0 12px #c20600a0' }, + }, + 'data-flow': { + '0%': { transform: 'translateY(-4px)', opacity: '0' }, + '50%': { opacity: '1' }, + '100%': { transform: 'translateY(4px)', opacity: '0' }, + }, + }, + }, + }, + plugins: [], +} satisfies Config; diff --git a/site/tsconfig.json b/site/tsconfig.json new file mode 100644 index 0000000..957675a --- /dev/null +++ b/site/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "strict": true, + "noEmit": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "allowImportingTsExtensions": true, + "esModuleInterop": true + }, + "include": ["src"] +} diff --git a/site/vite.config.ts b/site/vite.config.ts new file mode 100644 index 0000000..480a5c1 --- /dev/null +++ b/site/vite.config.ts @@ -0,0 +1,31 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + root: '.', + publicDir: 'public', + server: { + port: 5180, + host: '0.0.0.0', + }, + build: { + outDir: 'dist', + emptyOutDir: true, + rolldownOptions: { + output: { + codeSplitting: { + minSize: 20000, + groups: [ + { + name: 'vendor', + test: /[\\/]node_modules[\\/]/, + priority: 10, + maxSize: 250000, + }, + ], + }, + }, + }, + }, +});