Browse Source

feat: initial Jenado Unlimited website

- Next.js 16.3 + React 19 + TypeScript + Tailwind CSS 4
- ParallaxHero and ParallaxBand components with scroll effects
- Pages: Home, About, Contact, Gallery, Offerings, Privacy, Terms
- Offerings verticals: honey-bees, personal-training, sourdough, 3d-printing, laser-engraving, farm-to-table, recreation-apps
- Centralized page content in src/content/pages/ (barrel + per-page files)
- Domain content in src/content/verticals/
- Contact form with API route (/api/contact)
- Vitest + @testing-library/react with colocated *.test.* files (41 tests)
- JSON-LD structured data helpers
- Full static generation (18 routes)
- Custom components: Header, Footer, CTABand, GalleryGrid, PillarStrip, VerticalCard, ThemeToggle, etc.
- Responsive design, accessibility (skip links, ARIA), dark mode support

Co-authored-by: Timothy Pomeroy <tpomeroy@us.ibm.com>
Timothy Pomeroy 4 ngày trước cách đây
mục cha
commit
178d0a8f3c
87 tập tin đã thay đổi với 10147 bổ sung117 xóa
  1. 8 1
      next.config.ts
  2. 289 16
      package-lock.json
  3. 18 3
      package.json
  4. 5473 0
      pnpm-lock.yaml
  5. 4 0
      pnpm-workspace.yaml
  6. 0 1
      public/file.svg
  7. 0 1
      public/globe.svg
  8. BIN
      public/images/3d-printing.jpg
  9. BIN
      public/images/farm-to-table.jpg
  10. BIN
      public/images/gallery-honey.jpg
  11. BIN
      public/images/gallery-sourdough.jpg
  12. BIN
      public/images/gallery-training.jpg
  13. BIN
      public/images/hero-about.jpg
  14. BIN
      public/images/hero-contact.jpg
  15. BIN
      public/images/hero-gallery.jpg
  16. BIN
      public/images/hero-home.jpg
  17. BIN
      public/images/hero-offerings.jpg
  18. BIN
      public/images/hero-privacy.jpg
  19. BIN
      public/images/hero-terms.jpg
  20. BIN
      public/images/honey-bees.jpg
  21. BIN
      public/images/laser-engraving.jpg
  22. BIN
      public/images/personal-training.jpg
  23. BIN
      public/images/recreation-apps.jpg
  24. BIN
      public/images/sourdough.jpg
  25. BIN
      public/logo.png
  26. 2 0
      public/logo.svg
  27. 0 1
      public/next.svg
  28. 0 1
      public/vercel.svg
  29. 0 1
      public/window.svg
  30. 187 0
      src/app/about/page.tsx
  31. 96 0
      src/app/api/contact/route.ts
  32. 226 0
      src/app/contact/page.tsx
  33. 136 0
      src/app/gallery/page.tsx
  34. 169 15
      src/app/globals.css
  35. 44 16
      src/app/layout.tsx
  36. 22 0
      src/app/not-found.tsx
  37. 117 0
      src/app/offerings/[slug]/page.tsx
  38. 147 0
      src/app/offerings/page.tsx
  39. 124 61
      src/app/page.tsx
  40. 513 0
      src/app/privacy/page.tsx
  41. 551 0
      src/app/terms/page.tsx
  42. 40 0
      src/components/CTABand.test.tsx
  43. 39 0
      src/components/CTABand.tsx
  44. 162 0
      src/components/ContactForm.tsx
  45. 75 0
      src/components/Footer.tsx
  46. 81 0
      src/components/GalleryGrid.tsx
  47. 49 0
      src/components/Header.tsx
  48. 33 0
      src/components/Logo.test.tsx
  49. 51 0
      src/components/Logo.tsx
  50. 29 0
      src/components/NavLinks.tsx
  51. 83 0
      src/components/ParallaxBand.tsx
  52. 118 0
      src/components/ParallaxHero.tsx
  53. 19 0
      src/components/PillarStrip.test.tsx
  54. 33 0
      src/components/PillarStrip.tsx
  55. 9 0
      src/components/SkipToContent.tsx
  56. 59 0
      src/components/ThemeToggle.tsx
  57. 39 0
      src/components/VerticalCard.test.tsx
  58. 111 0
      src/components/VerticalCard.tsx
  59. 71 0
      src/content/pages/about.ts
  60. 52 0
      src/content/pages/contact.ts
  61. 40 0
      src/content/pages/gallery.ts
  62. 16 0
      src/content/pages/home.ts
  63. 32 0
      src/content/pages/index.ts
  64. 44 0
      src/content/pages/offerings.ts
  65. 18 0
      src/content/pages/privacy.ts
  66. 17 0
      src/content/pages/terms.ts
  67. 54 0
      src/content/pages/types.ts
  68. 13 0
      src/content/verticals/3d-printing.ts
  69. 7 0
      src/content/verticals/all.ts
  70. 13 0
      src/content/verticals/farm-to-table.ts
  71. 15 0
      src/content/verticals/honey-bees.ts
  72. 13 0
      src/content/verticals/laser-engraving.ts
  73. 13 0
      src/content/verticals/personal-training.ts
  74. 13 0
      src/content/verticals/recreation-apps.ts
  75. 13 0
      src/content/verticals/sourdough.ts
  76. 103 0
      src/lib/contact.test.ts
  77. 26 0
      src/lib/contact.ts
  78. 90 0
      src/lib/content.test.ts
  79. 41 0
      src/lib/content.ts
  80. 3 0
      src/lib/email.ts
  81. 40 0
      src/lib/gallery.test.ts
  82. 85 0
      src/lib/gallery.ts
  83. 39 0
      src/lib/json-ld.test.ts
  84. 27 0
      src/lib/json-ld.ts
  85. 52 0
      src/types/index.ts
  86. 22 0
      vitest.config.ts
  87. 19 0
      vitest.setup.ts

+ 8 - 1
next.config.ts

@@ -1,7 +1,14 @@
 import type { NextConfig } from "next";
 
 const nextConfig: NextConfig = {
-  /* config options here */
+  images: {
+    remotePatterns: [
+      {
+        protocol: "https",
+        hostname: "**",
+      },
+    ],
+  },
 };
 
 export default nextConfig;

+ 289 - 16
package-lock.json

@@ -8,9 +8,14 @@
       "name": "jenado-unlimited-website",
       "version": "0.1.0",
       "dependencies": {
+        "@hookform/resolvers": "^5.7.1",
+        "lucide-react": "^1.31.0",
         "next": "16.3.0",
         "react": "19.2.8",
-        "react-dom": "19.2.8"
+        "react-dom": "19.2.8",
+        "react-hook-form": "^7.85.0",
+        "resend": "^6.19.0",
+        "zod": "^4.4.3"
       },
       "devDependencies": {
         "@tailwindcss/postcss": "^4",
@@ -416,6 +421,30 @@
         "url": "https://opencollective.com/eslint"
       }
     },
+    "node_modules/@eslint/eslintrc/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": {
+        "fast-deep-equal": "^3.1.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/@eslint/eslintrc/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"
+    },
     "node_modules/@eslint/js": {
       "version": "9.39.5",
       "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz",
@@ -453,6 +482,116 @@
         "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
       }
     },
+    "node_modules/@hookform/resolvers": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.7.1.tgz",
+      "integrity": "sha512-8wS/P4UDr5sQDe4nFaV51TVyfDPrWgNIXweqG0Bs9Z5LSuzKLb+RQNPvkN2oHM5SRrJyWrVH/F+LOUcFjUyvwQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@standard-schema/utils": "^0.3.0"
+      },
+      "peerDependencies": {
+        "@sinclair/typebox": ">=0.25.24",
+        "@standard-schema/spec": "^1.0.0",
+        "@typeschema/main": ">=0.13.7",
+        "@vinejs/vine": "^2.0.0 || ^3.0.0 || ^4.0.0",
+        "ajv": "^8.12.0",
+        "ajv-errors": "^3.0.0",
+        "ajv-formats": "^2.1.1",
+        "arktype": "^2.0.0",
+        "ata-validator": "^1.2.0",
+        "class-transformer": ">=0.4.0",
+        "class-validator": ">=0.12.0",
+        "computed-types": "^1.0.0",
+        "effect": "^3.10.3",
+        "fluentvalidation-ts": "^3.0.0",
+        "fp-ts": "^2.7.0",
+        "io-ts": "^2.0.0",
+        "joi": "^17.0.0",
+        "nope-validator": ">=0.12.0",
+        "react-hook-form": "^7.55.0",
+        "superstruct": ">=0.12.0",
+        "typanion": "^3.3.2",
+        "valibot": ">=0.31.0 || ^1.0.0-beta.4 || ^1.0.0-rc",
+        "vest": ">=3.0.0",
+        "yup": "^1.0.0",
+        "zod": "^3.25.0 || ^4.0.0"
+      },
+      "peerDependenciesMeta": {
+        "@sinclair/typebox": {
+          "optional": true
+        },
+        "@standard-schema/spec": {
+          "optional": true
+        },
+        "@typeschema/main": {
+          "optional": true
+        },
+        "@vinejs/vine": {
+          "optional": true
+        },
+        "ajv": {
+          "optional": true
+        },
+        "ajv-errors": {
+          "optional": true
+        },
+        "ajv-formats": {
+          "optional": true
+        },
+        "arktype": {
+          "optional": true
+        },
+        "ata-validator": {
+          "optional": true
+        },
+        "class-transformer": {
+          "optional": true
+        },
+        "class-validator": {
+          "optional": true
+        },
+        "computed-types": {
+          "optional": true
+        },
+        "effect": {
+          "optional": true
+        },
+        "fluentvalidation-ts": {
+          "optional": true
+        },
+        "fp-ts": {
+          "optional": true
+        },
+        "io-ts": {
+          "optional": true
+        },
+        "joi": {
+          "optional": true
+        },
+        "nope-validator": {
+          "optional": true
+        },
+        "superstruct": {
+          "optional": true
+        },
+        "typanion": {
+          "optional": true
+        },
+        "valibot": {
+          "optional": true
+        },
+        "vest": {
+          "optional": true
+        },
+        "yup": {
+          "optional": true
+        },
+        "zod": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/@humanfs/core": {
       "version": "0.19.2",
       "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz",
@@ -1324,6 +1463,18 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/@stablelib/base64": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@stablelib/base64/-/base64-1.0.1.tgz",
+      "integrity": "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==",
+      "license": "MIT"
+    },
+    "node_modules/@standard-schema/utils": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz",
+      "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==",
+      "license": "MIT"
+    },
     "node_modules/@swc/helpers": {
       "version": "0.5.15",
       "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
@@ -2309,16 +2460,17 @@
       }
     },
     "node_modules/ajv": {
-      "version": "6.15.0",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
-      "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==",
-      "dev": true,
+      "version": "8.20.0",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+      "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
       "license": "MIT",
+      "optional": true,
+      "peer": true,
       "dependencies": {
-        "fast-deep-equal": "^3.1.1",
-        "fast-json-stable-stringify": "^2.0.0",
-        "json-schema-traverse": "^0.4.1",
-        "uri-js": "^4.2.2"
+        "fast-deep-equal": "^3.1.3",
+        "fast-uri": "^3.0.1",
+        "json-schema-traverse": "^1.0.0",
+        "require-from-string": "^2.0.2"
       },
       "funding": {
         "type": "github",
@@ -3559,6 +3711,30 @@
         "url": "https://opencollective.com/eslint"
       }
     },
+    "node_modules/eslint/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": {
+        "fast-deep-equal": "^3.1.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/eslint/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"
+    },
     "node_modules/espree": {
       "version": "10.4.0",
       "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
@@ -3627,7 +3803,7 @@
       "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,
+      "devOptional": true,
       "license": "MIT"
     },
     "node_modules/fast-glob": {
@@ -3674,6 +3850,30 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/fast-sha256": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/fast-sha256/-/fast-sha256-1.3.0.tgz",
+      "integrity": "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==",
+      "license": "Unlicense"
+    },
+    "node_modules/fast-uri": {
+      "version": "3.1.5",
+      "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz",
+      "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/fastify"
+        },
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/fastify"
+        }
+      ],
+      "license": "BSD-3-Clause",
+      "optional": true,
+      "peer": true
+    },
     "node_modules/fastq": {
       "version": "1.20.1",
       "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
@@ -4648,11 +4848,12 @@
       "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"
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+      "license": "MIT",
+      "optional": true,
+      "peer": true
     },
     "node_modules/json-stable-stringify-without-jsonify": {
       "version": "1.0.1",
@@ -5041,6 +5242,15 @@
         "yallist": "^3.0.2"
       }
     },
+    "node_modules/lucide-react": {
+      "version": "1.31.0",
+      "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.31.0.tgz",
+      "integrity": "sha512-G8u2eEtoHUnUa9f8lbvqDhCiORMnYLdUEo06EEG9MQvHQrInKcX3Pa2TH39MM5qyzRcWETxB0+aOwAPI1g1kEg==",
+      "license": "ISC",
+      "peerDependencies": {
+        "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+      }
+    },
     "node_modules/magic-string": {
       "version": "0.30.21",
       "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
@@ -5527,6 +5737,12 @@
         "node": ">= 0.4"
       }
     },
+    "node_modules/postal-mime": {
+      "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.26",
       "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz",
@@ -5630,6 +5846,22 @@
         "react": "^19.2.8"
       }
     },
+    "node_modules/react-hook-form": {
+      "version": "7.85.0",
+      "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.85.0.tgz",
+      "integrity": "sha512-U2MTriFXnclmV4rOE20p2DcRFv5WEg3FIcBFOKcOLFHDVvGIMPvLTkTWefUsonmlaVy23khVDxDWym6uJVGOzw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=18.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/react-hook-form"
+      },
+      "peerDependencies": {
+        "react": "^16.8.0 || ^17 || ^18 || ^19"
+      }
+    },
     "node_modules/react-is": {
       "version": "16.13.1",
       "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -5681,6 +5913,38 @@
         "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",
+      "optional": true,
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/resend": {
+      "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.5",
+        "standardwebhooks": "1.0.0"
+      },
+      "engines": {
+        "node": ">=20"
+      },
+      "peerDependencies": {
+        "@react-email/render": "*"
+      },
+      "peerDependenciesMeta": {
+        "@react-email/render": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/resolve": {
       "version": "2.0.0-next.7",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz",
@@ -6058,6 +6322,16 @@
       "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/stop-iteration-iterator": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
@@ -6758,7 +7032,6 @@
       "version": "4.4.3",
       "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz",
       "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==",
-      "dev": true,
       "license": "MIT",
       "funding": {
         "url": "https://github.com/sponsors/colinhacks"

+ 18 - 3
package.json

@@ -6,21 +6,36 @@
     "dev": "next dev",
     "build": "next build",
     "start": "next start",
-    "lint": "eslint"
+    "lint": "eslint",
+    "test": "vitest run",
+    "test:watch": "vitest",
+    "test:ui": "vitest --ui",
+    "test:coverage": "vitest run --coverage"
   },
   "dependencies": {
+    "@hookform/resolvers": "^5.7.1",
+    "lucide-react": "^1.31.0",
     "next": "16.3.0",
     "react": "19.2.8",
-    "react-dom": "19.2.8"
+    "react-dom": "19.2.8",
+    "react-hook-form": "^7.85.0",
+    "resend": "^6.19.0",
+    "zod": "^4.4.3"
   },
   "devDependencies": {
     "@tailwindcss/postcss": "^4",
+    "@testing-library/jest-dom": "^7.0.1",
+    "@testing-library/react": "^16.3.2",
+    "@testing-library/user-event": "^14.6.3",
     "@types/node": "^20",
     "@types/react": "^19",
     "@types/react-dom": "^19",
+    "@vitejs/plugin-react": "^6.0.5",
     "eslint": "^9",
     "eslint-config-next": "16.3.0",
+    "jsdom": "^30.0.1",
     "tailwindcss": "^4",
-    "typescript": "^5"
+    "typescript": "^5",
+    "vitest": "^4.1.10"
   }
 }

+ 5473 - 0
pnpm-lock.yaml

@@ -0,0 +1,5473 @@
+lockfileVersion: '9.0'
+
+settings:
+  autoInstallPeers: true
+  excludeLinksFromLockfile: false
+
+importers:
+
+  .:
+    dependencies:
+      '@hookform/resolvers':
+        specifier: ^5.7.1
+        version: 5.7.1(@standard-schema/spec@1.1.0)(react-hook-form@7.85.0(react@19.2.8))(zod@4.4.3)
+      lucide-react:
+        specifier: ^1.31.0
+        version: 1.31.0(react@19.2.8)
+      next:
+        specifier: 16.3.0
+        version: 16.3.0(@babel/core@7.29.7(supports-color@7.2.0))(@types/node@20.19.43)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+      react:
+        specifier: 19.2.8
+        version: 19.2.8
+      react-dom:
+        specifier: 19.2.8
+        version: 19.2.8(react@19.2.8)
+      react-hook-form:
+        specifier: ^7.85.0
+        version: 7.85.0(react@19.2.8)
+      resend:
+        specifier: ^6.19.0
+        version: 6.19.0
+      zod:
+        specifier: ^4.4.3
+        version: 4.4.3
+    devDependencies:
+      '@tailwindcss/postcss':
+        specifier: ^4
+        version: 4.3.3
+      '@testing-library/jest-dom':
+        specifier: ^7.0.1
+        version: 7.0.1(@testing-library/dom@10.4.1)(vitest@4.1.10(@types/node@20.19.43)(jsdom@30.0.1)(vite@8.2.1(@types/node@20.19.43)(jiti@2.7.0)))
+      '@testing-library/react':
+        specifier: ^16.3.2
+        version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+      '@testing-library/user-event':
+        specifier: ^14.6.3
+        version: 14.6.3(@testing-library/dom@10.4.1)
+      '@types/node':
+        specifier: ^20
+        version: 20.19.43
+      '@types/react':
+        specifier: ^19
+        version: 19.2.18
+      '@types/react-dom':
+        specifier: ^19
+        version: 19.2.4(@types/react@19.2.18)
+      '@vitejs/plugin-react':
+        specifier: ^6.0.5
+        version: 6.0.5(vite@8.2.1(@types/node@20.19.43)(jiti@2.7.0))
+      eslint:
+        specifier: ^9
+        version: 9.39.5(jiti@2.7.0)(supports-color@7.2.0)
+      eslint-config-next:
+        specifier: 16.3.0
+        version: 16.3.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
+      jsdom:
+        specifier: ^30.0.1
+        version: 30.0.1
+      tailwindcss:
+        specifier: ^4
+        version: 4.3.3
+      typescript:
+        specifier: ^5
+        version: 5.9.3
+      vitest:
+        specifier: ^4.1.10
+        version: 4.1.10(@types/node@20.19.43)(jsdom@30.0.1)(vite@8.2.1(@types/node@20.19.43)(jiti@2.7.0))
+
+packages:
+
+  '@adobe/css-tools@4.5.0':
+    resolution: {integrity: sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==}
+
+  '@alloc/quick-lru@5.2.0':
+    resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
+    engines: {node: '>=10'}
+
+  '@asamuzakjp/css-color@6.0.7':
+    resolution: {integrity: sha512-vC/bk1Lz7Tn/EfU9/apOTBk80/8dyGyWMowPoV1tJ52muDGsDqt2HPT2klrFUiY60MQmQv9q8yIht15JnBgDGw==}
+    engines: {node: ^22.13.0 || >=24.0.0}
+
+  '@asamuzakjp/dom-selector@8.3.2':
+    resolution: {integrity: sha512-93Z1N+BQNXysodoicpOIyNh2drHfz/CTf9nnT0FEx72GJcIiwgydD7tGAr78j41LsYn3hlRn+LdGPuBLn1Bl8Q==}
+    engines: {node: ^22.13.0 || >=24.0.0}
+
+  '@babel/code-frame@7.29.7':
+    resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/compat-data@7.29.7':
+    resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/core@7.29.7':
+    resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/generator@7.29.8':
+    resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-compilation-targets@7.29.7':
+    resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-globals@7.29.7':
+    resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-module-imports@7.29.7':
+    resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-module-transforms@7.29.7':
+    resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0
+
+  '@babel/helper-string-parser@7.29.7':
+    resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-validator-identifier@7.29.7':
+    resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helper-validator-option@7.29.7':
+    resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/helpers@7.29.7':
+    resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/parser@7.29.8':
+    resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==}
+    engines: {node: '>=6.0.0'}
+    hasBin: true
+
+  '@babel/runtime@7.29.7':
+    resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/template@7.29.7':
+    resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/traverse@7.29.8':
+    resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==}
+    engines: {node: '>=6.9.0'}
+
+  '@babel/types@7.29.8':
+    resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==}
+    engines: {node: '>=6.9.0'}
+
+  '@bramus/specificity@2.4.2':
+    resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==}
+    hasBin: true
+
+  '@csstools/color-helpers@6.1.0':
+    resolution: {integrity: sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg==}
+    engines: {node: '>=20.19.0'}
+
+  '@csstools/css-calc@3.3.0':
+    resolution: {integrity: sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==}
+    engines: {node: '>=20.19.0'}
+    peerDependencies:
+      '@csstools/css-parser-algorithms': ^4.0.0
+      '@csstools/css-tokenizer': ^4.0.0
+
+  '@csstools/css-color-parser@4.1.10':
+    resolution: {integrity: sha512-UZhQLIUyJaaMepqehrCODwCg2KW25vFvLWBmqYFaPclYvvxzj/sG8LBOhBFCp11i9uE7t1EyS+RAoV9tztPFyw==}
+    engines: {node: '>=20.19.0'}
+    peerDependencies:
+      '@csstools/css-parser-algorithms': ^4.0.0
+      '@csstools/css-tokenizer': ^4.0.0
+
+  '@csstools/css-parser-algorithms@4.0.0':
+    resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==}
+    engines: {node: '>=20.19.0'}
+    peerDependencies:
+      '@csstools/css-tokenizer': ^4.0.0
+
+  '@csstools/css-syntax-patches-for-csstree@1.1.7':
+    resolution: {integrity: sha512-fQ+05118eQS1cofO3aJpB5efgpBZMvIzwr/sbC8kDLVA5XLG8q1kJV5yzrUAI1f7lvhPnm8fgIjzFB8/O/5Dig==}
+    peerDependencies:
+      css-tree: ^3.2.1
+    peerDependenciesMeta:
+      css-tree:
+        optional: true
+
+  '@csstools/css-tokenizer@4.0.0':
+    resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==}
+    engines: {node: '>=20.19.0'}
+
+  '@emnapi/core@1.10.0':
+    resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==}
+
+  '@emnapi/runtime@1.10.0':
+    resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==}
+
+  '@emnapi/runtime@1.11.3':
+    resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==}
+
+  '@emnapi/wasi-threads@1.2.1':
+    resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==}
+
+  '@eslint-community/eslint-utils@4.10.1':
+    resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    peerDependencies:
+      eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+
+  '@eslint-community/eslint-utils@4.9.1':
+    resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    peerDependencies:
+      eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+
+  '@eslint-community/regexpp@4.12.2':
+    resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==}
+    engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+
+  '@eslint/config-array@0.21.2':
+    resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@eslint/config-helpers@0.4.2':
+    resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@eslint/core@0.17.0':
+    resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@eslint/eslintrc@3.3.6':
+    resolution: {integrity: sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@eslint/js@9.39.5':
+    resolution: {integrity: sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@eslint/object-schema@2.1.7':
+    resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@eslint/plugin-kit@0.4.1':
+    resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@exodus/bytes@1.15.1':
+    resolution: {integrity: sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==}
+    engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
+    peerDependencies:
+      '@noble/hashes': ^1.8.0 || ^2.0.0
+    peerDependenciesMeta:
+      '@noble/hashes':
+        optional: true
+
+  '@hookform/resolvers@5.7.1':
+    resolution: {integrity: sha512-8wS/P4UDr5sQDe4nFaV51TVyfDPrWgNIXweqG0Bs9Z5LSuzKLb+RQNPvkN2oHM5SRrJyWrVH/F+LOUcFjUyvwQ==}
+    peerDependencies:
+      '@sinclair/typebox': '>=0.25.24'
+      '@standard-schema/spec': ^1.0.0
+      '@typeschema/main': '>=0.13.7'
+      '@vinejs/vine': ^2.0.0 || ^3.0.0 || ^4.0.0
+      ajv: ^8.12.0
+      ajv-errors: ^3.0.0
+      ajv-formats: ^2.1.1
+      arktype: ^2.0.0
+      ata-validator: ^1.2.0
+      class-transformer: '>=0.4.0'
+      class-validator: '>=0.12.0'
+      computed-types: ^1.0.0
+      effect: ^3.10.3
+      fluentvalidation-ts: ^3.0.0
+      fp-ts: ^2.7.0
+      io-ts: ^2.0.0
+      joi: ^17.0.0
+      nope-validator: '>=0.12.0'
+      react-hook-form: ^7.55.0
+      superstruct: '>=0.12.0'
+      typanion: ^3.3.2
+      valibot: '>=0.31.0 || ^1.0.0-beta.4 || ^1.0.0-rc'
+      vest: '>=3.0.0'
+      yup: ^1.0.0
+      zod: ^3.25.0 || ^4.0.0
+    peerDependenciesMeta:
+      '@sinclair/typebox':
+        optional: true
+      '@standard-schema/spec':
+        optional: true
+      '@typeschema/main':
+        optional: true
+      '@vinejs/vine':
+        optional: true
+      ajv:
+        optional: true
+      ajv-errors:
+        optional: true
+      ajv-formats:
+        optional: true
+      arktype:
+        optional: true
+      ata-validator:
+        optional: true
+      class-transformer:
+        optional: true
+      class-validator:
+        optional: true
+      computed-types:
+        optional: true
+      effect:
+        optional: true
+      fluentvalidation-ts:
+        optional: true
+      fp-ts:
+        optional: true
+      io-ts:
+        optional: true
+      joi:
+        optional: true
+      nope-validator:
+        optional: true
+      superstruct:
+        optional: true
+      typanion:
+        optional: true
+      valibot:
+        optional: true
+      vest:
+        optional: true
+      yup:
+        optional: true
+      zod:
+        optional: true
+
+  '@humanfs/core@0.19.2':
+    resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==}
+    engines: {node: '>=18.18.0'}
+
+  '@humanfs/node@0.16.8':
+    resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==}
+    engines: {node: '>=18.18.0'}
+
+  '@humanfs/types@0.15.0':
+    resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==}
+    engines: {node: '>=18.18.0'}
+
+  '@humanwhocodes/module-importer@1.0.1':
+    resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
+    engines: {node: '>=12.22'}
+
+  '@humanwhocodes/retry@0.4.3':
+    resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
+    engines: {node: '>=18.18'}
+
+  '@img/colour@1.1.0':
+    resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
+    engines: {node: '>=18'}
+
+  '@img/sharp-darwin-arm64@0.35.3':
+    resolution: {integrity: sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==}
+    engines: {node: '>=20.9.0'}
+    cpu: [arm64]
+    os: [darwin]
+
+  '@img/sharp-darwin-x64@0.35.3':
+    resolution: {integrity: sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==}
+    engines: {node: '>=20.9.0'}
+    cpu: [x64]
+    os: [darwin]
+
+  '@img/sharp-freebsd-wasm32@0.35.3':
+    resolution: {integrity: sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==}
+    engines: {node: '>=20.9.0'}
+    os: [freebsd]
+
+  '@img/sharp-libvips-darwin-arm64@1.3.2':
+    resolution: {integrity: sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==}
+    cpu: [arm64]
+    os: [darwin]
+
+  '@img/sharp-libvips-darwin-x64@1.3.2':
+    resolution: {integrity: sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==}
+    cpu: [x64]
+    os: [darwin]
+
+  '@img/sharp-libvips-linux-arm64@1.3.2':
+    resolution: {integrity: sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==}
+    cpu: [arm64]
+    os: [linux]
+    libc: [glibc]
+
+  '@img/sharp-libvips-linux-arm@1.3.2':
+    resolution: {integrity: sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==}
+    cpu: [arm]
+    os: [linux]
+    libc: [glibc]
+
+  '@img/sharp-libvips-linux-ppc64@1.3.2':
+    resolution: {integrity: sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==}
+    cpu: [ppc64]
+    os: [linux]
+    libc: [glibc]
+
+  '@img/sharp-libvips-linux-riscv64@1.3.2':
+    resolution: {integrity: sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==}
+    cpu: [riscv64]
+    os: [linux]
+    libc: [glibc]
+
+  '@img/sharp-libvips-linux-s390x@1.3.2':
+    resolution: {integrity: sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==}
+    cpu: [s390x]
+    os: [linux]
+    libc: [glibc]
+
+  '@img/sharp-libvips-linux-x64@1.3.2':
+    resolution: {integrity: sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==}
+    cpu: [x64]
+    os: [linux]
+    libc: [glibc]
+
+  '@img/sharp-libvips-linuxmusl-arm64@1.3.2':
+    resolution: {integrity: sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==}
+    cpu: [arm64]
+    os: [linux]
+    libc: [musl]
+
+  '@img/sharp-libvips-linuxmusl-x64@1.3.2':
+    resolution: {integrity: sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==}
+    cpu: [x64]
+    os: [linux]
+    libc: [musl]
+
+  '@img/sharp-linux-arm64@0.35.3':
+    resolution: {integrity: sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==}
+    engines: {node: '>=20.9.0'}
+    cpu: [arm64]
+    os: [linux]
+    libc: [glibc]
+
+  '@img/sharp-linux-arm@0.35.3':
+    resolution: {integrity: sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==}
+    engines: {node: '>=20.9.0'}
+    cpu: [arm]
+    os: [linux]
+    libc: [glibc]
+
+  '@img/sharp-linux-ppc64@0.35.3':
+    resolution: {integrity: sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==}
+    engines: {node: '>=20.9.0'}
+    cpu: [ppc64]
+    os: [linux]
+    libc: [glibc]
+
+  '@img/sharp-linux-riscv64@0.35.3':
+    resolution: {integrity: sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==}
+    engines: {node: '>=20.9.0'}
+    cpu: [riscv64]
+    os: [linux]
+    libc: [glibc]
+
+  '@img/sharp-linux-s390x@0.35.3':
+    resolution: {integrity: sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==}
+    engines: {node: '>=20.9.0'}
+    cpu: [s390x]
+    os: [linux]
+    libc: [glibc]
+
+  '@img/sharp-linux-x64@0.35.3':
+    resolution: {integrity: sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==}
+    engines: {node: '>=20.9.0'}
+    cpu: [x64]
+    os: [linux]
+    libc: [glibc]
+
+  '@img/sharp-linuxmusl-arm64@0.35.3':
+    resolution: {integrity: sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==}
+    engines: {node: '>=20.9.0'}
+    cpu: [arm64]
+    os: [linux]
+    libc: [musl]
+
+  '@img/sharp-linuxmusl-x64@0.35.3':
+    resolution: {integrity: sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==}
+    engines: {node: '>=20.9.0'}
+    cpu: [x64]
+    os: [linux]
+    libc: [musl]
+
+  '@img/sharp-wasm32@0.35.3':
+    resolution: {integrity: sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==}
+    engines: {node: '>=20.9.0'}
+
+  '@img/sharp-webcontainers-wasm32@0.35.3':
+    resolution: {integrity: sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==}
+    engines: {node: '>=20.9.0'}
+    cpu: [wasm32]
+
+  '@img/sharp-win32-arm64@0.35.3':
+    resolution: {integrity: sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==}
+    engines: {node: '>=20.9.0'}
+    cpu: [arm64]
+    os: [win32]
+
+  '@img/sharp-win32-ia32@0.35.3':
+    resolution: {integrity: sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==}
+    engines: {node: ^20.9.0}
+    cpu: [ia32]
+    os: [win32]
+
+  '@img/sharp-win32-x64@0.35.3':
+    resolution: {integrity: sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==}
+    engines: {node: '>=20.9.0'}
+    cpu: [x64]
+    os: [win32]
+
+  '@jridgewell/gen-mapping@0.3.13':
+    resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
+
+  '@jridgewell/remapping@2.3.5':
+    resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
+
+  '@jridgewell/resolve-uri@3.1.2':
+    resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+    engines: {node: '>=6.0.0'}
+
+  '@jridgewell/sourcemap-codec@1.5.5':
+    resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
+
+  '@jridgewell/trace-mapping@0.3.31':
+    resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+
+  '@napi-rs/wasm-runtime@1.2.2':
+    resolution: {integrity: sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==}
+    engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0}
+    peerDependencies:
+      '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.3
+      '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.3
+
+  '@next/env@16.3.0':
+    resolution: {integrity: sha512-o9r1S0BNiNreHP9Vs+Qnqd9kviDkJh8xIACY7UFZSmiGbbQRzPBBosvHzAU4TULHOIuOj/18RSsyz2qrREmIFw==}
+
+  '@next/eslint-plugin-next@16.3.0':
+    resolution: {integrity: sha512-OqgJ8PN0d04KcPhDX/PTY5tJUJZxlbrt7O7FBsm4XE0XW2JDrKnDXsc9uo9WUimJGPoo2j+JRGhyXApC//mvbw==}
+
+  '@next/swc-darwin-arm64@16.3.0':
+    resolution: {integrity: sha512-55hpqq18bEVAlxedlTt3tFqZmKg2nUXT1kn1G/BGEy0R13h3LwtwHPVzzjG6P4LLeOHE32PFDQUVaJEWvBEZBw==}
+    engines: {node: '>= 10'}
+    cpu: [arm64]
+    os: [darwin]
+
+  '@next/swc-darwin-x64@16.3.0':
+    resolution: {integrity: sha512-SOi96kSaF5T+0wW4koiM1bWzSPwjzTesC1p3df+FjdOi5LIQkBK/blxh7HdoKnNuI4PURF1OO7TZqtfnbWDSgw==}
+    engines: {node: '>= 10'}
+    cpu: [x64]
+    os: [darwin]
+
+  '@next/swc-linux-arm64-gnu@16.3.0':
+    resolution: {integrity: sha512-P0gZAoPMF4dyTRzhmkV4PrqVzSOB6t4mC1oI3c4dqijJ+OVEVx5clIXAKR4/uQpsqw2KKM/0D5tVumcR2r5blg==}
+    engines: {node: '>= 10'}
+    cpu: [arm64]
+    os: [linux]
+    libc: [glibc]
+
+  '@next/swc-linux-arm64-musl@16.3.0':
+    resolution: {integrity: sha512-tXXGKJw0m37O0eKJARVTX/TheKPhz0QFVtVVZXmOig+9YKLQOSP6hvf2pxv5DO7CLEJyTHx3Pg043CDQkv1G4Q==}
+    engines: {node: '>= 10'}
+    cpu: [arm64]
+    os: [linux]
+    libc: [musl]
+
+  '@next/swc-linux-x64-gnu@16.3.0':
+    resolution: {integrity: sha512-pjGxK5EY7yWml78ALejFkWmgHsU7wbFQrISiugpH6FbUJhgEvw3xFZ/EBAtLl7QtL0WdQKiG9eWJ3mOKGTukHw==}
+    engines: {node: '>= 10'}
+    cpu: [x64]
+    os: [linux]
+    libc: [glibc]
+
+  '@next/swc-linux-x64-musl@16.3.0':
+    resolution: {integrity: sha512-sjo++Xx+lomlPs3HRsHWhVDyGG6ms1kGW5EtHLERdII8AyG1i+f6aq68xHREO6AEMlhjTNEWBSmfJfqm9orf7g==}
+    engines: {node: '>= 10'}
+    cpu: [x64]
+    os: [linux]
+    libc: [musl]
+
+  '@next/swc-win32-arm64-msvc@16.3.0':
+    resolution: {integrity: sha512-C5JSgiO54wURdaxdEUIXqkz04uMqC9UmPX1gtDrV/5Tf1UowdWYI8uA5hfFbPolTlp0q4KZ60xlHePNibf0VIw==}
+    engines: {node: '>= 10'}
+    cpu: [arm64]
+    os: [win32]
+
+  '@next/swc-win32-x64-msvc@16.3.0':
+    resolution: {integrity: sha512-fDOggsweNb5SSw0ZKVk6U+gxSyGFFlIBY/LBc1r8GUj4u/6t6oArL+Pmkg0MBnsgR+KkdsURilVH4F3GXUGepA==}
+    engines: {node: '>= 10'}
+    cpu: [x64]
+    os: [win32]
+
+  '@nodelib/fs.scandir@2.1.5':
+    resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+    engines: {node: '>= 8'}
+
+  '@nodelib/fs.stat@2.0.5':
+    resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+    engines: {node: '>= 8'}
+
+  '@nodelib/fs.walk@1.2.8':
+    resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+    engines: {node: '>= 8'}
+
+  '@nolyfill/is-core-module@1.0.39':
+    resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
+    engines: {node: '>=12.4.0'}
+
+  '@oxc-project/types@0.143.0':
+    resolution: {integrity: sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==}
+
+  '@rolldown/binding-android-arm64@1.2.3':
+    resolution: {integrity: sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    cpu: [arm64]
+    os: [android]
+
+  '@rolldown/binding-darwin-arm64@1.2.3':
+    resolution: {integrity: sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    cpu: [arm64]
+    os: [darwin]
+
+  '@rolldown/binding-darwin-x64@1.2.3':
+    resolution: {integrity: sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    cpu: [x64]
+    os: [darwin]
+
+  '@rolldown/binding-freebsd-x64@1.2.3':
+    resolution: {integrity: sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    cpu: [x64]
+    os: [freebsd]
+
+  '@rolldown/binding-linux-arm-gnueabihf@1.2.3':
+    resolution: {integrity: sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    cpu: [arm]
+    os: [linux]
+
+  '@rolldown/binding-linux-arm64-gnu@1.2.3':
+    resolution: {integrity: sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    cpu: [arm64]
+    os: [linux]
+    libc: [glibc]
+
+  '@rolldown/binding-linux-arm64-musl@1.2.3':
+    resolution: {integrity: sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    cpu: [arm64]
+    os: [linux]
+    libc: [musl]
+
+  '@rolldown/binding-linux-ppc64-gnu@1.2.3':
+    resolution: {integrity: sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    cpu: [ppc64]
+    os: [linux]
+    libc: [glibc]
+
+  '@rolldown/binding-linux-s390x-gnu@1.2.3':
+    resolution: {integrity: sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    cpu: [s390x]
+    os: [linux]
+    libc: [glibc]
+
+  '@rolldown/binding-linux-x64-gnu@1.2.3':
+    resolution: {integrity: sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    cpu: [x64]
+    os: [linux]
+    libc: [glibc]
+
+  '@rolldown/binding-linux-x64-musl@1.2.3':
+    resolution: {integrity: sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    cpu: [x64]
+    os: [linux]
+    libc: [musl]
+
+  '@rolldown/binding-openharmony-arm64@1.2.3':
+    resolution: {integrity: sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    cpu: [arm64]
+    os: [openharmony]
+
+  '@rolldown/binding-win32-arm64-msvc@1.2.3':
+    resolution: {integrity: sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    cpu: [arm64]
+    os: [win32]
+
+  '@rolldown/binding-win32-x64-msvc@1.2.3':
+    resolution: {integrity: sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    cpu: [x64]
+    os: [win32]
+
+  '@rolldown/pluginutils@1.0.1':
+    resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==}
+
+  '@rtsao/scc@1.1.0':
+    resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
+
+  '@stablelib/base64@1.0.1':
+    resolution: {integrity: sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==}
+
+  '@standard-schema/spec@1.1.0':
+    resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
+
+  '@standard-schema/utils@0.3.0':
+    resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==}
+
+  '@swc/helpers@0.5.15':
+    resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
+
+  '@tailwindcss/node@4.3.3':
+    resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==}
+
+  '@tailwindcss/oxide-android-arm64@4.3.3':
+    resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==}
+    engines: {node: '>= 20'}
+    cpu: [arm64]
+    os: [android]
+
+  '@tailwindcss/oxide-darwin-arm64@4.3.3':
+    resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==}
+    engines: {node: '>= 20'}
+    cpu: [arm64]
+    os: [darwin]
+
+  '@tailwindcss/oxide-darwin-x64@4.3.3':
+    resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==}
+    engines: {node: '>= 20'}
+    cpu: [x64]
+    os: [darwin]
+
+  '@tailwindcss/oxide-freebsd-x64@4.3.3':
+    resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==}
+    engines: {node: '>= 20'}
+    cpu: [x64]
+    os: [freebsd]
+
+  '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3':
+    resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==}
+    engines: {node: '>= 20'}
+    cpu: [arm]
+    os: [linux]
+
+  '@tailwindcss/oxide-linux-arm64-gnu@4.3.3':
+    resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==}
+    engines: {node: '>= 20'}
+    cpu: [arm64]
+    os: [linux]
+    libc: [glibc]
+
+  '@tailwindcss/oxide-linux-arm64-musl@4.3.3':
+    resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==}
+    engines: {node: '>= 20'}
+    cpu: [arm64]
+    os: [linux]
+    libc: [musl]
+
+  '@tailwindcss/oxide-linux-x64-gnu@4.3.3':
+    resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==}
+    engines: {node: '>= 20'}
+    cpu: [x64]
+    os: [linux]
+    libc: [glibc]
+
+  '@tailwindcss/oxide-linux-x64-musl@4.3.3':
+    resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==}
+    engines: {node: '>= 20'}
+    cpu: [x64]
+    os: [linux]
+    libc: [musl]
+
+  '@tailwindcss/oxide-wasm32-wasi@4.3.3':
+    resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==}
+    engines: {node: '>=14.0.0'}
+    cpu: [wasm32]
+    bundledDependencies:
+      - '@napi-rs/wasm-runtime'
+      - '@emnapi/core'
+      - '@emnapi/runtime'
+      - '@tybys/wasm-util'
+      - '@emnapi/wasi-threads'
+      - tslib
+
+  '@tailwindcss/oxide-win32-arm64-msvc@4.3.3':
+    resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==}
+    engines: {node: '>= 20'}
+    cpu: [arm64]
+    os: [win32]
+
+  '@tailwindcss/oxide-win32-x64-msvc@4.3.3':
+    resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==}
+    engines: {node: '>= 20'}
+    cpu: [x64]
+    os: [win32]
+
+  '@tailwindcss/oxide@4.3.3':
+    resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==}
+    engines: {node: '>= 20'}
+
+  '@tailwindcss/postcss@4.3.3':
+    resolution: {integrity: sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==}
+
+  '@testing-library/dom@10.4.1':
+    resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==}
+    engines: {node: '>=18'}
+
+  '@testing-library/jest-dom@7.0.1':
+    resolution: {integrity: sha512-oMDTC3oA+6CXSO2JZnvOI7CA6oVub6kij5ggk9ohwye5slmkwxYDXcPOVxgMw/RQlticjtO0C1RZkR97HgrWMw==}
+    engines: {node: '>=22', npm: '>=6', yarn: '>=1'}
+    peerDependencies:
+      '@testing-library/dom': '>=10 <11'
+      vitest: '>= 0.32'
+    peerDependenciesMeta:
+      vitest:
+        optional: true
+
+  '@testing-library/react@16.3.2':
+    resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==}
+    engines: {node: '>=18'}
+    peerDependencies:
+      '@testing-library/dom': ^10.0.0
+      '@types/react': ^18.0.0 || ^19.0.0
+      '@types/react-dom': ^18.0.0 || ^19.0.0
+      react: ^18.0.0 || ^19.0.0
+      react-dom: ^18.0.0 || ^19.0.0
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+      '@types/react-dom':
+        optional: true
+
+  '@testing-library/user-event@14.6.3':
+    resolution: {integrity: sha512-6dBq67jT8lE+JTE8Exm02Kt6ze43hz1jdiSpSJwtTZiT1xQQ6b7nZYTTQ9njdArdU8XklOwaDp/AbT/eYSKF4g==}
+    engines: {node: '>=12', npm: '>=6'}
+    peerDependencies:
+      '@testing-library/dom': '>=7.21.4'
+
+  '@tybys/wasm-util@0.10.3':
+    resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==}
+
+  '@types/aria-query@5.0.4':
+    resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==}
+
+  '@types/chai@5.2.3':
+    resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
+
+  '@types/deep-eql@4.0.2':
+    resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
+
+  '@types/estree@1.0.9':
+    resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
+
+  '@types/json-schema@7.0.15':
+    resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
+
+  '@types/json5@0.0.29':
+    resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
+
+  '@types/node@20.19.43':
+    resolution: {integrity: sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==}
+
+  '@types/react-dom@19.2.4':
+    resolution: {integrity: sha512-Bsc+QHgp+P/F02XDzNCY9jnZNCUuLki36KT7VKrTXXLdHf+vHMNZnW1rVu5DNW/rCK+fya3DATySbLM4yhtKUw==}
+    peerDependencies:
+      '@types/react': ^19.2.0
+
+  '@types/react@19.2.18':
+    resolution: {integrity: sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==}
+
+  '@typescript-eslint/eslint-plugin@8.67.0':
+    resolution: {integrity: sha512-Un7Heoyj65NREbKAyIrFxeM143NZpExWmy1Nep4DLeQOeLlTeumPjoNKnBrU5D5moWXbPJgRa5Uwcdu0faVNGQ==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    peerDependencies:
+      '@typescript-eslint/parser': ^8.67.0
+      eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
+      typescript: '>=4.8.4 <6.1.0'
+
+  '@typescript-eslint/parser@8.67.0':
+    resolution: {integrity: sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    peerDependencies:
+      eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
+      typescript: '>=4.8.4 <6.1.0'
+
+  '@typescript-eslint/project-service@8.67.0':
+    resolution: {integrity: sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    peerDependencies:
+      typescript: '>=4.8.4 <6.1.0'
+
+  '@typescript-eslint/scope-manager@8.67.0':
+    resolution: {integrity: sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@typescript-eslint/tsconfig-utils@8.67.0':
+    resolution: {integrity: sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    peerDependencies:
+      typescript: '>=4.8.4 <6.1.0'
+
+  '@typescript-eslint/type-utils@8.67.0':
+    resolution: {integrity: sha512-aVWDXbRmdXO9siTfX4ditQI1T9+zVcNazT48EJCD0v40/9RIFoUgZ05CmGEq9H2gixRpjUn/iplwvlcvutJW/Q==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    peerDependencies:
+      eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
+      typescript: '>=4.8.4 <6.1.0'
+
+  '@typescript-eslint/types@8.67.0':
+    resolution: {integrity: sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@typescript-eslint/typescript-estree@8.67.0':
+    resolution: {integrity: sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    peerDependencies:
+      typescript: '>=4.8.4 <6.1.0'
+
+  '@typescript-eslint/utils@8.67.0':
+    resolution: {integrity: sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    peerDependencies:
+      eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
+      typescript: '>=4.8.4 <6.1.0'
+
+  '@typescript-eslint/visitor-keys@8.67.0':
+    resolution: {integrity: sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@unrs/resolver-binding-android-arm-eabi@1.12.2':
+    resolution: {integrity: sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==}
+    cpu: [arm]
+    os: [android]
+
+  '@unrs/resolver-binding-android-arm64@1.12.2':
+    resolution: {integrity: sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==}
+    cpu: [arm64]
+    os: [android]
+
+  '@unrs/resolver-binding-darwin-arm64@1.12.2':
+    resolution: {integrity: sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==}
+    cpu: [arm64]
+    os: [darwin]
+
+  '@unrs/resolver-binding-darwin-x64@1.12.2':
+    resolution: {integrity: sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==}
+    cpu: [x64]
+    os: [darwin]
+
+  '@unrs/resolver-binding-freebsd-x64@1.12.2':
+    resolution: {integrity: sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==}
+    cpu: [x64]
+    os: [freebsd]
+
+  '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2':
+    resolution: {integrity: sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==}
+    cpu: [arm]
+    os: [linux]
+
+  '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2':
+    resolution: {integrity: sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==}
+    cpu: [arm]
+    os: [linux]
+
+  '@unrs/resolver-binding-linux-arm64-gnu@1.12.2':
+    resolution: {integrity: sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==}
+    cpu: [arm64]
+    os: [linux]
+    libc: [glibc]
+
+  '@unrs/resolver-binding-linux-arm64-musl@1.12.2':
+    resolution: {integrity: sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==}
+    cpu: [arm64]
+    os: [linux]
+    libc: [musl]
+
+  '@unrs/resolver-binding-linux-loong64-gnu@1.12.2':
+    resolution: {integrity: sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==}
+    cpu: [loong64]
+    os: [linux]
+    libc: [glibc]
+
+  '@unrs/resolver-binding-linux-loong64-musl@1.12.2':
+    resolution: {integrity: sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==}
+    cpu: [loong64]
+    os: [linux]
+    libc: [musl]
+
+  '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2':
+    resolution: {integrity: sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==}
+    cpu: [ppc64]
+    os: [linux]
+    libc: [glibc]
+
+  '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2':
+    resolution: {integrity: sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==}
+    cpu: [riscv64]
+    os: [linux]
+    libc: [glibc]
+
+  '@unrs/resolver-binding-linux-riscv64-musl@1.12.2':
+    resolution: {integrity: sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==}
+    cpu: [riscv64]
+    os: [linux]
+    libc: [musl]
+
+  '@unrs/resolver-binding-linux-s390x-gnu@1.12.2':
+    resolution: {integrity: sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==}
+    cpu: [s390x]
+    os: [linux]
+    libc: [glibc]
+
+  '@unrs/resolver-binding-linux-x64-gnu@1.12.2':
+    resolution: {integrity: sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==}
+    cpu: [x64]
+    os: [linux]
+    libc: [glibc]
+
+  '@unrs/resolver-binding-linux-x64-musl@1.12.2':
+    resolution: {integrity: sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==}
+    cpu: [x64]
+    os: [linux]
+    libc: [musl]
+
+  '@unrs/resolver-binding-openharmony-arm64@1.12.2':
+    resolution: {integrity: sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==}
+    cpu: [arm64]
+    os: [openharmony]
+
+  '@unrs/resolver-binding-wasm32-wasi@1.12.2':
+    resolution: {integrity: sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==}
+    engines: {node: '>=14.0.0'}
+    cpu: [wasm32]
+
+  '@unrs/resolver-binding-win32-arm64-msvc@1.12.2':
+    resolution: {integrity: sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==}
+    cpu: [arm64]
+    os: [win32]
+
+  '@unrs/resolver-binding-win32-ia32-msvc@1.12.2':
+    resolution: {integrity: sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==}
+    cpu: [ia32]
+    os: [win32]
+
+  '@unrs/resolver-binding-win32-x64-msvc@1.12.2':
+    resolution: {integrity: sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==}
+    cpu: [x64]
+    os: [win32]
+
+  '@vitejs/plugin-react@6.0.5':
+    resolution: {integrity: sha512-BOVzne/NL162sMdResB25mUv+vWMF5NoAjNf09TeGlE7ZpszZWSD3winycicLJw72yeVsoCn/2kOhEuCvEShMA==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    peerDependencies:
+      '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0
+      babel-plugin-react-compiler: ^1.0.0
+      vite: ^8.0.0
+    peerDependenciesMeta:
+      '@rolldown/plugin-babel':
+        optional: true
+      babel-plugin-react-compiler:
+        optional: true
+
+  '@vitest/expect@4.1.10':
+    resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==}
+
+  '@vitest/mocker@4.1.10':
+    resolution: {integrity: sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==}
+    peerDependencies:
+      msw: ^2.4.9
+      vite: ^6.0.0 || ^7.0.0 || ^8.0.0
+    peerDependenciesMeta:
+      msw:
+        optional: true
+      vite:
+        optional: true
+
+  '@vitest/pretty-format@4.1.10':
+    resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==}
+
+  '@vitest/runner@4.1.10':
+    resolution: {integrity: sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==}
+
+  '@vitest/snapshot@4.1.10':
+    resolution: {integrity: sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==}
+
+  '@vitest/spy@4.1.10':
+    resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==}
+
+  '@vitest/utils@4.1.10':
+    resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==}
+
+  acorn-jsx@5.3.2:
+    resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+    peerDependencies:
+      acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+
+  acorn@8.18.0:
+    resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==}
+    engines: {node: '>=0.4.0'}
+    hasBin: true
+
+  ajv@6.15.0:
+    resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==}
+
+  ansi-regex@5.0.1:
+    resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+    engines: {node: '>=8'}
+
+  ansi-styles@4.3.0:
+    resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+    engines: {node: '>=8'}
+
+  ansi-styles@5.2.0:
+    resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
+    engines: {node: '>=10'}
+
+  argparse@2.0.1:
+    resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+
+  aria-query@5.3.0:
+    resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==}
+
+  aria-query@5.3.2:
+    resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
+    engines: {node: '>= 0.4'}
+
+  array-buffer-byte-length@1.0.2:
+    resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==}
+    engines: {node: '>= 0.4'}
+
+  array-includes@3.1.9:
+    resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==}
+    engines: {node: '>= 0.4'}
+
+  array.prototype.findlast@1.2.5:
+    resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==}
+    engines: {node: '>= 0.4'}
+
+  array.prototype.findlastindex@1.2.6:
+    resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==}
+    engines: {node: '>= 0.4'}
+
+  array.prototype.flat@1.3.3:
+    resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==}
+    engines: {node: '>= 0.4'}
+
+  array.prototype.flatmap@1.3.3:
+    resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==}
+    engines: {node: '>= 0.4'}
+
+  array.prototype.tosorted@1.1.4:
+    resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==}
+    engines: {node: '>= 0.4'}
+
+  arraybuffer.prototype.slice@1.0.4:
+    resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
+    engines: {node: '>= 0.4'}
+
+  assertion-error@2.0.1:
+    resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
+    engines: {node: '>=12'}
+
+  ast-types-flow@0.0.8:
+    resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
+
+  async-function@1.0.0:
+    resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
+    engines: {node: '>= 0.4'}
+
+  available-typed-arrays@1.0.7:
+    resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
+    engines: {node: '>= 0.4'}
+
+  axe-core@4.13.0:
+    resolution: {integrity: sha512-UzGt8zg7Ny8djbYMhxl2zuEevVa7r2gJjYY5Lwr1xM7+XU2nd6CkIWFTVcCIbAP63vSz71NaVyyuSk9lHKcy0A==}
+    engines: {node: '>=4'}
+
+  axobject-query@4.1.0:
+    resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
+    engines: {node: '>= 0.4'}
+
+  balanced-match@1.0.2:
+    resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
+  balanced-match@4.0.4:
+    resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
+    engines: {node: 18 || 20 || >=22}
+
+  baseline-browser-mapping@2.11.13:
+    resolution: {integrity: sha512-k9HNuUVMlqVjQ9UHzfPjIqiDbWw7WqT1AoT7GL8VwvF3r0ZfArtgiSPAlmupyNquNgOJHTuH4CKYf8ttMTWBTQ==}
+    engines: {node: '>=6.0.0'}
+    hasBin: true
+
+  bidi-js@1.0.3:
+    resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==}
+
+  brace-expansion@1.1.18:
+    resolution: {integrity: sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==}
+
+  brace-expansion@5.0.9:
+    resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==}
+    engines: {node: 20 || >=22}
+
+  braces@3.0.3:
+    resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+    engines: {node: '>=8'}
+
+  browserslist@4.28.8:
+    resolution: {integrity: sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==}
+    engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+    hasBin: true
+
+  call-bind-apply-helpers@1.0.2:
+    resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
+    engines: {node: '>= 0.4'}
+
+  call-bind@1.0.9:
+    resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==}
+    engines: {node: '>= 0.4'}
+
+  call-bound@1.0.4:
+    resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
+    engines: {node: '>= 0.4'}
+
+  callsites@3.1.0:
+    resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+    engines: {node: '>=6'}
+
+  caniuse-lite@1.0.30001809:
+    resolution: {integrity: sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==}
+
+  chai@6.2.2:
+    resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==}
+    engines: {node: '>=18'}
+
+  chalk@4.1.2:
+    resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+    engines: {node: '>=10'}
+
+  client-only@0.0.1:
+    resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
+
+  color-convert@2.0.1:
+    resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+    engines: {node: '>=7.0.0'}
+
+  color-name@1.1.4:
+    resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+  concat-map@0.0.1:
+    resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+
+  convert-source-map@2.0.0:
+    resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+
+  cross-spawn@7.0.6:
+    resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
+    engines: {node: '>= 8'}
+
+  css-tree@3.2.1:
+    resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==}
+    engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
+
+  css.escape@1.5.1:
+    resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
+
+  csstype@3.2.3:
+    resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+
+  damerau-levenshtein@1.0.8:
+    resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
+
+  data-urls@7.0.0:
+    resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==}
+    engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
+
+  data-view-buffer@1.0.2:
+    resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
+    engines: {node: '>= 0.4'}
+
+  data-view-byte-length@1.0.2:
+    resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==}
+    engines: {node: '>= 0.4'}
+
+  data-view-byte-offset@1.0.1:
+    resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==}
+    engines: {node: '>= 0.4'}
+
+  debug@3.2.7:
+    resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+    peerDependencies:
+      supports-color: '*'
+    peerDependenciesMeta:
+      supports-color:
+        optional: true
+
+  debug@4.4.3:
+    resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+    engines: {node: '>=6.0'}
+    peerDependencies:
+      supports-color: '*'
+    peerDependenciesMeta:
+      supports-color:
+        optional: true
+
+  decimal.js@10.6.0:
+    resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==}
+
+  deep-is@0.1.4:
+    resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+
+  define-data-property@1.1.4:
+    resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
+    engines: {node: '>= 0.4'}
+
+  define-properties@1.2.1:
+    resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
+    engines: {node: '>= 0.4'}
+
+  dequal@2.0.3:
+    resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+    engines: {node: '>=6'}
+
+  detect-libc@2.1.2:
+    resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
+    engines: {node: '>=8'}
+
+  doctrine@2.1.0:
+    resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
+    engines: {node: '>=0.10.0'}
+
+  dom-accessibility-api@0.5.16:
+    resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==}
+
+  dom-accessibility-api@0.6.3:
+    resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==}
+
+  dunder-proto@1.0.1:
+    resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
+    engines: {node: '>= 0.4'}
+
+  electron-to-chromium@1.5.403:
+    resolution: {integrity: sha512-MQsYmdaLzvaCX5j+ZZBr5Fm6uCCnPQcRtlvmvRlWqrXy+BH2O4ffXIAScF+JQznQWB9brWp4lSD9Z4yNmaf2BA==}
+
+  emoji-regex@9.2.2:
+    resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+
+  enhanced-resolve@5.24.5:
+    resolution: {integrity: sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==}
+    engines: {node: '>=10.13.0'}
+
+  entities@8.0.0:
+    resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==}
+    engines: {node: '>=20.19.0'}
+
+  es-abstract-get@1.0.0:
+    resolution: {integrity: sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==}
+    engines: {node: '>= 0.4'}
+
+  es-abstract@1.24.2:
+    resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==}
+    engines: {node: '>= 0.4'}
+
+  es-define-property@1.0.1:
+    resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
+    engines: {node: '>= 0.4'}
+
+  es-errors@1.3.0:
+    resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+    engines: {node: '>= 0.4'}
+
+  es-iterator-helpers@1.4.0:
+    resolution: {integrity: sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q==}
+    engines: {node: '>= 0.4'}
+
+  es-module-lexer@2.3.1:
+    resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==}
+
+  es-object-atoms@1.1.2:
+    resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==}
+    engines: {node: '>= 0.4'}
+
+  es-set-tostringtag@2.1.0:
+    resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
+    engines: {node: '>= 0.4'}
+
+  es-shim-unscopables@1.1.0:
+    resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==}
+    engines: {node: '>= 0.4'}
+
+  es-to-primitive@1.3.4:
+    resolution: {integrity: sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==}
+    engines: {node: '>= 0.4'}
+
+  escalade@3.2.0:
+    resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+    engines: {node: '>=6'}
+
+  escape-string-regexp@4.0.0:
+    resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+    engines: {node: '>=10'}
+
+  eslint-config-next@16.3.0:
+    resolution: {integrity: sha512-lPrf1kHsMJEZqO0uXkNB400c5MGrhrTk3BNX7P0ol4gt61+iUlQfjy9TyIOEA9eOXrf+5+mYbT/JsY8+zqUByQ==}
+    peerDependencies:
+      eslint: '>=9.0.0'
+      typescript: '>=3.3.1'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+
+  eslint-import-resolver-node@0.3.10:
+    resolution: {integrity: sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==}
+
+  eslint-import-resolver-typescript@3.10.1:
+    resolution: {integrity: sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==}
+    engines: {node: ^14.18.0 || >=16.0.0}
+    peerDependencies:
+      eslint: '*'
+      eslint-plugin-import: '*'
+      eslint-plugin-import-x: '*'
+    peerDependenciesMeta:
+      eslint-plugin-import:
+        optional: true
+      eslint-plugin-import-x:
+        optional: true
+
+  eslint-module-utils@2.14.0:
+    resolution: {integrity: sha512-W2WCRZ9Dqntd+2u8jJcVMV2PKulc6RdLgUUoh/yQr3uB6lo/ZOeGx11sv60/8S4QFFKNslAlWhr9u0Ef7ZW6Ig==}
+    engines: {node: '>=4'}
+    peerDependencies:
+      '@typescript-eslint/parser': '*'
+      eslint: '*'
+      eslint-import-resolver-node: '*'
+      eslint-import-resolver-typescript: '*'
+      eslint-import-resolver-webpack: '*'
+    peerDependenciesMeta:
+      '@typescript-eslint/parser':
+        optional: true
+      eslint:
+        optional: true
+      eslint-import-resolver-node:
+        optional: true
+      eslint-import-resolver-typescript:
+        optional: true
+      eslint-import-resolver-webpack:
+        optional: true
+
+  eslint-plugin-import@2.32.0:
+    resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==}
+    engines: {node: '>=4'}
+    peerDependencies:
+      '@typescript-eslint/parser': '*'
+      eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9
+    peerDependenciesMeta:
+      '@typescript-eslint/parser':
+        optional: true
+
+  eslint-plugin-jsx-a11y@6.10.2:
+    resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==}
+    engines: {node: '>=4.0'}
+    peerDependencies:
+      eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9
+
+  eslint-plugin-react-hooks@7.1.1:
+    resolution: {integrity: sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==}
+    engines: {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
+
+  eslint-plugin-react@7.37.5:
+    resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==}
+    engines: {node: '>=4'}
+    peerDependencies:
+      eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7
+
+  eslint-scope@8.4.0:
+    resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  eslint-visitor-keys@3.4.3:
+    resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+  eslint-visitor-keys@4.2.1:
+    resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  eslint-visitor-keys@5.0.1:
+    resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==}
+    engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+
+  eslint@9.39.5:
+    resolution: {integrity: sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    hasBin: true
+    peerDependencies:
+      jiti: '*'
+    peerDependenciesMeta:
+      jiti:
+        optional: true
+
+  espree@10.4.0:
+    resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  esquery@1.7.0:
+    resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==}
+    engines: {node: '>=0.10'}
+
+  esrecurse@4.3.0:
+    resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+    engines: {node: '>=4.0'}
+
+  estraverse@5.3.0:
+    resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+    engines: {node: '>=4.0'}
+
+  estree-walker@3.0.3:
+    resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+
+  esutils@2.0.3:
+    resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+    engines: {node: '>=0.10.0'}
+
+  expect-type@1.4.0:
+    resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==}
+    engines: {node: '>=12.0.0'}
+
+  fast-deep-equal@3.1.3:
+    resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+
+  fast-glob@3.3.1:
+    resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==}
+    engines: {node: '>=8.6.0'}
+
+  fast-json-stable-stringify@2.1.0:
+    resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+
+  fast-levenshtein@2.0.6:
+    resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+
+  fast-sha256@1.3.0:
+    resolution: {integrity: sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==}
+
+  fastq@1.20.1:
+    resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
+
+  fdir@6.5.0:
+    resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+    engines: {node: '>=12.0.0'}
+    peerDependencies:
+      picomatch: ^3 || ^4
+    peerDependenciesMeta:
+      picomatch:
+        optional: true
+
+  file-entry-cache@8.0.0:
+    resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
+    engines: {node: '>=16.0.0'}
+
+  fill-range@7.1.1:
+    resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+    engines: {node: '>=8'}
+
+  find-up@5.0.0:
+    resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+    engines: {node: '>=10'}
+
+  flat-cache@4.0.1:
+    resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
+    engines: {node: '>=16'}
+
+  flatted@3.4.4:
+    resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==}
+
+  for-each@0.3.5:
+    resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
+    engines: {node: '>= 0.4'}
+
+  fsevents@2.3.3:
+    resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+    engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+    os: [darwin]
+
+  function-bind@1.1.2:
+    resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+  function.prototype.name@1.2.0:
+    resolution: {integrity: sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==}
+    engines: {node: '>= 0.4'}
+
+  functions-have-names@1.2.3:
+    resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+
+  generator-function@2.0.1:
+    resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==}
+    engines: {node: '>= 0.4'}
+
+  gensync@1.0.0-beta.2:
+    resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+    engines: {node: '>=6.9.0'}
+
+  get-intrinsic@1.3.0:
+    resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
+    engines: {node: '>= 0.4'}
+
+  get-proto@1.0.1:
+    resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
+    engines: {node: '>= 0.4'}
+
+  get-symbol-description@1.1.0:
+    resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
+    engines: {node: '>= 0.4'}
+
+  get-tsconfig@4.14.1:
+    resolution: {integrity: sha512-Dz/6HxkrxgNehhxLVeyv8sad9UzF2xBVeaKBQNDfJ5XiSXmp2gTR0eO0RWiT2NCKS5aGP9jjkOMggTN90qU50A==}
+
+  glob-parent@5.1.2:
+    resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+    engines: {node: '>= 6'}
+
+  glob-parent@6.0.2:
+    resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+    engines: {node: '>=10.13.0'}
+
+  globals@14.0.0:
+    resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
+    engines: {node: '>=18'}
+
+  globals@16.4.0:
+    resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==}
+    engines: {node: '>=18'}
+
+  globalthis@1.0.4:
+    resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
+    engines: {node: '>= 0.4'}
+
+  gopd@1.2.0:
+    resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
+    engines: {node: '>= 0.4'}
+
+  graceful-fs@4.2.11:
+    resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+  has-bigints@1.1.0:
+    resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
+    engines: {node: '>= 0.4'}
+
+  has-flag@4.0.0:
+    resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+    engines: {node: '>=8'}
+
+  has-property-descriptors@1.0.2:
+    resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
+
+  has-proto@1.2.0:
+    resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==}
+    engines: {node: '>= 0.4'}
+
+  has-symbols@1.1.0:
+    resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
+    engines: {node: '>= 0.4'}
+
+  has-tostringtag@1.0.2:
+    resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
+    engines: {node: '>= 0.4'}
+
+  hasown@2.0.4:
+    resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==}
+    engines: {node: '>= 0.4'}
+
+  hermes-estree@0.25.1:
+    resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==}
+
+  hermes-parser@0.25.1:
+    resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==}
+
+  html-encoding-sniffer@6.0.0:
+    resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==}
+    engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
+
+  ignore@5.3.2:
+    resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
+    engines: {node: '>= 4'}
+
+  ignore@7.0.6:
+    resolution: {integrity: sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==}
+    engines: {node: '>= 4'}
+
+  import-fresh@3.3.1:
+    resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
+    engines: {node: '>=6'}
+
+  imurmurhash@0.1.4:
+    resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+    engines: {node: '>=0.8.19'}
+
+  indent-string@4.0.0:
+    resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
+    engines: {node: '>=8'}
+
+  internal-slot@1.1.0:
+    resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
+    engines: {node: '>= 0.4'}
+
+  is-array-buffer@3.0.5:
+    resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
+    engines: {node: '>= 0.4'}
+
+  is-async-function@2.1.1:
+    resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==}
+    engines: {node: '>= 0.4'}
+
+  is-bigint@1.1.0:
+    resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==}
+    engines: {node: '>= 0.4'}
+
+  is-boolean-object@1.2.2:
+    resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==}
+    engines: {node: '>= 0.4'}
+
+  is-bun-module@2.0.0:
+    resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==}
+
+  is-callable@1.2.7:
+    resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
+    engines: {node: '>= 0.4'}
+
+  is-core-module@2.16.2:
+    resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==}
+    engines: {node: '>= 0.4'}
+
+  is-data-view@1.0.2:
+    resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==}
+    engines: {node: '>= 0.4'}
+
+  is-date-object@1.1.0:
+    resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
+    engines: {node: '>= 0.4'}
+
+  is-document.all@1.0.0:
+    resolution: {integrity: sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==}
+    engines: {node: '>= 0.4'}
+
+  is-extglob@2.1.1:
+    resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+    engines: {node: '>=0.10.0'}
+
+  is-finalizationregistry@1.1.1:
+    resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==}
+    engines: {node: '>= 0.4'}
+
+  is-generator-function@1.1.2:
+    resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==}
+    engines: {node: '>= 0.4'}
+
+  is-glob@4.0.3:
+    resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+    engines: {node: '>=0.10.0'}
+
+  is-map@2.0.3:
+    resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
+    engines: {node: '>= 0.4'}
+
+  is-negative-zero@2.0.3:
+    resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==}
+    engines: {node: '>= 0.4'}
+
+  is-number-object@1.1.1:
+    resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==}
+    engines: {node: '>= 0.4'}
+
+  is-number@7.0.0:
+    resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+    engines: {node: '>=0.12.0'}
+
+  is-potential-custom-element-name@1.0.1:
+    resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
+
+  is-regex@1.2.1:
+    resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
+    engines: {node: '>= 0.4'}
+
+  is-set@2.0.3:
+    resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==}
+    engines: {node: '>= 0.4'}
+
+  is-shared-array-buffer@1.0.4:
+    resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==}
+    engines: {node: '>= 0.4'}
+
+  is-string@1.1.1:
+    resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==}
+    engines: {node: '>= 0.4'}
+
+  is-symbol@1.1.1:
+    resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==}
+    engines: {node: '>= 0.4'}
+
+  is-typed-array@1.1.15:
+    resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
+    engines: {node: '>= 0.4'}
+
+  is-weakmap@2.0.2:
+    resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
+    engines: {node: '>= 0.4'}
+
+  is-weakref@1.1.1:
+    resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==}
+    engines: {node: '>= 0.4'}
+
+  is-weakset@2.0.4:
+    resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
+    engines: {node: '>= 0.4'}
+
+  isarray@2.0.5:
+    resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
+
+  isexe@2.0.0:
+    resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+  iterator.prototype@1.1.5:
+    resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==}
+    engines: {node: '>= 0.4'}
+
+  jiti@2.7.0:
+    resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==}
+    hasBin: true
+
+  js-tokens@4.0.0:
+    resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+  js-yaml@4.3.1:
+    resolution: {integrity: sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==}
+    hasBin: true
+
+  jsdom@30.0.1:
+    resolution: {integrity: sha512-52v7mUVUfNQVYYqE1lcdaymWL0njO7lTLUog6ZvW2U5KsbiLk/GnZlVJ+qx0xfNJZ6Gn+KSpPNE52vurbxZwrA==}
+    engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0}
+    peerDependencies:
+      canvas: ^3.2.3
+    peerDependenciesMeta:
+      canvas:
+        optional: true
+
+  jsesc@3.1.0:
+    resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
+    engines: {node: '>=6'}
+    hasBin: true
+
+  json-buffer@3.0.1:
+    resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+
+  json-schema-traverse@0.4.1:
+    resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+
+  json-stable-stringify-without-jsonify@1.0.1:
+    resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+
+  json5@1.0.2:
+    resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
+    hasBin: true
+
+  json5@2.2.3:
+    resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+    engines: {node: '>=6'}
+    hasBin: true
+
+  jsx-ast-utils@3.3.5:
+    resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
+    engines: {node: '>=4.0'}
+
+  keyv@4.5.4:
+    resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+
+  language-subtag-registry@0.3.23:
+    resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==}
+
+  language-tags@1.0.9:
+    resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==}
+    engines: {node: '>=0.10'}
+
+  levn@0.4.1:
+    resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+    engines: {node: '>= 0.8.0'}
+
+  lightningcss-android-arm64@1.32.0:
+    resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [arm64]
+    os: [android]
+
+  lightningcss-android-arm64@1.33.0:
+    resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [arm64]
+    os: [android]
+
+  lightningcss-darwin-arm64@1.32.0:
+    resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [arm64]
+    os: [darwin]
+
+  lightningcss-darwin-arm64@1.33.0:
+    resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [arm64]
+    os: [darwin]
+
+  lightningcss-darwin-x64@1.32.0:
+    resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [x64]
+    os: [darwin]
+
+  lightningcss-darwin-x64@1.33.0:
+    resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [x64]
+    os: [darwin]
+
+  lightningcss-freebsd-x64@1.32.0:
+    resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [x64]
+    os: [freebsd]
+
+  lightningcss-freebsd-x64@1.33.0:
+    resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [x64]
+    os: [freebsd]
+
+  lightningcss-linux-arm-gnueabihf@1.32.0:
+    resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [arm]
+    os: [linux]
+
+  lightningcss-linux-arm-gnueabihf@1.33.0:
+    resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [arm]
+    os: [linux]
+
+  lightningcss-linux-arm64-gnu@1.32.0:
+    resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [arm64]
+    os: [linux]
+    libc: [glibc]
+
+  lightningcss-linux-arm64-gnu@1.33.0:
+    resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [arm64]
+    os: [linux]
+    libc: [glibc]
+
+  lightningcss-linux-arm64-musl@1.32.0:
+    resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [arm64]
+    os: [linux]
+    libc: [musl]
+
+  lightningcss-linux-arm64-musl@1.33.0:
+    resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [arm64]
+    os: [linux]
+    libc: [musl]
+
+  lightningcss-linux-x64-gnu@1.32.0:
+    resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [x64]
+    os: [linux]
+    libc: [glibc]
+
+  lightningcss-linux-x64-gnu@1.33.0:
+    resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [x64]
+    os: [linux]
+    libc: [glibc]
+
+  lightningcss-linux-x64-musl@1.32.0:
+    resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [x64]
+    os: [linux]
+    libc: [musl]
+
+  lightningcss-linux-x64-musl@1.33.0:
+    resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [x64]
+    os: [linux]
+    libc: [musl]
+
+  lightningcss-win32-arm64-msvc@1.32.0:
+    resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [arm64]
+    os: [win32]
+
+  lightningcss-win32-arm64-msvc@1.33.0:
+    resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [arm64]
+    os: [win32]
+
+  lightningcss-win32-x64-msvc@1.32.0:
+    resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [x64]
+    os: [win32]
+
+  lightningcss-win32-x64-msvc@1.33.0:
+    resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==}
+    engines: {node: '>= 12.0.0'}
+    cpu: [x64]
+    os: [win32]
+
+  lightningcss@1.32.0:
+    resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==}
+    engines: {node: '>= 12.0.0'}
+
+  lightningcss@1.33.0:
+    resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==}
+    engines: {node: '>= 12.0.0'}
+
+  locate-path@6.0.0:
+    resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+    engines: {node: '>=10'}
+
+  lodash.merge@4.6.2:
+    resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+
+  loose-envify@1.4.0:
+    resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+    hasBin: true
+
+  lru-cache@11.5.2:
+    resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==}
+    engines: {node: 20 || >=22}
+
+  lru-cache@5.1.1:
+    resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+
+  lucide-react@1.31.0:
+    resolution: {integrity: sha512-G8u2eEtoHUnUa9f8lbvqDhCiORMnYLdUEo06EEG9MQvHQrInKcX3Pa2TH39MM5qyzRcWETxB0+aOwAPI1g1kEg==}
+    peerDependencies:
+      react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
+  lz-string@1.5.0:
+    resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
+    hasBin: true
+
+  magic-string@0.30.21:
+    resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+
+  math-intrinsics@1.1.0:
+    resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
+    engines: {node: '>= 0.4'}
+
+  mdn-data@2.27.1:
+    resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==}
+
+  merge2@1.4.1:
+    resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+    engines: {node: '>= 8'}
+
+  micromatch@4.0.8:
+    resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
+    engines: {node: '>=8.6'}
+
+  min-indent@1.0.1:
+    resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
+    engines: {node: '>=4'}
+
+  minimatch@10.2.6:
+    resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==}
+    engines: {node: 18 || 20 || >=22}
+
+  minimatch@3.1.5:
+    resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==}
+
+  minimist@1.2.8:
+    resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+
+  ms@2.1.3:
+    resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+  nanoid@3.3.18:
+    resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==}
+    engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+    hasBin: true
+
+  napi-postinstall@0.3.4:
+    resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==}
+    engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+    hasBin: true
+
+  natural-compare@1.4.0:
+    resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+
+  next@16.3.0:
+    resolution: {integrity: sha512-NEdGOzH+08eTXMUp9UYkA99Nhi5N6Thrhc1jgFOQgfgnGK/dA2hRwBpXep+exdFQrnwlRf/3Wixyp8lLBUpE2A==}
+    engines: {node: '>=20.9.0'}
+    hasBin: true
+    peerDependencies:
+      '@opentelemetry/api': ^1.1.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:
+      '@opentelemetry/api':
+        optional: true
+      '@playwright/test':
+        optional: true
+      babel-plugin-react-compiler:
+        optional: true
+      sass:
+        optional: true
+
+  node-exports-info@1.6.2:
+    resolution: {integrity: sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==}
+    engines: {node: '>= 0.4'}
+
+  node-releases@2.0.53:
+    resolution: {integrity: sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==}
+    engines: {node: '>=18'}
+
+  object-assign@4.1.1:
+    resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+    engines: {node: '>=0.10.0'}
+
+  object-inspect@1.13.4:
+    resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
+    engines: {node: '>= 0.4'}
+
+  object-keys@1.1.1:
+    resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
+    engines: {node: '>= 0.4'}
+
+  object.assign@4.1.7:
+    resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==}
+    engines: {node: '>= 0.4'}
+
+  object.entries@1.1.9:
+    resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==}
+    engines: {node: '>= 0.4'}
+
+  object.fromentries@2.0.8:
+    resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==}
+    engines: {node: '>= 0.4'}
+
+  object.groupby@1.0.3:
+    resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==}
+    engines: {node: '>= 0.4'}
+
+  object.values@1.2.1:
+    resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
+    engines: {node: '>= 0.4'}
+
+  obug@2.1.4:
+    resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==}
+    engines: {node: '>=12.20.0'}
+
+  optionator@0.9.4:
+    resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
+    engines: {node: '>= 0.8.0'}
+
+  own-keys@1.0.2:
+    resolution: {integrity: sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==}
+    engines: {node: '>= 0.4'}
+
+  p-limit@3.1.0:
+    resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+    engines: {node: '>=10'}
+
+  p-locate@5.0.0:
+    resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+    engines: {node: '>=10'}
+
+  parent-module@1.0.1:
+    resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+    engines: {node: '>=6'}
+
+  parse5@8.0.1:
+    resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==}
+
+  path-exists@4.0.0:
+    resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+    engines: {node: '>=8'}
+
+  path-key@3.1.1:
+    resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+    engines: {node: '>=8'}
+
+  path-parse@1.0.7:
+    resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+
+  pathe@2.0.3:
+    resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
+
+  picocolors@1.1.1:
+    resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+  picomatch@2.3.2:
+    resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==}
+    engines: {node: '>=8.6'}
+
+  picomatch@4.0.5:
+    resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==}
+    engines: {node: '>=12'}
+
+  possible-typed-array-names@1.1.0:
+    resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
+    engines: {node: '>= 0.4'}
+
+  postal-mime@2.7.5:
+    resolution: {integrity: sha512-GNEXKvWFQnbgO5NlrGzVa0FmWzBZ24PersAWErttSg1Hjpf0ATxTwS5DOMGaOpTG6bUh5cTr7xi0jAD942wCJA==}
+
+  postcss@8.5.23:
+    resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==}
+    engines: {node: ^10 || ^12 || >=14}
+
+  postcss@8.5.26:
+    resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==}
+    engines: {node: ^10 || ^12 || >=14}
+
+  prelude-ls@1.2.1:
+    resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+    engines: {node: '>= 0.8.0'}
+
+  pretty-format@27.5.1:
+    resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==}
+    engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
+
+  prop-types@15.8.1:
+    resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+
+  punycode@2.3.1:
+    resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+    engines: {node: '>=6'}
+
+  queue-microtask@1.2.3:
+    resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+
+  react-dom@19.2.8:
+    resolution: {integrity: sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==}
+    peerDependencies:
+      react: ^19.2.8
+
+  react-hook-form@7.85.0:
+    resolution: {integrity: sha512-U2MTriFXnclmV4rOE20p2DcRFv5WEg3FIcBFOKcOLFHDVvGIMPvLTkTWefUsonmlaVy23khVDxDWym6uJVGOzw==}
+    engines: {node: '>=18.0.0'}
+    peerDependencies:
+      react: ^16.8.0 || ^17 || ^18 || ^19
+
+  react-is@16.13.1:
+    resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
+
+  react-is@17.0.2:
+    resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
+
+  react@19.2.8:
+    resolution: {integrity: sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==}
+    engines: {node: '>=0.10.0'}
+
+  redent@3.0.0:
+    resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
+    engines: {node: '>=8'}
+
+  reflect.getprototypeof@1.0.10:
+    resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
+    engines: {node: '>= 0.4'}
+
+  regexp.prototype.flags@1.5.4:
+    resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
+    engines: {node: '>= 0.4'}
+
+  require-from-string@2.0.2:
+    resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
+    engines: {node: '>=0.10.0'}
+
+  resend@6.19.0:
+    resolution: {integrity: sha512-JnEdYnd9WyBDIzunsEZtUF8n3cBKM9SlmySaos/7wwi4sEXKG1Zz4M64VFAyk+278erX01Fq2wHQ3p7OIdPriA==}
+    engines: {node: '>=20'}
+    peerDependencies:
+      '@react-email/render': '*'
+    peerDependenciesMeta:
+      '@react-email/render':
+        optional: true
+
+  resolve-from@4.0.0:
+    resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+    engines: {node: '>=4'}
+
+  resolve-pkg-maps@1.0.0:
+    resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+
+  resolve@2.0.0-next.7:
+    resolution: {integrity: sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==}
+    engines: {node: '>= 0.4'}
+    hasBin: true
+
+  reusify@1.1.0:
+    resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
+    engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+  rolldown@1.2.3:
+    resolution: {integrity: sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    hasBin: true
+
+  run-parallel@1.2.0:
+    resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+
+  safe-array-concat@1.1.4:
+    resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==}
+    engines: {node: '>=0.4'}
+
+  safe-push-apply@1.0.0:
+    resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
+    engines: {node: '>= 0.4'}
+
+  safe-regex-test@1.1.0:
+    resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
+    engines: {node: '>= 0.4'}
+
+  saxes@6.0.0:
+    resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
+    engines: {node: '>=v12.22.7'}
+
+  scheduler@0.27.0:
+    resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
+
+  semver@6.3.1:
+    resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+    hasBin: true
+
+  semver@7.8.5:
+    resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==}
+    engines: {node: '>=10'}
+    hasBin: true
+
+  set-function-length@1.2.2:
+    resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
+    engines: {node: '>= 0.4'}
+
+  set-function-name@2.0.2:
+    resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==}
+    engines: {node: '>= 0.4'}
+
+  set-proto@1.0.0:
+    resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
+    engines: {node: '>= 0.4'}
+
+  sharp@0.35.3:
+    resolution: {integrity: sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==}
+    engines: {node: '>=20.9.0'}
+    peerDependencies:
+      '@types/node': '*'
+    peerDependenciesMeta:
+      '@types/node':
+        optional: true
+
+  shebang-command@2.0.0:
+    resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+    engines: {node: '>=8'}
+
+  shebang-regex@3.0.0:
+    resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+    engines: {node: '>=8'}
+
+  side-channel-list@1.0.1:
+    resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==}
+    engines: {node: '>= 0.4'}
+
+  side-channel-map@1.0.1:
+    resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
+    engines: {node: '>= 0.4'}
+
+  side-channel-weakmap@1.0.2:
+    resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
+    engines: {node: '>= 0.4'}
+
+  side-channel@1.1.1:
+    resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==}
+    engines: {node: '>= 0.4'}
+
+  siginfo@2.0.0:
+    resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
+
+  source-map-js@1.2.1:
+    resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+    engines: {node: '>=0.10.0'}
+
+  stable-hash@0.0.5:
+    resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
+
+  stackback@0.0.2:
+    resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
+
+  standardwebhooks@1.0.0:
+    resolution: {integrity: sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==}
+
+  std-env@4.2.0:
+    resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==}
+
+  stop-iteration-iterator@1.1.0:
+    resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
+    engines: {node: '>= 0.4'}
+
+  string.prototype.includes@2.0.1:
+    resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==}
+    engines: {node: '>= 0.4'}
+
+  string.prototype.matchall@4.0.12:
+    resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==}
+    engines: {node: '>= 0.4'}
+
+  string.prototype.repeat@1.0.0:
+    resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==}
+
+  string.prototype.trim@1.2.11:
+    resolution: {integrity: sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==}
+    engines: {node: '>= 0.4'}
+
+  string.prototype.trimend@1.0.10:
+    resolution: {integrity: sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==}
+    engines: {node: '>= 0.4'}
+
+  string.prototype.trimstart@1.0.8:
+    resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
+    engines: {node: '>= 0.4'}
+
+  strip-bom@3.0.0:
+    resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
+    engines: {node: '>=4'}
+
+  strip-indent@3.0.0:
+    resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
+    engines: {node: '>=8'}
+
+  strip-json-comments@3.1.1:
+    resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+    engines: {node: '>=8'}
+
+  styled-jsx@5.1.6:
+    resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==}
+    engines: {node: '>= 12.0.0'}
+    peerDependencies:
+      '@babel/core': '*'
+      babel-plugin-macros: '*'
+      react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0'
+    peerDependenciesMeta:
+      '@babel/core':
+        optional: true
+      babel-plugin-macros:
+        optional: true
+
+  supports-color@7.2.0:
+    resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+    engines: {node: '>=8'}
+
+  supports-preserve-symlinks-flag@1.0.0:
+    resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+    engines: {node: '>= 0.4'}
+
+  symbol-tree@3.2.4:
+    resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
+
+  tailwindcss@4.3.3:
+    resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==}
+
+  tapable@2.3.3:
+    resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==}
+    engines: {node: '>=6'}
+
+  tinybench@2.9.0:
+    resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
+
+  tinyexec@1.3.0:
+    resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==}
+    engines: {node: '>=18'}
+
+  tinyglobby@0.2.17:
+    resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
+    engines: {node: '>=12.0.0'}
+
+  tinyrainbow@3.1.1:
+    resolution: {integrity: sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==}
+    engines: {node: '>=14.0.0'}
+
+  tldts-core@7.4.10:
+    resolution: {integrity: sha512-KnQjp53ZekKgm/r3l+u8kJGGzYgrWdP8+Mql7a4vijh2WE0IrZWspQj/TpTxDho/YxO+AnOZnIjQcCD+q6iJsw==}
+
+  tldts@7.4.10:
+    resolution: {integrity: sha512-GgouD1B+sWwvkaEq8vXC15DjQitxbvs12oIXELpconwm+Tg3zfcEv4jgzq3vtKverDXsg3VI8aRgNL2Nra0Iog==}
+    hasBin: true
+
+  to-regex-range@5.0.1:
+    resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+    engines: {node: '>=8.0'}
+
+  tough-cookie@6.0.2:
+    resolution: {integrity: sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==}
+    engines: {node: '>=16'}
+
+  tr46@6.0.0:
+    resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==}
+    engines: {node: '>=20'}
+
+  ts-api-utils@2.5.0:
+    resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==}
+    engines: {node: '>=18.12'}
+    peerDependencies:
+      typescript: '>=4.8.4'
+
+  tsconfig-paths@3.15.0:
+    resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
+
+  tslib@2.8.1:
+    resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
+  type-check@0.4.0:
+    resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+    engines: {node: '>= 0.8.0'}
+
+  typed-array-buffer@1.0.3:
+    resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
+    engines: {node: '>= 0.4'}
+
+  typed-array-byte-length@1.0.3:
+    resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==}
+    engines: {node: '>= 0.4'}
+
+  typed-array-byte-offset@1.0.4:
+    resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==}
+    engines: {node: '>= 0.4'}
+
+  typed-array-length@1.0.8:
+    resolution: {integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==}
+    engines: {node: '>= 0.4'}
+
+  typescript-eslint@8.67.0:
+    resolution: {integrity: sha512-S2udFs8tCKEKffuJ4TB1idGUZiXdCPGi3IPBGWXarbLQ5UPXORV8QEVzJ4gCRduURMb5EkpNCdjbk0eDIuI8Yg==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+    peerDependencies:
+      eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
+      typescript: '>=4.8.4 <6.1.0'
+
+  typescript@5.9.3:
+    resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
+    engines: {node: '>=14.17'}
+    hasBin: true
+
+  unbox-primitive@1.1.0:
+    resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
+    engines: {node: '>= 0.4'}
+
+  undici-types@6.21.0:
+    resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
+
+  undici@8.10.0:
+    resolution: {integrity: sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ==}
+    engines: {node: '>=22.19.0'}
+
+  unrs-resolver@1.12.2:
+    resolution: {integrity: sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==}
+
+  update-browserslist-db@1.3.1:
+    resolution: {integrity: sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==}
+    hasBin: true
+    peerDependencies:
+      browserslist: '>= 4.21.0'
+
+  uri-js@4.4.1:
+    resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+
+  vite@8.2.1:
+    resolution: {integrity: sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==}
+    engines: {node: ^20.19.0 || >=22.12.0}
+    hasBin: true
+    peerDependencies:
+      '@types/node': ^20.19.0 || >=22.12.0
+      '@vitejs/devtools': ^0.4.0
+      esbuild: ^0.27.0 || ^0.28.0
+      jiti: '>=1.21.0'
+      less: ^4.0.0
+      sass: ^1.70.0
+      sass-embedded: ^1.70.0
+      stylus: '>=0.54.8'
+      sugarss: ^5.0.0
+      terser: ^5.16.0
+      tsx: ^4.8.1
+      yaml: ^2.4.2
+    peerDependenciesMeta:
+      '@types/node':
+        optional: true
+      '@vitejs/devtools':
+        optional: true
+      esbuild:
+        optional: true
+      jiti:
+        optional: true
+      less:
+        optional: true
+      sass:
+        optional: true
+      sass-embedded:
+        optional: true
+      stylus:
+        optional: true
+      sugarss:
+        optional: true
+      terser:
+        optional: true
+      tsx:
+        optional: true
+      yaml:
+        optional: true
+
+  vitest@4.1.10:
+    resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==}
+    engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
+    hasBin: true
+    peerDependencies:
+      '@edge-runtime/vm': '*'
+      '@opentelemetry/api': ^1.9.0
+      '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0
+      '@vitest/browser-playwright': 4.1.10
+      '@vitest/browser-preview': 4.1.10
+      '@vitest/browser-webdriverio': 4.1.10
+      '@vitest/coverage-istanbul': 4.1.10
+      '@vitest/coverage-v8': 4.1.10
+      '@vitest/ui': 4.1.10
+      happy-dom: '*'
+      jsdom: '*'
+      vite: ^6.0.0 || ^7.0.0 || ^8.0.0
+    peerDependenciesMeta:
+      '@edge-runtime/vm':
+        optional: true
+      '@opentelemetry/api':
+        optional: true
+      '@types/node':
+        optional: true
+      '@vitest/browser-playwright':
+        optional: true
+      '@vitest/browser-preview':
+        optional: true
+      '@vitest/browser-webdriverio':
+        optional: true
+      '@vitest/coverage-istanbul':
+        optional: true
+      '@vitest/coverage-v8':
+        optional: true
+      '@vitest/ui':
+        optional: true
+      happy-dom:
+        optional: true
+      jsdom:
+        optional: true
+
+  w3c-xmlserializer@5.0.0:
+    resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
+    engines: {node: '>=18'}
+
+  webidl-conversions@8.0.1:
+    resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==}
+    engines: {node: '>=20'}
+
+  whatwg-mimetype@5.0.0:
+    resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==}
+    engines: {node: '>=20'}
+
+  whatwg-url@16.0.1:
+    resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==}
+    engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
+
+  whatwg-url@17.1.0:
+    resolution: {integrity: sha512-3GeworPmc2ZfEEHP7lEbUfBX/L75wdEsi0rLNhXcXxnoN5jyq0SL5gCy06SGW2cyTIZdTvWIDQNQoza++vKeaw==}
+    engines: {node: ^22.14.0 || >=24.0.0}
+
+  which-boxed-primitive@1.1.1:
+    resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
+    engines: {node: '>= 0.4'}
+
+  which-builtin-type@1.2.1:
+    resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==}
+    engines: {node: '>= 0.4'}
+
+  which-collection@1.0.2:
+    resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==}
+    engines: {node: '>= 0.4'}
+
+  which-typed-array@1.1.22:
+    resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==}
+    engines: {node: '>= 0.4'}
+
+  which@2.0.2:
+    resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+    engines: {node: '>= 8'}
+    hasBin: true
+
+  why-is-node-running@2.3.0:
+    resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
+    engines: {node: '>=8'}
+    hasBin: true
+
+  word-wrap@1.2.5:
+    resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
+    engines: {node: '>=0.10.0'}
+
+  xml-name-validator@5.0.0:
+    resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==}
+    engines: {node: '>=18'}
+
+  xmlchars@2.2.0:
+    resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
+
+  yallist@3.1.1:
+    resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+
+  yocto-queue@0.1.0:
+    resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+    engines: {node: '>=10'}
+
+  zod-validation-error@4.0.2:
+    resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==}
+    engines: {node: '>=18.0.0'}
+    peerDependencies:
+      zod: ^3.25.0 || ^4.0.0
+
+  zod@4.4.3:
+    resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==}
+
+snapshots:
+
+  '@adobe/css-tools@4.5.0': {}
+
+  '@alloc/quick-lru@5.2.0': {}
+
+  '@asamuzakjp/css-color@6.0.7':
+    dependencies:
+      '@csstools/css-calc': 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)
+      '@csstools/css-color-parser': 4.1.10(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)
+      '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0)
+      '@csstools/css-tokenizer': 4.0.0
+      lru-cache: 11.5.2
+
+  '@asamuzakjp/dom-selector@8.3.2':
+    dependencies:
+      bidi-js: 1.0.3
+      css-tree: 3.2.1
+      is-potential-custom-element-name: 1.0.1
+      lru-cache: 11.5.2
+
+  '@babel/code-frame@7.29.7':
+    dependencies:
+      '@babel/helper-validator-identifier': 7.29.7
+      js-tokens: 4.0.0
+      picocolors: 1.1.1
+
+  '@babel/compat-data@7.29.7': {}
+
+  '@babel/core@7.29.7(supports-color@7.2.0)':
+    dependencies:
+      '@babel/code-frame': 7.29.7
+      '@babel/generator': 7.29.8
+      '@babel/helper-compilation-targets': 7.29.7
+      '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)
+      '@babel/helpers': 7.29.7
+      '@babel/parser': 7.29.8
+      '@babel/template': 7.29.7
+      '@babel/traverse': 7.29.8(supports-color@7.2.0)
+      '@babel/types': 7.29.8
+      '@jridgewell/remapping': 2.3.5
+      convert-source-map: 2.0.0
+      debug: 4.4.3(supports-color@7.2.0)
+      gensync: 1.0.0-beta.2
+      json5: 2.2.3
+      semver: 6.3.1
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/generator@7.29.8':
+    dependencies:
+      '@babel/parser': 7.29.8
+      '@babel/types': 7.29.8
+      '@jridgewell/gen-mapping': 0.3.13
+      '@jridgewell/trace-mapping': 0.3.31
+      jsesc: 3.1.0
+
+  '@babel/helper-compilation-targets@7.29.7':
+    dependencies:
+      '@babel/compat-data': 7.29.7
+      '@babel/helper-validator-option': 7.29.7
+      browserslist: 4.28.8
+      lru-cache: 5.1.1
+      semver: 6.3.1
+
+  '@babel/helper-globals@7.29.7': {}
+
+  '@babel/helper-module-imports@7.29.7(supports-color@7.2.0)':
+    dependencies:
+      '@babel/traverse': 7.29.8(supports-color@7.2.0)
+      '@babel/types': 7.29.8
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)':
+    dependencies:
+      '@babel/core': 7.29.7(supports-color@7.2.0)
+      '@babel/helper-module-imports': 7.29.7(supports-color@7.2.0)
+      '@babel/helper-validator-identifier': 7.29.7
+      '@babel/traverse': 7.29.8(supports-color@7.2.0)
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/helper-string-parser@7.29.7': {}
+
+  '@babel/helper-validator-identifier@7.29.7': {}
+
+  '@babel/helper-validator-option@7.29.7': {}
+
+  '@babel/helpers@7.29.7':
+    dependencies:
+      '@babel/template': 7.29.7
+      '@babel/types': 7.29.8
+
+  '@babel/parser@7.29.8':
+    dependencies:
+      '@babel/types': 7.29.8
+
+  '@babel/runtime@7.29.7': {}
+
+  '@babel/template@7.29.7':
+    dependencies:
+      '@babel/code-frame': 7.29.7
+      '@babel/parser': 7.29.8
+      '@babel/types': 7.29.8
+
+  '@babel/traverse@7.29.8(supports-color@7.2.0)':
+    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.4.3(supports-color@7.2.0)
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/types@7.29.8':
+    dependencies:
+      '@babel/helper-string-parser': 7.29.7
+      '@babel/helper-validator-identifier': 7.29.7
+
+  '@bramus/specificity@2.4.2':
+    dependencies:
+      css-tree: 3.2.1
+
+  '@csstools/color-helpers@6.1.0': {}
+
+  '@csstools/css-calc@3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)':
+    dependencies:
+      '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0)
+      '@csstools/css-tokenizer': 4.0.0
+
+  '@csstools/css-color-parser@4.1.10(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)':
+    dependencies:
+      '@csstools/color-helpers': 6.1.0
+      '@csstools/css-calc': 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)
+      '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0)
+      '@csstools/css-tokenizer': 4.0.0
+
+  '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)':
+    dependencies:
+      '@csstools/css-tokenizer': 4.0.0
+
+  '@csstools/css-syntax-patches-for-csstree@1.1.7(css-tree@3.2.1)':
+    optionalDependencies:
+      css-tree: 3.2.1
+
+  '@csstools/css-tokenizer@4.0.0': {}
+
+  '@emnapi/core@1.10.0':
+    dependencies:
+      '@emnapi/wasi-threads': 1.2.1
+      tslib: 2.8.1
+    optional: true
+
+  '@emnapi/runtime@1.10.0':
+    dependencies:
+      tslib: 2.8.1
+    optional: true
+
+  '@emnapi/runtime@1.11.3':
+    dependencies:
+      tslib: 2.8.1
+    optional: true
+
+  '@emnapi/wasi-threads@1.2.1':
+    dependencies:
+      tslib: 2.8.1
+    optional: true
+
+  '@eslint-community/eslint-utils@4.10.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))':
+    dependencies:
+      eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0)
+      eslint-visitor-keys: 3.4.3
+
+  '@eslint-community/eslint-utils@4.9.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))':
+    dependencies:
+      eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0)
+      eslint-visitor-keys: 3.4.3
+
+  '@eslint-community/regexpp@4.12.2': {}
+
+  '@eslint/config-array@0.21.2(supports-color@7.2.0)':
+    dependencies:
+      '@eslint/object-schema': 2.1.7
+      debug: 4.4.3(supports-color@7.2.0)
+      minimatch: 3.1.5
+    transitivePeerDependencies:
+      - supports-color
+
+  '@eslint/config-helpers@0.4.2':
+    dependencies:
+      '@eslint/core': 0.17.0
+
+  '@eslint/core@0.17.0':
+    dependencies:
+      '@types/json-schema': 7.0.15
+
+  '@eslint/eslintrc@3.3.6(supports-color@7.2.0)':
+    dependencies:
+      ajv: 6.15.0
+      debug: 4.4.3(supports-color@7.2.0)
+      espree: 10.4.0
+      globals: 14.0.0
+      ignore: 5.3.2
+      import-fresh: 3.3.1
+      js-yaml: 4.3.1
+      minimatch: 3.1.5
+      strip-json-comments: 3.1.1
+    transitivePeerDependencies:
+      - supports-color
+
+  '@eslint/js@9.39.5': {}
+
+  '@eslint/object-schema@2.1.7': {}
+
+  '@eslint/plugin-kit@0.4.1':
+    dependencies:
+      '@eslint/core': 0.17.0
+      levn: 0.4.1
+
+  '@exodus/bytes@1.15.1': {}
+
+  '@hookform/resolvers@5.7.1(@standard-schema/spec@1.1.0)(react-hook-form@7.85.0(react@19.2.8))(zod@4.4.3)':
+    dependencies:
+      '@standard-schema/utils': 0.3.0
+      react-hook-form: 7.85.0(react@19.2.8)
+    optionalDependencies:
+      '@standard-schema/spec': 1.1.0
+      zod: 4.4.3
+
+  '@humanfs/core@0.19.2':
+    dependencies:
+      '@humanfs/types': 0.15.0
+
+  '@humanfs/node@0.16.8':
+    dependencies:
+      '@humanfs/core': 0.19.2
+      '@humanfs/types': 0.15.0
+      '@humanwhocodes/retry': 0.4.3
+
+  '@humanfs/types@0.15.0': {}
+
+  '@humanwhocodes/module-importer@1.0.1': {}
+
+  '@humanwhocodes/retry@0.4.3': {}
+
+  '@img/colour@1.1.0':
+    optional: true
+
+  '@img/sharp-darwin-arm64@0.35.3':
+    optionalDependencies:
+      '@img/sharp-libvips-darwin-arm64': 1.3.2
+    optional: true
+
+  '@img/sharp-darwin-x64@0.35.3':
+    optionalDependencies:
+      '@img/sharp-libvips-darwin-x64': 1.3.2
+    optional: true
+
+  '@img/sharp-freebsd-wasm32@0.35.3':
+    dependencies:
+      '@img/sharp-wasm32': 0.35.3
+    optional: true
+
+  '@img/sharp-libvips-darwin-arm64@1.3.2':
+    optional: true
+
+  '@img/sharp-libvips-darwin-x64@1.3.2':
+    optional: true
+
+  '@img/sharp-libvips-linux-arm64@1.3.2':
+    optional: true
+
+  '@img/sharp-libvips-linux-arm@1.3.2':
+    optional: true
+
+  '@img/sharp-libvips-linux-ppc64@1.3.2':
+    optional: true
+
+  '@img/sharp-libvips-linux-riscv64@1.3.2':
+    optional: true
+
+  '@img/sharp-libvips-linux-s390x@1.3.2':
+    optional: true
+
+  '@img/sharp-libvips-linux-x64@1.3.2':
+    optional: true
+
+  '@img/sharp-libvips-linuxmusl-arm64@1.3.2':
+    optional: true
+
+  '@img/sharp-libvips-linuxmusl-x64@1.3.2':
+    optional: true
+
+  '@img/sharp-linux-arm64@0.35.3':
+    optionalDependencies:
+      '@img/sharp-libvips-linux-arm64': 1.3.2
+    optional: true
+
+  '@img/sharp-linux-arm@0.35.3':
+    optionalDependencies:
+      '@img/sharp-libvips-linux-arm': 1.3.2
+    optional: true
+
+  '@img/sharp-linux-ppc64@0.35.3':
+    optionalDependencies:
+      '@img/sharp-libvips-linux-ppc64': 1.3.2
+    optional: true
+
+  '@img/sharp-linux-riscv64@0.35.3':
+    optionalDependencies:
+      '@img/sharp-libvips-linux-riscv64': 1.3.2
+    optional: true
+
+  '@img/sharp-linux-s390x@0.35.3':
+    optionalDependencies:
+      '@img/sharp-libvips-linux-s390x': 1.3.2
+    optional: true
+
+  '@img/sharp-linux-x64@0.35.3':
+    optionalDependencies:
+      '@img/sharp-libvips-linux-x64': 1.3.2
+    optional: true
+
+  '@img/sharp-linuxmusl-arm64@0.35.3':
+    optionalDependencies:
+      '@img/sharp-libvips-linuxmusl-arm64': 1.3.2
+    optional: true
+
+  '@img/sharp-linuxmusl-x64@0.35.3':
+    optionalDependencies:
+      '@img/sharp-libvips-linuxmusl-x64': 1.3.2
+    optional: true
+
+  '@img/sharp-wasm32@0.35.3':
+    dependencies:
+      '@emnapi/runtime': 1.11.3
+    optional: true
+
+  '@img/sharp-webcontainers-wasm32@0.35.3':
+    dependencies:
+      '@img/sharp-wasm32': 0.35.3
+    optional: true
+
+  '@img/sharp-win32-arm64@0.35.3':
+    optional: true
+
+  '@img/sharp-win32-ia32@0.35.3':
+    optional: true
+
+  '@img/sharp-win32-x64@0.35.3':
+    optional: true
+
+  '@jridgewell/gen-mapping@0.3.13':
+    dependencies:
+      '@jridgewell/sourcemap-codec': 1.5.5
+      '@jridgewell/trace-mapping': 0.3.31
+
+  '@jridgewell/remapping@2.3.5':
+    dependencies:
+      '@jridgewell/gen-mapping': 0.3.13
+      '@jridgewell/trace-mapping': 0.3.31
+
+  '@jridgewell/resolve-uri@3.1.2': {}
+
+  '@jridgewell/sourcemap-codec@1.5.5': {}
+
+  '@jridgewell/trace-mapping@0.3.31':
+    dependencies:
+      '@jridgewell/resolve-uri': 3.1.2
+      '@jridgewell/sourcemap-codec': 1.5.5
+
+  '@napi-rs/wasm-runtime@1.2.2(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)':
+    dependencies:
+      '@emnapi/core': 1.10.0
+      '@emnapi/runtime': 1.10.0
+      '@tybys/wasm-util': 0.10.3
+    optional: true
+
+  '@next/env@16.3.0': {}
+
+  '@next/eslint-plugin-next@16.3.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))':
+    dependencies:
+      '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))
+      fast-glob: 3.3.1
+    transitivePeerDependencies:
+      - eslint
+
+  '@next/swc-darwin-arm64@16.3.0':
+    optional: true
+
+  '@next/swc-darwin-x64@16.3.0':
+    optional: true
+
+  '@next/swc-linux-arm64-gnu@16.3.0':
+    optional: true
+
+  '@next/swc-linux-arm64-musl@16.3.0':
+    optional: true
+
+  '@next/swc-linux-x64-gnu@16.3.0':
+    optional: true
+
+  '@next/swc-linux-x64-musl@16.3.0':
+    optional: true
+
+  '@next/swc-win32-arm64-msvc@16.3.0':
+    optional: true
+
+  '@next/swc-win32-x64-msvc@16.3.0':
+    optional: true
+
+  '@nodelib/fs.scandir@2.1.5':
+    dependencies:
+      '@nodelib/fs.stat': 2.0.5
+      run-parallel: 1.2.0
+
+  '@nodelib/fs.stat@2.0.5': {}
+
+  '@nodelib/fs.walk@1.2.8':
+    dependencies:
+      '@nodelib/fs.scandir': 2.1.5
+      fastq: 1.20.1
+
+  '@nolyfill/is-core-module@1.0.39': {}
+
+  '@oxc-project/types@0.143.0': {}
+
+  '@rolldown/binding-android-arm64@1.2.3':
+    optional: true
+
+  '@rolldown/binding-darwin-arm64@1.2.3':
+    optional: true
+
+  '@rolldown/binding-darwin-x64@1.2.3':
+    optional: true
+
+  '@rolldown/binding-freebsd-x64@1.2.3':
+    optional: true
+
+  '@rolldown/binding-linux-arm-gnueabihf@1.2.3':
+    optional: true
+
+  '@rolldown/binding-linux-arm64-gnu@1.2.3':
+    optional: true
+
+  '@rolldown/binding-linux-arm64-musl@1.2.3':
+    optional: true
+
+  '@rolldown/binding-linux-ppc64-gnu@1.2.3':
+    optional: true
+
+  '@rolldown/binding-linux-s390x-gnu@1.2.3':
+    optional: true
+
+  '@rolldown/binding-linux-x64-gnu@1.2.3':
+    optional: true
+
+  '@rolldown/binding-linux-x64-musl@1.2.3':
+    optional: true
+
+  '@rolldown/binding-openharmony-arm64@1.2.3':
+    optional: true
+
+  '@rolldown/binding-win32-arm64-msvc@1.2.3':
+    optional: true
+
+  '@rolldown/binding-win32-x64-msvc@1.2.3':
+    optional: true
+
+  '@rolldown/pluginutils@1.0.1': {}
+
+  '@rtsao/scc@1.1.0': {}
+
+  '@stablelib/base64@1.0.1': {}
+
+  '@standard-schema/spec@1.1.0': {}
+
+  '@standard-schema/utils@0.3.0': {}
+
+  '@swc/helpers@0.5.15':
+    dependencies:
+      tslib: 2.8.1
+
+  '@tailwindcss/node@4.3.3':
+    dependencies:
+      '@jridgewell/remapping': 2.3.5
+      enhanced-resolve: 5.24.5
+      jiti: 2.7.0
+      lightningcss: 1.32.0
+      magic-string: 0.30.21
+      source-map-js: 1.2.1
+      tailwindcss: 4.3.3
+
+  '@tailwindcss/oxide-android-arm64@4.3.3':
+    optional: true
+
+  '@tailwindcss/oxide-darwin-arm64@4.3.3':
+    optional: true
+
+  '@tailwindcss/oxide-darwin-x64@4.3.3':
+    optional: true
+
+  '@tailwindcss/oxide-freebsd-x64@4.3.3':
+    optional: true
+
+  '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3':
+    optional: true
+
+  '@tailwindcss/oxide-linux-arm64-gnu@4.3.3':
+    optional: true
+
+  '@tailwindcss/oxide-linux-arm64-musl@4.3.3':
+    optional: true
+
+  '@tailwindcss/oxide-linux-x64-gnu@4.3.3':
+    optional: true
+
+  '@tailwindcss/oxide-linux-x64-musl@4.3.3':
+    optional: true
+
+  '@tailwindcss/oxide-wasm32-wasi@4.3.3':
+    optional: true
+
+  '@tailwindcss/oxide-win32-arm64-msvc@4.3.3':
+    optional: true
+
+  '@tailwindcss/oxide-win32-x64-msvc@4.3.3':
+    optional: true
+
+  '@tailwindcss/oxide@4.3.3':
+    optionalDependencies:
+      '@tailwindcss/oxide-android-arm64': 4.3.3
+      '@tailwindcss/oxide-darwin-arm64': 4.3.3
+      '@tailwindcss/oxide-darwin-x64': 4.3.3
+      '@tailwindcss/oxide-freebsd-x64': 4.3.3
+      '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3
+      '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3
+      '@tailwindcss/oxide-linux-arm64-musl': 4.3.3
+      '@tailwindcss/oxide-linux-x64-gnu': 4.3.3
+      '@tailwindcss/oxide-linux-x64-musl': 4.3.3
+      '@tailwindcss/oxide-wasm32-wasi': 4.3.3
+      '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3
+      '@tailwindcss/oxide-win32-x64-msvc': 4.3.3
+
+  '@tailwindcss/postcss@4.3.3':
+    dependencies:
+      '@alloc/quick-lru': 5.2.0
+      '@tailwindcss/node': 4.3.3
+      '@tailwindcss/oxide': 4.3.3
+      postcss: 8.5.26
+      tailwindcss: 4.3.3
+
+  '@testing-library/dom@10.4.1':
+    dependencies:
+      '@babel/code-frame': 7.29.7
+      '@babel/runtime': 7.29.7
+      '@types/aria-query': 5.0.4
+      aria-query: 5.3.0
+      dom-accessibility-api: 0.5.16
+      lz-string: 1.5.0
+      picocolors: 1.1.1
+      pretty-format: 27.5.1
+
+  '@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.1)(vitest@4.1.10(@types/node@20.19.43)(jsdom@30.0.1)(vite@8.2.1(@types/node@20.19.43)(jiti@2.7.0)))':
+    dependencies:
+      '@adobe/css-tools': 4.5.0
+      '@testing-library/dom': 10.4.1
+      aria-query: 5.3.2
+      css.escape: 1.5.1
+      dom-accessibility-api: 0.6.3
+      picocolors: 1.1.1
+      redent: 3.0.0
+    optionalDependencies:
+      vitest: 4.1.10(@types/node@20.19.43)(jsdom@30.0.1)(vite@8.2.1(@types/node@20.19.43)(jiti@2.7.0))
+
+  '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
+    dependencies:
+      '@babel/runtime': 7.29.7
+      '@testing-library/dom': 10.4.1
+      react: 19.2.8
+      react-dom: 19.2.8(react@19.2.8)
+    optionalDependencies:
+      '@types/react': 19.2.18
+      '@types/react-dom': 19.2.4(@types/react@19.2.18)
+
+  '@testing-library/user-event@14.6.3(@testing-library/dom@10.4.1)':
+    dependencies:
+      '@testing-library/dom': 10.4.1
+
+  '@tybys/wasm-util@0.10.3':
+    dependencies:
+      tslib: 2.8.1
+    optional: true
+
+  '@types/aria-query@5.0.4': {}
+
+  '@types/chai@5.2.3':
+    dependencies:
+      '@types/deep-eql': 4.0.2
+      assertion-error: 2.0.1
+
+  '@types/deep-eql@4.0.2': {}
+
+  '@types/estree@1.0.9': {}
+
+  '@types/json-schema@7.0.15': {}
+
+  '@types/json5@0.0.29': {}
+
+  '@types/node@20.19.43':
+    dependencies:
+      undici-types: 6.21.0
+
+  '@types/react-dom@19.2.4(@types/react@19.2.18)':
+    dependencies:
+      '@types/react': 19.2.18
+
+  '@types/react@19.2.18':
+    dependencies:
+      csstype: 3.2.3
+
+  '@typescript-eslint/eslint-plugin@8.67.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)':
+    dependencies:
+      '@eslint-community/regexpp': 4.12.2
+      '@typescript-eslint/parser': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
+      '@typescript-eslint/scope-manager': 8.67.0
+      '@typescript-eslint/type-utils': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
+      '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
+      '@typescript-eslint/visitor-keys': 8.67.0
+      eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0)
+      ignore: 7.0.6
+      natural-compare: 1.4.0
+      ts-api-utils: 2.5.0(typescript@5.9.3)
+      typescript: 5.9.3
+    transitivePeerDependencies:
+      - supports-color
+
+  '@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)':
+    dependencies:
+      '@typescript-eslint/scope-manager': 8.67.0
+      '@typescript-eslint/types': 8.67.0
+      '@typescript-eslint/typescript-estree': 8.67.0(supports-color@7.2.0)(typescript@5.9.3)
+      '@typescript-eslint/visitor-keys': 8.67.0
+      debug: 4.4.3(supports-color@7.2.0)
+      eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0)
+      typescript: 5.9.3
+    transitivePeerDependencies:
+      - supports-color
+
+  '@typescript-eslint/project-service@8.67.0(supports-color@7.2.0)(typescript@5.9.3)':
+    dependencies:
+      '@typescript-eslint/tsconfig-utils': 8.67.0(typescript@5.9.3)
+      '@typescript-eslint/types': 8.67.0
+      debug: 4.4.3(supports-color@7.2.0)
+      typescript: 5.9.3
+    transitivePeerDependencies:
+      - supports-color
+
+  '@typescript-eslint/scope-manager@8.67.0':
+    dependencies:
+      '@typescript-eslint/types': 8.67.0
+      '@typescript-eslint/visitor-keys': 8.67.0
+
+  '@typescript-eslint/tsconfig-utils@8.67.0(typescript@5.9.3)':
+    dependencies:
+      typescript: 5.9.3
+
+  '@typescript-eslint/type-utils@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)':
+    dependencies:
+      '@typescript-eslint/types': 8.67.0
+      '@typescript-eslint/typescript-estree': 8.67.0(supports-color@7.2.0)(typescript@5.9.3)
+      '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
+      debug: 4.4.3(supports-color@7.2.0)
+      eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0)
+      ts-api-utils: 2.5.0(typescript@5.9.3)
+      typescript: 5.9.3
+    transitivePeerDependencies:
+      - supports-color
+
+  '@typescript-eslint/types@8.67.0': {}
+
+  '@typescript-eslint/typescript-estree@8.67.0(supports-color@7.2.0)(typescript@5.9.3)':
+    dependencies:
+      '@typescript-eslint/project-service': 8.67.0(supports-color@7.2.0)(typescript@5.9.3)
+      '@typescript-eslint/tsconfig-utils': 8.67.0(typescript@5.9.3)
+      '@typescript-eslint/types': 8.67.0
+      '@typescript-eslint/visitor-keys': 8.67.0
+      debug: 4.4.3(supports-color@7.2.0)
+      minimatch: 10.2.6
+      semver: 7.8.5
+      tinyglobby: 0.2.17
+      ts-api-utils: 2.5.0(typescript@5.9.3)
+      typescript: 5.9.3
+    transitivePeerDependencies:
+      - supports-color
+
+  '@typescript-eslint/utils@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)':
+    dependencies:
+      '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))
+      '@typescript-eslint/scope-manager': 8.67.0
+      '@typescript-eslint/types': 8.67.0
+      '@typescript-eslint/typescript-estree': 8.67.0(supports-color@7.2.0)(typescript@5.9.3)
+      eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0)
+      typescript: 5.9.3
+    transitivePeerDependencies:
+      - supports-color
+
+  '@typescript-eslint/visitor-keys@8.67.0':
+    dependencies:
+      '@typescript-eslint/types': 8.67.0
+      eslint-visitor-keys: 5.0.1
+
+  '@unrs/resolver-binding-android-arm-eabi@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-android-arm64@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-darwin-arm64@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-darwin-x64@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-freebsd-x64@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-linux-arm64-gnu@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-linux-arm64-musl@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-linux-loong64-gnu@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-linux-loong64-musl@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-linux-riscv64-musl@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-linux-s390x-gnu@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-linux-x64-gnu@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-linux-x64-musl@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-openharmony-arm64@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-wasm32-wasi@1.12.2':
+    dependencies:
+      '@emnapi/core': 1.10.0
+      '@emnapi/runtime': 1.10.0
+      '@napi-rs/wasm-runtime': 1.2.2(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)
+    optional: true
+
+  '@unrs/resolver-binding-win32-arm64-msvc@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-win32-ia32-msvc@1.12.2':
+    optional: true
+
+  '@unrs/resolver-binding-win32-x64-msvc@1.12.2':
+    optional: true
+
+  '@vitejs/plugin-react@6.0.5(vite@8.2.1(@types/node@20.19.43)(jiti@2.7.0))':
+    dependencies:
+      '@rolldown/pluginutils': 1.0.1
+      vite: 8.2.1(@types/node@20.19.43)(jiti@2.7.0)
+
+  '@vitest/expect@4.1.10':
+    dependencies:
+      '@standard-schema/spec': 1.1.0
+      '@types/chai': 5.2.3
+      '@vitest/spy': 4.1.10
+      '@vitest/utils': 4.1.10
+      chai: 6.2.2
+      tinyrainbow: 3.1.1
+
+  '@vitest/mocker@4.1.10(vite@8.2.1(@types/node@20.19.43)(jiti@2.7.0))':
+    dependencies:
+      '@vitest/spy': 4.1.10
+      estree-walker: 3.0.3
+      magic-string: 0.30.21
+    optionalDependencies:
+      vite: 8.2.1(@types/node@20.19.43)(jiti@2.7.0)
+
+  '@vitest/pretty-format@4.1.10':
+    dependencies:
+      tinyrainbow: 3.1.1
+
+  '@vitest/runner@4.1.10':
+    dependencies:
+      '@vitest/utils': 4.1.10
+      pathe: 2.0.3
+
+  '@vitest/snapshot@4.1.10':
+    dependencies:
+      '@vitest/pretty-format': 4.1.10
+      '@vitest/utils': 4.1.10
+      magic-string: 0.30.21
+      pathe: 2.0.3
+
+  '@vitest/spy@4.1.10': {}
+
+  '@vitest/utils@4.1.10':
+    dependencies:
+      '@vitest/pretty-format': 4.1.10
+      convert-source-map: 2.0.0
+      tinyrainbow: 3.1.1
+
+  acorn-jsx@5.3.2(acorn@8.18.0):
+    dependencies:
+      acorn: 8.18.0
+
+  acorn@8.18.0: {}
+
+  ajv@6.15.0:
+    dependencies:
+      fast-deep-equal: 3.1.3
+      fast-json-stable-stringify: 2.1.0
+      json-schema-traverse: 0.4.1
+      uri-js: 4.4.1
+
+  ansi-regex@5.0.1: {}
+
+  ansi-styles@4.3.0:
+    dependencies:
+      color-convert: 2.0.1
+
+  ansi-styles@5.2.0: {}
+
+  argparse@2.0.1: {}
+
+  aria-query@5.3.0:
+    dependencies:
+      dequal: 2.0.3
+
+  aria-query@5.3.2: {}
+
+  array-buffer-byte-length@1.0.2:
+    dependencies:
+      call-bound: 1.0.4
+      is-array-buffer: 3.0.5
+
+  array-includes@3.1.9:
+    dependencies:
+      call-bind: 1.0.9
+      call-bound: 1.0.4
+      define-properties: 1.2.1
+      es-abstract: 1.24.2
+      es-object-atoms: 1.1.2
+      get-intrinsic: 1.3.0
+      is-string: 1.1.1
+      math-intrinsics: 1.1.0
+
+  array.prototype.findlast@1.2.5:
+    dependencies:
+      call-bind: 1.0.9
+      define-properties: 1.2.1
+      es-abstract: 1.24.2
+      es-errors: 1.3.0
+      es-object-atoms: 1.1.2
+      es-shim-unscopables: 1.1.0
+
+  array.prototype.findlastindex@1.2.6:
+    dependencies:
+      call-bind: 1.0.9
+      call-bound: 1.0.4
+      define-properties: 1.2.1
+      es-abstract: 1.24.2
+      es-errors: 1.3.0
+      es-object-atoms: 1.1.2
+      es-shim-unscopables: 1.1.0
+
+  array.prototype.flat@1.3.3:
+    dependencies:
+      call-bind: 1.0.9
+      define-properties: 1.2.1
+      es-abstract: 1.24.2
+      es-shim-unscopables: 1.1.0
+
+  array.prototype.flatmap@1.3.3:
+    dependencies:
+      call-bind: 1.0.9
+      define-properties: 1.2.1
+      es-abstract: 1.24.2
+      es-shim-unscopables: 1.1.0
+
+  array.prototype.tosorted@1.1.4:
+    dependencies:
+      call-bind: 1.0.9
+      define-properties: 1.2.1
+      es-abstract: 1.24.2
+      es-errors: 1.3.0
+      es-shim-unscopables: 1.1.0
+
+  arraybuffer.prototype.slice@1.0.4:
+    dependencies:
+      array-buffer-byte-length: 1.0.2
+      call-bind: 1.0.9
+      define-properties: 1.2.1
+      es-abstract: 1.24.2
+      es-errors: 1.3.0
+      get-intrinsic: 1.3.0
+      is-array-buffer: 3.0.5
+
+  assertion-error@2.0.1: {}
+
+  ast-types-flow@0.0.8: {}
+
+  async-function@1.0.0: {}
+
+  available-typed-arrays@1.0.7:
+    dependencies:
+      possible-typed-array-names: 1.1.0
+
+  axe-core@4.13.0: {}
+
+  axobject-query@4.1.0: {}
+
+  balanced-match@1.0.2: {}
+
+  balanced-match@4.0.4: {}
+
+  baseline-browser-mapping@2.11.13: {}
+
+  bidi-js@1.0.3:
+    dependencies:
+      require-from-string: 2.0.2
+
+  brace-expansion@1.1.18:
+    dependencies:
+      balanced-match: 1.0.2
+      concat-map: 0.0.1
+
+  brace-expansion@5.0.9:
+    dependencies:
+      balanced-match: 4.0.4
+
+  braces@3.0.3:
+    dependencies:
+      fill-range: 7.1.1
+
+  browserslist@4.28.8:
+    dependencies:
+      baseline-browser-mapping: 2.11.13
+      caniuse-lite: 1.0.30001809
+      electron-to-chromium: 1.5.403
+      node-releases: 2.0.53
+      update-browserslist-db: 1.3.1(browserslist@4.28.8)
+
+  call-bind-apply-helpers@1.0.2:
+    dependencies:
+      es-errors: 1.3.0
+      function-bind: 1.1.2
+
+  call-bind@1.0.9:
+    dependencies:
+      call-bind-apply-helpers: 1.0.2
+      es-define-property: 1.0.1
+      get-intrinsic: 1.3.0
+      set-function-length: 1.2.2
+
+  call-bound@1.0.4:
+    dependencies:
+      call-bind-apply-helpers: 1.0.2
+      get-intrinsic: 1.3.0
+
+  callsites@3.1.0: {}
+
+  caniuse-lite@1.0.30001809: {}
+
+  chai@6.2.2: {}
+
+  chalk@4.1.2:
+    dependencies:
+      ansi-styles: 4.3.0
+      supports-color: 7.2.0
+
+  client-only@0.0.1: {}
+
+  color-convert@2.0.1:
+    dependencies:
+      color-name: 1.1.4
+
+  color-name@1.1.4: {}
+
+  concat-map@0.0.1: {}
+
+  convert-source-map@2.0.0: {}
+
+  cross-spawn@7.0.6:
+    dependencies:
+      path-key: 3.1.1
+      shebang-command: 2.0.0
+      which: 2.0.2
+
+  css-tree@3.2.1:
+    dependencies:
+      mdn-data: 2.27.1
+      source-map-js: 1.2.1
+
+  css.escape@1.5.1: {}
+
+  csstype@3.2.3: {}
+
+  damerau-levenshtein@1.0.8: {}
+
+  data-urls@7.0.0:
+    dependencies:
+      whatwg-mimetype: 5.0.0
+      whatwg-url: 16.0.1
+    transitivePeerDependencies:
+      - '@noble/hashes'
+
+  data-view-buffer@1.0.2:
+    dependencies:
+      call-bound: 1.0.4
+      es-errors: 1.3.0
+      is-data-view: 1.0.2
+
+  data-view-byte-length@1.0.2:
+    dependencies:
+      call-bound: 1.0.4
+      es-errors: 1.3.0
+      is-data-view: 1.0.2
+
+  data-view-byte-offset@1.0.1:
+    dependencies:
+      call-bound: 1.0.4
+      es-errors: 1.3.0
+      is-data-view: 1.0.2
+
+  debug@3.2.7(supports-color@7.2.0):
+    dependencies:
+      ms: 2.1.3
+    optionalDependencies:
+      supports-color: 7.2.0
+
+  debug@4.4.3(supports-color@7.2.0):
+    dependencies:
+      ms: 2.1.3
+    optionalDependencies:
+      supports-color: 7.2.0
+
+  decimal.js@10.6.0: {}
+
+  deep-is@0.1.4: {}
+
+  define-data-property@1.1.4:
+    dependencies:
+      es-define-property: 1.0.1
+      es-errors: 1.3.0
+      gopd: 1.2.0
+
+  define-properties@1.2.1:
+    dependencies:
+      define-data-property: 1.1.4
+      has-property-descriptors: 1.0.2
+      object-keys: 1.1.1
+
+  dequal@2.0.3: {}
+
+  detect-libc@2.1.2: {}
+
+  doctrine@2.1.0:
+    dependencies:
+      esutils: 2.0.3
+
+  dom-accessibility-api@0.5.16: {}
+
+  dom-accessibility-api@0.6.3: {}
+
+  dunder-proto@1.0.1:
+    dependencies:
+      call-bind-apply-helpers: 1.0.2
+      es-errors: 1.3.0
+      gopd: 1.2.0
+
+  electron-to-chromium@1.5.403: {}
+
+  emoji-regex@9.2.2: {}
+
+  enhanced-resolve@5.24.5:
+    dependencies:
+      graceful-fs: 4.2.11
+      tapable: 2.3.3
+
+  entities@8.0.0: {}
+
+  es-abstract-get@1.0.0:
+    dependencies:
+      es-errors: 1.3.0
+      es-object-atoms: 1.1.2
+      is-callable: 1.2.7
+      object-inspect: 1.13.4
+
+  es-abstract@1.24.2:
+    dependencies:
+      array-buffer-byte-length: 1.0.2
+      arraybuffer.prototype.slice: 1.0.4
+      available-typed-arrays: 1.0.7
+      call-bind: 1.0.9
+      call-bound: 1.0.4
+      data-view-buffer: 1.0.2
+      data-view-byte-length: 1.0.2
+      data-view-byte-offset: 1.0.1
+      es-define-property: 1.0.1
+      es-errors: 1.3.0
+      es-object-atoms: 1.1.2
+      es-set-tostringtag: 2.1.0
+      es-to-primitive: 1.3.4
+      function.prototype.name: 1.2.0
+      get-intrinsic: 1.3.0
+      get-proto: 1.0.1
+      get-symbol-description: 1.1.0
+      globalthis: 1.0.4
+      gopd: 1.2.0
+      has-property-descriptors: 1.0.2
+      has-proto: 1.2.0
+      has-symbols: 1.1.0
+      hasown: 2.0.4
+      internal-slot: 1.1.0
+      is-array-buffer: 3.0.5
+      is-callable: 1.2.7
+      is-data-view: 1.0.2
+      is-negative-zero: 2.0.3
+      is-regex: 1.2.1
+      is-set: 2.0.3
+      is-shared-array-buffer: 1.0.4
+      is-string: 1.1.1
+      is-typed-array: 1.1.15
+      is-weakref: 1.1.1
+      math-intrinsics: 1.1.0
+      object-inspect: 1.13.4
+      object-keys: 1.1.1
+      object.assign: 4.1.7
+      own-keys: 1.0.2
+      regexp.prototype.flags: 1.5.4
+      safe-array-concat: 1.1.4
+      safe-push-apply: 1.0.0
+      safe-regex-test: 1.1.0
+      set-proto: 1.0.0
+      stop-iteration-iterator: 1.1.0
+      string.prototype.trim: 1.2.11
+      string.prototype.trimend: 1.0.10
+      string.prototype.trimstart: 1.0.8
+      typed-array-buffer: 1.0.3
+      typed-array-byte-length: 1.0.3
+      typed-array-byte-offset: 1.0.4
+      typed-array-length: 1.0.8
+      unbox-primitive: 1.1.0
+      which-typed-array: 1.1.22
+
+  es-define-property@1.0.1: {}
+
+  es-errors@1.3.0: {}
+
+  es-iterator-helpers@1.4.0:
+    dependencies:
+      call-bind: 1.0.9
+      call-bound: 1.0.4
+      define-properties: 1.2.1
+      es-abstract: 1.24.2
+      es-errors: 1.3.0
+      es-set-tostringtag: 2.1.0
+      function-bind: 1.1.2
+      get-intrinsic: 1.3.0
+      globalthis: 1.0.4
+      gopd: 1.2.0
+      has-property-descriptors: 1.0.2
+      has-proto: 1.2.0
+      has-symbols: 1.1.0
+      internal-slot: 1.1.0
+      iterator.prototype: 1.1.5
+      math-intrinsics: 1.1.0
+
+  es-module-lexer@2.3.1: {}
+
+  es-object-atoms@1.1.2:
+    dependencies:
+      es-errors: 1.3.0
+
+  es-set-tostringtag@2.1.0:
+    dependencies:
+      es-errors: 1.3.0
+      get-intrinsic: 1.3.0
+      has-tostringtag: 1.0.2
+      hasown: 2.0.4
+
+  es-shim-unscopables@1.1.0:
+    dependencies:
+      hasown: 2.0.4
+
+  es-to-primitive@1.3.4:
+    dependencies:
+      es-abstract-get: 1.0.0
+      es-define-property: 1.0.1
+      es-errors: 1.3.0
+      is-callable: 1.2.7
+      is-date-object: 1.1.0
+      is-symbol: 1.1.1
+
+  escalade@3.2.0: {}
+
+  escape-string-regexp@4.0.0: {}
+
+  eslint-config-next@16.3.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3):
+    dependencies:
+      '@next/eslint-plugin-next': 16.3.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))
+      eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0)
+      eslint-import-resolver-node: 0.3.10(supports-color@7.2.0)
+      eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)
+      eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)
+      eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))
+      eslint-plugin-react: 7.37.5(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))
+      eslint-plugin-react-hooks: 7.1.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)
+      globals: 16.4.0
+      typescript-eslint: 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
+    optionalDependencies:
+      typescript: 5.9.3
+    transitivePeerDependencies:
+      - '@typescript-eslint/parser'
+      - eslint-import-resolver-webpack
+      - eslint-plugin-import-x
+      - supports-color
+
+  eslint-import-resolver-node@0.3.10(supports-color@7.2.0):
+    dependencies:
+      debug: 3.2.7(supports-color@7.2.0)
+      is-core-module: 2.16.2
+      resolve: 2.0.0-next.7
+    transitivePeerDependencies:
+      - supports-color
+
+  eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0):
+    dependencies:
+      '@nolyfill/is-core-module': 1.0.39
+      debug: 4.4.3(supports-color@7.2.0)
+      eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0)
+      get-tsconfig: 4.14.1
+      is-bun-module: 2.0.0
+      stable-hash: 0.0.5
+      tinyglobby: 0.2.17
+      unrs-resolver: 1.12.2
+    optionalDependencies:
+      eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)
+    transitivePeerDependencies:
+      - supports-color
+
+  eslint-module-utils@2.14.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-node@0.3.10(supports-color@7.2.0))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0):
+    dependencies:
+      debug: 3.2.7(supports-color@7.2.0)
+    optionalDependencies:
+      '@typescript-eslint/parser': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
+      eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0)
+      eslint-import-resolver-node: 0.3.10(supports-color@7.2.0)
+      eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)
+    transitivePeerDependencies:
+      - supports-color
+
+  eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0):
+    dependencies:
+      '@rtsao/scc': 1.1.0
+      array-includes: 3.1.9
+      array.prototype.findlastindex: 1.2.6
+      array.prototype.flat: 1.3.3
+      array.prototype.flatmap: 1.3.3
+      debug: 3.2.7(supports-color@7.2.0)
+      doctrine: 2.1.0
+      eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0)
+      eslint-import-resolver-node: 0.3.10(supports-color@7.2.0)
+      eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-node@0.3.10(supports-color@7.2.0))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)
+      hasown: 2.0.4
+      is-core-module: 2.16.2
+      is-glob: 4.0.3
+      minimatch: 3.1.5
+      object.fromentries: 2.0.8
+      object.groupby: 1.0.3
+      object.values: 1.2.1
+      semver: 6.3.1
+      string.prototype.trimend: 1.0.10
+      tsconfig-paths: 3.15.0
+    optionalDependencies:
+      '@typescript-eslint/parser': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
+    transitivePeerDependencies:
+      - eslint-import-resolver-typescript
+      - eslint-import-resolver-webpack
+      - supports-color
+
+  eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)):
+    dependencies:
+      aria-query: 5.3.2
+      array-includes: 3.1.9
+      array.prototype.flatmap: 1.3.3
+      ast-types-flow: 0.0.8
+      axe-core: 4.13.0
+      axobject-query: 4.1.0
+      damerau-levenshtein: 1.0.8
+      emoji-regex: 9.2.2
+      eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0)
+      hasown: 2.0.4
+      jsx-ast-utils: 3.3.5
+      language-tags: 1.0.9
+      minimatch: 3.1.5
+      object.fromentries: 2.0.8
+      safe-regex-test: 1.1.0
+      string.prototype.includes: 2.0.1
+
+  eslint-plugin-react-hooks@7.1.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0):
+    dependencies:
+      '@babel/core': 7.29.7(supports-color@7.2.0)
+      '@babel/parser': 7.29.8
+      eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0)
+      hermes-parser: 0.25.1
+      zod: 4.4.3
+      zod-validation-error: 4.0.2(zod@4.4.3)
+    transitivePeerDependencies:
+      - supports-color
+
+  eslint-plugin-react@7.37.5(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)):
+    dependencies:
+      array-includes: 3.1.9
+      array.prototype.findlast: 1.2.5
+      array.prototype.flatmap: 1.3.3
+      array.prototype.tosorted: 1.1.4
+      doctrine: 2.1.0
+      es-iterator-helpers: 1.4.0
+      eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0)
+      estraverse: 5.3.0
+      hasown: 2.0.4
+      jsx-ast-utils: 3.3.5
+      minimatch: 3.1.5
+      object.entries: 1.1.9
+      object.fromentries: 2.0.8
+      object.values: 1.2.1
+      prop-types: 15.8.1
+      resolve: 2.0.0-next.7
+      semver: 6.3.1
+      string.prototype.matchall: 4.0.12
+      string.prototype.repeat: 1.0.0
+
+  eslint-scope@8.4.0:
+    dependencies:
+      esrecurse: 4.3.0
+      estraverse: 5.3.0
+
+  eslint-visitor-keys@3.4.3: {}
+
+  eslint-visitor-keys@4.2.1: {}
+
+  eslint-visitor-keys@5.0.1: {}
+
+  eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0):
+    dependencies:
+      '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))
+      '@eslint-community/regexpp': 4.12.2
+      '@eslint/config-array': 0.21.2(supports-color@7.2.0)
+      '@eslint/config-helpers': 0.4.2
+      '@eslint/core': 0.17.0
+      '@eslint/eslintrc': 3.3.6(supports-color@7.2.0)
+      '@eslint/js': 9.39.5
+      '@eslint/plugin-kit': 0.4.1
+      '@humanfs/node': 0.16.8
+      '@humanwhocodes/module-importer': 1.0.1
+      '@humanwhocodes/retry': 0.4.3
+      '@types/estree': 1.0.9
+      ajv: 6.15.0
+      chalk: 4.1.2
+      cross-spawn: 7.0.6
+      debug: 4.4.3(supports-color@7.2.0)
+      escape-string-regexp: 4.0.0
+      eslint-scope: 8.4.0
+      eslint-visitor-keys: 4.2.1
+      espree: 10.4.0
+      esquery: 1.7.0
+      esutils: 2.0.3
+      fast-deep-equal: 3.1.3
+      file-entry-cache: 8.0.0
+      find-up: 5.0.0
+      glob-parent: 6.0.2
+      ignore: 5.3.2
+      imurmurhash: 0.1.4
+      is-glob: 4.0.3
+      json-stable-stringify-without-jsonify: 1.0.1
+      lodash.merge: 4.6.2
+      minimatch: 3.1.5
+      natural-compare: 1.4.0
+      optionator: 0.9.4
+    optionalDependencies:
+      jiti: 2.7.0
+    transitivePeerDependencies:
+      - supports-color
+
+  espree@10.4.0:
+    dependencies:
+      acorn: 8.18.0
+      acorn-jsx: 5.3.2(acorn@8.18.0)
+      eslint-visitor-keys: 4.2.1
+
+  esquery@1.7.0:
+    dependencies:
+      estraverse: 5.3.0
+
+  esrecurse@4.3.0:
+    dependencies:
+      estraverse: 5.3.0
+
+  estraverse@5.3.0: {}
+
+  estree-walker@3.0.3:
+    dependencies:
+      '@types/estree': 1.0.9
+
+  esutils@2.0.3: {}
+
+  expect-type@1.4.0: {}
+
+  fast-deep-equal@3.1.3: {}
+
+  fast-glob@3.3.1:
+    dependencies:
+      '@nodelib/fs.stat': 2.0.5
+      '@nodelib/fs.walk': 1.2.8
+      glob-parent: 5.1.2
+      merge2: 1.4.1
+      micromatch: 4.0.8
+
+  fast-json-stable-stringify@2.1.0: {}
+
+  fast-levenshtein@2.0.6: {}
+
+  fast-sha256@1.3.0: {}
+
+  fastq@1.20.1:
+    dependencies:
+      reusify: 1.1.0
+
+  fdir@6.5.0(picomatch@4.0.5):
+    optionalDependencies:
+      picomatch: 4.0.5
+
+  file-entry-cache@8.0.0:
+    dependencies:
+      flat-cache: 4.0.1
+
+  fill-range@7.1.1:
+    dependencies:
+      to-regex-range: 5.0.1
+
+  find-up@5.0.0:
+    dependencies:
+      locate-path: 6.0.0
+      path-exists: 4.0.0
+
+  flat-cache@4.0.1:
+    dependencies:
+      flatted: 3.4.4
+      keyv: 4.5.4
+
+  flatted@3.4.4: {}
+
+  for-each@0.3.5:
+    dependencies:
+      is-callable: 1.2.7
+
+  fsevents@2.3.3:
+    optional: true
+
+  function-bind@1.1.2: {}
+
+  function.prototype.name@1.2.0:
+    dependencies:
+      call-bind: 1.0.9
+      call-bound: 1.0.4
+      es-define-property: 1.0.1
+      es-errors: 1.3.0
+      functions-have-names: 1.2.3
+      has-property-descriptors: 1.0.2
+      hasown: 2.0.4
+      is-callable: 1.2.7
+      is-document.all: 1.0.0
+
+  functions-have-names@1.2.3: {}
+
+  generator-function@2.0.1: {}
+
+  gensync@1.0.0-beta.2: {}
+
+  get-intrinsic@1.3.0:
+    dependencies:
+      call-bind-apply-helpers: 1.0.2
+      es-define-property: 1.0.1
+      es-errors: 1.3.0
+      es-object-atoms: 1.1.2
+      function-bind: 1.1.2
+      get-proto: 1.0.1
+      gopd: 1.2.0
+      has-symbols: 1.1.0
+      hasown: 2.0.4
+      math-intrinsics: 1.1.0
+
+  get-proto@1.0.1:
+    dependencies:
+      dunder-proto: 1.0.1
+      es-object-atoms: 1.1.2
+
+  get-symbol-description@1.1.0:
+    dependencies:
+      call-bound: 1.0.4
+      es-errors: 1.3.0
+      get-intrinsic: 1.3.0
+
+  get-tsconfig@4.14.1:
+    dependencies:
+      resolve-pkg-maps: 1.0.0
+
+  glob-parent@5.1.2:
+    dependencies:
+      is-glob: 4.0.3
+
+  glob-parent@6.0.2:
+    dependencies:
+      is-glob: 4.0.3
+
+  globals@14.0.0: {}
+
+  globals@16.4.0: {}
+
+  globalthis@1.0.4:
+    dependencies:
+      define-properties: 1.2.1
+      gopd: 1.2.0
+
+  gopd@1.2.0: {}
+
+  graceful-fs@4.2.11: {}
+
+  has-bigints@1.1.0: {}
+
+  has-flag@4.0.0: {}
+
+  has-property-descriptors@1.0.2:
+    dependencies:
+      es-define-property: 1.0.1
+
+  has-proto@1.2.0:
+    dependencies:
+      dunder-proto: 1.0.1
+
+  has-symbols@1.1.0: {}
+
+  has-tostringtag@1.0.2:
+    dependencies:
+      has-symbols: 1.1.0
+
+  hasown@2.0.4:
+    dependencies:
+      function-bind: 1.1.2
+
+  hermes-estree@0.25.1: {}
+
+  hermes-parser@0.25.1:
+    dependencies:
+      hermes-estree: 0.25.1
+
+  html-encoding-sniffer@6.0.0:
+    dependencies:
+      '@exodus/bytes': 1.15.1
+    transitivePeerDependencies:
+      - '@noble/hashes'
+
+  ignore@5.3.2: {}
+
+  ignore@7.0.6: {}
+
+  import-fresh@3.3.1:
+    dependencies:
+      parent-module: 1.0.1
+      resolve-from: 4.0.0
+
+  imurmurhash@0.1.4: {}
+
+  indent-string@4.0.0: {}
+
+  internal-slot@1.1.0:
+    dependencies:
+      es-errors: 1.3.0
+      hasown: 2.0.4
+      side-channel: 1.1.1
+
+  is-array-buffer@3.0.5:
+    dependencies:
+      call-bind: 1.0.9
+      call-bound: 1.0.4
+      get-intrinsic: 1.3.0
+
+  is-async-function@2.1.1:
+    dependencies:
+      async-function: 1.0.0
+      call-bound: 1.0.4
+      get-proto: 1.0.1
+      has-tostringtag: 1.0.2
+      safe-regex-test: 1.1.0
+
+  is-bigint@1.1.0:
+    dependencies:
+      has-bigints: 1.1.0
+
+  is-boolean-object@1.2.2:
+    dependencies:
+      call-bound: 1.0.4
+      has-tostringtag: 1.0.2
+
+  is-bun-module@2.0.0:
+    dependencies:
+      semver: 7.8.5
+
+  is-callable@1.2.7: {}
+
+  is-core-module@2.16.2:
+    dependencies:
+      hasown: 2.0.4
+
+  is-data-view@1.0.2:
+    dependencies:
+      call-bound: 1.0.4
+      get-intrinsic: 1.3.0
+      is-typed-array: 1.1.15
+
+  is-date-object@1.1.0:
+    dependencies:
+      call-bound: 1.0.4
+      has-tostringtag: 1.0.2
+
+  is-document.all@1.0.0:
+    dependencies:
+      call-bound: 1.0.4
+
+  is-extglob@2.1.1: {}
+
+  is-finalizationregistry@1.1.1:
+    dependencies:
+      call-bound: 1.0.4
+
+  is-generator-function@1.1.2:
+    dependencies:
+      call-bound: 1.0.4
+      generator-function: 2.0.1
+      get-proto: 1.0.1
+      has-tostringtag: 1.0.2
+      safe-regex-test: 1.1.0
+
+  is-glob@4.0.3:
+    dependencies:
+      is-extglob: 2.1.1
+
+  is-map@2.0.3: {}
+
+  is-negative-zero@2.0.3: {}
+
+  is-number-object@1.1.1:
+    dependencies:
+      call-bound: 1.0.4
+      has-tostringtag: 1.0.2
+
+  is-number@7.0.0: {}
+
+  is-potential-custom-element-name@1.0.1: {}
+
+  is-regex@1.2.1:
+    dependencies:
+      call-bound: 1.0.4
+      gopd: 1.2.0
+      has-tostringtag: 1.0.2
+      hasown: 2.0.4
+
+  is-set@2.0.3: {}
+
+  is-shared-array-buffer@1.0.4:
+    dependencies:
+      call-bound: 1.0.4
+
+  is-string@1.1.1:
+    dependencies:
+      call-bound: 1.0.4
+      has-tostringtag: 1.0.2
+
+  is-symbol@1.1.1:
+    dependencies:
+      call-bound: 1.0.4
+      has-symbols: 1.1.0
+      safe-regex-test: 1.1.0
+
+  is-typed-array@1.1.15:
+    dependencies:
+      which-typed-array: 1.1.22
+
+  is-weakmap@2.0.2: {}
+
+  is-weakref@1.1.1:
+    dependencies:
+      call-bound: 1.0.4
+
+  is-weakset@2.0.4:
+    dependencies:
+      call-bound: 1.0.4
+      get-intrinsic: 1.3.0
+
+  isarray@2.0.5: {}
+
+  isexe@2.0.0: {}
+
+  iterator.prototype@1.1.5:
+    dependencies:
+      define-data-property: 1.1.4
+      es-object-atoms: 1.1.2
+      get-intrinsic: 1.3.0
+      get-proto: 1.0.1
+      has-symbols: 1.1.0
+      set-function-name: 2.0.2
+
+  jiti@2.7.0: {}
+
+  js-tokens@4.0.0: {}
+
+  js-yaml@4.3.1:
+    dependencies:
+      argparse: 2.0.1
+
+  jsdom@30.0.1:
+    dependencies:
+      '@asamuzakjp/css-color': 6.0.7
+      '@asamuzakjp/dom-selector': 8.3.2
+      '@bramus/specificity': 2.4.2
+      '@csstools/css-syntax-patches-for-csstree': 1.1.7(css-tree@3.2.1)
+      '@exodus/bytes': 1.15.1
+      css-tree: 3.2.1
+      data-urls: 7.0.0
+      decimal.js: 10.6.0
+      html-encoding-sniffer: 6.0.0
+      is-potential-custom-element-name: 1.0.1
+      lru-cache: 11.5.2
+      parse5: 8.0.1
+      saxes: 6.0.0
+      symbol-tree: 3.2.4
+      tough-cookie: 6.0.2
+      undici: 8.10.0
+      w3c-xmlserializer: 5.0.0
+      webidl-conversions: 8.0.1
+      whatwg-mimetype: 5.0.0
+      whatwg-url: 17.1.0
+      xml-name-validator: 5.0.0
+    transitivePeerDependencies:
+      - '@noble/hashes'
+
+  jsesc@3.1.0: {}
+
+  json-buffer@3.0.1: {}
+
+  json-schema-traverse@0.4.1: {}
+
+  json-stable-stringify-without-jsonify@1.0.1: {}
+
+  json5@1.0.2:
+    dependencies:
+      minimist: 1.2.8
+
+  json5@2.2.3: {}
+
+  jsx-ast-utils@3.3.5:
+    dependencies:
+      array-includes: 3.1.9
+      array.prototype.flat: 1.3.3
+      object.assign: 4.1.7
+      object.values: 1.2.1
+
+  keyv@4.5.4:
+    dependencies:
+      json-buffer: 3.0.1
+
+  language-subtag-registry@0.3.23: {}
+
+  language-tags@1.0.9:
+    dependencies:
+      language-subtag-registry: 0.3.23
+
+  levn@0.4.1:
+    dependencies:
+      prelude-ls: 1.2.1
+      type-check: 0.4.0
+
+  lightningcss-android-arm64@1.32.0:
+    optional: true
+
+  lightningcss-android-arm64@1.33.0:
+    optional: true
+
+  lightningcss-darwin-arm64@1.32.0:
+    optional: true
+
+  lightningcss-darwin-arm64@1.33.0:
+    optional: true
+
+  lightningcss-darwin-x64@1.32.0:
+    optional: true
+
+  lightningcss-darwin-x64@1.33.0:
+    optional: true
+
+  lightningcss-freebsd-x64@1.32.0:
+    optional: true
+
+  lightningcss-freebsd-x64@1.33.0:
+    optional: true
+
+  lightningcss-linux-arm-gnueabihf@1.32.0:
+    optional: true
+
+  lightningcss-linux-arm-gnueabihf@1.33.0:
+    optional: true
+
+  lightningcss-linux-arm64-gnu@1.32.0:
+    optional: true
+
+  lightningcss-linux-arm64-gnu@1.33.0:
+    optional: true
+
+  lightningcss-linux-arm64-musl@1.32.0:
+    optional: true
+
+  lightningcss-linux-arm64-musl@1.33.0:
+    optional: true
+
+  lightningcss-linux-x64-gnu@1.32.0:
+    optional: true
+
+  lightningcss-linux-x64-gnu@1.33.0:
+    optional: true
+
+  lightningcss-linux-x64-musl@1.32.0:
+    optional: true
+
+  lightningcss-linux-x64-musl@1.33.0:
+    optional: true
+
+  lightningcss-win32-arm64-msvc@1.32.0:
+    optional: true
+
+  lightningcss-win32-arm64-msvc@1.33.0:
+    optional: true
+
+  lightningcss-win32-x64-msvc@1.32.0:
+    optional: true
+
+  lightningcss-win32-x64-msvc@1.33.0:
+    optional: true
+
+  lightningcss@1.32.0:
+    dependencies:
+      detect-libc: 2.1.2
+    optionalDependencies:
+      lightningcss-android-arm64: 1.32.0
+      lightningcss-darwin-arm64: 1.32.0
+      lightningcss-darwin-x64: 1.32.0
+      lightningcss-freebsd-x64: 1.32.0
+      lightningcss-linux-arm-gnueabihf: 1.32.0
+      lightningcss-linux-arm64-gnu: 1.32.0
+      lightningcss-linux-arm64-musl: 1.32.0
+      lightningcss-linux-x64-gnu: 1.32.0
+      lightningcss-linux-x64-musl: 1.32.0
+      lightningcss-win32-arm64-msvc: 1.32.0
+      lightningcss-win32-x64-msvc: 1.32.0
+
+  lightningcss@1.33.0:
+    dependencies:
+      detect-libc: 2.1.2
+    optionalDependencies:
+      lightningcss-android-arm64: 1.33.0
+      lightningcss-darwin-arm64: 1.33.0
+      lightningcss-darwin-x64: 1.33.0
+      lightningcss-freebsd-x64: 1.33.0
+      lightningcss-linux-arm-gnueabihf: 1.33.0
+      lightningcss-linux-arm64-gnu: 1.33.0
+      lightningcss-linux-arm64-musl: 1.33.0
+      lightningcss-linux-x64-gnu: 1.33.0
+      lightningcss-linux-x64-musl: 1.33.0
+      lightningcss-win32-arm64-msvc: 1.33.0
+      lightningcss-win32-x64-msvc: 1.33.0
+
+  locate-path@6.0.0:
+    dependencies:
+      p-locate: 5.0.0
+
+  lodash.merge@4.6.2: {}
+
+  loose-envify@1.4.0:
+    dependencies:
+      js-tokens: 4.0.0
+
+  lru-cache@11.5.2: {}
+
+  lru-cache@5.1.1:
+    dependencies:
+      yallist: 3.1.1
+
+  lucide-react@1.31.0(react@19.2.8):
+    dependencies:
+      react: 19.2.8
+
+  lz-string@1.5.0: {}
+
+  magic-string@0.30.21:
+    dependencies:
+      '@jridgewell/sourcemap-codec': 1.5.5
+
+  math-intrinsics@1.1.0: {}
+
+  mdn-data@2.27.1: {}
+
+  merge2@1.4.1: {}
+
+  micromatch@4.0.8:
+    dependencies:
+      braces: 3.0.3
+      picomatch: 2.3.2
+
+  min-indent@1.0.1: {}
+
+  minimatch@10.2.6:
+    dependencies:
+      brace-expansion: 5.0.9
+
+  minimatch@3.1.5:
+    dependencies:
+      brace-expansion: 1.1.18
+
+  minimist@1.2.8: {}
+
+  ms@2.1.3: {}
+
+  nanoid@3.3.18: {}
+
+  napi-postinstall@0.3.4: {}
+
+  natural-compare@1.4.0: {}
+
+  next@16.3.0(@babel/core@7.29.7(supports-color@7.2.0))(@types/node@20.19.43)(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
+    dependencies:
+      '@next/env': 16.3.0
+      '@swc/helpers': 0.5.15
+      baseline-browser-mapping: 2.11.13
+      caniuse-lite: 1.0.30001809
+      postcss: 8.5.23
+      react: 19.2.8
+      react-dom: 19.2.8(react@19.2.8)
+      styled-jsx: 5.1.6(@babel/core@7.29.7(supports-color@7.2.0))(react@19.2.8)
+    optionalDependencies:
+      '@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(@types/node@20.19.43)
+    transitivePeerDependencies:
+      - '@babel/core'
+      - '@types/node'
+      - babel-plugin-macros
+
+  node-exports-info@1.6.2:
+    dependencies:
+      array.prototype.flatmap: 1.3.3
+      es-errors: 1.3.0
+      object.entries: 1.1.9
+      semver: 6.3.1
+
+  node-releases@2.0.53: {}
+
+  object-assign@4.1.1: {}
+
+  object-inspect@1.13.4: {}
+
+  object-keys@1.1.1: {}
+
+  object.assign@4.1.7:
+    dependencies:
+      call-bind: 1.0.9
+      call-bound: 1.0.4
+      define-properties: 1.2.1
+      es-object-atoms: 1.1.2
+      has-symbols: 1.1.0
+      object-keys: 1.1.1
+
+  object.entries@1.1.9:
+    dependencies:
+      call-bind: 1.0.9
+      call-bound: 1.0.4
+      define-properties: 1.2.1
+      es-object-atoms: 1.1.2
+
+  object.fromentries@2.0.8:
+    dependencies:
+      call-bind: 1.0.9
+      define-properties: 1.2.1
+      es-abstract: 1.24.2
+      es-object-atoms: 1.1.2
+
+  object.groupby@1.0.3:
+    dependencies:
+      call-bind: 1.0.9
+      define-properties: 1.2.1
+      es-abstract: 1.24.2
+
+  object.values@1.2.1:
+    dependencies:
+      call-bind: 1.0.9
+      call-bound: 1.0.4
+      define-properties: 1.2.1
+      es-object-atoms: 1.1.2
+
+  obug@2.1.4: {}
+
+  optionator@0.9.4:
+    dependencies:
+      deep-is: 0.1.4
+      fast-levenshtein: 2.0.6
+      levn: 0.4.1
+      prelude-ls: 1.2.1
+      type-check: 0.4.0
+      word-wrap: 1.2.5
+
+  own-keys@1.0.2:
+    dependencies:
+      call-bound: 1.0.4
+      get-intrinsic: 1.3.0
+      object-keys: 1.1.1
+      safe-push-apply: 1.0.0
+
+  p-limit@3.1.0:
+    dependencies:
+      yocto-queue: 0.1.0
+
+  p-locate@5.0.0:
+    dependencies:
+      p-limit: 3.1.0
+
+  parent-module@1.0.1:
+    dependencies:
+      callsites: 3.1.0
+
+  parse5@8.0.1:
+    dependencies:
+      entities: 8.0.0
+
+  path-exists@4.0.0: {}
+
+  path-key@3.1.1: {}
+
+  path-parse@1.0.7: {}
+
+  pathe@2.0.3: {}
+
+  picocolors@1.1.1: {}
+
+  picomatch@2.3.2: {}
+
+  picomatch@4.0.5: {}
+
+  possible-typed-array-names@1.1.0: {}
+
+  postal-mime@2.7.5: {}
+
+  postcss@8.5.23:
+    dependencies:
+      nanoid: 3.3.18
+      picocolors: 1.1.1
+      source-map-js: 1.2.1
+
+  postcss@8.5.26:
+    dependencies:
+      nanoid: 3.3.18
+      picocolors: 1.1.1
+      source-map-js: 1.2.1
+
+  prelude-ls@1.2.1: {}
+
+  pretty-format@27.5.1:
+    dependencies:
+      ansi-regex: 5.0.1
+      ansi-styles: 5.2.0
+      react-is: 17.0.2
+
+  prop-types@15.8.1:
+    dependencies:
+      loose-envify: 1.4.0
+      object-assign: 4.1.1
+      react-is: 16.13.1
+
+  punycode@2.3.1: {}
+
+  queue-microtask@1.2.3: {}
+
+  react-dom@19.2.8(react@19.2.8):
+    dependencies:
+      react: 19.2.8
+      scheduler: 0.27.0
+
+  react-hook-form@7.85.0(react@19.2.8):
+    dependencies:
+      react: 19.2.8
+
+  react-is@16.13.1: {}
+
+  react-is@17.0.2: {}
+
+  react@19.2.8: {}
+
+  redent@3.0.0:
+    dependencies:
+      indent-string: 4.0.0
+      strip-indent: 3.0.0
+
+  reflect.getprototypeof@1.0.10:
+    dependencies:
+      call-bind: 1.0.9
+      define-properties: 1.2.1
+      es-abstract: 1.24.2
+      es-errors: 1.3.0
+      es-object-atoms: 1.1.2
+      get-intrinsic: 1.3.0
+      get-proto: 1.0.1
+      which-builtin-type: 1.2.1
+
+  regexp.prototype.flags@1.5.4:
+    dependencies:
+      call-bind: 1.0.9
+      define-properties: 1.2.1
+      es-errors: 1.3.0
+      get-proto: 1.0.1
+      gopd: 1.2.0
+      set-function-name: 2.0.2
+
+  require-from-string@2.0.2: {}
+
+  resend@6.19.0:
+    dependencies:
+      postal-mime: 2.7.5
+      standardwebhooks: 1.0.0
+
+  resolve-from@4.0.0: {}
+
+  resolve-pkg-maps@1.0.0: {}
+
+  resolve@2.0.0-next.7:
+    dependencies:
+      es-errors: 1.3.0
+      is-core-module: 2.16.2
+      node-exports-info: 1.6.2
+      object-keys: 1.1.1
+      path-parse: 1.0.7
+      supports-preserve-symlinks-flag: 1.0.0
+
+  reusify@1.1.0: {}
+
+  rolldown@1.2.3:
+    dependencies:
+      '@oxc-project/types': 0.143.0
+      '@rolldown/pluginutils': 1.0.1
+    optionalDependencies:
+      '@rolldown/binding-android-arm64': 1.2.3
+      '@rolldown/binding-darwin-arm64': 1.2.3
+      '@rolldown/binding-darwin-x64': 1.2.3
+      '@rolldown/binding-freebsd-x64': 1.2.3
+      '@rolldown/binding-linux-arm-gnueabihf': 1.2.3
+      '@rolldown/binding-linux-arm64-gnu': 1.2.3
+      '@rolldown/binding-linux-arm64-musl': 1.2.3
+      '@rolldown/binding-linux-ppc64-gnu': 1.2.3
+      '@rolldown/binding-linux-s390x-gnu': 1.2.3
+      '@rolldown/binding-linux-x64-gnu': 1.2.3
+      '@rolldown/binding-linux-x64-musl': 1.2.3
+      '@rolldown/binding-openharmony-arm64': 1.2.3
+      '@rolldown/binding-win32-arm64-msvc': 1.2.3
+      '@rolldown/binding-win32-x64-msvc': 1.2.3
+
+  run-parallel@1.2.0:
+    dependencies:
+      queue-microtask: 1.2.3
+
+  safe-array-concat@1.1.4:
+    dependencies:
+      call-bind: 1.0.9
+      call-bound: 1.0.4
+      get-intrinsic: 1.3.0
+      has-symbols: 1.1.0
+      isarray: 2.0.5
+
+  safe-push-apply@1.0.0:
+    dependencies:
+      es-errors: 1.3.0
+      isarray: 2.0.5
+
+  safe-regex-test@1.1.0:
+    dependencies:
+      call-bound: 1.0.4
+      es-errors: 1.3.0
+      is-regex: 1.2.1
+
+  saxes@6.0.0:
+    dependencies:
+      xmlchars: 2.2.0
+
+  scheduler@0.27.0: {}
+
+  semver@6.3.1: {}
+
+  semver@7.8.5: {}
+
+  set-function-length@1.2.2:
+    dependencies:
+      define-data-property: 1.1.4
+      es-errors: 1.3.0
+      function-bind: 1.1.2
+      get-intrinsic: 1.3.0
+      gopd: 1.2.0
+      has-property-descriptors: 1.0.2
+
+  set-function-name@2.0.2:
+    dependencies:
+      define-data-property: 1.1.4
+      es-errors: 1.3.0
+      functions-have-names: 1.2.3
+      has-property-descriptors: 1.0.2
+
+  set-proto@1.0.0:
+    dependencies:
+      dunder-proto: 1.0.1
+      es-errors: 1.3.0
+      es-object-atoms: 1.1.2
+
+  sharp@0.35.3(@types/node@20.19.43):
+    dependencies:
+      '@img/colour': 1.1.0
+      detect-libc: 2.1.2
+      semver: 7.8.5
+    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
+      '@types/node': 20.19.43
+    optional: true
+
+  shebang-command@2.0.0:
+    dependencies:
+      shebang-regex: 3.0.0
+
+  shebang-regex@3.0.0: {}
+
+  side-channel-list@1.0.1:
+    dependencies:
+      es-errors: 1.3.0
+      object-inspect: 1.13.4
+
+  side-channel-map@1.0.1:
+    dependencies:
+      call-bound: 1.0.4
+      es-errors: 1.3.0
+      get-intrinsic: 1.3.0
+      object-inspect: 1.13.4
+
+  side-channel-weakmap@1.0.2:
+    dependencies:
+      call-bound: 1.0.4
+      es-errors: 1.3.0
+      get-intrinsic: 1.3.0
+      object-inspect: 1.13.4
+      side-channel-map: 1.0.1
+
+  side-channel@1.1.1:
+    dependencies:
+      es-errors: 1.3.0
+      object-inspect: 1.13.4
+      side-channel-list: 1.0.1
+      side-channel-map: 1.0.1
+      side-channel-weakmap: 1.0.2
+
+  siginfo@2.0.0: {}
+
+  source-map-js@1.2.1: {}
+
+  stable-hash@0.0.5: {}
+
+  stackback@0.0.2: {}
+
+  standardwebhooks@1.0.0:
+    dependencies:
+      '@stablelib/base64': 1.0.1
+      fast-sha256: 1.3.0
+
+  std-env@4.2.0: {}
+
+  stop-iteration-iterator@1.1.0:
+    dependencies:
+      es-errors: 1.3.0
+      internal-slot: 1.1.0
+
+  string.prototype.includes@2.0.1:
+    dependencies:
+      call-bind: 1.0.9
+      define-properties: 1.2.1
+      es-abstract: 1.24.2
+
+  string.prototype.matchall@4.0.12:
+    dependencies:
+      call-bind: 1.0.9
+      call-bound: 1.0.4
+      define-properties: 1.2.1
+      es-abstract: 1.24.2
+      es-errors: 1.3.0
+      es-object-atoms: 1.1.2
+      get-intrinsic: 1.3.0
+      gopd: 1.2.0
+      has-symbols: 1.1.0
+      internal-slot: 1.1.0
+      regexp.prototype.flags: 1.5.4
+      set-function-name: 2.0.2
+      side-channel: 1.1.1
+
+  string.prototype.repeat@1.0.0:
+    dependencies:
+      define-properties: 1.2.1
+      es-abstract: 1.24.2
+
+  string.prototype.trim@1.2.11:
+    dependencies:
+      call-bind: 1.0.9
+      call-bound: 1.0.4
+      define-data-property: 1.1.4
+      define-properties: 1.2.1
+      es-abstract: 1.24.2
+      es-object-atoms: 1.1.2
+      has-property-descriptors: 1.0.2
+      safe-regex-test: 1.1.0
+
+  string.prototype.trimend@1.0.10:
+    dependencies:
+      call-bind: 1.0.9
+      call-bound: 1.0.4
+      define-properties: 1.2.1
+      es-object-atoms: 1.1.2
+
+  string.prototype.trimstart@1.0.8:
+    dependencies:
+      call-bind: 1.0.9
+      define-properties: 1.2.1
+      es-object-atoms: 1.1.2
+
+  strip-bom@3.0.0: {}
+
+  strip-indent@3.0.0:
+    dependencies:
+      min-indent: 1.0.1
+
+  strip-json-comments@3.1.1: {}
+
+  styled-jsx@5.1.6(@babel/core@7.29.7(supports-color@7.2.0))(react@19.2.8):
+    dependencies:
+      client-only: 0.0.1
+      react: 19.2.8
+    optionalDependencies:
+      '@babel/core': 7.29.7(supports-color@7.2.0)
+
+  supports-color@7.2.0:
+    dependencies:
+      has-flag: 4.0.0
+
+  supports-preserve-symlinks-flag@1.0.0: {}
+
+  symbol-tree@3.2.4: {}
+
+  tailwindcss@4.3.3: {}
+
+  tapable@2.3.3: {}
+
+  tinybench@2.9.0: {}
+
+  tinyexec@1.3.0: {}
+
+  tinyglobby@0.2.17:
+    dependencies:
+      fdir: 6.5.0(picomatch@4.0.5)
+      picomatch: 4.0.5
+
+  tinyrainbow@3.1.1: {}
+
+  tldts-core@7.4.10: {}
+
+  tldts@7.4.10:
+    dependencies:
+      tldts-core: 7.4.10
+
+  to-regex-range@5.0.1:
+    dependencies:
+      is-number: 7.0.0
+
+  tough-cookie@6.0.2:
+    dependencies:
+      tldts: 7.4.10
+
+  tr46@6.0.0:
+    dependencies:
+      punycode: 2.3.1
+
+  ts-api-utils@2.5.0(typescript@5.9.3):
+    dependencies:
+      typescript: 5.9.3
+
+  tsconfig-paths@3.15.0:
+    dependencies:
+      '@types/json5': 0.0.29
+      json5: 1.0.2
+      minimist: 1.2.8
+      strip-bom: 3.0.0
+
+  tslib@2.8.1: {}
+
+  type-check@0.4.0:
+    dependencies:
+      prelude-ls: 1.2.1
+
+  typed-array-buffer@1.0.3:
+    dependencies:
+      call-bound: 1.0.4
+      es-errors: 1.3.0
+      is-typed-array: 1.1.15
+
+  typed-array-byte-length@1.0.3:
+    dependencies:
+      call-bind: 1.0.9
+      for-each: 0.3.5
+      gopd: 1.2.0
+      has-proto: 1.2.0
+      is-typed-array: 1.1.15
+
+  typed-array-byte-offset@1.0.4:
+    dependencies:
+      available-typed-arrays: 1.0.7
+      call-bind: 1.0.9
+      for-each: 0.3.5
+      gopd: 1.2.0
+      has-proto: 1.2.0
+      is-typed-array: 1.1.15
+      reflect.getprototypeof: 1.0.10
+
+  typed-array-length@1.0.8:
+    dependencies:
+      call-bind: 1.0.9
+      for-each: 0.3.5
+      gopd: 1.2.0
+      is-typed-array: 1.1.15
+      possible-typed-array-names: 1.1.0
+      reflect.getprototypeof: 1.0.10
+
+  typescript-eslint@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3):
+    dependencies:
+      '@typescript-eslint/eslint-plugin': 8.67.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
+      '@typescript-eslint/parser': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
+      '@typescript-eslint/typescript-estree': 8.67.0(supports-color@7.2.0)(typescript@5.9.3)
+      '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)
+      eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0)
+      typescript: 5.9.3
+    transitivePeerDependencies:
+      - supports-color
+
+  typescript@5.9.3: {}
+
+  unbox-primitive@1.1.0:
+    dependencies:
+      call-bound: 1.0.4
+      has-bigints: 1.1.0
+      has-symbols: 1.1.0
+      which-boxed-primitive: 1.1.1
+
+  undici-types@6.21.0: {}
+
+  undici@8.10.0: {}
+
+  unrs-resolver@1.12.2:
+    dependencies:
+      napi-postinstall: 0.3.4
+    optionalDependencies:
+      '@unrs/resolver-binding-android-arm-eabi': 1.12.2
+      '@unrs/resolver-binding-android-arm64': 1.12.2
+      '@unrs/resolver-binding-darwin-arm64': 1.12.2
+      '@unrs/resolver-binding-darwin-x64': 1.12.2
+      '@unrs/resolver-binding-freebsd-x64': 1.12.2
+      '@unrs/resolver-binding-linux-arm-gnueabihf': 1.12.2
+      '@unrs/resolver-binding-linux-arm-musleabihf': 1.12.2
+      '@unrs/resolver-binding-linux-arm64-gnu': 1.12.2
+      '@unrs/resolver-binding-linux-arm64-musl': 1.12.2
+      '@unrs/resolver-binding-linux-loong64-gnu': 1.12.2
+      '@unrs/resolver-binding-linux-loong64-musl': 1.12.2
+      '@unrs/resolver-binding-linux-ppc64-gnu': 1.12.2
+      '@unrs/resolver-binding-linux-riscv64-gnu': 1.12.2
+      '@unrs/resolver-binding-linux-riscv64-musl': 1.12.2
+      '@unrs/resolver-binding-linux-s390x-gnu': 1.12.2
+      '@unrs/resolver-binding-linux-x64-gnu': 1.12.2
+      '@unrs/resolver-binding-linux-x64-musl': 1.12.2
+      '@unrs/resolver-binding-openharmony-arm64': 1.12.2
+      '@unrs/resolver-binding-wasm32-wasi': 1.12.2
+      '@unrs/resolver-binding-win32-arm64-msvc': 1.12.2
+      '@unrs/resolver-binding-win32-ia32-msvc': 1.12.2
+      '@unrs/resolver-binding-win32-x64-msvc': 1.12.2
+
+  update-browserslist-db@1.3.1(browserslist@4.28.8):
+    dependencies:
+      browserslist: 4.28.8
+      escalade: 3.2.0
+      picocolors: 1.1.1
+
+  uri-js@4.4.1:
+    dependencies:
+      punycode: 2.3.1
+
+  vite@8.2.1(@types/node@20.19.43)(jiti@2.7.0):
+    dependencies:
+      lightningcss: 1.33.0
+      picomatch: 4.0.5
+      postcss: 8.5.26
+      rolldown: 1.2.3
+      tinyglobby: 0.2.17
+    optionalDependencies:
+      '@types/node': 20.19.43
+      fsevents: 2.3.3
+      jiti: 2.7.0
+
+  vitest@4.1.10(@types/node@20.19.43)(jsdom@30.0.1)(vite@8.2.1(@types/node@20.19.43)(jiti@2.7.0)):
+    dependencies:
+      '@vitest/expect': 4.1.10
+      '@vitest/mocker': 4.1.10(vite@8.2.1(@types/node@20.19.43)(jiti@2.7.0))
+      '@vitest/pretty-format': 4.1.10
+      '@vitest/runner': 4.1.10
+      '@vitest/snapshot': 4.1.10
+      '@vitest/spy': 4.1.10
+      '@vitest/utils': 4.1.10
+      es-module-lexer: 2.3.1
+      expect-type: 1.4.0
+      magic-string: 0.30.21
+      obug: 2.1.4
+      pathe: 2.0.3
+      picomatch: 4.0.5
+      std-env: 4.2.0
+      tinybench: 2.9.0
+      tinyexec: 1.3.0
+      tinyglobby: 0.2.17
+      tinyrainbow: 3.1.1
+      vite: 8.2.1(@types/node@20.19.43)(jiti@2.7.0)
+      why-is-node-running: 2.3.0
+    optionalDependencies:
+      '@types/node': 20.19.43
+      jsdom: 30.0.1
+    transitivePeerDependencies:
+      - msw
+
+  w3c-xmlserializer@5.0.0:
+    dependencies:
+      xml-name-validator: 5.0.0
+
+  webidl-conversions@8.0.1: {}
+
+  whatwg-mimetype@5.0.0: {}
+
+  whatwg-url@16.0.1:
+    dependencies:
+      '@exodus/bytes': 1.15.1
+      tr46: 6.0.0
+      webidl-conversions: 8.0.1
+    transitivePeerDependencies:
+      - '@noble/hashes'
+
+  whatwg-url@17.1.0:
+    dependencies:
+      '@exodus/bytes': 1.15.1
+      tr46: 6.0.0
+      webidl-conversions: 8.0.1
+    transitivePeerDependencies:
+      - '@noble/hashes'
+
+  which-boxed-primitive@1.1.1:
+    dependencies:
+      is-bigint: 1.1.0
+      is-boolean-object: 1.2.2
+      is-number-object: 1.1.1
+      is-string: 1.1.1
+      is-symbol: 1.1.1
+
+  which-builtin-type@1.2.1:
+    dependencies:
+      call-bound: 1.0.4
+      function.prototype.name: 1.2.0
+      has-tostringtag: 1.0.2
+      is-async-function: 2.1.1
+      is-date-object: 1.1.0
+      is-finalizationregistry: 1.1.1
+      is-generator-function: 1.1.2
+      is-regex: 1.2.1
+      is-weakref: 1.1.1
+      isarray: 2.0.5
+      which-boxed-primitive: 1.1.1
+      which-collection: 1.0.2
+      which-typed-array: 1.1.22
+
+  which-collection@1.0.2:
+    dependencies:
+      is-map: 2.0.3
+      is-set: 2.0.3
+      is-weakmap: 2.0.2
+      is-weakset: 2.0.4
+
+  which-typed-array@1.1.22:
+    dependencies:
+      available-typed-arrays: 1.0.7
+      call-bind: 1.0.9
+      call-bound: 1.0.4
+      for-each: 0.3.5
+      get-proto: 1.0.1
+      gopd: 1.2.0
+      has-tostringtag: 1.0.2
+
+  which@2.0.2:
+    dependencies:
+      isexe: 2.0.0
+
+  why-is-node-running@2.3.0:
+    dependencies:
+      siginfo: 2.0.0
+      stackback: 0.0.2
+
+  word-wrap@1.2.5: {}
+
+  xml-name-validator@5.0.0: {}
+
+  xmlchars@2.2.0: {}
+
+  yallist@3.1.1: {}
+
+  yocto-queue@0.1.0: {}
+
+  zod-validation-error@4.0.2(zod@4.4.3):
+    dependencies:
+      zod: 4.4.3
+
+  zod@4.4.3: {}

+ 4 - 0
pnpm-workspace.yaml

@@ -0,0 +1,4 @@
+allowBuilds:
+  unrs-resolver: true
+minimumReleaseAgeExclude:
+  - resend@6.19.0

+ 0 - 1
public/file.svg

@@ -1 +0,0 @@
-<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>

+ 0 - 1
public/globe.svg

@@ -1 +0,0 @@
-<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>

BIN
public/images/3d-printing.jpg


BIN
public/images/farm-to-table.jpg


BIN
public/images/gallery-honey.jpg


BIN
public/images/gallery-sourdough.jpg


BIN
public/images/gallery-training.jpg


BIN
public/images/hero-about.jpg


BIN
public/images/hero-contact.jpg


BIN
public/images/hero-gallery.jpg


BIN
public/images/hero-home.jpg


BIN
public/images/hero-offerings.jpg


BIN
public/images/hero-privacy.jpg


BIN
public/images/hero-terms.jpg


BIN
public/images/honey-bees.jpg


BIN
public/images/laser-engraving.jpg


BIN
public/images/personal-training.jpg


BIN
public/images/recreation-apps.jpg


BIN
public/images/sourdough.jpg


BIN
public/logo.png


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 2 - 0
public/logo.svg


+ 0 - 1
public/next.svg

@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

+ 0 - 1
public/vercel.svg

@@ -1 +0,0 @@
-<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>

+ 0 - 1
public/window.svg

@@ -1 +0,0 @@
-<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>

+ 187 - 0
src/app/about/page.tsx

@@ -0,0 +1,187 @@
+import { ParallaxHero } from "@/components/ParallaxHero";
+import { getPageContent } from "@/content/pages";
+import type { Metadata } from "next";
+import Link from "next/link";
+
+const page = getPageContent("about");
+
+export default function AboutPage() {
+  const values = page?.sections?.find((s) => s.title === "Values")?.items || [];
+  const pillars =
+    page?.sections?.find((s) => s.title === "Pillars")?.items || [];
+
+  return (
+    <>
+      <ParallaxHero
+        image={page?.heroImage || "/images/hero-about.jpg"}
+        alt={
+          page?.heroAlt ||
+          "Sunlit workshop kitchen with honey jars, artisan bread, sketchbook, and coffee on a rustic wooden table"
+        }
+        size={page?.heroSize || "md"}
+        priority={page?.heroPriority}
+        align={page?.heroAlign}
+        overlayClassName={
+          page?.heroOverlay ||
+          "bg-gradient-to-r from-black/80 via-black/55 to-black/30"
+        }
+        contentClassName={page?.heroContentClass}
+      >
+        <div className="max-w-2xl">
+          <p className="mb-4 text-[11px] font-medium uppercase tracking-[0.3em] text-white/65">
+            {page?.heroLabel}
+          </p>
+          <h1 className="mb-5 text-4xl font-semibold tracking-[-0.03em] text-white md:text-6xl">
+            {page?.title}
+          </h1>
+          <p className="max-w-xl text-lg leading-relaxed text-white/80 md:text-xl">
+            {page?.heroDescription}
+          </p>
+        </div>
+      </ParallaxHero>
+
+      <section className="py-16 md:py-24">
+        <div className="container-xl max-w-3xl">
+          <div className="space-y-6 text-lg leading-relaxed text-[var(--color-text)]">
+            <p>
+              We started with a simple observation: the things that make a day
+              feel whole rarely fit in one aisle. A good loaf. A honest training
+              plan. Honey from nearby hives. A custom piece that marks a moment.
+              Tools that help you rest as intentionally as you work.
+            </p>
+            <p>
+              Jenado Unlimited brings those practices under one roof — not as a
+              random assortment, but as a deliberate ecosystem built on the
+              pillars of{" "}
+              <strong className="font-medium text-[var(--color-heading)]">
+                Mind
+              </strong>
+              ,{" "}
+              <strong className="font-medium text-[var(--color-heading)]">
+                Body
+              </strong>
+              , and{" "}
+              <strong className="font-medium text-[var(--color-heading)]">
+                Soul
+              </strong>
+              . From artisan sourdough and local honey to personal training,
+              seasonal food experiences, recreation apps, laser engraving, and
+              3D printing, we treat every vertical with the same standard:
+              thoughtful process, clear communication, and work we are proud to
+              put our name on.
+            </p>
+            <p className="text-[var(--color-text-muted)]">
+              Our mission is straightforward — to offer experiences and products
+              that nourish the mind, strengthen the body, and uplift the soul.
+              Some offerings are fully active today; others are in soft launch
+              or on the horizon. What does not change is the care behind each
+              one.
+            </p>
+          </div>
+
+          <div className="mt-16 border-t border-[var(--color-border)] pt-12">
+            <p className="mb-3 text-[11px] font-medium uppercase tracking-[0.3em] text-[var(--color-text-muted)]">
+              The pillars
+            </p>
+            <h2 className="mb-8 text-2xl font-semibold tracking-[-0.02em] md:text-3xl">
+              One brand. Three ways in.
+            </h2>
+            <div className="space-y-8">
+              {pillars.map((pillar) => (
+                <div
+                  key={pillar.label}
+                  className="grid gap-2 border-l-2 border-[var(--color-heading)] pl-5 md:grid-cols-[7rem_1fr] md:gap-6 md:border-l-0 md:pl-0"
+                >
+                  <p className="text-[11px] font-medium uppercase tracking-[0.3em] text-[var(--color-heading)] md:pt-1">
+                    {pillar.label}
+                  </p>
+                  <div>
+                    <h3 className="mb-2 text-lg font-medium tracking-[-0.01em] text-[var(--color-heading)]">
+                      {pillar.title}
+                    </h3>
+                    <p className="text-[15px] leading-relaxed text-[var(--color-text-muted)]">
+                      {pillar.description}
+                    </p>
+                  </div>
+                </div>
+              ))}
+            </div>
+          </div>
+
+          <div className="mt-16 border-t border-[var(--color-border)] pt-12">
+            <p className="mb-3 text-[11px] font-medium uppercase tracking-[0.3em] text-[var(--color-text-muted)]">
+              How we work
+            </p>
+            <h2 className="mb-5 text-2xl font-semibold tracking-[-0.02em]">
+              Small by design. Serious about quality.
+            </h2>
+            <div className="space-y-5 text-[15px] leading-relaxed text-[var(--color-text-muted)] md:text-base">
+              <p>
+                We are not a faceless marketplace. Inquiries come to real
+                people. Custom projects get conversation, not just a checkout
+                button. Training is personal, not a one-size program dropped in
+                a PDF.
+              </p>
+              <p>
+                That also means capacity is finite. Bread is baked in batches.
+                Engraving and printing take time. Training calendars fill.
+                Transparency about status — active, soft launch, coming soon —
+                is part of respecting your time and ours.
+              </p>
+              <p>
+                If you are exploring a gift, a habit change, a custom piece, or
+                simply curious what we are building next, we would rather talk
+                early and honestly than overpromise.
+              </p>
+            </div>
+          </div>
+
+          <div className="mt-16 border-t border-[var(--color-border)] pt-12">
+            <p className="mb-8 text-[11px] font-medium uppercase tracking-[0.3em] text-[var(--color-text-muted)]">
+              Our values
+            </p>
+            <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
+              {values.map((value) => (
+                <div
+                  key={value.title}
+                  className="border border-[var(--color-border)] bg-[var(--color-surface)] p-6 transition-shadow duration-300 hover:shadow-[0_16px_40px_-24px_rgba(0,0,0,0.35)] dark:hover:shadow-[0_16px_40px_-24px_rgba(0,0,0,0.8)]"
+                >
+                  <h2 className="mb-2 text-lg font-medium tracking-[-0.01em] text-[var(--color-heading)]">
+                    {value.title}
+                  </h2>
+                  <p className="text-[15px] leading-relaxed text-[var(--color-text-muted)]">
+                    {value.description}
+                  </p>
+                </div>
+              ))}
+            </div>
+          </div>
+
+          <div className="mt-16 flex flex-wrap items-center gap-4 border-t border-[var(--color-border)] pt-12">
+            <Link href="/contact" className="btn-primary">
+              Get in Touch
+            </Link>
+            <Link
+              href="/offerings"
+              className="text-sm font-medium tracking-wide text-[var(--color-heading)] transition-opacity hover:opacity-70"
+            >
+              Explore offerings →
+            </Link>
+            <Link
+              href="/gallery"
+              className="text-sm font-medium tracking-wide text-[var(--color-heading)] transition-opacity hover:opacity-70"
+            >
+              View gallery →
+            </Link>
+          </div>
+        </div>
+      </section>
+    </>
+  );
+}
+
+export const metadata: Metadata = {
+  title: "About | Jenado Unlimited",
+  description:
+    "Learn about Jenado Unlimited — our mission, values, and multi-vertical brand built on mind, body, and soul.",
+};

+ 96 - 0
src/app/api/contact/route.ts

@@ -0,0 +1,96 @@
+import { NextResponse } from "next/server";
+import { contactBodySchema, isHoneypotTriggered, sanitizeHeaderValue } from "@/lib/contact";
+import { getResend } from "@/lib/email";
+
+export async function POST(request: Request) {
+  const FORMS_ENABLED = process.env.FORMS_ENABLED !== "false";
+  if (!FORMS_ENABLED) {
+    return NextResponse.json(
+      { ok: false, error: "disabled" },
+      { status: 503 }
+    );
+  }
+
+
+  const contentType = request.headers.get("content-type");
+  if (contentType !== "application/json") {
+    return NextResponse.json(
+      { ok: false, error: "validation" },
+      { status: 400 }
+    );
+  }
+
+  const siteUrl = process.env.NEXT_PUBLIC_SITE_URL;
+  if (siteUrl) {
+    const origin = request.headers.get("origin");
+    if (origin) {
+      const expectedOrigin = new URL(siteUrl).origin;
+      if (origin !== expectedOrigin) {
+        return NextResponse.json(
+          { ok: false, error: "forbidden" },
+          { status: 403 }
+        );
+      }
+    }
+  }
+
+  let parsed: Record<string, string | undefined>;
+  try {
+    parsed = await request.json();
+  } catch {
+    return NextResponse.json(
+      { ok: false, error: "validation" },
+      { status: 400 }
+    );
+  }
+
+  const validated = contactBodySchema.safeParse(parsed);
+  if (!validated.success) {
+    return NextResponse.json(
+      {
+        ok: false,
+        error: "validation",
+        issues: validated.error.issues.map((i) => i.message),
+      },
+      { status: 400 }
+    );
+  }
+
+  if (isHoneypotTriggered({ website: parsed.website, company: parsed.company })) {
+    return NextResponse.json({ ok: true }, { status: 200 });
+  }
+
+  const { name, email, topic, message, phone } = validated.data;
+
+  const sanitizedName = sanitizeHeaderValue(name);
+  const sanitizedEmail = sanitizeHeaderValue(email);
+  const sanitizedTopic = sanitizeHeaderValue(topic);
+  const sanitizedPhone = phone ? sanitizeHeaderValue(phone) : "";
+  const sanitizedMessage = message.replace(/[\r\n]+/g, " ").trim();
+
+  const subject = `New inquiry: ${sanitizedTopic}`;
+  const from = `Jenado Unlimited <onboarding@resend.dev>`;
+  const toEmail = process.env.RESEND_EMAIL || "hello@jenadounlimited.com";
+
+  try {
+    await getResend().emails.send({
+      from,
+      to: toEmail,
+      subject,
+      text: `Name: ${sanitizedName}
+Email: ${sanitizedEmail}
+Phone: ${sanitizedPhone}
+Topic: ${sanitizedTopic}
+
+Message:
+${sanitizedMessage}`,
+    });
+
+    return NextResponse.json({ ok: true }, { status: 200 });
+  } catch {
+    return NextResponse.json(
+      { ok: false, error: "server" },
+      { status: 500 }
+    );
+  }
+}

+ 226 - 0
src/app/contact/page.tsx

@@ -0,0 +1,226 @@
+import { ContactForm } from "@/components/ContactForm";
+import { ParallaxHero } from "@/components/ParallaxHero";
+import { getPageContent } from "@/content/pages";
+import { siteConfig } from "@/lib/content";
+import { contactPageJsonLd } from "@/lib/json-ld";
+import type { Metadata } from "next";
+import Link from "next/link";
+import Script from "next/script";
+
+const FORMS_ENABLED = process.env.FORMS_ENABLED !== "false";
+const page = getPageContent("contact");
+const topics = page?.sections?.find((s) => s.title === "Topics")?.items || [];
+
+export default function ContactPage() {
+  const email = siteConfig.contactEmail || "hello@jenadounlimited.com";
+  const phone = siteConfig.contactPhone;
+
+  return (
+    <>
+      <Script
+        id="contact-jsonld"
+        type="application/ld+json"
+        strategy="afterInteractive"
+      >
+        {`{${JSON.stringify(contactPageJsonLd())}}`}
+      </Script>
+
+      <ParallaxHero
+        image={page?.heroImage || "/images/hero-contact.jpg"}
+        alt={
+          page?.heroAlt ||
+          "Handwritten note, fountain pen, wax-sealed envelope, and flower on a dark wooden desk"
+        }
+        size={page?.heroSize || "md"}
+        priority={page?.heroPriority}
+        align={page?.heroAlign}
+        overlayClassName={
+          page?.heroOverlay ||
+          "bg-gradient-to-r from-black/80 via-black/55 to-black/30"
+        }
+        contentClassName={page?.heroContentClass}
+      >
+        <div className="max-w-2xl">
+          <p className="mb-4 text-[11px] font-medium uppercase tracking-[0.3em] text-white/65">
+            {page?.heroLabel}
+          </p>
+          <h1 className="mb-5 text-4xl font-semibold tracking-[-0.03em] text-white md:text-6xl">
+            {page?.title}
+          </h1>
+          <p className="max-w-xl text-lg leading-relaxed text-white/80 md:text-xl">
+            {page?.heroDescription}
+          </p>
+        </div>
+      </ParallaxHero>
+
+      <section className="border-b border-[var(--color-border)] py-12 md:py-16">
+        <div className="container-xl max-w-3xl">
+          <p className="text-lg leading-relaxed text-[var(--color-text-muted)]">
+            The form is the fastest way to reach us with context. Pick the topic
+            that fits best, share what you are hoping for, and include any
+            timing or constraints that matter. Prefer email or a call? Use the
+            direct details in the sidebar — same team either way.
+          </p>
+        </div>
+      </section>
+
+      <section className="py-16 md:py-24">
+        <div className="container-xl">
+          <div className="grid grid-cols-1 gap-12 lg:grid-cols-12 lg:gap-16">
+            <div className="lg:col-span-7">
+              <div className="mb-8">
+                <h2 className="mb-3 text-2xl font-semibold tracking-[-0.02em]">
+                  Send a message
+                </h2>
+                <p className="leading-relaxed text-[var(--color-text-muted)]">
+                  A few sentences are enough to start. If you are requesting
+                  custom work, rough dimensions, material ideas, or reference
+                  photos (described in text) help us respond with something
+                  useful the first time.
+                </p>
+              </div>
+
+              {FORMS_ENABLED ? (
+                <ContactForm />
+              ) : (
+                <div className="border border-[var(--color-border)] bg-[var(--color-surface)] p-10 text-center">
+                  <h2 className="mb-3 text-xl font-medium">
+                    Contact temporarily unavailable
+                  </h2>
+                  <p className="mb-6 text-[var(--color-text-muted)]">
+                    The form is disabled right now. Reach us directly by email
+                    or phone — we are still here.
+                  </p>
+                  <a
+                    href={`mailto:${email}`}
+                    className="btn-primary inline-block"
+                  >
+                    Send Email
+                  </a>
+                </div>
+              )}
+
+              <div className="mt-14 border-t border-[var(--color-border)] pt-12">
+                <h2 className="mb-3 text-xl font-semibold tracking-[-0.02em]">
+                  What helps us help you
+                </h2>
+                <p className="mb-6 text-[15px] leading-relaxed text-[var(--color-text-muted)]">
+                  You do not need a polished brief. These prompts simply speed
+                  up a useful reply:
+                </p>
+                <ul className="space-y-4">
+                  {topics.map((topic) => (
+                    <li
+                      key={topic.title}
+                      className="flex gap-3 border-b border-[var(--color-border)] pb-4 last:border-b-0 last:pb-0"
+                    >
+                      <span
+                        className="mt-2 h-1 w-1 shrink-0 rounded-full bg-[var(--color-heading)]"
+                        aria-hidden
+                      />
+                      <div>
+                        <p className="font-medium text-[var(--color-heading)]">
+                          {topic.title}
+                        </p>
+                        <p className="mt-1 text-[15px] text-[var(--color-text-muted)]">
+                          {topic.description}
+                        </p>
+                      </div>
+                    </li>
+                  ))}
+                </ul>
+              </div>
+            </div>
+
+            <aside className="lg:col-span-5">
+              <div className="space-y-6 md:sticky md:top-24">
+                <div className="border border-[var(--color-border)] bg-[var(--color-surface)] p-8">
+                  <p className="mb-6 text-[11px] font-medium uppercase tracking-[0.3em] text-[var(--color-text-muted)]">
+                    Direct contact
+                  </p>
+                  <div className="space-y-6">
+                    <div>
+                      <div className="mb-1 text-sm font-medium text-[var(--color-heading)]">
+                        Email
+                      </div>
+                      <a
+                        href={`mailto:${email}`}
+                        className="text-[var(--color-text-muted)] transition-colors hover:text-[var(--color-heading)]"
+                      >
+                        {email}
+                      </a>
+                    </div>
+                    {phone && (
+                      <div>
+                        <div className="mb-1 text-sm font-medium text-[var(--color-heading)]">
+                          Phone
+                        </div>
+                        <a
+                          href={`tel:${phone.replace(/[^\d+]/g, "")}`}
+                          className="text-[var(--color-text-muted)] transition-colors hover:text-[var(--color-heading)]"
+                        >
+                          {phone}
+                        </a>
+                      </div>
+                    )}
+                    <div className="border-t border-[var(--color-border)] pt-6">
+                      <p className="text-sm leading-relaxed text-[var(--color-text-muted)]">
+                        We typically respond within one to two business days.
+                        For time-sensitive training slots or event dates, put
+                        the deadline in your message subject line or first
+                        sentence so we can prioritize.
+                      </p>
+                    </div>
+                  </div>
+                </div>
+
+                <div className="border border-[var(--color-border)] bg-[var(--color-surface)] p-8">
+                  <p className="mb-4 text-[11px] font-medium uppercase tracking-[0.3em] text-[var(--color-text-muted)]">
+                    What to expect
+                  </p>
+                  <ul className="space-y-3 text-sm leading-relaxed text-[var(--color-text-muted)]">
+                    <li>
+                      A real reply — not an autoresponder loop — once we have
+                      reviewed your note.
+                    </li>
+                    <li>
+                      Honest availability. If something is waitlisted or still
+                      coming soon, we will say so clearly.
+                    </li>
+                    <li>
+                      Next steps when it makes sense: samples, sessions, proofs,
+                      or a short call.
+                    </li>
+                  </ul>
+                  <p className="mt-6 text-sm text-[var(--color-text-muted)]">
+                    Prefer to browse first?{" "}
+                    <Link
+                      href="/offerings"
+                      className="font-medium text-[var(--color-heading)] underline-offset-4 hover:underline"
+                    >
+                      Explore offerings
+                    </Link>{" "}
+                    or{" "}
+                    <Link
+                      href="/gallery"
+                      className="font-medium text-[var(--color-heading)] underline-offset-4 hover:underline"
+                    >
+                      view the gallery
+                    </Link>
+                    .
+                  </p>
+                </div>
+              </div>
+            </aside>
+          </div>
+        </div>
+      </section>
+    </>
+  );
+}
+
+export const metadata: Metadata = {
+  title: "Contact | Jenado Unlimited",
+  description:
+    "Contact Jenado Unlimited — send us a message about honey, training, sourdough, custom craft, and more.",
+};

+ 136 - 0
src/app/gallery/page.tsx

@@ -0,0 +1,136 @@
+import { GalleryGrid } from "@/components/GalleryGrid";
+import { ParallaxHero } from "@/components/ParallaxHero";
+import { getPageContent } from "@/content/pages";
+import { galleryItems } from "@/lib/gallery";
+import type { Metadata } from "next";
+import Link from "next/link";
+
+const page = getPageContent("gallery");
+const themes = page?.sections?.find((s) => s.title === "Themes")?.items || [];
+
+export default function GalleryPage() {
+  return (
+    <>
+      <ParallaxHero
+        image={page?.heroImage || "/images/hero-gallery.jpg"}
+        alt={
+          page?.heroAlt ||
+          "Abstract textures of honey, wood grain, engraved metal, and fabric"
+        }
+        size={page?.heroSize || "md"}
+        priority={page?.heroPriority}
+        align={page?.heroAlign}
+        overlayClassName={
+          page?.heroOverlay ||
+          "bg-gradient-to-r from-black/75 via-black/50 to-black/30"
+        }
+        contentClassName={page?.heroContentClass}
+      >
+        <div className="max-w-2xl">
+          <p className="mb-4 text-[11px] font-medium uppercase tracking-[0.3em] text-white/65">
+            {page?.heroLabel}
+          </p>
+          <h1 className="mb-5 text-4xl font-semibold tracking-[-0.03em] text-white md:text-6xl">
+            {page?.title}
+          </h1>
+          <p className="max-w-xl text-lg leading-relaxed text-white/80 md:text-xl">
+            {page?.heroDescription}
+          </p>
+        </div>
+      </ParallaxHero>
+
+      <section className="border-b border-[var(--color-border)] py-14 md:py-16">
+        <div className="container-xl">
+          <div className="mx-auto max-w-3xl">
+            <p className="mb-6 text-lg leading-relaxed text-[var(--color-text)]">
+              We believe craft is easier to trust when you can see it. This
+              gallery gathers frames from across our verticals — not a catalog
+              of every SKU, but a sense of the rooms we work in, the textures we
+              handle, and the standards we hold.
+            </p>
+            <p className="text-[var(--color-text-muted)] leading-relaxed">
+              Some images are product-forward. Others are atmosphere: light on
+              wood, a loaf torn open, metal after the laser cools. Click a frame
+              labeled with an offering to jump into that vertical and learn more
+              — or simply scroll and take it in.
+            </p>
+          </div>
+
+          <div className="mt-12 grid grid-cols-1 gap-6 md:grid-cols-3">
+            {themes.map((theme) => (
+              <div
+                key={theme.title}
+                className="border border-[var(--color-border)] bg-[var(--color-surface)] p-6"
+              >
+                <h2 className="mb-2 text-base font-medium tracking-[-0.01em] text-[var(--color-heading)]">
+                  {theme.title}
+                </h2>
+                <p className="text-[14px] leading-relaxed text-[var(--color-text-muted)]">
+                  {theme.description}
+                </p>
+              </div>
+            ))}
+          </div>
+        </div>
+      </section>
+
+      <section className="py-16 md:py-24">
+        <div className="container-xl">
+          <div className="mb-12 flex flex-col gap-4 md:mb-16 md:flex-row md:items-end md:justify-between">
+            <div className="max-w-xl">
+              <h2 className="mb-2 text-2xl font-semibold tracking-[-0.02em]">
+                Selected frames
+              </h2>
+              <p className="leading-relaxed text-[var(--color-text-muted)]">
+                A rotating selection from our work and process. Labels point to
+                related offerings when there is a clear path to explore.
+              </p>
+            </div>
+            <p className="text-sm tabular-nums text-[var(--color-text-muted)]">
+              {galleryItems.length} images
+            </p>
+          </div>
+
+          <GalleryGrid images={galleryItems} />
+
+          <div className="mt-16 grid gap-8 border-t border-[var(--color-border)] pt-12 md:grid-cols-2 md:gap-12">
+            <div>
+              <h2 className="mb-3 text-xl font-semibold tracking-[-0.02em]">
+                Want the real thing?
+              </h2>
+              <p className="mb-6 leading-relaxed text-[var(--color-text-muted)]">
+                Images are a starting point. If something here sparks a gift
+                idea, a custom engraving, a training conversation, or a simple
+                “do you still have honey this week?” — we are easy to reach.
+              </p>
+              <Link href="/contact" className="btn-primary inline-block">
+                Start a conversation
+              </Link>
+            </div>
+            <div>
+              <h2 className="mb-3 text-xl font-semibold tracking-[-0.02em]">
+                Explore by offering
+              </h2>
+              <p className="mb-6 leading-relaxed text-[var(--color-text-muted)]">
+                Prefer words over pictures first? Our offerings page walks
+                through each vertical — status, summary, and a path to inquire.
+              </p>
+              <Link
+                href="/offerings"
+                className="text-sm font-medium tracking-wide text-[var(--color-heading)] transition-opacity hover:opacity-70"
+              >
+                View all offerings →
+              </Link>
+            </div>
+          </div>
+        </div>
+      </section>
+    </>
+  );
+}
+
+export const metadata: Metadata = {
+  title: "Gallery | Jenado Unlimited",
+  description:
+    "A visual gallery of Jenado Unlimited — honey, bread, training, craft, and the textures behind our work.",
+};

+ 169 - 15
src/app/globals.css

@@ -1,26 +1,180 @@
 @import "tailwindcss";
 
+@theme {
+  --color-bg: var(--color-bg);
+  --color-surface: var(--color-surface);
+  --color-text: var(--color-text);
+  --color-text-muted: var(--color-text-muted);
+  --color-accent: var(--color-accent);
+  --color-accent-hover: var(--color-accent-hover);
+  --color-heading: var(--color-heading);
+  --color-border: var(--color-border);
+  --color-success: var(--color-success);
+  --color-error: var(--color-error);
+}
+
+/* Clean black & white palette — high contrast, timeless */
 :root {
-  --background: #ffffff;
-  --foreground: #171717;
+  --color-bg: #ffffff;
+  --color-surface: #ffffff;
+  --color-text: #111111;
+  --color-text-muted: #666666;
+  --color-accent: #000000;
+  --color-accent-hover: #333333;
+  --color-heading: #000000;
+  --color-border: #e5e5e5;
+  --color-success: #16a34a;
+  --color-error: #dc2626;
+
+  /* Logo colors: black on white (light mode) */
+  --logo-bg: #ffffff;
+  --logo-fg: #111111;
+}
+
+.dark {
+  --color-bg: #000000;
+  --color-surface: #0a0a0a;
+  --color-text: #f5f5f5;
+  --color-text-muted: #a3a3a3;
+  --color-accent: #ffffff;
+  --color-accent-hover: #e5e5e5;
+  --color-heading: #ffffff;
+  --color-border: #262626;
+  --color-success: #22c55e;
+  --color-error: #ef4444;
+
+  /* Logo colors: white on black (dark mode) */
+  --logo-bg: #111111;
+  --logo-fg: #ffffff;
 }
 
-@theme inline {
-  --color-background: var(--background);
-  --color-foreground: var(--foreground);
-  --font-sans: var(--font-geist-sans);
-  --font-mono: var(--font-geist-mono);
+/* Invert logo SVG for dark mode — the SVG uses black fills, so invert makes it white */
+.dark .logo img {
+  filter: invert(1);
+}
+
+@layer base {
+  html {
+    scroll-behavior: smooth;
+  }
+
+  body {
+    -webkit-font-smoothing: antialiased;
+    -moz-osx-font-smoothing: grayscale;
+  }
+
+  h1,
+  h2,
+  h3,
+  h4,
+  h5,
+  h6 {
+    font-weight: 600;
+    letter-spacing: -0.02em;
+    line-height: 1.2;
+  }
+
+  h1 {
+    font-size: 3rem;
+  }
+
+  h2 {
+    font-size: 2rem;
+  }
+
+  h3 {
+    font-size: 1.5rem;
+  }
+
+  p {
+    line-height: 1.7;
+  }
+
+  a {
+    color: inherit;
+    text-decoration: none;
+    transition: color 0.15s ease;
+  }
+
+  a:hover {
+    color: var(--color-accent);
+  }
 }
 
-@media (prefers-color-scheme: dark) {
-  :root {
-    --background: #0a0a0a;
-    --foreground: #ededed;
+@layer components {
+  .btn-primary {
+    @apply inline-flex items-center justify-center rounded-none border border-[var(--color-heading)] bg-[var(--color-heading)] px-8 py-3 font-medium text-[var(--color-bg)] transition-all hover:bg-transparent hover:text-[var(--color-heading)];
+  }
+
+  .btn-secondary {
+    @apply inline-flex items-center justify-center rounded-none border border-[var(--color-border)] px-8 py-3 font-medium transition-all hover:border-[var(--color-heading)] hover:text-[var(--color-heading)];
+  }
+
+  /* Hero CTAs on dark photography */
+  .btn-hero-primary {
+    @apply inline-flex items-center justify-center border border-white bg-white px-8 py-3.5 font-medium text-black transition-all hover:bg-transparent hover:text-white;
+  }
+
+  .btn-hero-secondary {
+    @apply inline-flex items-center justify-center border border-white/50 bg-transparent px-8 py-3.5 font-medium text-white transition-all hover:border-white hover:bg-white/10;
+  }
+
+  /* Force logo mark to white when sitting on dark hero imagery */
+  .logo-on-dark .logo img {
+    filter: invert(1);
+  }
+
+  .input {
+    @apply w-full border-b border-[var(--color-border)] bg-transparent py-3 text-[var(--color-text)] placeholder:text-[var(--color-text-muted)] transition-colors focus:border-[var(--color-heading)] focus:outline-none;
+  }
+
+  .textarea {
+    @apply w-full border-b border-[var(--color-border)] bg-transparent py-3 text-[var(--color-text)] placeholder:text-[var(--color-text-muted)] transition-colors focus:border-[var(--color-heading)] focus:outline-none min-h-[120px] resize-y;
+  }
+
+  .honeypot-hidden {
+    display: none;
   }
 }
 
-body {
-  background: var(--background);
-  color: var(--foreground);
-  font-family: Arial, Helvetica, sans-serif;
+/* Logo uses currentColor so it follows the theme automatically.
+   We set the color to the heading token so it is black in light, white in dark. */
+.logo {
+  display: inline-block;
+  vertical-align: middle;
+  color: var(--color-heading);
+}
+
+@layer utilities {
+  .container-xl {
+    max-width: 80rem;
+    margin-left: auto;
+    margin-right: auto;
+    padding-left: 1.5rem;
+    padding-right: 1.5rem;
+  }
+
+  @media (min-width: 64rem) {
+    .container-xl {
+      padding-left: 2.5rem;
+      padding-right: 2.5rem;
+    }
+  }
+
+  .skip-to-content {
+    position: absolute;
+    left: 1rem;
+    top: -9999px;
+    z-index: 50;
+    border: 1px solid var(--color-heading);
+    background-color: var(--color-heading);
+    padding: 0.5rem 1rem;
+    font-weight: 500;
+    color: var(--color-bg);
+    transition: top 0.15s ease;
+  }
+
+  .skip-to-content:focus {
+    top: 1rem;
+  }
 }

+ 44 - 16
src/app/layout.tsx

@@ -1,29 +1,57 @@
+import Script from "next/script";
 import type { Metadata } from "next";
-import { Geist, Geist_Mono } from "next/font/google";
+import { Inter } from "next/font/google";
 import "./globals.css";
+import { Header } from "@/components/Header";
+import { Footer } from "@/components/Footer";
+import { SkipToContent } from "@/components/SkipToContent";
+import { organizationJsonLd, websiteJsonLd } from "@/lib/json-ld";
 
-const geistSans = Geist({
-  variable: "--font-geist-sans",
-  subsets: ["latin"],
-});
-
-const geistMono = Geist_Mono({
-  variable: "--font-geist-mono",
+const inter = Inter({
   subsets: ["latin"],
+  variable: "--font-inter",
+  weight: ["400", "500", "600", "700"],
+  display: "swap",
 });
 
 export const metadata: Metadata = {
-  title: "Create Next App",
-  description: "Generated by create next app",
+  title: {
+    default: "Jenado Unlimited — Honey, Training, Sourdough & More",
+    template: "%s | Jenado Unlimited",
+  },
+  description: "Jenado Unlimited — local honey, personal training, artisan sourdough, farm-to-table dining, recreation apps, laser engraving, and 3D printing.",
+  generator: "Next.js",
+  keywords: ["honey", "personal training", "sourdough", "farm-to-table", "recreation apps", "laser engraving", "3d printing"],
+  openGraph: {
+    type: "website",
+    locale: "en_US",
+    siteName: "Jenado Unlimited",
+  },
+  robots: {
+    index: true,
+    follow: true,
+  },
 };
 
-export default function RootLayout({ children }: LayoutProps<"/">) {
+export default function RootLayout({
+  children,
+}: {
+  children: React.ReactNode;
+}) {
   return (
-    <html
-      lang="en"
-      className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
-    >
-      <body className="min-h-full flex flex-col">{children}</body>
+    <html lang="en" data-scroll-behavior="smooth" suppressHydrationWarning className={inter.variable}>
+      <body className="antialiased bg-[var(--color-bg)] text-[var(--color-text)] font-sans">
+        <Script id="org-jsonld" type="application/ld+json" strategy="afterInteractive">
+          {`{${JSON.stringify(organizationJsonLd())}}`}
+        </Script>
+        <Script id="website-jsonld" type="application/ld+json" strategy="afterInteractive">
+          {`{${JSON.stringify(websiteJsonLd())}}`}
+        </Script>
+        <SkipToContent />
+        <Header />
+        <main id="main-content" className="min-h-screen">{children}</main>
+        <Footer />
+      </body>
     </html>
   );
 }

+ 22 - 0
src/app/not-found.tsx

@@ -0,0 +1,22 @@
+import Link from "next/link";
+
+export default function NotFound() {
+  return (
+    <section className="py-24">
+      <div className="container-xl text-center">
+        <div className="text-[10px] uppercase tracking-[3px] text-[var(--color-text-muted)] mb-4">
+          Error
+        </div>
+        <h1 className="mb-4 text-4xl font-semibold tracking-[-0.02em]">
+          Page not found
+        </h1>
+        <p className="mb-10 text-[var(--color-text-muted)] max-w-sm mx-auto">
+          The page you are looking for does not exist.
+        </p>
+        <Link href="/" className="btn-primary inline-block">
+          Back to Home
+        </Link>
+      </div>
+    </section>
+  );
+}

+ 117 - 0
src/app/offerings/[slug]/page.tsx

@@ -0,0 +1,117 @@
+import { GalleryGrid } from "@/components/GalleryGrid";
+import { ParallaxHero } from "@/components/ParallaxHero";
+import { VerticalCard } from "@/components/VerticalCard";
+import { getRelatedVerticals, getVerticalBySlug } from "@/lib/content";
+import type { Metadata } from "next";
+import Link from "next/link";
+import { notFound } from "next/navigation";
+
+export function generateStaticParams() {
+  return [
+    { slug: "honey-bees" },
+    { slug: "personal-training" },
+    { slug: "sourdough" },
+    { slug: "farm-to-table" },
+    { slug: "recreation-apps" },
+    { slug: "laser-engraving" },
+    { slug: "3d-printing" },
+  ];
+}
+
+export async function generateMetadata({
+  params,
+}: {
+  params: Promise<{ slug: string }>;
+}): Promise<Metadata> {
+  const { slug } = await params;
+  const vertical = getVerticalBySlug(slug);
+  if (!vertical)
+    return { title: "Not Found", description: "This offering does not exist." };
+  return {
+    title: `${vertical.title} | Jenado Unlimited`,
+    description: vertical.summary,
+  };
+}
+
+export default async function VerticalPage({
+  params,
+}: {
+  params: Promise<{ slug: string }>;
+}) {
+  const { slug } = await params;
+  const vertical = getVerticalBySlug(slug);
+
+  if (!vertical) notFound();
+
+  const related = getRelatedVerticals(slug);
+
+  return (
+    <>
+      <ParallaxHero
+        image={vertical.image}
+        alt={vertical.title}
+        size="md"
+        priority
+        align="start"
+        overlayClassName="bg-gradient-to-r from-black/80 via-black/55 to-black/25"
+        contentClassName="!items-start !text-left"
+      >
+        <div className="max-w-2xl">
+          <div className="mb-4 flex flex-wrap items-center gap-3 text-[11px] font-medium uppercase tracking-[0.25em] text-white/65">
+            <span>{vertical.status.replace("-", " ")}</span>
+            {vertical.pillars?.length > 0 && (
+              <span>· {vertical.pillars.join(" · ")}</span>
+            )}
+          </div>
+          <h1 className="mb-5 text-4xl font-semibold tracking-[-0.03em] text-white md:text-6xl">
+            {vertical.title}
+          </h1>
+          <p className="max-w-xl text-lg leading-relaxed text-white/80 md:text-xl">
+            {vertical.summary}
+          </p>
+        </div>
+      </ParallaxHero>
+
+      <section className="py-16 md:py-20">
+        <div className="container-xl max-w-4xl">
+          <article>
+            <div className="prose prose-lg mb-14 max-w-none">
+              <p className="text-lg leading-relaxed md:text-xl">
+                {vertical.description}
+              </p>
+            </div>
+
+            {vertical.gallery && vertical.gallery.length > 0 && (
+              <div className="mb-14">
+                <div className="mb-6 text-sm uppercase tracking-[2px] text-[var(--color-text-muted)]">
+                  Gallery
+                </div>
+                <GalleryGrid images={vertical.gallery} />
+              </div>
+            )}
+
+            <Link
+              href={`/contact?topic=${vertical.slug}`}
+              className="btn-primary inline-block"
+            >
+              Inquire about {vertical.title}
+            </Link>
+          </article>
+
+          {related.length > 0 && (
+            <div className="mt-20 border-t border-[var(--color-border)] pt-12">
+              <div className="mb-8 text-sm uppercase tracking-[2px] text-[var(--color-text-muted)]">
+                Related Offerings
+              </div>
+              <div className="grid grid-cols-1 gap-5 md:grid-cols-3">
+                {related.map((rv) => (
+                  <VerticalCard key={rv.slug} vertical={rv} />
+                ))}
+              </div>
+            </div>
+          )}
+        </div>
+      </section>
+    </>
+  );
+}

+ 147 - 0
src/app/offerings/page.tsx

@@ -0,0 +1,147 @@
+import { ParallaxHero } from "@/components/ParallaxHero";
+import { VerticalCard } from "@/components/VerticalCard";
+import { getPageContent } from "@/content/pages";
+import { getAllVerticals } from "@/lib/content";
+import type { Metadata } from "next";
+import Link from "next/link";
+
+const page = getPageContent("offerings");
+const pillars =
+  page?.sections?.find((s) => s.title === "How we organize our work")?.items ||
+  [];
+
+export default function OfferingsPage() {
+  const verticals = getAllVerticals();
+
+  return (
+    <>
+      <ParallaxHero
+        image={page?.heroImage || "/images/hero-offerings.jpg"}
+        alt={
+          page?.heroAlt ||
+          "Artisan flatlay of honeycomb, dumbbell, sourdough, produce, laser-cut wood, and 3D printed object"
+        }
+        size={page?.heroSize || "md"}
+        priority={page?.heroPriority}
+        align={page?.heroAlign}
+        overlayClassName={
+          page?.heroOverlay ||
+          "bg-gradient-to-r from-black/75 via-black/55 to-black/35"
+        }
+        contentClassName={page?.heroContentClass}
+      >
+        <div className="max-w-2xl">
+          <p className="mb-4 text-[11px] font-medium uppercase tracking-[0.3em] text-white/65">
+            {page?.heroLabel}
+          </p>
+          <h1 className="mb-5 text-4xl font-semibold tracking-[-0.03em] text-white md:text-6xl">
+            {page?.title}
+          </h1>
+          <p className="max-w-xl text-lg leading-relaxed text-white/80 md:text-xl">
+            {page?.heroDescription}
+          </p>
+        </div>
+      </ParallaxHero>
+
+      <section className="border-b border-[var(--color-border)] py-16 md:py-20">
+        <div className="container-xl">
+          <div className="mx-auto max-w-3xl text-center">
+            <p className="mb-4 text-[11px] font-medium uppercase tracking-[0.3em] text-[var(--color-text-muted)]">
+              How we organize our work
+            </p>
+            <h2 className="mb-5 text-2xl font-semibold tracking-[-0.02em] md:text-3xl">
+              Built around how people actually live
+            </h2>
+            <p className="text-lg leading-relaxed text-[var(--color-text-muted)]">
+              Jenado Unlimited is not a single product line — it is a collection
+              of practices that support a fuller life. Whether you are looking
+              for a loaf for the table, a training plan that fits your season,
+              or a custom piece from the workshop, every offering starts with
+              the same questions: Is it honest? Is it well made? Does it serve
+              mind, body, or soul?
+            </p>
+          </div>
+
+          <div className="mt-14 grid grid-cols-1 gap-6 md:grid-cols-3">
+            {pillars.map((pillar) => (
+              <div
+                key={pillar.key}
+                className="border border-[var(--color-border)] bg-[var(--color-surface)] p-6 md:p-8"
+              >
+                <p className="mb-3 text-[11px] font-medium uppercase tracking-[0.3em] text-[var(--color-heading)]">
+                  {pillar.label}
+                </p>
+                <p className="text-[15px] leading-relaxed text-[var(--color-text-muted)]">
+                  {pillar.description}
+                </p>
+              </div>
+            ))}
+          </div>
+        </div>
+      </section>
+
+      <section className="py-16 md:py-24">
+        <div className="container-xl">
+          <div className="mb-14 flex flex-col gap-6 border-b border-[var(--color-border)] pb-10 md:flex-row md:items-end md:justify-between">
+            <div className="max-w-2xl">
+              <h2 className="mb-3 text-2xl font-semibold tracking-[-0.02em] md:text-3xl">
+                All verticals
+              </h2>
+              <p className="text-[var(--color-text-muted)] leading-relaxed">
+                Browse each offering below. Status labels show what is actively
+                available, in soft launch, or coming soon — so you always know
+                what is ready for inquiry today.
+              </p>
+            </div>
+            <Link
+              href="/contact"
+              className="shrink-0 text-sm font-medium tracking-wide text-[var(--color-heading)] transition-opacity hover:opacity-70"
+            >
+              Not sure where to start? Contact us →
+            </Link>
+          </div>
+
+          <div className="space-y-4 md:space-y-0">
+            {verticals.map((vertical, index) => (
+              <VerticalCard
+                key={vertical.slug}
+                vertical={vertical}
+                variant="feature"
+                reverse={index % 2 === 1}
+              />
+            ))}
+          </div>
+
+          <div className="mt-20 border border-[var(--color-border)] bg-[var(--color-surface)] p-8 text-center md:p-12">
+            <h2 className="mb-3 text-2xl font-semibold tracking-[-0.02em]">
+              Looking for something specific?
+            </h2>
+            <p className="mx-auto mb-8 max-w-xl text-[var(--color-text-muted)] leading-relaxed">
+              Many of our verticals can meet in the middle — gift sets of honey
+              and bread, custom engraved pieces for events, or training paired
+              with practical nutrition habits. Tell us what you have in mind and
+              we will help chart a path.
+            </p>
+            <div className="flex flex-wrap items-center justify-center gap-4">
+              <Link href="/contact" className="btn-primary">
+                Start a conversation
+              </Link>
+              <Link
+                href="/gallery"
+                className="text-sm font-medium tracking-wide text-[var(--color-heading)] transition-opacity hover:opacity-70"
+              >
+                Browse the gallery →
+              </Link>
+            </div>
+          </div>
+        </div>
+      </section>
+    </>
+  );
+}
+
+export const metadata: Metadata = {
+  title: "Offerings",
+  description:
+    "Explore Jenado Unlimited offerings — honey bees, personal training, sourdough, farm-to-table, recreation apps, laser engraving, and 3D printing.",
+};

+ 124 - 61
src/app/page.tsx

@@ -1,69 +1,132 @@
-import Image from "next/image";
+import { CTABand } from "@/components/CTABand";
+import { Logo } from "@/components/Logo";
+import { ParallaxBand } from "@/components/ParallaxBand";
+import { ParallaxHero } from "@/components/ParallaxHero";
+import { PillarStrip } from "@/components/PillarStrip";
+import { VerticalCard } from "@/components/VerticalCard";
+import { getPageContent } from "@/content/pages";
+import { getAllVerticals, siteConfig } from "@/lib/content";
+import Link from "next/link";
+
+export default function HomePage() {
+  const verticals = getAllVerticals().slice(0, 6);
+  const page = getPageContent("home");
+  const tagline =
+    siteConfig.tagline ||
+    "Craft for mind, body, and soul — local honey, training, sourdough, and more.";
 
-export default function Home() {
   return (
-    <div className="flex flex-col flex-1 items-center justify-center bg-zinc-50 font-sans dark:bg-black">
-      <main className="flex flex-1 w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
-        <Image
-          className="dark:invert h-5 w-[100px]"
-          src="/next.svg"
-          alt="Next.js logo"
-          width={100}
-          height={20}
-          priority
-        />
-        <div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
-          <h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
-            To get started, edit the{" "}
-            <code className="rounded bg-black/[.06] px-1.5 py-0.5 font-mono text-[0.9em] dark:bg-white/[.08]">
-              page.tsx
-            </code>{" "}
-            file.
+    <>
+      <ParallaxHero
+        image={page?.heroImage || "/images/hero-home.jpg"}
+        alt={
+          page?.heroAlt ||
+          "Honey, artisan bread, and candle on a wooden table overlooking a wildflower meadow at golden hour"
+        }
+        size={page?.heroSize || "full"}
+        priority={page?.heroPriority}
+        overlayClassName={
+          page?.heroOverlay ||
+          "bg-gradient-to-b from-black/50 via-black/35 to-black/75"
+        }
+      >
+        <div className="mx-auto max-w-3xl">
+          <div className="mb-8 flex justify-center">
+            <span className="logo-on-dark">
+              <Logo
+                size={88}
+                withText={false}
+                link={false}
+                className="text-white"
+              />
+            </span>
+          </div>
+          <p className="mb-3 text-[24px] font-medium uppercase tracking-[0.35em] text-white/70">
+            Jenado Unlimited
+          </p>
+          <h1 className="mb-6 text-4xl font-semibold tracking-[-0.03em] text-white md:text-6xl md:leading-[1.05]">
+            Mind. Body. Soul.
           </h1>
-          <p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
-            Looking for a starting point or more instructions? Head over to{" "}
-            <a
-              href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
-              className="font-medium text-zinc-950 dark:text-zinc-50"
-            >
-              Templates
-            </a>{" "}
-            or the{" "}
-            <a
-              href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
-              className="font-medium text-zinc-950 dark:text-zinc-50"
-            >
-              Learning
-            </a>{" "}
-            center.
+          <p className="mx-auto mb-10 max-w-xl text-lg leading-relaxed text-white/80 md:text-xl">
+            {tagline}
           </p>
+          <div className="flex flex-wrap items-center justify-center gap-4">
+            <Link href="/offerings" className="btn-hero-primary">
+              Explore Offerings
+            </Link>
+            <Link href="/contact" className="btn-hero-secondary">
+              Get in Touch
+            </Link>
+          </div>
         </div>
-        <div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
-          <a
-            className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
-            href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
-            target="_blank"
-            rel="noopener noreferrer"
-          >
-            <Image
-              className="dark:invert h-[14px] w-4"
-              src="/vercel.svg"
-              alt="Vercel logomark"
-              width={16}
-              height={14}
-            />
-            Deploy Now
-          </a>
-          <a
-            className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
-            href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
-            target="_blank"
-            rel="noopener noreferrer"
-          >
-            Documentation
-          </a>
+      </ParallaxHero>
+
+      <PillarStrip />
+
+      <section className="py-20 md:py-28">
+        <div className="container-xl">
+          <div className="mx-auto mb-14 max-w-2xl text-center">
+            <p className="mb-3 text-[11px] font-medium uppercase tracking-[0.3em] text-[var(--color-text-muted)]">
+              What we offer
+            </p>
+            <h2 className="mb-4 text-3xl font-semibold tracking-[-0.02em] md:text-4xl">
+              Crafted with intention
+            </h2>
+            <p className="text-lg text-[var(--color-text-muted)]">
+              From the hive to the gym, the oven to the workshop — explore
+              everything Jenado Unlimited has to offer.
+            </p>
+          </div>
+          <div className="grid grid-cols-1 gap-5 md:grid-cols-2 lg:grid-cols-3 lg:gap-6">
+            {verticals.map((vertical) => (
+              <VerticalCard key={vertical.slug} vertical={vertical} />
+            ))}
+          </div>
+          <div className="mt-12 text-center">
+            <Link
+              href="/offerings"
+              className="inline-flex items-center gap-2 text-sm font-medium tracking-wide text-[var(--color-heading)] transition-opacity hover:opacity-70"
+            >
+              View all offerings
+              <span aria-hidden>→</span>
+            </Link>
+          </div>
         </div>
-      </main>
-    </div>
+      </section>
+
+      <ParallaxBand
+        image="/images/hero-gallery.jpg"
+        alt="Textured still life of honey, wood grain, metal, and fabric"
+      >
+        <p className="mb-4 text-[11px] font-medium uppercase tracking-[0.3em] text-white/65">
+          The gallery
+        </p>
+        <h2 className="mx-auto mb-5 max-w-2xl text-3xl font-semibold tracking-[-0.02em] md:text-4xl">
+          A closer look at the craft
+        </h2>
+        <p className="mx-auto mb-10 max-w-lg text-lg text-white/75">
+          Honey, bread, training, and handmade work — see the textures behind
+          every offering.
+        </p>
+        <Link href="/gallery" className="btn-hero-primary">
+          Open Gallery
+        </Link>
+      </ParallaxBand>
+
+      <CTABand
+        title="Ready to Get Started?"
+        description="Whether you are interested in our honey products, fitness training, or artisan sourdough, we would love to hear from you."
+        href="/contact"
+        buttonLabel="Contact Us"
+      />
+    </>
   );
 }
+
+export function generateMetadata() {
+  return {
+    title: "Jenado Unlimited — Honey, Training, Sourdough & More",
+    description:
+      "Home page for Jenado Unlimited. Explore honey bee products, personal training, sourdough bread, farm-to-table dining, recreation apps, laser engraving, and 3D printing.",
+  };
+}

+ 513 - 0
src/app/privacy/page.tsx

@@ -0,0 +1,513 @@
+import { ParallaxHero } from "@/components/ParallaxHero";
+import { getPageContent } from "@/content/pages";
+import { siteConfig } from "@/lib/content";
+import type { Metadata } from "next";
+import Link from "next/link";
+import type { ReactNode } from "react";
+
+const page = getPageContent("privacy");
+const LAST_UPDATED = page?.lastUpdated || "August 12, 2026";
+
+function Section({
+  id,
+  title,
+  children,
+}: {
+  id: string;
+  title: string;
+  children: ReactNode;
+}) {
+  return (
+    <section
+      id={id}
+      className="scroll-mt-28 border-t border-[var(--color-border)] pt-10"
+    >
+      <h2 className="mb-5 text-[11px] font-medium uppercase tracking-[0.3em] text-[var(--color-text-muted)]">
+        {title}
+      </h2>
+      <div className="space-y-4 text-[15px] leading-relaxed text-[var(--color-text)]">
+        {children}
+      </div>
+    </section>
+  );
+}
+
+function BulletList({ items }: { items: ReactNode[] }) {
+  return (
+    <ul className="space-y-3">
+      {items.map((item, i) => (
+        <li key={i} className="flex gap-3">
+          <span
+            className="mt-2 h-1 w-1 shrink-0 rounded-full bg-[var(--color-heading)]"
+            aria-hidden
+          />
+          <span>{item}</span>
+        </li>
+      ))}
+    </ul>
+  );
+}
+
+export default function PrivacyPage() {
+  const email = siteConfig.contactEmail || "contact@jenado-unlimited.com";
+  const phone = siteConfig.contactPhone;
+  const name = siteConfig.name;
+
+  return (
+    <>
+      <ParallaxHero
+        image={page?.heroImage || "/images/hero-privacy.jpg"}
+        alt={
+          page?.heroAlt ||
+          "Layered translucent glass panes with soft light, suggesting clarity and protection"
+        }
+        size={page?.heroSize || "sm"}
+        priority={page?.heroPriority}
+        align={page?.heroAlign}
+        overlayClassName={
+          page?.heroOverlay ||
+          "bg-gradient-to-r from-black/85 via-black/60 to-black/35"
+        }
+        contentClassName={page?.heroContentClass}
+      >
+        <div className="max-w-2xl">
+          <p className="mb-4 text-[11px] font-medium uppercase tracking-[0.3em] text-white/65">
+            {page?.heroLabel}
+          </p>
+          <h1 className="mb-5 text-4xl font-semibold tracking-[-0.03em] text-white md:text-5xl">
+            {page?.title}
+          </h1>
+          <p className="max-w-xl text-lg leading-relaxed text-white/80">
+            {page?.heroDescription}
+          </p>
+        </div>
+      </ParallaxHero>
+
+      <section className="py-16 md:py-24">
+        <div className="container-xl max-w-2xl">
+          <p className="mb-4 text-sm text-[var(--color-text-muted)]">
+            Last updated: {LAST_UPDATED}
+          </p>
+
+          <nav
+            aria-label="Privacy policy sections"
+            className="mb-12 border border-[var(--color-border)] bg-[var(--color-surface)] p-6"
+          >
+            <p className="mb-4 text-[11px] font-medium uppercase tracking-[0.25em] text-[var(--color-text-muted)]">
+              On this page
+            </p>
+            <ol className="grid gap-2 text-sm text-[var(--color-text-muted)] sm:grid-cols-2">
+              {[
+                ["who-we-are", "Who we are"],
+                ["scope", "Scope"],
+                ["information-we-collect", "Information we collect"],
+                ["how-we-use", "How we use information"],
+                ["legal-bases", "Legal bases"],
+                ["sharing", "How we share information"],
+                ["cookies", "Cookies & analytics"],
+                ["retention", "Data retention"],
+                ["security", "Security"],
+                ["your-rights", "Your rights"],
+                ["children", "Children’s privacy"],
+                ["changes", "Changes to this policy"],
+                ["contact", "Contact us"],
+              ].map(([id, label]) => (
+                <li key={id}>
+                  <a
+                    href={`#${id}`}
+                    className="underline-offset-4 hover:text-[var(--color-heading)] hover:underline"
+                  >
+                    {label}
+                  </a>
+                </li>
+              ))}
+            </ol>
+          </nav>
+
+          <div className="space-y-12">
+            <p className="text-base leading-relaxed text-[var(--color-text)] md:text-lg">
+              {name} (“we,” “us,” or “our”) respects your privacy. This Privacy
+              Policy describes what information we collect when you use our
+              website, how we use it, when we share it, and the choices
+              available to you. By using our website, you agree to the practices
+              described here. If you do not agree, please do not use the site.
+            </p>
+
+            <Section id="who-we-are" title="1. Who we are">
+              <p>
+                {name} is a multi-vertical brand offering products and services
+                related to mind, body, and soul — including local honey and bee
+                products, personal training, artisan sourdough, farm-to-table
+                experiences, recreation apps, laser engraving, and 3D printing
+                (availability varies by offering).
+              </p>
+              <p>
+                For privacy questions, reach us at{" "}
+                <a
+                  href={`mailto:${email}`}
+                  className="font-medium text-[var(--color-heading)] underline-offset-4 hover:underline"
+                >
+                  {email}
+                </a>
+                {phone ? <> or {phone}</> : null}. You can also use our{" "}
+                <Link
+                  href="/contact"
+                  className="font-medium text-[var(--color-heading)] underline-offset-4 hover:underline"
+                >
+                  contact page
+                </Link>
+                .
+              </p>
+            </Section>
+
+            <Section id="scope" title="2. Scope">
+              <p>This policy applies to:</p>
+              <BulletList
+                items={[
+                  "Our public website and pages linked from it under the Jenado Unlimited brand",
+                  "Information you submit through our contact form or by email/phone",
+                  "Technical data collected automatically when you browse the site",
+                ]}
+              />
+              <p>
+                This policy does not cover third-party websites, apps, or
+                services we may link to. Their privacy practices are governed by
+                their own policies. If you purchase products, book training, or
+                work with us offline, additional terms or notices may apply and
+                will be provided in that context.
+              </p>
+            </Section>
+
+            <Section
+              id="information-we-collect"
+              title="3. Information we collect"
+            >
+              <p className="font-medium text-[var(--color-heading)]">
+                Information you provide
+              </p>
+              <p>
+                When you use our contact form or otherwise reach out, you may
+                choose to provide:
+              </p>
+              <BulletList
+                items={[
+                  "Name and email address",
+                  "Phone number (if you include one)",
+                  "Topic or offering of interest (for example, Honey Bees, Personal Training, Sourdough)",
+                  "Message content and any other details you voluntarily share",
+                ]}
+              />
+              <p>
+                You control what you put in a message. Please avoid sending
+                sensitive personal information (such as government ID numbers,
+                detailed medical records, or payment card numbers) through the
+                contact form unless we specifically ask for it through a secure
+                channel.
+              </p>
+
+              <p className="pt-2 font-medium text-[var(--color-heading)]">
+                Information collected automatically
+              </p>
+              <p>
+                Like most websites, we and our hosting or infrastructure
+                providers may automatically receive:
+              </p>
+              <BulletList
+                items={[
+                  "IP address, general location derived from IP, browser type, and device information",
+                  "Pages visited, referring URL, timestamps, and approximate usage patterns",
+                  "Diagnostic logs needed to operate, secure, and troubleshoot the site",
+                ]}
+              />
+
+              <p className="pt-2 font-medium text-[var(--color-heading)]">
+                Cookies and similar technologies
+              </p>
+              <p>
+                We may use cookies, local storage, or similar technologies for
+                essential site functions (for example, remembering theme
+                preference) and, if enabled, limited analytics or performance
+                measurement. See{" "}
+                <a
+                  href="#cookies"
+                  className="font-medium text-[var(--color-heading)] underline-offset-4 hover:underline"
+                >
+                  Cookies & analytics
+                </a>{" "}
+                below.
+              </p>
+            </Section>
+
+            <Section id="how-we-use" title="4. How we use information">
+              <p>We use the information we collect to:</p>
+              <BulletList
+                items={[
+                  "Respond to inquiries and provide information about our offerings",
+                  "Route messages to the right vertical (honey, training, craft services, and so on)",
+                  "Operate, maintain, secure, and improve the website",
+                  "Detect, prevent, and address spam, abuse, fraud, or technical issues",
+                  "Comply with legal obligations and enforce our Terms of Service",
+                  "Communicate with you about updates related to a request you initiated, when appropriate",
+                ]}
+              />
+              <p>
+                We do not sell your personal information. We do not use contact
+                form submissions to build marketing lists without a clear,
+                separate opt-in where required by law.
+              </p>
+            </Section>
+
+            <Section id="legal-bases" title="5. Legal bases for processing">
+              <p>
+                Depending on where you live and how you interact with us, we may
+                rely on one or more of the following bases to process personal
+                information:
+              </p>
+              <BulletList
+                items={[
+                  "Your consent (for example, when you voluntarily submit a form)",
+                  "Performance of a contract or steps prior to entering a contract (for example, responding to a service inquiry)",
+                  "Our legitimate interests in operating a secure website, improving services, and communicating about requests you made — balanced against your rights",
+                  "Compliance with legal obligations",
+                ]}
+              />
+            </Section>
+
+            <Section id="sharing" title="6. How we share information">
+              <p>
+                We share personal information only as needed to run our business
+                and as described below:
+              </p>
+              <BulletList
+                items={[
+                  <>
+                    <strong className="font-medium text-[var(--color-heading)]">
+                      Service providers.
+                    </strong>{" "}
+                    Hosting, email delivery, form processing, security, and
+                    similar vendors who process data on our behalf under
+                    contractual obligations to protect it.
+                  </>,
+                  <>
+                    <strong className="font-medium text-[var(--color-heading)]">
+                      Legal and safety.
+                    </strong>{" "}
+                    When required by law, regulation, legal process, or
+                    governmental request, or when we believe disclosure is
+                    necessary to protect rights, safety, or property.
+                  </>,
+                  <>
+                    <strong className="font-medium text-[var(--color-heading)]">
+                      Business transfers.
+                    </strong>{" "}
+                    In connection with a merger, acquisition, financing, or sale
+                    of assets, subject to appropriate confidentiality
+                    safeguards.
+                  </>,
+                  <>
+                    <strong className="font-medium text-[var(--color-heading)]">
+                      With your direction.
+                    </strong>{" "}
+                    When you ask us to share information or interact with a
+                    third party through us.
+                  </>,
+                ]}
+              />
+              <p>
+                Team members or contractors working with a specific vertical may
+                receive inquiry details needed to respond (for example, a
+                training inquiry may be handled by our fitness team).
+              </p>
+            </Section>
+
+            <Section id="cookies" title="7. Cookies & analytics">
+              <p>
+                <strong className="font-medium text-[var(--color-heading)]">
+                  Essential.
+                </strong>{" "}
+                Some technologies are needed for the site to function (security,
+                load balancing, remembering preferences such as light/dark
+                mode).
+              </p>
+              <p>
+                <strong className="font-medium text-[var(--color-heading)]">
+                  Analytics (if used).
+                </strong>{" "}
+                We may use privacy-conscious analytics or server logs to
+                understand aggregate traffic (for example, which pages are
+                popular). Where required, we will provide additional notice or
+                choice.
+              </p>
+              <p>
+                You can control cookies through your browser settings. Blocking
+                certain cookies may affect site functionality. Do Not Track
+                signals are not consistently standardized; we treat personal
+                information according to this policy regardless of DNT headers.
+              </p>
+            </Section>
+
+            <Section id="retention" title="8. Data retention">
+              <p>
+                We keep personal information only as long as needed for the
+                purposes described in this policy, unless a longer period is
+                required or permitted by law. Typical practices include:
+              </p>
+              <BulletList
+                items={[
+                  "Contact form and email correspondence: retained for as long as needed to complete your request and for a reasonable follow-up period, then deleted or archived according to our records practices",
+                  "Server and security logs: retained for a limited period for operations, security, and troubleshooting",
+                  "Legal holds: retained longer when necessary for disputes, investigations, or compliance",
+                ]}
+              />
+            </Section>
+
+            <Section id="security" title="9. Security">
+              <p>
+                We implement reasonable administrative, technical, and
+                organizational measures designed to protect personal information
+                against unauthorized access, loss, misuse, or alteration. No
+                method of transmission over the Internet or electronic storage
+                is completely secure. We cannot guarantee absolute security, and
+                you use the site at your own risk with respect to residual
+                threats.
+              </p>
+              <p>
+                If we become aware of a data incident that affects your personal
+                information and notification is required by law, we will notify
+                you and/or regulators as required.
+              </p>
+            </Section>
+
+            <Section id="your-rights" title="10. Your rights & choices">
+              <p>
+                Depending on your location, you may have rights regarding your
+                personal information, which can include:
+              </p>
+              <BulletList
+                items={[
+                  "Accessing the personal information we hold about you",
+                  "Correcting inaccurate information",
+                  "Requesting deletion, subject to legal exceptions",
+                  "Objecting to or restricting certain processing",
+                  "Withdrawing consent where processing is based on consent",
+                  "Receiving a portable copy of information you provided, where applicable",
+                ]}
+              />
+              <p>
+                To exercise these rights, contact us at{" "}
+                <a
+                  href={`mailto:${email}`}
+                  className="font-medium text-[var(--color-heading)] underline-offset-4 hover:underline"
+                >
+                  {email}
+                </a>
+                . We may need to verify your identity before fulfilling a
+                request. Residents of certain U.S. states (including California
+                and others with consumer privacy laws) may have additional
+                rights; we will honor applicable state law. If you are in the
+                EEA/UK, you may also lodge a complaint with your local data
+                protection authority.
+              </p>
+            </Section>
+
+            <Section id="children" title="11. Children’s privacy">
+              <p>
+                Our website is not directed to children under 13 (or the
+                equivalent minimum age in your jurisdiction), and we do not
+                knowingly collect personal information from children. If you
+                believe a child has provided us personal information, contact us
+                and we will take steps to delete it as appropriate.
+              </p>
+              <p>
+                Personal training, food products, and other offerings may have
+                additional age or guardian requirements when services are
+                delivered in person; those will be communicated separately.
+              </p>
+            </Section>
+
+            <Section id="international" title="12. International visitors">
+              <p>
+                We are based in the United States. If you access the site from
+                outside the U.S., your information may be processed in the
+                United States or other countries where our service providers
+                operate. Those countries may have different data-protection
+                rules than your home country. By using the site, you understand
+                that your information may be transferred as described in this
+                policy.
+              </p>
+            </Section>
+
+            <Section id="changes" title="13. Changes to this policy">
+              <p>
+                We may update this Privacy Policy from time to time. When we do,
+                we will revise the “Last updated” date at the top of this page
+                and, if changes are material, we may provide additional notice
+                (for example, a site banner or email when appropriate). Your
+                continued use of the website after an update constitutes
+                acceptance of the revised policy, to the extent permitted by
+                law.
+              </p>
+            </Section>
+
+            <Section id="contact" title="14. Contact us">
+              <p>
+                Questions about this Privacy Policy or our privacy practices:
+              </p>
+              <div className="border border-[var(--color-border)] bg-[var(--color-surface)] p-6">
+                <p className="font-medium text-[var(--color-heading)]">
+                  {name}
+                </p>
+                <p className="mt-3">
+                  Email:{" "}
+                  <a
+                    href={`mailto:${email}`}
+                    className="font-medium text-[var(--color-heading)] underline-offset-4 hover:underline"
+                  >
+                    {email}
+                  </a>
+                </p>
+                {phone && (
+                  <p className="mt-1">
+                    Phone:{" "}
+                    <a
+                      href={`tel:${phone.replace(/[^\d+]/g, "")}`}
+                      className="font-medium text-[var(--color-heading)] underline-offset-4 hover:underline"
+                    >
+                      {phone}
+                    </a>
+                  </p>
+                )}
+                <p className="mt-4 text-[var(--color-text-muted)]">
+                  Prefer a form?{" "}
+                  <Link
+                    href="/contact"
+                    className="font-medium text-[var(--color-heading)] underline-offset-4 hover:underline"
+                  >
+                    Contact us
+                  </Link>
+                  .
+                </p>
+              </div>
+              <p className="text-sm text-[var(--color-text-muted)]">
+                Related:{" "}
+                <Link
+                  href="/terms"
+                  className="underline-offset-4 hover:text-[var(--color-heading)] hover:underline"
+                >
+                  Terms of Service
+                </Link>
+                .
+              </p>
+            </Section>
+          </div>
+        </div>
+      </section>
+    </>
+  );
+}
+
+export const metadata: Metadata = {
+  title: "Privacy Policy | Jenado Unlimited",
+  description:
+    "Jenado Unlimited Privacy Policy — how we collect, use, share, and protect your personal information.",
+};

+ 551 - 0
src/app/terms/page.tsx

@@ -0,0 +1,551 @@
+import { ParallaxHero } from "@/components/ParallaxHero";
+import { getPageContent } from "@/content/pages";
+import { siteConfig } from "@/lib/content";
+import type { Metadata } from "next";
+import Link from "next/link";
+import type { ReactNode } from "react";
+
+const page = getPageContent("terms");
+const LAST_UPDATED = page?.lastUpdated || "August 12, 2026";
+
+function Section({
+  id,
+  title,
+  children,
+}: {
+  id: string;
+  title: string;
+  children: ReactNode;
+}) {
+  return (
+    <section
+      id={id}
+      className="scroll-mt-28 border-t border-[var(--color-border)] pt-10"
+    >
+      <h2 className="mb-5 text-[11px] font-medium uppercase tracking-[0.3em] text-[var(--color-text-muted)]">
+        {title}
+      </h2>
+      <div className="space-y-4 text-[15px] leading-relaxed text-[var(--color-text)]">
+        {children}
+      </div>
+    </section>
+  );
+}
+
+function BulletList({ items }: { items: ReactNode[] }) {
+  return (
+    <ul className="space-y-3">
+      {items.map((item, i) => (
+        <li key={i} className="flex gap-3">
+          <span
+            className="mt-2 h-1 w-1 shrink-0 rounded-full bg-[var(--color-heading)]"
+            aria-hidden
+          />
+          <span>{item}</span>
+        </li>
+      ))}
+    </ul>
+  );
+}
+
+export default function TermsPage() {
+  const email = siteConfig.contactEmail || "contact@jenado-unlimited.com";
+  const phone = siteConfig.contactPhone;
+  const name = siteConfig.name;
+
+  return (
+    <>
+      <ParallaxHero
+        image={page?.heroImage || "/images/hero-terms.jpg"}
+        alt={
+          page?.heroAlt ||
+          "Leather-bound book with brass paperweight on a warm wooden desk"
+        }
+        size={page?.heroSize || "sm"}
+        priority={page?.heroPriority}
+        align={page?.heroAlign}
+        overlayClassName={
+          page?.heroOverlay ||
+          "bg-gradient-to-r from-black/85 via-black/60 to-black/35"
+        }
+        contentClassName={page?.heroContentClass}
+      >
+        <div className="max-w-2xl">
+          <p className="mb-4 text-[11px] font-medium uppercase tracking-[0.3em] text-white/65">
+            {page?.heroLabel}
+          </p>
+          <h1 className="mb-5 text-4xl font-semibold tracking-[-0.03em] text-white md:text-5xl">
+            {page?.title}
+          </h1>
+          <p className="max-w-xl text-lg leading-relaxed text-white/80">
+            {page?.heroDescription}
+          </p>
+        </div>
+      </ParallaxHero>
+
+      <section className="py-16 md:py-24">
+        <div className="container-xl max-w-2xl">
+          <p className="mb-4 text-sm text-[var(--color-text-muted)]">
+            Last updated: {LAST_UPDATED}
+          </p>
+
+          <nav
+            aria-label="Terms of service sections"
+            className="mb-12 border border-[var(--color-border)] bg-[var(--color-surface)] p-6"
+          >
+            <p className="mb-4 text-[11px] font-medium uppercase tracking-[0.25em] text-[var(--color-text-muted)]">
+              On this page
+            </p>
+            <ol className="grid gap-2 text-sm text-[var(--color-text-muted)] sm:grid-cols-2">
+              {[
+                ["agreement", "Agreement to terms"],
+                ["about", "About our services"],
+                ["eligibility", "Eligibility"],
+                ["acceptable-use", "Acceptable use"],
+                ["inquiries", "Inquiries & communications"],
+                ["intellectual-property", "Intellectual property"],
+                ["offerings", "Products & offerings"],
+                ["disclaimers-health", "Health, food & safety"],
+                ["no-advice", "No professional advice"],
+                ["third-parties", "Third-party links"],
+                ["disclaimers", "Disclaimers"],
+                ["liability", "Limitation of liability"],
+                ["indemnification", "Indemnification"],
+                ["governing-law", "Governing law"],
+                ["changes", "Changes"],
+                ["contact", "Contact"],
+              ].map(([id, label]) => (
+                <li key={id}>
+                  <a
+                    href={`#${id}`}
+                    className="underline-offset-4 hover:text-[var(--color-heading)] hover:underline"
+                  >
+                    {label}
+                  </a>
+                </li>
+              ))}
+            </ol>
+          </nav>
+
+          <div className="space-y-12">
+            <p className="text-base leading-relaxed text-[var(--color-text)] md:text-lg">
+              These Terms of Service (“Terms”) govern your access to and use of
+              the website operated by {name} (“we,” “us,” or “our”), including
+              content, features, and contact forms available on the site. By
+              accessing or using the website, you agree to these Terms and our{" "}
+              <Link
+                href="/privacy"
+                className="font-medium text-[var(--color-heading)] underline-offset-4 hover:underline"
+              >
+                Privacy Policy
+              </Link>
+              . If you do not agree, do not use the website.
+            </p>
+
+            <Section id="agreement" title="1. Agreement to terms">
+              <p>
+                These Terms form a binding agreement between you and {name}. We
+                may update these Terms from time to time. The “Last updated”
+                date at the top of this page will change when we do. Continued
+                use of the website after changes become effective constitutes
+                acceptance of the revised Terms, except where applicable law
+                requires additional consent.
+              </p>
+            </Section>
+
+            <Section id="about" title="2. About our services">
+              <p>
+                {name} is a multi-vertical brand. Through this website we
+                describe and invite inquiries about offerings that may include,
+                without limitation:
+              </p>
+              <BulletList
+                items={[
+                  "Honey bees — local honey and related bee products",
+                  "Personal training — fitness coaching and related programs",
+                  "Sourdough breads — artisan baked goods",
+                  "Farm-to-table — seasonal dining and local ingredients experiences",
+                  "Recreation apps — digital tools for mindful recreation",
+                  "Laser engraving and 3D printing — custom craft and fabrication services",
+                ]}
+              />
+              <p>
+                Not every offering is available at all times. Some may be listed
+                as soft-launch, coming soon, or otherwise limited. Website
+                descriptions are informational and do not guarantee
+                availability, pricing, or specific results.
+              </p>
+            </Section>
+
+            <Section id="eligibility" title="3. Eligibility">
+              <p>
+                You must be able to form a binding contract under applicable law
+                to use this website. If you use the site on behalf of an
+                organization, you represent that you have authority to bind that
+                organization to these Terms. Certain offerings (for example,
+                training programs or food products) may have additional age,
+                health, or guardian requirements communicated at the time of
+                booking or sale.
+              </p>
+            </Section>
+
+            <Section id="acceptable-use" title="4. Acceptable use">
+              <p>
+                You agree to use the website only for lawful purposes. You will
+                not:
+              </p>
+              <BulletList
+                items={[
+                  "Violate any applicable law, regulation, or third-party right",
+                  "Submit spam, malware, automated bulk requests, or abuse the contact form",
+                  "Attempt to gain unauthorized access to our systems, accounts, or data",
+                  "Scrape, harvest, or index the site in a way that overloads or harms our infrastructure, except for standard search-engine indexing",
+                  "Impersonate any person or entity, or misrepresent your affiliation",
+                  "Interfere with or disrupt the website or related networks",
+                  "Use the site to harass, threaten, or harm others",
+                  "Copy, modify, or create derivative works from our content except as expressly allowed",
+                ]}
+              />
+              <p>
+                We may suspend or terminate access, refuse service, or take
+                other appropriate action if we reasonably believe you have
+                violated these Terms.
+              </p>
+            </Section>
+
+            <Section id="inquiries" title="5. Inquiries & communications">
+              <p>
+                Submitting a contact form, email, or phone inquiry does not
+                create a client, student, patient, or sales contract. We will
+                use commercially reasonable efforts to respond, but we do not
+                guarantee response times or that every inquiry will result in
+                engagement.
+              </p>
+              <p>
+                You represent that information you provide is accurate and that
+                you have the right to share it. You agree not to submit
+                unlawful, defamatory, or infringing content. Messages may be
+                monitored for spam, security, and quality.
+              </p>
+              <p>
+                Any quotes, schedules, or agreements for products or services
+                will be confirmed separately in writing (including email) or
+                through another process we designate. Website content does not
+                modify those separate terms unless expressly stated.
+              </p>
+            </Section>
+
+            <Section
+              id="intellectual-property"
+              title="6. Intellectual property"
+            >
+              <p>
+                The website and its contents — including text, graphics, logos,
+                photographs, layouts, and software — are owned by {name} or our
+                licensors and are protected by copyright, trademark, and other
+                laws. “Jenado Unlimited” and related marks are used to identify
+                our brand.
+              </p>
+              <p>
+                We grant you a limited, non-exclusive, non-transferable,
+                revocable license to access and view the website for personal,
+                non-commercial use. You may not reproduce, distribute, publicly
+                display, sell, or exploit site content without our prior written
+                permission, except for fair use or other rights that cannot be
+                waived under law.
+              </p>
+              <p>
+                If you believe content on the site infringes your copyright,
+                contact us at{" "}
+                <a
+                  href={`mailto:${email}`}
+                  className="font-medium text-[var(--color-heading)] underline-offset-4 hover:underline"
+                >
+                  {email}
+                </a>{" "}
+                with sufficient detail for us to locate the material and
+                respond.
+              </p>
+            </Section>
+
+            <Section id="offerings" title="7. Products, services & custom work">
+              <p>
+                Descriptions of honey products, breads, training, craft
+                services, apps, and other offerings are provided for general
+                information. Features, ingredients, availability, lead times,
+                and pricing may change. Images are representative and may not
+                depict the exact item you receive.
+              </p>
+              <p>
+                Custom laser engraving, 3D printing, and similar work may
+                require your review of proofs, material choices, and usage
+                rights for any designs or files you provide. You are responsible
+                for ensuring you have rights to content you ask us to produce
+                and that the requested work does not violate law or third-party
+                rights.
+              </p>
+              <p>
+                Digital or app offerings, if made available, may be subject to
+                additional end-user license terms, store policies, or platform
+                rules.
+              </p>
+            </Section>
+
+            <Section
+              id="disclaimers-health"
+              title="8. Health, food & safety notices"
+            >
+              <p className="font-medium text-[var(--color-heading)]">
+                Food products (including honey and sourdough)
+              </p>
+              <p>
+                Our food products may contain or be produced near allergens such
+                as gluten, dairy, nuts, seeds, or bee products. Honey is not
+                recommended for infants under one year of age. If you have
+                allergies, dietary restrictions, or medical conditions, review
+                ingredients carefully and consult a qualified professional as
+                needed. We cannot guarantee a completely allergen-free
+                environment for artisan or small-batch production.
+              </p>
+
+              <p className="pt-2 font-medium text-[var(--color-heading)]">
+                Personal training & fitness
+              </p>
+              <p>
+                Physical activity involves risk of injury. Training content or
+                programs described on this site are not a substitute for medical
+                advice, diagnosis, or treatment. Consult a physician before
+                beginning any exercise program, especially if you have health
+                conditions, are pregnant, or have been inactive. You assume
+                responsibility for knowing your limits and following safety
+                guidance provided in any formal training engagement.
+              </p>
+
+              <p className="pt-2 font-medium text-[var(--color-heading)]">
+                Farm-to-table & events
+              </p>
+              <p>
+                Seasonal menus, ingredient sourcing, and event details may vary.
+                Notify us of allergies or restrictions when booking or
+                inquiring. We will make reasonable efforts to accommodate but
+                cannot eliminate all cross-contact risks.
+              </p>
+            </Section>
+
+            <Section id="no-advice" title="9. No professional advice">
+              <p>
+                Content on this website — including wellness, fitness,
+                nutrition, craft, or lifestyle information — is for general
+                educational and marketing purposes only. It is not medical,
+                legal, financial, or other professional advice. Always seek the
+                advice of qualified professionals regarding your specific
+                situation.
+              </p>
+            </Section>
+
+            <Section id="third-parties" title="10. Third-party links & tools">
+              <p>
+                The website may link to third-party sites, platforms, or tools
+                (for example, social media or app stores). We do not control and
+                are not responsible for their content, policies, or practices.
+                Your use of third-party services is at your own risk and subject
+                to their terms.
+              </p>
+            </Section>
+
+            <Section id="disclaimers" title="11. Disclaimers">
+              <p>
+                THE WEBSITE AND ALL CONTENT ARE PROVIDED “AS IS” AND “AS
+                AVAILABLE.” TO THE FULLEST EXTENT PERMITTED BY LAW, WE DISCLAIM
+                ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING MERCHANTABILITY,
+                FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT.
+              </p>
+              <p>
+                We do not warrant that the site will be uninterrupted, secure,
+                error-free, or free of viruses or other harmful components, or
+                that content will be accurate, complete, or current. You are
+                responsible for implementing appropriate safeguards when using
+                the Internet.
+              </p>
+              <p>
+                Some jurisdictions do not allow certain warranty disclaimers; in
+                those places, disclaimers apply to the maximum extent permitted.
+              </p>
+            </Section>
+
+            <Section id="liability" title="12. Limitation of liability">
+              <p>
+                TO THE FULLEST EXTENT PERMITTED BY LAW, {name.toUpperCase()} AND
+                ITS OWNERS, EMPLOYEES, CONTRACTORS, AND AGENTS WILL NOT BE
+                LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL,
+                EXEMPLARY, OR PUNITIVE DAMAGES, OR ANY LOSS OF PROFITS, DATA,
+                GOODWILL, OR BUSINESS OPPORTUNITY, ARISING OUT OF OR RELATED TO
+                YOUR USE OF (OR INABILITY TO USE) THE WEBSITE OR RELIANCE ON
+                SITE CONTENT, WHETHER BASED ON WARRANTY, CONTRACT, TORT
+                (INCLUDING NEGLIGENCE), STATUTE, OR ANY OTHER LEGAL THEORY, EVEN
+                IF WE HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+              </p>
+              <p>
+                TO THE FULLEST EXTENT PERMITTED BY LAW, OUR TOTAL LIABILITY FOR
+                ANY CLAIM ARISING OUT OF OR RELATING TO THE WEBSITE OR THESE
+                TERMS WILL NOT EXCEED THE GREATER OF (A) THE AMOUNT YOU PAID US,
+                IF ANY, FOR THE SPECIFIC PRODUCT OR SERVICE GIVING RISE TO THE
+                CLAIM IN THE TWELVE MONTHS BEFORE THE CLAIM, OR (B) ONE HUNDRED
+                U.S. DOLLARS (US $100).
+              </p>
+              <p>
+                Nothing in these Terms limits liability that cannot be limited
+                under applicable law (for example, certain liability for
+                personal injury caused by negligence, or fraud). Separate
+                written agreements for products or services may specify
+                different allocations of risk for those engagements.
+              </p>
+            </Section>
+
+            <Section id="indemnification" title="13. Indemnification">
+              <p>
+                You agree to defend, indemnify, and hold harmless {name} and its
+                owners, employees, contractors, and agents from and against any
+                claims, damages, losses, liabilities, costs, and expenses
+                (including reasonable attorneys’ fees) arising out of or related
+                to: (a) your use of the website; (b) your violation of these
+                Terms; (c) your violation of any law or third-party right; or
+                (d) content or materials you submit to us (including designs or
+                files for custom work), except to the extent caused by our
+                willful misconduct.
+              </p>
+            </Section>
+
+            <Section id="governing-law" title="14. Governing law & disputes">
+              <p>
+                These Terms are governed by the laws of the State of Wisconsin,
+                United States, without regard to conflict-of-law principles,
+                except where mandatory consumer protection laws of your place of
+                residence provide otherwise.
+              </p>
+              <p>
+                You agree that exclusive venue for any dispute arising out of or
+                relating to these Terms or the website will be the state or
+                federal courts located in Wisconsin, and you consent to personal
+                jurisdiction there, unless applicable law requires otherwise. If
+                you are a consumer, you may also have rights to bring claims in
+                your local courts.
+              </p>
+              <p>
+                Before filing a formal claim, please contact us so we can try to
+                resolve the issue informally.
+              </p>
+            </Section>
+
+            <Section id="miscellaneous" title="15. Miscellaneous">
+              <BulletList
+                items={[
+                  <>
+                    <strong className="font-medium text-[var(--color-heading)]">
+                      Entire agreement.
+                    </strong>{" "}
+                    These Terms, together with the Privacy Policy and any
+                    additional terms we present for specific services, are the
+                    entire agreement between you and us regarding the website.
+                  </>,
+                  <>
+                    <strong className="font-medium text-[var(--color-heading)]">
+                      Severability.
+                    </strong>{" "}
+                    If any provision is held unenforceable, the remaining
+                    provisions will continue in effect.
+                  </>,
+                  <>
+                    <strong className="font-medium text-[var(--color-heading)]">
+                      Waiver.
+                    </strong>{" "}
+                    Failure to enforce a provision is not a waiver of the right
+                    to enforce it later.
+                  </>,
+                  <>
+                    <strong className="font-medium text-[var(--color-heading)]">
+                      Assignment.
+                    </strong>{" "}
+                    You may not assign these Terms without our consent. We may
+                    assign them in connection with a reorganization, merger, or
+                    sale of assets.
+                  </>,
+                  <>
+                    <strong className="font-medium text-[var(--color-heading)]">
+                      Force majeure.
+                    </strong>{" "}
+                    We are not liable for delays or failures due to causes
+                    beyond our reasonable control.
+                  </>,
+                ]}
+              />
+            </Section>
+
+            <Section id="changes" title="16. Changes to the website">
+              <p>
+                We may modify, suspend, or discontinue any part of the website
+                at any time, with or without notice. We are not liable if the
+                site is unavailable for any period.
+              </p>
+            </Section>
+
+            <Section id="contact" title="17. Contact">
+              <p>Questions about these Terms of Service:</p>
+              <div className="border border-[var(--color-border)] bg-[var(--color-surface)] p-6">
+                <p className="font-medium text-[var(--color-heading)]">
+                  {name}
+                </p>
+                <p className="mt-3">
+                  Email:{" "}
+                  <a
+                    href={`mailto:${email}`}
+                    className="font-medium text-[var(--color-heading)] underline-offset-4 hover:underline"
+                  >
+                    {email}
+                  </a>
+                </p>
+                {phone && (
+                  <p className="mt-1">
+                    Phone:{" "}
+                    <a
+                      href={`tel:${phone.replace(/[^\d+]/g, "")}`}
+                      className="font-medium text-[var(--color-heading)] underline-offset-4 hover:underline"
+                    >
+                      {phone}
+                    </a>
+                  </p>
+                )}
+                <p className="mt-4 text-[var(--color-text-muted)]">
+                  Prefer a form?{" "}
+                  <Link
+                    href="/contact"
+                    className="font-medium text-[var(--color-heading)] underline-offset-4 hover:underline"
+                  >
+                    Contact us
+                  </Link>
+                  .
+                </p>
+              </div>
+              <p className="text-sm text-[var(--color-text-muted)]">
+                Related:{" "}
+                <Link
+                  href="/privacy"
+                  className="underline-offset-4 hover:text-[var(--color-heading)] hover:underline"
+                >
+                  Privacy Policy
+                </Link>
+                .
+              </p>
+            </Section>
+          </div>
+        </div>
+      </section>
+    </>
+  );
+}
+
+export const metadata: Metadata = {
+  title: "Terms of Service | Jenado Unlimited",
+  description:
+    "Jenado Unlimited Terms of Service — rules for using our website, content, and related offerings.",
+};

+ 40 - 0
src/components/CTABand.test.tsx

@@ -0,0 +1,40 @@
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it } from "vitest";
+import { CTABand } from "./CTABand";
+
+describe("CTABand", () => {
+  it("renders title and description", () => {
+    render(
+      <CTABand
+        title="Ready?"
+        description="Let's go."
+        href="/contact"
+        buttonLabel="Contact"
+      />,
+    );
+    expect(screen.getByRole("heading", { name: "Ready?" })).toBeInTheDocument();
+    expect(screen.getByText("Let's go.")).toBeInTheDocument();
+  });
+
+  it("renders a link with the correct href and label", () => {
+    render(
+      <CTABand
+        title="Go"
+        description="Now"
+        href="/offerings"
+        buttonLabel="Explore"
+      />,
+    );
+    const link = screen.getByRole("link", { name: "Explore" });
+    expect(link).toHaveAttribute("href", "/offerings");
+  });
+
+  it("applies variant classes", () => {
+    const { container } = render(
+      <CTABand title="Accent" description="Test" href="/x" variant="accent" />,
+    );
+    // The section should contain the accent background class
+    const section = container.querySelector("section");
+    expect(section?.className).toContain("bg-[var(--color-accent)]");
+  });
+});

+ 39 - 0
src/components/CTABand.tsx

@@ -0,0 +1,39 @@
+export function CTABand({
+  title,
+  description,
+  href,
+  buttonLabel = "Learn more",
+  variant = "default",
+}: {
+  title: string;
+  description: string;
+  href: string;
+  buttonLabel?: string;
+  variant?: "default" | "accent" | "dark";
+}) {
+  const variants = {
+    default: "bg-[var(--color-surface)] text-[var(--color-heading)]",
+    accent: "bg-[var(--color-accent)] text-white",
+    dark: "bg-[var(--color-heading)] text-[var(--color-surface)]",
+  };
+
+  return (
+    <section
+      className={`border-t border-[var(--color-border)] py-20 md:py-28 ${variants[variant]}`}
+    >
+      <div className="container-xl text-center">
+        <h2 className="mb-4 text-3xl font-semibold tracking-[-0.02em] md:text-4xl">
+          {title}
+        </h2>
+        <p
+          className={`mx-auto mb-10 max-w-xl text-lg ${variant === "default" ? "text-[var(--color-text-muted)]" : "opacity-80"}`}
+        >
+          {description}
+        </p>
+        <a href={href} className="btn-primary">
+          {buttonLabel}
+        </a>
+      </div>
+    </section>
+  );
+}

+ 162 - 0
src/components/ContactForm.tsx

@@ -0,0 +1,162 @@
+"use client";
+
+import { useState } from "react";
+
+const topics = [
+  { value: "general", label: "General Inquiry" },
+  { value: "honey-bees", label: "Honey Bees" },
+  { value: "personal-training", label: "Personal Training" },
+  { value: "sourdough", label: "Sourdough Breads" },
+  { value: "farm-to-table", label: "Farm-to-Table" },
+  { value: "recreation-apps", label: "Recreation Apps" },
+  { value: "laser-engraving", label: "Laser Engraving" },
+  { value: "3d-printing", label: "3D Printing" },
+];
+
+export function ContactForm() {
+  const [formState, setFormState] = useState<"idle" | "submitting" | "success" | "error">("idle");
+  const [formMessage, setFormMessage] = useState("");
+
+  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
+    e.preventDefault();
+    const raw = new FormData(e.target as HTMLFormElement);
+    const data: Record<string, string> = {} as Record<string, string>;
+    raw.forEach((v, k) => { data[k] = v as string; });
+
+    // Honeypot check — bots fill these hidden fields
+    if (data.honeybee_website || data.honeybee_company) {
+      // Silent success — indistinguishable from real submission
+      setFormState("success");
+      setFormMessage("Message sent successfully!");
+      return;
+    }
+
+    setFormState("submitting");
+
+    try {
+      const response = await fetch("/api/contact", {
+        method: "POST",
+        headers: { "Content-Type": "application/json" },
+        body: JSON.stringify(data),
+      });
+
+      const result = await response.json();
+
+      if (!result.ok) {
+        setFormState("error");
+        setFormMessage(result.error || "Something went wrong. Please try again.");
+        return;
+      }
+
+      setFormState("success");
+      setFormMessage("Message sent successfully! We will get back to you soon.");
+      (e.target as HTMLFormElement).reset();
+    } catch {
+      setFormState("error");
+      setFormMessage("Network error. Please try again.");
+    }
+  };
+
+  return (
+    <form onSubmit={handleSubmit} className="space-y-6">
+      {formMessage && (
+        <div
+          className={`rounded-lg p-4 text-sm ${
+            formState === "error"
+              ? "bg-red-50 text-red-700 dark:bg-red-900/20 dark:text-red-400"
+              : "bg-green-50 text-green-700 dark:bg-green-900/20 dark:text-green-400"
+          }`}
+          role="alert"
+        >
+          {formMessage}
+        </div>
+      )}
+
+      <div>
+        <label htmlFor="name" className="mb-1 block text-sm font-medium">
+          Name <span className="text-red-500">*</span>
+        </label>
+        <input
+          id="name"
+          name="name"
+          type="text"
+          className="input"
+          placeholder="Your name"
+          required
+          minLength={2}
+          maxLength={80}
+        />
+      </div>
+
+      <div>
+        <label htmlFor="email" className="mb-1 block text-sm font-medium">
+          Email <span className="text-red-500">*</span>
+        </label>
+        <input
+          id="email"
+          name="email"
+          type="email"
+          className="input"
+          placeholder="you@example.com"
+          required
+          maxLength={254}
+        />
+      </div>
+
+      <div>
+        <label htmlFor="topic" className="mb-1 block text-sm font-medium">
+          Topic
+        </label>
+        <select id="topic" name="topic" className="input" defaultValue="general">
+          {topics.map((t) => (
+            <option key={t.value} value={t.value}>{t.label}</option>
+          ))}
+        </select>
+      </div>
+
+      <div>
+        <label htmlFor="phone" className="mb-1 block text-sm font-medium">
+          Phone (optional)
+        </label>
+        <input
+          id="phone"
+          name="phone"
+          type="tel"
+          className="input"
+          placeholder="(555) 123-4567"
+        />
+      </div>
+
+      <div>
+        <label htmlFor="message" className="mb-1 block text-sm font-medium">
+          Message <span className="text-red-500">*</span>
+        </label>
+        <textarea
+          id="message"
+          name="message"
+          className="textarea"
+          placeholder="How can we help?"
+          required
+          minLength={10}
+          maxLength={5000}
+        />
+      </div>
+
+      {/* Honeypot — hidden from users, filled by bots */}
+      <div className="hidden">
+        <label htmlFor="honeybee_website" className="sr-only">Website</label>
+        <input id="honeybee_website" name="honeybee_website" tabIndex={-1} autoComplete="off" />
+        <label htmlFor="honeybee_company" className="sr-only">Company</label>
+        <input id="honeybee_company" name="honeybee_company" tabIndex={-1} autoComplete="off" />
+      </div>
+
+      <button
+        type="submit"
+        disabled={formState === "submitting"}
+        className="btn-primary w-full"
+      >
+        {formState === "submitting" ? "Sending..." : "Send Message"}
+      </button>
+    </form>
+  );
+}

+ 75 - 0
src/components/Footer.tsx

@@ -0,0 +1,75 @@
+import { siteConfig } from "@/lib/content";
+import Link from "next/link";
+import { Logo } from "./Logo";
+
+const legalLinks = [
+  { href: "/privacy", label: "Privacy" },
+  { href: "/terms", label: "Terms" },
+];
+
+const linkClass =
+  "text-[12px] tracking-wide text-[var(--color-text-muted)] transition-colors hover:text-[var(--color-heading)]";
+
+export function Footer() {
+  const year = new Date().getFullYear();
+  const phoneHref = siteConfig.contactPhone
+    ? `tel:${siteConfig.contactPhone.replace(/[^\d+]/g, "")}`
+    : undefined;
+
+  return (
+    <footer className="border-t border-[var(--color-border)] bg-[var(--color-surface)]">
+      <div className="container-xl">
+        <div className="flex flex-col items-start justify-between gap-4 py-4 sm:flex-row sm:items-center sm:gap-6">
+          {/* Brand */}
+          <Link
+            href="/"
+            aria-label={siteConfig.name}
+            className="inline-flex shrink-0 items-center gap-2.5 transition-opacity hover:opacity-70"
+          >
+            <Logo size={18} withText={false} link={false} />
+            <span className="text-[12px] font-medium tracking-[-0.01em] text-[var(--color-heading)]">
+              {siteConfig.name}
+            </span>
+          </Link>
+
+          {/* Contact — always one line */}
+          <div className="flex min-w-0 flex-nowrap items-center gap-x-2.5 overflow-x-auto">
+            {siteConfig.contactEmail && (
+              <Link
+                href={`mailto:${siteConfig.contactEmail}`}
+                className={`${linkClass} whitespace-nowrap`}
+              >
+                {siteConfig.contactEmail}
+              </Link>
+            )}
+            {siteConfig.contactEmail && siteConfig.contactPhone && (
+              <span className="shrink-0 text-[var(--color-border)]" aria-hidden>
+                ·
+              </span>
+            )}
+            {siteConfig.contactPhone && phoneHref && (
+              <Link
+                href={phoneHref}
+                className={`${linkClass} whitespace-nowrap`}
+              >
+                {siteConfig.contactPhone}
+              </Link>
+            )}
+          </div>
+
+          {/* Legal + copyright */}
+          <div className="flex shrink-0 flex-nowrap items-center gap-x-4">
+            {legalLinks.map((link) => (
+              <Link key={link.href} href={link.href} className={linkClass}>
+                {link.label}
+              </Link>
+            ))}
+            <span className="whitespace-nowrap text-[11px] tracking-wide text-[var(--color-text-muted)]/80">
+              © {year} {siteConfig.name}
+            </span>
+          </div>
+        </div>
+      </div>
+    </footer>
+  );
+}

+ 81 - 0
src/components/GalleryGrid.tsx

@@ -0,0 +1,81 @@
+import Image from "next/image";
+import Link from "next/link";
+import type { GalleryItem } from "@/lib/gallery";
+
+function cellClass(span?: GalleryItem["span"]) {
+  if (span === "wide") return "md:col-span-2";
+  if (span === "tall") return "md:row-span-2";
+  return "";
+}
+
+function aspectClass(span?: GalleryItem["span"]) {
+  if (span === "tall") return "aspect-[3/4] md:aspect-auto md:min-h-full md:h-full";
+  if (span === "wide") return "aspect-[16/10] md:aspect-[21/9]";
+  return "aspect-[4/3]";
+}
+
+export function GalleryGrid({
+  images,
+  showLabels = true,
+}: {
+  images?: GalleryItem[];
+  showLabels?: boolean;
+}) {
+  if (!images || images.length === 0) {
+    return (
+      <div className="flex items-center justify-center border border-[var(--color-border)] py-20 text-[var(--color-text-muted)]">
+        <p className="text-sm uppercase tracking-[2px]">Gallery coming soon</p>
+      </div>
+    );
+  }
+
+  return (
+    <div className="grid auto-rows-fr grid-cols-1 gap-3 md:grid-cols-2 md:gap-4 lg:grid-cols-3">
+      {images.map((img, i) => {
+        const inner = (
+          <>
+            <Image
+              src={img.url}
+              alt={img.alt || `Gallery image ${i + 1}`}
+              fill
+              sizes={
+                img.span === "wide"
+                  ? "(max-width: 768px) 100vw, 66vw"
+                  : "(max-width: 768px) 100vw, 33vw"
+              }
+              className="object-cover transition-transform duration-700 ease-out group-hover:scale-105"
+            />
+            <div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-black/60 via-black/5 to-transparent opacity-80 transition-opacity duration-300 group-hover:opacity-100" />
+            {showLabels && img.label && (
+              <div className="absolute inset-x-0 bottom-0 p-4 md:p-5">
+                <span className="text-xs font-medium uppercase tracking-[2px] text-white/90">
+                  {img.label}
+                </span>
+              </div>
+            )}
+          </>
+        );
+
+        const classes = `group relative block overflow-hidden bg-[var(--color-surface)] ${aspectClass(img.span)} ${cellClass(img.span)}`;
+
+        if (img.href) {
+          return (
+            <Link
+              key={`${img.url}-${i}`}
+              href={img.href}
+              className={`${classes} focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-heading)]`}
+            >
+              {inner}
+            </Link>
+          );
+        }
+
+        return (
+          <div key={`${img.url}-${i}`} className={classes}>
+            {inner}
+          </div>
+        );
+      })}
+    </div>
+  );
+}

+ 49 - 0
src/components/Header.tsx

@@ -0,0 +1,49 @@
+"use client";
+import { NavLinks } from "./NavLinks";
+import { ThemeToggle } from "./ThemeToggle";
+import { Logo } from "./Logo";
+import { Menu, X } from "lucide-react";
+import { useState } from "react";
+
+export function Header() {
+  const [mobileOpen, setMobileOpen] = useState(false);
+
+  return (
+    <header className="sticky top-0 z-40 border-b border-[var(--color-border)] bg-[var(--color-surface)]/90 backdrop-blur-md supports-[backdrop-filter]:bg-[var(--color-surface)]/75">
+      <div className="container-xl">
+        <div className="flex h-16 items-center justify-between">
+          <Logo size={26} withText />
+
+          <nav className="hidden md:flex items-center gap-8 text-sm">
+            <NavLinks />
+            <ThemeToggle />
+          </nav>
+
+          <button
+            onClick={() => setMobileOpen(!mobileOpen)}
+            className="p-2 md:hidden"
+            aria-label="Toggle menu"
+            type="button"
+          >
+            {mobileOpen ? (
+              <X className="h-5 w-5" />
+            ) : (
+              <Menu className="h-5 w-5" />
+            )}
+          </button>
+        </div>
+
+        {mobileOpen && (
+          <nav className="border-t border-[var(--color-border)] py-6 md:hidden">
+            <div className="flex flex-col gap-5 text-base">
+              <NavLinks mobile />
+              <div className="pt-2 border-t border-[var(--color-border)]">
+                <ThemeToggle />
+              </div>
+            </div>
+          </nav>
+        )}
+      </div>
+    </header>
+  );
+}

+ 33 - 0
src/components/Logo.test.tsx

@@ -0,0 +1,33 @@
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it } from "vitest";
+import { Logo } from "./Logo";
+
+describe("Logo", () => {
+  it("renders an image with alt text", () => {
+    render(<Logo />);
+    const img = screen.getByAltText("Jenado Unlimited");
+    expect(img).toBeInTheDocument();
+  });
+
+  it("wraps in a link by default", () => {
+    render(<Logo />);
+    const link = screen.getByRole("link", { name: "Jenado Unlimited" });
+    expect(link).toHaveAttribute("href", "/");
+  });
+
+  it("does not wrap in a link when link=false", () => {
+    render(<Logo link={false} />);
+    // There should be no link wrapping the logo
+    const links = screen.queryAllByRole("link");
+    // Filter to those that would contain our logo image
+    const logoLinks = links.filter(
+      (l) => l.getAttribute("aria-label") === "Jenado Unlimited",
+    );
+    expect(logoLinks.length).toBe(0);
+  });
+
+  it("shows text when withText is true", () => {
+    render(<Logo withText />);
+    expect(screen.getByText("Jenado Unlimited")).toBeInTheDocument();
+  });
+});

+ 51 - 0
src/components/Logo.tsx

@@ -0,0 +1,51 @@
+import Image from "next/image";
+import Link from "next/link";
+
+interface LogoProps {
+  /** Size of the logo icon in pixels (default: 28 for nav, 64 for home) */
+  size?: number;
+  /** Whether to show the "Jenado Unlimited" text next to the icon (default: false) */
+  withText?: boolean;
+  /** Additional CSS classes */
+  className?: string;
+  /** Whether to wrap in a Link to home (default: true) */
+  link?: boolean;
+}
+
+export function Logo({
+  size = 28,
+  withText = false,
+  className = "",
+  link = true,
+}: LogoProps) {
+  const height = Math.round(size * (1077 / 939));
+
+  const content = (
+    <span className={`inline-flex items-center gap-3 ${className}`}>
+      <span className="logo block" style={{ width: size, height }}>
+        <Image
+          src="/logo.svg"
+          alt="Jenado Unlimited"
+          width={size}
+          height={height}
+          className="h-full w-full object-contain"
+          unoptimized
+        />
+      </span>
+      {withText && (
+        <span className="text-lg font-medium tracking-[-0.01em] text-[var(--color-heading)]">
+          Jenado Unlimited
+        </span>
+      )}
+    </span>
+  );
+
+  if (link) {
+    return (
+      <Link href="/" aria-label="Jenado Unlimited">
+        {content}
+      </Link>
+    );
+  }
+  return content;
+}

+ 29 - 0
src/components/NavLinks.tsx

@@ -0,0 +1,29 @@
+import Link from "next/link";
+
+interface NavLinksProps {
+  mobile?: boolean;
+}
+
+const links = [
+  { href: "/", label: "Home" },
+  { href: "/offerings", label: "Offerings" },
+  { href: "/about", label: "About" },
+  { href: "/gallery", label: "Gallery" },
+  { href: "/contact", label: "Contact" },
+];
+
+export function NavLinks({ mobile }: NavLinksProps) {
+  const className = mobile
+    ? "block py-2 text-base font-medium transition-colors hover:text-[var(--color-accent)]"
+    : "text-sm font-medium transition-colors hover:text-[var(--color-accent)]";
+
+  return (
+    <>
+      {links.map((link) => (
+        <Link key={link.href} href={link.href} className={className}>
+          {link.label}
+        </Link>
+      ))}
+    </>
+  );
+}

+ 83 - 0
src/components/ParallaxBand.tsx

@@ -0,0 +1,83 @@
+"use client";
+
+import Image from "next/image";
+import { useEffect, useRef, useState, type ReactNode } from "react";
+
+/** Mid-page parallax strip — shorter than a full hero, great for quotes / CTAs */
+export function ParallaxBand({
+  image,
+  alt,
+  children,
+  className = "",
+}: {
+  image: string;
+  alt: string;
+  children: ReactNode;
+  className?: string;
+}) {
+  const sectionRef = useRef<HTMLElement>(null);
+  const bgRef = useRef<HTMLDivElement>(null);
+  const [reduceMotion, setReduceMotion] = useState(false);
+
+  useEffect(() => {
+    const media = window.matchMedia("(prefers-reduced-motion: reduce)");
+    const update = () => setReduceMotion(media.matches);
+    update();
+    media.addEventListener("change", update);
+    return () => media.removeEventListener("change", update);
+  }, []);
+
+  useEffect(() => {
+    if (reduceMotion) return;
+
+    let frame = 0;
+    const bg = bgRef.current;
+    const section = sectionRef.current;
+    if (!bg || !section) return;
+
+    const onScroll = () => {
+      cancelAnimationFrame(frame);
+      frame = requestAnimationFrame(() => {
+        const rect = section.getBoundingClientRect();
+        const viewH = window.innerHeight || 1;
+        if (rect.bottom < 0 || rect.top > viewH) return;
+        const offset = rect.top * -0.28;
+        bg.style.transform = `translate3d(0, ${offset}px, 0)`;
+      });
+    };
+
+    onScroll();
+    window.addEventListener("scroll", onScroll, { passive: true });
+    window.addEventListener("resize", onScroll, { passive: true });
+    return () => {
+      cancelAnimationFrame(frame);
+      window.removeEventListener("scroll", onScroll);
+      window.removeEventListener("resize", onScroll);
+    };
+  }, [reduceMotion]);
+
+  return (
+    <section
+      ref={sectionRef}
+      className={`relative isolate overflow-hidden py-24 md:py-32 ${className}`}
+    >
+      <div
+        ref={bgRef}
+        className="pointer-events-none absolute inset-x-0 -top-[20%] h-[140%] w-full will-change-transform"
+        aria-hidden
+      >
+        <Image
+          src={image}
+          alt={alt}
+          fill
+          sizes="100vw"
+          className="object-cover object-center"
+        />
+      </div>
+      <div className="absolute inset-0 bg-black/60" aria-hidden />
+      <div className="container-xl relative z-10 text-center text-white">
+        {children}
+      </div>
+    </section>
+  );
+}

+ 118 - 0
src/components/ParallaxHero.tsx

@@ -0,0 +1,118 @@
+"use client";
+
+import Image from "next/image";
+import { useEffect, useRef, useState, type ReactNode } from "react";
+
+type HeroSize = "sm" | "md" | "lg" | "full";
+
+const sizeClasses: Record<HeroSize, string> = {
+  sm: "min-h-[42vh] md:min-h-[48vh]",
+  md: "min-h-[52vh] md:min-h-[58vh]",
+  lg: "min-h-[70vh] md:min-h-[78vh]",
+  full: "min-h-[88vh] md:min-h-[92vh]",
+};
+
+export function ParallaxHero({
+  image,
+  alt,
+  children,
+  size = "md",
+  priority = false,
+  overlayClassName = "bg-gradient-to-b from-black/55 via-black/45 to-black/70",
+  contentClassName = "",
+  align = "center",
+}: {
+  image: string;
+  alt: string;
+  children: ReactNode;
+  size?: HeroSize;
+  priority?: boolean;
+  overlayClassName?: string;
+  contentClassName?: string;
+  align?: "center" | "start" | "end";
+}) {
+  const sectionRef = useRef<HTMLElement>(null);
+  const bgRef = useRef<HTMLDivElement>(null);
+  const [reduceMotion, setReduceMotion] = useState(false);
+
+  useEffect(() => {
+    const media = window.matchMedia("(prefers-reduced-motion: reduce)");
+    const update = () => setReduceMotion(media.matches);
+    update();
+    media.addEventListener("change", update);
+    return () => media.removeEventListener("change", update);
+  }, []);
+
+  useEffect(() => {
+    if (reduceMotion) return;
+
+    let frame = 0;
+    const bg = bgRef.current;
+    const section = sectionRef.current;
+    if (!bg || !section) return;
+
+    const onScroll = () => {
+      cancelAnimationFrame(frame);
+      frame = requestAnimationFrame(() => {
+        const rect = section.getBoundingClientRect();
+        const viewH = window.innerHeight || 1;
+        // Only transform while near the viewport
+        if (rect.bottom < 0 || rect.top > viewH) return;
+        const offset = rect.top * -0.35;
+        bg.style.transform = `translate3d(0, ${offset}px, 0)`;
+      });
+    };
+
+    onScroll();
+    window.addEventListener("scroll", onScroll, { passive: true });
+    window.addEventListener("resize", onScroll, { passive: true });
+    return () => {
+      cancelAnimationFrame(frame);
+      window.removeEventListener("scroll", onScroll);
+      window.removeEventListener("resize", onScroll);
+    };
+  }, [reduceMotion]);
+
+  const alignClass =
+    align === "start"
+      ? "items-start text-left"
+      : align === "end"
+        ? "items-end text-right"
+        : "items-center text-center";
+
+  return (
+    <section
+      ref={sectionRef}
+      className={`relative isolate flex overflow-hidden ${sizeClasses[size]}`}
+    >
+      <div
+        ref={bgRef}
+        className="pointer-events-none absolute inset-x-0 -top-[18%] h-[136%] w-full will-change-transform"
+        aria-hidden
+      >
+        <Image
+          src={image}
+          alt={alt}
+          fill
+          priority={priority}
+          sizes="100vw"
+          className="object-cover object-center"
+        />
+      </div>
+
+      <div className={`absolute inset-0 ${overlayClassName}`} aria-hidden />
+
+      {/* Soft vignette for readability */}
+      <div
+        className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,transparent_0%,rgba(0,0,0,0.35)_100%)]"
+        aria-hidden
+      />
+
+      <div
+        className={`container-xl relative z-10 flex w-full flex-col justify-center py-16 md:py-24 ${alignClass} ${contentClassName}`}
+      >
+        {children}
+      </div>
+    </section>
+  );
+}

+ 19 - 0
src/components/PillarStrip.test.tsx

@@ -0,0 +1,19 @@
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it } from "vitest";
+import { PillarStrip } from "./PillarStrip";
+
+describe("PillarStrip", () => {
+  it("renders the three pillars", () => {
+    render(<PillarStrip />);
+    expect(screen.getByText("Mind")).toBeInTheDocument();
+    expect(screen.getByText("Body")).toBeInTheDocument();
+    expect(screen.getByText("Soul")).toBeInTheDocument();
+  });
+
+  it("shows descriptive blurbs", () => {
+    render(<PillarStrip />);
+    expect(screen.getByText("Focus & recreation")).toBeInTheDocument();
+    expect(screen.getByText("Strength & vitality")).toBeInTheDocument();
+    expect(screen.getByText("Craft & nourishment")).toBeInTheDocument();
+  });
+});

+ 33 - 0
src/components/PillarStrip.tsx

@@ -0,0 +1,33 @@
+const pillars = [
+  { key: "mind", label: "Mind", blurb: "Focus & recreation" },
+  { key: "body", label: "Body", blurb: "Strength & vitality" },
+  { key: "soul", label: "Soul", blurb: "Craft & nourishment" },
+];
+
+export function PillarStrip() {
+  return (
+    <div className="border-y border-[var(--color-border)] bg-[var(--color-surface)] py-8 md:py-10">
+      <div className="container-xl">
+        <div className="grid grid-cols-1 gap-8 text-center sm:grid-cols-3 sm:gap-4">
+          {pillars.map((pillar, i) => (
+            <div
+              key={pillar.key}
+              className={`flex flex-col items-center gap-2 ${
+                i < pillars.length - 1
+                  ? "sm:border-r sm:border-[var(--color-border)]"
+                  : ""
+              }`}
+            >
+              <span className="text-[11px] font-medium uppercase tracking-[0.3em] text-[var(--color-heading)]">
+                {pillar.label}
+              </span>
+              <span className="text-sm text-[var(--color-text-muted)]">
+                {pillar.blurb}
+              </span>
+            </div>
+          ))}
+        </div>
+      </div>
+    </div>
+  );
+}

+ 9 - 0
src/components/SkipToContent.tsx

@@ -0,0 +1,9 @@
+"use client";
+
+export function SkipToContent() {
+  return (
+    <a href="#main-content" className="skip-to-content">
+      Skip to main content
+    </a>
+  );
+}

+ 59 - 0
src/components/ThemeToggle.tsx

@@ -0,0 +1,59 @@
+"use client";
+
+import { Laptop, Moon, Sun } from "lucide-react";
+import { useEffect, useMemo, useState } from "react";
+
+type ThemeVal = "light" | "dark" | "system";
+const themes: ThemeVal[] = ["light", "dark", "system"];
+
+export function ThemeToggle() {
+  const initialTheme = useMemo<ThemeVal>(() => {
+    if (typeof window === "undefined") return "system";
+    const stored = window.localStorage.getItem("theme") as ThemeVal | null;
+    return stored && themes.includes(stored) ? stored : "system";
+  }, []);
+
+  const [theme, setTheme] = useState<ThemeVal>(initialTheme);
+
+  // Persist to localStorage
+  useEffect(() => {
+    window.localStorage.setItem("theme", theme);
+  }, [theme]);
+
+  // Apply theme to DOM
+  useEffect(() => {
+    const root = document.documentElement;
+    root.classList.remove("light", "dark");
+    if (theme === "system") {
+      root.classList.add(
+        window.matchMedia("(prefers-color-scheme: dark)").matches
+          ? "dark"
+          : "light",
+      );
+    } else {
+      root.classList.add(theme);
+    }
+  }, [theme]);
+
+  const handleToggle = () => {
+    const currentIndex = themes.indexOf(theme);
+    const nextIndex = (currentIndex + 1) % themes.length;
+    setTheme(themes[nextIndex]);
+  };
+
+  const Icon = theme === "light" ? Sun : theme === "dark" ? Moon : Laptop;
+
+  return (
+    <button
+      onClick={handleToggle}
+      className="inline-flex items-center gap-2 text-sm text-[var(--color-text-muted)] hover:text-[var(--color-heading)] transition-colors"
+      aria-label={`Current theme: ${theme}`}
+      type="button"
+    >
+      <Icon className="h-4 w-4" />
+      <span className="hidden sm:inline uppercase tracking-[1px] text-xs">
+        {theme}
+      </span>
+    </button>
+  );
+}

+ 39 - 0
src/components/VerticalCard.test.tsx

@@ -0,0 +1,39 @@
+import type { Vertical } from "@/types";
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it } from "vitest";
+import { VerticalCard } from "./VerticalCard";
+
+const mockVertical: Vertical = {
+  slug: "honey-bees",
+  title: "Honey Bees",
+  summary: "Fresh local honey",
+  image: "/images/honey-bees.jpg",
+  description: "Details here.",
+  pillars: ["body"],
+  status: "active",
+};
+
+describe("VerticalCard", () => {
+  it("renders title and summary in grid variant (default)", () => {
+    render(<VerticalCard vertical={mockVertical} />);
+    expect(screen.getByText("Honey Bees")).toBeInTheDocument();
+    expect(screen.getByText("Fresh local honey")).toBeInTheDocument();
+  });
+
+  it("renders status badge text", () => {
+    render(<VerticalCard vertical={mockVertical} />);
+    // status is rendered as "active" -> "active"
+    expect(screen.getByText("active")).toBeInTheDocument();
+  });
+
+  it("links to the correct offering page", () => {
+    render(<VerticalCard vertical={mockVertical} />);
+    const link = screen.getByRole("link");
+    expect(link).toHaveAttribute("href", "/offerings/honey-bees");
+  });
+
+  it("renders feature variant without crashing", () => {
+    render(<VerticalCard vertical={mockVertical} variant="feature" />);
+    expect(screen.getByText("Honey Bees")).toBeInTheDocument();
+  });
+});

+ 111 - 0
src/components/VerticalCard.tsx

@@ -0,0 +1,111 @@
+import type { Vertical } from "@/types";
+import Image from "next/image";
+import Link from "next/link";
+
+export function VerticalCard({
+  vertical,
+  variant = "grid",
+  reverse = false,
+}: {
+  vertical: Vertical;
+  /** grid = compact card; feature = wide image + copy row */
+  variant?: "grid" | "feature";
+  /** Flip image/copy order on feature layout */
+  reverse?: boolean;
+}) {
+  if (variant === "feature") {
+    return (
+      <Link
+        href={`/offerings/${vertical.slug}`}
+        className="group grid items-center gap-8 border-b border-[var(--color-border)] pb-12 transition-colors last:border-b-0 md:grid-cols-2 md:gap-12 md:pb-16"
+      >
+        <div
+          className={`relative aspect-[16/10] overflow-hidden bg-[var(--color-surface)] ${
+            reverse ? "md:order-2" : ""
+          }`}
+        >
+          <Image
+            src={vertical.image}
+            alt={vertical.title}
+            fill
+            sizes="(max-width: 768px) 100vw, 50vw"
+            className="object-cover transition-transform duration-700 ease-out group-hover:scale-105"
+          />
+          <div className="absolute inset-0 bg-black/0 transition-colors duration-500 group-hover:bg-black/10" />
+        </div>
+        <div className={`md:py-4 ${reverse ? "md:order-1 md:text-right md:ml-auto" : ""}`}>
+          <div
+            className={`mb-4 flex flex-wrap items-center gap-3 ${
+              reverse ? "md:justify-end" : ""
+            }`}
+          >
+            <span className="text-[10px] font-medium uppercase tracking-[2px] text-[var(--color-text-muted)]">
+              {vertical.status.replace("-", " ")}
+            </span>
+            {vertical.pillars?.length > 0 && (
+              <span className="text-[10px] font-medium uppercase tracking-[2px] text-[var(--color-text-muted)]">
+                · {vertical.pillars.join(" · ")}
+              </span>
+            )}
+          </div>
+          <h3 className="mb-3 text-2xl font-semibold tracking-[-0.02em] text-[var(--color-heading)] transition-colors group-hover:text-[var(--color-accent)] md:text-3xl">
+            {vertical.title}
+          </h3>
+          <p
+            className={`mb-6 max-w-md text-[15px] leading-relaxed text-[var(--color-text-muted)] md:text-base ${
+              reverse ? "md:ml-auto" : ""
+            }`}
+          >
+            {vertical.summary}
+          </p>
+          <span
+            className={`inline-flex items-center gap-2 text-sm font-medium tracking-wide text-[var(--color-heading)] ${
+              reverse ? "md:flex-row-reverse" : ""
+            }`}
+          >
+            Explore
+            <span
+              aria-hidden
+              className={`transition-transform duration-300 ${
+                reverse
+                  ? "group-hover:-translate-x-1"
+                  : "group-hover:translate-x-1"
+              }`}
+            >
+              →
+            </span>
+          </span>
+        </div>
+      </Link>
+    );
+  }
+
+  return (
+    <Link
+      href={`/offerings/${vertical.slug}`}
+      className="group flex h-full flex-col overflow-hidden border border-[var(--color-border)] bg-[var(--color-surface)] transition-shadow duration-300 hover:shadow-[0_20px_50px_-24px_rgba(0,0,0,0.35)] dark:hover:shadow-[0_20px_50px_-24px_rgba(0,0,0,0.8)]"
+    >
+      <div className="relative aspect-[16/11] overflow-hidden">
+        <Image
+          src={vertical.image}
+          alt={vertical.title}
+          fill
+          sizes="(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw"
+          className="object-cover transition-transform duration-700 ease-out group-hover:scale-105"
+        />
+        <div className="absolute inset-0 bg-gradient-to-t from-black/40 via-transparent to-transparent opacity-60" />
+        <span className="absolute bottom-3 left-3 text-[10px] font-medium uppercase tracking-[2px] text-white/90">
+          {vertical.status.replace("-", " ")}
+        </span>
+      </div>
+      <div className="flex flex-1 flex-col p-5 md:p-6">
+        <h3 className="mb-2 text-xl font-medium tracking-[-0.01em] text-[var(--color-heading)] transition-colors group-hover:text-[var(--color-accent)]">
+          {vertical.title}
+        </h3>
+        <p className="text-[15px] leading-relaxed text-[var(--color-text-muted)]">
+          {vertical.summary}
+        </p>
+      </div>
+    </Link>
+  );
+}

+ 71 - 0
src/content/pages/about.ts

@@ -0,0 +1,71 @@
+import type { PageContent } from "./types";
+
+export const about: PageContent = {
+  slug: "about",
+  title: "About",
+  heroImage: "/images/hero-about.jpg",
+  heroAlt:
+    "Sunlit workshop kitchen with honey jars, artisan bread, sketchbook, and coffee on a rustic wooden table",
+  heroOverlay: "bg-gradient-to-r from-black/80 via-black/55 to-black/30",
+  heroAlign: "start",
+  heroSize: "md",
+  heroPriority: true,
+  heroContentClass: "!items-start !text-left",
+  heroLabel: "Our Story",
+  heroDescription:
+    "Jenado Unlimited is a collection of practices that support a fuller life — rooted in connection, craft, and care.",
+  sections: [
+    {
+      title: "Pillars",
+      description:
+        "Three dimensions of a well-lived life, each with its own practices and offerings.",
+      items: [
+        {
+          title: "Clarity & play",
+          description:
+            "Recreation apps and reflective experiences designed for focus without friction — digital tools that respect your attention instead of exploiting it.",
+          label: "Mind",
+        },
+        {
+          title: "Strength & vitality",
+          description:
+            "Personal training grounded in sustainable progress, plus local honey and everyday nourishment that support how you move through the world.",
+          label: "Body",
+        },
+        {
+          title: "Craft & nourishment",
+          description:
+            "Sourdough, seasonal food, laser engraving, and fabrication — tangible work that carries care from our hands to your table, wall, or ritual.",
+          label: "Soul",
+        },
+      ],
+    },
+    {
+      title: "Values",
+      description:
+        "The principles that guide every offering, from the loaf to the laser.",
+      items: [
+        {
+          title: "Quality",
+          description:
+            "We choose ingredients, materials, and methods that hold up to scrutiny — whether that is flour for the loaf, a training cue that protects the joints, or a clean laser path on wood.",
+        },
+        {
+          title: "Community",
+          description:
+            "Rooted in connection. We favor local relationships, personal conversation over anonymous transactions, and work that makes sense in the places we actually live.",
+        },
+        {
+          title: "Craft",
+          description:
+            "Pride in the details. Process matters as much as product — slow fermentation, careful programming, patient design iterations in the workshop.",
+        },
+        {
+          title: "Inclusivity",
+          description:
+            "Mind, body, and soul for everyone who walks through our door. Beginners and lifelong practitioners are equally welcome; we meet people where they are.",
+        },
+      ],
+    },
+  ],
+};

+ 52 - 0
src/content/pages/contact.ts

@@ -0,0 +1,52 @@
+import type { PageContent } from "./types";
+
+export const contact: PageContent = {
+  slug: "contact",
+  title: "Contact",
+  heroImage: "/images/hero-contact.jpg",
+  heroAlt:
+    "Open notebook with pen, honey dipper, and coffee cup on a wooden desk, suggesting conversation and planning",
+  heroOverlay: "bg-gradient-to-r from-black/80 via-black/55 to-black/30",
+  heroAlign: "start",
+  heroSize: "md",
+  heroPriority: true,
+  heroContentClass: "!items-start !text-left",
+  heroLabel: "Get in Touch",
+  heroDescription:
+    "Have a question, a project in mind, or just want to say hello? We'd love to hear from you.",
+  sections: [
+    {
+      title: "Topics",
+      description: "Pick the topic that fits best when reaching out.",
+      items: [
+        {
+          title: "Honey & bee products",
+          description: "Availability, gift jars, bulk, or allergy questions.",
+        },
+        {
+          title: "Personal training",
+          description:
+            "Goals, schedule, experience level, and preferred format.",
+        },
+        {
+          title: "Sourdough & food",
+          description: "Loaves, seasonal menus, events, or dietary notes.",
+        },
+        {
+          title: "Custom craft",
+          description:
+            "Laser engraving, 3D printing ideas, materials, and timelines.",
+        },
+        {
+          title: "Apps & partnerships",
+          description: "Recreation apps, collaborations, or press inquiries.",
+        },
+        {
+          title: "Something else",
+          description:
+            "General questions are always welcome — no perfect pitch required.",
+        },
+      ],
+    },
+  ],
+};

+ 40 - 0
src/content/pages/gallery.ts

@@ -0,0 +1,40 @@
+import type { PageContent } from "./types";
+
+export const gallery: PageContent = {
+  slug: "gallery",
+  title: "Gallery",
+  heroImage: "/images/hero-gallery.jpg",
+  heroAlt: "Abstract textures of honey, wood grain, engraved metal, and fabric",
+  heroOverlay: "bg-gradient-to-r from-black/80 via-black/55 to-black/30",
+  heroAlign: "start",
+  heroSize: "md",
+  heroPriority: true,
+  heroContentClass: "!items-start !text-left",
+  heroLabel: "Visual Stories",
+  heroDescription:
+    "A curated collection of frames from across our verticals — not a catalog of every SKU, but a sense of the rooms we work in, the textures we handle, and the standards we hold.",
+  sections: [
+    {
+      title: "Themes",
+      description:
+        "Each frame belongs to a theme that reflects how we think about our work.",
+      items: [
+        {
+          title: "Product",
+          description:
+            "Close-ups of the finished work — the loaf, the engraved piece, the training plan — shot with care and clarity.",
+        },
+        {
+          title: "Process",
+          description:
+            "The in-between moments: dough rising, laser cooling, code compiling, a training session mid-set.",
+        },
+        {
+          title: "Atmosphere",
+          description:
+            "Light on wood, a torn-open crust, metal after the laser cools — the mood of the spaces where the work happens.",
+        },
+      ],
+    },
+  ],
+};

+ 16 - 0
src/content/pages/home.ts

@@ -0,0 +1,16 @@
+import type { PageContent } from "./types";
+
+export const home: PageContent = {
+  slug: "home",
+  title: "Jenado Unlimited",
+  heroImage: "/images/hero-home.jpg",
+  heroAlt:
+    "Honey, artisan bread, and candle on a wooden table overlooking a wildflower meadow at golden hour",
+  heroOverlay: "bg-gradient-to-b from-black/50 via-black/35 to-black/75",
+  heroAlign: "center",
+  heroSize: "full",
+  heroPriority: true,
+  heroLabel: "Mind · Body · Soul",
+  heroDescription:
+    "Craft for mind, body, and soul — local honey, training, sourdough, and more.",
+};

+ 32 - 0
src/content/pages/index.ts

@@ -0,0 +1,32 @@
+export type { ItemContent, PageContent, SectionContent } from "./types";
+
+export { about } from "./about";
+export { contact } from "./contact";
+export { gallery } from "./gallery";
+export { home } from "./home";
+export { offerings } from "./offerings";
+export { privacy } from "./privacy";
+export { terms } from "./terms";
+
+import { about } from "./about";
+import { contact } from "./contact";
+import { gallery } from "./gallery";
+import { home } from "./home";
+import { offerings } from "./offerings";
+import { privacy } from "./privacy";
+import { terms } from "./terms";
+import type { PageContent } from "./types";
+
+const pages: Record<string, PageContent> = {
+  home,
+  about,
+  contact,
+  gallery,
+  offerings,
+  privacy,
+  terms,
+};
+
+export function getPageContent(slug: string): PageContent | undefined {
+  return pages[slug];
+}

+ 44 - 0
src/content/pages/offerings.ts

@@ -0,0 +1,44 @@
+import type { PageContent } from "./types";
+
+export const offerings: PageContent = {
+  slug: "offerings",
+  title: "Offerings",
+  heroImage: "/images/hero-offerings.jpg",
+  heroAlt:
+    "Artisan flatlay of honeycomb, dumbbell, sourdough, produce, laser-cut wood, and 3D printed object",
+  heroOverlay: "bg-gradient-to-r from-black/75 via-black/55 to-black/35",
+  heroAlign: "start",
+  heroSize: "md",
+  heroPriority: true,
+  heroContentClass: "!items-start !text-left",
+  heroLabel: "Mind · Body · Soul",
+  heroDescription:
+    "Seven verticals. One standard of care. Explore products and services spanning craft, wellness, food, and digital play — each shaped with intention.",
+  sections: [
+    {
+      title: "How we organize our work",
+      description:
+        "Jenado Unlimited is not a single product line — it is a collection of practices that support a fuller life. Whether you are looking for a loaf for the table, a training plan that fits your season, or a custom piece from the workshop, every offering starts with the same questions: Is it honest? Is it well made? Does it serve mind, body, or soul?",
+      items: [
+        {
+          title: "Mind",
+          description:
+            "Tools and experiences that invite focus, play, and reflection — including recreation apps built for mindful downtime.",
+          key: "mind",
+        },
+        {
+          title: "Body",
+          description:
+            "Strength, vitality, and daily fuel — from personal training to local honey that supports a well-lived life.",
+          key: "body",
+        },
+        {
+          title: "Soul",
+          description:
+            "Craft and nourishment with heart — sourdough, seasonal food, laser engraving, and made objects from the workshop.",
+          key: "soul",
+        },
+      ],
+    },
+  ],
+};

+ 18 - 0
src/content/pages/privacy.ts

@@ -0,0 +1,18 @@
+import type { PageContent } from "./types";
+
+export const privacy: PageContent = {
+  slug: "privacy",
+  title: "Privacy Policy",
+  heroImage: "/images/hero-privacy.jpg",
+  heroAlt:
+    "Layered translucent glass panes with soft light, suggesting clarity and protection",
+  heroOverlay: "bg-gradient-to-r from-black/85 via-black/60 to-black/35",
+  heroAlign: "start",
+  heroSize: "sm",
+  heroPriority: true,
+  heroContentClass: "!items-start !text-left",
+  heroLabel: "Legal",
+  heroDescription:
+    "How we collect, use, and protect your information when you visit our website.",
+  lastUpdated: "August 12, 2026",
+};

+ 17 - 0
src/content/pages/terms.ts

@@ -0,0 +1,17 @@
+import type { PageContent } from "./types";
+
+export const terms: PageContent = {
+  slug: "terms",
+  title: "Terms of Service",
+  heroImage: "/images/hero-terms.jpg",
+  heroAlt: "Leather-bound book with brass paperweight on a warm wooden desk",
+  heroOverlay: "bg-gradient-to-r from-black/85 via-black/60 to-black/35",
+  heroAlign: "start",
+  heroSize: "sm",
+  heroPriority: true,
+  heroContentClass: "!items-start !text-left",
+  heroLabel: "Legal",
+  heroDescription:
+    "The rules for using our website and related online content.",
+  lastUpdated: "August 12, 2026",
+};

+ 54 - 0
src/content/pages/types.ts

@@ -0,0 +1,54 @@
+export interface PageContent {
+  /** Unique page identifier */
+  slug: string;
+  /** Page title */
+  title: string;
+  /** Hero image path */
+  heroImage: string;
+  /** Hero image alt text */
+  heroAlt: string;
+  /** Hero overlay gradient class */
+  heroOverlay?: string;
+  /** Hero alignment */
+  heroAlign?: "start" | "end" | "center";
+  /** Hero content alignment */
+  heroContentClass?: string;
+  /** Hero size */
+  heroSize?: "sm" | "md" | "full";
+  /** Hero priority */
+  heroPriority?: boolean;
+  /** Section label shown above title in hero */
+  heroLabel?: string;
+  /** Hero description */
+  heroDescription?: string;
+  /** Sub-hero section content */
+  sections?: SectionContent[];
+  /** Last updated date for legal pages */
+  lastUpdated?: string;
+}
+
+export interface SectionContent {
+  /** Section title */
+  title: string;
+  /** Section description */
+  description: string;
+  /** Section items (for lists, cards, etc.) */
+  items?: ItemContent[];
+  /** Section ID for anchor links */
+  id?: string;
+}
+
+export interface ItemContent {
+  /** Item title */
+  title: string;
+  /** Item description */
+  description: string;
+  /** Item key (for grid keys) */
+  key?: string;
+  /** Item URL (for links) */
+  url?: string;
+  /** Item label */
+  label?: string;
+  /** Item span (for grid spans) */
+  span?: string;
+}

+ 13 - 0
src/content/verticals/3d-printing.ts

@@ -0,0 +1,13 @@
+import type { Vertical } from "@/types";
+
+export const threeDPrinting: Vertical = {
+  slug: "3d-printing",
+  title: "3D Printing",
+  summary:
+    "Custom printed objects and prototypes — form exploration from idea to held-in-hand piece.",
+  image: "/images/3d-printing.jpg",
+  description:
+    "Custom 3D printing services for prototypes, models, and made objects. Whether you need a functional prototype, a small-run part, or a geometric piece that only exists digitally until printed, we help bridge design and physical form. This vertical is coming soon — inquire to join the waitlist or discuss future projects.",
+  pillars: ["soul"],
+  status: "coming-soon",
+};

+ 7 - 0
src/content/verticals/all.ts

@@ -0,0 +1,7 @@
+export * from "./honey-bees";
+export * from "./personal-training";
+export * from "./sourdough";
+export * from "./farm-to-table";
+export * from "./recreation-apps";
+export * from "./laser-engraving";
+export * from "./3d-printing";

+ 13 - 0
src/content/verticals/farm-to-table.ts

@@ -0,0 +1,13 @@
+import type { Vertical } from "@/types";
+
+export const farmToTable: Vertical = {
+  slug: "farm-to-table",
+  title: "Farm-to-Table",
+  summary:
+    "Seasonal dining and local ingredients — menus that follow the land, not a warehouse calendar.",
+  image: "/images/farm-to-table.jpg",
+  description:
+    "Farm-to-table dining experiences featuring locally sourced, seasonal ingredients. We favor short supply chains, honest flavors, and meals that feel connected to place. Soft-launch offerings may include pop-ups, private tables, or limited seasonal menus — ask us what is next on the calendar.",
+  pillars: ["soul"],
+  status: "soft-launch",
+};

+ 15 - 0
src/content/verticals/honey-bees.ts

@@ -0,0 +1,15 @@
+import type { Vertical } from "@/types";
+
+export const honeyBees: Vertical = {
+  slug: "honey-bees",
+  title: "Honey Bees",
+  summary:
+    "Small-batch local honey and bee-friendly products with real hive character — golden, seasonal, and never anonymous.",
+  image: "/images/honey-bees.jpg",
+  description:
+    "Our honey bees produce the finest local honey, beeswax products, and pollinator-friendly experiences. Every jar reflects the forage of the season and the care of the hive — ideal for the table, gifting, or anyone who wants sweetness with a story. Please note potential bee-product allergies before enjoying.",
+  pillars: ["body"],
+  status: "active",
+  disclaimerKey: "allergy",
+  gallery: [],
+};

+ 13 - 0
src/content/verticals/laser-engraving.ts

@@ -0,0 +1,13 @@
+import type { Vertical } from "@/types";
+
+export const laserEngraving: Vertical = {
+  slug: "laser-engraving",
+  title: "Laser Engraving",
+  summary:
+    "Precision custom engraving for gifts, signage, and pieces that deserve a permanent mark.",
+  image: "/images/laser-engraving.jpg",
+  description:
+    "Precision laser engraving services for custom gifts, signage, and personalized creations. Bring a monogram, logo, map, date, or idea — we help translate it cleanly onto wood, and other suitable materials with crisp detail and careful finishing. Ideal for events, branding, and keepsakes.",
+  pillars: ["soul"],
+  status: "active",
+};

+ 13 - 0
src/content/verticals/personal-training.ts

@@ -0,0 +1,13 @@
+import type { Vertical } from "@/types";
+
+export const personalTraining: Vertical = {
+  slug: "personal-training",
+  title: "Personal Training",
+  summary:
+    "Coaching for real schedules and real bodies — sustainable strength, mobility, and confidence at every level.",
+  image: "/images/personal-training.jpg",
+  description:
+    "Personalized fitness training programs designed to help you reach your health and wellness goals. We emphasize form, progression, and habits you can keep — whether you are returning to movement, training for performance, or simply want to feel stronger in daily life. Sessions are collaborative, clear, and built around you.",
+  pillars: ["body"],
+  status: "active",
+};

+ 13 - 0
src/content/verticals/recreation-apps.ts

@@ -0,0 +1,13 @@
+import type { Vertical } from "@/types";
+
+export const recreationApps: Vertical = {
+  slug: "recreation-apps",
+  title: "Recreation Apps",
+  summary:
+    "Digital experiences for mindful recreation — play, pause, and learn without the noise of endless feeds.",
+  image: "/images/recreation-apps.jpg",
+  description:
+    "Apps designed for mindful recreation, relaxation, and reflective learning. We build toward calm utility and genuine delight — tools that respect attention and support the mind pillar of Jenado Unlimited. Reach out if you want early access, feedback loops, or partnership conversations.",
+  pillars: ["mind"],
+  status: "active",
+};

+ 13 - 0
src/content/verticals/sourdough.ts

@@ -0,0 +1,13 @@
+import type { Vertical } from "@/types";
+
+export const sourdough: Vertical = {
+  slug: "sourdough",
+  title: "Sourdough Breads",
+  summary:
+    "Naturally leavened loaves with open crumb and deep flavor — baked in small batches the long way.",
+  image: "/images/sourdough.jpg",
+  description:
+    "Handcrafted sourdough breads using traditional methods and carefully chosen ingredients. Long fermentation, patient shaping, and a proper bake yield crust and character you can taste. Perfect for the everyday table, gatherings, or anyone who believes bread should still feel like craft.",
+  pillars: ["soul"],
+  status: "active",
+};

+ 103 - 0
src/lib/contact.test.ts

@@ -0,0 +1,103 @@
+import { describe, expect, it } from "vitest";
+import {
+  contactBodySchema,
+  contactSchema,
+  isHoneypotTriggered,
+  sanitizeHeaderValue,
+} from "./contact";
+
+describe("contact.ts utilities", () => {
+  describe("sanitizeHeaderValue", () => {
+    it("trims whitespace and removes newlines", () => {
+      expect(sanitizeHeaderValue("  hello\r\nworld  ")).toBe("hello world");
+    });
+
+    it("slices to 200 chars", () => {
+      const long = "a".repeat(300);
+      const result = sanitizeHeaderValue(long);
+      expect(result.length).toBe(200);
+    });
+  });
+
+  describe("isHoneypotTriggered", () => {
+    it("returns true if website is filled", () => {
+      expect(isHoneypotTriggered({ website: "spam.com" })).toBe(true);
+    });
+
+    it("returns true if company is filled", () => {
+      expect(isHoneypotTriggered({ company: "EvilCorp" })).toBe(true);
+    });
+
+    it("returns false for empty or whitespace", () => {
+      expect(isHoneypotTriggered({ website: "   ", company: "" })).toBe(false);
+      expect(isHoneypotTriggered({})).toBe(false);
+    });
+  });
+
+  describe("contactSchema", () => {
+    it("validates a minimal valid input", () => {
+      const result = contactSchema.safeParse({
+        name: "Jane Doe",
+        email: "jane@example.com",
+        message: "Hello there, this is a test message.",
+      });
+      expect(result.success).toBe(true);
+      if (result.success) {
+        expect(result.data.topic).toBe("general");
+        expect(result.data.phone).toBe("");
+      }
+    });
+
+    it("rejects short name", () => {
+      const result = contactSchema.safeParse({
+        name: "J",
+        email: "j@example.com",
+        message: "Valid message here.",
+      });
+      expect(result.success).toBe(false);
+    });
+
+    it("rejects invalid email", () => {
+      const result = contactSchema.safeParse({
+        name: "Jane",
+        email: "not-an-email",
+        message: "Valid message here.",
+      });
+      expect(result.success).toBe(false);
+    });
+
+    it("strips newlines from name", () => {
+      const result = contactSchema.safeParse({
+        name: "Jane\nDoe",
+        email: "jane@example.com",
+        message: "Hello there, this is long enough.",
+      });
+      expect(result.success).toBe(true);
+      if (result.success) {
+        expect(result.data.name).toBe("Jane Doe");
+      }
+    });
+
+    it("rejects short message", () => {
+      const result = contactSchema.safeParse({
+        name: "Jane",
+        email: "jane@example.com",
+        message: "short",
+      });
+      expect(result.success).toBe(false);
+    });
+  });
+
+  describe("contactBodySchema", () => {
+    it("accepts honeypot fields", () => {
+      const result = contactBodySchema.safeParse({
+        name: "Jane",
+        email: "jane@example.com",
+        message: "A sufficiently long message for the body schema.",
+        website: "",
+        company: "",
+      });
+      expect(result.success).toBe(true);
+    });
+  });
+});

+ 26 - 0
src/lib/contact.ts

@@ -0,0 +1,26 @@
+import { z } from "zod";
+
+export const contactSchema = z.object({
+  name: z.string().min(2).max(80).transform((v) => v.replace(/[\r\n]+/g, " ").trim()),
+  email: z.string().email().max(254),
+  topic: z.enum(["general", "honey-bees", "personal-training", "sourdough", "farm-to-table", "recreation-apps", "laser-engraving", "3d-printing"]).default("general"),
+  message: z.string().min(10).max(5000),
+  phone: z.string().optional().default(""),
+});
+
+export const contactBodySchema = contactSchema.extend({
+  website: z.string().optional().default(""),
+  company: z.string().optional().default(""),
+});
+
+export type ContactInput = z.infer<typeof contactSchema>;
+export type ContactBody = z.infer<typeof contactBodySchema>;
+
+export function isHoneypotTriggered(body: { website?: string; company?: string }): boolean {
+  const filled = (v?: string) => typeof v === "string" && v.trim().length > 0;
+  return filled(body.website) || filled(body.company);
+}
+
+export function sanitizeHeaderValue(value: string): string {
+  return value.replace(/[\r\n]+/g, " ").trim().slice(0, 200);
+}

+ 90 - 0
src/lib/content.test.ts

@@ -0,0 +1,90 @@
+import { describe, expect, it } from "vitest";
+import {
+  contactTopics,
+  getAllVerticals,
+  getRelatedVerticals,
+  getVerticalBySlug,
+  siteConfig,
+} from "./content";
+
+describe("content.ts", () => {
+  describe("siteConfig", () => {
+    it("has required fields", () => {
+      expect(siteConfig.name).toBe("Jenado Unlimited");
+      expect(siteConfig.tagline).toContain("Craft for mind");
+      expect(siteConfig.contactEmail).toContain("@");
+      expect(siteConfig.siteUrl).toBeTruthy();
+    });
+  });
+
+  describe("contactTopics", () => {
+    it("contains expected topics", () => {
+      const values = contactTopics.map((t) => t.value);
+      expect(values).toContain("general");
+      expect(values).toContain("honey-bees");
+      expect(values).toContain("personal-training");
+      expect(values).toContain("sourdough");
+    });
+  });
+
+  describe("getAllVerticals", () => {
+    it("returns an array of verticals", () => {
+      const verticals = getAllVerticals();
+      expect(Array.isArray(verticals)).toBe(true);
+      expect(verticals.length).toBeGreaterThan(0);
+    });
+
+    it("sorts alphabetically by title", () => {
+      const verticals = getAllVerticals();
+      const titles = verticals.map((v) => v.title);
+      const sorted = [...titles].sort((a, b) => a.localeCompare(b));
+      expect(titles).toEqual(sorted);
+    });
+
+    it("each vertical has required shape", () => {
+      const verticals = getAllVerticals();
+      for (const v of verticals) {
+        expect(v).toHaveProperty("slug");
+        expect(v).toHaveProperty("title");
+        expect(v).toHaveProperty("summary");
+        expect(v).toHaveProperty("image");
+        expect(v).toHaveProperty("pillars");
+        expect(v).toHaveProperty("status");
+      }
+    });
+  });
+
+  describe("getVerticalBySlug", () => {
+    it("returns a vertical for a valid slug", () => {
+      const v = getVerticalBySlug("honey-bees");
+      expect(v).toBeTruthy();
+      expect(v?.slug).toBe("honey-bees");
+      expect(v?.title).toContain("Honey");
+    });
+
+    it("returns undefined for unknown slug", () => {
+      const v = getVerticalBySlug("does-not-exist" as any);
+      expect(v).toBeUndefined();
+    });
+  });
+
+  describe("getRelatedVerticals", () => {
+    it("excludes the given slug", () => {
+      const related = getRelatedVerticals("honey-bees", 5);
+      expect(related.every((v) => v.slug !== "honey-bees")).toBe(true);
+    });
+
+    it("respects the limit", () => {
+      const related = getRelatedVerticals("honey-bees", 2);
+      expect(related.length).toBeLessThanOrEqual(2);
+    });
+
+    it("returns verticals with correct shape", () => {
+      const related = getRelatedVerticals("sourdough", 3);
+      for (const v of related) {
+        expect(v).toHaveProperty("slug");
+        expect(v.slug).not.toBe("sourdough");
+      }
+    });
+  });
+});

+ 41 - 0
src/lib/content.ts

@@ -0,0 +1,41 @@
+import * as verticals from "@/content/verticals/all";
+import type { ContactTopic, SiteConfig, Vertical } from "@/types";
+
+export const siteConfig: SiteConfig = {
+  name: "Jenado Unlimited",
+  tagline:
+    "Craft for mind, body, and soul — local honey, training, sourdough, and more.",
+  contactEmail: "contact@jenado-unlimited.com",
+  contactPhone: "(920) 284-6299",
+  siteUrl: process.env.NEXT_PUBLIC_SITE_URL || "http://localhost:3000",
+};
+
+export const contactTopics: Array<{ value: ContactTopic; label: string }> = [
+  { value: "general", label: "General Inquiry" },
+  { value: "honey-bees", label: "Honey Bees" },
+  { value: "personal-training", label: "Personal Training" },
+  { value: "sourdough", label: "Sourdough Breads" },
+  { value: "farm-to-table", label: "Farm-to-Table" },
+  { value: "recreation-apps", label: "Recreation Apps" },
+  { value: "laser-engraving", label: "Laser Engraving" },
+  { value: "3d-printing", label: "3D Printing" },
+];
+
+export function getAllVerticals(): Vertical[] {
+  return Object.values(verticals).sort((a, b) =>
+    a.title.localeCompare(b.title),
+  );
+}
+
+export function getVerticalBySlug(slug: string): Vertical | undefined {
+  const vertical = Object.values(verticals).find(
+    (v) => v.slug === (slug as typeof v.slug),
+  );
+  return vertical;
+}
+
+export function getRelatedVerticals(slug: string, limit = 3): Vertical[] {
+  return getAllVerticals()
+    .filter((v) => v.slug !== slug)
+    .slice(0, limit);
+}

+ 3 - 0
src/lib/email.ts

@@ -0,0 +1,3 @@
+import { Resend } from "resend";
+
+export const getResend = () => new Resend(process.env.RESEND_API_KEY);

+ 40 - 0
src/lib/gallery.test.ts

@@ -0,0 +1,40 @@
+import { describe, expect, it } from "vitest";
+import { galleryItems } from "./gallery";
+
+describe("gallery.ts", () => {
+  it("exports an array of gallery items", () => {
+    expect(Array.isArray(galleryItems)).toBe(true);
+    expect(galleryItems.length).toBeGreaterThan(0);
+  });
+
+  it("each item has a url and optional label when present", () => {
+    for (const item of galleryItems) {
+      expect(typeof item.url).toBe("string");
+      expect(item.url.length).toBeGreaterThan(0);
+      if (item.label !== undefined) {
+        expect(typeof item.label).toBe("string");
+        expect(item.label.length).toBeGreaterThan(0);
+      }
+    }
+  });
+
+  it("optional fields are either undefined or correct types", () => {
+    for (const item of galleryItems) {
+      if (item.alt !== undefined) {
+        expect(typeof item.alt).toBe("string");
+      }
+      if (item.href !== undefined) {
+        expect(typeof item.href).toBe("string");
+      }
+      if (item.span !== undefined) {
+        expect(["normal", "wide", "tall"]).toContain(item.span);
+      }
+    }
+  });
+
+  it("contains expected known entries", () => {
+    const urls = galleryItems.map((i) => i.url);
+    expect(urls).toContain("/images/gallery-honey.jpg");
+    expect(urls).toContain("/images/gallery-sourdough.jpg");
+  });
+});

+ 85 - 0
src/lib/gallery.ts

@@ -0,0 +1,85 @@
+export type GalleryItem = {
+  url: string;
+  alt?: string;
+  label?: string;
+  href?: string;
+  span?: "normal" | "wide" | "tall";
+};
+
+/** Curated gallery images used on the Gallery page (and reusable elsewhere). */
+export const galleryItems: GalleryItem[] = [
+  {
+    url: "/images/gallery-honey.jpg",
+    alt: "Jar of raw honey with honeycomb and wildflowers",
+    label: "Honey Bees",
+    href: "/offerings/honey-bees",
+    span: "wide",
+  },
+  {
+    url: "/images/gallery-sourdough.jpg",
+    alt: "Artisan sourdough boule torn open on linen",
+    label: "Sourdough",
+    href: "/offerings/sourdough",
+    span: "tall",
+  },
+  {
+    url: "/images/gallery-training.jpg",
+    alt: "Kettlebell and yoga mat in a sunlit training space",
+    label: "Personal Training",
+    href: "/offerings/personal-training",
+  },
+  {
+    url: "/images/hero-home.jpg",
+    alt: "Honey, bread, and candle on a wooden table in a wildflower meadow at golden hour",
+    label: "Mind · Body · Soul",
+    span: "wide",
+  },
+  {
+    url: "/images/farm-to-table.jpg",
+    alt: "Fresh farm-to-table ingredients",
+    label: "Farm-to-Table",
+    href: "/offerings/farm-to-table",
+  },
+  {
+    url: "/images/laser-engraving.jpg",
+    alt: "Precision laser engraving in progress",
+    label: "Laser Engraving",
+    href: "/offerings/laser-engraving",
+  },
+  {
+    url: "/images/3d-printing.jpg",
+    alt: "3D printed objects and prototypes",
+    label: "3D Printing",
+    href: "/offerings/3d-printing",
+  },
+  {
+    url: "/images/recreation-apps.jpg",
+    alt: "Mindful recreation and digital wellness",
+    label: "Recreation Apps",
+    href: "/offerings/recreation-apps",
+  },
+  {
+    url: "/images/hero-offerings.jpg",
+    alt: "Artisan flatlay of honey, fitness, bread, produce, and craft work",
+    label: "Our Craft",
+    span: "wide",
+  },
+  {
+    url: "/images/honey-bees.jpg",
+    alt: "Close-up of honeycomb cells filled with honey",
+    label: "Honeycomb",
+    href: "/offerings/honey-bees",
+  },
+  {
+    url: "/images/sourdough.jpg",
+    alt: "Rustic seeded loaves with wheat stalks",
+    label: "Daily Bread",
+    href: "/offerings/sourdough",
+  },
+  {
+    url: "/images/personal-training.jpg",
+    alt: "Athlete lifting dumbbells in the gym",
+    label: "Strength",
+    href: "/offerings/personal-training",
+  },
+];

+ 39 - 0
src/lib/json-ld.test.ts

@@ -0,0 +1,39 @@
+import { describe, expect, it } from "vitest";
+import {
+  contactPageJsonLd,
+  organizationJsonLd,
+  websiteJsonLd,
+} from "./json-ld";
+
+describe("json-ld.ts", () => {
+  describe("organizationJsonLd", () => {
+    it("returns Organization schema with required fields", () => {
+      const data = organizationJsonLd();
+      expect(data["@context"]).toBe("https://schema.org");
+      expect(data["@type"]).toBe("Organization");
+      expect(data.name).toBe("Jenado Unlimited");
+      expect(typeof data.description).toBe("string");
+      expect(typeof data.url).toBe("string");
+    });
+  });
+
+  describe("contactPageJsonLd", () => {
+    it("returns ContactPage schema", () => {
+      const data = contactPageJsonLd();
+      expect(data["@context"]).toBe("https://schema.org");
+      expect(data["@type"]).toBe("ContactPage");
+      expect(data.name).toBe("Contact Us");
+      expect(typeof data.description).toBe("string");
+    });
+  });
+
+  describe("websiteJsonLd", () => {
+    it("returns WebSite schema", () => {
+      const data = websiteJsonLd();
+      expect(data["@context"]).toBe("https://schema.org");
+      expect(data["@type"]).toBe("WebSite");
+      expect(data.name).toBe("Jenado Unlimited");
+      expect(typeof data.url).toBe("string");
+    });
+  });
+});

+ 27 - 0
src/lib/json-ld.ts

@@ -0,0 +1,27 @@
+export function organizationJsonLd() {
+  return {
+    "@context": "https://schema.org",
+    "@type": "Organization",
+    name: "Jenado Unlimited",
+    description: "Multi-vertical brand built on the pillars of Mind, Body, and Soul.",
+    url: process.env.NEXT_PUBLIC_SITE_URL || "http://localhost:3000",
+  };
+}
+
+export function contactPageJsonLd() {
+  return {
+    "@context": "https://schema.org",
+    "@type": "ContactPage",
+    name: "Contact Us",
+    description: "Contact Jenado Unlimited for inquiries about honey, personal training, sourdough, and more.",
+  };
+}
+
+export function websiteJsonLd() {
+  return {
+    "@context": "https://schema.org",
+    "@type": "WebSite",
+    name: "Jenado Unlimited",
+    url: process.env.NEXT_PUBLIC_SITE_URL || "http://localhost:3000",
+  };
+}

+ 52 - 0
src/types/index.ts

@@ -0,0 +1,52 @@
+export type VerticalSlug =
+  | "honey-bees"
+  | "personal-training"
+  | "sourdough"
+  | "farm-to-table"
+  | "recreation-apps"
+  | "laser-engraving"
+  | "3d-printing";
+
+export type WellnessPillar = "mind" | "body" | "soul";
+
+export type ContactTopic =
+  | "general"
+  | "honey-bees"
+  | "personal-training"
+  | "sourdough"
+  | "farm-to-table"
+  | "recreation-apps"
+  | "laser-engraving"
+  | "3d-printing";
+
+export interface Vertical {
+  slug: VerticalSlug;
+  title: string;
+  summary: string;
+  image: string;
+  description: string;
+  pillars: WellnessPillar[];
+  status: "active" | "soft-launch" | "coming-soon";
+  disclaimerKey?: string;
+  gallery?: Array<{ url: string; alt?: string }>;
+}
+
+export interface SiteConfig {
+  name: string;
+  tagline: string;
+  contactEmail: string;
+  contactPhone?: string;
+  siteUrl: string;
+}
+
+export interface ContactInput {
+  name: string;
+  email: string;
+  topic: ContactTopic;
+  message: string;
+  phone?: string;
+  website?: string;
+  company?: string;
+}
+
+export type ThemeMode = "light" | "dark" | "system";

+ 22 - 0
vitest.config.ts

@@ -0,0 +1,22 @@
+import react from "@vitejs/plugin-react";
+import path from "path";
+import { defineConfig } from "vitest/config";
+
+export default defineConfig({
+  plugins: [react()],
+  test: {
+    environment: "jsdom",
+    globals: true,
+    setupFiles: ["./vitest.setup.ts"],
+    include: ["src/**/*.{test,spec}.{ts,tsx}"],
+    coverage: {
+      provider: "v8",
+      reporter: ["text", "json", "html"],
+    },
+  },
+  resolve: {
+    alias: {
+      "@": path.resolve(__dirname, "./src"),
+    },
+  },
+});

+ 19 - 0
vitest.setup.ts

@@ -0,0 +1,19 @@
+import "@testing-library/jest-dom/vitest";
+import { cleanup } from "@testing-library/react";
+import { afterEach } from "vitest";
+
+// Clean up after each test
+afterEach(() => {
+  cleanup();
+});
+
+// Mock Next.js router if needed in future tests
+// import { vi } from "vitest";
+// vi.mock("next/navigation", () => ({
+//   useRouter: () => ({
+//     push: vi.fn(),
+//     replace: vi.fn(),
+//     prefetch: vi.fn(),
+//   }),
+//   usePathname: () => "/",
+// }));

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác