diff --git a/components/grid-wallet-prod/.cursor/rules/wallet-skins.mdc b/components/grid-wallet-prod/.cursor/rules/wallet-skins.mdc new file mode 100644 index 000000000..88c218241 --- /dev/null +++ b/components/grid-wallet-prod/.cursor/rules/wallet-skins.mdc @@ -0,0 +1,47 @@ +--- +description: Wallet demo skin architecture — share the brain, not the face +globs: **/src/apps/**/*.{ts,tsx,scss} +alwaysApply: false +--- + +# Wallet demo: share the brain, not the face + +`components/grid-wallet-demo` shares app logic once; each persona ("skin") owns its +entire UI. Full guide: `src/apps/SKINS.md` — read it before building or restyling a skin. + +## The one rule + +A per-skin file is **presentational only**. It calls the shared "brain" — +`useWalletHome()` and `useMoneySheet()` in `apps/shared/wallet` — reads shared data, and +renders. Never re-implement balance math, FX/fees, API calls, card issuance, tap-to-pay, +or bank/address data inside a skin. + +## Restyle by forking the face — never by adding props + +To give a skin its own look, **copy the face** into `apps//wallet/` and edit freely. +Do NOT add props / tokens / variants to a shared component to reskin it. + +## iOS system sheets are shared mechanics, not faces + +OS chrome (the passkey sheet, `apps/shared/PasskeySheet`) looks identical in every app, so +it lives in `apps/shared/` with colors pinned to canonical iOS and the app name passed as +`appName` (from the registry `label`). Don't fork it per skin. Branded auth UI like +`AuthSheet` (OTP) is the opposite — it stays a per-skin face. + +## Don't edit these to change one skin + +`apps/shared/**`, `apps/aurora/**` (shipped — treat as untouchable), `data/`, `lib/`, +`hooks/` are shared by every skin. Edit the skin's own folder instead. + +## Naming: code = category, brand = data + +- Name skin code by its stable category: folder `apps/creator/`, components + `CreatorWalletScreen`, `id: 'creator'`, token `[data-app='creator']`. +- The brand name is a data value: `export const BRAND = '...'` in the skin's `config.ts`, + read by every face + the registry `label`. Re-branding is a one-line edit; never bake a + brand name into a filename or identifier. (Aurora keeps its `aurora` id historically.) + +## Verify before done + +- `npx tsc --noEmit` — ignore the 3 baseline errors (`cornerShape`×2, `superellipse`); add none. +- After any shared change, confirm Aurora (Financial app) looks identical AND your skin works. diff --git a/components/grid-wallet-prod/.dockerignore b/components/grid-wallet-prod/.dockerignore new file mode 100644 index 000000000..d1fb2e565 --- /dev/null +++ b/components/grid-wallet-prod/.dockerignore @@ -0,0 +1,20 @@ +# Build context hygiene — anything here is either rebuilt in the image, secret, +# or irrelevant to the server bundle. +node_modules +.next +.git +.cursor +.playwright-mcp + +# Secrets never belong in an image layer; pass them at `docker run` with +# --env-file / -e instead. +.env +.env.local +.env*.local + +# Local scratch + verification artefacts. +scripts/.tmp-* +*.png +tsconfig.tsbuildinfo +npm-debug.log* +.DS_Store diff --git a/components/grid-wallet-prod/.env.example b/components/grid-wallet-prod/.env.example new file mode 100644 index 000000000..142a9e2e8 --- /dev/null +++ b/components/grid-wallet-prod/.env.example @@ -0,0 +1,18 @@ +# Grid API credentials — from https://app.lightspark.com (Developers → API keys). +GRID_CLIENT_ID= +GRID_CLIENT_SECRET= + +# Grid API base URL (same host for sandbox and production; the KEY decides which). +GRID_API_BASE_URL=https://api.lightspark.com/grid/2025-10-13 + +# Webhook signature verification: the P-256 public key from the dashboard's +# webhook settings. Deliveries to /api/webhooks 401 without a matching key. +GRID_WEBHOOK_PUBKEY="-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n" + +# The customer whose Global Account this demo drives. +GRID_CUSTOMER_ID= + +# Sandbox keys? Gates demo-only affordances that must never run against real +# money (the simulated inbound transfer). NEXT_PUBLIC_* is inlined at BUILD time, +# so a production build must omit this. +NEXT_PUBLIC_GRID_SANDBOX=true diff --git a/components/grid-wallet-prod/.gitignore b/components/grid-wallet-prod/.gitignore new file mode 100644 index 000000000..17447f0db --- /dev/null +++ b/components/grid-wallet-prod/.gitignore @@ -0,0 +1,10 @@ +node_modules/ +.next/ +out/ +.vercel/ +*.tsbuildinfo +next-env.d.ts +.env*.local +.DS_Store +certs/ +.vercel diff --git a/components/grid-wallet-prod/Dockerfile b/components/grid-wallet-prod/Dockerfile new file mode 100644 index 000000000..b03e7c6ed --- /dev/null +++ b/components/grid-wallet-prod/Dockerfile @@ -0,0 +1,56 @@ +# Grid wallet production demo — Next 14 standalone server. +# +# docker build -t grid-wallet-prod . +# docker run --rm -p 4001:4001 --env-file .env.local grid-wallet-prod +# +# Then http://localhost:4001, and the webhook receiver at /api/webhooks +# (point ngrok or your platform's webhook config at that path). +# +# NOTE ON ENV: NEXT_PUBLIC_* is INLINED AT BUILD TIME, so the sandbox flag is a +# build arg, not a runtime var — a production image must be built WITHOUT it, or +# it will still offer the "simulate funding" affordance. Everything else +# (GRID_CLIENT_ID / GRID_CLIENT_SECRET / GRID_API_BASE_URL / GRID_CUSTOMER_ID / +# GRID_WEBHOOK_PUBKEY) is read per request and belongs at `docker run` time. + +# ── deps ────────────────────────────────────────────────────────────────────── +FROM node:22-alpine AS deps +WORKDIR /app +# Playwright is a devDependency used only by the verification scripts; its +# postinstall would otherwise pull ~400MB of browsers into the build. +ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 +COPY package.json package-lock.json ./ +RUN npm ci + +# ── build ───────────────────────────────────────────────────────────────────── +FROM node:22-alpine AS builder +WORKDIR /app +ENV NEXT_TELEMETRY_DISABLED=1 +# Sandbox keys? Pass --build-arg NEXT_PUBLIC_GRID_SANDBOX=true to bake in the +# simulated-funding button. Omit for a production build. +ARG NEXT_PUBLIC_GRID_SANDBOX +ENV NEXT_PUBLIC_GRID_SANDBOX=$NEXT_PUBLIC_GRID_SANDBOX +COPY --from=deps /app/node_modules ./node_modules +COPY . . +RUN npm run build + +# ── run ─────────────────────────────────────────────────────────────────────── +FROM node:22-alpine AS runner +WORKDIR /app +ENV NODE_ENV=production \ + NEXT_TELEMETRY_DISABLED=1 \ + PORT=4001 \ + HOSTNAME=0.0.0.0 +# Unprivileged: nothing here needs root. +RUN addgroup -g 1001 -S nodejs && adduser -S -u 1001 -G nodejs nextjs +# `standalone` traces in only the server files actually reached, and ships its +# own minimal node_modules; static assets and public/ are copied alongside it. +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static +COPY --from=builder --chown=nextjs:nodejs /app/public ./public +USER nextjs +EXPOSE 4001 +# The SSE webhook stream is long-lived; give the container a plain HTTP check +# that doesn't hold a connection open. +HEALTHCHECK --interval=30s --timeout=5s --start-period=20s \ + CMD node -e "fetch('http://127.0.0.1:'+(process.env.PORT||4001)+'/').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" +CMD ["node", "server.js"] diff --git a/components/grid-wallet-prod/README.md b/components/grid-wallet-prod/README.md new file mode 100644 index 000000000..14ae4b94e --- /dev/null +++ b/components/grid-wallet-prod/README.md @@ -0,0 +1,95 @@ +# Grid Wallet Prod + +Live demo of the **Grid Global Accounts** wallet lifecycle, running against the real Grid API, +forked from [`components/grid-wallet-demo`](../grid-wallet-demo) (the scripted variant embedded in +the Grid docs). Same stack and design system: Next.js 14 + React 18 + TypeScript, SCSS modules, +`@lightsparkdev/origin` tokens + text-style mixins, `@central-icons-react` icons, `motion`. + +Differences from the demo: + +- No config sidebar — the layout is the phone plus the API panel. +- The use case is pinned to **Fintech**, and the bank corridors to the **US + euro area** + (ACH/wire/RTP and SEPA — the two rails this wallet settles). +- Calls are **real**. The panel shows only traffic that actually happened: the request and response + of every call to Grid, plus webhooks Grid delivered. A flow with no client call behind it (card + issuance, tap to pay) logs nothing rather than inventing a request. + +## Auth + +Sign-in leads with the credential a Global Account is actually born with — `EMAIL_OTP`, with the +entry step prefilled from that credential's own `nickname`. A passkey is added **later**, from the +wallet, as its own signed action (one device ceremony, authorized by the live session). Once this +device has registered a passkey the sign-in button says so, and the passkey carries subsequent +sign-ins. + +Passkeys are device-bound: one listed on the account but registered on another device is ignored +here, because `navigator.credentials.get` in this browser could never satisfy it. + +A session lasts 15 minutes. Inside it, no re-authentication — each signed action (a cash-out) +stamps the quote's `payloadToSign` with the session key. Past it, the next signed action +re-authenticates in place. + +## Money in + +Two shapes, and the API only supports each one way: + +- **Push** — a country's deposit instructions, read off the customer's own fiat account + (`GET /customers/internal-accounts`): account number, routing number, the rails they settle on, + and the reference that credits the deposit. The EUR block is a marked placeholder + (`src/data/placeholderDeposit.ts`) until the customer has an EUR internal account; the read + already returns one section per fiat account, so a real one appears with no code change. +- **Pull** — "add an account", which quotes from the registered `ExternalAccount`. Grid rejects + `POST /quotes/{id}/execute` for such a quote ("funds must be pushed to Lightspark from the source + account"), so the quote is created and left pending until the payment lands. Amounts here are in + USD cents, not the wallet's USDB micro-units. +- **Crypto** — USDC on Base / Solana / Ethereum: pick a network, enter an amount, and the screen + shows the real Grid-provisioned deposit address for that chain. + +Arrival is reported by **webhook**, not by tapping: `INCOMING_PAYMENT.COMPLETED` drives the toast +and the Activity row, and the balance is re-read from the API. + +## Webhooks + +`POST /api/webhooks` verifies `X-Grid-Signature` against `GRID_WEBHOOK_PUBKEY` (SHA256/ECDSA over +the raw body, P-256 SPKI PEM). Grid sends `{"v":"1","s":""}`; a bare base64 header is also +accepted, per the docs. Verified deliveries are **pushed** to the panel over SSE +(`GET /api/webhooks/stream`) — nothing polls. + +To receive real deliveries locally, tunnel the port and register the URL with your platform: + +```bash +ngrok http 4001 # then register https://.ngrok-free.app/api/webhooks +``` + +## Develop + +```bash +cp .env.example .env.local # then fill in the values (see below) +npm install --ignore-scripts # --ignore-scripts avoids a central-icons license postinstall +npm run dev # http://localhost:4001 (grid-wallet-demo keeps 4000) +npm test # vitest +``` + +`NEXT_PUBLIC_GRID_SANDBOX=true` gates the sandbox-only "simulate funding" button in the API panel. +`NEXT_PUBLIC_*` is inlined at **build** time, so a production build must omit it. + +There's also a `Dockerfile` (`output: 'standalone'`, port 4001): + +```bash +docker build -t grid-wallet-prod --build-arg NEXT_PUBLIC_GRID_SANDBOX=true . +docker run --rm -p 4001:4001 --env-file .env.local grid-wallet-prod +``` + +## Sandbox notes + +- The magic OTP is `000000`. Sandbox **skips email delivery** — the code the phone "receives" is + simulated; the HPKE encryption and signature verification around it are real. +- `POST /sandbox/send` stands in for a customer pushing funds to a pending quote. That's what the + panel's "Simulate funding" button calls when a pull quote is waiting. +- A direct sandbox fund of the wallet itself (`POST /sandbox/internal-accounts/{id}/fund`) only + mints **book** balance with no on-chain USDB, which is why the balance hero shows available with + the account total beneath — the two diverge in sandbox. The instructions-screen stand-in funds the + platform's USD account and on-ramps from it instead. +- Any fee Grid's on-ramp charges comes straight out of the real quote (observed anywhere from $0 to + ~$0.20 on a $5–$20 add across sandbox runs), so the balance credit can land at or slightly under + the amount you added — that's real fee behavior, not a bug. diff --git a/components/grid-wallet-prod/next.config.mjs b/components/grid-wallet-prod/next.config.mjs new file mode 100644 index 000000000..6be58cc9d --- /dev/null +++ b/components/grid-wallet-prod/next.config.mjs @@ -0,0 +1,67 @@ +import * as sass from 'sass'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +/** @type {import('next').NextConfig} */ +const nextConfig = { + // Self-contained server bundle (.next/standalone) — what the Docker runtime + // stage copies, so the image carries no node_modules of its own. + output: 'standalone', + transpilePackages: ['@lightsparkdev/origin'], + typescript: { + // Origin is source-linked without its own node_modules, + // so its transitive type imports can't resolve from ../origin + ignoreBuildErrors: true, + }, + sassOptions: { + implementation: sass, + importers: [new sass.NodePackageImporter(__dirname)], + includePaths: [ + path.resolve(__dirname, 'node_modules'), + ], + }, + async headers() { + return [ + { + source: '/:path*', + headers: [ + { + key: 'Content-Security-Policy', + value: "frame-ancestors 'self' https://docs.lightspark.com https://*.lightspark.com https://*.mintlify.app https://*.mintlify.dev http://localhost:*", + }, + ], + }, + ]; + }, + webpack: (config) => { + // Ensure dependencies imported by the local Origin package resolve from + // this project's node_modules. The relative 'node_modules' entry comes + // FIRST so webpack's default nested walk-up still wins (e.g. @turnkey/crypto's + // own node_modules/@noble/* pin, which differs from this project's top-level + // @noble/* version and exports different subpaths) — the absolute path is + // only a fallback for imports with no node_modules to walk up from. + config.resolve.modules = [ + 'node_modules', + path.resolve(__dirname, 'node_modules'), + ]; + + // Origin only exports its main barrel — narrow imports for tree-shaken components. + config.resolve.alias = { + ...config.resolve.alias, + '@lightsparkdev/origin/checkbox': path.resolve( + __dirname, + 'node_modules/@lightsparkdev/origin/src/components/Checkbox/index.ts', + ), + '@lightsparkdev/origin/badge': path.resolve( + __dirname, + 'node_modules/@lightsparkdev/origin/src/components/Badge/index.ts', + ), + }; + + return config; + }, +}; + +export default nextConfig; diff --git a/components/grid-wallet-prod/package-lock.json b/components/grid-wallet-prod/package-lock.json new file mode 100644 index 000000000..d75126ec1 --- /dev/null +++ b/components/grid-wallet-prod/package-lock.json @@ -0,0 +1,4538 @@ +{ + "name": "grid-wallet-prod", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "grid-wallet-prod", + "version": "1.0.0", + "dependencies": { + "@central-icons-react/round-filled-radius-0-stroke-2": "^1.1.267", + "@central-icons-react/round-filled-radius-2-stroke-2": "^1.1.286", + "@central-icons-react/round-outlined-radius-0-stroke-2": "^1.1.267", + "@central-icons-react/round-outlined-radius-1-stroke-1.5": "^1.1.265", + "@central-icons-react/round-outlined-radius-2-stroke-2": "^1.1.286", + "@central-icons-react/round-outlined-radius-3-stroke-1.5": "^1.1.135", + "@central-icons-react/round-outlined-radius-3-stroke-2": "^1.1.290", + "@lightsparkdev/origin": "^0.13.4", + "@noble/curves": "^2.2.0", + "@noble/hashes": "^2.2.0", + "@react-three/drei": "^9.122.0", + "@react-three/fiber": "^8.18.0", + "@scure/base": "^2.2.0", + "@turnkey/api-key-stamper": "^0.6.5", + "@turnkey/crypto": "^2.8.14", + "clsx": "^2.1.1", + "geist": "^1.7.2", + "motion": "^12.33.0", + "next": "^14.2.35", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "sass": "^1.97.3", + "three": "^0.169.0", + "torph": "^0.0.9" + }, + "devDependencies": { + "@types/node": "^22.10.0", + "@types/react": "^18.3.28", + "@types/react-dom": "^18.3.7", + "@types/three": "^0.169.0", + "playwright": "^1.60.0", + "tsx": "^4.22.4", + "typescript": "^5.9.3", + "vitest": "^2.1.9" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@base-ui/react": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@base-ui/react/-/react-1.5.0.tgz", + "integrity": "sha512-z1gSAlced1yY+iM+mHDEtIkD8UI3Ebs52MuBPxvV6f5hRutk+xvCH/wuB7hDqDzK9JG5FoMz5nhrqtSs1wjt1A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "@base-ui/utils": "0.2.9", + "@floating-ui/react-dom": "^2.1.8", + "@floating-ui/utils": "^0.2.11", + "use-sync-external-store": "^1.6.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@date-fns/tz": "^1.2.0", + "@types/react": "^17 || ^18 || ^19", + "date-fns": "^4.0.0", + "react": "^17 || ^18 || ^19", + "react-dom": "^17 || ^18 || ^19" + }, + "peerDependenciesMeta": { + "@date-fns/tz": { + "optional": true + }, + "@types/react": { + "optional": true + }, + "date-fns": { + "optional": true + } + } + }, + "node_modules/@base-ui/utils": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@base-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-x/PDDCYzoqPpjrdyb3VcyylTI2IjUXEtYDGi5foh7KsnmNJIIaVwA2GLgDH1dps1GgXiJbA60hM+AyuTfQzIvw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "@floating-ui/utils": "^0.2.11", + "reselect": "^5.1.1", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "@types/react": "^17 || ^18 || ^19", + "react": "^17 || ^18 || ^19", + "react-dom": "^17 || ^18 || ^19" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@central-icons-react/round-filled-radius-0-stroke-2": { + "version": "1.1.267", + "resolved": "https://registry.npmjs.org/@central-icons-react/round-filled-radius-0-stroke-2/-/round-filled-radius-0-stroke-2-1.1.267.tgz", + "integrity": "sha512-r9xcmE/YFkfngaEhKXHBm/xiCbCmJg6YIbqg/5ISRJGd0jBbkZw9tXwOt9Aj/nhngXd/misZbDNWOVuIwT4f/w==", + "hasInstallScript": true, + "license": "SEE LICENSE IN LICENSE.md", + "peerDependencies": { + "react": ">=14.0.0 <= 19" + } + }, + "node_modules/@central-icons-react/round-filled-radius-2-stroke-2": { + "version": "1.1.286", + "resolved": "https://registry.npmjs.org/@central-icons-react/round-filled-radius-2-stroke-2/-/round-filled-radius-2-stroke-2-1.1.286.tgz", + "integrity": "sha512-fKpxHLDyqHmcmy3mQP46lpIsS+GVFElKUfzaWN5+dCbz1E01jyhNlZxRrtlDS35nzhbpGY+c91bAu7yaGPIkTg==", + "hasInstallScript": true, + "license": "SEE LICENSE IN LICENSE.md", + "peerDependencies": { + "react": ">=14.0.0 <= 19" + } + }, + "node_modules/@central-icons-react/round-outlined-radius-0-stroke-2": { + "version": "1.1.267", + "resolved": "https://registry.npmjs.org/@central-icons-react/round-outlined-radius-0-stroke-2/-/round-outlined-radius-0-stroke-2-1.1.267.tgz", + "integrity": "sha512-cuaKUpw5Rt2RSl3siFcH7OjiDMc/0E7dUpX8w6XX2eYngCG38l/szMEsExA7wTXeRoY1ansl9fzlpkNGx5zMMA==", + "hasInstallScript": true, + "license": "SEE LICENSE IN LICENSE.md", + "peerDependencies": { + "react": ">=14.0.0 <= 19" + } + }, + "node_modules/@central-icons-react/round-outlined-radius-1-stroke-1.5": { + "version": "1.1.265", + "resolved": "https://registry.npmjs.org/@central-icons-react/round-outlined-radius-1-stroke-1.5/-/round-outlined-radius-1-stroke-1.5-1.1.265.tgz", + "integrity": "sha512-eQB/OHqCqoEEYlCcjqFm2lLtoMgaGheagmF7fr+S7Pypr2OlLJLSU/CSCp3iPViI/iGl3Kdzggdjl2DgM6qf8g==", + "hasInstallScript": true, + "license": "SEE LICENSE IN LICENSE.md", + "peerDependencies": { + "react": ">=14.0.0 <= 19" + } + }, + "node_modules/@central-icons-react/round-outlined-radius-2-stroke-2": { + "version": "1.1.286", + "resolved": "https://registry.npmjs.org/@central-icons-react/round-outlined-radius-2-stroke-2/-/round-outlined-radius-2-stroke-2-1.1.286.tgz", + "integrity": "sha512-ZRuwfjVSpgt9jTD8Zh4Y+Mkp9FUhup+YEStfq3RqF6li5S5FgS/2rt7Lj8PlGrPLmDusj3afSuxXZMbcbsk2ZA==", + "hasInstallScript": true, + "license": "SEE LICENSE IN LICENSE.md", + "peerDependencies": { + "react": ">=14.0.0 <= 19" + } + }, + "node_modules/@central-icons-react/round-outlined-radius-3-stroke-1.5": { + "version": "1.1.252", + "resolved": "https://registry.npmjs.org/@central-icons-react/round-outlined-radius-3-stroke-1.5/-/round-outlined-radius-3-stroke-1.5-1.1.252.tgz", + "integrity": "sha512-/NCb8laycDWFl/7pkXN92ujxHtEgdSo85IQgAjOJfrKixocTF2EI/D4wk3bMv5iR15wH91si1wEpwCD+Rm3qRQ==", + "hasInstallScript": true, + "license": "SEE LICENSE IN LICENSE.md", + "peerDependencies": { + "react": ">=14.0.0 <= 19" + } + }, + "node_modules/@central-icons-react/round-outlined-radius-3-stroke-2": { + "version": "1.1.290", + "resolved": "https://registry.npmjs.org/@central-icons-react/round-outlined-radius-3-stroke-2/-/round-outlined-radius-3-stroke-2-1.1.290.tgz", + "integrity": "sha512-G+AEhEV5piZznCEcHi06UtjFpLu6D4tfBlIHu5fvabY5iJpGhu37HM/q/zcfGw4BORwFS8n5zCEnHE19C/7Hyw==", + "hasInstallScript": true, + "license": "SEE LICENSE IN LICENSE.md", + "peerDependencies": { + "react": ">=14.0.0 <= 19" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz", + "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.6" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "license": "MIT" + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@lightsparkdev/origin": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/@lightsparkdev/origin/-/origin-0.13.6.tgz", + "integrity": "sha512-XX7W83kFzVgPEtzIZm1I+JeucTf0NbhUll4NxPnM9u2tpV5OYAxlS8d0ItU1tSKgpRhhS8Szp4/J32qJfzOZpw==", + "license": "Apache-2.0", + "dependencies": { + "@base-ui/react": "^1.1.0", + "@base-ui/utils": "^0.2.3", + "@tanstack/react-table": "^8.21.3", + "ajv": "^8.18.0", + "clsx": "^2.1.1", + "motion": "^12.23.26" + }, + "peerDependencies": { + "next": ">=14", + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "sass": { + "optional": true + } + } + }, + "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/@next/env": { + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz", + "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==", + "license": "MIT" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.33.tgz", + "integrity": "sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.33.tgz", + "integrity": "sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.33.tgz", + "integrity": "sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.33.tgz", + "integrity": "sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.33.tgz", + "integrity": "sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.33.tgz", + "integrity": "sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.33.tgz", + "integrity": "sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.33.tgz", + "integrity": "sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.33", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.33.tgz", + "integrity": "sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@noble/ciphers": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", + "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-2.2.0.tgz", + "integrity": "sha512-T/BoHgFXirb0ENSPBquzX0rcjXeM6Lo892a2jlYJkqk83LqZx0l1Of7DzlKJ6jkpvMrkHSnAcgb5JegL8SeIkQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "2.2.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.2.0.tgz", + "integrity": "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@peculiar/asn1-cms": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.8.0.tgz", + "integrity": "sha512-NgekZOrSJFSBFLFoLfwePguAWAx7z1+f2TEsWFUMyiqqfntZ4+S/S5hzqME3q4pCA0iOsFKdwiQ35dwY24eVqA==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "@peculiar/asn1-x509-attr": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-csr": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.8.0.tgz", + "integrity": "sha512-akbF8+uvleHs8sejNPQxwmVFuInAg6FMNHOwMILXfP518YfFJwdR3jr6oNUPOaEJfuEhn/vkNOCIT6ASUd4mbg==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-ecc": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.8.0.tgz", + "integrity": "sha512-ohwlk+u9Rv2NOAY1c6MfHj45ATVF8R1DUN/WCgABiRtLi2ZftlZWZX7KvpAbU8v9xPcmoILfELeEABj/rn18AQ==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pfx": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.8.0.tgz", + "integrity": "sha512-5yof1ytoB++RQtaFbqSUJ8pxDJtZT6vbVqZ8XoJ61ph7UjNVvfFwAilnCodqkNsAodpy13gDhoxZXw00pghnyg==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.8.0", + "@peculiar/asn1-pkcs8": "^2.8.0", + "@peculiar/asn1-rsa": "^2.8.0", + "@peculiar/asn1-schema": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pkcs8": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.8.0.tgz", + "integrity": "sha512-qAKXtLpBEw9LqhKpjw3ajZSXlBur+ipW+y2ivVBQAG6F6qRx94yO+1ZR4mvw+YaCfKSaOzLeYEzsPaBp4SJELA==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pkcs9": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.8.0.tgz", + "integrity": "sha512-b5nDWCnkV60+cQ141D6sVVwK9nz64R5n3zSVnklGd+ECdkW2Ol3U1a6yYFlalpSOaD557yuJB64A+q42jG7lUQ==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.8.0", + "@peculiar/asn1-pfx": "^2.8.0", + "@peculiar/asn1-pkcs8": "^2.8.0", + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "@peculiar/asn1-x509-attr": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-rsa": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.8.0.tgz", + "integrity": "sha512-zHEUlCqB2mk7x2lxDwHHJy7hWZOPdGHVlsmITWKB5/PbQo61atbu9PJ/0r9dQNMwFzbKPXZ8uK8/91eUhRznSg==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.8.0.tgz", + "integrity": "sha512-7YT0U/ze0tF2QOBbE15gKZwy5tvgGyLRiRHLzhlbOpf7BT032oBSd0haZqXn5W6l26WLlu3dyxzjM+2638/z2Q==", + "license": "MIT", + "dependencies": { + "@peculiar/utils": "^2.0.2", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-x509": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.8.0.tgz", + "integrity": "sha512-N0CMuhWUzsWEVq6F1q9X6+VKUnWzSW+cSVg+aPaGGwDdbFoFWTYgin5MHwXgpWd6y9COMBxnfy/Qc+Xc7F0Zwg==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/utils": "^2.0.2", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-x509-attr": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.8.0.tgz", + "integrity": "sha512-tHjkfS/qhMnmrlB2J9NhflQlQ7In3khO3CfmVrriOlpTeErY9ZIKOso1hQ5JQiyrJ7ShvqVPk7E5fQmbclkSKA==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@peculiar/utils/-/utils-2.0.3.tgz", + "integrity": "sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/x509": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.12.3.tgz", + "integrity": "sha512-+Mzq+W7cNEKfkNZzyLl6A6ffqc3r21HGZUezgfKxpZrkORfOqgRXnS80Zu0IV6a9Ue9QBJeKD7kN0iWfc3bhRQ==", + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.3.13", + "@peculiar/asn1-csr": "^2.3.13", + "@peculiar/asn1-ecc": "^2.3.14", + "@peculiar/asn1-pkcs9": "^2.3.13", + "@peculiar/asn1-rsa": "^2.3.13", + "@peculiar/asn1-schema": "^2.3.13", + "@peculiar/asn1-x509": "^2.3.13", + "pvtsutils": "^1.3.5", + "reflect-metadata": "^0.2.2", + "tslib": "^2.7.0", + "tsyringe": "^4.8.0" + } + }, + "node_modules/@react-spring/animated": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.5.tgz", + "integrity": "sha512-Tqrwz7pIlsSDITzxoLS3n/v/YCUHQdOIKtOJf4yL6kYVSDTSmVK1LI1Q3M/uu2Sx4X3pIWF3xLUhlsA6SPNTNg==", + "license": "MIT", + "dependencies": { + "@react-spring/shared": "~9.7.5", + "@react-spring/types": "~9.7.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/core": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.5.tgz", + "integrity": "sha512-rmEqcxRcu7dWh7MnCcMXLvrf6/SDlSokLaLTxiPlAYi11nN3B5oiCUAblO72o+9z/87j2uzxa2Inm8UbLjXA+w==", + "license": "MIT", + "dependencies": { + "@react-spring/animated": "~9.7.5", + "@react-spring/shared": "~9.7.5", + "@react-spring/types": "~9.7.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-spring/donate" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/rafz": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.5.tgz", + "integrity": "sha512-5ZenDQMC48wjUzPAm1EtwQ5Ot3bLIAwwqP2w2owG5KoNdNHpEJV263nGhCeKKmuA3vG2zLLOdu3or6kuDjA6Aw==", + "license": "MIT" + }, + "node_modules/@react-spring/shared": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.5.tgz", + "integrity": "sha512-wdtoJrhUeeyD/PP/zo+np2s1Z820Ohr/BbuVYv+3dVLW7WctoiN7std8rISoYoHpUXtbkpesSKuPIw/6U1w1Pw==", + "license": "MIT", + "dependencies": { + "@react-spring/rafz": "~9.7.5", + "@react-spring/types": "~9.7.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/three": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/three/-/three-9.7.5.tgz", + "integrity": "sha512-RxIsCoQfUqOS3POmhVHa1wdWS0wyHAUway73uRLp3GAL5U2iYVNdnzQsep6M2NZ994BlW8TcKuMtQHUqOsy6WA==", + "license": "MIT", + "dependencies": { + "@react-spring/animated": "~9.7.5", + "@react-spring/core": "~9.7.5", + "@react-spring/shared": "~9.7.5", + "@react-spring/types": "~9.7.5" + }, + "peerDependencies": { + "@react-three/fiber": ">=6.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "three": ">=0.126" + } + }, + "node_modules/@react-spring/types": { + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.5.tgz", + "integrity": "sha512-HVj7LrZ4ReHWBimBvu2SKND3cDVUPWKLqRTmWe/fNY6o1owGOX0cAHbdPDTMelgBlVbrTKrre6lFkhqGZErK/g==", + "license": "MIT" + }, + "node_modules/@react-three/drei": { + "version": "9.122.0", + "resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-9.122.0.tgz", + "integrity": "sha512-SEO/F/rBCTjlLez7WAlpys+iGe9hty4rNgjZvgkQeXFSiwqD4Hbk/wNHMAbdd8vprO2Aj81mihv4dF5bC7D0CA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@mediapipe/tasks-vision": "0.10.17", + "@monogrid/gainmap-js": "^3.0.6", + "@react-spring/three": "~9.7.5", + "@use-gesture/react": "^10.3.1", + "camera-controls": "^2.9.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", + "react-composer": "^5.0.3", + "stats-gl": "^2.2.8", + "stats.js": "^0.17.0", + "suspend-react": "^0.1.3", + "three-mesh-bvh": "^0.7.8", + "three-stdlib": "^2.35.6", + "troika-three-text": "^0.52.0", + "tunnel-rat": "^0.1.2", + "utility-types": "^3.11.0", + "zustand": "^5.0.1" + }, + "peerDependencies": { + "@react-three/fiber": "^8", + "react": "^18", + "react-dom": "^18", + "three": ">=0.137" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/@react-three/drei/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/@react-three/fiber": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.18.0.tgz", + "integrity": "sha512-FYZZqD0UUHUswKz3LQl2Z7H24AhD14XGTsIRw3SJaXUxyfVMi+1yiZGmqTcPt/CkPpdU7rrxqcyQ1zJE5DjvIQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.17.8", + "@types/react-reconciler": "^0.26.7", + "@types/webxr": "*", + "base64-js": "^1.5.1", + "buffer": "^6.0.3", + "its-fine": "^1.0.6", + "react-reconciler": "^0.27.0", + "react-use-measure": "^2.1.7", + "scheduler": "^0.21.0", + "suspend-react": "^0.1.3", + "zustand": "^3.7.1" + }, + "peerDependencies": { + "expo": ">=43.0", + "expo-asset": ">=8.4", + "expo-file-system": ">=11.0", + "expo-gl": ">=11.0", + "react": ">=18 <19", + "react-dom": ">=18 <19", + "react-native": ">=0.64", + "three": ">=0.133" + }, + "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/fiber/node_modules/scheduler": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.21.0.tgz", + "integrity": "sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/@react-three/fiber/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/@rollup/rollup-android-arm-eabi": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", + "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", + "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", + "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", + "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", + "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", + "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", + "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", + "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", + "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", + "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", + "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", + "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", + "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", + "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", + "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", + "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", + "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", + "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", + "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", + "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", + "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", + "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", + "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", + "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", + "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@scure/base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-2.2.0.tgz", + "integrity": "sha512-b8XEupJibegiXV+tDUseI8oLQc8ei3d/4Jkb2RpbHh3MfE054ov3uIz2dhFkB3FI8iwYkEh0gGCApkrYggkPNg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" + }, + "node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@tanstack/react-table": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz", + "integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==", + "license": "MIT", + "dependencies": { + "@tanstack/table-core": "8.21.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/@tanstack/table-core": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz", + "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@turnkey/api-key-stamper": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@turnkey/api-key-stamper/-/api-key-stamper-0.6.8.tgz", + "integrity": "sha512-kBXdNwl7LzqdzfzOtUSZaDf7FOTvD0lK0Ji5CLlPw8CQcXxTjapl9IYdIW7I5oc3r0+UnSrnWZhlNPVzu9k5tw==", + "license": "Apache-2.0", + "dependencies": { + "@noble/curves": "^1.3.0", + "@turnkey/crypto": "2.10.1", + "@turnkey/encoding": "0.6.0", + "sha256-uint8array": "^0.10.7" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@turnkey/api-key-stamper/node_modules/@noble/curves": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", + "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@turnkey/api-key-stamper/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@turnkey/crypto": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@turnkey/crypto/-/crypto-2.10.1.tgz", + "integrity": "sha512-A9dqEXHIhTNy4t32LodJOTm/I762TjcPAck8gl9E004f73Gz0WCGORnsgiSrSYHAkj4rC4oLUK8rbmRIikGBCQ==", + "license": "Apache-2.0", + "dependencies": { + "@noble/ciphers": "1.3.0", + "@noble/curves": "1.9.0", + "@noble/hashes": "1.8.0", + "@peculiar/x509": "1.12.3", + "@turnkey/encoding": "0.6.0", + "@turnkey/sdk-types": "1.2.0", + "borsh": "2.0.0", + "cbor-js": "0.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@turnkey/crypto/node_modules/@noble/curves": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.0.tgz", + "integrity": "sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@turnkey/crypto/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@turnkey/encoding": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@turnkey/encoding/-/encoding-0.6.0.tgz", + "integrity": "sha512-IC8qXvy36+iGAeiaVIuJvB35uU2Ld/RAWI/DRTKS+ttBej0GXhOn48Ouu5mlca4jt8ZEuwXmDVv74A8uBQclsA==", + "license": "Apache-2.0", + "dependencies": { + "bs58": "6.0.0", + "bs58check": "4.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@turnkey/sdk-types": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@turnkey/sdk-types/-/sdk-types-1.2.0.tgz", + "integrity": "sha512-S37cabMXICiM5ZpeRhYDuPuRrtE3GLlsHjasWCusWS7PUOP7Ru+g7HOHHWhb7A390j+NKvz1CJ1z8kvdfC0nvg==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@tweenjs/tween.js": { + "version": "23.1.3", + "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz", + "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==", + "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.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.19.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz", + "integrity": "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "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/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.29", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.29.tgz", + "integrity": "sha512-ch0qJdr2JY0r04NXSprbK6TXOgnaJ1Tz23fm5W+z0/CBah6BSBc3n96h7K9GOtwh0HrilNWHIBzE1Ko4Dcw/Wg==", + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@types/react-reconciler": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.26.7.tgz", + "integrity": "sha512-mBDYl8x+oyPX/VBb3E638N0B7xG+SPk/EAMcVPeexqus/5aTpTphQi0curhhshOqRrc9t6OPoJfEUkbymse/lQ==", + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/stats.js": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.4.tgz", + "integrity": "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==", + "license": "MIT" + }, + "node_modules/@types/three": { + "version": "0.169.0", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.169.0.tgz", + "integrity": "sha512-oan7qCgJBt03wIaK+4xPWclYRPG9wzcg7Z2f5T8xYTNEF95kh0t0lklxLLYBDo7gQiGLYzE6iF4ta7nXF2bcsw==", + "license": "MIT", + "dependencies": { + "@tweenjs/tween.js": "~23.1.3", + "@types/stats.js": "*", + "@types/webxr": "*", + "@webgpu/types": "*", + "fflate": "~0.8.2", + "meshoptimizer": "~0.18.1" + } + }, + "node_modules/@types/webxr": { + "version": "0.5.24", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz", + "integrity": "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==", + "license": "MIT" + }, + "node_modules/@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/@vitest/expect": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz", + "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.9", + "@vitest/utils": "2.1.9", + "chai": "^5.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz", + "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.9", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.12" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", + "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.9.tgz", + "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "2.1.9", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz", + "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.9", + "magic-string": "^0.30.12", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz", + "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz", + "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.9", + "loupe": "^3.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@webgpu/types": { + "version": "0.1.71", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.71.tgz", + "integrity": "sha512-mMy8/ODcKhab808co15eW+yN+HgXoQxRQHTiBV9Mrvl1r0ufnid7YOcI+gi4eUWSWl9ezD6TW2KXccrL8HCh2A==", + "license": "BSD-3-Clause" + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/asn1js": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.10.tgz", + "integrity": "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==", + "license": "BSD-3-Clause", + "dependencies": { + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.5", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/base-x": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.1.tgz", + "integrity": "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==", + "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/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/borsh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/borsh/-/borsh-2.0.0.tgz", + "integrity": "sha512-kc9+BgR3zz9+cjbwM8ODoUB4fs3X3I5A/HtX7LZKxCLaMrEeDFoBpnhZY//DTS1VZBSs6S5v46RZRbZjRFspEg==", + "license": "Apache-2.0" + }, + "node_modules/bs58": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz", + "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==", + "license": "MIT", + "dependencies": { + "base-x": "^5.0.0" + } + }, + "node_modules/bs58check": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-4.0.0.tgz", + "integrity": "sha512-FsGDOnFg9aVI9erdriULkd/JjEWONV/lQE5aYziB5PoBsXRind56lh8doIZIc9X4HoxT5x4bLjMWN1/NB8Zp5g==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.2.0", + "bs58": "^6.0.0" + } + }, + "node_modules/bs58check/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "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/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/camera-controls": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/camera-controls/-/camera-controls-2.10.1.tgz", + "integrity": "sha512-KnaKdcvkBJ1Irbrzl8XD6WtZltkRjp869Jx8c0ujs9K+9WD+1D7ryBsCiVqJYUqt6i/HR5FxT7RLASieUD+Q5w==", + "license": "MIT", + "peerDependencies": { + "three": ">=0.126.1" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001793", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", + "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/cbor-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cbor-js/-/cbor-js-0.1.0.tgz", + "integrity": "sha512-7sQ/TvDZPl7csT1Sif9G0+MA0I0JOVah8+wWlJVQdVEgIbCzlN/ab3x+uvMNsc34TUvO6osQTAmB2ls80JX6tw==", + "license": "MIT" + }, + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/check-error": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "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/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fflate": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", + "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", + "license": "MIT" + }, + "node_modules/framer-motion": { + "version": "12.40.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.40.0.tgz", + "integrity": "sha512-uaBd3qC1v3KQqBEjwTUd183K6PbS+j0yR9w9VmEOLWA/tnUcSn8Xa3uck7t4dgpDoUss8xQTcj8W2L07lrnLFg==", + "license": "MIT", + "dependencies": { + "motion-dom": "^12.40.0", + "motion-utils": "^12.39.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/geist": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/geist/-/geist-1.7.2.tgz", + "integrity": "sha512-Gu5lDFa3pLRyoBlBPf0QIFHVdWAnpco7fS1bJm41jyLPFoguBgiubseUN2oLXMgqZ7uxAxDoXcHMhCY/fOTTgg==", + "license": "SIL OPEN FONT LICENSE", + "peerDependencies": { + "next": ">=13.2.0" + } + }, + "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", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/hls.js": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.6.16.tgz", + "integrity": "sha512-VSIRpLfRwlAAdGL4wiTucx2ScRipo0ed1FBatWkyt832jC4CReKstga6yIhYVwGu9LOBjuX9wzmRMeQdBJtzEA==", + "license": "Apache-2.0" + }, + "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/immutable": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", + "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", + "license": "MIT" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/its-fine": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/its-fine/-/its-fine-1.2.5.tgz", + "integrity": "sha512-fXtDA0X0t0eBYAGLVM5YsgJGsJ5jEmqZEPrGbzdf5awjv0xE7nqv3TVnvtUF060Tkes15DbDAKW/I48vsb6SyA==", + "license": "MIT", + "dependencies": { + "@types/react-reconciler": "^0.28.0" + }, + "peerDependencies": { + "react": ">=18.0" + } + }, + "node_modules/its-fine/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/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "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/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true, + "license": "MIT" + }, + "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", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "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": "0.18.1", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.18.1.tgz", + "integrity": "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==", + "license": "MIT" + }, + "node_modules/motion": { + "version": "12.40.0", + "resolved": "https://registry.npmjs.org/motion/-/motion-12.40.0.tgz", + "integrity": "sha512-yjrHUrBFW6kQvjJwRsoiPSAhC5tRwRqNGJWmiJ4CrGnbKp0V88AdzkhBmDoqIsIPfarOe0Uddd37Xq43/gIocA==", + "license": "MIT", + "dependencies": { + "framer-motion": "^12.40.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/motion-dom": { + "version": "12.40.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.40.0.tgz", + "integrity": "sha512-HxU3ZaBwNPVQUBQf1xxgq+7JrPNZvjLVxgbpEZL7RrWJnsxOf0/OM+yrHG9ogLQ31Do/r57Oz2gQWPK+6q62mg==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.39.0" + } + }, + "node_modules/motion-utils": { + "version": "12.39.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.39.0.tgz", + "integrity": "sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.16", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", + "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/next": { + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.35.tgz", + "integrity": "sha512-KhYd2Hjt/O1/1aZVX3dCwGXM1QmOV4eNM2UTacK5gipDdPN/oHHK/4oVGy7X8GMfPMsUTUEmGlsy0EY1YGAkig==", + "license": "MIT", + "dependencies": { + "@next/env": "14.2.35", + "@swc/helpers": "0.5.5", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", + "postcss": "8.4.31", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.17.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "14.2.33", + "@next/swc-darwin-x64": "14.2.33", + "@next/swc-linux-arm64-gnu": "14.2.33", + "@next/swc-linux-arm64-musl": "14.2.33", + "@next/swc-linux-x64-gnu": "14.2.33", + "@next/swc-linux-x64-musl": "14.2.33", + "@next/swc-win32-arm64-msvc": "14.2.33", + "@next/swc-win32-ia32-msvc": "14.2.33", + "@next/swc-win32-x64-msvc": "14.2.33" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT", + "optional": true + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/playwright": { + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.60.0.tgz", + "integrity": "sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.60.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.60.0.tgz", + "integrity": "sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "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/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/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/pvtsutils": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", + "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.5.tgz", + "integrity": "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==", + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-composer": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/react-composer/-/react-composer-5.0.3.tgz", + "integrity": "sha512-1uWd07EME6XZvMfapwZmc7NgCZqDemcvicRi3wMJzXsQLvZ3L7fTHVyPy1bZdnWXM4iPjYuNE+uJ41MLKeTtnA==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.6.0" + }, + "peerDependencies": { + "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/react-reconciler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.27.0.tgz", + "integrity": "sha512-HmMDKciQjYmBRGuuhIaKA1ba/7a+UsM5FzOZsMO2JYHt9Jh8reCb7j1eDC95NOyUlKM9KRyvdx0flBuDvYSBoA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.21.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/react-reconciler/node_modules/scheduler": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.21.0.tgz", + "integrity": "sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.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", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "license": "Apache-2.0" + }, + "node_modules/require-from-string": { + "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==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reselect": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.2.0.tgz", + "integrity": "sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==", + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", + "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.2", + "@rollup/rollup-android-arm64": "4.62.2", + "@rollup/rollup-darwin-arm64": "4.62.2", + "@rollup/rollup-darwin-x64": "4.62.2", + "@rollup/rollup-freebsd-arm64": "4.62.2", + "@rollup/rollup-freebsd-x64": "4.62.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", + "@rollup/rollup-linux-arm-musleabihf": "4.62.2", + "@rollup/rollup-linux-arm64-gnu": "4.62.2", + "@rollup/rollup-linux-arm64-musl": "4.62.2", + "@rollup/rollup-linux-loong64-gnu": "4.62.2", + "@rollup/rollup-linux-loong64-musl": "4.62.2", + "@rollup/rollup-linux-ppc64-gnu": "4.62.2", + "@rollup/rollup-linux-ppc64-musl": "4.62.2", + "@rollup/rollup-linux-riscv64-gnu": "4.62.2", + "@rollup/rollup-linux-riscv64-musl": "4.62.2", + "@rollup/rollup-linux-s390x-gnu": "4.62.2", + "@rollup/rollup-linux-x64-gnu": "4.62.2", + "@rollup/rollup-linux-x64-musl": "4.62.2", + "@rollup/rollup-openbsd-x64": "4.62.2", + "@rollup/rollup-openharmony-arm64": "4.62.2", + "@rollup/rollup-win32-arm64-msvc": "4.62.2", + "@rollup/rollup-win32-ia32-msvc": "4.62.2", + "@rollup/rollup-win32-x64-gnu": "4.62.2", + "@rollup/rollup-win32-x64-msvc": "4.62.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/sass": { + "version": "1.100.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.100.0.tgz", + "integrity": "sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==", + "license": "MIT", + "dependencies": { + "chokidar": "^5.0.0", + "immutable": "^5.1.5", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=20.19.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/sha256-uint8array": { + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/sha256-uint8array/-/sha256-uint8array-0.10.7.tgz", + "integrity": "sha512-1Q6JQU4tX9NqsDGodej6pkrUVQVNapLZnvkwIhddH/JqzBZF1fSaxSWNY6sziXBE8aEa2twtGkXUrwzGeZCMpQ==", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "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/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "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/three": { + "version": "0.169.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.169.0.tgz", + "integrity": "sha512-Ed906MA3dR4TS5riErd4QBsRGPcx+HBDX2O5yYE5GqJeFQTPU+M56Va/f/Oph9X7uZo3W3o4l2ZhBZ6f6qUv0w==", + "license": "MIT" + }, + "node_modules/three-mesh-bvh": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.7.8.tgz", + "integrity": "sha512-BGEZTOIC14U0XIRw3tO4jY7IjP7n7v24nv9JXS1CyeVRWOCkcOMhRnmENUjuV39gktAw4Ofhr0OvIAiTspQrrw==", + "deprecated": "Deprecated due to three.js version incompatibility. Please use v0.8.0, instead.", + "license": "MIT", + "peerDependencies": { + "three": ">= 0.151.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/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/torph": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/torph/-/torph-0.0.9.tgz", + "integrity": "sha512-WrFMtJwqXCfIXbLNuTOwHWff0XVm/Ewctb+71bFis3HykPvCXl1CHXapU0r67pQhAI323fsA1L2pGPeqxXeRRA==", + "license": "MIT", + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18", + "svelte": ">=5", + "vue": ">=3" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "svelte": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "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/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.4.tgz", + "integrity": "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.28.0" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/tsx/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/tsyringe": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz", + "integrity": "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==", + "license": "MIT", + "dependencies": { + "tslib": "^1.9.3" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/tsyringe/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "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/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/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/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz", + "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.7", + "es-module-lexer": "^1.5.4", + "pathe": "^1.1.2", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/vite/node_modules/postcss": { + "version": "8.5.22", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.22.tgz", + "integrity": "sha512-KBDEIpLrvpv16pp3K0Fw+UCoZfopFjjgeB+0tA/aaThfEE74kKDLrgg603YvOWJyg3+WYtyq3xYsQWsIyZlPqQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/vitest": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz", + "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "2.1.9", + "@vitest/mocker": "2.1.9", + "@vitest/pretty-format": "^2.1.9", + "@vitest/runner": "2.1.9", + "@vitest/snapshot": "2.1.9", + "@vitest/spy": "2.1.9", + "@vitest/utils": "2.1.9", + "chai": "^5.1.2", + "debug": "^4.3.7", + "expect-type": "^1.1.0", + "magic-string": "^0.30.12", + "pathe": "^1.1.2", + "std-env": "^3.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.1", + "tinypool": "^1.0.1", + "tinyrainbow": "^1.2.0", + "vite": "^5.0.0", + "vite-node": "2.1.9", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "2.1.9", + "@vitest/ui": "2.1.9", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "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/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + } + } +} diff --git a/components/grid-wallet-prod/package.json b/components/grid-wallet-prod/package.json new file mode 100644 index 000000000..ba8f9bf1f --- /dev/null +++ b/components/grid-wallet-prod/package.json @@ -0,0 +1,62 @@ +{ + "name": "grid-wallet-prod", + "version": "1.0.0", + "private": true, + "description": "Live production demo of the Grid Global Accounts wallet.", + "scripts": { + "dev": "next dev -p 4001", + "build": "next build", + "start": "next start -p 4001", + "lint": "next lint", + "export-sf-symbols": "node scripts/export-sf-symbols.mjs --sync-paths", + "fetch:flags": "node scripts/fetch-flags.mjs", + "gen:bank-fields": "node scripts/generate-bank-fields.mjs", + "ensure:business-customer": "node scripts/ensure-business-customer.mjs", + "verify:bank-fields": "node scripts/generate-bank-fields.mjs && git diff --exit-code -- src/data/bankAccountFields.generated.ts", + "verify:bank-data": "tsx scripts/verify-bank-data.ts", + "verify:bank": "npm run verify:bank-fields && npm run verify:bank-data", + "test": "vitest run" + }, + "dependencies": { + "@central-icons-react/round-filled-radius-0-stroke-2": "^1.1.267", + "@central-icons-react/round-filled-radius-2-stroke-2": "^1.1.286", + "@central-icons-react/round-outlined-radius-0-stroke-2": "^1.1.267", + "@central-icons-react/round-outlined-radius-1-stroke-1.5": "^1.1.265", + "@central-icons-react/round-outlined-radius-2-stroke-2": "^1.1.286", + "@central-icons-react/round-outlined-radius-3-stroke-1.5": "^1.1.135", + "@central-icons-react/round-outlined-radius-3-stroke-2": "^1.1.290", + "@lightsparkdev/origin": "^0.13.4", + "@noble/curves": "^2.2.0", + "@noble/hashes": "^2.2.0", + "@turnkey/api-key-stamper": "^0.6.5", + "@turnkey/crypto": "^2.8.14", + "@react-three/drei": "^9.122.0", + "@react-three/fiber": "^8.18.0", + "@scure/base": "^2.2.0", + "clsx": "^2.1.1", + "geist": "^1.7.2", + "motion": "^12.33.0", + "next": "^14.2.35", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "sass": "^1.97.3", + "three": "^0.169.0", + "torph": "^0.0.9" + }, + "devDependencies": { + "@types/node": "^22.10.0", + "@types/react": "^18.3.28", + "@types/react-dom": "^18.3.7", + "@types/three": "^0.169.0", + "playwright": "^1.60.0", + "tsx": "^4.22.4", + "typescript": "^5.9.3", + "vitest": "^2.1.9" + }, + "comments": { + "overrides": "react-three-fiber v8 imports zustand's default export; the next.config resolve.modules flattening forces a single zustand, so pin it to v4 (which still has the default export). drei's Environment/Lightformer don't use zustand directly." + }, + "overrides": { + "zustand": "^4.5.7" + } +} diff --git a/components/grid-wallet-prod/public/assets/VisaLogo.svg b/components/grid-wallet-prod/public/assets/VisaLogo.svg new file mode 100644 index 000000000..481dec225 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/VisaLogo.svg @@ -0,0 +1,3 @@ + diff --git a/components/grid-wallet-prod/public/assets/add-money/IconApple.svg b/components/grid-wallet-prod/public/assets/add-money/IconApple.svg new file mode 100644 index 000000000..d0b9d62b6 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/add-money/IconApple.svg @@ -0,0 +1,3 @@ + + + diff --git a/components/grid-wallet-prod/public/assets/add-money/IconBank.svg b/components/grid-wallet-prod/public/assets/add-money/IconBank.svg new file mode 100644 index 000000000..22cf939a4 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/add-money/IconBank.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/add-money/IconCash.svg b/components/grid-wallet-prod/public/assets/add-money/IconCash.svg new file mode 100644 index 000000000..5cd891215 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/add-money/IconCash.svg @@ -0,0 +1,3 @@ + + + diff --git a/components/grid-wallet-prod/public/assets/add-money/IconDollar.svg b/components/grid-wallet-prod/public/assets/add-money/IconDollar.svg new file mode 100644 index 000000000..9b13502ec --- /dev/null +++ b/components/grid-wallet-prod/public/assets/add-money/IconDollar.svg @@ -0,0 +1,3 @@ + + + diff --git a/components/grid-wallet-prod/public/assets/add-money/IconWallet2.svg b/components/grid-wallet-prod/public/assets/add-money/IconWallet2.svg new file mode 100644 index 000000000..5493b1d50 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/add-money/IconWallet2.svg @@ -0,0 +1,3 @@ + + + diff --git a/components/grid-wallet-prod/public/assets/add-money/flag-mx.svg b/components/grid-wallet-prod/public/assets/add-money/flag-mx.svg new file mode 100644 index 000000000..2671a86e7 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/add-money/flag-mx.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/app-icon-bnb.png b/components/grid-wallet-prod/public/assets/app-icon-bnb.png new file mode 100644 index 000000000..14890a2df Binary files /dev/null and b/components/grid-wallet-prod/public/assets/app-icon-bnb.png differ diff --git a/components/grid-wallet-prod/public/assets/app-icon-car.png b/components/grid-wallet-prod/public/assets/app-icon-car.png new file mode 100644 index 000000000..8c3f0674d Binary files /dev/null and b/components/grid-wallet-prod/public/assets/app-icon-car.png differ diff --git a/components/grid-wallet-prod/public/assets/app-icon-creator.png b/components/grid-wallet-prod/public/assets/app-icon-creator.png new file mode 100644 index 000000000..ad83c7994 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/app-icon-creator.png differ diff --git a/components/grid-wallet-prod/public/assets/app-icon-marketplace.png b/components/grid-wallet-prod/public/assets/app-icon-marketplace.png new file mode 100644 index 000000000..f9dfdfcf5 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/app-icon-marketplace.png differ diff --git a/components/grid-wallet-prod/public/assets/app-icon-messaging.png b/components/grid-wallet-prod/public/assets/app-icon-messaging.png new file mode 100644 index 000000000..f2ae24d4d Binary files /dev/null and b/components/grid-wallet-prod/public/assets/app-icon-messaging.png differ diff --git a/components/grid-wallet-prod/public/assets/app-icon-ondemand.png b/components/grid-wallet-prod/public/assets/app-icon-ondemand.png new file mode 100644 index 000000000..c043dfbb8 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/app-icon-ondemand.png differ diff --git a/components/grid-wallet-prod/public/assets/app-icon-social.png b/components/grid-wallet-prod/public/assets/app-icon-social.png new file mode 100644 index 000000000..fb9e0fe8c Binary files /dev/null and b/components/grid-wallet-prod/public/assets/app-icon-social.png differ diff --git a/components/grid-wallet-prod/public/assets/app-icon-twitch.png b/components/grid-wallet-prod/public/assets/app-icon-twitch.png new file mode 100644 index 000000000..2ef233891 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/app-icon-twitch.png differ diff --git a/components/grid-wallet-prod/public/assets/app-icon-wa.png b/components/grid-wallet-prod/public/assets/app-icon-wa.png new file mode 100644 index 000000000..d6a8b3584 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/app-icon-wa.png differ diff --git a/components/grid-wallet-prod/public/assets/app-icon-wallet.png b/components/grid-wallet-prod/public/assets/app-icon-wallet.png new file mode 100644 index 000000000..a2c0b73d9 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/app-icon-wallet.png differ diff --git a/components/grid-wallet-prod/public/assets/app-icon-x.png b/components/grid-wallet-prod/public/assets/app-icon-x.png new file mode 100644 index 000000000..a7636c576 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/app-icon-x.png differ diff --git a/components/grid-wallet-prod/public/assets/auth/generic-contact.svg b/components/grid-wallet-prod/public/assets/auth/generic-contact.svg new file mode 100644 index 000000000..715412049 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/auth/generic-contact.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/auth/mail-app-icon.webp b/components/grid-wallet-prod/public/assets/auth/mail-app-icon.webp new file mode 100644 index 000000000..9ff01e73a Binary files /dev/null and b/components/grid-wallet-prod/public/assets/auth/mail-app-icon.webp differ diff --git a/components/grid-wallet-prod/public/assets/auth/messages-app-icon.webp b/components/grid-wallet-prod/public/assets/auth/messages-app-icon.webp new file mode 100644 index 000000000..c470e3d5f Binary files /dev/null and b/components/grid-wallet-prod/public/assets/auth/messages-app-icon.webp differ diff --git a/components/grid-wallet-prod/public/assets/creator/logo-creator-platform-color.svg b/components/grid-wallet-prod/public/assets/creator/logo-creator-platform-color.svg new file mode 100644 index 000000000..472446a1d --- /dev/null +++ b/components/grid-wallet-prod/public/assets/creator/logo-creator-platform-color.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/creator/logo-creator-platform-white.svg b/components/grid-wallet-prod/public/assets/creator/logo-creator-platform-white.svg new file mode 100644 index 000000000..a15de36cd --- /dev/null +++ b/components/grid-wallet-prod/public/assets/creator/logo-creator-platform-white.svg @@ -0,0 +1,3 @@ + + + diff --git a/components/grid-wallet-prod/public/assets/creator/logo-creator-platform.svg b/components/grid-wallet-prod/public/assets/creator/logo-creator-platform.svg new file mode 100644 index 000000000..6300b1db8 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/creator/logo-creator-platform.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/face-id-check-blur.png b/components/grid-wallet-prod/public/assets/face-id-check-blur.png new file mode 100644 index 000000000..33d70bbb1 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/face-id-check-blur.png differ diff --git a/components/grid-wallet-prod/public/assets/face-id.mp4 b/components/grid-wallet-prod/public/assets/face-id.mp4 new file mode 100644 index 000000000..033ff74c1 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/face-id.mp4 differ diff --git a/components/grid-wallet-prod/public/assets/financial-app/aurora-wallet.png b/components/grid-wallet-prod/public/assets/financial-app/aurora-wallet.png new file mode 100644 index 000000000..c7e41cfdc Binary files /dev/null and b/components/grid-wallet-prod/public/assets/financial-app/aurora-wallet.png differ diff --git a/components/grid-wallet-prod/public/assets/financial-app/aurora-wallet.svg b/components/grid-wallet-prod/public/assets/financial-app/aurora-wallet.svg new file mode 100644 index 000000000..ef3d7639f --- /dev/null +++ b/components/grid-wallet-prod/public/assets/financial-app/aurora-wallet.svg @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/components/grid-wallet-prod/public/assets/financial-app/aurora-wallet.webp b/components/grid-wallet-prod/public/assets/financial-app/aurora-wallet.webp new file mode 100644 index 000000000..e1a9eabfd Binary files /dev/null and b/components/grid-wallet-prod/public/assets/financial-app/aurora-wallet.webp differ diff --git a/components/grid-wallet-prod/public/assets/flags/ae.svg b/components/grid-wallet-prod/public/assets/flags/ae.svg new file mode 100644 index 000000000..779b9f50b --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/ae.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/at.svg b/components/grid-wallet-prod/public/assets/flags/at.svg new file mode 100644 index 000000000..73a87c887 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/at.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/be.svg b/components/grid-wallet-prod/public/assets/flags/be.svg new file mode 100644 index 000000000..382568194 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/be.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/bg.svg b/components/grid-wallet-prod/public/assets/flags/bg.svg new file mode 100644 index 000000000..43c143c00 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/bj.svg b/components/grid-wallet-prod/public/assets/flags/bj.svg new file mode 100644 index 000000000..7a18b52d2 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/bj.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/br.svg b/components/grid-wallet-prod/public/assets/flags/br.svg new file mode 100644 index 000000000..44aacbd43 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/br.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/ch.svg b/components/grid-wallet-prod/public/assets/flags/ch.svg new file mode 100644 index 000000000..3943b1fbb --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/ch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/ci.svg b/components/grid-wallet-prod/public/assets/flags/ci.svg new file mode 100644 index 000000000..1d21f102e --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/ci.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/cm.svg b/components/grid-wallet-prod/public/assets/flags/cm.svg new file mode 100644 index 000000000..fad286c5d --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/cm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/cn.svg b/components/grid-wallet-prod/public/assets/flags/cn.svg new file mode 100644 index 000000000..a61d24ca4 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/cn.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/cy.svg b/components/grid-wallet-prod/public/assets/flags/cy.svg new file mode 100644 index 000000000..126b94db2 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/cy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/cz.svg b/components/grid-wallet-prod/public/assets/flags/cz.svg new file mode 100644 index 000000000..70668af64 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/cz.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/de.svg b/components/grid-wallet-prod/public/assets/flags/de.svg new file mode 100644 index 000000000..efde34193 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/de.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/dk.svg b/components/grid-wallet-prod/public/assets/flags/dk.svg new file mode 100644 index 000000000..9a0cb4c0f --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/dk.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/ee.svg b/components/grid-wallet-prod/public/assets/flags/ee.svg new file mode 100644 index 000000000..05e9d26d5 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/ee.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/es.svg b/components/grid-wallet-prod/public/assets/flags/es.svg new file mode 100644 index 000000000..55d3ab504 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/es.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/fi.svg b/components/grid-wallet-prod/public/assets/flags/fi.svg new file mode 100644 index 000000000..cac8507ca --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/fi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/fr.svg b/components/grid-wallet-prod/public/assets/flags/fr.svg new file mode 100644 index 000000000..0fe5619a7 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/fr.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/gb.svg b/components/grid-wallet-prod/public/assets/flags/gb.svg new file mode 100644 index 000000000..4dca1e782 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/gb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/gr.svg b/components/grid-wallet-prod/public/assets/flags/gr.svg new file mode 100644 index 000000000..5e991bc75 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/gr.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/hr.svg b/components/grid-wallet-prod/public/assets/flags/hr.svg new file mode 100644 index 000000000..5ddd7188b --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/hr.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/hu.svg b/components/grid-wallet-prod/public/assets/flags/hu.svg new file mode 100644 index 000000000..a0a71b05e --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/hu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/id.svg b/components/grid-wallet-prod/public/assets/flags/id.svg new file mode 100644 index 000000000..7795a4548 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/id.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/ie.svg b/components/grid-wallet-prod/public/assets/flags/ie.svg new file mode 100644 index 000000000..a680a7f2d --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/ie.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/in.svg b/components/grid-wallet-prod/public/assets/flags/in.svg new file mode 100644 index 000000000..2f070cbd6 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/in.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/is.svg b/components/grid-wallet-prod/public/assets/flags/is.svg new file mode 100644 index 000000000..5a2706c0d --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/is.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/it.svg b/components/grid-wallet-prod/public/assets/flags/it.svg new file mode 100644 index 000000000..56b4fb300 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/it.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/ke.svg b/components/grid-wallet-prod/public/assets/flags/ke.svg new file mode 100644 index 000000000..d2e7f4375 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/ke.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/li.svg b/components/grid-wallet-prod/public/assets/flags/li.svg new file mode 100644 index 000000000..495815f55 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/li.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/lt.svg b/components/grid-wallet-prod/public/assets/flags/lt.svg new file mode 100644 index 000000000..3d5ff126d --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/lt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/lu.svg b/components/grid-wallet-prod/public/assets/flags/lu.svg new file mode 100644 index 000000000..5e226fe95 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/lu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/lv.svg b/components/grid-wallet-prod/public/assets/flags/lv.svg new file mode 100644 index 000000000..9152e7a00 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/lv.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/mt.svg b/components/grid-wallet-prod/public/assets/flags/mt.svg new file mode 100644 index 000000000..41b7cd6ef --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/mt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/mw.svg b/components/grid-wallet-prod/public/assets/flags/mw.svg new file mode 100644 index 000000000..76ed981cc --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/mw.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/mx.svg b/components/grid-wallet-prod/public/assets/flags/mx.svg new file mode 100644 index 000000000..2671a86e7 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/mx.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/my.svg b/components/grid-wallet-prod/public/assets/flags/my.svg new file mode 100644 index 000000000..5f482a6f2 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/my.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/ng.svg b/components/grid-wallet-prod/public/assets/flags/ng.svg new file mode 100644 index 000000000..ee20b59a7 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/ng.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/nl.svg b/components/grid-wallet-prod/public/assets/flags/nl.svg new file mode 100644 index 000000000..25b6c9100 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/nl.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/no.svg b/components/grid-wallet-prod/public/assets/flags/no.svg new file mode 100644 index 000000000..bc702a397 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/no.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/ph.svg b/components/grid-wallet-prod/public/assets/flags/ph.svg new file mode 100644 index 000000000..a5fc56927 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/ph.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/pl.svg b/components/grid-wallet-prod/public/assets/flags/pl.svg new file mode 100644 index 000000000..cf3574a18 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/pl.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/pt.svg b/components/grid-wallet-prod/public/assets/flags/pt.svg new file mode 100644 index 000000000..32ce13f2f --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/pt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/ro.svg b/components/grid-wallet-prod/public/assets/flags/ro.svg new file mode 100644 index 000000000..2d3bfd9c5 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/ro.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/rw.svg b/components/grid-wallet-prod/public/assets/flags/rw.svg new file mode 100644 index 000000000..ae6fc4769 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/rw.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/se.svg b/components/grid-wallet-prod/public/assets/flags/se.svg new file mode 100644 index 000000000..c8520bcd2 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/se.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/sg.svg b/components/grid-wallet-prod/public/assets/flags/sg.svg new file mode 100644 index 000000000..363610028 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/sg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/si.svg b/components/grid-wallet-prod/public/assets/flags/si.svg new file mode 100644 index 000000000..520693c54 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/si.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/sk.svg b/components/grid-wallet-prod/public/assets/flags/sk.svg new file mode 100644 index 000000000..ee0e1292b --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/sk.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/sn.svg b/components/grid-wallet-prod/public/assets/flags/sn.svg new file mode 100644 index 000000000..f634dca72 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/sn.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/th.svg b/components/grid-wallet-prod/public/assets/flags/th.svg new file mode 100644 index 000000000..680994bcf --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/th.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/tz.svg b/components/grid-wallet-prod/public/assets/flags/tz.svg new file mode 100644 index 000000000..b9e9eb19a --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/tz.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/ug.svg b/components/grid-wallet-prod/public/assets/flags/ug.svg new file mode 100644 index 000000000..2394c76c8 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/ug.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/us.svg b/components/grid-wallet-prod/public/assets/flags/us.svg new file mode 100644 index 000000000..e3560c6a5 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/us.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/vn.svg b/components/grid-wallet-prod/public/assets/flags/vn.svg new file mode 100644 index 000000000..742759826 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/vn.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/za.svg b/components/grid-wallet-prod/public/assets/flags/za.svg new file mode 100644 index 000000000..4bb7bd5fb --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/za.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/flags/zm.svg b/components/grid-wallet-prod/public/assets/flags/zm.svg new file mode 100644 index 000000000..31682dc47 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/flags/zm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/gga-logo-light.svg b/components/grid-wallet-prod/public/assets/gga-logo-light.svg new file mode 100644 index 000000000..aa3d03b24 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/gga-logo-light.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/hold-near-reader-dark.mp4 b/components/grid-wallet-prod/public/assets/hold-near-reader-dark.mp4 new file mode 100644 index 000000000..118e72edc Binary files /dev/null and b/components/grid-wallet-prod/public/assets/hold-near-reader-dark.mp4 differ diff --git a/components/grid-wallet-prod/public/assets/hold-near-reader-light.mp4 b/components/grid-wallet-prod/public/assets/hold-near-reader-light.mp4 new file mode 100644 index 000000000..99fdc724a Binary files /dev/null and b/components/grid-wallet-prod/public/assets/hold-near-reader-light.mp4 differ diff --git a/components/grid-wallet-prod/public/assets/icon-apple-wallet.png b/components/grid-wallet-prod/public/assets/icon-apple-wallet.png new file mode 100644 index 000000000..1f6e17248 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/icon-apple-wallet.png differ diff --git a/components/grid-wallet-prod/public/assets/marketplace/card-chip.svg b/components/grid-wallet-prod/public/assets/marketplace/card-chip.svg new file mode 100644 index 000000000..3f3e8fc48 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/marketplace/card-chip.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-01.webp b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-01.webp new file mode 100644 index 000000000..9a80bfda9 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-01.webp differ diff --git a/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-02.webp b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-02.webp new file mode 100644 index 000000000..eb5b65be0 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-02.webp differ diff --git a/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-03.webp b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-03.webp new file mode 100644 index 000000000..57c36522e Binary files /dev/null and b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-03.webp differ diff --git a/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-04.webp b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-04.webp new file mode 100644 index 000000000..e598f784a Binary files /dev/null and b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-04.webp differ diff --git a/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-05.webp b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-05.webp new file mode 100644 index 000000000..6450eecd7 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-05.webp differ diff --git a/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-06.webp b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-06.webp new file mode 100644 index 000000000..0dbc5dfeb Binary files /dev/null and b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-06.webp differ diff --git a/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-07.webp b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-07.webp new file mode 100644 index 000000000..b4850edfe Binary files /dev/null and b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-07.webp differ diff --git a/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-08.webp b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-08.webp new file mode 100644 index 000000000..241016d7c Binary files /dev/null and b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-08.webp differ diff --git a/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-09.webp b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-09.webp new file mode 100644 index 000000000..e27ebc3c2 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-09.webp differ diff --git a/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-10.webp b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-10.webp new file mode 100644 index 000000000..8907c61c3 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-10.webp differ diff --git a/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-11.webp b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-11.webp new file mode 100644 index 000000000..30716abc3 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/marketplace/card-designs/design-11.webp differ diff --git a/components/grid-wallet-prod/public/assets/marketplace/card-house-solid.svg b/components/grid-wallet-prod/public/assets/marketplace/card-house-solid.svg new file mode 100644 index 000000000..3befa6200 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/marketplace/card-house-solid.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/components/grid-wallet-prod/public/assets/marketplace/card-house.svg b/components/grid-wallet-prod/public/assets/marketplace/card-house.svg new file mode 100644 index 000000000..c73eb484e --- /dev/null +++ b/components/grid-wallet-prod/public/assets/marketplace/card-house.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/components/grid-wallet-prod/public/assets/marketplace/card-promo.webp b/components/grid-wallet-prod/public/assets/marketplace/card-promo.webp new file mode 100644 index 000000000..6ed5d1a62 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/marketplace/card-promo.webp differ diff --git a/components/grid-wallet-prod/public/assets/marketplace/listing-cabin.png b/components/grid-wallet-prod/public/assets/marketplace/listing-cabin.png new file mode 100644 index 000000000..0d645b05d Binary files /dev/null and b/components/grid-wallet-prod/public/assets/marketplace/listing-cabin.png differ diff --git a/components/grid-wallet-prod/public/assets/marketplace/listing-palm-springs.png b/components/grid-wallet-prod/public/assets/marketplace/listing-palm-springs.png new file mode 100644 index 000000000..ecd393cc9 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/marketplace/listing-palm-springs.png differ diff --git a/components/grid-wallet-prod/public/assets/marketplace/visa-logo.svg b/components/grid-wallet-prod/public/assets/marketplace/visa-logo.svg new file mode 100644 index 000000000..dc00f5e44 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/marketplace/visa-logo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/marketplace/world-map.svg b/components/grid-wallet-prod/public/assets/marketplace/world-map.svg new file mode 100644 index 000000000..7463232fd --- /dev/null +++ b/components/grid-wallet-prod/public/assets/marketplace/world-map.svg @@ -0,0 +1,3 @@ + + + diff --git a/components/grid-wallet-prod/public/assets/messaging/card-watermark.svg b/components/grid-wallet-prod/public/assets/messaging/card-watermark.svg new file mode 100644 index 000000000..1d620a3e6 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/messaging/card-watermark.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/messaging/doodle/bubble-cream.svg b/components/grid-wallet-prod/public/assets/messaging/doodle/bubble-cream.svg new file mode 100644 index 000000000..5c2fbb658 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/messaging/doodle/bubble-cream.svg @@ -0,0 +1,4 @@ + + + + diff --git a/components/grid-wallet-prod/public/assets/messaging/doodle/bubble-mint.svg b/components/grid-wallet-prod/public/assets/messaging/doodle/bubble-mint.svg new file mode 100644 index 000000000..def77b375 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/messaging/doodle/bubble-mint.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/messaging/doodle/coin.svg b/components/grid-wallet-prod/public/assets/messaging/doodle/coin.svg new file mode 100644 index 000000000..a82c30ae9 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/messaging/doodle/coin.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/messaging/doodle/globe.svg b/components/grid-wallet-prod/public/assets/messaging/doodle/globe.svg new file mode 100644 index 000000000..ccfd38c90 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/messaging/doodle/globe.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/messaging/doodle/handset.svg b/components/grid-wallet-prod/public/assets/messaging/doodle/handset.svg new file mode 100644 index 000000000..57cc58c87 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/messaging/doodle/handset.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/components/grid-wallet-prod/public/assets/messaging/doodle/heart.svg b/components/grid-wallet-prod/public/assets/messaging/doodle/heart.svg new file mode 100644 index 000000000..953e3ce8e --- /dev/null +++ b/components/grid-wallet-prod/public/assets/messaging/doodle/heart.svg @@ -0,0 +1,4 @@ + + + + diff --git a/components/grid-wallet-prod/public/assets/messaging/doodle/padlock.svg b/components/grid-wallet-prod/public/assets/messaging/doodle/padlock.svg new file mode 100644 index 000000000..44f8e14c9 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/messaging/doodle/padlock.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/components/grid-wallet-prod/public/assets/messaging/visa-logo.svg b/components/grid-wallet-prod/public/assets/messaging/visa-logo.svg new file mode 100644 index 000000000..dc00f5e44 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/messaging/visa-logo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/networks/icon-network-base.svg b/components/grid-wallet-prod/public/assets/networks/icon-network-base.svg new file mode 100644 index 000000000..afd1b7e99 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/networks/icon-network-base.svg @@ -0,0 +1,4 @@ + + + + diff --git a/components/grid-wallet-prod/public/assets/networks/icon-network-bitcoin.svg b/components/grid-wallet-prod/public/assets/networks/icon-network-bitcoin.svg new file mode 100644 index 000000000..41652c376 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/networks/icon-network-bitcoin.svg @@ -0,0 +1,4 @@ + + + + diff --git a/components/grid-wallet-prod/public/assets/networks/icon-network-ethereum.svg b/components/grid-wallet-prod/public/assets/networks/icon-network-ethereum.svg new file mode 100644 index 000000000..53166b9ce --- /dev/null +++ b/components/grid-wallet-prod/public/assets/networks/icon-network-ethereum.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/networks/icon-network-solana.svg b/components/grid-wallet-prod/public/assets/networks/icon-network-solana.svg new file mode 100644 index 000000000..5b30357c1 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/networks/icon-network-solana.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/networks/icon-network-spark.svg b/components/grid-wallet-prod/public/assets/networks/icon-network-spark.svg new file mode 100644 index 000000000..0cd522e60 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/networks/icon-network-spark.svg @@ -0,0 +1,4 @@ + + + + diff --git a/components/grid-wallet-prod/public/assets/networks/icon-network-tron.svg b/components/grid-wallet-prod/public/assets/networks/icon-network-tron.svg new file mode 100644 index 000000000..d6de81c78 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/networks/icon-network-tron.svg @@ -0,0 +1,4 @@ + + + + diff --git a/components/grid-wallet-prod/public/assets/ondemand/card-chip.svg b/components/grid-wallet-prod/public/assets/ondemand/card-chip.svg new file mode 100644 index 000000000..3f3e8fc48 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/ondemand/card-chip.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/ondemand/tile-add.webp b/components/grid-wallet-prod/public/assets/ondemand/tile-add.webp new file mode 100644 index 000000000..ce778063a Binary files /dev/null and b/components/grid-wallet-prod/public/assets/ondemand/tile-add.webp differ diff --git a/components/grid-wallet-prod/public/assets/ondemand/tile-card.webp b/components/grid-wallet-prod/public/assets/ondemand/tile-card.webp new file mode 100644 index 000000000..f57032839 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/ondemand/tile-card.webp differ diff --git a/components/grid-wallet-prod/public/assets/ondemand/tile-cashout.webp b/components/grid-wallet-prod/public/assets/ondemand/tile-cashout.webp new file mode 100644 index 000000000..f625af17a Binary files /dev/null and b/components/grid-wallet-prod/public/assets/ondemand/tile-cashout.webp differ diff --git a/components/grid-wallet-prod/public/assets/ondemand/tile-pay.webp b/components/grid-wallet-prod/public/assets/ondemand/tile-pay.webp new file mode 100644 index 000000000..1b98939dc Binary files /dev/null and b/components/grid-wallet-prod/public/assets/ondemand/tile-pay.webp differ diff --git a/components/grid-wallet-prod/public/assets/ondemand/tile-rewards.webp b/components/grid-wallet-prod/public/assets/ondemand/tile-rewards.webp new file mode 100644 index 000000000..1570942ed Binary files /dev/null and b/components/grid-wallet-prod/public/assets/ondemand/tile-rewards.webp differ diff --git a/components/grid-wallet-prod/public/assets/ondemand/tile-send.webp b/components/grid-wallet-prod/public/assets/ondemand/tile-send.webp new file mode 100644 index 000000000..64224df21 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/ondemand/tile-send.webp differ diff --git a/components/grid-wallet-prod/public/assets/ondemand/visa-logo.svg b/components/grid-wallet-prod/public/assets/ondemand/visa-logo.svg new file mode 100644 index 000000000..dc00f5e44 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/ondemand/visa-logo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/send/icon-token-sol.svg b/components/grid-wallet-prod/public/assets/send/icon-token-sol.svg new file mode 100644 index 000000000..230224eb8 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/send/icon-token-sol.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + diff --git a/components/grid-wallet-prod/public/assets/social/card-maps/blank-map.webp b/components/grid-wallet-prod/public/assets/social/card-maps/blank-map.webp new file mode 100644 index 000000000..5fe6bc151 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/social/card-maps/blank-map.webp differ diff --git a/components/grid-wallet-prod/public/assets/social/card-maps/grain-normal.png b/components/grid-wallet-prod/public/assets/social/card-maps/grain-normal.png new file mode 100644 index 000000000..ac67f9d2e Binary files /dev/null and b/components/grid-wallet-prod/public/assets/social/card-maps/grain-normal.png differ diff --git a/components/grid-wallet-prod/public/assets/social/card-maps/grain-rough.png b/components/grid-wallet-prod/public/assets/social/card-maps/grain-rough.png new file mode 100644 index 000000000..0142fa99f Binary files /dev/null and b/components/grid-wallet-prod/public/assets/social/card-maps/grain-rough.png differ diff --git a/components/grid-wallet-prod/public/assets/social/card-maps/issued-map.webp b/components/grid-wallet-prod/public/assets/social/card-maps/issued-map.webp new file mode 100644 index 000000000..17d7c2c71 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/social/card-maps/issued-map.webp differ diff --git a/components/grid-wallet-prod/public/assets/social/card-maps/structure-normal.png b/components/grid-wallet-prod/public/assets/social/card-maps/structure-normal.png new file mode 100644 index 000000000..5b0944cad Binary files /dev/null and b/components/grid-wallet-prod/public/assets/social/card-maps/structure-normal.png differ diff --git a/components/grid-wallet-prod/public/assets/social/card-maps/structure-rough.png b/components/grid-wallet-prod/public/assets/social/card-maps/structure-rough.png new file mode 100644 index 000000000..93ce7658d Binary files /dev/null and b/components/grid-wallet-prod/public/assets/social/card-maps/structure-rough.png differ diff --git a/components/grid-wallet-prod/public/assets/social/z-card.webp b/components/grid-wallet-prod/public/assets/social/z-card.webp new file mode 100644 index 000000000..9adfc2fb3 Binary files /dev/null and b/components/grid-wallet-prod/public/assets/social/z-card.webp differ diff --git a/components/grid-wallet-prod/public/assets/symbols/arrow.left.svg b/components/grid-wallet-prod/public/assets/symbols/arrow.left.svg new file mode 100644 index 000000000..92874915a --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/arrow.left.svg @@ -0,0 +1,4 @@ + + arrow.left + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/arrow.up.arrow.down.svg b/components/grid-wallet-prod/public/assets/symbols/arrow.up.arrow.down.svg new file mode 100644 index 000000000..536e75d9a --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/arrow.up.arrow.down.svg @@ -0,0 +1,4 @@ + + arrow.up.arrow.down + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/arrow.up.svg b/components/grid-wallet-prod/public/assets/symbols/arrow.up.svg new file mode 100644 index 000000000..7e340ada4 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/arrow.up.svg @@ -0,0 +1,4 @@ + + arrow.up + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/bell.svg b/components/grid-wallet-prod/public/assets/symbols/bell.svg new file mode 100644 index 000000000..77d352975 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/bell.svg @@ -0,0 +1,4 @@ + + bell + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/checkmark.svg b/components/grid-wallet-prod/public/assets/symbols/checkmark.svg new file mode 100644 index 000000000..7c934ab1d --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/checkmark.svg @@ -0,0 +1,4 @@ + + checkmark + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/chevron.down.svg b/components/grid-wallet-prod/public/assets/symbols/chevron.down.svg new file mode 100644 index 000000000..4822aa4dc --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/chevron.down.svg @@ -0,0 +1,4 @@ + + chevron.down + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/chevron.left.svg b/components/grid-wallet-prod/public/assets/symbols/chevron.left.svg new file mode 100644 index 000000000..d4b9a61e7 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/chevron.left.svg @@ -0,0 +1,4 @@ + + chevron.left + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/chevron.right.svg b/components/grid-wallet-prod/public/assets/symbols/chevron.right.svg new file mode 100644 index 000000000..8327814c5 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/chevron.right.svg @@ -0,0 +1,4 @@ + + chevron.right + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/creditcard.and.numbers.svg b/components/grid-wallet-prod/public/assets/symbols/creditcard.and.numbers.svg new file mode 100644 index 000000000..9293569dc --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/creditcard.and.numbers.svg @@ -0,0 +1,4 @@ + + creditcard.and.numbers + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/delete.left.svg b/components/grid-wallet-prod/public/assets/symbols/delete.left.svg new file mode 100644 index 000000000..62627b6d0 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/delete.left.svg @@ -0,0 +1,4 @@ + + delete.left + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/dollarsign.circle.fill.svg b/components/grid-wallet-prod/public/assets/symbols/dollarsign.circle.fill.svg new file mode 100644 index 000000000..e3b9f3615 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/dollarsign.circle.fill.svg @@ -0,0 +1,4 @@ + + dollarsign.circle.fill + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/ellipsis.svg b/components/grid-wallet-prod/public/assets/symbols/ellipsis.svg new file mode 100644 index 000000000..18018322e --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/ellipsis.svg @@ -0,0 +1,4 @@ + + ellipsis + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/faceid.svg b/components/grid-wallet-prod/public/assets/symbols/faceid.svg new file mode 100644 index 000000000..3f4174ccc --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/faceid.svg @@ -0,0 +1,4 @@ + + faceid + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/gearshape.fill.svg b/components/grid-wallet-prod/public/assets/symbols/gearshape.fill.svg new file mode 100644 index 000000000..f1f86f1ac --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/gearshape.fill.svg @@ -0,0 +1,4 @@ + + gearshape.fill + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/message.svg b/components/grid-wallet-prod/public/assets/symbols/message.svg new file mode 100644 index 000000000..459f3a51b --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/message.svg @@ -0,0 +1,4 @@ + + message + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/person.2.svg b/components/grid-wallet-prod/public/assets/symbols/person.2.svg new file mode 100644 index 000000000..bd4d7320f --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/person.2.svg @@ -0,0 +1,4 @@ + + person.2 + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/person.crop.circle.svg b/components/grid-wallet-prod/public/assets/symbols/person.crop.circle.svg new file mode 100644 index 000000000..02040bcd2 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/person.crop.circle.svg @@ -0,0 +1,4 @@ + + person.crop.circle + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/play.fill.svg b/components/grid-wallet-prod/public/assets/symbols/play.fill.svg new file mode 100644 index 000000000..274604baa --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/play.fill.svg @@ -0,0 +1,4 @@ + + play.fill + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/plus.svg b/components/grid-wallet-prod/public/assets/symbols/plus.svg new file mode 100644 index 000000000..0e3dac68f --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/plus.svg @@ -0,0 +1,4 @@ + + plus + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/viewfinder.svg b/components/grid-wallet-prod/public/assets/symbols/viewfinder.svg new file mode 100644 index 000000000..3414571a4 --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/viewfinder.svg @@ -0,0 +1,4 @@ + + viewfinder + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/assets/symbols/xmark.svg b/components/grid-wallet-prod/public/assets/symbols/xmark.svg new file mode 100644 index 000000000..1ea26ee1b --- /dev/null +++ b/components/grid-wallet-prod/public/assets/symbols/xmark.svg @@ -0,0 +1,4 @@ + + xmark + + \ No newline at end of file diff --git a/components/grid-wallet-prod/public/dev/bezel-compare.png b/components/grid-wallet-prod/public/dev/bezel-compare.png new file mode 100644 index 000000000..2f69bf388 Binary files /dev/null and b/components/grid-wallet-prod/public/dev/bezel-compare.png differ diff --git a/components/grid-wallet-prod/public/dev/demo-img-01.png b/components/grid-wallet-prod/public/dev/demo-img-01.png new file mode 100644 index 000000000..308f728d6 Binary files /dev/null and b/components/grid-wallet-prod/public/dev/demo-img-01.png differ diff --git a/components/grid-wallet-prod/public/fonts/InterVariable.woff2 b/components/grid-wallet-prod/public/fonts/InterVariable.woff2 new file mode 100644 index 000000000..5a8d3e72a Binary files /dev/null and b/components/grid-wallet-prod/public/fonts/InterVariable.woff2 differ diff --git a/components/grid-wallet-prod/public/fonts/SF-Pro-Rounded.woff2 b/components/grid-wallet-prod/public/fonts/SF-Pro-Rounded.woff2 new file mode 100644 index 000000000..12ae4225b Binary files /dev/null and b/components/grid-wallet-prod/public/fonts/SF-Pro-Rounded.woff2 differ diff --git a/components/grid-wallet-prod/public/fonts/SF-Pro.woff2 b/components/grid-wallet-prod/public/fonts/SF-Pro.woff2 new file mode 100644 index 000000000..d45da4989 Binary files /dev/null and b/components/grid-wallet-prod/public/fonts/SF-Pro.woff2 differ diff --git a/components/grid-wallet-prod/public/fonts/SuisseIntl-Book.woff2 b/components/grid-wallet-prod/public/fonts/SuisseIntl-Book.woff2 new file mode 100644 index 000000000..b43587ca4 Binary files /dev/null and b/components/grid-wallet-prod/public/fonts/SuisseIntl-Book.woff2 differ diff --git a/components/grid-wallet-prod/public/fonts/SuisseIntl-Medium.woff2 b/components/grid-wallet-prod/public/fonts/SuisseIntl-Medium.woff2 new file mode 100644 index 000000000..6089a9f6e Binary files /dev/null and b/components/grid-wallet-prod/public/fonts/SuisseIntl-Medium.woff2 differ diff --git a/components/grid-wallet-prod/public/fonts/SuisseIntl-Regular.woff2 b/components/grid-wallet-prod/public/fonts/SuisseIntl-Regular.woff2 new file mode 100644 index 000000000..afdcff979 Binary files /dev/null and b/components/grid-wallet-prod/public/fonts/SuisseIntl-Regular.woff2 differ diff --git a/components/grid-wallet-prod/public/fonts/SuisseIntlMono-Regular-WebXL.woff2 b/components/grid-wallet-prod/public/fonts/SuisseIntlMono-Regular-WebXL.woff2 new file mode 100644 index 000000000..894e80287 Binary files /dev/null and b/components/grid-wallet-prod/public/fonts/SuisseIntlMono-Regular-WebXL.woff2 differ diff --git a/components/grid-wallet-prod/public/fonts/circular/lineto-circular-black.ttf b/components/grid-wallet-prod/public/fonts/circular/lineto-circular-black.ttf new file mode 100644 index 000000000..da47c5081 Binary files /dev/null and b/components/grid-wallet-prod/public/fonts/circular/lineto-circular-black.ttf differ diff --git a/components/grid-wallet-prod/public/fonts/circular/lineto-circular-blackItalic.ttf b/components/grid-wallet-prod/public/fonts/circular/lineto-circular-blackItalic.ttf new file mode 100644 index 000000000..2cc36c07b Binary files /dev/null and b/components/grid-wallet-prod/public/fonts/circular/lineto-circular-blackItalic.ttf differ diff --git a/components/grid-wallet-prod/public/fonts/circular/lineto-circular-bold.ttf b/components/grid-wallet-prod/public/fonts/circular/lineto-circular-bold.ttf new file mode 100644 index 000000000..65a2231be Binary files /dev/null and b/components/grid-wallet-prod/public/fonts/circular/lineto-circular-bold.ttf differ diff --git a/components/grid-wallet-prod/public/fonts/circular/lineto-circular-boldItalic.ttf b/components/grid-wallet-prod/public/fonts/circular/lineto-circular-boldItalic.ttf new file mode 100644 index 000000000..9235aee38 Binary files /dev/null and b/components/grid-wallet-prod/public/fonts/circular/lineto-circular-boldItalic.ttf differ diff --git a/components/grid-wallet-prod/public/fonts/circular/lineto-circular-book.ttf b/components/grid-wallet-prod/public/fonts/circular/lineto-circular-book.ttf new file mode 100644 index 000000000..7c0308ac2 Binary files /dev/null and b/components/grid-wallet-prod/public/fonts/circular/lineto-circular-book.ttf differ diff --git a/components/grid-wallet-prod/public/fonts/circular/lineto-circular-bookItalic.ttf b/components/grid-wallet-prod/public/fonts/circular/lineto-circular-bookItalic.ttf new file mode 100644 index 000000000..5bc022bed Binary files /dev/null and b/components/grid-wallet-prod/public/fonts/circular/lineto-circular-bookItalic.ttf differ diff --git a/components/grid-wallet-prod/public/fonts/circular/lineto-circular-medium.ttf b/components/grid-wallet-prod/public/fonts/circular/lineto-circular-medium.ttf new file mode 100644 index 000000000..1578d68bb Binary files /dev/null and b/components/grid-wallet-prod/public/fonts/circular/lineto-circular-medium.ttf differ diff --git a/components/grid-wallet-prod/public/fonts/circular/lineto-circular-mediumItalic.ttf b/components/grid-wallet-prod/public/fonts/circular/lineto-circular-mediumItalic.ttf new file mode 100644 index 000000000..c350a6acc Binary files /dev/null and b/components/grid-wallet-prod/public/fonts/circular/lineto-circular-mediumItalic.ttf differ diff --git a/components/grid-wallet-prod/public/og-global-accounts-playground.webp b/components/grid-wallet-prod/public/og-global-accounts-playground.webp new file mode 100644 index 000000000..50b0cf171 Binary files /dev/null and b/components/grid-wallet-prod/public/og-global-accounts-playground.webp differ diff --git a/components/grid-wallet-prod/scripts/auth-flow-verify.mjs b/components/grid-wallet-prod/scripts/auth-flow-verify.mjs new file mode 100644 index 000000000..fc524979e --- /dev/null +++ b/components/grid-wallet-prod/scripts/auth-flow-verify.mjs @@ -0,0 +1,330 @@ +// End-to-end auth sheet verification for BOTH OTP methods (email / phone): +// entry → Continue → sending → code step → notification → autofill (email: +// notification tap, phone: code-cell tap) → staged submit (verifying spinner +// → checkmark → dismiss completes → intro) → sign-in lands. Samples the sheet +// height per frame through the forward and X-back transitions (snap +// detection), and asserts the notification's per-method content (SMS: avatar +// + Messages badge + 2-line clamped body). +// +// OAUTH methods (google / apple) run a different scenario: real provider +// popups can't be automated, so the harness installs the __oauthPopupStub +// test seam (src/lib/auth.ts) and asserts the Airbnb model — tap → phone +// untouched while pending (no busy look), double-tap swallowed, cancel → +// still untouched + re-tappable, resolve → sign-in calls + wallet intro. +// +// node scripts/auth-flow-verify.mjs [email|phone|google|apple] [chromium|webkit] +import { chromium, webkit } from 'playwright'; + +const method = process.argv[2] ?? 'phone'; +const engineName = process.argv[3] ?? 'chromium'; +const engine = engineName === 'webkit' ? webkit : chromium; + +// Per-method harness knobs: the config checkbox label (compact, 1600px +// viewport), the aurora CTA, the prefill, and the expected notification. +const M = { + email: { + checkbox: 'Email', + cta: 'Continue with email', + prefill: 'demo@lightspark.com', + typed: null, + // Final autofill via the notification tap (phone covers the cell tap). + finalTrigger: 'capsule', + notif: { + icon: 'mail-app-icon', + badge: null, + title: 'Aurora', + bodyPart: 'Your one-time code is 123-456', + lines: 1, + }, + }, + phone: { + checkbox: 'Phone', + cta: 'Continue with phone', + prefill: '(415) 555-0132', + // Live-format check: retype the number digit-by-digit. + typed: { digits: '4155550199', formatted: '(415) 555-0199', masked: '(•••) •••-0199' }, + // Final autofill via a tap on the code cells (the new trigger). + finalTrigger: 'cells', + notif: { + icon: 'generic-contact', + badge: 'messages-app-icon', + title: '22395', + bodyPart: 'Your Aurora verification code is: 123456', + lines: 2, + }, + }, +}[method]; + +const fails = []; +const check = (label, ok, detail = '') => { + console.log(`${ok ? 'PASS' : 'FAIL'} ${label}${detail ? ` — ${detail}` : ''}`); + if (!ok) fails.push(label); +}; + +const browser = await engine.launch(); +const page = await browser.newPage({ viewport: { width: 1600, height: 1000 } }); +await page.goto('http://localhost:4000', { waitUntil: 'networkidle' }); +await page.waitForTimeout(800); + +// ── OAuth popup scenario (google / apple) ── +if (method === 'google' || method === 'apple') { + const cta = method === 'google' ? 'Continue with Google' : 'Continue with Apple'; + // Google is the default-enabled method; Apple needs its checkbox on. + if (method === 'apple') { + await page.getByText('Apple', { exact: true }).first().click(); + await page.waitForTimeout(400); + } + // Install the popup stub: each "popup" parks its resolvers for the harness. + await page.evaluate(() => { + window.__popupStubCalls = []; + window.__oauthPopupStub = (provider) => + new Promise((resolve, reject) => { + window.__popupStubCalls.push({ provider, resolve, reject }); + }); + }); + const stubCalls = () => page.evaluate(() => window.__popupStubCalls.length); + // The idle auth screen, summarized: no sheet, sleeve at rest, CTA enabled + // (the popup wait must NOT read as busy — that's the Airbnb model). + const authState = () => + page.evaluate((ctaLabel) => { + const sleeve = document.querySelector('[class*="AuroraAuthScreen_sleeve__"]'); + const tr = sleeve ? getComputedStyle(sleeve).transform : null; + const btn = [...document.querySelectorAll('button')].find( + (b) => b.textContent.trim() === ctaLabel, + ); + return { + authScreen: !!document.querySelector('[class*="AuroraAuthScreen_root__"]'), + sheet: !!document.querySelector('[class*="BottomSheet_sheet__"]'), + sleeveY: !tr || tr === 'none' ? 0 : Math.round(new DOMMatrixReadOnly(tr).m42), + ctaDisabled: btn ? btn.disabled : null, + }; + }, cta); + const assertIdle = async (label) => { + const s = await authState(); + check(label, s.authScreen && !s.sheet && s.sleeveY === 0 && s.ctaDisabled === false, + JSON.stringify(s)); + }; + + // The API panel seeds demo entries — compare against the baseline count. + const oauthCallCount = () => page.getByText('Verify OAuth token').count(); + const baselineCalls = await oauthCallCount(); + + await assertIdle('idle before tap'); + + // Tap → popup "opens" (stub). Phone must stay exactly as it is. + await page.getByText(cta, { exact: true }).first().click(); + await page.waitForTimeout(400); + check('popup opened once', (await stubCalls()) === 1, `${await stubCalls()} calls`); + await assertIdle('phone untouched while popup pending'); + + // Double-tap while pending — swallowed before a second window can open. + await page.getByText(cta, { exact: true }).first().click(); + await page.waitForTimeout(300); + check('double-tap swallowed', (await stubCalls()) === 1, `${await stubCalls()} calls`); + + // Cancel (user closes the popup) → nothing happens, still re-tappable. + await page.evaluate(() => window.__popupStubCalls[0].reject(new Error('cancelled'))); + await page.waitForTimeout(500); + await assertIdle('idle again after cancel'); + check('no sign-in calls after cancel', (await oauthCallCount()) === baselineCalls); + + // Tap again → a fresh popup; resolve it → staged calls + wallet intro. + await page.getByText(cta, { exact: true }).first().click(); + await page.waitForTimeout(400); + check('re-tap opens a new popup', (await stubCalls()) === 2, `${await stubCalls()} calls`); + await page.evaluate(() => window.__popupStubCalls[1].resolve('fake-oidc-token')); + // Post-resolve beat is 400ms, then the calls push and the intro starts. + await page.waitForTimeout(900); + check('sign-in calls pushed', (await oauthCallCount()) > baselineCalls); + const introY = (await authState()).sleeveY; + check('wallet intro playing (sleeve moving)', introY > 2, `sleeveY=${introY}`); + await page.locator('[class*="AuroraWalletScreen_"]').first() + .waitFor({ state: 'visible', timeout: 15000 }); + check('sign-in completed (wallet visible)', true); + + await browser.close(); + console.log(fails.length ? `\n${fails.length} FAILURES: ${fails.join(', ')}` : '\nALL PASS'); + process.exit(fails.length ? 1 : 0); +} + +await page.getByText(M.checkbox, { exact: true }).first().click(); +await page.waitForTimeout(800); +await page.getByText(M.cta, { exact: true }).first().click(); +await page.waitForTimeout(1000); + +// ── Step 1: entry — prefill + (phone) live formatting ── +const input = page.locator('[class*="AuthSheet_input__"]'); +check('entry prefill', (await input.inputValue()) === M.prefill, await input.inputValue()); +if (M.typed) { + await input.fill(''); + await input.pressSequentially(M.typed.digits, { delay: 25 }); + check('live formatting', (await input.inputValue()) === M.typed.formatted, await input.inputValue()); +} + +// Per-frame height sampler — clicks the labelled button, then rAF-samples the +// sheet height for `windowMs`. Returns {samples, maxJump, range}. +const sampleTransition = (buttonLabel, windowMs) => + page.evaluate(async ({ label, windowMs }) => { + const sheet = document.querySelector('[class*="BottomSheet_sheet__"]'); + const btn = [...document.querySelectorAll('button')].find( + (b) => b.getAttribute('aria-label') === label || b.textContent.trim() === label, + ); + const out = []; + const t0 = performance.now(); + btn.click(); + await new Promise((resolve) => { + const tick = () => { + out.push({ + t: Math.round(performance.now() - t0), + h: Math.round(sheet.getBoundingClientRect().height * 10) / 10, + }); + if (performance.now() - t0 < windowMs) requestAnimationFrame(tick); + else resolve(); + }; + requestAnimationFrame(tick); + }); + let maxJump = 0; + let movingFrames = 0; + for (let i = 1; i < out.length; i++) { + const d = Math.abs(out[i].h - out[i - 1].h); + maxJump = Math.max(maxJump, d); + if (d > 0.5) movingFrames += 1; + } + const hs = out.map((s) => s.h); + return { + samples: out, + maxJump, + movingFrames, + range: Math.max(...hs) - Math.min(...hs), + }; + }, { label: buttonLabel, windowMs }); + +// Eased = the height actually changed, spread across several frames (a snap +// would cover the whole range in 1-2 frames). +const eased = (r) => r.range > 5 && r.movingFrames >= 4 && r.maxJump < r.range * 0.7; + +// ── Step 1 → 2 forward (the 600ms sending beat runs first, so the tween +// lands late in the window — 1600ms covers beat + 350ms ease + settle). ── +const fwd = await sampleTransition('Continue', 1600); +console.log( + `forward: range ${fwd.range}px, max frame jump ${fwd.maxJump}px, ${fwd.movingFrames} moving frames`, +); +check('forward height eases', eased(fwd), `${fwd.samples.length} samples`); +await page.waitForTimeout(600); + +// ── Code step copy (masked destination) ── +const sub = page.locator('[class*="AuthSheet_sub__"]'); +const subText = await sub.innerText(); +if (M.typed) { + check('masked number in code copy', subText.includes(M.typed.masked), subText.trim()); +} + +// ── Notification (lands 1s after the code step) ── +await page.waitForTimeout(1400); +const capsule = page.locator('[class*="GlassNotification_capsule__"]'); +check('notification shown', await capsule.isVisible()); +check('notification icon', await capsule.locator(`img[src*="${M.notif.icon}"]`).count() === 1); +const badgeCount = await capsule.locator(`[class*="GlassNotification_badge__"] img`).count(); +check('notification badge', M.notif.badge ? badgeCount === 1 : badgeCount === 0, + M.notif.badge ?? 'none expected'); +const title = await capsule.locator('[class*="GlassNotification_title__"]').innerText(); +check('notification title', title === M.notif.title, title); +const bodyEl = capsule.locator('[class*="GlassNotification_body__"]'); +check('notification body', (await bodyEl.innerText()).includes(M.notif.bodyPart)); +const bodyMetrics = await bodyEl.evaluate((el) => ({ + clamp: getComputedStyle(el).webkitLineClamp, + height: el.getBoundingClientRect().height, + scrollH: el.scrollHeight, + timePad: getComputedStyle(el.closest('[class*="inner"]').querySelector('[class*="time"]')) + .paddingRight, +})); +// Chromium's standardized line-clamp sizes the box to the clamp point (a few +// px shy of N × 18px line boxes); WebKit's -webkit-box reports the full N +// lines. Accept the band, and for clamped bodies require real truncation. +const expectedH = M.notif.lines * 18; +check( + `body renders ${M.notif.lines} line(s)`, + bodyMetrics.height > expectedH - 8 && + bodyMetrics.height < expectedH + 4 && + (M.notif.lines === 1 || + (bodyMetrics.clamp === String(M.notif.lines) && bodyMetrics.scrollH > bodyMetrics.height)), + `h=${bodyMetrics.height} clamp=${bodyMetrics.clamp} scrollH=${bodyMetrics.scrollH}`, +); +check('time 3px right pad', bodyMetrics.timePad === '3px', bodyMetrics.timePad); +await page.screenshot({ path: `/tmp/auth-${method}-${engineName}-notif.png` }); + +// ── X-back (code → entry) height choreography, then forward again ── +const back = await sampleTransition('Back', 900); +console.log( + `back: range ${back.range}px, max frame jump ${back.maxJump}px, ${back.movingFrames} moving frames`, +); +check('back height eases', eased(back), `${back.samples.length} samples`); +await page.waitForTimeout(400); +check('back lands on entry step', await input.isVisible()); +await page.getByRole('button', { name: 'Continue', exact: true }).first().click(); +await page.waitForTimeout(2000); + +// ── Final autofill → staged submit (spinner → checkmark → dismiss → intro) ── +// Timeline from the trigger: digits land 0–125ms (25ms cadence), the staged +// submit starts at ~475ms, verifying spinner 475–975ms, checkmark 975–1475ms, +// onSubmitCode at ~1475ms, BottomSheet exit ~350ms, wallet flip 400ms later. +await capsule.waitFor({ state: 'visible', timeout: 4000 }); +if (M.finalTrigger === 'cells') { + await page.locator('[class*="AuthSheet_codeContainer__"]').click(); +} else { + await capsule.click(); +} +await page.waitForTimeout(250); +check('autofill filled 123456', + (await page.locator('[class*="AuthSheet_codeCell__"]').allInnerTexts()).join('') === '123456'); +// Mid-verifying beat (~700ms after trigger) — the notification's 0.25s exit +// tuck has also finished by now. +await page.waitForTimeout(450); +check('trigger dismissed notification', !(await capsule.isVisible())); +check('CTA verifying spinner', await page.locator('[aria-label="Verifying"]').isVisible()); +// Mid-checkmark beat (~1200ms) — glyph swapped, sheet still up. +await page.waitForTimeout(500); +check('CTA checkmark', await page.locator('[aria-label="Verified"]').isVisible()); +check('sheet still up at checkmark', + await page.locator('[class*="BottomSheet_sheet__"]').isVisible()); +// The dismiss must visibly COMPLETE before the intro: per-frame poll for the +// sheet's unmount (AnimatePresence removes it when the exit ends) vs the +// auth sleeve's first intro movement. +const order = await page.evaluate(async () => { + const t0 = performance.now(); + let tSheetGone = null; + let tIntroStart = null; + await new Promise((resolve) => { + const tick = () => { + const now = performance.now() - t0; + if (tSheetGone === null && !document.querySelector('[class*="BottomSheet_sheet__"]')) { + tSheetGone = now; + } + const sleeve = document.querySelector('[class*="AuroraAuthScreen_sleeve__"]'); + if (tIntroStart === null && sleeve) { + const tr = getComputedStyle(sleeve).transform; + if (tr && tr !== 'none' && new DOMMatrixReadOnly(tr).m42 > 2) tIntroStart = now; + } + if ((tSheetGone !== null && tIntroStart !== null) || now > 5000) resolve(); + else requestAnimationFrame(tick); + }; + requestAnimationFrame(tick); + }); + return { tSheetGone, tIntroStart }; +}); +console.log( + `dismiss complete at ${Math.round(order.tSheetGone ?? -1)}ms, intro starts at ${Math.round(order.tIntroStart ?? -1)}ms`, +); +check( + 'sheet fully dismissed before intro', + order.tSheetGone !== null && order.tIntroStart !== null && order.tSheetGone <= order.tIntroStart, +); +await page.locator('[class*="AuroraWalletScreen_"]').first() + .waitFor({ state: 'visible', timeout: 15000 }); +check('sign-in completed (wallet visible)', true); +await page.waitForTimeout(1500); +await page.screenshot({ path: `/tmp/auth-${method}-${engineName}-wallet.png` }); + +await browser.close(); +console.log(fails.length ? `\n${fails.length} FAILURES: ${fails.join(', ')}` : '\nALL PASS'); +process.exit(fails.length ? 1 : 0); diff --git a/components/grid-wallet-prod/scripts/ensure-business-customer.mjs b/components/grid-wallet-prod/scripts/ensure-business-customer.mjs new file mode 100644 index 000000000..745a5a393 --- /dev/null +++ b/components/grid-wallet-prod/scripts/ensure-business-customer.mjs @@ -0,0 +1,236 @@ +#!/usr/bin/env node +/** + * Idempotently provision the demo's sample BUSINESS customer. + * + * node scripts/ensure-business-customer.mjs [--platform-id biz-…] [--dry-run] + * + * Looks the customer up by `platformCustomerId` (GET /customers?platformCustomerId=…), + * creates it only when absent, then upserts GRID_BUSINESS_CUSTOMER_ID into + * .env.local. Re-running is a no-op beyond re-printing the current state. + * + * Note: unlike INDIVIDUAL customers (auto-KYC'd on creation), BUSINESS customers + * start at kybStatus UNVERIFIED and need an out-of-band verification step. The + * embedded-wallet internal accounts only appear AFTER approval, so a freshly + * created business customer has no accounts yet — the script says so rather than + * pretending otherwise. + */ + +import { readFileSync, writeFileSync, existsSync } from 'node:fs'; +import { dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..'); +const ENV_PATH = resolve(ROOT, '.env.local'); +const ENV_KEY = 'GRID_BUSINESS_CUSTOMER_ID'; +const DEFAULT_PLATFORM_ID = 'biz-grid-wallet-prod'; + +/* ── args ─────────────────────────────────────────────────────────────────── */ + +function parseArgs(argv) { + const args = { platformId: DEFAULT_PLATFORM_ID, dryRun: false }; + for (let i = 0; i < argv.length; i++) { + const a = argv[i]; + if (a === '--dry-run') args.dryRun = true; + else if (a === '--platform-id') args.platformId = argv[++i]; + else if (a.startsWith('--platform-id=')) args.platformId = a.slice('--platform-id='.length); + else die(`Unknown argument: ${a}`); + } + if (!args.platformId) die('--platform-id needs a value'); + return args; +} + +function die(msg) { + console.error(`error: ${msg}`); + process.exit(1); +} + +/* ── .env.local ───────────────────────────────────────────────────────────── */ + +/** Minimal dotenv read: KEY=value, optional quotes, # comments, no interpolation. */ +function readEnvFile(path) { + if (!existsSync(path)) return {}; + const out = {}; + for (const line of readFileSync(path, 'utf8').split('\n')) { + const m = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(line); + if (!m) continue; + let v = m[2].trim(); + if ( + (v.startsWith('"') && v.endsWith('"') && v.length > 1) || + (v.startsWith("'") && v.endsWith("'") && v.length > 1) + ) { + v = v.slice(1, -1); + } + out[m[1]] = v; + } + return out; +} + +/** Replace KEY's line in place, or append it with a comment block. */ +function upsertEnvKey(path, key, value, comment) { + const original = existsSync(path) ? readFileSync(path, 'utf8') : ''; + const line = `${key}=${value}`; + const re = new RegExp(`^${key}=.*$`, 'm'); + if (re.test(original)) { + const next = original.replace(re, line); + if (next === original) return 'unchanged'; + writeFileSync(path, next); + return 'updated'; + } + const sep = original === '' || original.endsWith('\n') ? '' : '\n'; + const block = `${sep}\n${comment ? `# ${comment}\n` : ''}${line}\n`; + writeFileSync(path, original + block); + return 'added'; +} + +/* ── Grid ─────────────────────────────────────────────────────────────────── */ + +function gridConfig(env) { + const clientId = process.env.GRID_CLIENT_ID || env.GRID_CLIENT_ID; + const clientSecret = process.env.GRID_CLIENT_SECRET || env.GRID_CLIENT_SECRET; + const baseUrl = + process.env.GRID_API_BASE_URL || + env.GRID_API_BASE_URL || + 'https://api.lightspark.com/grid/2025-10-13'; + if (!clientId || !clientSecret) { + die('GRID_CLIENT_ID / GRID_CLIENT_SECRET not found in the environment or .env.local'); + } + const auth = 'Basic ' + Buffer.from(`${clientId}:${clientSecret}`).toString('base64'); + return { baseUrl: baseUrl.replace(/\/$/, ''), auth }; +} + +async function grid({ baseUrl, auth }, method, path, body) { + const res = await fetch(baseUrl + path, { + method, + headers: { + Authorization: auth, + ...(body ? { 'Content-Type': 'application/json' } : {}), + }, + body: body ? JSON.stringify(body) : undefined, + }); + const text = await res.text(); + let parsed; + try { + parsed = text ? JSON.parse(text) : {}; + } catch { + parsed = { raw: text }; + } + return { status: res.status, body: parsed }; +} + +function fail(where, res) { + const err = res.body?.error; + die( + `${where}: HTTP ${res.status}` + + (err ? ` (${err.code ?? ''} ${err.message ?? ''})`.replace(/\s+/g, ' ').trimEnd() : '') + + `\n${JSON.stringify(res.body, null, 2)}`, + ); +} + +/** Sample business — deliberately boring, matches the OpenAPI businessCustomer example. */ +function businessPayload(platformId) { + return { + customerType: 'BUSINESS', + platformCustomerId: platformId, + region: 'US', + currencies: ['USD', 'USDB'], + email: 'peng+grid-wallet-prod-biz@lightspark.com', + phoneNumber: '+14155559876', + businessInfo: { + legalName: 'Aurora Labs LLC', + doingBusinessAs: 'Aurora', + country: 'US', + registrationNumber: '5523041', + incorporatedOn: '2018-03-14', + entityType: 'LLC', + taxId: '47-1234567', + countriesOfOperation: ['US'], + businessType: 'INFORMATION', + purposeOfAccount: 'CONTRACTOR_PAYOUTS', + sourceOfFunds: 'Funds derived from customer payments for software services', + expectedMonthlyTransactionCount: 'COUNT_100_TO_500', + expectedMonthlyTransactionVolume: 'VOLUME_100K_TO_1M', + expectedRecipientJurisdictions: ['US'], + }, + address: { + line1: '123 Market Street', + line2: 'Suite 400', + city: 'San Francisco', + state: 'CA', + postalCode: '94105', + country: 'US', + }, + }; +} + +function kybOf(customer) { + return customer?.kybStatus ?? customer?.kycStatus ?? 'UNKNOWN'; +} + +/* ── main ─────────────────────────────────────────────────────────────────── */ + +const args = parseArgs(process.argv.slice(2)); +const env = readEnvFile(ENV_PATH); +const cfg = gridConfig(env); + +console.log(`base: ${cfg.baseUrl}`); +console.log(`platform id: ${args.platformId}`); + +const lookup = await grid( + cfg, + 'GET', + `/customers?platformCustomerId=${encodeURIComponent(args.platformId)}`, +); +if (lookup.status !== 200) fail('list customers', lookup); + +// The filter is server-side, but match defensively — a broader result set must +// not be mistaken for "found". +const existing = (lookup.body.data ?? []).find( + (c) => c.platformCustomerId === args.platformId && c.customerType === 'BUSINESS', +); + +let customer = existing; +if (existing) { + console.log(`found: ${existing.id} (kyb: ${kybOf(existing)})`); +} else if (args.dryRun) { + console.log('dry-run: no BUSINESS customer with that platform id — would create one'); + console.log(JSON.stringify(businessPayload(args.platformId), null, 2)); + process.exit(0); +} else { + const created = await grid(cfg, 'POST', '/customers', businessPayload(args.platformId)); + if (created.status !== 201) fail('create customer', created); + customer = created.body; + console.log(`created: ${customer.id} (kyb: ${kybOf(customer)})`); +} + +// Internal accounts only exist post-approval; report either way. +const accts = await grid( + cfg, + 'GET', + `/customers/internal-accounts?customerId=${encodeURIComponent(customer.id)}`, +); +if (accts.status === 200) { + const rows = accts.body.data ?? []; + if (rows.length === 0) { + console.log( + `accounts: none yet — BUSINESS customers provision internal accounts after KYB approval (kyb: ${kybOf(customer)})`, + ); + } else { + for (const a of rows) { + console.log(`account: ${a.id} ${a.balance?.currency?.code ?? '?'} ${a.type ?? ''}`.trimEnd()); + } + } +} else { + console.log(`accounts: lookup returned HTTP ${accts.status} (skipped)`); +} + +if (args.dryRun) { + console.log(`dry-run: would set ${ENV_KEY}=${customer.id} in .env.local`); +} else { + const wrote = upsertEnvKey( + ENV_PATH, + ENV_KEY, + customer.id, + `Sample business customer (platformCustomerId: ${args.platformId}) — scripts/ensure-business-customer.mjs`, + ); + console.log(`.env.local: ${ENV_KEY} ${wrote}`); +} diff --git a/components/grid-wallet-prod/scripts/export-sf-symbols.mjs b/components/grid-wallet-prod/scripts/export-sf-symbols.mjs new file mode 100644 index 000000000..286246762 --- /dev/null +++ b/components/grid-wallet-prod/scripts/export-sf-symbols.mjs @@ -0,0 +1,127 @@ +#!/usr/bin/env node +/** + * Export SF Symbol SVGs from installed Apple SF Pro fonts (macOS). + * + * Note: only ~5,572 / 8,302 symbols have PUA codepoints in SF-Pro.woff2. + * faceid and xmark are NOT unicode-mapped — use SVG paths for those. + * + * Prereqs: SF Pro in /Library/Fonts (Apple developer download) + Node. + * Usage: node scripts/export-sf-symbols.mjs [symbol...] + * node scripts/export-sf-symbols.mjs xmark faceid + * + * Writes: + * public/assets/symbols/{name}.svg + * src/apps/shared/icons/sfSymbolPaths.ts (when --sync-paths is passed) + */ + +import { execSync } from 'node:child_process'; +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const root = path.join(__dirname, '..'); +const symbols = process.argv.slice(2).filter((a) => !a.startsWith('--')); +const syncPaths = process.argv.includes('--sync-paths'); +const names = symbols.length ? symbols : ['xmark', 'faceid']; + +/** Per-symbol SF Symbol weight for sf-symbols-svg export (Figma specs). */ +const WEIGHT_BY_SYMBOL = { + xmark: 'semibold', + plus: 'semibold', + checkmark: 'semibold', + faceid: 'bold', + 'arrow.up': 'semibold', + 'arrow.up.arrow.down': 'bold', + 'play.fill': 'semibold', + 'creditcard.and.numbers': 'medium', + ellipsis: 'medium', + 'arrow.left': 'semibold', + 'chevron.left': 'semibold', + 'chevron.right': 'semibold', + 'chevron.down': 'semibold', + 'delete.left': 'semibold', + viewfinder: 'semibold', + // Widest tab-bar glyph — the 24px fit-scale is the smallest of the set, so + // lighter weights read ~20% thinner than the neighbors; semibold compensates. + 'person.2': 'semibold', +}; + +const outDir = path.join(root, 'public/assets/symbols'); +const tmpDir = fs.mkdtempSync(path.join(root, '.tmp-sf-symbols-')); +const iconsFile = path.join(tmpDir, 'icons.txt'); +const exportDir = path.join(tmpDir, 'out'); + +fs.mkdirSync(outDir, { recursive: true }); +fs.writeFileSync(iconsFile, `${names.join('\n')}\n`); + +const weightFlags = [...new Set(names.map((n) => WEIGHT_BY_SYMBOL[n] ?? 'regular'))] + .flatMap((w) => ['--weight', w]) + .join(' '); + +execSync( + `npx --yes sf-symbols-svg --icons-list "${iconsFile}" --output "${exportDir}" --fonts-dir /Library/Fonts ${weightFlags}`, + { stdio: 'inherit', cwd: root }, +); + +for (const name of names) { + const weight = WEIGHT_BY_SYMBOL[name] ?? 'regular'; + const src = + weight === 'regular' + ? path.join(exportDir, `${name}.svg`) + : path.join(exportDir, `${name}-${weight}.svg`); + const dest = path.join(outDir, `${name}.svg`); + if (!fs.existsSync(src)) { + console.error(`Missing export for "${name}" — is SF Pro installed in /Library/Fonts?`); + process.exit(1); + } + fs.copyFileSync(src, dest); + console.log('wrote', path.relative(root, dest)); +} + +if (syncPaths) { + const entries = names.map((name) => { + const weight = WEIGHT_BY_SYMBOL[name] ?? 'regular'; + const svgName = weight === 'regular' ? `${name}.svg` : `${name}-${weight}.svg`; + const svg = fs.readFileSync(path.join(exportDir, svgName), 'utf8'); + const pathMatch = svg.match(/]*)\/>/); + if (!pathMatch) throw new Error(`Could not parse path for ${name}`); + const attrs = pathMatch[1]; + const d = attrs.match(/d="([^"]+)"/)?.[1]; + const transform = attrs.match(/transform="([^"]+)"/)?.[1]; + if (!d) throw new Error(`Missing d for ${name}`); + return { name, d, transform }; + }); + + const union = entries.map((e) => `'${e.name}'`).join(' | '); + const body = entries + .map(({ name, d, transform }) => { + const transformLine = transform + ? `\n transform:\n '${transform}',` + : ''; + const key = /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name) ? name : `'${name}'`; + return ` ${key}: {${transformLine}\n d: '${d}',\n },`; + }) + .join('\n'); + + const ts = `/** SF Symbol outlines — generated from system fonts via scripts/export-sf-symbols.mjs */ + +export type SfSymbolName = ${union}; + +export interface SfSymbolPath { + d: string; + transform?: string; +} + +export const SF_SYMBOL_PATHS: Record = { +${body} +}; +`; + + const tsPath = path.join(root, 'src/apps/shared/icons/sfSymbolPaths.ts'); + fs.writeFileSync(tsPath, ts); + console.log('wrote', path.relative(root, tsPath)); +} + +fs.rmSync(tmpDir, { recursive: true, force: true }); +console.log('Done.'); diff --git a/components/grid-wallet-prod/scripts/fetch-flags.mjs b/components/grid-wallet-prod/scripts/fetch-flags.mjs new file mode 100644 index 000000000..38d239937 --- /dev/null +++ b/components/grid-wallet-prod/scripts/fetch-flags.mjs @@ -0,0 +1,39 @@ +#!/usr/bin/env node +// Vendors the circular country flags used by the bank picker into +// public/assets/flags/.svg, so the demo is self-contained (no runtime CDN). +// Source: HatScripts/circle-flags (https://github.com/HatScripts/circle-flags). +// Codes are read from bankCountries.ts so this never drifts from the list. +// npm run fetch:flags + +import { readFileSync, mkdirSync, writeFileSync } from 'node:fs'; +import { resolve, dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const scriptDir = dirname(fileURLToPath(import.meta.url)); +const src = readFileSync(resolve(scriptDir, '../src/data/bankCountries.ts'), 'utf8'); +const codes = [...new Set([...src.matchAll(/code:\s*'([a-z]{2})'/g)].map((m) => m[1]))]; + +const outDir = resolve(scriptDir, '../public/assets/flags'); +mkdirSync(outDir, { recursive: true }); + +const BASE = 'https://cdn.jsdelivr.net/gh/HatScripts/circle-flags@gh-pages/flags'; +let ok = 0; +const failed = []; +for (const cc of codes) { + try { + const res = await fetch(`${BASE}/${cc}.svg`); + if (!res.ok) throw new Error(`HTTP ${res.status}`); + const svg = await res.text(); + if (!svg.includes(' ${outDir}`); +if (failed.length) { + console.error('Failed:', failed); + process.exit(1); +} diff --git a/components/grid-wallet-prod/scripts/generate-bank-fields.mjs b/components/grid-wallet-prod/scripts/generate-bank-fields.mjs new file mode 100644 index 000000000..495a4927d --- /dev/null +++ b/components/grid-wallet-prod/scripts/generate-bank-fields.mjs @@ -0,0 +1,136 @@ +#!/usr/bin/env node +// Generates src/data/bankAccountFields.generated.ts from the Grid OpenAPI spec. +// +// Accuracy guard: this demo ships next to the docs, so per-country bank fields +// must be 1:1 with the API. Field facts (keys, required, patterns, enums, and +// even sample values) are DERIVED from openapi/ via a Redocly bundle - never +// hand-authored or recalled. Regenerate after any spec change: +// npm run gen:bank-fields +// and `npm run verify:bank-fields` fails CI if the committed output drifts. + +import { execSync } from 'node:child_process'; +import { readFileSync, writeFileSync } from 'node:fs'; +import { dirname, resolve, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { tmpdir } from 'node:os'; + +const scriptDir = dirname(fileURLToPath(import.meta.url)); +const repoRoot = resolve(scriptDir, '../../..'); +const outFile = resolve(scriptDir, '../src/data/bankAccountFields.generated.ts'); +const tmpJson = join(tmpdir(), `grid-bundle-${process.pid}.json`); + +// Crypto wallets are the demo's separate "Crypto wallet" path, not the fiat +// bank picker - exclude them here. +const CRYPTO = new Set([ + 'SPARK_WALLET', + 'LIGHTNING', + 'SOLANA_WALLET', + 'TRON_WALLET', + 'POLYGON_WALLET', + 'BASE_WALLET', + 'ETHEREUM_WALLET', +]); + +// Handled by the POST builder, not shown as editable account fields: +// accountType is the discriminator; beneficiary is a uniform sub-object. +const OMIT_FIELDS = new Set(['accountType', 'beneficiary']); + +console.log('Bundling spec via Redocly...'); +execSync(`npx --no-install @redocly/cli bundle openapi/openapi.yaml -o "${tmpJson}"`, { + cwd: repoRoot, + stdio: ['ignore', 'ignore', 'inherit'], +}); + +const spec = JSON.parse(readFileSync(tmpJson, 'utf8')); +const schemas = spec.components?.schemas; +if (!schemas) throw new Error('No components.schemas in bundled spec'); + +const refName = (ref) => (typeof ref === 'string' ? ref.split('/').pop() : null); +const deref = (node) => (node && node.$ref ? schemas[refName(node.$ref)] : node); + +const oneOf = schemas.ExternalAccountCreateInfoOneOf; +const mapping = oneOf?.discriminator?.mapping; +if (!mapping) throw new Error('No ExternalAccountCreateInfoOneOf discriminator mapping'); + +function collectFields(createInfo) { + const required = new Set(); + const props = {}; + let example = {}; + for (const memberRaw of createInfo.allOf ?? []) { + const member = deref(memberRaw); + if (!member) continue; + (member.required ?? []).forEach((r) => required.add(r)); + Object.assign(props, member.properties ?? {}); + if (member.example && typeof member.example === 'object') { + example = { ...example, ...member.example }; + } + } + + const fields = []; + for (const [key, propRaw] of Object.entries(props)) { + if (OMIT_FIELDS.has(key)) continue; + const prop = deref(propRaw) ?? propRaw; + const field = { key, required: required.has(key), kind: prop.enum ? 'select' : 'text' }; + if (prop.enum) field.enum = prop.enum; + if (prop.pattern) field.pattern = prop.pattern; + if (typeof prop.minLength === 'number') field.minLength = prop.minLength; + if (typeof prop.maxLength === 'number') field.maxLength = prop.maxLength; + if (prop.description) field.description = prop.description; + const ex = prop.example ?? example[key]; + if (ex !== undefined) field.example = String(ex); + fields.push(field); + } + return fields; +} + +const out = {}; +for (const [accountType, ref] of Object.entries(mapping)) { + if (CRYPTO.has(accountType)) continue; + const createInfo = schemas[refName(ref)]; + if (!createInfo) throw new Error(`Missing create-info schema for ${accountType}`); + out[accountType] = { + accountType, + currency: accountType.replace(/_ACCOUNT$/, ''), + fields: collectFields(createInfo), + }; +} + +const sorted = Object.fromEntries(Object.keys(out).sort().map((k) => [k, out[k]])); + +const header = `// GENERATED by scripts/generate-bank-fields.mjs from the Grid OpenAPI spec. +// DO NOT EDIT BY HAND. Field facts (keys, required, patterns, enums, examples) +// are derived 1:1 from openapi/ so the demo stays accurate next to the docs. +// Regenerate: npm run gen:bank-fields | Verify (CI): npm run verify:bank-fields +// +// Every fiat external account also requires a \`beneficiary\` (INDIVIDUAL +// { fullName } or BUSINESS { legalName }) - added by the POST builder, not here. +/* eslint-disable */ + +export type BankFieldKind = 'text' | 'select'; + +export interface BankFieldSpec { + key: string; + required: boolean; + kind: BankFieldKind; + enum?: string[]; + pattern?: string; + minLength?: number; + maxLength?: number; + description?: string; + example?: string; +} + +export interface BankAccountSchema { + /** Discriminator value, e.g. "USD_ACCOUNT". */ + accountType: string; + /** ISO 4217 currency (the accountType prefix), e.g. "USD". */ + currency: string; + /** Country-specific account fields (excludes accountType + beneficiary). */ + fields: BankFieldSpec[]; +} + +export const BANK_ACCOUNT_SCHEMAS: Record = ${JSON.stringify(sorted, null, 2)}; +`; + +writeFileSync(outFile, header); +console.log(`Wrote ${Object.keys(sorted).length} account types -> ${outFile}`); diff --git a/components/grid-wallet-prod/scripts/messaging-batch.mjs b/components/grid-wallet-prod/scripts/messaging-batch.mjs new file mode 100644 index 000000000..a5747cbd4 --- /dev/null +++ b/components/grid-wallet-prod/scripts/messaging-batch.mjs @@ -0,0 +1,125 @@ +/* ChatsApp batch: every screen/flow of the messaging skin, one theme per run. + Usage: node scripts/messaging-batch.mjs [dark] + Writes /tmp/chatsapp-batch//NN-name.png (clipped to the phone). */ +import { chromium } from 'playwright'; +import fs from 'node:fs'; + +const dark = process.argv.includes('dark'); +const theme = dark ? 'dark' : 'light'; +const outDir = `/tmp/chatsapp-batch/${theme}`; +fs.rmSync(outDir, { recursive: true, force: true }); +fs.mkdirSync(outDir, { recursive: true }); + +const browser = await chromium.launch(); +const page = await browser.newPage({ viewport: { width: 1600, height: 1000 } }); +page.on('pageerror', (e) => console.log('[pageerror]', e.message)); +await page.goto(`http://localhost:4000/${dark ? '?theme=dark' : ''}`, { + waitUntil: 'networkidle', +}); +await page.waitForTimeout(1500); + +const phone = page.locator('[class*=phone]').first(); +let n = 0; +async function shot(name, settle = 600) { + await page.waitForTimeout(settle); + const box = await phone.boundingBox(); + n += 1; + const file = `${outDir}/${String(n).padStart(2, '0')}-${name}.png`; + await page.screenshot({ path: file, clip: box }); + console.log('shot', file); +} +async function dismissSheet() { + // Full-bleed money sheets cover the scrim — use their header X when it's up. + const close = page.getByRole('button', { name: 'Close' }).last(); + if (await close.isVisible().catch(() => false)) { + await close.click(); + } else { + const scrim = page.getByRole('button', { name: 'Dismiss' }).last(); + if (await scrim.isVisible().catch(() => false)) await scrim.click(); + } + await page.waitForTimeout(900); +} + +const sidebar = page.getByRole('complementary'); + +// ── Auth ──────────────────────────────────────────────────────────────────── +await sidebar.getByText('Messaging', { exact: true }).click(); +await page.waitForTimeout(1400); +await shot('auth-welcome'); + +// Email sheet (capture, then back out). +await page.getByRole('button', { name: 'Continue with email' }).click(); +await shot('auth-email-sheet', 900); +await page.getByRole('button', { name: 'Close' }).click(); +await page.waitForTimeout(900); + +// Phone sheet → Next → OTP + notification → tap notification → sign in. +await page.getByRole('button', { name: 'Continue with phone' }).click(); +await shot('auth-phone-sheet', 900); +await page.getByRole('button', { name: 'Next' }).click(); +await page.waitForTimeout(2400); // code step + the notification swoop +await shot('auth-otp-notification', 0); +await page.getByText('22395').first().click(); // autofill + verify + submit +await page.waitForTimeout(4500); // checkmark beat + sheet dismiss + reveal +await shot('wallet-home-entrance', 1800); + +// ── Deposit (full flow: sources → add bank → amount → confirm → Face ID) ─── +await page.getByRole('button', { name: 'Add', exact: true }).click(); +await shot('deposit-sources', 1000); +await page.getByText('Bank account', { exact: true }).first().click(); +await page.waitForTimeout(2000); // skeleton → empty state +await shot('deposit-banks-empty', 0); +await page.getByRole('button', { name: 'Add bank', exact: true }).click(); +await shot('deposit-country-picker', 1000); +await page.getByText('Mexico', { exact: true }).first().click(); +await shot('deposit-bank-form', 1000); +await page.getByRole('button', { name: 'Add bank account' }).last().click(); // save +await page.waitForTimeout(2000); // saving beat → amount step +for (const d of ['5', '0', '0']) { + await page.getByRole('button', { name: d, exact: true }).first().click(); + await page.waitForTimeout(120); +} +await shot('deposit-amount', 400); +await page.locator('[class*=ctaWrap] button').first().click(); // Continue +await shot('deposit-confirm', 1200); +await page.locator('[class*=ctaWrap] button').first().click(); // Confirm +await shot('deposit-faceid', 600); +await page.waitForTimeout(2800); // Face ID resolves → toast + activity row +await shot('deposit-toast-home', 0); +await page.waitForTimeout(2500); // let the toast clear + +// ── Withdraw / Send / Receive (sidebar jumps — entry screen each) ────────── +await sidebar.getByText('Withdraw', { exact: true }).click(); +await shot('withdraw-sheet', 1800); +await dismissSheet(); + +await sidebar.getByText('Send', { exact: true }).click(); +await shot('send-sheet', 1800); +await dismissSheet(); + +await sidebar.getByText('Receive', { exact: true }).click(); +await shot('receive-sheet', 1800); +await dismissSheet(); + +// ── Card flow ─────────────────────────────────────────────────────────────── +await sidebar.getByText('Issue card', { exact: true }).click(); +await shot('card-intro', 1800); +await page.getByRole('button', { name: 'Get your free card' }).click(); +await shot('card-creating', 700); +await page.waitForTimeout(2600); // brain settles on 'ready' +await shot('card-ready', 0); +await page.getByRole('button', { name: 'Continue' }).click(); +await shot('card-home-empty', 1200); + +// Tap to pay (system choreography) — reader status, then the charge lands. +await phone.getByRole('button', { name: /Tap to pay/ }).click(); +await shot('tap-to-pay-hold', 900); +await page.waitForTimeout(6500); // Face ID beat + done + content back in +await shot('card-home-transaction', 600); + +// Close the card flow → back at home with activity. +await page.getByRole('button', { name: 'Close' }).first().click(); +await shot('wallet-home-final', 1200); + +console.log('batch done:', outDir); +await browser.close(); diff --git a/components/grid-wallet-prod/scripts/messaging-fixes-probe.mjs b/components/grid-wallet-prod/scripts/messaging-fixes-probe.mjs new file mode 100644 index 000000000..cfd712253 --- /dev/null +++ b/components/grid-wallet-prod/scripts/messaging-fixes-probe.mjs @@ -0,0 +1,56 @@ +/* Probe the feedback fixes: circle flags, timestamp-only activity, hover dim. */ +import { chromium } from 'playwright'; +import fs from 'node:fs'; + +const outDir = '/tmp/msg-fixes'; +fs.rmSync(outDir, { recursive: true, force: true }); +fs.mkdirSync(outDir, { recursive: true }); + +const browser = await chromium.launch(); +const page = await browser.newPage({ viewport: { width: 1600, height: 1000 } }); +await page.goto('http://localhost:4000/', { waitUntil: 'networkidle' }); +await page.waitForTimeout(1500); + +const phone = page.locator('[class*=phone]').first(); +const sidebar = page.getByRole('complementary'); +async function shot(name, settle = 800) { + await page.waitForTimeout(settle); + const box = await phone.boundingBox(); + await page.screenshot({ path: `${outDir}/${name}.png`, clip: box }); + console.log('shot', name); +} + +await sidebar.getByText('Messaging', { exact: true }).click(); +await page.waitForTimeout(1000); + +// Deposit flow → country picker + amount/confirm (flags + green CTA check). +await sidebar.getByText('Deposit', { exact: true }).click(); +await page.waitForTimeout(2600); +await page.getByText('Bank account', { exact: true }).first().click(); +await page.waitForTimeout(2000); +await page.getByRole('button', { name: 'Add bank', exact: true }).click(); +await shot('country-picker', 1000); +await page.getByText('Mexico', { exact: true }).first().click(); +await page.waitForTimeout(1000); +await page.getByRole('button', { name: 'Add bank account' }).last().click(); +await page.waitForTimeout(2000); +for (const d of ['5', '0', '0']) { + await page.getByRole('button', { name: d, exact: true }).first().click(); + await page.waitForTimeout(100); +} +await shot('amount-flag-row', 400); +await page.locator('[class*=ctaWrap] button').first().click(); +await shot('confirm-flag-row', 1200); +await page.locator('[class*=ctaWrap] button').first().click(); +await page.waitForTimeout(3000); // Face ID → toast → activity row lands +await page.waitForTimeout(2500); // toast clears + +// Home: full-bleed flag row + timestamp-only status. +await shot('home-activity', 400); + +// Hover the action grid (over Scan) — no-ops should dim. +await phone.getByRole('button', { name: 'Scan' }).hover(); +await shot('home-actions-hover', 600); + +console.log('done'); +await browser.close(); diff --git a/components/grid-wallet-prod/scripts/messaging-home-shot.mjs b/components/grid-wallet-prod/scripts/messaging-home-shot.mjs new file mode 100644 index 000000000..be2dd0dd3 --- /dev/null +++ b/components/grid-wallet-prod/scripts/messaging-home-shot.mjs @@ -0,0 +1,25 @@ +/* Quick home-only shot after tweaks. Usage: node scripts/messaging-home-shot.mjs [dark] */ +import { chromium } from 'playwright'; + +const dark = process.argv.includes('dark'); +const tag = dark ? 'dark' : 'light'; + +const browser = await chromium.launch(); +const page = await browser.newPage({ viewport: { width: 1600, height: 1000 } }); +await page.goto(`http://localhost:4000/${dark ? '?theme=dark' : ''}`, { + waitUntil: 'networkidle', +}); +await page.waitForTimeout(1500); +const sidebar = page.getByRole('complementary'); +await sidebar.getByText('Messaging', { exact: true }).click(); +await page.waitForTimeout(1000); +await sidebar.getByText('Deposit', { exact: true }).click(); +await page.waitForTimeout(2600); +// Close the deposit sheet so the home shows. +const close = page.getByRole('button', { name: 'Close' }).last(); +if (await close.isVisible().catch(() => false)) await close.click(); +await page.waitForTimeout(1200); +const box = await page.locator('[class*=phone]').first().boundingBox(); +await page.screenshot({ path: `/tmp/msg-home-${tag}.png`, clip: box }); +console.log('done', tag); +await browser.close(); diff --git a/components/grid-wallet-prod/scripts/messaging-inline-probe.mjs b/components/grid-wallet-prod/scripts/messaging-inline-probe.mjs new file mode 100644 index 000000000..d63c53ae3 --- /dev/null +++ b/components/grid-wallet-prod/scripts/messaging-inline-probe.mjs @@ -0,0 +1,57 @@ +/* Probe the inline auth flow + flat home buttons + glass pill tab bar. */ +import { chromium } from 'playwright'; +import fs from 'node:fs'; + +const dark = process.argv.includes('dark'); +const tag = dark ? 'dark' : 'light'; +const outDir = `/tmp/msg-inline/${tag}`; +fs.rmSync(outDir, { recursive: true, force: true }); +fs.mkdirSync(outDir, { recursive: true }); + +const browser = await chromium.launch(); +const page = await browser.newPage({ viewport: { width: 1600, height: 1000 } }); +page.on('pageerror', (e) => console.log('[pageerror]', e.message)); +await page.goto(`http://localhost:4000/${dark ? '?theme=dark' : ''}`, { + waitUntil: 'networkidle', +}); +await page.waitForTimeout(1500); + +const phone = page.locator('[class*=phone]').first(); +const sidebar = page.getByRole('complementary'); +let n = 0; +async function shot(name, settle = 800) { + await page.waitForTimeout(settle); + const box = await phone.boundingBox(); + n += 1; + await page.screenshot({ path: `${outDir}/${String(n).padStart(2, '0')}-${name}.png`, clip: box }); + console.log('shot', name); +} + +await sidebar.getByText('Messaging', { exact: true }).click(); +await shot('welcome', 1400); + +// Phone: entry push → country push → pick → back → OTP push → autofill → home. +await page.getByRole('button', { name: 'Continue with phone' }).click(); +await shot('phone-entry', 900); +await phone.getByRole('button', { name: /United States/ }).click(); +await shot('country-page', 900); +await phone.getByRole('button', { name: /Brazil/ }).first().click(); +await shot('entry-brazil', 900); +// Back to US for the demo corridor. +await phone.getByRole('button', { name: /Brazil/ }).click(); +await page.waitForTimeout(800); +await phone.getByRole('button', { name: /United States/ }).first().click(); +await page.waitForTimeout(800); +await page.getByRole('button', { name: 'Next' }).click(); +await page.waitForTimeout(2400); +await shot('otp-notification', 0); +await page.getByText('22395').first().click(); +await page.waitForTimeout(4500); +await shot('wallet-home', 1800); + +// Hover a real action + the tab bar zone for the flat buttons + glass pill. +await phone.getByRole('button', { name: 'Scan' }).hover(); +await shot('home-hover-dim', 500); + +console.log('done:', outDir); +await browser.close(); diff --git a/components/grid-wallet-prod/scripts/messaging-smoke.mjs b/components/grid-wallet-prod/scripts/messaging-smoke.mjs new file mode 100644 index 000000000..e8d65648b --- /dev/null +++ b/components/grid-wallet-prod/scripts/messaging-smoke.mjs @@ -0,0 +1,29 @@ +/* Quick smoke: pick the Messaging use case, screenshot auth; jump Deposit, + screenshot wallet home. Usage: node scripts/messaging-smoke.mjs [dark] */ +import { chromium } from 'playwright'; + +const dark = process.argv.includes('dark'); +const url = `http://localhost:4000/${dark ? '?theme=dark' : ''}`; +const tag = dark ? 'dark' : 'light'; + +const browser = await chromium.launch(); +const page = await browser.newPage({ viewport: { width: 1600, height: 1000 } }); +page.on('console', (m) => { + if (m.type() === 'error') console.log('[console.error]', m.text()); +}); +page.on('pageerror', (e) => console.log('[pageerror]', e.message)); +await page.goto(url, { waitUntil: 'networkidle' }); +await page.waitForTimeout(1200); + +const sidebar = page.getByRole('complementary'); +await sidebar.getByText('Messaging', { exact: true }).click(); +await page.waitForTimeout(1400); +await page.screenshot({ path: `/tmp/msg-smoke-auth-${tag}.png` }); + +// Jump straight into the wallet via a flow jump (passkey won't run headless). +await sidebar.getByText('Deposit', { exact: true }).click(); +await page.waitForTimeout(2600); +await page.screenshot({ path: `/tmp/msg-smoke-deposit-${tag}.png` }); + +console.log('done'); +await browser.close(); diff --git a/components/grid-wallet-prod/scripts/messaging-verify.mjs b/components/grid-wallet-prod/scripts/messaging-verify.mjs new file mode 100644 index 000000000..cbeb2ff46 --- /dev/null +++ b/components/grid-wallet-prod/scripts/messaging-verify.mjs @@ -0,0 +1,41 @@ +/* Cross-skin sanity: every built skin still renders its auth screen, and a + mid-flow skin switch INTO messaging renders sanely (money sheet open). */ +import { chromium } from 'playwright'; +import fs from 'node:fs'; + +const outDir = '/tmp/chatsapp-verify'; +fs.rmSync(outDir, { recursive: true, force: true }); +fs.mkdirSync(outDir, { recursive: true }); + +const browser = await chromium.launch(); +const page = await browser.newPage({ viewport: { width: 1600, height: 1000 } }); +page.on('pageerror', (e) => console.log('[pageerror]', e.message)); +await page.goto('http://localhost:4000/', { waitUntil: 'networkidle' }); +await page.waitForTimeout(1500); + +const phone = page.locator('[class*=phone]').first(); +const sidebar = page.getByRole('complementary'); + +async function shot(name, settle = 1400) { + await page.waitForTimeout(settle); + const box = await phone.boundingBox(); + await page.screenshot({ path: `${outDir}/${name}.png`, clip: box }); + console.log('shot', name); +} + +for (const label of ['Fintech', 'Creator', 'Social', 'Marketplace', 'On-demand']) { + await sidebar.getByText(label, { exact: true }).click(); + await shot(`auth-${label.toLowerCase()}`); +} + +// Mid-flow switch: open the deposit sheet on Aurora, then switch to Messaging. +await sidebar.getByText('Fintech', { exact: true }).click(); +await page.waitForTimeout(1200); +await sidebar.getByText('Deposit', { exact: true }).click(); +await page.waitForTimeout(2600); +await shot('aurora-deposit-open', 400); +await sidebar.getByText('Messaging', { exact: true }).click(); +await shot('messaging-after-midflow-switch', 2000); + +console.log('verify done:', outDir); +await browser.close(); diff --git a/components/grid-wallet-prod/scripts/sheet-frames.mjs b/components/grid-wallet-prod/scripts/sheet-frames.mjs new file mode 100644 index 000000000..58d26f023 --- /dev/null +++ b/components/grid-wallet-prod/scripts/sheet-frames.mjs @@ -0,0 +1,39 @@ +// Burst-capture the email sheet during the back (code → email) transition to +// see whether the height eases or snaps. One engine, one run. +import { chromium } from 'playwright'; + +const browser = await chromium.launch(); +const page = await browser.newPage({ viewport: { width: 1600, height: 1000 } }); +await page.goto('http://localhost:4000', { waitUntil: 'networkidle' }); +await page.waitForTimeout(800); +await page.getByText('Email', { exact: true }).first().click(); +await page.waitForTimeout(800); +await page.getByText('Continue with email', { exact: true }).first().click(); +await page.waitForTimeout(1000); +await page.getByRole('button', { name: 'Continue', exact: true }).first().click(); +await page.waitForTimeout(2600); + +// Sample the sheet's height every ~40ms across the back transition. +const samples = await page.evaluate(async () => { + const sheet = document.querySelector('[class*="BottomSheet_sheet__"]'); + const back = [...document.querySelectorAll('button')].find( + (b) => b.getAttribute('aria-label') === 'Back', + ); + const out = []; + const t0 = performance.now(); + back.click(); + await new Promise((resolve) => { + const tick = () => { + out.push({ + t: Math.round(performance.now() - t0), + h: Math.round(sheet.getBoundingClientRect().height * 10) / 10, + }); + if (performance.now() - t0 < 700) requestAnimationFrame(tick); + else resolve(); + }; + requestAnimationFrame(tick); + }); + return out; +}); +console.log(samples.map((s) => `${s.t}ms ${s.h}`).join('\n')); +await browser.close(); diff --git a/components/grid-wallet-prod/scripts/verify-bank-data.ts b/components/grid-wallet-prod/scripts/verify-bank-data.ts new file mode 100644 index 000000000..a5e8e2a6d --- /dev/null +++ b/components/grid-wallet-prod/scripts/verify-bank-data.ts @@ -0,0 +1,11 @@ +// Accuracy check for the curated country list: asserts every BANK_COUNTRIES +// entry maps to a real spec accountType, has a valid region where required, and +// that any sample override satisfies the spec field pattern. Run in CI: +// npm run verify:bank-data +import { assertBankCountries, BANK_COUNTRIES, currencyFor } from '../src/data/bankCountries'; + +assertBankCountries(); +const currencies = new Set(BANK_COUNTRIES.map(currencyFor)); +console.log( + `bankCountries OK: ${BANK_COUNTRIES.length} countries across ${currencies.size} currencies, all validated against the spec.`, +); diff --git a/components/grid-wallet-prod/scripts/webkit-lens-swoop.mjs b/components/grid-wallet-prod/scripts/webkit-lens-swoop.mjs new file mode 100644 index 000000000..0b48e98f6 --- /dev/null +++ b/components/grid-wallet-prod/scripts/webkit-lens-swoop.mjs @@ -0,0 +1,32 @@ +// Captures a burst of frames around the notification's swoop entrance. +// Usage: node scripts/webkit-lens-swoop.mjs +import { webkit, chromium } from 'playwright'; + +const engine = process.argv[2] === 'chromium' ? chromium : webkit; +const prefix = process.argv[3] ?? `/tmp/swoop-${process.argv[2] ?? 'webkit'}`; + +const browser = await engine.launch(); +const page = await browser.newPage({ + viewport: { width: 1600, height: 1000 }, + deviceScaleFactor: 2, +}); +await page.goto('http://localhost:4000', { waitUntil: 'networkidle' }); +await page.waitForTimeout(800); +await page.getByText('Email', { exact: true }).first().click(); +await page.waitForTimeout(800); +await page.getByText('Continue with email', { exact: true }).first().click(); +await page.waitForTimeout(600); + +// The phone screen region only (keeps the burst shots small). +const phone = await page.locator('main').boundingBox(); +const clip = { x: 1000, y: 50, width: 560, height: 400 }; + +await page.getByRole('button', { name: 'Continue', exact: true }).first().click(); +const t0 = Date.now(); +for (const ms of [1450, 1600, 1750, 1950]) { + const wait = t0 + ms - Date.now(); + if (wait > 0) await page.waitForTimeout(wait); + await page.screenshot({ path: `${prefix}-${ms}.png`, clip }); +} +console.log('ok', prefix, phone ? '' : '(no main bbox)'); +await browser.close(); diff --git a/components/grid-wallet-prod/scripts/webkit-lens-verify.mjs b/components/grid-wallet-prod/scripts/webkit-lens-verify.mjs new file mode 100644 index 000000000..66064baf8 --- /dev/null +++ b/components/grid-wallet-prod/scripts/webkit-lens-verify.mjs @@ -0,0 +1,59 @@ +// Verification harness for the Safari WebGL notification lens. +// Usage: node scripts/webkit-lens-verify.mjs +// Captures: full capsule at t0 and t0+1s (liveness diff), TL/BR corner crops, +// a mid-swoop frame, and any console errors. +import { webkit, chromium } from 'playwright'; + +const engine = process.argv[2] === 'chromium' ? chromium : webkit; +const prefix = process.argv[3] ?? `/tmp/lens-${process.argv[2] ?? 'webkit'}`; + +const browser = await engine.launch(); +const page = await browser.newPage({ + viewport: { width: 1600, height: 1000 }, + deviceScaleFactor: 3, +}); +const errors = []; +page.on('console', (msg) => { + if (msg.type() === 'error' || msg.type() === 'warning') { + errors.push(`[${msg.type()}] ${msg.text()}`); + } +}); +page.on('pageerror', (err) => errors.push(`[pageerror] ${err.message}`)); + +await page.goto('http://localhost:4000', { waitUntil: 'networkidle' }); +await page.waitForTimeout(800); +await page.getByText('Email', { exact: true }).first().click(); +await page.waitForTimeout(800); +await page.getByText('Continue with email', { exact: true }).first().click(); +await page.waitForTimeout(600); +await page.getByRole('button', { name: 'Continue', exact: true }).first().click(); + +// Catch the swoop mid-flight (~1s settle + ~0.25s into the spring). +await page.waitForTimeout(1250); +await page.screenshot({ path: `${prefix}-swoop.png` }); +await page.waitForTimeout(2000); + +const notif = page.getByRole('button', { name: /one-time code/i }).first(); +const box = await notif.boundingBox(); +const clip = { + x: box.x - 12, + y: box.y - 12, + width: box.width + 24, + height: box.height + 24, +}; +await page.screenshot({ path: `${prefix}-frame-a.png`, clip }); +await page.waitForTimeout(1000); +await page.screenshot({ path: `${prefix}-frame-b.png`, clip }); + +await page.screenshot({ + path: `${prefix}-tl.png`, + clip: { x: box.x - 12, y: box.y - 12, width: 80, height: 60 }, +}); +await page.screenshot({ + path: `${prefix}-br.png`, + clip: { x: box.x + box.width - 68, y: box.y + box.height - 48, width: 80, height: 60 }, +}); + +console.log('box', JSON.stringify(box)); +console.log(errors.length ? `console issues:\n${errors.join('\n')}` : 'console clean'); +await browser.close(); diff --git a/components/grid-wallet-prod/scripts/webkit-notif-corner.mjs b/components/grid-wallet-prod/scripts/webkit-notif-corner.mjs new file mode 100644 index 000000000..6428f6864 --- /dev/null +++ b/components/grid-wallet-prod/scripts/webkit-notif-corner.mjs @@ -0,0 +1,43 @@ +// Corner-comparison harness for the glass notification. +// Usage: node scripts/webkit-notif-corner.mjs [hideShadow] +import { webkit, chromium } from 'playwright'; + +const engine = process.argv[2] === 'chromium' ? chromium : webkit; +const prefix = process.argv[3] ?? `/tmp/notif-${process.argv[2] ?? 'webkit'}`; +const hideShadow = process.argv.includes('hideShadow'); + +const browser = await engine.launch(); +const page = await browser.newPage({ + viewport: { width: 1600, height: 1000 }, + deviceScaleFactor: 3, +}); +await page.goto('http://localhost:4000', { waitUntil: 'networkidle' }); +await page.waitForTimeout(800); +await page.getByText('Email', { exact: true }).first().click(); +await page.waitForTimeout(800); +await page.getByText('Continue with email', { exact: true }).first().click(); +await page.waitForTimeout(600); +await page.getByRole('button', { name: 'Continue', exact: true }).first().click(); +await page.waitForTimeout(3200); + +if (hideShadow) { + await page.evaluate(() => { + for (const el of document.querySelectorAll('[class*="shadowBlob"]')) { + el.style.display = 'none'; + } + }); + await page.waitForTimeout(300); +} + +const notif = page.getByRole('button', { name: /one-time code/i }).first(); +const box = await notif.boundingBox(); +await page.screenshot({ + path: `${prefix}-tl.png`, + clip: { x: box.x - 12, y: box.y - 12, width: 80, height: 60 }, +}); +await page.screenshot({ + path: `${prefix}-br.png`, + clip: { x: box.x + box.width - 68, y: box.y + box.height - 48, width: 80, height: 60 }, +}); +console.log('ok', prefix); +await browser.close(); diff --git a/components/grid-wallet-prod/scripts/webkit-notif-probe.mjs b/components/grid-wallet-prod/scripts/webkit-notif-probe.mjs new file mode 100644 index 000000000..4e67478dc --- /dev/null +++ b/components/grid-wallet-prod/scripts/webkit-notif-probe.mjs @@ -0,0 +1,97 @@ +// Probe which style on the tint overlay causes WebKit's corner mismatch. +// Usage: node scripts/webkit-notif-probe.mjs +import { webkit } from 'playwright'; + +const variant = process.argv[2] ?? 'none'; + +const browser = await webkit.launch(); +const page = await browser.newPage({ + viewport: { width: 1600, height: 1000 }, + deviceScaleFactor: 3, +}); +await page.goto('http://localhost:4000', { waitUntil: 'networkidle' }); +await page.waitForTimeout(800); +await page.getByText('Email', { exact: true }).first().click(); +await page.waitForTimeout(800); +await page.getByText('Continue with email', { exact: true }).first().click(); +await page.waitForTimeout(600); +await page.getByRole('button', { name: 'Continue', exact: true }).first().click(); +await page.waitForTimeout(3200); + +const result = await page.evaluate((variant) => { + // The tint overlay: the absolutely-positioned div with a backdrop-filter + // inside the notification button. + const btn = [...document.querySelectorAll('button')].find((b) => + /one-time code/i.test(b.textContent ?? ''), + ); + if (!btn) return 'no button'; + const tint = [...btn.querySelectorAll('div')].find( + (d) => d.style.backdropFilter || d.style.webkitBackdropFilter, + ); + if (!tint) return 'no tint el'; + // hide the shadow for a clean read + for (const el of btn.querySelectorAll('[class*="shadowBlob"]')) el.style.display = 'none'; + if (variant === 'noBackdrop') { + tint.style.backdropFilter = 'none'; + tint.style.webkitBackdropFilter = 'none'; + } else if (variant === 'noClip') { + tint.style.clipPath = 'none'; + tint.style.webkitClipPath = 'none'; + } else if (variant === 'radius') { + tint.style.borderRadius = '28.8px'; + } else if (variant === 'hideTint') { + tint.style.display = 'none'; + } else if (variant === 'hideLens') { + const lens = [...btn.querySelectorAll('div')].find((d) => + (d.style.filter ?? '').startsWith('url('), + ); + if (lens) lens.style.display = 'none'; + } else if (variant === 'hideBrightness') { + const bright = [...btn.querySelectorAll('div')].find( + (d) => d.style.mixBlendMode === 'soft-light', + ); + if (bright) bright.style.display = 'none'; + else return 'no brightness el'; + } else if (variant === 'flatBackdrop') { + // Replace the filter's source content with a plain sharp gradient: if the + // lens then renders, the screen-copy subtree is what WebKit refuses. + const lens = [...btn.querySelectorAll('div')].find((d) => + (d.style.filter ?? '').startsWith('url('), + ); + if (!lens) return 'no lens el'; + lens.innerHTML = + '
'; + } else if (variant === 'underRed') { + // If the dark rim is ALPHA HOLES in the displaced output, a red layer + // under the glass will tint the ring red. + btn.style.background = 'red'; + } else if (variant === 'paint') { + // Solid debug fills: tint RED, output-clip wrapper LIME — whichever shape + // each one's clip actually renders is then unambiguous. + tint.style.background = 'rgba(255,0,0,0.85)'; + tint.style.backdropFilter = 'none'; + tint.style.webkitBackdropFilter = 'none'; + const out = [...btn.querySelectorAll('div')].find( + (d) => d.style.isolation === 'isolate', + ); + if (out) out.style.background = 'rgba(0,255,0,0.85)'; + else return 'no outputClip el'; + } + return { + clipPath: tint.style.clipPath ? 'path(...)' : tint.style.clipPath, + backdrop: tint.style.webkitBackdropFilter || tint.style.backdropFilter, + borderRadius: tint.style.borderRadius, + computedClip: getComputedStyle(tint).clipPath.slice(0, 24), + }; +}, variant); +console.log(JSON.stringify(result)); + +await page.waitForTimeout(400); +const notif = page.getByRole('button', { name: /one-time code/i }).first(); +const box = await notif.boundingBox(); +await page.screenshot({ + path: `/tmp/probe-${variant}-br.png`, + clip: { x: box.x + box.width - 68, y: box.y + box.height - 48, width: 80, height: 60 }, +}); +console.log('wrote', `/tmp/probe-${variant}-br.png`); +await browser.close(); diff --git a/components/grid-wallet-prod/scripts/webkit-notif-shot.mjs b/components/grid-wallet-prod/scripts/webkit-notif-shot.mjs new file mode 100644 index 000000000..304bb4b52 --- /dev/null +++ b/components/grid-wallet-prod/scripts/webkit-notif-shot.mjs @@ -0,0 +1,43 @@ +// Reproduce the Safari notification-corner mismatch in WebKit and screenshot +// it for inspection. Usage: node scripts/webkit-notif-shot.mjs [out.png] +import { webkit } from 'playwright'; + +const OUT = process.argv[2] ?? '/tmp/webkit-notif.png'; + +const browser = await webkit.launch(); +const page = await browser.newPage({ viewport: { width: 1600, height: 1000 } }); +await page.goto('http://localhost:4000', { waitUntil: 'networkidle' }); +await page.waitForTimeout(800); +await page.getByText('Email', { exact: true }).first().click(); +await page.waitForTimeout(800); + +// The aurora auth screen renders inside the phone. Start the email flow. +await page.getByText('Continue with email', { exact: true }).first().click(); +await page.waitForTimeout(600); + +// Email step's Continue (prefilled address) → sending beat → code step. +await page.getByRole('button', { name: 'Continue', exact: true }).first().click(); + +// Notification swoops in 1s after the code step lands; let it settle. +await page.waitForTimeout(3200); + +// Clip to the notification capsule (plus margin for the corners/shadow). +const notif = page.getByRole('button', { name: /one-time code/i }).first(); +let clip = null; +try { + const box = await notif.boundingBox(); + if (box) { + clip = { + x: Math.max(0, box.x - 24), + y: Math.max(0, box.y - 24), + width: box.width + 48, + height: box.height + 48, + }; + } +} catch { + // fall through to full-page shot +} + +await page.screenshot({ path: OUT, ...(clip ? { clip } : {}) }); +console.log('wrote', OUT, clip ? `clip=${JSON.stringify(clip)}` : '(full page)'); +await browser.close(); diff --git a/components/grid-wallet-prod/scripts/webkit-sheet-bottom.mjs b/components/grid-wallet-prod/scripts/webkit-sheet-bottom.mjs new file mode 100644 index 000000000..1cbf8e542 --- /dev/null +++ b/components/grid-wallet-prod/scripts/webkit-sheet-bottom.mjs @@ -0,0 +1,40 @@ +// Inspect the email sheet's bottom edge (frost fill vs edge stroke) before +// and after step-height changes. Usage: node scripts/webkit-sheet-bottom.mjs +import { webkit, chromium } from 'playwright'; + +const engine = process.argv[2] === 'chromium' ? chromium : webkit; +const tag = process.argv[2] === 'chromium' ? 'c' : 'w'; + +const browser = await engine.launch(); +const page = await browser.newPage({ + viewport: { width: 1600, height: 1000 }, + deviceScaleFactor: 3, +}); +await page.goto('http://localhost:4000', { waitUntil: 'networkidle' }); +await page.waitForTimeout(800); +await page.getByText('Email', { exact: true }).first().click(); +await page.waitForTimeout(800); +await page.getByText('Continue with email', { exact: true }).first().click(); +await page.waitForTimeout(1200); + +const sheet = page.locator('[class*="BottomSheet_sheet__"]').first(); +const shot = async (name) => { + const box = await sheet.boundingBox(); + await page.screenshot({ + path: `/tmp/sheet-${tag}-${name}.png`, + clip: { x: box.x - 8, y: box.y + box.height - 56, width: box.width + 16, height: 80 }, + }); +}; + +await shot('initial'); + +// → code step (height change) and back. +await page.getByRole('button', { name: 'Continue', exact: true }).first().click(); +await page.waitForTimeout(2500); +await shot('code'); +await page.getByRole('button', { name: 'Back' }).first().click(); +await page.waitForTimeout(1200); +await shot('back'); + +console.log('ok'); +await browser.close(); diff --git a/components/grid-wallet-prod/src/app/api/grid/[...path]/route.ts b/components/grid-wallet-prod/src/app/api/grid/[...path]/route.ts new file mode 100644 index 000000000..8b8e5e3f9 --- /dev/null +++ b/components/grid-wallet-prod/src/app/api/grid/[...path]/route.ts @@ -0,0 +1,99 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { + isAllowed, + redactHeaders, + substituteCustomerId, +} from '../allowlist'; + +export const runtime = 'nodejs'; +export const dynamic = 'force-dynamic'; + +const BASE = process.env.GRID_API_BASE_URL ?? 'https://api.lightspark.com/grid/2025-10-13'; +const CUSTOMER_ID = process.env.GRID_CUSTOMER_ID ?? ''; + +// Client-supplied headers that must reach Grid verbatim. +const PASS_THROUGH = ['grid-wallet-signature', 'request-id', 'idempotency-key']; +// Grid response headers worth surfacing to the client/panel. +const ECHO_RESPONSE = ['retry-after', 'content-type']; + +function basicAuth(): string { + const id = process.env.GRID_CLIENT_ID ?? ''; + const secret = process.env.GRID_CLIENT_SECRET ?? ''; + return 'Basic ' + Buffer.from(`${id}:${secret}`).toString('base64'); +} + +async function handle(req: NextRequest, method: string): Promise { + const url = new URL(req.url); + const pathname = url.pathname.replace(/^\/api\/grid/, ''); // e.g. "/quotes" + if (!isAllowed(method, pathname)) { + return NextResponse.json( + { + request: { method, path: pathname, headers: {} }, + response: { status: 403, body: { error: { code: 'PROXY_NOT_ALLOWED', message: `${method} ${pathname} is not proxied` } } }, + }, + { status: 403 }, + ); + } + + // Build target URL: substitute {customerId} in path + query. + const query = substituteCustomerId(url.search, CUSTOMER_ID); + const target = BASE + pathname + query; + + // Body: read raw, substitute {customerId}, forward as-is (byte stable for stamps). + const rawBody = method === 'GET' ? undefined : await req.text(); + const body = rawBody ? substituteCustomerId(rawBody, CUSTOMER_ID) : undefined; + + const outHeaders: Record = { Authorization: basicAuth() }; + if (body) outHeaders['Content-Type'] = 'application/json'; + for (const name of PASS_THROUGH) { + const v = req.headers.get(name); + if (v) outHeaders[name] = v; + } + + let gridStatus = 502; + let gridBody: unknown = { error: { code: 'PROXY_UPSTREAM_ERROR', message: 'No response from Grid' } }; + const echoed: Record = {}; + try { + const res = await fetch(target, { method, headers: outHeaders, body }); + gridStatus = res.status; + const text = await res.text(); + try { + gridBody = text ? JSON.parse(text) : {}; + } catch { + gridBody = { raw: text }; + } + for (const name of ECHO_RESPONSE) { + const v = res.headers.get(name); + if (v) echoed[name] = v; + } + } catch (e) { + gridBody = { error: { code: 'PROXY_UPSTREAM_ERROR', message: String(e) } }; + } + + const envelope = { + request: { + method, + path: pathname + query, + headers: redactHeaders(outHeaders), + body: body ? safeJson(body) : undefined, + }, + response: { status: gridStatus, body: gridBody, headers: echoed }, + }; + // Mirror Grid's status as the proxy status so fetch semantics stay truthful. + return NextResponse.json(envelope, { status: gridStatus >= 200 && gridStatus < 600 ? gridStatus : 502 }); +} + +function safeJson(s: string): unknown { + try { + return JSON.parse(s); + } catch { + return s; + } +} + +export async function GET(req: NextRequest) { + return handle(req, 'GET'); +} +export async function POST(req: NextRequest) { + return handle(req, 'POST'); +} diff --git a/components/grid-wallet-prod/src/app/api/grid/allowlist.test.ts b/components/grid-wallet-prod/src/app/api/grid/allowlist.test.ts new file mode 100644 index 000000000..29a47d1e4 --- /dev/null +++ b/components/grid-wallet-prod/src/app/api/grid/allowlist.test.ts @@ -0,0 +1,36 @@ +import { describe, it, expect } from 'vitest'; +import { isAllowed, redactHeaders, substituteCustomerId } from './allowlist'; + +describe('proxy allow-list', () => { + it('allows the M1/M2 endpoints', () => { + expect(isAllowed('GET', '/auth/credentials')).toBe(true); + expect(isAllowed('POST', '/auth/credentials')).toBe(true); + expect(isAllowed('POST', '/auth/credentials/AuthMethod:abc/challenge')).toBe(true); + expect(isAllowed('POST', '/auth/credentials/AuthMethod:abc/verify')).toBe(true); + expect(isAllowed('GET', '/customers/internal-accounts')).toBe(true); + expect(isAllowed('GET', '/platform/internal-accounts')).toBe(true); + expect(isAllowed('POST', '/customers/external-accounts')).toBe(true); + expect(isAllowed('GET', '/transactions')).toBe(true); + expect(isAllowed('GET', '/transactions/Transaction:abc')).toBe(true); + expect(isAllowed('POST', '/quotes')).toBe(true); + expect(isAllowed('POST', '/quotes/Quote:abc/execute')).toBe(true); + expect(isAllowed('POST', '/sandbox/internal-accounts/InternalAccount:abc/fund')).toBe(true); + }); + it('rejects everything else (incl. cards + wrong method)', () => { + expect(isAllowed('POST', '/cards')).toBe(false); + expect(isAllowed('DELETE', '/auth/credentials')).toBe(false); + expect(isAllowed('POST', '/transactions/Transaction:abc')).toBe(false); // GET only + expect(isAllowed('GET', '/quotes')).toBe(false); // POST only + expect(isAllowed('POST', '/customers')).toBe(false); + }); + it('redacts Authorization only', () => { + const r = redactHeaders({ Authorization: 'Basic secret', 'Request-Id': 'Request:1' }); + expect(r.Authorization).toBe('Basic ***'); + expect(r['Request-Id']).toBe('Request:1'); + }); + it('substitutes every {customerId} token', () => { + expect(substituteCustomerId('?customerId={customerId}', 'Customer:1')).toBe('?customerId=Customer:1'); + expect(substituteCustomerId('{customerId}/{customerId}', 'C')).toBe('C/C'); + expect(substituteCustomerId('nothing', 'C')).toBe('nothing'); + }); +}); diff --git a/components/grid-wallet-prod/src/app/api/grid/allowlist.ts b/components/grid-wallet-prod/src/app/api/grid/allowlist.ts new file mode 100644 index 000000000..5df3625d5 --- /dev/null +++ b/components/grid-wallet-prod/src/app/api/grid/allowlist.ts @@ -0,0 +1,41 @@ +/** Pure helpers for the Grid proxy — no Next runtime, unit-tested directly. */ + +const ID = '[^/?]+'; // a path segment (e.g. AuthMethod:..., Quote:..., InternalAccount:...) + +export const GRID_ALLOWLIST: { method: string; pattern: RegExp }[] = [ + { method: 'GET', pattern: new RegExp('^/auth/credentials$') }, + { method: 'POST', pattern: new RegExp('^/auth/credentials$') }, + { method: 'POST', pattern: new RegExp(`^/auth/credentials/${ID}/challenge$`) }, + { method: 'POST', pattern: new RegExp(`^/auth/credentials/${ID}/verify$`) }, + { method: 'GET', pattern: new RegExp('^/customers/internal-accounts$') }, + { method: 'GET', pattern: new RegExp('^/platform/internal-accounts$') }, + { method: 'GET', pattern: new RegExp('^/customers/external-accounts$') }, + { method: 'POST', pattern: new RegExp('^/customers/external-accounts$') }, + { method: 'GET', pattern: new RegExp('^/transactions$') }, + { method: 'GET', pattern: new RegExp(`^/transactions/${ID}$`) }, + { method: 'POST', pattern: new RegExp('^/quotes$') }, + { method: 'POST', pattern: new RegExp(`^/quotes/${ID}/execute$`) }, + { method: 'POST', pattern: new RegExp(`^/sandbox/internal-accounts/${ID}/fund$`) }, + { method: 'POST', pattern: new RegExp('^/sandbox/send$') }, +]; + +/** `pathname` is the Grid path WITHOUT query string (e.g. "/quotes"). */ +export function isAllowed(method: string, pathname: string): boolean { + return GRID_ALLOWLIST.some( + (r) => r.method === method.toUpperCase() && r.pattern.test(pathname), + ); +} + +/** Redact the injected Basic auth so it can be echoed to the panel safely. */ +export function redactHeaders(h: Record): Record { + const out: Record = {}; + for (const [k, v] of Object.entries(h)) { + out[k] = k.toLowerCase() === 'authorization' ? 'Basic ***' : v; + } + return out; +} + +/** Replace every {customerId} placeholder token with the real id. */ +export function substituteCustomerId(text: string, customerId: string): string { + return text.split('{customerId}').join(customerId); +} diff --git a/components/grid-wallet-prod/src/app/api/webhooks/route.ts b/components/grid-wallet-prod/src/app/api/webhooks/route.ts new file mode 100644 index 000000000..f912a1a07 --- /dev/null +++ b/components/grid-wallet-prod/src/app/api/webhooks/route.ts @@ -0,0 +1,21 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { verifyGridSignature } from '@/lib/gridWebhook'; +import { pushEvent } from '@/lib/webhookEvents'; + +export const runtime = 'nodejs'; +export const dynamic = 'force-dynamic'; + +export async function POST(req: NextRequest) { + const raw = await req.text(); // RAW body, exactly as received (used for signature) + const sig = req.headers.get('x-grid-signature') ?? ''; + const pubkey = process.env.GRID_WEBHOOK_PUBKEY ?? ''; + if (!verifyGridSignature(raw, sig, pubkey)) { + return NextResponse.json({ error: { code: 'INVALID_SIGNATURE' } }, { status: 401 }); + } + try { + pushEvent(JSON.parse(raw)); + } catch { + // Signature already passed; a non-JSON body is unexpected but non-fatal. + } + return NextResponse.json({ ok: true }, { status: 200 }); +} diff --git a/components/grid-wallet-prod/src/app/api/webhooks/stream/route.ts b/components/grid-wallet-prod/src/app/api/webhooks/stream/route.ts new file mode 100644 index 000000000..3b3ad4e15 --- /dev/null +++ b/components/grid-wallet-prod/src/app/api/webhooks/stream/route.ts @@ -0,0 +1,65 @@ +import { subscribe, type WebhookEvent } from '@/lib/webhookEvents'; + +export const runtime = 'nodejs'; +export const dynamic = 'force-dynamic'; + +/** Comment frames keep proxies (and ngrok) from closing an idle stream. */ +const KEEPALIVE_MS = 15_000; + +/** + * Server-sent events: every webhook that passes signature verification is pushed + * to connected panels as it lands. One-way and text-only, so it survives the + * ngrok tunnel a real Grid webhook arrives through — no polling, no client + * timers, and the panel shows the event at the moment Grid delivers it. + */ +export async function GET(req: Request) { + const encoder = new TextEncoder(); + let unsubscribe: (() => void) | undefined; + let keepalive: ReturnType | undefined; + + const stream = new ReadableStream({ + start(controller) { + const send = (event: WebhookEvent) => { + try { + controller.enqueue(encoder.encode(`data: ${JSON.stringify(event)}\n\n`)); + } catch { + // Client vanished between the push and the enqueue — drop it. + } + }; + // An opening comment flushes headers so EventSource fires `open`. + controller.enqueue(encoder.encode(': connected\n\n')); + unsubscribe = subscribe(send); + keepalive = setInterval(() => { + try { + controller.enqueue(encoder.encode(': keepalive\n\n')); + } catch { + /* closing */ + } + }, KEEPALIVE_MS); + // Tab closed / navigated away. + req.signal.addEventListener('abort', () => { + unsubscribe?.(); + if (keepalive) clearInterval(keepalive); + try { + controller.close(); + } catch { + /* already closed */ + } + }); + }, + cancel() { + unsubscribe?.(); + if (keepalive) clearInterval(keepalive); + }, + }); + + return new Response(stream, { + headers: { + 'Content-Type': 'text/event-stream; charset=utf-8', + 'Cache-Control': 'no-cache, no-transform', + Connection: 'keep-alive', + // Nginx-style proxies buffer by default, which would stall the stream. + 'X-Accel-Buffering': 'no', + }, + }); +} diff --git a/components/grid-wallet-prod/src/app/fonts/circular.scss b/components/grid-wallet-prod/src/app/fonts/circular.scss new file mode 100644 index 000000000..5599d2743 --- /dev/null +++ b/components/grid-wallet-prod/src/app/fonts/circular.scss @@ -0,0 +1,70 @@ +/* Circular (Lineto) — the marketplace skin's brand type (stand-in for Airbnb + Cereal). Book 400 / Medium 500 / Bold 700 / Black 900, with italics. */ + +@font-face { + font-family: 'Circular'; + src: url('/fonts/circular/lineto-circular-book.ttf') format('truetype'); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Circular'; + src: url('/fonts/circular/lineto-circular-bookItalic.ttf') format('truetype'); + font-weight: 400; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: 'Circular'; + src: url('/fonts/circular/lineto-circular-medium.ttf') format('truetype'); + font-weight: 500; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Circular'; + src: url('/fonts/circular/lineto-circular-mediumItalic.ttf') format('truetype'); + font-weight: 500; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: 'Circular'; + src: url('/fonts/circular/lineto-circular-bold.ttf') format('truetype'); + font-weight: 700; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Circular'; + src: url('/fonts/circular/lineto-circular-boldItalic.ttf') format('truetype'); + font-weight: 700; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: 'Circular'; + src: url('/fonts/circular/lineto-circular-black.ttf') format('truetype'); + font-weight: 900; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Circular'; + src: url('/fonts/circular/lineto-circular-blackItalic.ttf') format('truetype'); + font-weight: 900; + font-style: italic; + font-display: swap; +} + +:root { + --font-family-circular: 'Circular', system-ui, -apple-system, BlinkMacSystemFont, sans-serif; +} diff --git a/components/grid-wallet-prod/src/app/fonts/geist.scss b/components/grid-wallet-prod/src/app/fonts/geist.scss new file mode 100644 index 000000000..882617e24 --- /dev/null +++ b/components/grid-wallet-prod/src/app/fonts/geist.scss @@ -0,0 +1,7 @@ +/* Geist — the Z (social) skin's typeface. Loaded via next/font (the `geist` + package); `GeistSans.variable` on (see app/layout.tsx) defines + `--font-geist-sans`. This exposes a named token with a system fallback so the + skin can reference it the same way it does SF Pro / Inter. */ +:root { + --font-family-geist: var(--font-geist-sans), system-ui, -apple-system, BlinkMacSystemFont, sans-serif; +} diff --git a/components/grid-wallet-prod/src/app/fonts/inter.scss b/components/grid-wallet-prod/src/app/fonts/inter.scss new file mode 100644 index 000000000..17a98f52a --- /dev/null +++ b/components/grid-wallet-prod/src/app/fonts/inter.scss @@ -0,0 +1,19 @@ +/* Inter variable font — Creator skin tab labels and wallet chrome. + + Self-hosted from the upstream source (https://github.com/rsms/inter, + font-files at https://rsms.me/inter/font-files/InterVariable.woff2) rather than + Google Fonts. The single variable file carries both the weight (100..900) and + optical-size (opsz) axes, so `font-variation-settings` (opsz/wght) keeps working. */ + +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 100 900; + font-display: swap; + src: url('/fonts/InterVariable.woff2') format('woff2'); + font-named-instance: 'Regular'; +} + +:root { + --font-family-inter: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif; +} diff --git a/components/grid-wallet-prod/src/app/fonts/sf-pro-rounded.scss b/components/grid-wallet-prod/src/app/fonts/sf-pro-rounded.scss new file mode 100644 index 000000000..672f3decf --- /dev/null +++ b/components/grid-wallet-prod/src/app/fonts/sf-pro-rounded.scss @@ -0,0 +1,13 @@ +/* SF Pro Rounded variable font — iOS phone mock screens. + Source: macOS .SF NS Rounded (SFNSRounded.ttf). Axes: wght 1–1000, GRAD 400–1000. */ + +@font-face { + font-family: 'SF Pro Rounded'; + src: url('/fonts/SF-Pro-Rounded.woff2') format('woff2'); + font-weight: 1 1000; + font-display: swap; +} + +:root { + --font-family-sf-pro-rounded: 'SF Pro Rounded', system-ui, -apple-system, BlinkMacSystemFont, sans-serif; +} diff --git a/components/grid-wallet-prod/src/app/fonts/sf-pro.scss b/components/grid-wallet-prod/src/app/fonts/sf-pro.scss new file mode 100644 index 000000000..db534065e --- /dev/null +++ b/components/grid-wallet-prod/src/app/fonts/sf-pro.scss @@ -0,0 +1,14 @@ +/* SF Pro variable font — iOS phone mock screens. + Axes: wght 1–1000, wdth 30–150, opsz 17–28 (auto via font-optical-sizing). */ + +@font-face { + font-family: 'SF Pro'; + src: url('/fonts/SF-Pro.woff2') format('woff2'); + font-weight: 1 1000; + font-stretch: 30% 150%; + font-display: swap; +} + +:root { + --font-family-sf-pro: 'SF Pro', system-ui, -apple-system, BlinkMacSystemFont, sans-serif; +} diff --git a/components/grid-wallet-prod/src/app/fonts/suisse-intl.scss b/components/grid-wallet-prod/src/app/fonts/suisse-intl.scss new file mode 100644 index 000000000..16ec4e3ee --- /dev/null +++ b/components/grid-wallet-prod/src/app/fonts/suisse-intl.scss @@ -0,0 +1,44 @@ +/* Suisse Intl metric overrides. + + @lightsparkdev/origin (src/tokens/_fonts.scss) declares these faces with + ascent-override: 81% / descent-override: 19%. We re-declare the same faces + (identical family + weight + style + src) so the later rule wins the cascade, + bumping them to the Mintlify docs' 85% / 15% so glyphs sit at the same height + in the line box across the docs and the demo. + + Must be @use'd AFTER the origin fonts import in globals.scss. Same src URLs as + origin, so the browser reuses the already-loaded woff2 (no extra download). + Mono is intentionally left untouched, matching origin and the docs. */ + +@font-face { + font-family: 'Suisse Intl'; + src: url('/fonts/SuisseIntl-Regular.woff2') format('woff2'); + font-weight: 400; + font-style: normal; + font-display: swap; + ascent-override: 85%; + descent-override: 15%; + line-gap-override: 0%; +} + +@font-face { + font-family: 'Suisse Intl'; + src: url('/fonts/SuisseIntl-Book.woff2') format('woff2'); + font-weight: 450; + font-style: normal; + font-display: swap; + ascent-override: 85%; + descent-override: 15%; + line-gap-override: 0%; +} + +@font-face { + font-family: 'Suisse Intl'; + src: url('/fonts/SuisseIntl-Medium.woff2') format('woff2'); + font-weight: 500; + font-style: normal; + font-display: swap; + ascent-override: 85%; + descent-override: 15%; + line-gap-override: 0%; +} diff --git a/components/grid-wallet-prod/src/app/globals.scss b/components/grid-wallet-prod/src/app/globals.scss new file mode 100644 index 000000000..c24d8d4ba --- /dev/null +++ b/components/grid-wallet-prod/src/app/globals.scss @@ -0,0 +1,205 @@ +/* Grid Wallet Demo — adopts the Lightspark Origin design system, + matching grid-visualizer / flow-builder exactly. */ + +@use '@lightsparkdev/origin/src/tokens/variables'; +@use '@lightsparkdev/origin/src/tokens/fonts'; +@use './fonts/suisse-intl'; // overrides origin's Suisse Intl ascent/descent (81/19 → 85/15); must follow origin fonts +@use '@lightsparkdev/origin/src/tokens/typography'; +@use '@lightsparkdev/origin/src/tokens/effects'; +@use '@lightsparkdev/origin/src/tokens/reset'; +@use './fonts/sf-pro'; +@use './fonts/sf-pro-rounded'; +@use './fonts/inter'; +@use './fonts/geist'; +@use './fonts/circular'; +@use '../apps/shared/typography/ios-type'; + +/* Origin sets --font-family-sans/-mono to just "Suisse Intl" with NO fallback, + and its @font-face uses font-display: swap. So any frame the webfont isn't + painted (e.g. the repaint when the docs theme toggles) falls back to the + browser default — which is *serif*. Add a system sans/mono fallback so that + moment renders a near-identical system sans, never serif. */ +:root { + --font-family-sans: 'Suisse Intl', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; + --font-family-mono: "Suisse Int'l Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; +} + +/* App-wide corner curve, single source of truth. superellipse(1.24) = exp ~2.48, + the iOS-matched shape dialed in on the phone (smoothing 0.12 → superellipse(1 + + 0.12*2)). Rounder/smoother than `squircle` (= superellipse(2), exp 4). Change it + here and every corner (components reference var(--corner-shape)) follows. */ +* { + corner-shape: var(--corner-shape); +} + +:root { + --corner-shape: superellipse(1.24); + /* Figma radius × this scale ≈ matching superellipse roundness (Chromium + corner-shape + clip-path squircle on every browser). */ + --corner-superellipse-scale: 1.2; + --app-shell-padding: 16px; + --app-screen-width: 402px; + --app-screen-height: 874px; + --app-shell-width: 434px; + --app-shell-height: 906px; + /* Figma phone-gga (2121:17475) — figma values; scaled in @supports below. */ + --figma-corner-radius-phone-shell: 76px; + --figma-corner-radius-phone-screen: 60px; + --corner-radius-phone-shell: var(--figma-corner-radius-phone-shell); + --corner-radius-phone-screen: var(--figma-corner-radius-phone-screen); + /* Wallet home (Figma Bitcoin 2026). */ + --figma-corner-radius-wallet-sheet: 40px; + --figma-corner-radius-wallet-card: 32px; + --figma-corner-radius-debit-card: 13px; + --corner-radius-wallet-sheet: var(--figma-corner-radius-wallet-sheet); + --corner-radius-wallet-card: var(--figma-corner-radius-wallet-card); + /* clip-path squircle — always scaled (all browsers). */ + --corner-radius-wallet-card-squircle: calc( + var(--figma-corner-radius-wallet-card) * var(--corner-superellipse-scale) + ); + --corner-radius-debit-card-squircle: calc( + var(--figma-corner-radius-debit-card) * var(--corner-superellipse-scale) + ); +} + +/* When corner-shape is supported, bump border-radius tokens to match superellipse. */ +@supports (corner-shape: squircle) { + :root { + --corner-radius-2xs: calc(2px * var(--corner-superellipse-scale)); + --corner-radius-xs: calc(4px * var(--corner-superellipse-scale)); + --corner-radius-sm: calc(6px * var(--corner-superellipse-scale)); + --corner-radius-md: calc(8px * var(--corner-superellipse-scale)); + --corner-radius-lg: calc(12px * var(--corner-superellipse-scale)); + --corner-radius-xl: calc(16px * var(--corner-superellipse-scale)); + --corner-radius-2xl: calc(24px * var(--corner-superellipse-scale)); + --corner-radius-3xl: calc(32px * var(--corner-superellipse-scale)); + --corner-radius-4xl: calc(40px * var(--corner-superellipse-scale)); + --corner-radius-phone-shell: calc( + var(--figma-corner-radius-phone-shell) * var(--corner-superellipse-scale) + ); + --corner-radius-phone-screen: calc( + var(--figma-corner-radius-phone-screen) * var(--corner-superellipse-scale) + ); + --corner-radius-wallet-sheet: calc( + var(--figma-corner-radius-wallet-sheet) * var(--corner-superellipse-scale) + ); + --corner-radius-wallet-card: calc( + var(--figma-corner-radius-wallet-card) * var(--corner-superellipse-scale) + ); + } +} + +body { + background: var(--surface-primary); + color: var(--text-primary); + font-family: var(--font-family-sans); + font-weight: var(--font-weight-book); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* Origin ships border-primary/secondary only; flow-builder SCSS uses + border-tertiary throughout — alias it so dividers and step connectors render. */ +:root { + --border-tertiary: var(--border-primary); +} + +/* Hover fills — match grid-visualizer / flow-builder. */ +:root { + --surface-hover: var(--color-alpha-black-04); + --phone-shell-shadow-opacity: 0.12; + /* Frosted overlay glass (sheets): milky tint + the white specular edge. Light: + a hair darker so the edge reads; the edge pops against it. */ + --glass-sheet-tint: rgba(234, 234, 240, 0.64); + --glass-sheet-edge: rgba(255, 255, 255, 0.5); + /* Backdrop a glass button refracts when it sits ON the frosted sheet — a neutral + that matches the milky surface (not the blue auth hero), themed so the small + lens never tints cold against a dark sheet. */ + --glass-symbol-backdrop: linear-gradient(180deg, #f5f5f7 0%, #e6e6eb 100%); + /* Flat (non-frosted) sheets: hairline outline only where the sheet would + otherwise melt into the scrim — invisible on light. */ + --sheet-flat-edge: transparent; + /* Floating chooser/entry sheets (send-receive picker, auth email): frosted, + pure white/black at matched alpha — reads as the app surface with the + frost showing through. */ + --float-sheet-tint: rgba(255, 255, 255, 0.85); +} + +[data-theme='dark'] { + --surface-hover: var(--color-alpha-white-06); + --phone-shell-shadow-opacity: 0.28; + --glass-sheet-tint: rgba(44, 44, 46, 0.62); + /* Subtler in dark — white-on-dark already pops. */ + --glass-sheet-edge: rgba(255, 255, 255, 0.3); + --glass-symbol-backdrop: linear-gradient(180deg, #242426 0%, #1a1a1c 100%); + --sheet-flat-edge: rgba(255, 255, 255, 0.1); + --float-sheet-tint: rgba(0, 0, 0, 0.85); +} + +/* iPhone mock palette — the wallet is a self-contained iOS app preview, so it + keeps its own iOS tokens (adapted from the keynote phone screens) rather than + Origin. These flip with Origin's [data-theme]. */ +/* iPhone palette — adapted 1:1 from the "bread" neobank app (sparkapp). */ +/* Dot-grid backdrop — single source of truth shared by the CSS fallback + backgrounds (DotGridCanvas / AppShell) AND the JS canvas / WebGL renderers + (DotGrid, StageGL). Keeping the colors in CSS — exactly like grid-visualizer, + whose dot grid is pure CSS — lets the canvas re-read them the instant + [data-theme] flips, so the whole backdrop changes in lockstep (no stagger). + `--dot-grid-dot` is the resting dot; `--dot-grid-dot-peak` is the ripple crest. */ +:root { + /* Light: surface-primary (#F8F8F7) — the stage sits a step ABOVE the + chrome-gray side panels (surface-secondary), matching the raised cards. + Dark overrides below mirror it: gray-950 stage over #111111 chrome. */ + --dot-grid-bg: var(--surface-primary); + --dot-grid-dot: #deded9; + --dot-grid-dot-peak: #b8b8b3; +} + +/* 3-col layout: the light stage steps down a hair so it separates from the + raised cards flanking it. Keyed to html's data-layout attribute (set + pre-paint by layout.tsx, kept live by page.tsx) so the color rides the + same clock as the arrangement flip. Light-only — the dark stage is + gray-950 in both arrangements. The JS canvas re-reads the token on resize + (StageGL's ResizeObserver), which every arrangement flip triggers. */ +html:not([data-theme='dark']):not([data-layout='stacked']) { + --dot-grid-bg: #f4f4f3; +} + +:root { + --p-accent: #11a967; + --p-accent-press: #0e8f57; + /* light variant */ + --p-bg: #f4f4f5; + --p-screen: #ffffff; + --p-surface: #f4f4f5; + --p-surface-2: #ececee; + --p-text: #0a0a0a; + --p-text-2: #707070; + --p-text-3: #b4b4b8; + --p-separator: rgba(0, 0, 0, 0.08); + --p-blue: #3b82f6; + --p-green: #22c55e; + --p-fill: #0a0a0a; /* primary button bg */ + --p-fg: #ffffff; /* text on primary button */ + --p-shadow: 0 24px 60px rgba(0, 0, 0, 0.16); + --p-card: linear-gradient(150deg, #1f6feb 0%, #1bb6c9 100%); +} + +[data-theme='dark'] { + /* gray-950 (#1A1A1A) — a step darker than the chrome-gray side panels' + raised cards, mirroring the light stage sitting under the panel surface. */ + --dot-grid-bg: var(--color-gray-950); + --dot-grid-dot: #2d2d2a; + --dot-grid-dot-peak: #474741; + --p-bg: #000000; + --p-screen: #000000; + --p-surface: #141414; + --p-surface-2: #1f1f1f; + --p-text: #ffffff; + --p-text-2: #8a8a8e; + --p-text-3: #5a5a5e; + --p-separator: rgba(255, 255, 255, 0.08); + --p-fill: #ffffff; + --p-fg: #0a0a0a; + --p-shadow: 0 24px 60px rgba(0, 0, 0, 0.6); +} diff --git a/components/grid-wallet-prod/src/app/layout.tsx b/components/grid-wallet-prod/src/app/layout.tsx new file mode 100644 index 000000000..cb89ed7ae --- /dev/null +++ b/components/grid-wallet-prod/src/app/layout.tsx @@ -0,0 +1,81 @@ +import type { Metadata } from 'next'; +import { GeistSans } from 'geist/font/sans'; +import { easingVarsStylesheet } from '@/lib/easing'; +import { CONFIGURE_COL_PX, LAYOUT_WIDE_PX } from '@/lib/layout'; +import './globals.scss'; + +const TITLE = 'Grid Global Accounts — Live demo'; +const DESCRIPTION = + 'Create a branded, self-custody dollar account and watch the Grid API calls fire in real time.'; + +export const metadata: Metadata = { + // Absolute base for social-card image URLs (scrapers need full URLs). + // VERCEL_PROJECT_PRODUCTION_URL covers previews; the default is prod. + metadataBase: new URL( + process.env.VERCEL_PROJECT_PRODUCTION_URL + ? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}` + : 'https://grid-wallet-demo.vercel.app', + ), + title: TITLE, + description: DESCRIPTION, + openGraph: { + title: TITLE, + description: DESCRIPTION, + images: [{ url: '/og-global-accounts-playground.webp', width: 2400, height: 1260 }], + }, + twitter: { + card: 'summary_large_image', + title: TITLE, + description: DESCRIPTION, + images: ['/og-global-accounts-playground.webp'], + }, +}; + +export default function RootLayout({ children }: { children: React.ReactNode }) { + return ( + + + + + {/* Preload the visible Suisse Intl weights so the first paint shows the + real font sooner (body=Book 450, headings/buttons=Medium 500, + code=Mono). crossOrigin is required even though the fonts are + same-origin: @font-face fetches use CORS mode, so without it the + preload wouldn't match and the font would download twice. */} + + + + {/* Boot attributes, set before first paint to avoid flashes — an + effect is too late (the SSR HTML paints long before hydration): + - data-embed / data-theme from the URL (embed) or stored pref + - data-layout (stacked ⇄ 2-col wide) from the viewport width + - --api-col-default from the embed's ?nav param (the live docs + sidebar width), so the wide layout's code column paints at its + real default — sidebar width plus the deferred (Phase 2) + configure-column offset — instead of the expanded-sidebar + assumption and re-fitting after hydration. */} +