From d5f1ce84b4188e6ffa4e3667a0af68c77cd2ac86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20SAILLANT?= <108685187+electron-rare@users.noreply.github.com> Date: Sun, 29 Mar 2026 17:32:38 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20WebGL=20cinematic=20countdown=20?= =?UTF-8?q?=E2=80=94=203D=20atom=20with=20circular=20orbital=20text?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Three.js + React Three Fiber + postprocessing (bloom, chromatic aberration, glitch, scanlines) - Nucleus with pulsing energy core, wireframe icosahedron shell - 3 electron orbits with trail particles + energy arcs - 600 particle cloud with organic movement - Circular orbital text: title, countdown timer, subtitle curved on 3D rings - Mouse interactions: camera parallax, atom speed boost, nucleus glow on proximity - Camera smooth lerp follow with gentle auto-drift - Font fix: woff2 → ttf for troika-three-text compatibility - Logo: static mark instead of missing sprite frames Co-Authored-By: Claude Opus 4.6 (1M context) --- package-lock.json | 675 +++++++++++++++++++++++- package.json | 7 +- public/assets/fonts/manrope-regular.ttf | Bin 0 -> 94972 bytes src/components/AtomGlitch.tsx | 526 ++++++++++++++++++ src/pages/index.astro | 310 +++++------ 5 files changed, 1317 insertions(+), 201 deletions(-) create mode 100644 public/assets/fonts/manrope-regular.ttf create mode 100644 src/components/AtomGlitch.tsx diff --git a/package-lock.json b/package-lock.json index 5cc1966..3217111 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,13 +11,18 @@ "@astrojs/node": "^9.4.5", "@astrojs/react": "^4.4.1", "@radix-ui/react-slot": "^1.2.3", + "@react-three/drei": "^10.7.7", + "@react-three/fiber": "^9.5.0", + "@react-three/postprocessing": "^3.0.4", "astro": "^5.13.8", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "motion": "^12.23.24", + "postprocessing": "^6.39.0", "react": "^19.1.1", "react-dom": "^19.1.1", - "tailwind-merge": "^3.3.1" + "tailwind-merge": "^3.3.1", + "three": "^0.183.2" }, "devDependencies": { "@astrojs/check": "^0.9.6", @@ -1013,9 +1018,7 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", - "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -1077,6 +1080,12 @@ "node": ">=18" } }, + "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==", + "license": "Apache-2.0" + }, "node_modules/@emmetio/abbreviation": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.3.3.tgz", @@ -2189,6 +2198,24 @@ "react": ">=16" } }, + "node_modules/@mediapipe/tasks-vision": { + "version": "0.10.17", + "resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.17.tgz", + "integrity": "sha512-CZWV/q6TTe8ta61cZXjfnnHsfWIdFhms03M9T7Cnd5y2mdpylJM0rF1qRq+wsQVRMLz1OYPVEBU9ph2Bx8cxrg==", + "license": "Apache-2.0" + }, + "node_modules/@monogrid/gainmap-js": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@monogrid/gainmap-js/-/gainmap-js-3.4.0.tgz", + "integrity": "sha512-2Z0FATFHaoYJ8b+Y4y4Hgfn3FRFwuU5zRrk+9dFWp4uGAdHGqVEdP7HP+gLA3X469KXHmfupJaUbKo1b/aDKIg==", + "license": "MIT", + "dependencies": { + "promise-worker-transferable": "^1.0.4" + }, + "peerDependencies": { + "three": ">= 0.159.0" + } + }, "node_modules/@oslojs/encoding": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", @@ -2239,6 +2266,120 @@ } } }, + "node_modules/@react-three/drei": { + "version": "10.7.7", + "resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-10.7.7.tgz", + "integrity": "sha512-ff+J5iloR0k4tC++QtD/j9u3w5fzfgFAWDtAGQah9pF2B1YgOq/5JxqY0/aVoQG5r3xSZz0cv5tk2YuBob4xEQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@mediapipe/tasks-vision": "0.10.17", + "@monogrid/gainmap-js": "^3.0.6", + "@use-gesture/react": "^10.3.1", + "camera-controls": "^3.1.0", + "cross-env": "^7.0.3", + "detect-gpu": "^5.0.56", + "glsl-noise": "^0.0.0", + "hls.js": "^1.5.17", + "maath": "^0.10.8", + "meshline": "^3.3.1", + "stats-gl": "^2.2.8", + "stats.js": "^0.17.0", + "suspend-react": "^0.1.3", + "three-mesh-bvh": "^0.8.3", + "three-stdlib": "^2.35.6", + "troika-three-text": "^0.52.4", + "tunnel-rat": "^0.1.2", + "use-sync-external-store": "^1.4.0", + "utility-types": "^3.11.0", + "zustand": "^5.0.1" + }, + "peerDependencies": { + "@react-three/fiber": "^9.0.0", + "react": "^19", + "react-dom": "^19", + "three": ">=0.159" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/@react-three/fiber": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-9.5.0.tgz", + "integrity": "sha512-FiUzfYW4wB1+PpmsE47UM+mCads7j2+giRBltfwH7SNhah95rqJs3ltEs9V3pP8rYdS0QlNne+9Aj8dS/SiaIA==", + "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/@react-three/postprocessing": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@react-three/postprocessing/-/postprocessing-3.0.4.tgz", + "integrity": "sha512-e4+F5xtudDYvhxx3y0NtWXpZbwvQ0x1zdOXWTbXMK6fFLVDd4qucN90YaaStanZGS4Bd5siQm0lGL/5ogf8iDQ==", + "license": "MIT", + "dependencies": { + "maath": "^0.6.0", + "n8ao": "^1.9.4", + "postprocessing": "^6.36.6" + }, + "peerDependencies": { + "@react-three/fiber": "^9.0.0", + "react": "^19.0", + "three": ">= 0.156.0" + } + }, + "node_modules/@react-three/postprocessing/node_modules/maath": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/maath/-/maath-0.6.0.tgz", + "integrity": "sha512-dSb2xQuP7vDnaYqfoKzlApeRcR2xtN8/f7WV/TMAkBC8552TwTLtOO0JTcSygkYMjNDPoo6V01jTw/aPi4JrMw==", + "license": "MIT", + "peerDependencies": { + "@types/three": ">=0.144.0", + "three": ">=0.144.0" + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", @@ -3230,6 +3371,12 @@ "@testing-library/dom": ">=7.21.4" } }, + "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==", + "license": "MIT" + }, "node_modules/@types/aria-query": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", @@ -3313,6 +3460,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/draco3d": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@types/draco3d/-/draco3d-1.4.10.tgz", + "integrity": "sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw==", + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -3359,6 +3512,12 @@ "@types/unist": "*" } }, + "node_modules/@types/offscreencanvas": { + "version": "2019.7.3", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz", + "integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==", + "license": "MIT" + }, "node_modules/@types/react": { "version": "19.2.14", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", @@ -3379,6 +3538,15 @@ "@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/resolve": { "version": "1.20.6", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", @@ -3386,18 +3554,63 @@ "dev": true, "license": "MIT" }, + "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==", + "license": "MIT" + }, + "node_modules/@types/three": { + "version": "0.183.1", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.183.1.tgz", + "integrity": "sha512-f2Pu5Hrepfgavttdye3PsH5RWyY/AvdZQwIVhrc4uNtvF7nOWJacQKcoVJn0S4f0yYbmAE6AR+ve7xDcuYtMGw==", + "license": "MIT", + "dependencies": { + "@dimforge/rapier3d-compat": "~0.12.0", + "@tweenjs/tween.js": "~23.1.3", + "@types/stats.js": "*", + "@types/webxr": ">=0.5.17", + "@webgpu/types": "*", + "fflate": "~0.8.2", + "meshoptimizer": "~1.0.1" + } + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "license": "MIT" }, + "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/@ungap/structured-clone": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "license": "ISC" }, + "node_modules/@use-gesture/core": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.3.1.tgz", + "integrity": "sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==", + "license": "MIT" + }, + "node_modules/@use-gesture/react": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@use-gesture/react/-/react-10.3.1.tgz", + "integrity": "sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==", + "license": "MIT", + "dependencies": { + "@use-gesture/core": "10.3.1" + }, + "peerDependencies": { + "react": ">= 16.8.0" + } + }, "node_modules/@vitejs/plugin-react": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", @@ -3611,6 +3824,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@webgpu/types": { + "version": "0.1.69", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.69.tgz", + "integrity": "sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ==", + "license": "BSD-3-Clause" + }, "node_modules/acorn": { "version": "8.16.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", @@ -4472,6 +4691,26 @@ "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", "license": "MIT" }, + "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/baseline-browser-mapping": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", @@ -4497,6 +4736,15 @@ "node": ">=12.0.0" } }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -4568,6 +4816,30 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "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/camelcase": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", @@ -4580,6 +4852,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/camera-controls": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/camera-controls/-/camera-controls-3.1.2.tgz", + "integrity": "sha512-xkxfpG2ECZ6Ww5/9+kf4mfg1VEYAoe9aDSY+IwF0UEs7qEzwy0aVRfs2grImIECs/PoBtWFrh7RXsQkwG922JA==", + "license": "MIT", + "engines": { + "node": ">=22.0.0", + "npm": ">=10.5.1" + }, + "peerDependencies": { + "three": ">=0.126.1" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001775", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001775.tgz", @@ -4896,11 +5181,28 @@ "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==", "license": "MIT" }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -5100,6 +5402,15 @@ "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", "license": "MIT" }, + "node_modules/detect-gpu": { + "version": "5.0.70", + "resolved": "https://registry.npmjs.org/detect-gpu/-/detect-gpu-5.0.70.tgz", + "integrity": "sha512-bqerEP1Ese6nt3rFkwPnGbsUF9a4q+gMmpTVVOEzoCyeCc+y7/RvJnQZJx1JwhgQI5Ntg0Kgat8Uu7XpBqnz1w==", + "license": "MIT", + "dependencies": { + "webgl-constants": "^1.1.1" + } + }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -5244,6 +5555,12 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/draco3d": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.7.tgz", + "integrity": "sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ==", + "license": "Apache-2.0" + }, "node_modules/dset": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", @@ -5509,6 +5826,12 @@ } } }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, "node_modules/find-up": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz", @@ -5693,6 +6016,12 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glsl-noise": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/glsl-noise/-/glsl-noise-0.0.0.tgz", + "integrity": "sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w==", + "license": "MIT" + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -5907,6 +6236,12 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hls.js": { + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.6.15.tgz", + "integrity": "sha512-E3a5VwgXimGHwpRGV+WxRTKeSp2DW5DI5MWv34ulL3t5UNmyJWCQ1KmLEHbYzcfThfXG8amBL+fCYPneGHC4VA==", + "license": "Apache-2.0" + }, "node_modules/html-escaper": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", @@ -5949,6 +6284,32 @@ "url": "https://opencollective.com/express" } }, + "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/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" + }, "node_modules/import-meta-resolve": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", @@ -6054,6 +6415,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "license": "MIT" + }, "node_modules/is-wsl": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", @@ -6073,9 +6440,20 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, "license": "ISC" }, + "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/jackspeak": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", @@ -6167,6 +6545,15 @@ "node": ">=6" } }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, "node_modules/lightningcss": { "version": "1.31.1", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", @@ -6470,6 +6857,16 @@ "lz-string": "bin/bin.js" } }, + "node_modules/maath": { + "version": "0.10.8", + "resolved": "https://registry.npmjs.org/maath/-/maath-0.10.8.tgz", + "integrity": "sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g==", + "license": "MIT", + "peerDependencies": { + "@types/three": ">=0.134.0", + "three": ">=0.134.0" + } + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -6731,6 +7128,21 @@ "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", "license": "CC0-1.0" }, + "node_modules/meshline": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/meshline/-/meshline-3.3.1.tgz", + "integrity": "sha512-/TQj+JdZkeSUOl5Mk2J7eLcYTLiQm2IDzmlSvYm7ov15anEcDJ92GHqqazxTSreeNgfnYu24kiEvvv0WlbCdFQ==", + "license": "MIT", + "peerDependencies": { + "three": ">=0.137" + } + }, + "node_modules/meshoptimizer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-1.0.1.tgz", + "integrity": "sha512-Vix+QlA1YYT3FwmBBZ+49cE5y/b+pRrcXKqGpS5ouh33d3lSp2PoTpCw19E0cKDFWalembrHnIaZetf27a+W2g==", + "license": "MIT" + }, "node_modules/micromark": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", @@ -7428,6 +7840,16 @@ "dev": true, "license": "MIT" }, + "node_modules/n8ao": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/n8ao/-/n8ao-1.10.1.tgz", + "integrity": "sha512-hhI1pC+BfOZBV1KMwynBrVlIm8wqLxj/abAWhF2nZ0qQKyzTSQa1QtLVS2veRiuoBQXojxobcnp0oe+PUoxf/w==", + "license": "ISC", + "peerDependencies": { + "postprocessing": ">=6.30.0", + "three": ">=0.137" + } + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -7739,7 +8161,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -7838,6 +8259,21 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postprocessing": { + "version": "6.39.0", + "resolved": "https://registry.npmjs.org/postprocessing/-/postprocessing-6.39.0.tgz", + "integrity": "sha512-/G6JY8hs426lcto/pBZlnFSkyEo1fHsh4gy7FPJtq1SaSUOzJgDW6f6f1K/+aMOYzK/eQEefyOb3++jPPIUeDA==", + "license": "Zlib", + "peerDependencies": { + "three": ">= 0.168.0 < 0.184.0" + } + }, + "node_modules/potpack": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz", + "integrity": "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==", + "license": "ISC" + }, "node_modules/prettier": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", @@ -7879,6 +8315,16 @@ "node": ">=6" } }, + "node_modules/promise-worker-transferable": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/promise-worker-transferable/-/promise-worker-transferable-1.0.4.tgz", + "integrity": "sha512-bN+0ehEnrXfxV2ZQvU2PetO0n4gqBD4ulq3MI1WOPLgr7/Mg9yRQkX5+0v1vagr74ZTsl7XtzlaYDo2EuCeYJw==", + "license": "Apache-2.0", + "dependencies": { + "is-promise": "^2.1.0", + "lie": "^3.0.2" + } + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -7987,6 +8433,21 @@ "node": ">=0.10.0" } }, + "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/readdirp": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", @@ -8231,7 +8692,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -8487,7 +8947,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -8500,7 +8959,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -8582,6 +9040,32 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/stats-gl": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/stats-gl/-/stats-gl-2.4.2.tgz", + "integrity": "sha512-g5O9B0hm9CvnM36+v7SFl39T7hmAlv541tU81ME8YeSb3i1CIP5/QdDeSB3A0la0bKNHpxpwxOVRo2wFTYEosQ==", + "license": "MIT", + "dependencies": { + "@types/three": "*", + "three": "^0.170.0" + }, + "peerDependencies": { + "@types/three": "*", + "three": "*" + } + }, + "node_modules/stats-gl/node_modules/three": { + "version": "0.170.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.170.0.tgz", + "integrity": "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ==", + "license": "MIT" + }, + "node_modules/stats.js": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/stats.js/-/stats.js-0.17.0.tgz", + "integrity": "sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==", + "license": "MIT" + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -9268,6 +9752,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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/svgo": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz", @@ -9324,6 +9817,44 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/three": { + "version": "0.183.2", + "resolved": "https://registry.npmjs.org/three/-/three-0.183.2.tgz", + "integrity": "sha512-di3BsL2FEQ1PA7Hcvn4fyJOlxRRgFYBpMTcyOgkwJIaDOdJMebEFPA+t98EvjuljDx4hNulAGwF6KIjtwI5jgQ==", + "license": "MIT" + }, + "node_modules/three-mesh-bvh": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.8.3.tgz", + "integrity": "sha512-4G5lBaF+g2auKX3P0yqx+MJC6oVt6sB5k+CchS6Ob0qvH0YIhuUk1eYr7ktsIpY+albCqE80/FVQGV190PmiAg==", + "license": "MIT", + "peerDependencies": { + "three": ">= 0.159.0" + } + }, + "node_modules/three-stdlib": { + "version": "2.36.1", + "resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.36.1.tgz", + "integrity": "sha512-XyGQrFmNQ5O/IoKm556ftwKsBg11TIb301MB5dWNicziQBEs2g3gtOYIf7pFiLa0zI2gUwhtCjv9fmjnxKZ1Cg==", + "license": "MIT", + "dependencies": { + "@types/draco3d": "^1.4.0", + "@types/offscreencanvas": "^2019.6.4", + "@types/webxr": "^0.5.2", + "draco3d": "^1.4.1", + "fflate": "^0.6.9", + "potpack": "^1.0.1" + }, + "peerDependencies": { + "three": ">=0.128.0" + } + }, + "node_modules/three-stdlib/node_modules/fflate": { + "version": "0.6.10", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.6.10.tgz", + "integrity": "sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==", + "license": "MIT" + }, "node_modules/tiny-inflate": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", @@ -9401,6 +9932,36 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/troika-three-text": { + "version": "0.52.4", + "resolved": "https://registry.npmjs.org/troika-three-text/-/troika-three-text-0.52.4.tgz", + "integrity": "sha512-V50EwcYGruV5rUZ9F4aNsrytGdKcXKALjEtQXIOBfhVoZU9VAqZNIoGQ3TMiooVqFAbR1w15T+f+8gkzoFzawg==", + "license": "MIT", + "dependencies": { + "bidi-js": "^1.0.2", + "troika-three-utils": "^0.52.4", + "troika-worker-utils": "^0.52.0", + "webgl-sdf-generator": "1.1.1" + }, + "peerDependencies": { + "three": ">=0.125.0" + } + }, + "node_modules/troika-three-utils": { + "version": "0.52.4", + "resolved": "https://registry.npmjs.org/troika-three-utils/-/troika-three-utils-0.52.4.tgz", + "integrity": "sha512-NORAStSVa/BDiG52Mfudk4j1FG4jC4ILutB3foPnfGbOeIs9+G5vZLa0pnmnaftZUGm4UwSoqEpWdqvC7zms3A==", + "license": "MIT", + "peerDependencies": { + "three": ">=0.125.0" + } + }, + "node_modules/troika-worker-utils": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/troika-worker-utils/-/troika-worker-utils-0.52.0.tgz", + "integrity": "sha512-W1CpvTHykaPH5brv5VHLfQo9D1OYuo0cSBEUQFFT/nBUzM8iD6Lq2/tgG/f1OelbAS1WtaTPQzE5uM49egnngw==", + "license": "MIT" + }, "node_modules/trough": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", @@ -9462,6 +10023,43 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/tunnel-rat": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tunnel-rat/-/tunnel-rat-0.1.2.tgz", + "integrity": "sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ==", + "license": "MIT", + "dependencies": { + "zustand": "^4.3.2" + } + }, + "node_modules/tunnel-rat/node_modules/zustand": { + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz", + "integrity": "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.2.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + }, "node_modules/type-fest": { "version": "4.41.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", @@ -9850,6 +10448,24 @@ "browserslist": ">= 4.21.0" } }, + "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/utility-types": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz", + "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", @@ -10264,6 +10880,17 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/webgl-constants": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/webgl-constants/-/webgl-constants-1.1.1.tgz", + "integrity": "sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg==" + }, + "node_modules/webgl-sdf-generator": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/webgl-sdf-generator/-/webgl-sdf-generator-1.1.1.tgz", + "integrity": "sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA==", + "license": "MIT" + }, "node_modules/webpack-virtual-modules": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", @@ -10275,7 +10902,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -10642,6 +11268,35 @@ "zod": "^3" } }, + "node_modules/zustand": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.12.tgz", + "integrity": "sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g==", + "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 + } + } + }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", diff --git a/package.json b/package.json index a838dfb..f4665f0 100644 --- a/package.json +++ b/package.json @@ -26,13 +26,18 @@ "@astrojs/node": "^9.4.5", "@astrojs/react": "^4.4.1", "@radix-ui/react-slot": "^1.2.3", + "@react-three/drei": "^10.7.7", + "@react-three/fiber": "^9.5.0", + "@react-three/postprocessing": "^3.0.4", "astro": "^5.13.8", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "motion": "^12.23.24", + "postprocessing": "^6.39.0", "react": "^19.1.1", "react-dom": "^19.1.1", - "tailwind-merge": "^3.3.1" + "tailwind-merge": "^3.3.1", + "three": "^0.183.2" }, "devDependencies": { "@astrojs/check": "^0.9.6", diff --git a/public/assets/fonts/manrope-regular.ttf b/public/assets/fonts/manrope-regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8594569243efb72d1c156a8d8acb9b5f4eb28e4a GIT binary patch literal 94972 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 JXEAj$000(zNTC1# literal 0 HcmV?d00001 diff --git a/src/components/AtomGlitch.tsx b/src/components/AtomGlitch.tsx new file mode 100644 index 0000000..2af4d91 --- /dev/null +++ b/src/components/AtomGlitch.tsx @@ -0,0 +1,526 @@ +import { useRef, useMemo, useEffect, useState, useCallback } from 'react'; +import { Canvas, useFrame, useThree } from '@react-three/fiber'; +import { Text } from '@react-three/drei'; +import { EffectComposer, Bloom, ChromaticAberration, Scanline, Glitch as GlitchEffect } from '@react-three/postprocessing'; +import { GlitchMode, BlendFunction } from 'postprocessing'; +import * as THREE from 'three'; + +/* =================================================================== + ATOM GLITCH — cinematic WebGL countdown for L'Electron Rare + - Nucleus core with pulsing energy + - 3 electron orbits with trail particles + - Particle cloud (electrons as sparks) + - Post-processing: bloom, chromatic aberration, glitch, scanlines + - Mouse-reactive + auto-orbit + =================================================================== */ + +const COLORS = { + cyan: new THREE.Color('#5bd1d8'), + amber: new THREE.Color('#f1c27a'), + green: new THREE.Color('#b6d18f'), + electric: new THREE.Color('#0071e3'), + white: new THREE.Color('#ffffff'), + nucleus: new THREE.Color('#ff6b35'), +}; + +/* ---------- Particle cloud around the atom ---------- */ +function ParticleField({ count = 600 }) { + const ref = useRef(null); + + const { positions, velocities, colors } = useMemo(() => { + const pos = new Float32Array(count * 3); + const vel = new Float32Array(count * 3); + const col = new Float32Array(count * 3); + const palette = [COLORS.cyan, COLORS.amber, COLORS.green, COLORS.electric]; + + for (let i = 0; i < count; i++) { + const r = 2 + Math.random() * 6; + const theta = Math.random() * Math.PI * 2; + const phi = Math.acos(2 * Math.random() - 1); + pos[i * 3] = r * Math.sin(phi) * Math.cos(theta); + pos[i * 3 + 1] = r * Math.sin(phi) * Math.sin(theta); + pos[i * 3 + 2] = r * Math.cos(phi); + + vel[i * 3] = (Math.random() - 0.5) * 0.004; + vel[i * 3 + 1] = (Math.random() - 0.5) * 0.004; + vel[i * 3 + 2] = (Math.random() - 0.5) * 0.004; + + const c = palette[Math.floor(Math.random() * palette.length)]; + col[i * 3] = c.r; + col[i * 3 + 1] = c.g; + col[i * 3 + 2] = c.b; + } + return { positions: pos, velocities: vel, colors: col }; + }, [count]); + + useFrame(({ clock }) => { + if (!ref.current) return; + const posAttr = ref.current.geometry.attributes.position as THREE.BufferAttribute; + const arr = posAttr.array as Float32Array; + const t = clock.getElapsedTime(); + + for (let i = 0; i < count; i++) { + arr[i * 3] += velocities[i * 3] + Math.sin(t * 0.5 + i) * 0.002; + arr[i * 3 + 1] += velocities[i * 3 + 1] + Math.cos(t * 0.3 + i) * 0.002; + arr[i * 3 + 2] += velocities[i * 3 + 2]; + + // respawn far particles + const dist = Math.sqrt(arr[i * 3] ** 2 + arr[i * 3 + 1] ** 2 + arr[i * 3 + 2] ** 2); + if (dist > 8) { + const r = 2 + Math.random() * 2; + const theta = Math.random() * Math.PI * 2; + const phi = Math.acos(2 * Math.random() - 1); + arr[i * 3] = r * Math.sin(phi) * Math.cos(theta); + arr[i * 3 + 1] = r * Math.sin(phi) * Math.sin(theta); + arr[i * 3 + 2] = r * Math.cos(phi); + } + } + posAttr.needsUpdate = true; + }); + + return ( + + + + + + + + ); +} + +/* ---------- Orbit trail (instanced tube of spheres) ---------- */ +function OrbitTrail({ tilt, speed, color, trailCount = 30 }: { tilt: number[]; speed: number; color: THREE.Color; trailCount?: number }) { + const meshRef = useRef(null); + const phase = useMemo(() => Math.random() * Math.PI * 2, []); + const dummy = useMemo(() => new THREE.Object3D(), []); + const orbitA = 3.2; + const orbitB = orbitA * 0.38; + + useFrame(({ clock }) => { + if (!meshRef.current) return; + const t = clock.getElapsedTime() * speed + phase; + + for (let i = 0; i < trailCount; i++) { + const age = i / trailCount; + const angle = t - age * 0.8; + dummy.position.set(Math.cos(angle) * orbitA, Math.sin(angle) * orbitB, 0); + const s = (1 - age) * 0.14 + 0.02; + dummy.scale.setScalar(s); + dummy.updateMatrix(); + meshRef.current.setMatrixAt(i, dummy.matrix); + } + meshRef.current.instanceMatrix.needsUpdate = true; + }); + + return ( + + + + + + + ); +} + +/* ---------- Orbit ring (thin glowing line) ---------- */ +function OrbitRing({ tilt, color }: { tilt: number[]; color: THREE.Color }) { + const points = useMemo(() => { + const pts: THREE.Vector3[] = []; + for (let i = 0; i <= 128; i++) { + const t = (i / 128) * Math.PI * 2; + pts.push(new THREE.Vector3(Math.cos(t) * 3.2, Math.sin(t) * 3.2 * 0.38, 0)); + } + return pts; + }, []); + const geo = useMemo(() => new THREE.BufferGeometry().setFromPoints(points), [points]); + + return ( + + + + + + ); +} + +/* ---------- Nucleus: pulsing energy core ---------- */ +function Nucleus() { + const coreRef = useRef(null); + const glowRef = useRef(null); + const outerRef = useRef(null); + + useFrame(({ clock, pointer }) => { + const t = clock.getElapsedTime(); + const mouseDist = Math.sqrt(pointer.x ** 2 + pointer.y ** 2); + const mouseProximity = Math.max(0, 1 - mouseDist); // 1 at center, 0 at edges + + if (coreRef.current) { + const s = 1 + Math.sin(t * 3) * 0.08 + Math.sin(t * 7.3) * 0.03 + mouseProximity * 0.15; + coreRef.current.scale.setScalar(s); + (coreRef.current.material as THREE.MeshStandardMaterial).emissiveIntensity = 2 + mouseProximity * 3; + } + if (glowRef.current) { + const s = 1 + Math.sin(t * 2) * 0.15 + mouseProximity * 0.3; + glowRef.current.scale.setScalar(s); + (glowRef.current.material as THREE.MeshStandardMaterial).opacity = 0.15 + Math.sin(t * 4) * 0.08 + mouseProximity * 0.2; + } + if (outerRef.current) { + outerRef.current.rotation.y = t * (0.5 + mouseProximity * 2); + outerRef.current.rotation.x = t * (0.3 + mouseProximity * 1.5); + } + }); + + return ( + + {/* outer energy shell */} + + + + + {/* glow sphere */} + + + + + {/* solid core */} + + + + + + ); +} + +/* ---------- Energy arcs (random lightning) ---------- */ +function EnergyArc({ color }: { color: THREE.Color }) { + const ref = useRef(null); + const [visible, setVisible] = useState(true); + + useFrame(({ clock }) => { + const t = clock.getElapsedTime(); + // flash randomly + setVisible(Math.sin(t * 12 + Math.random() * 100) > 0.7); + + if (ref.current && visible) { + const geo = ref.current.geometry; + const pts: THREE.Vector3[] = []; + const segments = 8; + const startAngle = Math.sin(t * 2) * Math.PI; + for (let i = 0; i <= segments; i++) { + const frac = i / segments; + const r = 0.4 + frac * 2.5; + const angle = startAngle + frac * 1.5; + pts.push(new THREE.Vector3( + Math.cos(angle) * r + (Math.random() - 0.5) * 0.3, + Math.sin(angle) * r * 0.4 + (Math.random() - 0.5) * 0.2, + (Math.random() - 0.5) * 0.4, + )); + } + geo.setFromPoints(pts); + } + }); + + if (!visible) return null; + + return ( + + + + + ); +} + +/* ---------- 3D Circular / Orbital text ---------- */ +const LAUNCH = new Date('2026-05-01T00:00:00+02:00').getTime(); +const FONT_URL = '/assets/fonts/manrope-regular.ttf'; + +function pad(n: number) { return String(n).padStart(2, '0'); } + +/* Each character placed on a circle arc, rotating together */ +function CircularText({ text, radius, speed, tilt, fontSize, color, emissive, opacity = 0.9, spread = 0.8 }: { + text: string; radius: number; speed: number; tilt: number[]; + fontSize: number; color: string; emissive: string; opacity?: number; spread?: number; +}) { + const groupRef = useRef(null); + const chars = useMemo(() => text.split(''), [text]); + const charWidth = fontSize * 0.55; + + useFrame(({ clock }) => { + if (!groupRef.current) return; + const t = clock.getElapsedTime() * speed; + groupRef.current.rotation.y = t; + }); + + return ( + + + {chars.map((char, i) => { + const angle = ((i - chars.length / 2) * charWidth * spread) / radius; + const x = Math.sin(angle) * radius; + const z = Math.cos(angle) * radius; + return ( + + {char} + + + ); + })} + + + ); +} + +/* Countdown — characters on a spinning ring */ +function CountdownRing() { + const [time, setTime] = useState(''); + const groupRef = useRef(null); + const radius = 4.2; + + useEffect(() => { + function tick() { + const diff = Math.max(0, LAUNCH - Date.now()); + const d = Math.floor(diff / 86400000); + const h = Math.floor((diff % 86400000) / 3600000); + const m = Math.floor((diff % 3600000) / 60000); + const s = Math.floor((diff % 60000) / 1000); + setTime(`${pad(d)}J ${pad(h)}H ${pad(m)}M ${pad(s)}S`); + } + tick(); + const id = setInterval(tick, 1000); + return () => clearInterval(id); + }, []); + + useFrame(({ clock }) => { + if (!groupRef.current) return; + groupRef.current.rotation.y = clock.getElapsedTime() * -0.2; + }); + + const chars = time.split(''); + const fontSize = 0.28; + const charWidth = fontSize * 0.5; + + return ( + + + {chars.map((char, i) => { + const angle = ((i - chars.length / 2) * charWidth * 0.9) / radius; + const x = Math.sin(angle) * radius; + const z = Math.cos(angle) * radius; + return ( + + {char} + + + ); + })} + + + ); +} + +/* All circular texts assembled */ +function CountdownText() { + return ( + + {/* "L'electron" — large ring, slow spin */} + + + {/* "rare" — opposite tilt, bigger */} + + + {/* Subtitle — wider ring, slow */} + + + {/* "LANCEMENT DANS" — small ring */} + + + {/* Countdown timer — spinning ring */} + + + {/* Extra decorative text rings */} + + + ); +} + +/* ---------- Main scene ---------- */ +function AtomScene() { + const groupRef = useRef(null); + + const orbits = useMemo(() => [ + { tilt: [-0.5, 0, 0], speed: 1.0, color: COLORS.cyan }, + { tilt: [0.5, 0.3, 0], speed: 0.72, color: COLORS.amber }, + { tilt: [1.57, 0.2, 0.4], speed: 0.55, color: COLORS.green }, + ], []); + + useFrame(({ clock, pointer }) => { + if (!groupRef.current) return; + const t = clock.getElapsedTime(); + // Mouse distance from center = speed boost + const mouseDist = Math.sqrt(pointer.x ** 2 + pointer.y ** 2); + const speedMul = 1 + mouseDist * 0.8; + groupRef.current.rotation.y = t * 0.12 * speedMul + pointer.x * 0.6; + groupRef.current.rotation.x = -0.2 + pointer.y * 0.4; + groupRef.current.rotation.z = pointer.x * 0.1; + }); + + return ( + + + {orbits.map((o, i) => ( + + ))} + {orbits.map((o, i) => ( + + ))} + + + + {/* Textes orbitants — dans le groupe, tournent avec l'atome */} + + + ); +} + +/* ---------- Camera with mouse parallax ---------- */ +function CameraRig() { + const { camera } = useThree(); + const mouse = useRef({ x: 0, y: 0 }); + const smooth = useRef({ x: 0, y: 0 }); + + useFrame(({ clock, pointer }) => { + const t = clock.getElapsedTime(); + + // Smooth mouse follow (lerp) + mouse.current.x = pointer.x; + mouse.current.y = pointer.y; + smooth.current.x += (mouse.current.x - smooth.current.x) * 0.05; + smooth.current.y += (mouse.current.y - smooth.current.y) * 0.05; + + // Camera orbits gently + follows mouse + camera.position.x = Math.sin(t * 0.08) * 0.5 + smooth.current.x * 2.5; + camera.position.y = Math.cos(t * 0.06) * 0.3 + smooth.current.y * 1.5; + camera.position.z = 9 + Math.sin(t * 0.1) * 0.3; + camera.lookAt(smooth.current.x * 0.5, smooth.current.y * 0.3, 0); + }); + + return null; +} + +/* ---------- Exported component ---------- */ +export default function AtomGlitch() { + return ( +
+ + + + + + + + + + + + + + + + + + + +
+ ); +} diff --git a/src/pages/index.astro b/src/pages/index.astro index 58bcb84..a8ec279 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,63 +1,42 @@ --- import BaseLayout from '@/layouts/BaseLayout.astro'; +import AtomGlitch from '@/components/AtomGlitch'; import '@/styles/global.css'; ---
-
- - - - - - - - - - - - - - - - - - - - - - - - -
-

L'électron rare

+ +
+
-
-
-
--jours
-
:
-
--heures
-
:
-
--minutes
-
:
-
--secondes
+ +
+ +
+
+ L'ELECTRON RARE
-
-
- -
+ +
+
+ > + +
+
-
- Systèmes électroniques spécifiques · Formations · Prototypage + +
+ electronique · automatisme · energie + mai 2026 +