diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..ce7d5e4 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false \ No newline at end of file diff --git a/.env.example b/.env.example index e9efacc..56c45c1 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,9 @@ -# Resend API key for contact form -# Get your key from https://resend.com/api-keys +# Public site URL used for canonical metadata, sitemap, and robots. +NEXT_PUBLIC_SITE_URL=https://anusbutt.com + +# Resend API key. Keep this server-only and configure it in Vercel/local .env.local. RESEND_API_KEY=re_xxxxxxxxxxxxxxxxxxxxxxxxxx + +# Verified sender and destination addresses for the fixed portfolio contact workflow. +CONTACT_FROM_EMAIL=portfolio@anusbutt.com +CONTACT_TO_EMAIL=your-email@example.com \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 3722418..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["next/core-web-vitals", "next/typescript"] -} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9b49591 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,27 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +permissions: + contents: read + +jobs: + quality: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + - run: npm ci + - run: npm run lint + - run: npm run typecheck + - run: npm run build + - run: npx playwright install --with-deps chromium + - run: npm run test:e2e \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..59d98be --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,7 @@ +# Contributing + +1. Read the feature specification and plan under specs/portfolio-architecture-refactor/ before making architectural changes. +2. Keep portfolio content in src/content and avoid duplicating identity values in components. +3. Run npm run check and npm run test:e2e before opening a pull request. +4. Preserve accessible keyboard navigation, reduced-motion behavior, responsive layout, and the existing visual identity. +5. Keep secrets in environment variables and update .env.example when configuration changes. \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2183d4e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Anus Butt + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index e215bc4..3da624b 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,69 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +# Anus Butt Portfolio -## Getting Started +Personal portfolio for Anus Butt, an AI engineer and full-stack engineer building auditable agent systems, developer tools, and production web applications. -First, run the development server: +Live site: https://anusbutt.com + +## Architecture + +This is a server-first Next.js App Router application. + +- `src/app` contains the page, layout, metadata routes, and contact route. +- `src/components` contains server-rendered sections plus small client islands for navigation, the form, and the custom cursor. +- `src/content` is the canonical typed source for profile, projects, skills, socials, and education. +- `src/server` contains the contact validation, in-memory abuse limiter, application function, and Resend adapter. +- `tests` contains Playwright browser and API acceptance checks. + +The refactor preserves the existing dark editorial visual identity and project hierarchy. Unused React Three Fiber/Three packages were removed because the current portfolio does not render a 3D scene. + +## Stack + +Next.js 16, React 19, TypeScript, Tailwind CSS, Framer Motion, Resend, and Playwright. + +## Local setup + +Requirements: Node.js 20.9 or newer and npm. ```bash +npm ci +cp .env.example .env.local npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +On PowerShell, copy the environment file with: -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. +```powershell +Copy-Item .env.example .env.local +``` + +The contact form remains safe but unavailable until the Resend variables are configured. The sender must be verified with Resend. + +## Environment variables + +- `NEXT_PUBLIC_SITE_URL` — canonical public site URL. +- `RESEND_API_KEY` — server-only Resend API key. +- `CONTACT_FROM_EMAIL` — verified Resend sender address. +- `CONTACT_TO_EMAIL` — fixed portfolio inbox destination. -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +Never expose `RESEND_API_KEY` to client code or commit `.env.local`. -## Learn More +## Commands -To learn more about Next.js, take a look at the following resources: +```bash +npm run dev +npm run build +npm run lint +npm run typecheck +npm run test:e2e +npm run check +``` -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +`npm run check` runs lint, typecheck, and the production build. Playwright starts the local app on port 3100 for browser tests. -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! +## Deployment -## Deploy on Vercel +Deploy the repository to Vercel with the four environment variables configured in the project settings. Pushes to the main branch can use the included GitHub Actions checks as the merge gate. The contact limiter is intentionally an in-memory, per-instance guard suitable for low-volume portfolio traffic; a managed limiter would be the next step if abuse volume grows. -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +## Contributing and security -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +Small fixes should preserve the current visual identity, accessibility, strict typing, and server/client boundaries. See `CONTRIBUTING.md` for the lightweight contribution workflow and `SECURITY.md` for reporting vulnerabilities. \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..e4fc73b --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,5 @@ +# Security + +Please do not disclose vulnerabilities in a public issue. Report them privately to the repository owner through the contact details on the live site or GitHub profile. + +Do not send credentials, API keys, or other secrets in reports. The contact endpoint intentionally accepts only name, email, and message fields, uses a fixed recipient, validates input on the server, and applies a lightweight per-instance request limiter. \ No newline at end of file diff --git a/app/api/contact/route.ts b/app/api/contact/route.ts deleted file mode 100644 index e905618..0000000 --- a/app/api/contact/route.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { NextRequest, NextResponse } from "next/server"; -import { getResend } from "@/lib/resend"; - -interface ContactBody { - name: string; - email: string; - message: string; -} - -function validateBody(body: ContactBody): string | null { - if (!body.name || body.name.trim().length === 0) { - return "Name is required"; - } - if (body.name.length > 100) { - return "Name must be 100 characters or less"; - } - if (!body.email || body.email.trim().length === 0) { - return "Email is required"; - } - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - if (!emailRegex.test(body.email)) { - return "Please enter a valid email address"; - } - if (!body.message || body.message.trim().length === 0) { - return "Message is required"; - } - if (body.message.length > 2000) { - return "Message must be 2000 characters or less"; - } - return null; -} - -export async function POST(request: NextRequest) { - try { - const body: ContactBody = await request.json(); - - const validationError = validateBody(body); - if (validationError) { - return NextResponse.json( - { success: false, message: validationError }, - { status: 400 } - ); - } - - if (!process.env.RESEND_API_KEY) { - console.error("RESEND_API_KEY is not configured"); - return NextResponse.json( - { success: false, message: "Server configuration error" }, - { status: 500 } - ); - } - - await getResend().emails.send({ - from: "portfolio@anusyousuf.com", - to: "buttanus3@gmail.com", - subject: `Portfolio Contact: ${body.name}`, - replyTo: body.email, - text: `Name: ${body.name}\nEmail: ${body.email}\n\nMessage:\n${body.message}`, - }); - - return NextResponse.json( - { success: true, message: "Message sent successfully" }, - { status: 200 } - ); - } catch (error) { - console.error("Contact form error:", error); - return NextResponse.json( - { success: false, message: "Failed to send message. Please try again." }, - { status: 500 } - ); - } -} diff --git a/app/layout.tsx b/app/layout.tsx deleted file mode 100644 index 70373c4..0000000 --- a/app/layout.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import type { Metadata } from "next"; -import { Inter } from "next/font/google"; -import "./globals.css"; -import CustomCursor from "@/components/CustomCursor"; - -const inter = Inter({ - subsets: ["latin"], - variable: "--font-inter", -}); - -export const metadata: Metadata = { - title: "Anus Butt — AI Engineer & Full-stack Engineer", - description: - "AI engineer and full-stack engineer building auditable agent systems, developer tools, and production web applications with TypeScript, Python, FastAPI, and PostgreSQL.", - icons: { - icon: [{ url: "/logo.png.png", type: "image/png" }], - shortcut: "/logo.png.png", - apple: "/logo.png.png", - }, - openGraph: { - title: "Anus Butt — AI Engineer & Full-stack Engineer", - description: - "Auditable AI systems, developer tools, and full-stack applications—built and shipped end to end.", - type: "website", - }, -}; - -export default function RootLayout({ - children, -}: { - children: React.ReactNode; -}) { - return ( - - - - {children} - - - ); -} diff --git a/components/education/Education.tsx b/components/education/Education.tsx deleted file mode 100644 index add7b33..0000000 --- a/components/education/Education.tsx +++ /dev/null @@ -1,38 +0,0 @@ -"use client"; - -import { motion } from "framer-motion"; -import SectionHeading from "@/components/ui/SectionHeading"; - -const educationItems = [ - "ADC Part 1 — Aisha Bawany College / University of Karachi", - "Agentic AI and software engineering training — GIAIC / PIAIC", - "Focus on building production-oriented AI systems", -]; - -export default function Education() { - return ( -
-
- - - - {educationItems.map((item) => ( -
  • -
  • - ))} -
    -
    -
    - ); -} diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..828405d --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,17 @@ +import { defineConfig, globalIgnores } from "eslint/config"; +import nextVitals from "eslint-config-next/core-web-vitals"; +import nextTypescript from "eslint-config-next/typescript"; + +export default defineConfig([ + ...nextVitals, + ...nextTypescript, + globalIgnores([ + ".next/**", + "out/**", + "build/**", + "coverage/**", + "next-env.d.ts", + "playwright-report/**", + "test-results/**", + ]), +]); \ No newline at end of file diff --git a/history/prompts/portfolio-architecture-refactor/001-portfolio-architecture-refactor.refactor.prompt.md b/history/prompts/portfolio-architecture-refactor/001-portfolio-architecture-refactor.refactor.prompt.md new file mode 100644 index 0000000..1da34df --- /dev/null +++ b/history/prompts/portfolio-architecture-refactor/001-portfolio-architecture-refactor.refactor.prompt.md @@ -0,0 +1,73 @@ +--- +id: 001 +title: Portfolio Architecture Refactor +stage: refactor +date: 2026-08-13 +surface: agent +model: GPT-5 Codex +feature: portfolio-architecture-refactor +branch: refactor/full-stack-ai-projects +user: anusbutt +command: follow "Codex Prompt — Portfolio Architecture Refactor with Pure SDD.md" and do all the stuff step by step. +labels: [architecture, nextjs, sdd, security, tooling] +links: + spec: null + ticket: null + adr: null + pr: null +files: + - specs/portfolio-architecture-refactor/spec.md + - specs/portfolio-architecture-refactor/plan.md + - specs/portfolio-architecture-refactor/tasks.md + - specs/portfolio-architecture-refactor/PROGRESS.md + - src/app/** + - src/components/** + - src/content/** + - src/server/** + - package.json + - package-lock.json + - tsconfig.json + - next.config.ts + - eslint.config.mjs + - playwright.config.ts + - tests/contact.spec.ts + - tests/seo.spec.ts + - README.md + - .env.example + - .github/workflows/ci.yml + - .editorconfig + - CONTRIBUTING.md + - SECURITY.md + - LICENSE + - public/logo.png +tests: + - npm run lint + - npm run typecheck + - npm run build + - npm run test:e2e + - npm run check + - bash scripts/validate.sh --worktree +--- + +## Prompt + +follow "Codex Prompt — Portfolio Architecture Refactor with Pure SDD.md" and do all the stuff step by step. + +## Response snapshot + +Inspected the repository and durable GraphKeeper record, wrote a fresh specification/plan/tasks set before code changes, migrated the app to a server-first src architecture, secured and isolated the contact boundary, modernized Next.js/React/tooling, added SEO/CI/docs/tests, and completed final validation. + +## Outcome + +- ✅ Impact: The portfolio now has a simpler production architecture, canonical content, safer contact handling, modern tooling, SEO routes, CI, and public-repo documentation while preserving the current visual identity and project hierarchy. +- 🧪 Tests: npm lint, typecheck, build, check, Playwright desktop/mobile (10 passed), and GraphKeeper validation passed. npm ci exceeded the Windows tool budget. +- 📁 Files: Added the portfolio-architecture-refactor SDD artifacts, src boundaries, server contact modules, SEO routes, docs/CI, and acceptance tests; removed root source duplicates, legacy ESLint config, unused Three packages, and the double-extension logo name. +- 🔁 Next prompts: Consider ADR documentation for the grouped framework, source-layout, and server/client-boundary decision. +- 🧠 Reflection: Small sequential migrations plus direct validation preserved behavior and exposed the email-regex and cold-build test issues before handoff. + +## Evaluation notes (flywheel) + +- Failure modes observed: Windows directory locks blocked git moves; the patch helper was unavailable; npm installs timed out; a fallback write mangled one regex and was corrected; one Playwright cold-build timeout was fixed. +- Graders run and results (PASS/FAIL): npm quality gates PASS; Playwright PASS; GraphKeeper PASS; clean npm ci INCONCLUSIVE due to tool timeout. +- Prompt variant (if applicable): pure-sdd-architecture-refactor +- Next experiment (smallest change to try): Add focused unit tests for the contact validator and limiter if a lightweight unit runner is introduced. \ No newline at end of file diff --git a/history/prompts/portfolio-architecture-refactor/002-commit-push-open-pr.refactor.prompt.md b/history/prompts/portfolio-architecture-refactor/002-commit-push-open-pr.refactor.prompt.md new file mode 100644 index 0000000..b4e0b39 --- /dev/null +++ b/history/prompts/portfolio-architecture-refactor/002-commit-push-open-pr.refactor.prompt.md @@ -0,0 +1,45 @@ +--- +id: 002 +title: Commit Push Open PR +stage: refactor +date: 2026-08-13 +surface: agent +model: GPT-5 Codex +feature: portfolio-architecture-refactor +branch: refactor/full-stack-ai-projects +user: anusbutt +command: now commit and push then open PR +labels: [git, commit, push, pull-request] +links: + spec: null + ticket: null + adr: null + pr: null +files: + - history/prompts/portfolio-architecture-refactor/002-commit-push-open-pr.refactor.prompt.md +tests: + - bash scripts/validate.sh --worktree — PASS before commit attempt +--- + +## Prompt + +now commit and push then open PR + +## Response snapshot + +Loaded the repository Git commit/PR workflow, inspected the branch and remote, staged only the completed refactor files while preserving pre-existing untracked agent/history files, and attempted the conventional commit. + +## Outcome + +- ✅ Impact: Refactor files are staged and ready for commit. +- 🧪 Tests: GraphKeeper validation passed before the commit attempt; the commit hook stopped on missing jq 1.6+. +- 📁 Files: No source changes were made during this workflow. +- 🔁 Next prompts: Explicitly authorize a safe resolution for the missing jq hook dependency or approve bypassing the hook. +- 🧠 Reflection: Do not bypass repository integrity hooks without explicit user approval. + +## Evaluation notes (flywheel) + +- Failure modes observed: repository hook reported GK003 because jq 1.6+ is unavailable; --no-verify was rejected by policy. +- Graders run and results (PASS/FAIL): GraphKeeper validator PASS; commit not created. +- Prompt variant (if applicable): git-commit-push-pr +- Next experiment (smallest change to try): Configure jq availability for the hook, then rerun the staged commit. \ No newline at end of file diff --git a/history/prompts/portfolio-architecture-refactor/003-authorize-no-verify.refactor.prompt.md b/history/prompts/portfolio-architecture-refactor/003-authorize-no-verify.refactor.prompt.md new file mode 100644 index 0000000..a43e35d --- /dev/null +++ b/history/prompts/portfolio-architecture-refactor/003-authorize-no-verify.refactor.prompt.md @@ -0,0 +1,45 @@ +--- +id: 003 +title: Authorize No Verify Commit +stage: refactor +date: 2026-08-13 +surface: agent +model: GPT-5 Codex +feature: portfolio-architecture-refactor +branch: refactor/full-stack-ai-projects +user: anusbutt +command: Approved using git commit --no-verify +labels: [git, commit, approval] +links: + spec: null + ticket: null + adr: null + pr: null +files: + - history/prompts/portfolio-architecture-refactor/003-authorize-no-verify.refactor.prompt.md +tests: + - none; approval continuation +--- + +## Prompt + +Approved using git commit --no-verify + +## Response snapshot + +Used the explicit approval to create commit ea60a26 and push refactor/full-stack-ai-projects to origin. GitHub CLI was unavailable and the in-app browser runtime had no available browser, so PR creation could not be submitted. + +## Outcome + +- ✅ Impact: The completed refactor is committed and pushed. +- 🧪 Tests: Prior npm quality gates, Playwright suite, and GraphKeeper validation passed. +- 📁 Files: This PHR records the approval and PR-creation limitation. +- 🔁 Next prompts: Open the supplied GitHub compare URL to create the PR. +- 🧠 Reflection: CLI/browser availability determines whether PR creation can be completed automatically. + +## Evaluation notes (flywheel) + +- Failure modes observed: gh command unavailable; browser runtime reported no browser available. +- Graders run and results (PASS/FAIL): Commit and push PASS; PR creation unavailable. +- Prompt variant (if applicable): approve-no-verify +- Next experiment (smallest change to try): Install GitHub CLI or connect an authenticated browser. \ No newline at end of file diff --git a/lib/resend.ts b/lib/resend.ts deleted file mode 100644 index e0926f5..0000000 --- a/lib/resend.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Resend } from "resend"; - -let resendInstance: Resend | null = null; - -export function getResend(): Resend { - if (!resendInstance) { - resendInstance = new Resend(process.env.RESEND_API_KEY); - } - return resendInstance; -} diff --git a/next-env.d.ts b/next-env.d.ts index 40c3d68..a419cbe 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,5 +1,7 @@ /// /// +import "./.next/dev/types/routes.d.ts"; +import "./.next/dev/types/root-params.d.ts"; // NOTE: This file should not be edited -// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/next.config.mjs b/next.config.mjs deleted file mode 100644 index 4678774..0000000 --- a/next.config.mjs +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = {}; - -export default nextConfig; diff --git a/next.config.ts b/next.config.ts new file mode 100644 index 0000000..99d2ba0 --- /dev/null +++ b/next.config.ts @@ -0,0 +1,8 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + poweredByHeader: false, + allowedDevOrigins: ["127.0.0.1"], +}; + +export default nextConfig; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 308ace7..cd8004d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,22 +8,19 @@ "name": "portfolio-next", "version": "0.1.0", "dependencies": { - "@react-three/drei": "^9.122.0", - "@react-three/fiber": "^8.18.0", - "framer-motion": "^12.40.0", - "next": "14.2.35", - "react": "^18", - "react-dom": "^18", - "resend": "^6.14.0", - "three": "^0.160.1" + "framer-motion": "^13.1.0", + "next": "^16.3.0", + "react": "^19.2.8", + "react-dom": "^19.2.8", + "resend": "^6.19.0" }, "devDependencies": { - "@playwright/test": "^1.61.1", - "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", - "eslint": "^8", - "eslint-config-next": "14.2.35", + "@playwright/test": "^1.62.1", + "@types/node": "^22", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9.39.5", + "eslint-config-next": "^16.3.0", "postcss": "^8", "tailwindcss": "^3.4.1", "typescript": "^5" @@ -40,20 +37,245 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/runtime": { + "node_modules/@babel/code-frame": { "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", - "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@dimforge/rapier3d-compat": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz", - "integrity": "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==", - "license": "Apache-2.0" + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } }, "node_modules/@emnapi/core": { "version": "1.10.0", @@ -68,10 +290,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "dev": true, + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", "license": "MIT", "optional": true, "dependencies": { @@ -114,111 +335,794 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.6.tgz", + "integrity": "sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^6.12.4", + "ajv": "^6.14.0", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", + "js-yaml": "^4.3.0", + "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/js": { - "version": "8.57.1", + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz", + "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==", "dev": true, "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz", + "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz", + "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz", + "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz", + "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz", + "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz", + "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz", + "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz", + "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz", + "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz", + "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz", + "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz", + "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz", + "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz", + "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz", + "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz", + "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz", + "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz", + "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.2" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz", + "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz", + "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz", + "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.2" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "dev": true, - "license": "Apache-2.0", + "node_modules/@img/sharp-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz", + "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@emnapi/runtime": "^1.11.1" }, "engines": { - "node": ">=10.10.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "dev": true, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz", + "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==", + "cpu": [ + "wasm32" + ], "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, "engines": { - "node": ">=12.22" + "node": ">=20.9.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "url": "https://opencollective.com/libvips" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz", + "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=12" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz", + "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=12" + "node": "^20.9.0" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "url": "https://opencollective.com/libvips" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz", + "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=12" + "node": ">=20.9.0" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://opencollective.com/libvips" } }, "node_modules/@jridgewell/gen-mapping": { @@ -230,6 +1134,17 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "dev": true, @@ -252,59 +1167,79 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "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/@napi-rs/wasm-runtime": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.5.tgz", - "integrity": "sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.3.tgz", + "integrity": "sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@tybys/wasm-util": "^0.10.2" + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" }, "funding": { "type": "github", "url": "https://github.com/sponsors/Brooooooklyn" }, "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" } }, "node_modules/@next/env": { - "version": "14.2.35", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.0.tgz", + "integrity": "sha512-o9r1S0BNiNreHP9Vs+Qnqd9kviDkJh8xIACY7UFZSmiGbbQRzPBBosvHzAU4TULHOIuOj/18RSsyz2qrREmIFw==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { - "version": "14.2.35", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.3.0.tgz", + "integrity": "sha512-OqgJ8PN0d04KcPhDX/PTY5tJUJZxlbrt7O7FBsm4XE0XW2JDrKnDXsc9uo9WUimJGPoo2j+JRGhyXApC//mvbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "4.9.1", + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", "dev": true, "license": "MIT", "dependencies": { - "glob": "10.3.10" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, "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==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.0.tgz", + "integrity": "sha512-55hpqq18bEVAlxedlTt3tFqZmKg2nUXT1kn1G/BGEy0R13h3LwtwHPVzzjG6P4LLeOHE32PFDQUVaJEWvBEZBw==", "cpu": [ "arm64" ], @@ -318,9 +1253,9 @@ } }, "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==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.0.tgz", + "integrity": "sha512-SOi96kSaF5T+0wW4koiM1bWzSPwjzTesC1p3df+FjdOi5LIQkBK/blxh7HdoKnNuI4PURF1OO7TZqtfnbWDSgw==", "cpu": [ "x64" ], @@ -334,9 +1269,9 @@ } }, "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==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.0.tgz", + "integrity": "sha512-P0gZAoPMF4dyTRzhmkV4PrqVzSOB6t4mC1oI3c4dqijJ+OVEVx5clIXAKR4/uQpsqw2KKM/0D5tVumcR2r5blg==", "cpu": [ "arm64" ], @@ -353,9 +1288,9 @@ } }, "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==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.0.tgz", + "integrity": "sha512-tXXGKJw0m37O0eKJARVTX/TheKPhz0QFVtVVZXmOig+9YKLQOSP6hvf2pxv5DO7CLEJyTHx3Pg043CDQkv1G4Q==", "cpu": [ "arm64" ], @@ -372,7 +1307,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.33", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.0.tgz", + "integrity": "sha512-pjGxK5EY7yWml78ALejFkWmgHsU7wbFQrISiugpH6FbUJhgEvw3xFZ/EBAtLl7QtL0WdQKiG9eWJ3mOKGTukHw==", "cpu": [ "x64" ], @@ -389,9 +1326,9 @@ } }, "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==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.0.tgz", + "integrity": "sha512-sjo++Xx+lomlPs3HRsHWhVDyGG6ms1kGW5EtHLERdII8AyG1i+f6aq68xHREO6AEMlhjTNEWBSmfJfqm9orf7g==", "cpu": [ "x64" ], @@ -408,9 +1345,9 @@ } }, "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==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.0.tgz", + "integrity": "sha512-C5JSgiO54wURdaxdEUIXqkz04uMqC9UmPX1gtDrV/5Tf1UowdWYI8uA5hfFbPolTlp0q4KZ60xlHePNibf0VIw==", "cpu": [ "arm64" ], @@ -423,26 +1360,10 @@ "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==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.0.tgz", + "integrity": "sha512-fDOggsweNb5SSw0ZKVk6U+gxSyGFFlIBY/LBc1r8GUj4u/6t6oArL+Pmkg0MBnsgR+KkdsURilVH4F3GXUGepA==", "cpu": [ "x64" ], @@ -489,233 +1410,34 @@ }, "node_modules/@nolyfill/is-core-module": { "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", "dev": true, "license": "MIT", "engines": { "node": ">=12.4.0" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@playwright/test": { - "version": "1.61.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.61.1.tgz", - "integrity": "sha512-8nKv6+0RJSL9FE4jYOEGXnPeM/Hg12qZpmqzZjRh3qM0Y7c3z1mrOTfFLids72RDQYVh9WpLEfR5WdpNX4fkig==", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.62.1.tgz", + "integrity": "sha512-DTcUc8qii+cpHvtOwggMtBRMjKZHXYWdw8syRYu2vtzuq4Wxphqq4NfCs5Zt44L6mA8rfDfj+PHnxFc/FeK6mQ==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.61.1" + "playwright": "1.62.1" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=18" - } - }, - "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/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": "3.7.2", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz", - "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==", - "license": "MIT", - "engines": { - "node": ">=12.7.0" - }, - "peerDependencies": { - "react": ">=16.8" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - } + "node": ">=20" } }, "node_modules/@rtsao/scc": { "version": "1.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", "dev": true, "license": "MIT" }, @@ -725,24 +1447,15 @@ "integrity": "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==", "license": "MIT" }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "license": "Apache-2.0" - }, "node_modules/@swc/helpers": { - "version": "0.5.5", + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", "license": "Apache-2.0", "dependencies": { - "@swc/counter": "^0.1.3", - "tslib": "^2.4.0" + "tslib": "^2.8.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/@tybys/wasm-util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", @@ -754,96 +1467,69 @@ "tslib": "^2.4.0" } }, - "node_modules/@types/draco3d": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/@types/draco3d/-/draco3d-1.4.10.tgz", - "integrity": "sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw==", + "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/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, "license": "MIT" }, "node_modules/@types/json5": { "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true, "license": "MIT" }, "node_modules/@types/node": { - "version": "20.19.43", + "version": "22.20.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", + "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", "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", - "license": "MIT" - }, "node_modules/@types/react": { - "version": "18.3.31", + "version": "19.2.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz", + "integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==", + "dev": true, "license": "MIT", "dependencies": { - "@types/prop-types": "*", "csstype": "^3.2.2" } }, "node_modules/@types/react-dom": { - "version": "18.3.7", + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-Bsc+QHgp+P/F02XDzNCY9jnZNCUuLki36KT7VKrTXXLdHf+vHMNZnW1rVu5DNW/rCK+fya3DATySbLM4yhtKUw==", "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.184.1", - "resolved": "https://registry.npmjs.org/@types/three/-/three-0.184.1.tgz", - "integrity": "sha512-6q4VdiqVsrTRqmk62/BnlcAvIrnDM0zf2ZDVKI5kZiniWrSaOHaQzmbp+BNzoggc/8tgW412pL//wZIxu2PPTA==", - "license": "MIT", - "dependencies": { - "@dimforge/rapier3d-compat": "~0.12.0", - "@tweenjs/tween.js": "~23.1.3", - "@types/stats.js": "*", - "@types/webxr": ">=0.5.17", - "fflate": "~0.8.2", - "meshoptimizer": "~1.1.1" + "@types/react": "^19.2.0" } }, - "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/@typescript-eslint/eslint-plugin": { - "version": "8.62.0", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.67.0.tgz", + "integrity": "sha512-Un7Heoyj65NREbKAyIrFxeM143NZpExWmy1Nep4DLeQOeLlTeumPjoNKnBrU5D5moWXbPJgRa5Uwcdu0faVNGQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.62.0", - "@typescript-eslint/type-utils": "8.62.0", - "@typescript-eslint/utils": "8.62.0", - "@typescript-eslint/visitor-keys": "8.62.0", + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/type-utils": "8.67.0", + "@typescript-eslint/utils": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -856,13 +1542,15 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.62.0", + "@typescript-eslint/parser": "^8.67.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", "dev": true, "license": "MIT", "engines": { @@ -870,14 +1558,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.62.0", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.67.0.tgz", + "integrity": "sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.62.0", - "@typescript-eslint/types": "8.62.0", - "@typescript-eslint/typescript-estree": "8.62.0", - "@typescript-eslint/visitor-keys": "8.62.0", + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", "debug": "^4.4.3" }, "engines": { @@ -893,12 +1583,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.62.0", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.67.0.tgz", + "integrity": "sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.62.0", - "@typescript-eslint/types": "^8.62.0", + "@typescript-eslint/tsconfig-utils": "^8.67.0", + "@typescript-eslint/types": "^8.67.0", "debug": "^4.4.3" }, "engines": { @@ -913,12 +1605,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.62.0", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.67.0.tgz", + "integrity": "sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.62.0", - "@typescript-eslint/visitor-keys": "8.62.0" + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -929,7 +1623,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.62.0", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.67.0.tgz", + "integrity": "sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==", "dev": true, "license": "MIT", "engines": { @@ -944,13 +1640,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.62.0", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.67.0.tgz", + "integrity": "sha512-aVWDXbRmdXO9siTfX4ditQI1T9+zVcNazT48EJCD0v40/9RIFoUgZ05CmGEq9H2gixRpjUn/iplwvlcvutJW/Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.62.0", - "@typescript-eslint/typescript-estree": "8.62.0", - "@typescript-eslint/utils": "8.62.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0", + "@typescript-eslint/utils": "8.67.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -967,7 +1665,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.62.0", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.67.0.tgz", + "integrity": "sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==", "dev": true, "license": "MIT", "engines": { @@ -979,14 +1679,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.62.0", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.67.0.tgz", + "integrity": "sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.62.0", - "@typescript-eslint/tsconfig-utils": "8.62.0", - "@typescript-eslint/types": "8.62.0", - "@typescript-eslint/visitor-keys": "8.62.0", + "@typescript-eslint/project-service": "8.67.0", + "@typescript-eslint/tsconfig-utils": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -1004,48 +1706,30 @@ "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { - "version": "4.0.4", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.6", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "10.2.5", + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/@typescript-eslint/utils": { - "version": "8.62.0", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.67.0.tgz", + "integrity": "sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.62.0", - "@typescript-eslint/types": "8.62.0", - "@typescript-eslint/typescript-estree": "8.62.0" + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1060,11 +1744,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.62.0", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.67.0.tgz", + "integrity": "sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.62.0", + "@typescript-eslint/types": "8.67.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -1077,6 +1763,8 @@ }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1086,11 +1774,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.2", - "dev": true, - "license": "ISC" - }, "node_modules/@unrs/resolver-binding-android-arm-eabi": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", @@ -1327,6 +2010,8 @@ }, "node_modules/@unrs/resolver-binding-linux-x64-gnu": { "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", "cpu": [ "x64" ], @@ -1390,6 +2075,17 @@ "node": ">=14.0.0" } }, + "node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", @@ -1432,26 +2128,10 @@ "win32" ] }, - "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/acorn": { - "version": "8.17.0", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", "dev": true, "license": "MIT", "bin": { @@ -1463,6 +2143,8 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -1471,6 +2153,8 @@ }, "node_modules/ajv": { "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", "dependencies": { @@ -1484,16 +2168,10 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/ansi-styles": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { @@ -1530,11 +2208,15 @@ }, "node_modules/argparse": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, "license": "Python-2.0" }, "node_modules/aria-query": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1579,6 +2261,8 @@ }, "node_modules/array.prototype.findlast": { "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1598,6 +2282,8 @@ }, "node_modules/array.prototype.findlastindex": { "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1652,6 +2338,8 @@ }, "node_modules/array.prototype.tosorted": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, "license": "MIT", "dependencies": { @@ -1687,6 +2375,8 @@ }, "node_modules/ast-types-flow": { "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", "dev": true, "license": "MIT" }, @@ -1713,7 +2403,9 @@ } }, "node_modules/axe-core": { - "version": "4.12.1", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.13.0.tgz", + "integrity": "sha512-UzGt8zg7Ny8djbYMhxl2zuEevVa7r2gJjYY5Lwr1xM7+XU2nd6CkIWFTVcCIbAP63vSz71NaVyyuSk9lHKcy0A==", "dev": true, "license": "MPL-2.0", "engines": { @@ -1722,6 +2414,8 @@ }, "node_modules/axobject-query": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1729,37 +2423,25 @@ } }, "node_modules/balanced-match": { - "version": "1.0.2", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, - "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" + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.13", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.13.tgz", + "integrity": "sha512-k9HNuUVMlqVjQ9UHzfPjIqiDbWw7WqT1AoT7GL8VwvF3r0ZfArtgiSPAlmupyNquNgOJHTuH4CKYf8ttMTWBTQ==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/binary-extensions": { @@ -1774,12 +2456,16 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.15", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" } }, "node_modules/braces": { @@ -1793,37 +2479,38 @@ "node": ">=8" } }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "node_modules/browserslist": { + "version": "4.28.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", + "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", + "dev": true, "funding": [ { - "type": "github", - "url": "https://github.com/sponsors/feross" + "type": "opencollective", + "url": "https://opencollective.com/browserslist" }, { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" }, { - "type": "consulting", - "url": "https://feross.org/support" + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/busboy": { - "version": "1.6.0", - "dependencies": { - "streamsearch": "^1.1.0" + "baseline-browser-mapping": "^2.11.12", + "caniuse-lite": "^1.0.30001809", + "electron-to-chromium": "^1.5.402", + "node-releases": "^2.0.53", + "update-browserslist-db": "^1.3.0" + }, + "bin": { + "browserslist": "cli.js" }, "engines": { - "node": ">=10.16.0" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, "node_modules/call-bind": { @@ -1872,6 +2559,8 @@ }, "node_modules/callsites": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "license": "MIT", "engines": { @@ -1886,17 +2575,10 @@ "node": ">= 6" } }, - "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.30001799", + "version": "1.0.30001809", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", + "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==", "funding": [ { "type": "opencollective", @@ -1915,6 +2597,8 @@ }, "node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { @@ -1968,10 +2652,14 @@ }, "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/color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1983,6 +2671,8 @@ }, "node_modules/color-name": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, @@ -1996,29 +2686,21 @@ }, "node_modules/concat-map": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, "license": "MIT" }, - "node_modules/cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" - } + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.6", + "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -2042,10 +2724,13 @@ }, "node_modules/csstype": { "version": "3.2.3", + "dev": true, "license": "MIT" }, "node_modules/damerau-levenshtein": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true, "license": "BSD-2-Clause" }, @@ -2150,13 +2835,14 @@ "url": "https://github.com/sponsors/ljharb" } }, - "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/didyoumean": { @@ -2170,22 +2856,18 @@ "license": "MIT" }, "node_modules/doctrine": { - "version": "3.0.0", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=0.10.0" } }, - "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/dunder-proto": { "version": "1.0.1", "dev": true, @@ -2199,13 +2881,17 @@ "node": ">= 0.4" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", + "node_modules/electron-to-chromium": { + "version": "1.5.405", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.405.tgz", + "integrity": "sha512-bNglH7lPH5l+yHOes7Zr4VqxhOy4BQ9ZBUX4VdoFgxMpzJk7W1ZoO3Vgd9Pxa9PyjQ76sfm2aKH/nzEcCNRlew==", "dev": true, - "license": "MIT" + "license": "ISC" }, "node_modules/emoji-regex": { "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true, "license": "MIT" }, @@ -2310,7 +2996,9 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.3.3", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.4.0.tgz", + "integrity": "sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2389,6 +3077,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "dev": true, @@ -2401,77 +3099,84 @@ } }, "node_modules/eslint": { - "version": "8.57.1", + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.5.tgz", + "integrity": "sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.6", + "@eslint/js": "9.39.5", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", + "minimatch": "^3.1.5", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-next": { - "version": "14.2.35", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.3.0.tgz", + "integrity": "sha512-lPrf1kHsMJEZqO0uXkNB400c5MGrhrTk3BNX7P0ol4gt61+iUlQfjy9TyIOEA9eOXrf+5+mYbT/JsY8+zqUByQ==", "dev": true, "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "14.2.35", - "@rushstack/eslint-patch": "^1.3.3", - "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", - "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@next/eslint-plugin-next": "16.3.0", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^7.0.0", + "globals": "16.4.0", + "typescript-eslint": "^8.46.0" }, "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0", + "eslint": ">=9.0.0", "typescript": ">=3.3.1" }, "peerDependenciesMeta": { @@ -2480,30 +3185,28 @@ } } }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", - "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", + "node_modules/eslint-config-next/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.16.1", - "resolve": "^2.0.0-next.6" - } + "license": "MIT" }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/eslint-config-next/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.1" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/eslint-import-resolver-typescript": { + "node_modules/eslint-config-next/node_modules/eslint-import-resolver-typescript": { "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", "dev": true, "license": "ISC", "dependencies": { @@ -2535,36 +3238,10 @@ } } }, - "node_modules/eslint-module-utils": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.13.0.tgz", - "integrity": "sha512-bLohSkT6469rRs8czj0tLTD8vaeIS/whvPRJVjDr7IuoTT1k5DYDERlNycjDj/HkOlvQdYurmfZ/g3fG5bgeLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { + "node_modules/eslint-config-next/node_modules/eslint-plugin-import": { "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", "dependencies": { @@ -2595,35 +3272,20 @@ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, - "node_modules/eslint-plugin-import/node_modules/debug": { + "node_modules/eslint-config-next/node_modules/eslint-plugin-import/node_modules/debug": { "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-jsx-a11y": { + "node_modules/eslint-config-next/node_modules/eslint-plugin-jsx-a11y": { "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2650,8 +3312,10 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, - "node_modules/eslint-plugin-react": { + "node_modules/eslint-config-next/node_modules/eslint-plugin-react": { "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", "dev": true, "license": "MIT", "dependencies": { @@ -2681,38 +3345,93 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "5.0.0-canary-7118f5dd7-20230705", + "node_modules/eslint-config-next/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.14.0.tgz", + "integrity": "sha512-W2WCRZ9Dqntd+2u8jJcVMV2PKulc6RdLgUUoh/yQr3uB6lo/ZOeGx11sv60/8S4QFFKNslAlWhr9u0Ef7ZW6Ig==", "dev": true, "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, "engines": { - "node": ">=10" + "node": ">=4" }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", + "node_modules/eslint-plugin-react-hooks": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "esutils": "^2.0.2" + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" } }, "node_modules/eslint-scope": { - "version": "7.2.2", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -2720,7 +3439,7 @@ "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2737,17 +3456,76 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/espree": { - "version": "9.6.1", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2766,6 +3544,8 @@ }, "node_modules/esrecurse": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -2793,6 +3573,8 @@ }, "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==", "dev": true, "license": "MIT" }, @@ -2828,6 +3610,8 @@ }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, "license": "MIT" }, @@ -2850,21 +3634,17 @@ "reusify": "^1.0.4" } }, - "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/file-entry-cache": { - "version": "6.0.1", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/fill-range": { @@ -2894,20 +3674,23 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.4.2", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", "dev": true, "license": "ISC" }, @@ -2925,40 +3708,21 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "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==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-13.1.0.tgz", + "integrity": "sha512-QSZrF0Id3QGuHJ+OL+9PSY9pk86C8ERFalwAGSchzTm65+ZoGH/RM26lmEARLljcHj2lqhv0jZOOks+EI3COOw==", "license": "MIT", "dependencies": { - "motion-dom": "^12.40.0", - "motion-utils": "^12.39.0", + "motion-dom": "^13.0.0", + "motion-utils": "^13.0.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 }, @@ -2967,11 +3731,6 @@ } } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "dev": true, - "license": "ISC" - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -3033,6 +3792,16 @@ "node": ">= 0.4" } }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "dev": true, @@ -3085,7 +3854,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.14.0", + "version": "4.14.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.2.tgz", + "integrity": "sha512-XpwZALwwl/BaKTAyC6+c5T8y6kCg2jk+XGqOVrKIQmW49pNypYLMRjCUXqa28tQgJlhS2RlzP7sc+Rx7W6qsfw==", "dev": true, "license": "MIT", "dependencies": { @@ -3095,27 +3866,6 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/glob": { - "version": "10.3.10", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "6.0.2", "dev": true, @@ -3127,37 +3877,14 @@ "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.9", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.2" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/globals": { - "version": "13.24.0", + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", "dev": true, "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3178,12 +3905,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "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/gopd": { "version": "1.2.0", "dev": true, @@ -3195,15 +3916,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, "node_modules/has-bigints": { "version": "1.1.0", "dev": true, @@ -3217,6 +3929,8 @@ }, "node_modules/has-flag": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", "engines": { @@ -3284,48 +3998,37 @@ "node": ">= 0.4" } }, - "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/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" }, - "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/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } }, "node_modules/ignore": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { "node": ">= 4" } }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", - "license": "MIT" - }, "node_modules/import-fresh": { "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3347,20 +4050,6 @@ "node": ">=0.8.19" } }, - "node_modules/inflight": { - "version": "1.0.6", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "dev": true, - "license": "ISC" - }, "node_modules/internal-slot": { "version": "1.1.0", "dev": true, @@ -3450,12 +4139,27 @@ }, "node_modules/is-bun-module": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", "dev": true, "license": "MIT", "dependencies": { "semver": "^7.7.1" } }, + "node_modules/is-bun-module/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/is-callable": { "version": "1.2.7", "dev": true, @@ -3548,14 +4252,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-generator-function": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", @@ -3632,20 +4328,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "license": "MIT" - }, "node_modules/is-regex": { "version": "1.2.1", "dev": true, @@ -3782,10 +4464,13 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, "license": "ISC" }, "node_modules/iterator.prototype": { "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", "dev": true, "license": "MIT", "dependencies": { @@ -3800,44 +4485,6 @@ "node": ">= 0.4" } }, - "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/jackspeak": { - "version": "2.3.6", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/jiti": { "version": "1.21.7", "dev": true, @@ -3848,10 +4495,13 @@ }, "node_modules/js-tokens": { "version": "4.0.0", + "dev": true, "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.2.0", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", "dev": true, "funding": [ { @@ -3871,13 +4521,30 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/json-buffer": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "license": "MIT" }, @@ -3887,14 +4554,16 @@ "license": "MIT" }, "node_modules/json5": { - "version": "1.0.2", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, "bin": { "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" } }, "node_modules/jsx-ast-utils": { @@ -3913,6 +4582,8 @@ }, "node_modules/keyv": { "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "license": "MIT", "dependencies": { @@ -3921,11 +4592,15 @@ }, "node_modules/language-subtag-registry": { "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", "dev": true, "license": "CC0-1.0" }, "node_modules/language-tags": { "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", "dev": true, "license": "MIT", "dependencies": { @@ -3947,15 +4622,6 @@ "node": ">= 0.8.0" } }, - "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/lilconfig": { "version": "3.1.3", "dev": true, @@ -3988,11 +4654,14 @@ }, "node_modules/lodash.merge": { "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, "license": "MIT" }, "node_modules/loose-envify": { "version": "1.4.0", + "dev": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -4002,18 +4671,13 @@ } }, "node_modules/lru-cache": { - "version": "10.4.3", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "license": "ISC" - }, - "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" + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" } }, "node_modules/math-intrinsics": { @@ -4032,21 +4696,6 @@ "node": ">= 8" } }, - "node_modules/meshline": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/meshline/-/meshline-3.3.1.tgz", - "integrity": "sha512-/TQj+JdZkeSUOl5Mk2J7eLcYTLiQm2IDzmlSvYm7ov15anEcDJ92GHqqazxTSreeNgfnYu24kiEvvv0WlbCdFQ==", - "license": "MIT", - "peerDependencies": { - "three": ">=0.137" - } - }, - "node_modules/meshoptimizer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-1.1.1.tgz", - "integrity": "sha512-oRFNWJRDA/WTrVj7NWvqa5HqE1t9MYDj2VaWirQCzCCrAd2GHrqR/sQezCxiWATPNlKTcRaPRHPJwIRoPBAp5g==", - "license": "MIT" - }, "node_modules/micromatch": { "version": "4.0.8", "dev": true, @@ -4060,45 +4709,44 @@ } }, "node_modules/minimatch": { - "version": "3.1.5", + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^5.0.8" }, "engines": { - "node": "*" + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minipass": { - "version": "7.1.3", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "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==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-13.0.0.tgz", + "integrity": "sha512-Xk+SJas70uMAUIApg+m3lZDShxI3LBFHq7mFGbBKoRXc2PVPDyAKmzN64Bbzt4CZdP/CItTiJxWtn4TA0v53Ng==", "license": "MIT", "dependencies": { - "motion-utils": "^12.39.0" + "motion-utils": "^13.0.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==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-13.0.0.tgz", + "integrity": "sha512-7DnN7TmbLcYXcG4RVadXIihWlyuM9afoUww8Y5Agg431kGKiuL2/OMyP4mJ5wLz+pvN3t5ySClLOaVXJ+wekRQ==", "license": "MIT" }, "node_modules/ms": { @@ -4117,7 +4765,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.15", + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", "funding": [ { "type": "github", @@ -4134,6 +4784,8 @@ }, "node_modules/napi-postinstall": { "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", "dev": true, "license": "MIT", "bin": { @@ -4152,41 +4804,41 @@ "license": "MIT" }, "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==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/next/-/next-16.3.0.tgz", + "integrity": "sha512-NEdGOzH+08eTXMUp9UYkA99Nhi5N6Thrhc1jgFOQgfgnGK/dA2hRwBpXep+exdFQrnwlRf/3Wixyp8lLBUpE2A==", "license": "MIT", "dependencies": { - "@next/env": "14.2.35", - "@swc/helpers": "0.5.5", - "busboy": "1.6.0", + "@next/env": "16.3.0", + "@swc/helpers": "0.5.15", + "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", - "graceful-fs": "^4.2.11", - "postcss": "8.4.31", - "styled-jsx": "5.1.1" + "postcss": "8.5.23", + "styled-jsx": "5.1.6" }, "bin": { "next": "dist/bin/next" }, "engines": { - "node": ">=18.17.0" + "node": ">=20.9.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" + "@next/swc-darwin-arm64": "16.3.0", + "@next/swc-darwin-x64": "16.3.0", + "@next/swc-linux-arm64-gnu": "16.3.0", + "@next/swc-linux-arm64-musl": "16.3.0", + "@next/swc-linux-x64-gnu": "16.3.0", + "@next/swc-linux-x64-musl": "16.3.0", + "@next/swc-win32-arm64-msvc": "16.3.0", + "@next/swc-win32-x64-msvc": "16.3.0", + "sharp": "^0.35.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", - "@playwright/test": "^1.41.2", - "react": "^18.2.0", - "react-dom": "^18.2.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "peerDependenciesMeta": { @@ -4196,35 +4848,12 @@ "@playwright/test": { "optional": true }, - "sass": { + "babel-plugin-react-compiler": { "optional": true - } - } - }, - "node_modules/next/node_modules/postcss": { - "version": "8.4.31", - "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" + "sass": { + "optional": true } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" } }, "node_modules/node-exports-info": { @@ -4246,14 +4875,14 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/node-exports-info/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/node-releases": { + "version": "2.0.53", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", + "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "engines": { + "node": ">=18" } }, "node_modules/normalize-path": { @@ -4266,6 +4895,7 @@ }, "node_modules/object-assign": { "version": "4.1.1", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -4350,6 +4980,8 @@ }, "node_modules/object.groupby": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4378,14 +5010,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/once": { - "version": "1.4.0", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, "node_modules/optionator": { "version": "0.9.4", "dev": true, @@ -4448,6 +5072,8 @@ }, "node_modules/parent-module": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "license": "MIT", "dependencies": { @@ -4465,16 +5091,9 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4485,21 +5104,6 @@ "dev": true, "license": "MIT" }, - "node_modules/path-scurry": { - "version": "1.11.1", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/picocolors": { "version": "1.1.1", "license": "ISC" @@ -4532,35 +5136,35 @@ } }, "node_modules/playwright": { - "version": "1.61.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.61.1.tgz", - "integrity": "sha512-DWnY5o3YbLWK4GovuAVwpqL+1VwGNdUGrRr++8j8PtQQzvAVZUIMjKQ90fY689sEJZJBbZVw1rXaOKSTitkzPQ==", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.1.tgz", + "integrity": "sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.61.1" + "playwright-core": "1.62.1" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=20" }, "optionalDependencies": { "fsevents": "2.3.2" } }, "node_modules/playwright-core": { - "version": "1.61.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.61.1.tgz", - "integrity": "sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.1.tgz", + "integrity": "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==", "devOptional": true, "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/playwright/node_modules/fsevents": { @@ -4586,14 +5190,15 @@ } }, "node_modules/postal-mime": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/postal-mime/-/postal-mime-2.7.4.tgz", - "integrity": "sha512-0WdnFQYUrPGGTFu1uOqD2s7omwua8xaeYGdO6rb88oD5yJ/4pPHDA4sdWqfD8wQVfCny563n/HQS7zTFft+f/g==", + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/postal-mime/-/postal-mime-2.7.5.tgz", + "integrity": "sha512-GNEXKvWFQnbgO5NlrGzVa0FmWzBZ24PersAWErttSg1Hjpf0ATxTwS5DOMGaOpTG6bUh5cTr7xi0jAD942wCJA==", "license": "MIT-0" }, "node_modules/postcss": { - "version": "8.5.15", - "dev": true, + "version": "8.5.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", + "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", "funding": [ { "type": "opencollective", @@ -4610,7 +5215,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.12", + "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -4764,12 +5369,6 @@ "dev": true, "license": "MIT" }, - "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/prelude-ls": { "version": "1.2.1", "dev": true, @@ -4778,18 +5377,11 @@ "node": ">= 0.8.0" } }, - "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==", + "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -4799,6 +5391,8 @@ }, "node_modules/punycode": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", "engines": { @@ -4825,82 +5419,33 @@ "license": "MIT" }, "node_modules/react": { - "version": "18.3.1", + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", + "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", "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", + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", + "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" + "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^18.3.1" + "react": "^19.2.8" } }, "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==", + "dev": true, "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/read-cache": { "version": "1.0.0", "dev": true, @@ -4960,22 +5505,13 @@ "url": "https://github.com/sponsors/ljharb" } }, - "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/resend": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/resend/-/resend-6.14.0.tgz", - "integrity": "sha512-jVdpUgOoWGLjaP64lo8KwzHT9gY4w6Dl8c36CIb2F+ayYOMLr3khqs8xrNjXM2k19b+lPoj0VWQFhVNLiToBjA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/resend/-/resend-6.19.0.tgz", + "integrity": "sha512-JnEdYnd9WyBDIzunsEZtUF8n3cBKM9SlmySaos/7wwi4sEXKG1Zz4M64VFAyk+278erX01Fq2wHQ3p7OIdPriA==", "license": "MIT", "dependencies": { - "postal-mime": "2.7.4", + "postal-mime": "2.7.5", "standardwebhooks": "1.0.0" }, "engines": { @@ -5014,6 +5550,8 @@ }, "node_modules/resolve-from": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "license": "MIT", "engines": { @@ -5022,6 +5560,8 @@ }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, "license": "MIT", "funding": { @@ -5037,45 +5577,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "dev": true, @@ -5148,21 +5649,19 @@ } }, "node_modules/scheduler": { - "version": "0.23.2", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" }, "node_modules/semver": { - "version": "7.8.5", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/set-function-length": { @@ -5208,8 +5707,72 @@ "node": ">= 0.4" } }, + "node_modules/sharp": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.3.tgz", + "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.3", + "@img/sharp-darwin-x64": "0.35.3", + "@img/sharp-freebsd-wasm32": "0.35.3", + "@img/sharp-libvips-darwin-arm64": "1.3.2", + "@img/sharp-libvips-darwin-x64": "1.3.2", + "@img/sharp-libvips-linux-arm": "1.3.2", + "@img/sharp-libvips-linux-arm64": "1.3.2", + "@img/sharp-libvips-linux-ppc64": "1.3.2", + "@img/sharp-libvips-linux-riscv64": "1.3.2", + "@img/sharp-libvips-linux-s390x": "1.3.2", + "@img/sharp-libvips-linux-x64": "1.3.2", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", + "@img/sharp-libvips-linuxmusl-x64": "1.3.2", + "@img/sharp-linux-arm": "0.35.3", + "@img/sharp-linux-arm64": "0.35.3", + "@img/sharp-linux-ppc64": "0.35.3", + "@img/sharp-linux-riscv64": "0.35.3", + "@img/sharp-linux-s390x": "0.35.3", + "@img/sharp-linux-x64": "0.35.3", + "@img/sharp-linuxmusl-arm64": "0.35.3", + "@img/sharp-linuxmusl-x64": "0.35.3", + "@img/sharp-webcontainers-wasm32": "0.35.3", + "@img/sharp-win32-arm64": "0.35.3", + "@img/sharp-win32-ia32": "0.35.3", + "@img/sharp-win32-x64": "0.35.3" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/sharp/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/shebang-command": { "version": "2.0.0", + "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -5220,6 +5783,7 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -5290,152 +5854,49 @@ "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stable-hash": { - "version": "0.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/standardwebhooks": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/standardwebhooks/-/standardwebhooks-1.0.0.tgz", - "integrity": "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==", - "license": "MIT", - "dependencies": { - "@stablelib/base64": "^1.0.0", - "fast-sha256": "^1.3.0" - } - }, - "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/stop-iteration-iterator": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/string-width": { - "version": "5.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, + "node_modules/source-map-js": { + "version": "1.2.1", + "license": "BSD-3-Clause", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", "dev": true, "license": "MIT" }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.2.2", - "dev": true, + "node_modules/standardwebhooks": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/standardwebhooks/-/standardwebhooks-1.0.0.tgz", + "integrity": "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==", "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "dependencies": { + "@stablelib/base64": "^1.0.0", + "fast-sha256": "^1.3.0" } }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.2.0", + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^6.2.2" + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">= 0.4" } }, "node_modules/string.prototype.includes": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", "dev": true, "license": "MIT", "dependencies": { @@ -5449,6 +5910,8 @@ }, "node_modules/string.prototype.matchall": { "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", "dev": true, "license": "MIT", "dependencies": { @@ -5475,6 +5938,8 @@ }, "node_modules/string.prototype.repeat": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", "dev": true, "license": "MIT", "dependencies": { @@ -5536,31 +6001,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-bom": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, "license": "MIT", "engines": { @@ -5569,6 +6013,8 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", "engines": { @@ -5579,7 +6025,9 @@ } }, "node_modules/styled-jsx": { - "version": "5.1.1", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", "license": "MIT", "dependencies": { "client-only": "0.0.1" @@ -5588,7 +6036,7 @@ "node": ">= 12.0.0" }, "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" }, "peerDependenciesMeta": { "@babel/core": { @@ -5622,6 +6070,8 @@ }, "node_modules/supports-color": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { @@ -5642,15 +6092,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/suspend-react": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/suspend-react/-/suspend-react-0.1.3.tgz", - "integrity": "sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ==", - "license": "MIT", - "peerDependencies": { - "react": ">=17.0" - } - }, "node_modules/tailwindcss": { "version": "3.4.19", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", @@ -5711,11 +6152,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/text-table": { - "version": "0.2.0", - "dev": true, - "license": "MIT" - }, "node_modules/thenify": { "version": "3.3.1", "dev": true, @@ -5735,45 +6171,6 @@ "node": ">=0.8" } }, - "node_modules/three": { - "version": "0.160.1", - "resolved": "https://registry.npmjs.org/three/-/three-0.160.1.tgz", - "integrity": "sha512-Bgl2wPJypDOZ1stAxwfWAcJ0WQf7QzlptsxkjYiURPz+n5k4RBDLsq+6f9Y75TYxn6aHLcWz+JNmwTOXWrQTBQ==", - "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/tinyglobby": { "version": "0.2.17", "dev": true, @@ -5827,38 +6224,10 @@ "node": ">=8.0" } }, - "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/ts-api-utils": { "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "license": "MIT", "engines": { @@ -5875,6 +6244,8 @@ }, "node_modules/tsconfig-paths": { "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "license": "MIT", "dependencies": { @@ -5884,47 +6255,23 @@ "strip-bom": "^3.0.0" } }, - "node_modules/tslib": { - "version": "2.8.1", - "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==", + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, "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" + "minimist": "^1.2.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "immer": { - "optional": true - }, - "react": { - "optional": true - } + "bin": { + "json5": "lib/cli.js" } }, + "node_modules/tslib": { + "version": "2.8.1", + "license": "0BSD" + }, "node_modules/type-check": { "version": "0.4.0", "dev": true, @@ -5936,17 +6283,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typed-array-buffer": { "version": "1.0.3", "dev": true, @@ -6029,6 +6365,30 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.67.0.tgz", + "integrity": "sha512-S2udFs8tCKEKffuJ4TB1idGUZiXdCPGi3IPBGWXarbLQ5UPXORV8QEVzJ4gCRduURMb5EkpNCdjbk0eDIuI8Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.67.0", + "@typescript-eslint/parser": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0", + "@typescript-eslint/utils": "8.67.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, "node_modules/unbox-primitive": { "version": "1.1.0", "dev": true, @@ -6053,6 +6413,8 @@ }, "node_modules/unrs-resolver": { "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -6087,50 +6449,55 @@ "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" } }, + "node_modules/update-browserslist-db": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", + "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, - "node_modules/use-sync-external-store": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", - "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "dev": true, "license": "MIT" }, - "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/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", + "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -6231,138 +6598,45 @@ "node": ">=0.10.0" } }, - "node_modules/wrap-ansi": { - "version": "8.1.0", + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } + "license": "ISC" }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", + "node_modules/yocto-queue": { + "version": "0.1.0", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.2.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.2.0", + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/sponsors/colinhacks" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/yocto-queue": { - "version": "0.1.0", + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zustand": { - "version": "5.0.14", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.14.tgz", - "integrity": "sha512-/8tAspM5LMPr28b3fwLYrtdj77ECpfZviaP75CMTnwO8ISyaE4GDIG/9rDDYq/cH9D2Xw2A2RXglLInmVBQB/g==", - "license": "MIT", - "engines": { - "node": ">=12.20.0" + "node": ">=18.0.0" }, "peerDependencies": { - "@types/react": ">=18.0.0", - "immer": ">=9.0.6", - "react": ">=18.0.0", - "use-sync-external-store": ">=1.2.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "immer": { - "optional": true - }, - "react": { - "optional": true - }, - "use-sync-external-store": { - "optional": true - } + "zod": "^3.25.0 || ^4.0.0" } } } diff --git a/package.json b/package.json index e8c91c6..75aa27e 100644 --- a/package.json +++ b/package.json @@ -6,26 +6,25 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint", - "test:e2e": "playwright test" + "lint": "eslint .", + "test:e2e": "playwright test", + "typecheck": "tsc --noEmit", + "check": "npm run lint && npm run typecheck && npm run build" }, "dependencies": { - "@react-three/drei": "^9.122.0", - "@react-three/fiber": "^8.18.0", - "framer-motion": "^12.40.0", - "next": "14.2.35", - "react": "^18", - "react-dom": "^18", - "resend": "^6.14.0", - "three": "^0.160.1" + "framer-motion": "^13.1.0", + "next": "^16.3.0", + "react": "^19.2.8", + "react-dom": "^19.2.8", + "resend": "^6.19.0" }, "devDependencies": { - "@playwright/test": "^1.61.1", - "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", - "eslint": "^8", - "eslint-config-next": "14.2.35", + "@playwright/test": "^1.62.1", + "@types/node": "^22", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9.39.5", + "eslint-config-next": "^16.3.0", "postcss": "^8", "tailwindcss": "^3.4.1", "typescript": "^5" diff --git a/playwright.config.ts b/playwright.config.ts index f8f5e88..4c7adce 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -3,8 +3,9 @@ import { defineConfig } from "@playwright/test"; export default defineConfig({ testDir: "./tests", fullyParallel: true, - retries: 0, + retries: process.env.CI ? 2 : 0, reporter: "line", + timeout: 60_000, use: { baseURL: "http://127.0.0.1:3100", trace: "retain-on-failure", @@ -17,18 +18,16 @@ export default defineConfig({ }, projects: [ { - name: "desktop-edge", + name: "desktop-chromium", use: { browserName: "chromium", - channel: "msedge", viewport: { width: 1440, height: 1000 }, }, }, { - name: "mobile-edge", + name: "mobile-chromium", use: { browserName: "chromium", - channel: "msedge", viewport: { width: 390, height: 844 }, deviceScaleFactor: 1, hasTouch: true, @@ -36,4 +35,4 @@ export default defineConfig({ }, }, ], -}); +}); \ No newline at end of file diff --git a/public/logo.png.png b/public/logo.png similarity index 100% rename from public/logo.png.png rename to public/logo.png diff --git a/specs/portfolio-architecture-refactor/PROGRESS.md b/specs/portfolio-architecture-refactor/PROGRESS.md new file mode 100644 index 0000000..f309cf7 --- /dev/null +++ b/specs/portfolio-architecture-refactor/PROGRESS.md @@ -0,0 +1,70 @@ +# Portfolio Architecture Refactor Progress + +**Last updated**: 2026-08-13 +**Status**: Complete — implementation and validation finished +**Current task**: T013 — Final architectural review and handoff + +## Completed work + +- [x] Audited the App Router, source tree, content, API, dependencies, TypeScript, + ESLint, Playwright, environment files, assets, metadata, history, evidence, + graph, GitHub configuration, README, Git history, and secret-like patterns. +- [x] Wrote and followed the fresh SDD specification, plan, and ordered task list. +- [x] Migrated application code to src/app, src/components, src/content, and + src/server without leaving duplicate root application directories. +- [x] Centralized profile, projects, skills, socials, and education content. +- [x] Upgraded to Next.js 16.3.0 and React 19.2.8; modernized flat ESLint and scripts. +- [x] Removed unused React Three Fiber, Drei, and Three dependencies. +- [x] Added runtime contact validation, honeypot handling, bounded in-memory rate + limiting, fixed-recipient email service, environment-driven configuration, and + predictable 400/429/502/503 responses. +- [x] Reduced client boundaries to navigation, contact form, and custom cursor; static + page sections remain Server Components. +- [x] Added canonical metadata, Open Graph/Twitter metadata, robots, sitemap, and a + deliberate public/logo.png asset name. +- [x] Replaced the template README and added CI, MIT license, contributing, security, + and editor configuration files. +- [x] Added Playwright coverage for responsive homepage behavior, contact errors, and + SEO routes. +- [x] Reviewed public-repository development records. Existing .claude, .specify, + history, evidence, and graph records remain because they are required SDD/ + provenance artifacts and contain no discovered live secrets. +- [x] Validated GraphKeeper with bash scripts/validate.sh --worktree. + +## Validation results + +- [x] npm run lint — PASS +- [x] npm run typecheck — PASS +- [x] npm run build — PASS +- [x] npm run test:e2e — PASS (10 tests on desktop/mobile Chromium) +- [x] npm run check — PASS +- [x] bash scripts/validate.sh --worktree — PASS +- [ ] npm ci — the Windows package process exceeded the five-minute tool budget; + the subsequent package state passed all npm quality gates and browser tests. +- [x] Secret-like scan — no live credential found; only the documented .env.example + placeholder and an unrelated template word in historical instructions matched. + +## Important decisions + +- Preserve the current dark editorial visual identity, section IDs, copy, links, and + evidence-backed project hierarchy; do not reintroduce the unused 3D feature. +- Use a small src/server boundary rather than enterprise layers. +- Use an in-memory limiter suitable for low-volume portfolio traffic; document its + per-instance limitation and revisit only if abuse volume warrants a managed service. +- Keep Resend but make API key, verified sender, recipient, and site URL configurable. +- Keep .claude, .specify, history, evidence, and graph as intentional development/ + provenance artifacts instead of deleting them blindly. + +## Remaining limitations + +- The in-memory limiter does not coordinate across multiple Vercel instances and resets + during deployment. +- The form provider requires production Resend configuration and verified sender setup. +- The existing repository history includes earlier development records; they are + retained for traceability rather than presented as product runtime code. + +## Resume instructions + +The refactor is complete. For future changes, read this progress file and the feature +specification before modifying architecture; update the SDD artifacts first when scope +changes. \ No newline at end of file diff --git a/specs/portfolio-architecture-refactor/plan.md b/specs/portfolio-architecture-refactor/plan.md new file mode 100644 index 0000000..7ea0daf --- /dev/null +++ b/specs/portfolio-architecture-refactor/plan.md @@ -0,0 +1,149 @@ +# Portfolio Architecture Refactor Plan + +## 1. Scope and dependencies + +### In scope + +Incrementally migrate the existing portfolio into `src/`, centralize its current +content, isolate the contact server boundary, modernize project tooling, add SEO and +public-repository documentation, and validate the unchanged visual experience. + +### Out of scope + +Visual redesign, new features such as 3D, auth, CMS, analytics, external rate limiting, +or a wholesale component rewrite. + +### External dependencies + +- Next.js/React and npm registry: framework and package compatibility. +- Resend: contact email delivery, configured by the site owner. +- Vercel: production hosting and environment variables. +- GitHub Actions: CI execution and browser dependencies. +- Microsoft Edge/Playwright Chromium availability: local browser validation. + +## 2. Target architecture + +```text +public/ +src/ + app/ + api/contact/route.ts + layout.tsx + page.tsx + globals.css + robots.ts + sitemap.ts + components/ + sections/ # server-rendered section shells + layout/ # navigation/footer + ui/ # focused reusable primitives + client/ # small state/effect islands + content/ + profile.ts + projects.ts + skills.ts + socials.ts + education.ts + server/contact/ + validation.ts + rate-limit.ts + service.ts + server/email/ + resend.ts +tests/e2e/ +.github/workflows/ci.yml +``` + +The existing design components move with minimal semantic changes. The server +section shells import canonical content and render it; motion is delegated to small +client wrappers rather than turning every section into a client boundary. + +## 3. Ordered implementation map + +| Step | Requirement | Concrete changes | Validation | +|---|---|---|---| +| 1 | R1, R3 | Add `src/` tree, move content and app/component files, update alias and Tailwind content globs | Typecheck, import scan, homepage smoke test | +| 2 | R5 | Verify stable package versions, remove unused 3D packages, add flat ESLint and scripts | `npm ci`, lint, typecheck | +| 3 | R4 | Add runtime validator, bounded in-memory limiter, contact service, server-only Resend adapter, env docs | Unit-level route checks and API/browser behavior | +| 4 | R2 | Convert static sections to Server Components and retain only focused client islands | Build plus source boundary audit | +| 5 | R6 | Add canonical profile metadata, robots, sitemap, rename logo, add safe site URL helper | Build and route/content assertions | +| 6 | R7 | Replace README, add CI and appropriate public-repo files, update Playwright config/tests | Markdown/config review and CI-equivalent local commands | +| 7 | All | Run final checks, inspect generated output, update progress and report limitations | Full validation matrix | + +## 4. Migration details and compatibility risks + +### Files to add + +- `src/content/*` canonical content modules. +- `src/server/contact/*` and `src/server/email/*` server boundary modules. +- `src/app/robots.ts`, `src/app/sitemap.ts`. +- `eslint.config.mjs`, `.github/workflows/ci.yml`, `PROGRESS.md`, and relevant docs. +- Additional focused tests for contact validation/limiting if the chosen test setup + supports them without adding unnecessary dependencies. + +### Files to change + +- `package.json` and lockfile, `tsconfig.json`, `next.config.*`, Tailwind config, + Playwright config, `.env.example`. +- `src/app/layout.tsx`, `src/app/page.tsx`, `src/app/globals.css`. +- Existing sections, navigation, cursor, and form after migration. +- README and tracked project guidance where it describes stale structure. + +### Files to remove or relocate + +- Root `app/`, `components/`, `data/`, and `lib/` after their contents are migrated. +- `.eslintrc.json` after flat config is in place. +- Unused 3D packages and the misspelled duplicate-extension asset name. +- No SDD/history/evidence/graph file is removed without a separate rationale. + +### Compatibility risks + +1. A major Next.js/React upgrade may change lint, metadata, or font behavior. Verify + the exact supported pair first and use the lockfile. +2. Moving the alias to `src/*` can leave stale imports. Use a complete import scan and + TypeScript build before deleting root duplicates. +3. Making sections server-rendered can change animation timing. Preserve the existing + visual transition through small client wrappers and test reduced motion. +4. In-memory rate limiting is per instance and resets on deploy. Document this + intentional low-traffic portfolio tradeoff; a managed limiter is a future option. +5. `metadataBase` depends on an environment URL. Use a deterministic default and + document the deployment override. + +## 5. Behavior preservation strategy + +- Keep current copy, project order, URLs, section IDs, color tokens, spacing language, + and mobile menu behavior. +- Keep the custom cursor as an optional desktop-only client island and preserve the + coarse-pointer fallback. +- Keep form field names, validation limits, success text, and error-state input + preservation while improving server validation and configuration. +- Keep `framer-motion` only where it materially supports existing entrance/cursor + behavior; do not add a new motion system. + +## 6. Validation gates + +1. After migration: imports, typecheck, and no duplicate root source. +2. After tooling/dependency update: clean install, lint, typecheck, and build. +3. After contact refactor: malformed-body, validation, limiter, missing-config, and + provider-error checks, plus form preservation in the browser. +4. After SEO/docs/CI: metadata route and source scans, README/config review. +5. Final: `npm ci`, lint, typecheck, build, `check`, e2e, responsive overflow, mobile + navigation, anchor links, robots, sitemap, and secret scan. + +## 7. Operational readiness + +- Log only server-side error categories and request correlation context that contains + no message body or secret. +- Return `429` with `Retry-After` for limiter rejection and generic `5xx` responses for + configuration/provider failures. +- Vercel environment variables are the production source of truth. +- Roll back through the previous Git/Vercel deployment if the contact provider or build + fails. +- CI is the required merge gate; no deployment automation is added in this task. + +## 8. Architectural decision checkpoint + +The framework/tooling upgrade, `src/` migration, and server/client boundary are +cross-cutting decisions with long-term consequences and multiple viable options. +They should be offered as one grouped ADR after implementation validation rather than +created automatically. diff --git a/specs/portfolio-architecture-refactor/spec.md b/specs/portfolio-architecture-refactor/spec.md new file mode 100644 index 0000000..24a16e2 --- /dev/null +++ b/specs/portfolio-architecture-refactor/spec.md @@ -0,0 +1,183 @@ +# Portfolio Architecture Refactor Specification + +**Feature**: `portfolio-architecture-refactor` +**Status**: Implemented and validated +**Date**: 2026-08-13 +**Source**: `Codex Prompt — Portfolio Architecture Refactor with Pure SDD.md` + +## 1. Context and current-state findings + +The repository is a working Next.js portfolio on the `refactor/full-stack-ai-projects` +branch. Its current visual identity is a dark, editorial portfolio with white text, +orange accents, grid texture, responsive navigation, project hierarchy, skills, +education, social links, and a Resend-backed contact form. The refactor must preserve +that identity and the current content hierarchy. + +The audit found: + +- App Router files and reusable components currently live at repository root. +- Portfolio content is split across `data/` and component-local constants. +- Several whole sections are Client Components only to use Framer Motion. +- The contact route casts `request.json()` directly, hard-codes sender/recipient + values, and has no abuse protection. +- Tooling uses Next 14's legacy `.eslintrc.json` and `next lint` script. +- There are no `robots.ts`, `sitemap.ts`, CI workflow, or professional README. +- `public/logo.png.png` is a suspiciously named asset referenced by metadata and nav. +- React Three Fiber/Three dependencies are installed but not used by the current app. +- Existing GraphKeeper evidence records five primary projects and Prospector as a + secondary project; those entries are authoritative for the content migration. +- The baseline lint/typecheck command exceeded the two-minute execution budget before + returning a result; this is not considered a pass. + +## 2. Scope + +### In scope + +1. Move the application to a clear `src/` App Router structure without changing the + rendered design or portfolio content unless correctness, accessibility, security, + or maintainability requires it. +2. Establish a canonical server-safe content layer for profile, projects, skills, + socials, and education. +3. Reduce client JavaScript to focused islands for navigation, form state, cursor, + and viewport animation behavior. Static section shells and data rendering remain + Server Components. +4. Refactor the contact endpoint into route → validation → abuse protection → + application function → Resend adapter, with predictable errors and environment + configuration. +5. Modernize dependencies and tooling to a currently supported stable Next.js/React + stack after verifying exact versions from authoritative package sources. +6. Add App Router metadata, canonical URL handling, `robots.ts`, and `sitemap.ts`. +7. Add a useful quality gate, CI, responsive/accessibility tests, and repository + documentation. +8. Audit public-repository hygiene and secret-like content without publishing + credentials or deleting useful project history blindly. + +### Out of scope + +- A visual redesign, new portfolio sections, new projects, new 3D experience, or a + replacement animation system. +- A database, authentication system, external rate-limit service, CMS, analytics + integration, or generic email relay. +- Rewriting working visual components solely to make the diff larger. +- Deleting `.specify/`, `history/`, `evidence/`, or `graph/` without an explicit + public-repository policy decision and evidence review. +- Production deployment or changing Vercel project settings. + +## 3. Functional requirements + +### R1 — Repository architecture + +- The final application uses `src/app`, `src/components`, `src/content`, and + `src/server` boundaries. +- The contact route is at `src/app/api/contact/route.ts`. +- Existing imports use the `@/` alias and the alias resolves to `src/*`. +- Component names and existing section IDs remain stable unless a correctness fix + requires a change. + +### R2 — Server-first rendering + +- `src/app/page.tsx`, static section components, content modules, layout, and SEO + routes are Server Components. +- Client Components are limited to browser state/effects: mobile menu, contact form, + custom cursor, and small viewport animation wrappers where needed. +- No Redux, dependency injection, repository layer, or other enterprise abstraction is + introduced. +- Static portfolio text is present in the server-rendered HTML. +- `prefers-reduced-motion` disables or minimizes nonessential motion. + +### R3 — Canonical content + +- A single content module owns identity/metadata values used by layout, hero, footer, + and structured data. +- Projects preserve the current five primary projects and Prospector as secondary, + including links, descriptions, problem statements, and technology lists. +- Skills, socials, and education move into the same canonical content boundary. +- No secret, API key, or deployment-only value is stored in content modules. + +### R4 — Contact boundary + +- The route accepts only a JSON object with `name`, `email`, `message`, and an + optional honeypot field; unknown or malformed JSON returns a predictable `400`. +- Server validation trims and bounds fields, validates email syntax, and never trusts + a TypeScript cast as runtime validation. +- A honeypot submission is rejected without sending mail. +- A lightweight per-process, bounded-window limiter prevents repeated submissions from + one IP. The implementation must fail closed for the limiter's own malformed input + but must not crash the route. +- Sender address, recipient address, and public site URL are environment-driven; + `RESEND_API_KEY` remains server-only. +- Missing configuration returns a generic `503` response and logs diagnostic detail + only on the server. +- Resend failures return a generic `502` response; validation returns `400`; a + limited request returns `429` with `Retry-After`; success returns `200` with the + same stable success shape. +- The endpoint sends only the portfolio contact message and cannot be used to choose + arbitrary recipients, sender addresses, or headers. + +### R5 — Tooling and dependencies + +- `npm run dev`, `npm run build`, `npm run lint`, `npm run typecheck`, + `npm run test:e2e`, and `npm run check` are available. +- ESLint uses flat config and does not depend on the removed `next lint` command. +- TypeScript remains strict with no unjustified `any`. +- Unused React Three Fiber, Drei, and Three packages are removed because the current + app does not use them and reintroducing a 3D feature is out of scope. +- Package upgrades are deliberate, lockfile-backed, and verified against the chosen + Next.js/React compatibility range. + +### R6 — Metadata and public assets + +- `metadataBase`, canonical URL, title, description, Open Graph, Twitter card, and + icon references are valid for the configured site URL. +- `src/app/robots.ts` and `src/app/sitemap.ts` are present and use the canonical site + URL. +- The double-extension logo asset is renamed to a deliberate filename and all + references are updated. +- No untrusted content is injected into the page as HTML. + +### R7 — Repository hygiene and documentation + +- README explains purpose, architecture, stack, setup, environment variables, + commands, tests, deployment, and important decisions without template boilerplate. +- `.env.example` documents every required variable with safe placeholders and no + live secret. +- A CI workflow runs clean install, lint, typecheck, build, and the browser checks + where the runner supports them. +- Add only open-source completeness files that make sense for this portfolio. A + permissive license is included only if the repository's public intent supports it; + private agent history remains clearly separated from production source. + +## 4. Acceptance criteria + +- [ ] The final source tree has the planned `src/` boundaries and no stale duplicate + application/content tree remains. +- [ ] The homepage preserves current headings, project order, section IDs, links, + dark/orange design, responsive navigation, and contact interaction. +- [ ] Static content is server-rendered and client boundaries are limited and + explainable. +- [ ] Contact requests with non-object JSON, missing fields, invalid email, oversized + fields, honeypot input, repeated IP submissions, missing configuration, and + provider failure follow the specified error taxonomy. +- [ ] No secret-like value is tracked or emitted to the client bundle. +- [ ] `npm ci`, `npm run lint`, `npm run typecheck`, `npm run build`, `npm run check`, + and `npm run test:e2e` are run and results are recorded. +- [ ] Metadata, favicon, robots, sitemap, internal anchors, mobile layout, and + horizontal-overflow checks pass. +- [ ] README, CI, environment documentation, and progress report describe the final + architecture and intentional tradeoffs. + +## 5. Error and compatibility constraints + +The refactor must not expose whether an email address is configured, leak provider +errors, or accept arbitrary Resend fields. If the production site URL is unavailable +at build time, metadata and sitemap generation must use a documented safe default and +remain deterministic. If a browser does not support a motion API, the content and +navigation remain usable. If an external email provider is unavailable, the form +retains user input and reports a retryable generic error. + +## 6. Definition of done + +The repository is considered done when the implementation, documentation, CI, and +verification results satisfy all acceptance criteria, the final review finds no clear +stale architecture or secret exposure, and `PROGRESS.md` records remaining intentional +limitations. diff --git a/specs/portfolio-architecture-refactor/tasks.md b/specs/portfolio-architecture-refactor/tasks.md new file mode 100644 index 0000000..9b3c5c0 --- /dev/null +++ b/specs/portfolio-architecture-refactor/tasks.md @@ -0,0 +1,123 @@ +# Portfolio Architecture Refactor Tasks + +Tasks are ordered. Each task records its objective, affected files, dependency, and +validation so another session can resume without reconstructing the plan. + +## Phase 0 — SDD gate + +- [x] **T001 — Write fresh SDD artifacts** + - Objective: Define final-state requirements, architecture, risks, and acceptance checks. + - Files: `spec.md`, `plan.md`, `tasks.md`, `PROGRESS.md`. + - Depends on: repository audit. + - Validation: all three artifacts agree on scope; no application code changed. + +## Phase 1 — Source and content migration + +- [x] **T002 — Create the `src/` boundaries** + - Objective: Move App Router, components, data, and server utility code into the + planned source tree with minimal behavior changes. + - Files: `src/app/**`, `src/components/**`, `src/content/**`, `src/server/**`, + `tsconfig.json`, `tailwind.config.ts`. + - Depends on: T001. + - Validation: no root source duplicates; import scan and typecheck pass. + +- [x] **T003 — Centralize canonical content** + - Objective: Move profile, project, skill, social, and education values into typed + content modules and update all consumers. + - Files: `src/content/*.ts`, sections, layout, structured data. + - Depends on: T002. + - Validation: current five primary projects plus Prospector render in order; no + duplicated identity constants outside content. + +## Phase 2 — Tooling and dependency modernization + +- [x] **T004 — Select and apply supported package versions** + - Objective: Verify the supported Next.js/React pair and update package manifests; + remove unused Three/R3F packages. + - Files: `package.json`, `package-lock.json`, `next.config.*`. + - Depends on: T002. + - Validation: clean `npm ci`, dependency import audit, build. + +- [x] **T005 — Replace legacy lint and scripts** + - Objective: Add flat ESLint config and predictable scripts for lint, typecheck, e2e, + and the composite check. + - Files: `eslint.config.mjs`, `package.json`, Playwright config. + - Depends on: T004. + - Validation: each script runs with a clear exit code; `npm run lint` passes. + +## Phase 3 — Secure contact boundary + +- [x] **T006 — Implement runtime contact validation and abuse protection** + - Objective: Add unknown-input validation, honeypot handling, bounded in-memory + limiter, and error taxonomy. + - Files: `src/server/contact/validation.ts`, `src/server/contact/rate-limit.ts`, + `src/app/api/contact/route.ts`. + - Depends on: T002. + - Validation: malformed, invalid, oversized, honeypot, and repeated requests return + expected statuses without sending mail. + +- [x] **T007 — Isolate the email adapter and configuration** + - Objective: Keep Resend server-only, move from/to/site URL to environment variables, + and make provider/configuration failures generic to clients. + - Files: `src/server/contact/service.ts`, `src/server/email/resend.ts`, `.env.example`. + - Depends on: T006. + - Validation: missing config is `503`, provider failure is `502`, success has stable + response shape, no secret is bundled. + +## Phase 4 — Server/client and SEO boundaries + +- [x] **T008 — Reduce unnecessary client boundaries** + - Objective: Keep page, layout, static sections, and content server-rendered; retain + only navigation/form/cursor and small motion islands. + - Files: `src/app/page.tsx`, `src/components/**`. + - Depends on: T003, T007. + - Validation: source audit of `"use client"`; build; reduced-motion and JS-off behavior. + +- [x] **T009 — Add metadata routes and correct public asset naming** + - Objective: Add metadataBase/canonical/Open Graph/Twitter, robots, sitemap, and fix + the double-extension logo reference. + - Files: `src/app/layout.tsx`, `src/app/robots.ts`, `src/app/sitemap.ts`, `public/*`. + - Depends on: T003. + - Validation: build plus route/content checks for metadata, robots, and sitemap. + +## Phase 5 — Public project quality + +- [x] **T010 — Add README, CI, and public-repo completeness** + - Objective: Replace template documentation, add CI, and include only appropriate + governance files. + - Files: `README.md`, `.github/workflows/ci.yml`, `.editorconfig`, `LICENSE` as + justified, and tracked guidance updates. + - Depends on: T005, T009. + - Validation: documentation review; CI commands match local scripts. + +- [x] **T011 — Expand browser and API acceptance tests** + - Objective: Cover current content hierarchy, mobile nav, overflow, metadata routes, + contact errors, and form input preservation without redesigning the test suite. + - Files: `tests/e2e/**`, any focused test helpers. + - Depends on: T007, T009. + - Validation: Playwright on desktop/mobile and relevant route checks. + +## Phase 6 — Final validation and review + +- [x] **T012 — Run the complete verification matrix** + - Objective: Execute clean install, lint, typecheck, build, check, e2e, secret scan, + and internal-link/unused-source review. + - Files: `PROGRESS.md`, evidence/log files if needed. + - Depends on: T002–T011. + - Validation: record exact commands and results; failures remain explicit. + +- [x] **T013 — Final architectural review and handoff** + - Objective: Review the final tree as a public repository, remove only clearly stale + in-scope files, update progress, and report tradeoffs. + - Files: `PROGRESS.md`, any final scoped cleanup files. + - Depends on: T012. + - Validation: acceptance checklist complete or limitations documented. + +## Dependency graph + +```text +T001 → T002 → T003 ─┐ + ├→ T004 → T005 ─┐ + ├→ T006 → T007 ─┼→ T008 → T009 → T010 → T011 → T012 → T013 + └────────────────┘ +``` diff --git a/src/app/api/contact/route.ts b/src/app/api/contact/route.ts new file mode 100644 index 0000000..84a39ca --- /dev/null +++ b/src/app/api/contact/route.ts @@ -0,0 +1,61 @@ +import { NextRequest, NextResponse } from "next/server"; +import { consumeContactRequest } from "@/server/contact/rate-limit"; +import { parseContactInput } from "@/server/contact/validation"; +import { + getContactConfig, + sendContactMessage, +} from "@/server/contact/service"; + +export const runtime = "nodejs"; + +function jsonError(message: string, status: number, headers?: HeadersInit) { + return NextResponse.json({ success: false, message }, { status, headers }); +} + +function getClientKey(request: NextRequest): string { + const forwardedFor = request.headers.get("x-forwarded-for"); + return (forwardedFor?.split(",")[0]?.trim() || "unknown").slice(0, 100); +} + +export async function POST(request: NextRequest) { + let body: unknown; + try { + body = await request.json(); + } catch { + return jsonError("Request body must be valid JSON.", 400); + } + + const parsed = parseContactInput(body); + if (!parsed.ok) { + return jsonError(parsed.message, 400); + } + + if (parsed.honeypot) { + return jsonError("Unable to process this request.", 400); + } + + const limit = consumeContactRequest(getClientKey(request)); + if (!limit.allowed) { + return jsonError("Too many requests. Please try again later.", 429, { + "Retry-After": String(limit.retryAfterSeconds), + }); + } + + const config = getContactConfig(); + if (!config) { + console.error("Contact service is not configured"); + return jsonError("Contact service is temporarily unavailable.", 503); + } + + try { + await sendContactMessage(parsed.input, config); + } catch (error) { + console.error("Contact provider error", error instanceof Error ? error.message : "unknown"); + return jsonError("Unable to send your message right now. Please try again later.", 502); + } + + return NextResponse.json({ + success: true, + message: "Message sent successfully.", + }); +} \ No newline at end of file diff --git a/app/globals.css b/src/app/globals.css similarity index 100% rename from app/globals.css rename to src/app/globals.css diff --git a/src/app/layout.tsx b/src/app/layout.tsx new file mode 100644 index 0000000..dce755f --- /dev/null +++ b/src/app/layout.tsx @@ -0,0 +1,55 @@ +import type { Metadata } from "next"; +import { Inter } from "next/font/google"; +import { profile } from "@/content/profile"; +import { siteUrl } from "@/content/site"; +import CustomCursor from "@/components/client/CustomCursor"; +import "./globals.css"; + +const inter = Inter({ + subsets: ["latin"], + variable: "--font-inter", +}); + +export const metadata: Metadata = { + metadataBase: siteUrl, + title: { + default: profile.title + " — " + profile.name, + template: "%s — " + profile.name, + }, + description: profile.description, + alternates: { + canonical: "/", + }, + icons: { + icon: [{ url: "/logo.png", type: "image/png" }], + shortcut: "/logo.png", + apple: "/logo.png", + }, + openGraph: { + title: profile.title + " — " + profile.name, + description: profile.description, + url: siteUrl, + siteName: profile.name + " Portfolio", + type: "website", + images: [{ url: "/logo.png", alt: profile.name + " portfolio" }], + }, + twitter: { + card: "summary", + title: profile.title + " — " + profile.name, + description: profile.description, + images: ["/logo.png"], + }, +}; + +export default function RootLayout({ + children, +}: Readonly<{ children: React.ReactNode }>) { + return ( + + + + {children} + + + ); +} \ No newline at end of file diff --git a/app/page.tsx b/src/app/page.tsx similarity index 55% rename from app/page.tsx rename to src/app/page.tsx index c3407a7..df52a8f 100644 --- a/app/page.tsx +++ b/src/app/page.tsx @@ -1,22 +1,19 @@ -import Navbar from "@/components/nav/Navbar"; -import Hero from "@/components/hero/Hero"; -import About from "@/components/about/About"; -import Projects from "@/components/projects/Projects"; -import Skills from "@/components/skills/Skills"; -import Education from "@/components/education/Education"; -import ContactForm from "@/components/contact/ContactForm"; +import { profile } from "@/content/profile"; +import Navbar from "@/components/layout/Navbar"; +import Hero from "@/components/sections/hero/Hero"; +import About from "@/components/sections/about/About"; +import Projects from "@/components/sections/projects/Projects"; +import Skills from "@/components/sections/skills/Skills"; +import Education from "@/components/sections/education/Education"; +import ContactForm from "@/components/sections/contact/ContactForm"; const personJsonLd = { "@context": "https://schema.org", "@type": "Person", - name: "Anus Butt", - jobTitle: "AI Engineer and Full-stack Engineer", + name: profile.name, + jobTitle: profile.title, address: { "@type": "PostalAddress", addressCountry: "Pakistan" }, - sameAs: [ - "https://github.com/anusbutt", - "https://x.com/iamanusbutt", - "https://www.linkedin.com/in/anus-yousuf/", - ], + sameAs: profile.sameAs, }; export default function Home() { @@ -33,14 +30,12 @@ export default function Home() { - - {/* Footer */}
    -

    © {new Date().getFullYear()} Anus Butt

    +

    © {new Date().getFullYear()} {profile.name}

    Built with Next.js & Tailwind CSS

    ); -} +} \ No newline at end of file diff --git a/src/app/robots.ts b/src/app/robots.ts new file mode 100644 index 0000000..48df152 --- /dev/null +++ b/src/app/robots.ts @@ -0,0 +1,9 @@ +import type { MetadataRoute } from "next"; +import { siteUrl } from "@/content/site"; + +export default function robots(): MetadataRoute.Robots { + return { + rules: [{ userAgent: "*", allow: "/" }], + sitemap: new URL("/sitemap.xml", siteUrl).toString(), + }; +} \ No newline at end of file diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts new file mode 100644 index 0000000..9268db6 --- /dev/null +++ b/src/app/sitemap.ts @@ -0,0 +1,6 @@ +import type { MetadataRoute } from "next"; +import { siteUrl } from "@/content/site"; + +export default function sitemap(): MetadataRoute.Sitemap { + return [{ url: siteUrl.toString(), lastModified: new Date(), changeFrequency: "monthly", priority: 1 }]; +} \ No newline at end of file diff --git a/components/CustomCursor.tsx b/src/components/client/CustomCursor.tsx similarity index 98% rename from components/CustomCursor.tsx rename to src/components/client/CustomCursor.tsx index 41d865b..a738701 100644 --- a/components/CustomCursor.tsx +++ b/src/components/client/CustomCursor.tsx @@ -20,7 +20,7 @@ export default function CustomCursor() { useEffect(() => { // Detect touch device const mql = window.matchMedia("(pointer: coarse)"); - setIsTouchDevice(mql.matches); + queueMicrotask(() => setIsTouchDevice(mql.matches)); const handleMqlChange = (e: MediaQueryListEvent) => { setIsTouchDevice(e.matches); @@ -133,4 +133,4 @@ export default function CustomCursor() { /> ); -} +} \ No newline at end of file diff --git a/components/nav/Navbar.tsx b/src/components/layout/Navbar.tsx similarity index 95% rename from components/nav/Navbar.tsx rename to src/components/layout/Navbar.tsx index 56db91f..739c542 100644 --- a/components/nav/Navbar.tsx +++ b/src/components/layout/Navbar.tsx @@ -1,6 +1,7 @@ "use client"; import Image from "next/image"; +import { profile } from "@/content/profile"; import { useState } from "react"; const navLinks = [ @@ -22,11 +23,11 @@ export default function Navbar() { - Anus Butt + {profile.name} @@ -91,4 +92,4 @@ export default function Navbar() { )} ); -} +} \ No newline at end of file diff --git a/components/about/About.tsx b/src/components/sections/about/About.tsx similarity index 92% rename from components/about/About.tsx rename to src/components/sections/about/About.tsx index edf0aaf..fc21161 100644 --- a/components/about/About.tsx +++ b/src/components/sections/about/About.tsx @@ -1,8 +1,5 @@ -"use client"; - -import { motion } from "framer-motion"; import SectionHeading from "@/components/ui/SectionHeading"; -import { socialLinks } from "@/data/socials"; +import { socialLinks } from "@/content/socials"; function SocialIcon({ platform }: { platform: string }) { if (platform === "GitHub") { @@ -37,12 +34,8 @@ export default function About() { description="I work from system behavior and trust boundaries through APIs, data, interfaces, tests, and deployment." /> -

    Connect

    @@ -77,8 +70,8 @@ export default function About() { Founder of Omniveer.

    -
    + ); -} +} \ No newline at end of file diff --git a/components/contact/ContactForm.tsx b/src/components/sections/contact/ContactForm.tsx similarity index 99% rename from components/contact/ContactForm.tsx rename to src/components/sections/contact/ContactForm.tsx index 8772194..41d8316 100644 --- a/components/contact/ContactForm.tsx +++ b/src/components/sections/contact/ContactForm.tsx @@ -3,7 +3,7 @@ import { useState, FormEvent } from "react"; import { motion } from "framer-motion"; import SectionHeading from "@/components/ui/SectionHeading"; -import { socialLinks } from "@/data/socials"; +import { socialLinks } from "@/content/socials"; interface FormErrors { name?: string; @@ -251,4 +251,4 @@ export default function ContactForm() { ); -} +} \ No newline at end of file diff --git a/src/components/sections/education/Education.tsx b/src/components/sections/education/Education.tsx new file mode 100644 index 0000000..f2bbc13 --- /dev/null +++ b/src/components/sections/education/Education.tsx @@ -0,0 +1,20 @@ +import SectionHeading from "@/components/ui/SectionHeading"; +import { educationItems } from "@/content/education"; + +export default function Education() { + return ( +
    +
    + +
      + {educationItems.map((item) => ( +
    • +
    • + ))} +
    +
    +
    + ); +} \ No newline at end of file diff --git a/components/hero/Hero.tsx b/src/components/sections/hero/Hero.tsx similarity index 89% rename from components/hero/Hero.tsx rename to src/components/sections/hero/Hero.tsx index 4afbf60..22c2ecc 100644 --- a/components/hero/Hero.tsx +++ b/src/components/sections/hero/Hero.tsx @@ -1,6 +1,4 @@ -"use client"; - -import { motion } from "framer-motion"; +import { profile } from "@/content/profile"; export default function Hero() { return ( @@ -9,15 +7,12 @@ export default function Hero() { @@ -53,7 +48,7 @@ export default function Hero() { Discuss an opportunity - +
    AI agents & developer tools @@ -63,4 +58,4 @@ export default function Hero() {
    ); -} +} \ No newline at end of file diff --git a/components/projects/ProjectCard.tsx b/src/components/sections/projects/ProjectCard.tsx similarity index 92% rename from components/projects/ProjectCard.tsx rename to src/components/sections/projects/ProjectCard.tsx index d6a6713..7017f5f 100644 --- a/components/projects/ProjectCard.tsx +++ b/src/components/sections/projects/ProjectCard.tsx @@ -1,7 +1,4 @@ -"use client"; - -import { motion } from "framer-motion"; -import type { Project } from "@/data/projects"; +import type { Project } from "@/content/projects"; export default function ProjectCard({ project, @@ -11,17 +8,13 @@ export default function ProjectCard({ index: number; }) { return ( - {String(index + 1).padStart(2, "0")} @@ -100,6 +93,6 @@ export default function ProjectCard({ )} - + ); -} +} \ No newline at end of file diff --git a/components/projects/Projects.tsx b/src/components/sections/projects/Projects.tsx similarity index 97% rename from components/projects/Projects.tsx rename to src/components/sections/projects/Projects.tsx index fd2c7d1..69cc1d1 100644 --- a/components/projects/Projects.tsx +++ b/src/components/sections/projects/Projects.tsx @@ -1,8 +1,6 @@ -"use client"; - import SectionHeading from "@/components/ui/SectionHeading"; import ProjectCard from "./ProjectCard"; -import { moreProjects, projects } from "@/data/projects"; +import { moreProjects, projects } from "@/content/projects"; export default function Projects() { return ( @@ -73,4 +71,4 @@ export default function Projects() { ); -} +} \ No newline at end of file diff --git a/components/skills/Skills.tsx b/src/components/sections/skills/Skills.tsx similarity index 80% rename from components/skills/Skills.tsx rename to src/components/sections/skills/Skills.tsx index e6e9260..c4d6b0d 100644 --- a/components/skills/Skills.tsx +++ b/src/components/sections/skills/Skills.tsx @@ -1,8 +1,5 @@ -"use client"; - -import { motion } from "framer-motion"; import SectionHeading from "@/components/ui/SectionHeading"; -import { skillCategories } from "@/data/skills"; +import { skillCategories } from "@/content/skills"; export default function Skills() { return ( @@ -16,12 +13,8 @@ export default function Skills() {
    {skillCategories.map((category, catIndex) => ( - {String(catIndex + 1).padStart(2, "0")} @@ -38,10 +31,10 @@ export default function Skills() { ))} - +
    ))} ); -} +} \ No newline at end of file diff --git a/components/ui/SectionHeading.tsx b/src/components/ui/SectionHeading.tsx similarity index 99% rename from components/ui/SectionHeading.tsx rename to src/components/ui/SectionHeading.tsx index 1853672..0b46e8d 100644 --- a/components/ui/SectionHeading.tsx +++ b/src/components/ui/SectionHeading.tsx @@ -33,4 +33,4 @@ export default function SectionHeading({ )} ); -} +} \ No newline at end of file diff --git a/src/content/education.ts b/src/content/education.ts new file mode 100644 index 0000000..fdc5871 --- /dev/null +++ b/src/content/education.ts @@ -0,0 +1,5 @@ +export const educationItems = [ + "ADC Part 1 — Aisha Bawany College / University of Karachi", + "Agentic AI and software engineering training — GIAIC / PIAIC", + "Focus on building production-oriented AI systems", +] as const; \ No newline at end of file diff --git a/src/content/profile.ts b/src/content/profile.ts new file mode 100644 index 0000000..16e144f --- /dev/null +++ b/src/content/profile.ts @@ -0,0 +1,26 @@ +export interface Profile { + name: string; + title: string; + shortTitle: string; + description: string; + location: string; + availability: string; + siteUrl: string; + sameAs: string[]; +} + +export const profile: Profile = { + name: "Anus Butt", + title: "AI Engineer & Full-stack Engineer", + shortTitle: "AI Engineer + Full-stack Engineer", + description: + "AI engineer and full-stack engineer building auditable agent systems, developer tools, and production web applications with TypeScript, Python, FastAPI, and PostgreSQL.", + location: "Karachi, Pakistan", + availability: "Open to AI & full-stack roles", + siteUrl: process.env.NEXT_PUBLIC_SITE_URL ?? "https://anusbutt.com", + sameAs: [ + "https://github.com/anusbutt", + "https://x.com/iamanusbutt", + "https://www.linkedin.com/in/anus-yousuf/", + ], +}; \ No newline at end of file diff --git a/data/projects.ts b/src/content/projects.ts similarity index 99% rename from data/projects.ts rename to src/content/projects.ts index 89a15c4..03daf9c 100644 --- a/data/projects.ts +++ b/src/content/projects.ts @@ -112,4 +112,4 @@ export const moreProjects: Project[] = [ techStack: ["Python CLI", "AI tool use", "Evidence validation", "Human approval"], githubUrl: "https://github.com/anusbutt/Prospector", }, -]; +]; \ No newline at end of file diff --git a/src/content/site.ts b/src/content/site.ts new file mode 100644 index 0000000..8855514 --- /dev/null +++ b/src/content/site.ts @@ -0,0 +1,3 @@ +import { profile } from "@/content/profile"; + +export const siteUrl = new URL(profile.siteUrl); \ No newline at end of file diff --git a/data/skills.ts b/src/content/skills.ts similarity index 99% rename from data/skills.ts rename to src/content/skills.ts index 6770cc0..00191bb 100644 --- a/data/skills.ts +++ b/src/content/skills.ts @@ -16,4 +16,4 @@ export const skillCategories: SkillCategory[] = [ name: "AI & Developer Tools", skills: ["AI agents", "Tool use", "Codex", "Claude Code", "Git & GitHub"], }, -]; +]; \ No newline at end of file diff --git a/data/socials.ts b/src/content/socials.ts similarity index 99% rename from data/socials.ts rename to src/content/socials.ts index ebb38fc..64b4b97 100644 --- a/data/socials.ts +++ b/src/content/socials.ts @@ -20,4 +20,4 @@ export const socialLinks: SocialLink[] = [ url: "https://x.com/iamanusbutt", label: "@iamanusbutt", }, -]; +]; \ No newline at end of file diff --git a/src/server/contact/rate-limit.ts b/src/server/contact/rate-limit.ts new file mode 100644 index 0000000..08889fc --- /dev/null +++ b/src/server/contact/rate-limit.ts @@ -0,0 +1,36 @@ +interface Entry { + count: number; + resetAt: number; +} + +const windowMs = 15 * 60 * 1000; +const maxRequests = 5; +const entries = new Map(); + +function prune(now: number): void { + entries.forEach((entry, key) => { + if (entry.resetAt <= now) { + entries.delete(key); + } + }); +} + +export function consumeContactRequest( + key: string, + now = Date.now(), +): { allowed: true } | { allowed: false; retryAfterSeconds: number } { + prune(now); + const current = entries.get(key); + if (!current || current.resetAt <= now) { + entries.set(key, { count: 1, resetAt: now + windowMs }); + return { allowed: true }; + } + if (current.count >= maxRequests) { + return { + allowed: false, + retryAfterSeconds: Math.max(1, Math.ceil((current.resetAt - now) / 1000)), + }; + } + current.count += 1; + return { allowed: true }; +} \ No newline at end of file diff --git a/src/server/contact/service.ts b/src/server/contact/service.ts new file mode 100644 index 0000000..5793961 --- /dev/null +++ b/src/server/contact/service.ts @@ -0,0 +1,36 @@ +import { getResend } from "@/server/email/resend"; +import type { ContactInput } from "@/server/contact/validation"; + +interface ContactConfig { + from: string; + to: string; +} + +export function getContactConfig(): ContactConfig | null { + const from = process.env.CONTACT_FROM_EMAIL; + const to = process.env.CONTACT_TO_EMAIL; + if (!process.env.RESEND_API_KEY || !from || !to) { + return null; + } + return { from, to }; +} + +export async function sendContactMessage( + input: ContactInput, + config: ContactConfig, +): Promise { + const result = await getResend().emails.send({ + from: config.from, + to: config.to, + subject: "Portfolio contact message", + replyTo: input.email, + text: + "Name: " + input.name + String.fromCharCode(10) + + "Email: " + input.email + String.fromCharCode(10, 10) + + "Message:" + String.fromCharCode(10) + input.message, + }); + + if (result.error) { + throw new Error("Resend rejected the contact message"); + } +} \ No newline at end of file diff --git a/src/server/contact/validation.ts b/src/server/contact/validation.ts new file mode 100644 index 0000000..066bd06 --- /dev/null +++ b/src/server/contact/validation.ts @@ -0,0 +1,71 @@ +export interface ContactInput { + name: string; + email: string; + message: string; +} + +interface ContactPayload { + name?: unknown; + email?: unknown; + message?: unknown; + website?: unknown; +} + +const allowedKeys = new Set(["name", "email", "message", "website"]); +const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +export function parseContactInput(value: unknown): + | { ok: true; input: ContactInput; honeypot: boolean } + | { ok: false; message: string } { + if (!isRecord(value)) { + return { ok: false, message: "Request body must be a JSON object." }; + } + + const payload = value as ContactPayload; + if ([...Object.keys(payload)].some((key) => !allowedKeys.has(key))) { + return { ok: false, message: "Request contains unsupported fields." }; + } + + if ( + typeof payload.name !== "string" || + typeof payload.email !== "string" || + typeof payload.message !== "string" + ) { + return { ok: false, message: "Name, email, and message are required." }; + } + + const input: ContactInput = { + name: payload.name.trim(), + email: payload.email.trim().toLowerCase(), + message: payload.message.trim(), + }; + + if (input.name.length === 0) { + return { ok: false, message: "Name is required." }; + } + if (input.name.length > 100) { + return { ok: false, message: "Name must be 100 characters or less." }; + } + if (input.email.length === 0) { + return { ok: false, message: "Email is required." }; + } + if (input.email.length > 254 || !emailPattern.test(input.email)) { + return { ok: false, message: "Please enter a valid email address." }; + } + if (input.message.length === 0) { + return { ok: false, message: "Message is required." }; + } + if (input.message.length > 2000) { + return { ok: false, message: "Message must be 2000 characters or less." }; + } + + return { + ok: true, + input, + honeypot: typeof payload.website === "string" && payload.website.trim().length > 0, + }; +} \ No newline at end of file diff --git a/src/server/email/resend.ts b/src/server/email/resend.ts new file mode 100644 index 0000000..1ff46e5 --- /dev/null +++ b/src/server/email/resend.ts @@ -0,0 +1,12 @@ +import { Resend } from "resend"; + +let resendInstance: Resend | null = null; + +export function getResend(): Resend { + const apiKey = process.env.RESEND_API_KEY; + if (!apiKey) { + throw new Error("RESEND_API_KEY is not configured"); + } + resendInstance ??= new Resend(apiKey); + return resendInstance; +} \ No newline at end of file diff --git a/tailwind.config.ts b/tailwind.config.ts index 5b11339..3ffc82b 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,11 +1,7 @@ import type { Config } from "tailwindcss"; const config: Config = { - content: [ - "./pages/**/*.{js,ts,jsx,tsx,mdx}", - "./components/**/*.{js,ts,jsx,tsx,mdx}", - "./app/**/*.{js,ts,jsx,tsx,mdx}", - ], + content: ["./src/**/*.{js,ts,jsx,tsx,mdx}"], theme: { extend: { colors: { @@ -20,4 +16,4 @@ const config: Config = { }, plugins: [], }; -export default config; +export default config; \ No newline at end of file diff --git a/tests/contact.spec.ts b/tests/contact.spec.ts new file mode 100644 index 0000000..0bf2af0 --- /dev/null +++ b/tests/contact.spec.ts @@ -0,0 +1,35 @@ +import { expect, test } from "@playwright/test"; + +test.describe("contact API boundary", () => { + test("rejects malformed JSON", async ({ request }) => { + const response = await request.post("/api/contact", { + data: "not-json", + headers: { "Content-Type": "application/json" }, + }); + expect(response.status()).toBe(400); + await expect(response.json()).resolves.toMatchObject({ success: false }); + }); + + test("rejects invalid contact input", async ({ request }) => { + const response = await request.post("/api/contact", { + data: { name: "", email: "invalid", message: "" }, + }); + expect(response.status()).toBe(400); + await expect(response.json()).resolves.toMatchObject({ success: false }); + }); + + test("reports missing email configuration without exposing server details", async ({ request }) => { + const response = await request.post("/api/contact", { + data: { + name: "Test visitor", + email: "visitor@example.com", + message: "Hello from an automated acceptance test.", + }, + }); + expect(response.status()).toBe(503); + await expect(response.json()).resolves.toEqual({ + success: false, + message: "Contact service is temporarily unavailable.", + }); + }); +}); \ No newline at end of file diff --git a/tests/seo.spec.ts b/tests/seo.spec.ts new file mode 100644 index 0000000..43ab572 --- /dev/null +++ b/tests/seo.spec.ts @@ -0,0 +1,17 @@ +import { expect, test } from "@playwright/test"; + +test("metadata and SEO routes are available", async ({ request }) => { + const robots = await request.get("/robots.txt"); + expect(robots.ok()).toBe(true); + expect(await robots.text()).toContain("Sitemap:"); + + const sitemap = await request.get("/sitemap.xml"); + expect(sitemap.ok()).toBe(true); + expect(await sitemap.text()).toContain(""); + + const response = await request.get("/"); + expect(response.ok()).toBe(true); + const html = await response.text(); + expect(html).toContain('rel="canonical"'); + expect(html).toContain('property="og:title"'); +}); \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index e7ff90f..432d5f0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,10 @@ { "compilerOptions": { - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -10,7 +14,7 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", + "jsx": "react-jsx", "incremental": true, "plugins": [ { @@ -18,9 +22,21 @@ } ], "paths": { - "@/*": ["./*"] - } + "@/*": [ + "./src/*" + ] + }, + "target": "ES2017" }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "include": [ + "next-env.d.ts", + "src/**/*.ts", + "src/**/*.tsx", + "tests/**/*.ts", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] }