diff --git a/docker-compose.gatekeeper.yml b/docker-compose.gatekeeper.yml new file mode 100644 index 0000000..4863599 --- /dev/null +++ b/docker-compose.gatekeeper.yml @@ -0,0 +1,39 @@ +services: + gatekeeper-proxy: + image: alpine:latest + command: sleep infinity + restart: unless-stopped + networks: + - infra + labels: + - "caddy=http://gatekeeper.localhost" + - "caddy.route=/*" + - "caddy.route.0_redir=/ /gatekeeper/login 302" + - "caddy.route.1_reverse_proxy=gatekeeper-app:3000" + + gatekeeper-app: + image: node:20-alpine + working_dir: /app + volumes: + - .:/app + - gatekeeper_root_node_modules:/app/node_modules + - gatekeeper_pkg_node_modules:/app/packages/gatekeeper/node_modules + - gatekeeper_next_cache:/app/packages/gatekeeper/.next + - gatekeeper_pnpm_store:/pnpm + environment: + - NODE_ENV=development + - NPM_TOKEN=${NPM_TOKEN:-} + networks: + - infra + command: > + sh -c "corepack enable && pnpm config set store-dir /pnpm && pnpm install --no-frozen-lockfile && pnpm --filter @mintel/gatekeeper run dev --hostname 0.0.0.0 --port 3000" + +networks: + infra: + external: true + +volumes: + gatekeeper_root_node_modules: + gatekeeper_pkg_node_modules: + gatekeeper_next_cache: + gatekeeper_pnpm_store: diff --git a/package.json b/package.json index ffa754f..e14d66c 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "scripts": { "build": "pnpm -r build", "dev": "pnpm -r dev", + "dev:gatekeeper": "bash -c 'trap \"COMPOSE_PROJECT_NAME=gatekeeper docker-compose -f docker-compose.gatekeeper.yml down\" EXIT INT TERM; docker network create infra 2>/dev/null || true && COMPOSE_PROJECT_NAME=gatekeeper docker-compose -f docker-compose.gatekeeper.yml down && COMPOSE_PROJECT_NAME=gatekeeper docker-compose -f docker-compose.gatekeeper.yml up --build --remove-orphans'", "lint": "pnpm -r --filter='./packages/**' --filter='./apps/**' lint", "test": "pnpm -r test", "changeset": "changeset", diff --git a/packages/gatekeeper/package.json b/packages/gatekeeper/package.json index facbeaf..1373dab 100644 --- a/packages/gatekeeper/package.json +++ b/packages/gatekeeper/package.json @@ -1,6 +1,6 @@ { "name": "@mintel/gatekeeper", - "version": "1.9.5", + "version": "1.9.6", "private": true, "type": "module", "scripts": { @@ -12,10 +12,14 @@ }, "dependencies": { "@mintel/next-utils": "workspace:*", + "@react-three/drei": "^10.7.7", + "@react-three/fiber": "^9.5.0", + "framer-motion": "^11.18.2", "lucide-react": "^0.474.0", "next": "16.1.6", "react": "^19.0.0", - "react-dom": "^19.0.0" + "react-dom": "^19.0.0", + "three": "^0.183.1" }, "devDependencies": { "@mintel/eslint-config": "workspace:*", @@ -25,6 +29,7 @@ "@types/node": "^20.0.0", "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", + "@types/three": "^0.183.1", "autoprefixer": "^10.4.20", "postcss": "^8.4.49", "tailwindcss": "^3.4.17", diff --git a/packages/gatekeeper/src/app/globals.css b/packages/gatekeeper/src/app/globals.css index 186933e..ff9ba1c 100644 --- a/packages/gatekeeper/src/app/globals.css +++ b/packages/gatekeeper/src/app/globals.css @@ -8,7 +8,7 @@ } body { - @apply bg-white text-slate-800 font-serif antialiased selection:bg-slate-900 selection:text-white; + @apply bg-[#f5f5f7] text-black/80 font-serif antialiased selection:bg-black/10 selection:text-black; line-height: 1.6; } @@ -18,15 +18,15 @@ h4, h5, h6 { - @apply font-sans font-bold text-slate-900 tracking-tighter; + @apply font-sans font-bold text-black tracking-tighter; } p { - @apply mb-4 text-base leading-relaxed text-slate-700; + @apply mb-4 text-base leading-relaxed text-black/50; } a { - @apply text-slate-900 hover:text-slate-700 transition-colors no-underline; + @apply text-black/50 hover:text-black transition-colors no-underline; } } @@ -36,34 +36,58 @@ } .btn { - @apply inline-flex items-center justify-center px-6 py-3 border border-slate-200 bg-white text-slate-600 font-sans font-bold text-sm uppercase tracking-widest rounded-full transition-all duration-500 ease-industrial hover:border-slate-400 hover:text-slate-900 hover:bg-slate-50 hover:-translate-y-0.5 hover:shadow-xl hover:shadow-slate-100 active:translate-y-0 active:shadow-sm; + @apply inline-flex items-center justify-center px-6 py-3 border border-black/10 bg-white text-black/60 font-sans font-bold text-sm uppercase tracking-widest rounded-full transition-all duration-500 ease-industrial hover:border-black/20 hover:text-black hover:bg-white hover:-translate-y-0.5 hover:shadow-xl hover:shadow-black/5 active:translate-y-0 active:shadow-sm; } .btn-primary { - @apply border-slate-900 text-slate-900 hover:bg-slate-900 hover:text-white; + @apply border-black bg-black text-white hover:bg-black/85 hover:text-white; } } -/* Custom scrollbar */ +/* Custom scrollbar - light theme */ ::-webkit-scrollbar { - width: 8px; - height: 8px; + width: 6px; + height: 6px; } ::-webkit-scrollbar-track { - background: #f1f5f9; + background: #f5f5f7; } ::-webkit-scrollbar-thumb { - background: #cbd5e1; + background: #d1d1d6; border-radius: 4px; } ::-webkit-scrollbar-thumb:hover { - background: #94a3b8; + background: #b0b0b8; } /* Animations */ +@keyframes fade-in { + from { + opacity: 0; + transform: translateY(12px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes slide-up { + from { + opacity: 0; + transform: translateY(20px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + @keyframes shake { 0%, 100% { @@ -79,6 +103,15 @@ } } +.animate-fade-in { + animation: fade-in 0.8s ease-out forwards; +} + +.animate-slide-up { + animation: slide-up 0.8s ease-out 0.2s forwards; + opacity: 0; +} + .animate-shake { animation: shake 0.2s ease-in-out 0s 2; } diff --git a/packages/gatekeeper/src/app/layout.tsx b/packages/gatekeeper/src/app/layout.tsx index c466d6c..27a1ffd 100644 --- a/packages/gatekeeper/src/app/layout.tsx +++ b/packages/gatekeeper/src/app/layout.tsx @@ -13,6 +13,17 @@ const newsreader = Newsreader({ export const metadata: Metadata = { title: "Gatekeeper | Access Control", description: "Mintel Infrastructure Protection", + openGraph: { + title: "Gatekeeper | Access Control", + description: "Mintel Infrastructure Protection", + siteName: "Mintel Gatekeeper", + type: "website", + }, + twitter: { + card: "summary_large_image", + title: "Gatekeeper | Access Control", + description: "Mintel Infrastructure Protection", + }, }; export default function RootLayout({ diff --git a/packages/gatekeeper/src/app/login/page.tsx b/packages/gatekeeper/src/app/login/page.tsx index 4eccf4e..be05dd8 100644 --- a/packages/gatekeeper/src/app/login/page.tsx +++ b/packages/gatekeeper/src/app/login/page.tsx @@ -1,7 +1,9 @@ import { cookies } from "next/headers"; import { redirect } from "next/navigation"; -import { ArrowRight, ShieldCheck } from "lucide-react"; +import { ShieldCheck } from "lucide-react"; import Image from "next/image"; +import { GateScene } from "../../components/gate-scene"; +import { AnimatedLoginForm } from "../../components/animated-login-form"; interface LoginPageProps { searchParams: Promise<{ [key: string]: string | string[] | undefined }>; @@ -17,8 +19,8 @@ export default async function LoginPage({ searchParams }: LoginPageProps) { async function login(formData: FormData) { "use server"; - const email = (formData.get("email") as string || "").trim(); - const password = (formData.get("password") as string || "").trim(); + const email = ((formData.get("email") as string) || "").trim(); + const password = ((formData.get("password") as string) || "").trim(); const expectedCode = process.env.GATEKEEPER_PASSWORD || "mintel"; const adminEmail = process.env.DIRECTUS_ADMIN_EMAIL; @@ -116,7 +118,9 @@ export default async function LoginPage({ searchParams }: LoginPageProps) { } if (userIdentity) { - console.log(`[Login] Success: ${userIdentity} | Redirect: ${targetRedirect}`); + console.log( + `[Login] Success: ${userIdentity} | Redirect: ${targetRedirect}`, + ); const cookieStore = await cookies(); // Store identity in the cookie (simplified for now, ideally signed) const sessionValue = JSON.stringify({ @@ -127,7 +131,9 @@ export default async function LoginPage({ searchParams }: LoginPageProps) { const isDev = process.env.NODE_ENV === "development"; - console.log(`[Login] Setting Cookie: ${authCookieName} | Domain: ${cookieDomain || "Default"}`); + console.log( + `[Login] Setting Cookie: ${authCookieName} | Domain: ${cookieDomain || "Default"}`, + ); cookieStore.set(authCookieName, sessionValue, { httpOnly: true, @@ -145,101 +151,81 @@ export default async function LoginPage({ searchParams }: LoginPageProps) { } return ( -
- {/* Background Decor - Signature mintel.me style */} -
+
+ {/* 3D Digital Gate Background */} + -
-
- {/* Top Icon Box - Signature mintel.me Black Square */} +
+
+ {/* Top Icon Box */} -
-
-

- {projectName} Gatekeeper +
+
+

+ {projectName} Gatekeeper

-

- - Infrastructure Protection - -

+
+
+

+ Infrastructure Protection +

+
+
{error && ( -
- +
+ Access Denied. Try Again.
)} -
- + {/* The Animated Framer Motion Form */} + -
-
- -
- -
- -
-
- - - - - {/* Bottom Section - Full Branding Parity */} -
-
-
{projectName} -
-

- © 2026 MINTEL + +

+ © {new Date().getFullYear()} MINTEL

diff --git a/packages/gatekeeper/src/app/opengraph-image.tsx b/packages/gatekeeper/src/app/opengraph-image.tsx new file mode 100644 index 0000000..1c474f0 --- /dev/null +++ b/packages/gatekeeper/src/app/opengraph-image.tsx @@ -0,0 +1,126 @@ +import { ImageResponse } from "next/og"; + +export const runtime = "edge"; + +// Image metadata +export const alt = "Gatekeeper Infrastructure Protection"; +export const size = { + width: 1200, + height: 630, +}; + +export const contentType = "image/png"; + +export default async function Image() { + const projectName = process.env.PROJECT_NAME || "MINTEL"; + + return new ImageResponse( +
+ {/* Subtle Background Pattern matching the industrial look */} +
+ + {/* Central Card Element */} +
+ {/* Top Icon Box */} +
+ + + +
+ + {/* Project Name & Typography */} +
+ {projectName}{" "} + + GATEKEEPER + +
+ +
+ Infrastructure Protection +
+
+
, + { + ...size, + }, + ); +} diff --git a/packages/gatekeeper/src/components/animated-login-form.tsx b/packages/gatekeeper/src/components/animated-login-form.tsx new file mode 100644 index 0000000..accb0d1 --- /dev/null +++ b/packages/gatekeeper/src/components/animated-login-form.tsx @@ -0,0 +1,283 @@ +"use client"; + +import { useState, useEffect, useRef } from "react"; +import { motion } from "framer-motion"; +import { ArrowRight, Lock, Shield, Fingerprint } from "lucide-react"; + +interface AnimatedLoginFormProps { + redirectUrl: string; + loginAction: (formData: FormData) => Promise; + projectName: string; +} + +export function AnimatedLoginForm({ + redirectUrl, + loginAction, +}: AnimatedLoginFormProps) { + const [isFocused, setIsFocused] = useState(false); + const [isSubmitting, setIsSubmitting] = useState(false); + const [mounted, setMounted] = useState(false); + const wrapperRef = useRef(null); + const beamRef = useRef(null); + + // Mouse tracking refs (no re-render) + const mouse = useRef({ x: 0, y: 0 }); + const angle = useRef(0); + const tilt = useRef({ x: 0, y: 0 }); + + useEffect(() => { + setMounted(true); + }, []); + + // Single rAF loop: iridescent border + perspective tilt + useEffect(() => { + let animId: number; + + const onMouseMove = (e: MouseEvent) => { + mouse.current = { x: e.clientX, y: e.clientY }; + }; + window.addEventListener("mousemove", onMouseMove); + + const animate = () => { + if (!wrapperRef.current || !beamRef.current) { + animId = requestAnimationFrame(animate); + return; + } + + const rect = wrapperRef.current.getBoundingClientRect(); + const cx = rect.left + rect.width / 2; + const cy = rect.top + rect.height / 2; + const dx = mouse.current.x - cx; + const dy = mouse.current.y - cy; + + // Angle from form center to mouse → positions the bright highlight + const targetAngle = (Math.atan2(dy, dx) * 180) / Math.PI; + + // Lerp angle smoothly (shortest path) + let diff = targetAngle - angle.current; + while (diff > 180) diff -= 360; + while (diff < -180) diff += 360; + angle.current += diff * 0.06; + + // Intensity: slightly stronger on focus + const intensity = isFocused ? 1 : 0.7; + + // Mouse-aligned iridescent conic gradient + // The "hotspot" (brightest white) faces the mouse + beamRef.current.style.background = `conic-gradient(from ${angle.current}deg at 50% 50%, + rgba(255,255,255,${1.0 * intensity}) 0deg, + rgba(200,210,255,${0.8 * intensity}) 20deg, + rgba(255,200,230,${0.7 * intensity}) 45deg, + rgba(150,160,180,${0.6 * intensity}) 80deg, + rgba(40,40,50,${0.5 * intensity}) 160deg, + rgba(20,20,30,${0.4 * intensity}) 200deg, + rgba(140,150,170,${0.5 * intensity}) 280deg, + rgba(210,225,255,${0.7 * intensity}) 320deg, + rgba(255,255,255,${1.0 * intensity}) 360deg)`; + + // Subtle perspective tilt — max ±4deg + const maxTilt = 4; + const normX = dx / (rect.width * 2); + const normY = dy / (rect.height * 2); + const targetTiltY = normX * maxTilt; + const targetTiltX = -normY * maxTilt; + tilt.current.x += (targetTiltX - tilt.current.x) * 0.08; + tilt.current.y += (targetTiltY - tilt.current.y) * 0.08; + + wrapperRef.current.style.transform = `perspective(800px) rotateX(${tilt.current.x}deg) rotateY(${tilt.current.y}deg)`; + + animId = requestAnimationFrame(animate); + }; + + animId = requestAnimationFrame(animate); + return () => { + window.removeEventListener("mousemove", onMouseMove); + cancelAnimationFrame(animId); + }; + }, [isFocused]); + + const handleSubmit = async (formData: FormData) => { + setIsSubmitting(true); + try { + await loginAction(formData); + } finally { + setIsSubmitting(false); + } + }; + + return ( + + {/* Outer wrapper for tilt (refs need non-motion div) */} +
+ {/* ── Always-on iridescent beam border ── */} +
+ {/* Sharp edge layer */} +
+ {/* Soft glow bloom */} +
+
+ + {/* ── Glassmorphism card — high-fidelity glossy light ── */} +
+ {/* Subtle surface "sheen" gradient */} +
+ + {/* Shield icon header */} + +
+
+ +
+ {mounted && ( +
+ )} +
+ + +
setIsFocused(true)} + onBlur={(e) => { + if (!e.currentTarget.contains(e.relatedTarget as Node)) { + setIsFocused(false); + } + }} + > + + +
+ {/* Email Input */} + + + setIsFocused(true)} + className="w-full bg-black/[0.02] border border-black/[0.06] rounded-2xl pl-11 pr-4 py-3.5 focus:outline-none focus:border-black/15 focus:bg-white/80 transition-all duration-300 text-[11px] font-sans font-medium tracking-[0.08em] placeholder:text-black/25 placeholder:normal-case placeholder:tracking-normal text-black/70" + /> +
+ + + {/* Password Input */} + + + setIsFocused(true)} + className="w-full bg-black/[0.02] border border-black/[0.06] rounded-2xl pl-11 pr-4 py-3.5 focus:outline-none focus:border-black/15 focus:bg-white/80 transition-all duration-300 text-[13px] font-sans font-medium tracking-[0.15em] placeholder:text-black/25 placeholder:tracking-normal placeholder:text-[11px] placeholder:font-normal text-black/80" + /> +
+ +
+ + {/* Submit Button */} + + + {!isSubmitting && ( +
+ )} + {isSubmitting ? ( + + + Authenticating... + + ) : ( + + Unlock Access + + + )} + + + + + {/* Security badge */} + +
+ Encrypted Connection + +
+
+
+ ); +} diff --git a/packages/gatekeeper/src/components/gate-scene.tsx b/packages/gatekeeper/src/components/gate-scene.tsx new file mode 100644 index 0000000..2c33e6e --- /dev/null +++ b/packages/gatekeeper/src/components/gate-scene.tsx @@ -0,0 +1,127 @@ +"use client"; + +import { useEffect, useRef } from "react"; + +export function GateScene() { + const canvasRef = useRef(null); + const mouse = useRef({ x: -1000, y: -1000 }); + + useEffect(() => { + const canvas = canvasRef.current; + if (!canvas) return; + const ctx = canvas.getContext("2d"); + if (!ctx) return; + + const FONT_SIZE = 13; + const COL_GAP = 18; + const ROW_GAP = 20; + + interface Cell { + char: string; + alpha: number; + targetAlpha: number; + speed: number; + nextChange: number; + } + + let cells: Cell[][] = []; + let cols = 0; + let rows = 0; + let animId: number; + + const init = () => { + cols = Math.ceil(canvas.width / COL_GAP); + rows = Math.ceil(canvas.height / ROW_GAP); + cells = Array.from({ length: cols }, () => + Array.from({ length: rows }, () => ({ + char: Math.random() > 0.5 ? "1" : "0", + alpha: Math.random() * 0.08, + targetAlpha: Math.random() * 0.15, + speed: 0.008 + Math.random() * 0.02, + nextChange: Math.floor(Math.random() * 80), + })), + ); + }; + + const onMouseMove = (e: MouseEvent) => { + mouse.current = { x: e.clientX, y: e.clientY }; + }; + + const resize = () => { + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + init(); + }; + + let frame = 0; + + const draw = () => { + frame++; + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.font = `${FONT_SIZE}px 'Courier New', monospace`; + + for (let c = 0; c < cols; c++) { + for (let r = 0; r < rows; r++) { + const cell = cells[c][r]; + const x = c * COL_GAP; + const y = r * ROW_GAP + FONT_SIZE; + + // Mouse proximity influence + const dx = mouse.current.x - x; + const dy = mouse.current.y - y; + const distSq = dx * dx + dy * dy; + const proximity = Math.max(0, 1 - Math.sqrt(distSq) / 250); + + // Nudge alpha toward target + cell.alpha += (cell.targetAlpha - cell.alpha) * cell.speed; + + // More aggressive random behavior + if (frame >= cell.nextChange) { + cell.targetAlpha = Math.random() * 0.25; // Higher max alpha + cell.speed = 0.01 + Math.random() * 0.03; // Faster transitions + cell.nextChange = frame + 20 + Math.floor(Math.random() * 80); // More frequent changes + + // Higher flip probability near mouse + const flipProb = 0.3 + proximity * 0.5; + if (Math.random() < flipProb) { + cell.char = cell.char === "0" ? "1" : "0"; + } + } + + const a = Math.min(0.4, cell.alpha + proximity * 0.35); + if (a < 0.01) continue; + + // Dark chars on light background + ctx.fillStyle = `rgba(0, 0, 0, ${a})`; + ctx.fillText(cell.char, x, y); + } + } + + animId = requestAnimationFrame(draw); + }; + + resize(); + window.addEventListener("resize", resize); + window.addEventListener("mousemove", onMouseMove); + animId = requestAnimationFrame(draw); + + return () => { + cancelAnimationFrame(animId); + window.removeEventListener("resize", resize); + window.removeEventListener("mousemove", onMouseMove); + }; + }, []); + + return ( +
+ +
+
+ ); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ecf553e..4f083c2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -232,7 +232,7 @@ importers: version: 5.9.3 vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.33)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.33)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) packages/content-engine: dependencies: @@ -328,6 +328,15 @@ importers: '@mintel/next-utils': specifier: workspace:* version: link:../next-utils + '@react-three/drei': + specifier: ^10.7.7 + version: 10.7.7(@react-three/fiber@9.5.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(three@0.183.1))(@types/react@19.2.13)(@types/three@0.183.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(three@0.183.1) + '@react-three/fiber': + specifier: ^9.5.0 + version: 9.5.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(three@0.183.1) + framer-motion: + specifier: ^11.18.2 + version: 11.18.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) lucide-react: specifier: ^0.474.0 version: 0.474.0(react@19.2.4) @@ -340,6 +349,9 @@ importers: react-dom: specifier: ^19.0.0 version: 19.2.4(react@19.2.4) + three: + specifier: ^0.183.1 + version: 0.183.1 devDependencies: '@mintel/eslint-config': specifier: workspace:* @@ -362,6 +374,9 @@ importers: '@types/react-dom': specifier: ^19.0.0 version: 19.2.3(@types/react@19.2.13) + '@types/three': + specifier: ^0.183.1 + version: 0.183.1 autoprefixer: specifier: ^10.4.20 version: 10.4.24(postcss@8.5.6) @@ -450,7 +465,7 @@ importers: version: 5.9.3 vitest: specifier: ^3.0.4 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.10)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.10)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) packages/meme-generator: dependencies: @@ -625,7 +640,7 @@ importers: version: 5.9.3 vitest: specifier: ^2.0.0 - version: 2.1.9(@types/node@22.19.10)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) + version: 2.1.9(@types/node@22.19.10)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) packages/page-audit: dependencies: @@ -1120,6 +1135,9 @@ packages: resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} engines: {node: '>=20.19.0'} + '@dimforge/rapier3d-compat@0.12.0': + resolution: {integrity: sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==} + '@emnapi/core@1.8.1': resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} @@ -1842,9 +1860,17 @@ packages: '@manypkg/get-packages@1.1.3': resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + '@mediapipe/tasks-vision@0.10.17': + resolution: {integrity: sha512-CZWV/q6TTe8ta61cZXjfnnHsfWIdFhms03M9T7Cnd5y2mdpylJM0rF1qRq+wsQVRMLz1OYPVEBU9ph2Bx8cxrg==} + '@medv/finder@4.0.2': resolution: {integrity: sha512-RraNY9SCcx4KZV0Dh6BEW6XEW2swkqYca74pkFFRw6hHItSHiy+O/xMnpbofjYbzXj0tSpBGthUF1hHTsr3vIQ==} + '@monogrid/gainmap-js@3.4.0': + resolution: {integrity: sha512-2Z0FATFHaoYJ8b+Y4y4Hgfn3FRFwuU5zRrk+9dFWp4uGAdHGqVEdP7HP+gLA3X469KXHmfupJaUbKo1b/aDKIg==} + peerDependencies: + three: '>= 0.159.0' + '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} @@ -2377,6 +2403,42 @@ packages: '@react-pdf/types@2.9.2': resolution: {integrity: sha512-dufvpKId9OajLLbgn9q7VLUmyo1Jf+iyGk2ZHmCL8nIDtL8N1Ejh9TH7+pXXrR0tdie1nmnEb5Bz9U7g4hI4/g==} + '@react-three/drei@10.7.7': + resolution: {integrity: sha512-ff+J5iloR0k4tC++QtD/j9u3w5fzfgFAWDtAGQah9pF2B1YgOq/5JxqY0/aVoQG5r3xSZz0cv5tk2YuBob4xEQ==} + peerDependencies: + '@react-three/fiber': ^9.0.0 + react: ^19 + react-dom: ^19 + three: '>=0.159' + peerDependenciesMeta: + react-dom: + optional: true + + '@react-three/fiber@9.5.0': + resolution: {integrity: sha512-FiUzfYW4wB1+PpmsE47UM+mCads7j2+giRBltfwH7SNhah95rqJs3ltEs9V3pP8rYdS0QlNne+9Aj8dS/SiaIA==} + 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 + '@rolldown/pluginutils@1.0.0-rc.2': resolution: {integrity: sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==} @@ -2806,6 +2868,9 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + '@tweenjs/tween.js@23.1.3': + resolution: {integrity: sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==} + '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} @@ -2839,6 +2904,9 @@ packages: '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/draco3d@1.4.10': + resolution: {integrity: sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw==} + '@types/eslint-scope@3.7.7': resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} @@ -2887,6 +2955,9 @@ packages: '@types/node@22.19.10': resolution: {integrity: sha512-tF5VOugLS/EuDlTBijk0MqABfP8UxgYazTLo3uIn3b4yJgg26QRbVYJYsDtHrjdDUIRfP70+VfhTTc+CE1yskw==} + '@types/offscreencanvas@2019.7.3': + resolution: {integrity: sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==} + '@types/pg-pool@2.0.7': resolution: {integrity: sha512-U4CwmGVQcbEuqpyju8/ptOKg6gEC+Tqsvj2xS9o1g71bUh8twxnC6ZL5rZKCsGN0iyH0CwgUyc9VR5owNQF9Ng==} @@ -2901,18 +2972,32 @@ packages: peerDependencies: '@types/react': ^19.2.0 + '@types/react-reconciler@0.28.9': + resolution: {integrity: sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg==} + peerDependencies: + '@types/react': '*' + '@types/react@19.2.13': resolution: {integrity: sha512-KkiJeU6VbYbUOp5ITMIc7kBfqlYkKA5KhEHVrGMmUUMt7NeaZg65ojdPk+FtNrBAOXNVM5QM72jnADjM+XVRAQ==} '@types/sax@1.2.7': resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} + '@types/stats.js@0.17.4': + resolution: {integrity: sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==} + '@types/tedious@4.0.14': resolution: {integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==} + '@types/three@0.183.1': + resolution: {integrity: sha512-f2Pu5Hrepfgavttdye3PsH5RWyY/AvdZQwIVhrc4uNtvF7nOWJacQKcoVJn0S4f0yYbmAE6AR+ve7xDcuYtMGw==} + '@types/tough-cookie@4.0.5': resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + '@types/webxr@0.5.24': + resolution: {integrity: sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==} + '@types/whatwg-mimetype@3.0.2': resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==} @@ -3073,6 +3158,14 @@ packages: cpu: [x64] os: [win32] + '@use-gesture/core@10.3.1': + resolution: {integrity: sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==} + + '@use-gesture/react@10.3.1': + resolution: {integrity: sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==} + peerDependencies: + react: '>= 16.8.0' + '@vitejs/plugin-react@5.1.3': resolution: {integrity: sha512-NVUnA6gQCl8jfoYqKqQU5Clv0aPw14KkZYCsX6T9Lfu9slI0LOU10OTwFHS/WmptsMMpshNd/1tuWsHQ2Uk+cg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -3220,6 +3313,9 @@ packages: '@webassemblyjs/wast-printer@1.14.1': resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} + '@webgpu/types@0.1.69': + resolution: {integrity: sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ==} + '@xtuc/ieee754@1.2.0': resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} @@ -3542,6 +3638,12 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} + camera-controls@3.1.2: + resolution: {integrity: sha512-xkxfpG2ECZ6Ww5/9+kf4mfg1VEYAoe9aDSY+IwF0UEs7qEzwy0aVRfs2grImIECs/PoBtWFrh7RXsQkwG922JA==} + engines: {node: '>=22.0.0', npm: '>=10.5.1'} + peerDependencies: + three: '>=0.126.1' + caniuse-lite@1.0.30001769: resolution: {integrity: sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==} @@ -3760,6 +3862,11 @@ packages: puppeteer: optional: true + cross-env@7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -3898,6 +4005,9 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + detect-gpu@5.0.70: + resolution: {integrity: sha512-bqerEP1Ese6nt3rFkwPnGbsUF9a4q+gMmpTVVOEzoCyeCc+y7/RvJnQZJx1JwhgQI5Ntg0Kgat8Uu7XpBqnz1w==} + detect-indent@6.1.0: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} @@ -3965,6 +4075,9 @@ packages: resolution: {integrity: sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==} engines: {node: '>=12'} + draco3d@1.5.7: + resolution: {integrity: sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ==} + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -4294,6 +4407,9 @@ packages: picomatch: optional: true + fflate@0.6.10: + resolution: {integrity: sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==} + fflate@0.8.2: resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} @@ -4531,6 +4647,9 @@ packages: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} + glsl-noise@0.0.0: + resolution: {integrity: sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w==} + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -4594,6 +4713,9 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + hls.js@1.6.15: + resolution: {integrity: sha512-E3a5VwgXimGHwpRGV+WxRTKeSp2DW5DI5MWv34ulL3t5UNmyJWCQ1KmLEHbYzcfThfXG8amBL+fCYPneGHC4VA==} + hsl-to-hex@1.0.0: resolution: {integrity: sha512-K6GVpucS5wFf44X0h2bLVRDsycgJmf9FF2elg+CrqD8GcFU8c6vYhgXn8NjUkFCwj+xDFb70qgLbTUm6sxwPmA==} @@ -4688,6 +4810,9 @@ packages: resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} engines: {node: '>= 4'} + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + immutable@5.1.4: resolution: {integrity: sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==} @@ -4850,6 +4975,9 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-promise@2.2.2: + resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + is-reference@1.2.1: resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} @@ -4918,6 +5046,11 @@ packages: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} + its-fine@2.0.0: + resolution: {integrity: sha512-KLViCmWx94zOvpLwSlsx6yOCeMhZYaxrJV87Po5k/FoZzcPSahvK5qJ7fYhS61sZi5ikmh2S3Hz55A2l3U69ng==} + peerDependencies: + react: ^19.0.0 + jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -5038,6 +5171,9 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + lie@3.3.0: + resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + lightningcss-android-arm64@1.30.2: resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} engines: {node: '>= 12.0.0'} @@ -5223,6 +5359,12 @@ packages: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true + maath@0.10.8: + resolution: {integrity: sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g==} + peerDependencies: + '@types/three': '>=0.134.0' + three: '>=0.134.0' + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -5268,6 +5410,14 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + meshline@3.3.1: + resolution: {integrity: sha512-/TQj+JdZkeSUOl5Mk2J7eLcYTLiQm2IDzmlSvYm7ov15anEcDJ92GHqqazxTSreeNgfnYu24kiEvvv0WlbCdFQ==} + peerDependencies: + three: '>=0.137' + + meshoptimizer@1.0.1: + resolution: {integrity: sha512-Vix+QlA1YYT3FwmBBZ+49cE5y/b+pRrcXKqGpS5ouh33d3lSp2PoTpCw19E0cKDFWalembrHnIaZetf27a+W2g==} + micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} @@ -5814,6 +5964,9 @@ packages: resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} engines: {node: '>=0.10.0'} + potpack@1.0.2: + resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==} + prebuild-install@7.1.3: resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} engines: {node: '>=10'} @@ -5858,6 +6011,9 @@ packages: resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} engines: {node: '>=0.4.0'} + promise-worker-transferable@1.0.4: + resolution: {integrity: sha512-bN+0ehEnrXfxV2ZQvU2PetO0n4gqBD4ulq3MI1WOPLgr7/Mg9yRQkX5+0v1vagr74ZTsl7XtzlaYDo2EuCeYJw==} + prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} @@ -5923,6 +6079,15 @@ packages: resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} engines: {node: '>=0.10.0'} + react-use-measure@2.1.7: + resolution: {integrity: sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==} + peerDependencies: + react: '>=16.13' + react-dom: '>=16.13' + peerDependenciesMeta: + react-dom: + optional: true + react@19.2.4: resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} engines: {node: '>=0.10.0'} @@ -6248,6 +6413,15 @@ packages: resolution: {integrity: sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==} engines: {node: '>=6'} + stats-gl@2.4.2: + resolution: {integrity: sha512-g5O9B0hm9CvnM36+v7SFl39T7hmAlv541tU81ME8YeSb3i1CIP5/QdDeSB3A0la0bKNHpxpwxOVRo2wFTYEosQ==} + peerDependencies: + '@types/three': '*' + three: '*' + + stats.js@0.17.0: + resolution: {integrity: sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==} + std-env@3.10.0: resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} @@ -6387,6 +6561,11 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + suspend-react@0.1.3: + resolution: {integrity: sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ==} + peerDependencies: + react: '>=17.0' + svg-arc-to-cubic-bezier@3.2.0: resolution: {integrity: sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==} @@ -6451,6 +6630,19 @@ packages: resolution: {integrity: sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==} engines: {node: '>=20'} + three-mesh-bvh@0.8.3: + resolution: {integrity: sha512-4G5lBaF+g2auKX3P0yqx+MJC6oVt6sB5k+CchS6Ob0qvH0YIhuUk1eYr7ktsIpY+albCqE80/FVQGV190PmiAg==} + peerDependencies: + three: '>= 0.159.0' + + three-stdlib@2.36.1: + resolution: {integrity: sha512-XyGQrFmNQ5O/IoKm556ftwKsBg11TIb301MB5dWNicziQBEs2g3gtOYIf7pFiLa0zI2gUwhtCjv9fmjnxKZ1Cg==} + peerDependencies: + three: '>=0.128.0' + + three@0.183.1: + resolution: {integrity: sha512-Psv6bbd3d/M/01MT2zZ+VmD0Vj2dbWTNhfe4CuSg7w5TuW96M3NOyCVuh9SZQ05CpGmD7NEcJhZw4GVjhCYxfQ==} + through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} @@ -6551,6 +6743,19 @@ packages: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true + troika-three-text@0.52.4: + resolution: {integrity: sha512-V50EwcYGruV5rUZ9F4aNsrytGdKcXKALjEtQXIOBfhVoZU9VAqZNIoGQ3TMiooVqFAbR1w15T+f+8gkzoFzawg==} + peerDependencies: + three: '>=0.125.0' + + troika-three-utils@0.52.4: + resolution: {integrity: sha512-NORAStSVa/BDiG52Mfudk4j1FG4jC4ILutB3foPnfGbOeIs9+G5vZLa0pnmnaftZUGm4UwSoqEpWdqvC7zms3A==} + peerDependencies: + three: '>=0.125.0' + + troika-worker-utils@0.52.0: + resolution: {integrity: sha512-W1CpvTHykaPH5brv5VHLfQo9D1OYuo0cSBEUQFFT/nBUzM8iD6Lq2/tgG/f1OelbAS1WtaTPQzE5uM49egnngw==} + ts-api-utils@2.4.0: resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} engines: {node: '>=18.12'} @@ -6593,6 +6798,9 @@ packages: tunnel-agent@0.6.0: resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + tunnel-rat@0.1.2: + resolution: {integrity: sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -6695,9 +6903,18 @@ packages: peerDependencies: react: ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0 + use-sync-external-store@1.6.0: + resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + utility-types@3.11.0: + resolution: {integrity: sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==} + engines: {node: '>= 4'} + utrie@1.0.2: resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==} @@ -6896,6 +7113,12 @@ packages: resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} engines: {node: '>= 14'} + webgl-constants@1.1.1: + resolution: {integrity: sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg==} + + webgl-sdf-generator@1.1.1: + resolution: {integrity: sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA==} + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -7063,6 +7286,39 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + zustand@4.5.7: + resolution: {integrity: sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==} + 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 + + zustand@5.0.11: + resolution: {integrity: sha512-fdZY+dk7zn/vbWNCYmzZULHRrss0jx5pPFiOuMZ/5HJN6Yv3u+1Wswy/4MpZEkEGhtNH+pwxZB8OKgUBPzYAGg==} + 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 + snapshots: '@acemir/cssom@0.9.31': {} @@ -7779,6 +8035,8 @@ snapshots: '@csstools/css-tokenizer@4.0.0': {} + '@dimforge/rapier3d-compat@0.12.0': {} + '@emnapi/core@1.8.1': dependencies: '@emnapi/wasi-threads': 1.1.0 @@ -8276,8 +8534,15 @@ snapshots: globby: 11.1.0 read-yaml-file: 1.1.0 + '@mediapipe/tasks-vision@0.10.17': {} + '@medv/finder@4.0.2': {} + '@monogrid/gainmap-js@3.4.0(three@0.183.1)': + dependencies: + promise-worker-transferable: 1.0.4 + three: 0.183.1 + '@napi-rs/wasm-runtime@0.2.12': dependencies: '@emnapi/core': 1.8.1 @@ -8867,6 +9132,59 @@ snapshots: '@react-pdf/primitives': 4.1.1 '@react-pdf/stylesheet': 6.1.2 + '@react-three/drei@10.7.7(@react-three/fiber@9.5.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(three@0.183.1))(@types/react@19.2.13)(@types/three@0.183.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(three@0.183.1)': + dependencies: + '@babel/runtime': 7.28.6 + '@mediapipe/tasks-vision': 0.10.17 + '@monogrid/gainmap-js': 3.4.0(three@0.183.1) + '@react-three/fiber': 9.5.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(three@0.183.1) + '@use-gesture/react': 10.3.1(react@19.2.4) + camera-controls: 3.1.2(three@0.183.1) + cross-env: 7.0.3 + detect-gpu: 5.0.70 + glsl-noise: 0.0.0 + hls.js: 1.6.15 + maath: 0.10.8(@types/three@0.183.1)(three@0.183.1) + meshline: 3.3.1(three@0.183.1) + react: 19.2.4 + stats-gl: 2.4.2(@types/three@0.183.1)(three@0.183.1) + stats.js: 0.17.0 + suspend-react: 0.1.3(react@19.2.4) + three: 0.183.1 + three-mesh-bvh: 0.8.3(three@0.183.1) + three-stdlib: 2.36.1(three@0.183.1) + troika-three-text: 0.52.4(three@0.183.1) + tunnel-rat: 0.1.2(@types/react@19.2.13)(react@19.2.4) + use-sync-external-store: 1.6.0(react@19.2.4) + utility-types: 3.11.0 + zustand: 5.0.11(@types/react@19.2.13)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)) + optionalDependencies: + react-dom: 19.2.4(react@19.2.4) + transitivePeerDependencies: + - '@types/react' + - '@types/three' + - immer + + '@react-three/fiber@9.5.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(three@0.183.1)': + dependencies: + '@babel/runtime': 7.28.6 + '@types/webxr': 0.5.24 + base64-js: 1.5.1 + buffer: 6.0.3 + its-fine: 2.0.0(@types/react@19.2.13)(react@19.2.4) + react: 19.2.4 + react-use-measure: 2.1.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + scheduler: 0.27.0 + suspend-react: 0.1.3(react@19.2.4) + three: 0.183.1 + use-sync-external-store: 1.6.0(react@19.2.4) + zustand: 5.0.11(@types/react@19.2.13)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)) + optionalDependencies: + react-dom: 19.2.4(react@19.2.4) + transitivePeerDependencies: + - '@types/react' + - immer + '@rolldown/pluginutils@1.0.0-rc.2': {} '@rollup/plugin-commonjs@28.0.1(rollup@4.57.1)': @@ -9331,6 +9649,8 @@ snapshots: '@tokenizer/token@0.3.0': {} + '@tweenjs/tween.js@23.1.3': {} + '@tybys/wasm-util@0.10.1': dependencies: tslib: 2.8.1 @@ -9377,6 +9697,8 @@ snapshots: '@types/deep-eql@4.0.2': {} + '@types/draco3d@1.4.10': {} + '@types/eslint-scope@3.7.7': dependencies: '@types/eslint': 9.6.1 @@ -9436,6 +9758,8 @@ snapshots: dependencies: undici-types: 6.21.0 + '@types/offscreencanvas@2019.7.3': {} + '@types/pg-pool@2.0.7': dependencies: '@types/pg': 8.15.6 @@ -9455,6 +9779,10 @@ snapshots: dependencies: '@types/react': 19.2.13 + '@types/react-reconciler@0.28.9(@types/react@19.2.13)': + dependencies: + '@types/react': 19.2.13 + '@types/react@19.2.13': dependencies: csstype: 3.2.3 @@ -9463,12 +9791,26 @@ snapshots: dependencies: '@types/node': 20.19.33 + '@types/stats.js@0.17.4': {} + '@types/tedious@4.0.14': dependencies: '@types/node': 20.19.33 + '@types/three@0.183.1': + dependencies: + '@dimforge/rapier3d-compat': 0.12.0 + '@tweenjs/tween.js': 23.1.3 + '@types/stats.js': 0.17.4 + '@types/webxr': 0.5.24 + '@webgpu/types': 0.1.69 + fflate: 0.8.2 + meshoptimizer: 1.0.1 + '@types/tough-cookie@4.0.5': {} + '@types/webxr@0.5.24': {} + '@types/whatwg-mimetype@3.0.2': {} '@types/ws@8.18.1': @@ -9625,6 +9967,13 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true + '@use-gesture/core@10.3.1': {} + + '@use-gesture/react@10.3.1(react@19.2.4)': + dependencies: + '@use-gesture/core': 10.3.1 + react: 19.2.4 + '@vitejs/plugin-react@5.1.3(vite@7.3.1(@types/node@20.19.33)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@babel/core': 7.29.0 @@ -9856,6 +10205,8 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 + '@webgpu/types@0.1.69': {} + '@xtuc/ieee754@1.2.0': {} '@xtuc/long@4.2.2': {} @@ -10138,7 +10489,6 @@ snapshots: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 - optional: true bundle-require@5.1.0(esbuild@0.27.3): dependencies: @@ -10184,6 +10534,10 @@ snapshots: camelcase-css@2.0.1: {} + camera-controls@3.1.2(three@0.183.1): + dependencies: + three: 0.183.1 + caniuse-lite@1.0.30001769: {} canvas@3.2.1: @@ -10399,6 +10753,10 @@ snapshots: - supports-color - utf-8-validate + cross-env@7.0.3: + dependencies: + cross-spawn: 7.0.6 + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -10530,6 +10888,10 @@ snapshots: dequal@2.0.3: {} + detect-gpu@5.0.70: + dependencies: + webgl-constants: 1.1.1 + detect-indent@6.1.0: {} detect-libc@2.1.2: {} @@ -10588,6 +10950,8 @@ snapshots: dotenv@17.3.1: {} + draco3d@1.5.7: {} + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -11116,6 +11480,8 @@ snapshots: optionalDependencies: picomatch: 4.0.3 + fflate@0.6.10: {} + fflate@0.8.2: {} figlet@1.10.0: @@ -11372,6 +11738,8 @@ snapshots: merge2: 1.4.1 slash: 3.0.0 + glsl-noise@0.0.0: {} + gopd@1.2.0: {} got-scraping@4.1.3: @@ -11454,6 +11822,8 @@ snapshots: dependencies: hermes-estree: 0.25.1 + hls.js@1.6.15: {} + hsl-to-hex@1.0.0: dependencies: hsl-to-rgb-for-reals: 1.1.1 @@ -11566,6 +11936,8 @@ snapshots: ignore@7.0.5: {} + immediate@3.0.6: {} + immutable@5.1.4: optional: true @@ -11756,6 +12128,8 @@ snapshots: is-potential-custom-element-name@1.0.1: {} + is-promise@2.2.2: {} + is-reference@1.2.1: dependencies: '@types/estree': 1.0.8 @@ -11824,6 +12198,13 @@ snapshots: has-symbols: 1.1.0 set-function-name: 2.0.2 + its-fine@2.0.0(@types/react@19.2.13)(react@19.2.4): + dependencies: + '@types/react-reconciler': 0.28.9(@types/react@19.2.13) + react: 19.2.4 + transitivePeerDependencies: + - '@types/react' + jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 @@ -11978,6 +12359,10 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + lie@3.3.0: + dependencies: + immediate: 3.0.6 + lightningcss-android-arm64@1.30.2: optional: true @@ -12135,6 +12520,11 @@ snapshots: lz-string@1.5.0: {} + maath@0.10.8(@types/three@0.183.1)(three@0.183.1): + dependencies: + '@types/three': 0.183.1 + three: 0.183.1 + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -12166,6 +12556,12 @@ snapshots: merge2@1.4.1: {} + meshline@3.3.1(three@0.183.1): + dependencies: + three: 0.183.1 + + meshoptimizer@1.0.1: {} + micromatch@4.0.8: dependencies: braces: 3.0.3 @@ -12716,6 +13112,8 @@ snapshots: dependencies: xtend: 4.0.2 + potpack@1.0.2: {} + prebuild-install@7.1.3: dependencies: detect-libc: 2.1.2 @@ -12755,6 +13153,11 @@ snapshots: progress@2.0.3: {} + promise-worker-transferable@1.0.4: + dependencies: + is-promise: 2.2.2 + lie: 3.3.0 + prop-types@15.8.1: dependencies: loose-envify: 1.4.0 @@ -12825,6 +13228,12 @@ snapshots: react-refresh@0.18.0: {} + react-use-measure@2.1.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + dependencies: + react: 19.2.4 + optionalDependencies: + react-dom: 19.2.4(react@19.2.4) + react@19.2.4: {} read-cache@1.0.0: @@ -13232,6 +13641,13 @@ snapshots: dependencies: type-fest: 0.7.1 + stats-gl@2.4.2(@types/three@0.183.1)(three@0.183.1): + dependencies: + '@types/three': 0.183.1 + three: 0.183.1 + + stats.js@0.17.0: {} + std-env@3.10.0: {} stop-iteration-iterator@1.1.0: @@ -13392,6 +13808,10 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + suspend-react@0.1.3(react@19.2.4): + dependencies: + react: 19.2.4 + svg-arc-to-cubic-bezier@3.2.0: {} symbol-tree@3.2.4: {} @@ -13490,6 +13910,22 @@ snapshots: dependencies: real-require: 0.2.0 + three-mesh-bvh@0.8.3(three@0.183.1): + dependencies: + three: 0.183.1 + + three-stdlib@2.36.1(three@0.183.1): + dependencies: + '@types/draco3d': 1.4.10 + '@types/offscreencanvas': 2019.7.3 + '@types/webxr': 0.5.24 + draco3d: 1.5.7 + fflate: 0.6.10 + potpack: 1.0.2 + three: 0.183.1 + + three@0.183.1: {} + through@2.3.8: {} tiny-inflate@1.0.3: {} @@ -13568,6 +14004,20 @@ snapshots: tree-kill@1.2.2: {} + troika-three-text@0.52.4(three@0.183.1): + dependencies: + bidi-js: 1.0.3 + three: 0.183.1 + troika-three-utils: 0.52.4(three@0.183.1) + troika-worker-utils: 0.52.0 + webgl-sdf-generator: 1.1.1 + + troika-three-utils@0.52.4(three@0.183.1): + dependencies: + three: 0.183.1 + + troika-worker-utils@0.52.0: {} + ts-api-utils@2.4.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -13624,6 +14074,14 @@ snapshots: safe-buffer: 5.2.1 optional: true + tunnel-rat@0.1.2(@types/react@19.2.13)(react@19.2.4): + dependencies: + zustand: 4.5.7(@types/react@19.2.13)(react@19.2.4) + transitivePeerDependencies: + - '@types/react' + - immer + - react + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -13762,8 +14220,14 @@ snapshots: intl-messageformat: 11.1.2 react: 19.2.4 + use-sync-external-store@1.6.0(react@19.2.4): + dependencies: + react: 19.2.4 + util-deprecate@1.0.2: {} + utility-types@3.11.0: {} + utrie@1.0.2: dependencies: base64-arraybuffer: 1.0.2 @@ -13874,7 +14338,7 @@ snapshots: tsx: 4.21.0 yaml: 2.8.2 - vitest@2.1.9(@types/node@22.19.10)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0): + vitest@2.1.9(@types/node@22.19.10)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0): dependencies: '@vitest/expect': 2.1.9 '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@22.19.10)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0)) @@ -13912,7 +14376,7 @@ snapshots: - supports-color - terser - vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.33)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.33)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 @@ -13954,7 +14418,7 @@ snapshots: - supports-color - terser - vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.19.10)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.19.10)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 @@ -14052,6 +14516,10 @@ snapshots: web-streams-polyfill@4.0.0-beta.3: {} + webgl-constants@1.1.1: {} + + webgl-sdf-generator@1.1.1: {} + webidl-conversions@3.0.1: {} webidl-conversions@7.0.0: {} @@ -14270,3 +14738,16 @@ snapshots: zod: 3.25.76 zod@3.25.76: {} + + zustand@4.5.7(@types/react@19.2.13)(react@19.2.4): + dependencies: + use-sync-external-store: 1.6.0(react@19.2.4) + optionalDependencies: + '@types/react': 19.2.13 + react: 19.2.4 + + zustand@5.0.11(@types/react@19.2.13)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)): + optionalDependencies: + '@types/react': 19.2.13 + react: 19.2.4 + use-sync-external-store: 1.6.0(react@19.2.4)