Compare commits
86 Commits
28fa04afc0
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 28bef26fbc | |||
| 73fe0e7c8e | |||
| c59c09eee8 | |||
| 75b660d81e | |||
| 3f86c7e87f | |||
| 1c2c274848 | |||
| 74d5bae622 | |||
| 1577eb6c6c | |||
| f4519ec8bf | |||
| c09928018c | |||
| f5e5063ba1 | |||
| 54333f2bd5 | |||
| e646198255 | |||
| 5f1774f03c | |||
| d52190268a | |||
| 8b2bbb2536 | |||
| 6f8edae241 | |||
| acbbc7445d | |||
| 6c3f1afecf | |||
| 7b5afa588e | |||
| 4cc20ac13f | |||
| 6116c5b87c | |||
| 602b78b5bd | |||
| 9a4f347ee8 | |||
| 017fc41d2b | |||
| ab14a5a8e5 | |||
| 41d4c3a054 | |||
| a362985d4c | |||
| 1d66fd60a4 | |||
| 43d995bbc2 | |||
| 0dedde3592 | |||
| d5b9303d94 | |||
| 3a240177c4 | |||
| 0479b7330a | |||
| a78bc67ed3 | |||
| a035500c34 | |||
| 2b5c502724 | |||
| a462afc8b2 | |||
| bf78cde2d8 | |||
| cde6c90033 | |||
| f5ab743987 | |||
| 45364a7452 | |||
| b7f25d712f | |||
| 2fdcb3697d | |||
| 204625b9a8 | |||
| 02557fcb82 | |||
| 9277bc7105 | |||
| 3f6ffbe4ea | |||
| 343b7ae22e | |||
| 5f6ad1c98d | |||
| 9e26dce717 | |||
| 8f997b2f86 | |||
| f712a6c894 | |||
| 1708aadf1e | |||
| dadf92559c | |||
| c3481f3221 | |||
| 8d83f44a07 | |||
| 9faaf7dee9 | |||
| fa7b8dbbb8 | |||
| 4b5c30c11e | |||
| bde7d37305 | |||
| b65f2aa538 | |||
| be949d65bd | |||
| 9ee0d678c9 | |||
| eb2ad2be3f | |||
| 34bd6522e3 | |||
| 273cb24a47 | |||
| 13ecc4d2ec | |||
| 979a6523fa | |||
| de6a83a87c | |||
| 4aff3a5c6b | |||
| 78e1e51877 | |||
| 3df200c7d2 | |||
| f4c247baa2 | |||
| cbc89b192b | |||
| c9af96e669 | |||
| 225c10a853 | |||
| d8da5325de | |||
| 6f2f7318bc | |||
| 29398d1e2e | |||
| a8fb5e2942 | |||
| bfdd5aae41 | |||
| e3ede705c7 | |||
|
|
c49a51783a | ||
| 4618fc3525 | |||
| 6e06d215fa |
158
README.md
@@ -1,35 +1,151 @@
|
|||||||
# Mycelium
|
# Project Mycelium Website
|
||||||
|
|
||||||
Mycelium is a [Tailwind Plus](https://tailwindcss.com/plus) site template built using [Tailwind CSS](https://tailwindcss.com) and [Next.js](https://nextjs.org).
|
- **Repository:** [https://git.ourworld.tf/ourworld_web/www_project_mycelium/](https://git.ourworld.tf/ourworld_web/www_project_mycelium/)
|
||||||
|
|
||||||
## Getting started
|
- **Main Branch (Production):** [https://project.mycelium.tf/](https://project.mycelium.tf/)
|
||||||
|
- **Dev Branch (Staging):** [https://www2.project.mycelium.tf/](https://www2.project.mycelium.tf/)
|
||||||
|
|
||||||
To get started with this template, first install the npm dependencies:
|
|
||||||
|
|
||||||
```bash
|
---
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
Next, run the development server:
|
## About
|
||||||
|
|
||||||
```bash
|
This is the official website for Mycelium Cloud, built using Next.js and Tailwind CSS.
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
Finally, open [http://localhost:3000](http://localhost:3000) in your browser to view the website.
|
---
|
||||||
|
|
||||||
## Customizing
|
## Technologies
|
||||||
|
|
||||||
You can start editing this template by modifying the files in the `/src` folder. The site will auto-update as you edit these files.
|
- **Framework**: [Next.js](https://nextjs.org/)
|
||||||
|
- **Language**: [TypeScript](https://www.typescriptlang.org/)
|
||||||
|
- **Styling**: [Tailwind CSS](https://tailwindcss.com/)
|
||||||
|
|
||||||
## License
|
---
|
||||||
|
|
||||||
This site template is a commercial product and is licensed under the [Tailwind Plus license](https://tailwindcss.com/plus/license).
|
## Dependencies
|
||||||
|
|
||||||
## Learn more
|
- **UI**: [@headlessui/react](https://headlessui.com/)
|
||||||
|
- **Animation**: [framer-motion](https://www.framer.com/motion/)
|
||||||
|
- **Utilities**: [clsx](https://github.com/lukeed/clsx), [use-debounce](https://github.com/xnimorz/use-debounce)
|
||||||
|
|
||||||
To learn more about the technologies used in this site template, see the following resources:
|
---
|
||||||
|
|
||||||
- [Tailwind CSS](https://tailwindcss.com/docs) - the official Tailwind CSS documentation
|
## File Structure
|
||||||
- [Next.js](https://nextjs.org/docs) - the official Next.js documentation
|
|
||||||
- [Headless UI](https://headlessui.dev) - the official Headless UI documentation
|
- **Pages**: To edit the content of a specific page, navigate to `src/app/(main)/`.
|
||||||
|
- **Components**: Reusable components are located in `src/components/`.
|
||||||
|
- **Images**: Add or modify images in the `public/images/` directory.
|
||||||
|
- **CSS**: Global styles can be found in `src/styles/tailwind.css`. Most styling is done using Tailwind CSS utility classes directly in the `.tsx` files.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Branding
|
||||||
|
|
||||||
|
- **Font**: The primary font used is [Mulish](https://fonts.google.com/specimen/Mulish).
|
||||||
|
- **Logos**: Project logos are stored in `public/images/logos/`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Get Started
|
||||||
|
|
||||||
|
Follow these steps to get the project running locally:
|
||||||
|
|
||||||
|
1. **Install Dependencies**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Build the Project**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Start the Development Server**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run start
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Development Guide
|
||||||
|
|
||||||
|
This project follows a modular, component-based architecture. Pages are assembled by combining reusable components into a single layout.
|
||||||
|
|
||||||
|
### Homepage Structure
|
||||||
|
|
||||||
|
The homepage (`src/app/(main)/page.tsx`) is composed of the following components:
|
||||||
|
|
||||||
|
- `HomeHero`
|
||||||
|
- `WorldMap`
|
||||||
|
- `StackSectionPreview`
|
||||||
|
- `Steps`
|
||||||
|
- `Companies`
|
||||||
|
- `ClickableGallery`
|
||||||
|
- `BentoReviews`
|
||||||
|
- `CallToAction`
|
||||||
|
|
||||||
|
To edit a specific section of the homepage, navigate to `src/components/` and modify the corresponding component file.
|
||||||
|
|
||||||
|
### Base Layout
|
||||||
|
|
||||||
|
The main layout for the application is defined in `src/components/Layout.tsx`. This file includes the `Header` and `Footer` and wraps the primary content of each page.
|
||||||
|
|
||||||
|
### Creating a New Page
|
||||||
|
|
||||||
|
To create a new page, follow these steps:
|
||||||
|
|
||||||
|
1. **Create a Folder**: Inside the `src/app/(main)/` directory, create a new folder with the desired URL slug for your page (e.g., `new-page`).
|
||||||
|
|
||||||
|
2. **Create the Page File**: Inside the new folder, create a `page.tsx` file.
|
||||||
|
|
||||||
|
3. **Add Page Content**: Compose your page by importing and using the reusable components from `src/components/`. For example:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { HomeHero } from '@/components/HomeHero'
|
||||||
|
import { Faqs } from '@/components/Faqs'
|
||||||
|
|
||||||
|
export default function NewPage() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<HomeHero />
|
||||||
|
<Faqs />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The new page will be accessible at `http://localhost:3000/new-page`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
- **Never update the `main` branch directly.** All changes must be reviewed and merged by the team through a pull request.
|
||||||
|
- **Always work on the `development` branch.** Create a feature branch from `development` and submit your pull request to `development`.
|
||||||
|
- **Request a review.** After submitting your pull request, ask the team to review and accept it into the `main` branch.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Report an Error
|
||||||
|
|
||||||
|
To report an issue, please use the following link and provide the requested information:
|
||||||
|
|
||||||
|
- **Issue Tracker**: [git.ourworld.tf/ourworld_web/HOME/issues/new](https://git.ourworld.tf/ourworld_web/HOME/issues/new) and tag **OW Website & Wiki Project 2025**
|
||||||
|
|
||||||
|
- See the current web rpoject on [OW Website & Wiki Project 2025](https://git.ourworld.tf/ourworld_web/-/projects/153)
|
||||||
|
|
||||||
|
When reporting an issue, please include:
|
||||||
|
|
||||||
|
- **URL**: The page where the error occurred.
|
||||||
|
- **Repo**: The repository you are working with.
|
||||||
|
- **Branch**: The specific branch you are on.
|
||||||
|
- **Problem**: A detailed description of the problem.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Questions
|
||||||
|
|
||||||
|
If you have any questions, you can reach out to [sashaastiadi](https://git.ourworld.tf/sashaastiadi).
|
||||||
|
|||||||
24
components.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema.json",
|
||||||
|
"style": "new-york",
|
||||||
|
"rsc": true,
|
||||||
|
"tsx": true,
|
||||||
|
"tailwind": {
|
||||||
|
"config": "",
|
||||||
|
"css": "src/styles/tailwind.css",
|
||||||
|
"baseColor": "gray",
|
||||||
|
"cssVariables": true,
|
||||||
|
"prefix": ""
|
||||||
|
},
|
||||||
|
"iconLibrary": "lucide",
|
||||||
|
"aliases": {
|
||||||
|
"components": "@/components",
|
||||||
|
"utils": "@/lib/utils",
|
||||||
|
"ui": "@/components/ui",
|
||||||
|
"lib": "@/lib",
|
||||||
|
"hooks": "@/hooks"
|
||||||
|
},
|
||||||
|
"registries": {
|
||||||
|
"@magicui": "https://magicui.design/r/{name}.json"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
next-env.d.ts
vendored
@@ -1,5 +1,6 @@
|
|||||||
/// <reference types="next" />
|
/// <reference types="next" />
|
||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
|
/// <reference types="next/navigation-types/compat/navigation" />
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
|
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {}
|
const nextConfig = {
|
||||||
|
output: 'export',
|
||||||
|
images: {
|
||||||
|
unoptimized: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = nextConfig
|
module.exports = nextConfig
|
||||||
|
|||||||
211
package-lock.json
generated
@@ -9,14 +9,19 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^2.1.0",
|
"@headlessui/react": "^2.1.0",
|
||||||
|
"@heroicons/react": "^2.2.0",
|
||||||
"@lobehub/icons": "^1.97.2",
|
"@lobehub/icons": "^1.97.2",
|
||||||
|
"@tabler/icons-react": "^3.35.0",
|
||||||
"@tailwindcss/forms": "^0.5.3",
|
"@tailwindcss/forms": "^0.5.3",
|
||||||
"@tailwindcss/postcss": "^4.1.7",
|
|
||||||
"@types/node": "^20.10.8",
|
"@types/node": "^20.10.8",
|
||||||
"@types/react": "^18.2.55",
|
"@types/react": "^18.2.55",
|
||||||
"@types/react-dom": "^18.2.18",
|
"@types/react-dom": "^18.2.18",
|
||||||
"clsx": "^2.1.0",
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"cobe": "^0.6.4",
|
||||||
"framer-motion": "^10.15.0",
|
"framer-motion": "^10.15.0",
|
||||||
|
"lucide-react": "^0.544.0",
|
||||||
|
"motion": "^12.23.12",
|
||||||
"next": "^14.0.4",
|
"next": "^14.0.4",
|
||||||
"popmotion": "^11.0.5",
|
"popmotion": "^11.0.5",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
@@ -30,17 +35,20 @@
|
|||||||
"use-debounce": "^10.0.0"
|
"use-debounce": "^10.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@tailwindcss/postcss": "^4.1.13",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.56.0",
|
||||||
"eslint-config-next": "^14.0.4",
|
"eslint-config-next": "^14.0.4",
|
||||||
"prettier": "^3.3.2",
|
"prettier": "^3.3.2",
|
||||||
"prettier-plugin-tailwindcss": "^0.6.11",
|
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||||
"sharp": "0.33.1"
|
"sharp": "0.33.1",
|
||||||
|
"tw-animate-css": "^1.3.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@alloc/quick-lru": {
|
"node_modules/@alloc/quick-lru": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
|
||||||
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
|
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
@@ -634,6 +642,7 @@
|
|||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz",
|
||||||
"integrity": "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==",
|
"integrity": "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -645,6 +654,7 @@
|
|||||||
"version": "0.44.0",
|
"version": "0.44.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-0.44.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-0.44.0.tgz",
|
||||||
"integrity": "sha512-ZX/etZEZw8DR7zAB1eVQT40lNo0jeqpb6dCgOvctB6FIQ5PoXfMuNY8+ayQfu8tNQbAB8gQWSSJupR8NxeiZXw==",
|
"integrity": "sha512-ZX/etZEZw8DR7zAB1eVQT40lNo0jeqpb6dCgOvctB6FIQ5PoXfMuNY8+ayQfu8tNQbAB8gQWSSJupR8NxeiZXw==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -655,6 +665,7 @@
|
|||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
|
||||||
"integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
|
"integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1020,6 +1031,15 @@
|
|||||||
"react-dom": "^18 || ^19 || ^19.0.0-rc"
|
"react-dom": "^18 || ^19 || ^19.0.0-rc"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@heroicons/react": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">= 16 || ^19.0.0-rc"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@humanwhocodes/config-array": {
|
"node_modules/@humanwhocodes/config-array": {
|
||||||
"version": "0.13.0",
|
"version": "0.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
|
||||||
@@ -1612,6 +1632,7 @@
|
|||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
|
||||||
"integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
|
"integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
|
||||||
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"minipass": "^7.0.4"
|
"minipass": "^7.0.4"
|
||||||
@@ -1713,6 +1734,15 @@
|
|||||||
"integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==",
|
"integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@lobehub/fluent-emoji/node_modules/lucide-react": {
|
||||||
|
"version": "0.469.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.469.0.tgz",
|
||||||
|
"integrity": "sha512-28vvUnnKQ/dBwiCQtwJw7QauYnE7yd2Cyp4tTTJpvglX4EMpbflcdBgrgToX2j71B3YvugK/NH3BGUk+E/p/Fw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@lobehub/icons": {
|
"node_modules/@lobehub/icons": {
|
||||||
"version": "1.97.2",
|
"version": "1.97.2",
|
||||||
"resolved": "https://registry.npmjs.org/@lobehub/icons/-/icons-1.97.2.tgz",
|
"resolved": "https://registry.npmjs.org/@lobehub/icons/-/icons-1.97.2.tgz",
|
||||||
@@ -1731,6 +1761,15 @@
|
|||||||
"react-dom": "^18.0.0 || ^19.0.0"
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@lobehub/icons/node_modules/lucide-react": {
|
||||||
|
"version": "0.469.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.469.0.tgz",
|
||||||
|
"integrity": "sha512-28vvUnnKQ/dBwiCQtwJw7QauYnE7yd2Cyp4tTTJpvglX4EMpbflcdBgrgToX2j71B3YvugK/NH3BGUk+E/p/Fw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@lobehub/ui": {
|
"node_modules/@lobehub/ui": {
|
||||||
"version": "1.171.0",
|
"version": "1.171.0",
|
||||||
"resolved": "https://registry.npmjs.org/@lobehub/ui/-/ui-1.171.0.tgz",
|
"resolved": "https://registry.npmjs.org/@lobehub/ui/-/ui-1.171.0.tgz",
|
||||||
@@ -1916,6 +1955,7 @@
|
|||||||
"version": "0.2.12",
|
"version": "0.2.12",
|
||||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
|
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
|
||||||
"integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==",
|
"integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1928,6 +1968,7 @@
|
|||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz",
|
||||||
"integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==",
|
"integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -2936,6 +2977,32 @@
|
|||||||
"tslib": "^2.8.0"
|
"tslib": "^2.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tabler/icons": {
|
||||||
|
"version": "3.35.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.35.0.tgz",
|
||||||
|
"integrity": "sha512-yYXe+gJ56xlZFiXwV9zVoe3FWCGuZ/D7/G4ZIlDtGxSx5CGQK110wrnT29gUj52kEZoxqF7oURTk97GQxELOFQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/codecalm"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tabler/icons-react": {
|
||||||
|
"version": "3.35.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tabler/icons-react/-/icons-react-3.35.0.tgz",
|
||||||
|
"integrity": "sha512-XG7t2DYf3DyHT5jxFNp5xyLVbL4hMJYJhiSdHADzAjLRYfL7AnjlRfiHDHeXxkb2N103rEIvTsBRazxXtAUz2g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@tabler/icons": "3.35.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/codecalm"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">= 16"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@tailwindcss/forms": {
|
"node_modules/@tailwindcss/forms": {
|
||||||
"version": "0.5.10",
|
"version": "0.5.10",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.10.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.10.tgz",
|
||||||
@@ -2952,6 +3019,7 @@
|
|||||||
"version": "4.1.13",
|
"version": "4.1.13",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.13.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.13.tgz",
|
||||||
"integrity": "sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw==",
|
"integrity": "sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/remapping": "^2.3.4",
|
"@jridgewell/remapping": "^2.3.4",
|
||||||
@@ -2967,6 +3035,7 @@
|
|||||||
"version": "4.1.13",
|
"version": "4.1.13",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.13.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.13.tgz",
|
||||||
"integrity": "sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA==",
|
"integrity": "sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA==",
|
||||||
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -2998,6 +3067,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3014,6 +3084,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3030,6 +3101,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3046,6 +3118,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3062,6 +3135,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3078,6 +3152,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3094,6 +3169,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3110,6 +3186,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3126,6 +3203,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3150,6 +3228,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"wasm32"
|
"wasm32"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -3171,6 +3250,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3187,6 +3267,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3200,6 +3281,7 @@
|
|||||||
"version": "4.1.13",
|
"version": "4.1.13",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.13.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.13.tgz",
|
||||||
"integrity": "sha512-HLgx6YSFKJT7rJqh9oJs/TkBFhxuMOfUKSBEPYwV+t78POOBsdQ7crhZLzwcH3T0UyUuOzU/GK5pk5eKr3wCiQ==",
|
"integrity": "sha512-HLgx6YSFKJT7rJqh9oJs/TkBFhxuMOfUKSBEPYwV+t78POOBsdQ7crhZLzwcH3T0UyUuOzU/GK5pk5eKr3wCiQ==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alloc/quick-lru": "^5.2.0",
|
"@alloc/quick-lru": "^5.2.0",
|
||||||
@@ -3240,6 +3322,7 @@
|
|||||||
"version": "0.10.1",
|
"version": "0.10.1",
|
||||||
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
|
||||||
"integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
|
"integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -4959,6 +5042,7 @@
|
|||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
|
||||||
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
|
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
|
||||||
|
"dev": true,
|
||||||
"license": "BlueOak-1.0.0",
|
"license": "BlueOak-1.0.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
@@ -5003,6 +5087,15 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cobe": {
|
||||||
|
"version": "0.6.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/cobe/-/cobe-0.6.4.tgz",
|
||||||
|
"integrity": "sha512-huuGFnDoXLy/tsCZYYa/H35BBRs9cxsS0XKJ3BXjRp699cQKuoEVrvKlAQMx0DKXG7+VUv4jsHVrS7yPbkLSkQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"phenomenon": "^1.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/collapse-white-space": {
|
"node_modules/collapse-white-space": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz",
|
||||||
@@ -5854,6 +5947,7 @@
|
|||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
|
||||||
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
|
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
|
||||||
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
@@ -5939,6 +6033,7 @@
|
|||||||
"version": "5.18.3",
|
"version": "5.18.3",
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
|
||||||
"integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
|
"integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"graceful-fs": "^4.2.4",
|
"graceful-fs": "^4.2.4",
|
||||||
@@ -8370,6 +8465,7 @@
|
|||||||
"version": "2.5.1",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz",
|
||||||
"integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==",
|
"integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
"jiti": "lib/jiti-cli.mjs"
|
"jiti": "lib/jiti-cli.mjs"
|
||||||
@@ -8610,6 +8706,7 @@
|
|||||||
"version": "1.30.1",
|
"version": "1.30.1",
|
||||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
|
||||||
"integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
|
"integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"detect-libc": "^2.0.3"
|
"detect-libc": "^2.0.3"
|
||||||
@@ -8641,6 +8738,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -8661,6 +8759,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -8681,6 +8780,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -8701,6 +8801,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -8721,6 +8822,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -8741,6 +8843,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -8761,6 +8864,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -8781,6 +8885,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -8801,6 +8906,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -8821,6 +8927,7 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -8959,9 +9066,9 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/lucide-react": {
|
"node_modules/lucide-react": {
|
||||||
"version": "0.469.0",
|
"version": "0.544.0",
|
||||||
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.469.0.tgz",
|
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.544.0.tgz",
|
||||||
"integrity": "sha512-28vvUnnKQ/dBwiCQtwJw7QauYnE7yd2Cyp4tTTJpvglX4EMpbflcdBgrgToX2j71B3YvugK/NH3BGUk+E/p/Fw==",
|
"integrity": "sha512-t5tS44bqd825zAW45UQxpG2CvcC4urOwn2TrwSH8u+MjeE+1NnWl6QqeQ/6NdjMqdOygyiT9p3Ev0p1NJykxjw==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
@@ -8971,6 +9078,7 @@
|
|||||||
"version": "0.30.19",
|
"version": "0.30.19",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
|
||||||
"integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==",
|
"integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||||
@@ -10191,6 +10299,7 @@
|
|||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||||
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
@@ -10200,6 +10309,7 @@
|
|||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz",
|
||||||
"integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==",
|
"integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"minipass": "^7.1.2"
|
"minipass": "^7.1.2"
|
||||||
@@ -10225,6 +10335,7 @@
|
|||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
|
||||||
"integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
|
"integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
"mkdirp": "dist/cjs/src/bin.js"
|
"mkdirp": "dist/cjs/src/bin.js"
|
||||||
@@ -10265,6 +10376,32 @@
|
|||||||
"pathe": "^2.0.1"
|
"pathe": "^2.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/motion": {
|
||||||
|
"version": "12.23.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion/-/motion-12.23.12.tgz",
|
||||||
|
"integrity": "sha512-8jCD8uW5GD1csOoqh1WhH1A6j5APHVE15nuBkFeRiMzYBdRwyAHmSP/oXSuW0WJPZRXTFdBoG4hY9TFWNhhwng==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"framer-motion": "^12.23.12",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/motion-dom": {
|
"node_modules/motion-dom": {
|
||||||
"version": "11.18.1",
|
"version": "11.18.1",
|
||||||
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz",
|
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz",
|
||||||
@@ -10280,6 +10417,48 @@
|
|||||||
"integrity": "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==",
|
"integrity": "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/motion/node_modules/framer-motion": {
|
||||||
|
"version": "12.23.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.12.tgz",
|
||||||
|
"integrity": "sha512-6e78rdVtnBvlEVgu6eFEAgG9v3wLnYEboM8I5O5EXvfKC8gxGQB8wXJdhkMy10iVcn05jl6CNw7/HTsTCfwcWg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-dom": "^12.23.12",
|
||||||
|
"motion-utils": "^12.23.6",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion/node_modules/motion-dom": {
|
||||||
|
"version": "12.23.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.12.tgz",
|
||||||
|
"integrity": "sha512-RcR4fvMCTESQBD/uKQe49D5RUeDOokkGRmz4ceaJKDBgHYtZtntC/s2vLvY38gqGaytinij/yi3hMcWVcEF5Kw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-utils": "^12.23.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion/node_modules/motion-utils": {
|
||||||
|
"version": "12.23.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz",
|
||||||
|
"integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
@@ -10806,6 +10985,12 @@
|
|||||||
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
|
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/phenomenon": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/phenomenon/-/phenomenon-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-7h9/fjPD3qNlgggzm88cY58l9sudZ6Ey+UmZsizfhtawO6E3srZQXywaNm2lBwT72TbpHYRPy7ytIHeBUD/G0A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/picocolors": {
|
"node_modules/picocolors": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||||
@@ -10896,6 +11081,7 @@
|
|||||||
"version": "8.5.6",
|
"version": "8.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
||||||
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
|
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
|
||||||
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@@ -13304,6 +13490,7 @@
|
|||||||
"version": "2.2.3",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz",
|
||||||
"integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==",
|
"integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
@@ -13317,6 +13504,7 @@
|
|||||||
"version": "7.4.3",
|
"version": "7.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz",
|
||||||
"integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
|
"integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
|
||||||
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@isaacs/fs-minipass": "^4.0.0",
|
"@isaacs/fs-minipass": "^4.0.0",
|
||||||
@@ -13491,6 +13679,16 @@
|
|||||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||||
"license": "0BSD"
|
"license": "0BSD"
|
||||||
},
|
},
|
||||||
|
"node_modules/tw-animate-css": {
|
||||||
|
"version": "1.3.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.3.8.tgz",
|
||||||
|
"integrity": "sha512-Qrk3PZ7l7wUcGYhwZloqfkWCmaXZAoqjkdbIDvzfGshwGtexa/DAs9koXxIkrpEasyevandomzCBAV1Yyop5rw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/Wombosvideo"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/type-check": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||||
@@ -14242,6 +14440,7 @@
|
|||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
||||||
"integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
|
"integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
|
||||||
|
"dev": true,
|
||||||
"license": "BlueOak-1.0.0",
|
"license": "BlueOak-1.0.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
|
|||||||
13
package.json
@@ -11,14 +11,19 @@
|
|||||||
"browserslist": "defaults, not ie <= 11",
|
"browserslist": "defaults, not ie <= 11",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^2.1.0",
|
"@headlessui/react": "^2.1.0",
|
||||||
|
"@heroicons/react": "^2.2.0",
|
||||||
"@lobehub/icons": "^1.97.2",
|
"@lobehub/icons": "^1.97.2",
|
||||||
|
"@tabler/icons-react": "^3.35.0",
|
||||||
"@tailwindcss/forms": "^0.5.3",
|
"@tailwindcss/forms": "^0.5.3",
|
||||||
"@tailwindcss/postcss": "^4.1.7",
|
|
||||||
"@types/node": "^20.10.8",
|
"@types/node": "^20.10.8",
|
||||||
"@types/react": "^18.2.55",
|
"@types/react": "^18.2.55",
|
||||||
"@types/react-dom": "^18.2.18",
|
"@types/react-dom": "^18.2.18",
|
||||||
"clsx": "^2.1.0",
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"cobe": "^0.6.4",
|
||||||
"framer-motion": "^10.15.0",
|
"framer-motion": "^10.15.0",
|
||||||
|
"lucide-react": "^0.544.0",
|
||||||
|
"motion": "^12.23.12",
|
||||||
"next": "^14.0.4",
|
"next": "^14.0.4",
|
||||||
"popmotion": "^11.0.5",
|
"popmotion": "^11.0.5",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
@@ -32,10 +37,12 @@
|
|||||||
"use-debounce": "^10.0.0"
|
"use-debounce": "^10.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@tailwindcss/postcss": "^4.1.13",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.56.0",
|
||||||
"eslint-config-next": "^14.0.4",
|
"eslint-config-next": "^14.0.4",
|
||||||
"prettier": "^3.3.2",
|
"prettier": "^3.3.2",
|
||||||
"prettier-plugin-tailwindcss": "^0.6.11",
|
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||||
"sharp": "0.33.1"
|
"sharp": "0.33.1",
|
||||||
|
"tw-animate-css": "^1.3.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
public/images/benefits.webp
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
public/images/deployment.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
public/images/gallery/branding.jpg
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
public/images/gallery/calendar.jpg
Normal file
|
After Width: | Height: | Size: 118 KiB |
BIN
public/images/gallery/code.jpg
Normal file
|
After Width: | Height: | Size: 114 KiB |
BIN
public/images/gallery/data.jpg
Normal file
|
After Width: | Height: | Size: 177 KiB |
BIN
public/images/gallery/datasets.jpg
Normal file
|
After Width: | Height: | Size: 128 KiB |
BIN
public/images/gallery/docs.jpg
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
public/images/gallery/flow.jpg
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
public/images/gallery/interface.jpg
Normal file
|
After Width: | Height: | Size: 110 KiB |
BIN
public/images/gallery/market.jpg
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
public/images/gallery/structure.jpg
Normal file
|
After Width: | Height: | Size: 109 KiB |
BIN
public/images/gallery/translate.jpg
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
public/images/getstarted.webp
Normal file
|
After Width: | Height: | Size: 281 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 6.3 KiB |
15
public/images/logo.svg
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
public/images/logomark.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
14
public/images/logomark.svg
Normal file
|
After Width: | Height: | Size: 112 KiB |
BIN
public/images/m.png
Normal file
|
After Width: | Height: | Size: 224 KiB |
BIN
public/images/placeholder.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/images/stars.webp
Normal file
|
After Width: | Height: | Size: 329 KiB |
BIN
public/videos/agent.mp4
Normal file
BIN
public/videos/benefits.jpg
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
public/videos/benefits.mp4
Normal file
BIN
public/videos/cta.mp4
Normal file
BIN
public/videos/deterministic.mp4
Normal file
BIN
public/videos/fungistor.mp4
Normal file
BIN
public/videos/herodb.mp4
Normal file
BIN
public/videos/mesh.mp4
Normal file
BIN
public/videos/mycelium2.mp4
Normal file
BIN
public/videos/sandbox.mp4
Normal file
BIN
public/videos/universal.mp4
Normal file
@@ -7,10 +7,13 @@ import { HomeAbout } from '@/components/HomeAbout'
|
|||||||
import { ClickableGallery } from '@/components/ClickableGallery'
|
import { ClickableGallery } from '@/components/ClickableGallery'
|
||||||
import { StackSectionPreview } from '@/components/StackSection'
|
import { StackSectionPreview } from '@/components/StackSection'
|
||||||
import { Companies } from '@/components/Companies'
|
import { Companies } from '@/components/Companies'
|
||||||
import { CallTo } from '@/components/CallTo'
|
import { CallToAction } from '@/components/CallToAction'
|
||||||
import { ScrollDown } from '@/components/ui/ScrollDown'
|
import { ScrollDown } from '@/components/ui/ScrollDown'
|
||||||
import { ScrollUp } from '@/components/ui/ScrollUp'
|
import { ScrollUp } from '@/components/ui/ScrollUp'
|
||||||
import { GridStats } from '@/components/GridStats'
|
import { GridStats } from '@/components/GridStats'
|
||||||
|
import { WorldMap } from '@/components/WorldMap'
|
||||||
|
import { GetStarted } from '@/components/GetStarted'
|
||||||
|
import { BentoReviews } from '@/components/BentoReviews'
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
@@ -18,35 +21,27 @@ export default function Home() {
|
|||||||
<section id="home-hero">
|
<section id="home-hero">
|
||||||
<HomeHero />
|
<HomeHero />
|
||||||
</section>
|
</section>
|
||||||
<section id="home-about">
|
<section id="network">
|
||||||
<HomeAbout />
|
<WorldMap />
|
||||||
</section>
|
</section>
|
||||||
<section id="grid-stats">
|
<section id="technologies">
|
||||||
<GridStats />
|
|
||||||
</section>
|
|
||||||
<section id="companies">
|
|
||||||
<Companies />
|
|
||||||
</section>
|
|
||||||
<section id="stack-section">
|
|
||||||
<StackSectionPreview />
|
<StackSectionPreview />
|
||||||
</section>
|
</section>
|
||||||
<section id="steps">
|
<section id="how-it-works">
|
||||||
<Steps />
|
<Steps />
|
||||||
</section>
|
</section>
|
||||||
|
<section id="llms">
|
||||||
|
<Companies />
|
||||||
|
</section>
|
||||||
<section id="clickable-gallery">
|
<section id="clickable-gallery">
|
||||||
<ClickableGallery />
|
<ClickableGallery />
|
||||||
</section>
|
</section>
|
||||||
<section id="use-cases">
|
<section id="bento-reviews">
|
||||||
<UseCases />
|
<BentoReviews />
|
||||||
</section>
|
</section>
|
||||||
<section id="call-to-action">
|
<section id="get-started">
|
||||||
<CallTo />
|
<CallToAction />
|
||||||
</section>
|
</section>
|
||||||
<section id="faqs">
|
|
||||||
<Faqs />
|
|
||||||
</section>
|
|
||||||
<ScrollDown />
|
|
||||||
<ScrollUp />
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
src/app/.DS_Store
vendored
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -1,4 +1,5 @@
|
|||||||
import { type Metadata } from 'next'
|
import { type Metadata } from 'next'
|
||||||
|
import Script from 'next/script'
|
||||||
import { Mulish } from 'next/font/google'
|
import { Mulish } from 'next/font/google'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
|
|
||||||
@@ -25,8 +26,21 @@ export default function RootLayout({
|
|||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<html lang="en" className={clsx('bg-white antialiased', mulish.variable)}>
|
<html lang="en" className={clsx('antialiased', mulish.variable)}>
|
||||||
<body>{children}</body>
|
<head>
|
||||||
|
{/* MailerLite Universal */}
|
||||||
|
<Script id="mailerlite-universal" strategy="afterInteractive">
|
||||||
|
{`(function(m,a,i,l,e,r){ m['MailerLiteObject']=e;function f(){
|
||||||
|
var c={ a:arguments,q:[]};var r=this.push(c);return "number"!=typeof r?r:f.bind(c.q);}
|
||||||
|
f.q=f.q||[];m[e]=m[e]||f.bind(f.q);m[e].q=m[e].q||f.q;r=a.createElement(i);
|
||||||
|
var _=a.getElementsByTagName(i)[0];r.async=1;r.src=l+'?v'+(~~(new Date().getTime()/1000000));
|
||||||
|
_.parentNode.insertBefore(r,_);})(window, document, 'script', 'https://static.mailerlite.com/js/universal.js', 'ml');
|
||||||
|
|
||||||
|
var ml_account = ml('accounts', '1778010', 'x2d3d9f8n1', 'load');`}
|
||||||
|
</Script>
|
||||||
|
{/* End MailerLite Universal */}
|
||||||
|
</head>
|
||||||
|
<body className="bg-black text-white">{children}</body>
|
||||||
</html>
|
</html>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
263
src/components/Archives/1UseCases.tsx
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import React, { useEffect, useMemo, useRef, useState } from 'react'
|
||||||
|
import clsx from 'clsx'
|
||||||
|
import {
|
||||||
|
ArchiveBoxIcon,
|
||||||
|
CodeBracketIcon,
|
||||||
|
CpuChipIcon,
|
||||||
|
GlobeAltIcon,
|
||||||
|
MagnifyingGlassIcon,
|
||||||
|
ShareIcon,
|
||||||
|
UserGroupIcon,
|
||||||
|
CheckBadgeIcon,
|
||||||
|
} from '@heroicons/react/24/solid'
|
||||||
|
|
||||||
|
import { Container } from '@/components/Container'
|
||||||
|
import { H2, P, CT, CP } from '@/components/Texts'
|
||||||
|
import { motion, useInView } from 'framer-motion'
|
||||||
|
|
||||||
|
interface Review {
|
||||||
|
title: string
|
||||||
|
body: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const reviews: Array<Review> = [
|
||||||
|
{
|
||||||
|
title: 'FungiStor: Long-Term AI Memory',
|
||||||
|
body: 'Quantum-safe permanent storage preserving AI knowledge forever. Zero-knowledge architecture with mathematical dispersal ensures immortality.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'HeroDB: Active AI Memory',
|
||||||
|
body: 'High-performance datastore for AI working memory. Multi-modal indexing enables vector search with global accessibility.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'MOS Sandboxes: Secure Agent Workspaces',
|
||||||
|
body: 'Lightweight isolated environments deploying globally in five seconds. Hardware-level isolation ensures maximum security for agents.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Mycelium Mesh: Secure Communication Network',
|
||||||
|
body: 'Peer-to-peer overlay network with end-to-end encryption. Self-healing shortest-path routing creates resilient agentic communication.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Deterministic Deployment: Verifiable Code Execution',
|
||||||
|
body: 'Cryptographic guarantee system ensuring deployed code matches specifications. Prevents supply-chain attacks with immutable trails.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Agent Coordination: Sovereign Workflow Management',
|
||||||
|
body: 'User-centric orchestration where HERO agents coordinate worker fleets. Planetary-scale coordination with instant spawning.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Universal Interface Layer: AI Service Gateway',
|
||||||
|
body: 'Unified broker connecting agents to LLMs, APIs, and services. Integrated micropayments simplify development.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Semantic Index & Search: Navigable Knowledge Fabric',
|
||||||
|
body: 'Transforms data chaos into unified knowledge graphs. Goes beyond keywords to understand meaning and context.',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
function getReviewIcon(title: string) {
|
||||||
|
if (title.startsWith('FungiStor')) return ArchiveBoxIcon;
|
||||||
|
if (title.startsWith('HeroDB')) return CpuChipIcon;
|
||||||
|
if (title.startsWith('MOS Sandboxes')) return CodeBracketIcon;
|
||||||
|
if (title.startsWith('Mycelium Mesh')) return ShareIcon;
|
||||||
|
if (title.startsWith('Deterministic Deployment')) return CheckBadgeIcon;
|
||||||
|
if (title.startsWith('Agent Coordination')) return UserGroupIcon;
|
||||||
|
if (title.startsWith('Universal Interface Layer')) return GlobeAltIcon;
|
||||||
|
if (title.startsWith('Semantic Index & Search')) return MagnifyingGlassIcon;
|
||||||
|
return GlobeAltIcon; // default
|
||||||
|
}
|
||||||
|
|
||||||
|
function Review({
|
||||||
|
title,
|
||||||
|
body,
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: Omit<React.ComponentPropsWithoutRef<'figure'>, keyof Review> & Review) {
|
||||||
|
let animationDelay = useMemo(() => {
|
||||||
|
let possibleAnimationDelays = ['0s', '0.1s', '0.2s', '0.3s', '0.4s', '0.5s']
|
||||||
|
return possibleAnimationDelays[
|
||||||
|
Math.floor(Math.random() * possibleAnimationDelays.length)
|
||||||
|
]
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<figure
|
||||||
|
className={clsx(
|
||||||
|
'animate-fade-in rounded-3xl bg-gray-900/50 p-6 opacity-0 shadow-md shadow-gray-900/5',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
style={{ animationDelay }}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<blockquote className="text-white">
|
||||||
|
{React.createElement(getReviewIcon(title), { className: "h-6 w-6 text-white mb-2" })}
|
||||||
|
<CT color="light" className="mt-4 text-lg/6 font-semibold">
|
||||||
|
{title}
|
||||||
|
</CT>
|
||||||
|
<CP color="light" className="mt-3 text-sm">{body}</CP>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
</figure>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function splitArray<T>(array: Array<T>, numParts: number) {
|
||||||
|
let result: Array<Array<T>> = []
|
||||||
|
for (let i = 0; i < array.length; i++) {
|
||||||
|
let index = i % numParts
|
||||||
|
if (!result[index]) {
|
||||||
|
result[index] = []
|
||||||
|
}
|
||||||
|
result[index].push(array[i])
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
function ReviewColumn({
|
||||||
|
reviews,
|
||||||
|
className,
|
||||||
|
reviewClassName,
|
||||||
|
msPerPixel = 0,
|
||||||
|
}: {
|
||||||
|
reviews: Array<Review>
|
||||||
|
className?: string
|
||||||
|
reviewClassName?: (reviewIndex: number) => string
|
||||||
|
msPerPixel?: number
|
||||||
|
}) {
|
||||||
|
let columnRef = useRef<React.ElementRef<'div'>>(null)
|
||||||
|
let [columnHeight, setColumnHeight] = useState(0)
|
||||||
|
let duration = `${columnHeight * msPerPixel}ms`
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!columnRef.current) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let resizeObserver = new window.ResizeObserver(() => {
|
||||||
|
setColumnHeight(columnRef.current?.offsetHeight ?? 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
resizeObserver.observe(columnRef.current)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
resizeObserver.disconnect()
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={columnRef}
|
||||||
|
className={clsx('animate-marquee space-y-8 py-4', className)}
|
||||||
|
style={{ '--marquee-duration': duration } as React.CSSProperties}
|
||||||
|
>
|
||||||
|
{reviews.concat(reviews).map((review, reviewIndex) => (
|
||||||
|
<Review
|
||||||
|
key={reviewIndex}
|
||||||
|
aria-hidden={reviewIndex >= reviews.length}
|
||||||
|
className={reviewClassName?.(reviewIndex % reviews.length)}
|
||||||
|
{...review}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ReviewGrid() {
|
||||||
|
let containerRef = useRef<React.ElementRef<'div'>>(null)
|
||||||
|
let isInView = useInView(containerRef, { once: true, amount: 0.4 })
|
||||||
|
let columns = splitArray(reviews, 3)
|
||||||
|
let column1 = columns[0]
|
||||||
|
let column2 = columns[1]
|
||||||
|
let column3 = splitArray(columns[2], 2)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={containerRef}
|
||||||
|
className="relative -mx-4 mt-0 grid h-196 max-h-[150vh] grid-cols-1 items-start gap-8 overflow-hidden px-4 md:grid-cols-2 lg:grid-cols-3"
|
||||||
|
>
|
||||||
|
{isInView && (
|
||||||
|
<>
|
||||||
|
<ReviewColumn
|
||||||
|
reviews={[...column1, ...column3.flat(), ...column2]}
|
||||||
|
reviewClassName={(reviewIndex) =>
|
||||||
|
clsx(
|
||||||
|
reviewIndex >= column1.length + column3[0].length &&
|
||||||
|
'md:hidden',
|
||||||
|
reviewIndex >= column1.length && 'lg:hidden',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
msPerPixel={10}
|
||||||
|
/>
|
||||||
|
<ReviewColumn
|
||||||
|
reviews={[...column2, ...column3[1]]}
|
||||||
|
className="hidden md:block"
|
||||||
|
reviewClassName={(reviewIndex) =>
|
||||||
|
reviewIndex >= column2.length ? 'lg:hidden' : ''
|
||||||
|
}
|
||||||
|
msPerPixel={15}
|
||||||
|
/>
|
||||||
|
<ReviewColumn
|
||||||
|
reviews={column3.flat()}
|
||||||
|
className="hidden lg:block"
|
||||||
|
msPerPixel={10}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<div className="pointer-events-none absolute inset-x-0 top-0 h-32 bg-linear-to-b from-black" />
|
||||||
|
<div className="pointer-events-none absolute inset-x-0 bottom-0 h-32 bg-linear-to-t from-black" />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function UseCases() {
|
||||||
|
const ref = useRef(null);
|
||||||
|
const isInView = useInView(ref, { once: true });
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
id="usecases"
|
||||||
|
ref={ref}
|
||||||
|
aria-labelledby="usecases-title"
|
||||||
|
className="bg-black py-24"
|
||||||
|
>
|
||||||
|
<Container className=''>
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
||||||
|
transition={{ duration: 0.8, delay: 0.1 }}
|
||||||
|
className="mx-auto max-w-2xl lg:max-w-5xl"
|
||||||
|
>
|
||||||
|
<H2
|
||||||
|
id="usecases-title"
|
||||||
|
color="light"
|
||||||
|
className="text-center"
|
||||||
|
>
|
||||||
|
Coming Soon: The Future of Mycelium
|
||||||
|
</H2>
|
||||||
|
<P className="mt-6 text-center" color="light">
|
||||||
|
Mycelium Cloud is evolving to bring even more powerful decentralized features, designed to enhance your experience and expand possibilities. Be the first to explore what's coming next by staying connected with our latest updates.
|
||||||
|
</P>
|
||||||
|
</motion.div>
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
||||||
|
transition={{ duration: 1, delay: 0.2 }}
|
||||||
|
aria-hidden="true"
|
||||||
|
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
clipPath:
|
||||||
|
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
||||||
|
}}
|
||||||
|
className="relative left-[calc(50%-30rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#93c5fd] to-[#9089fc] opacity-30 sm:left-[calc(50%-36rem)] sm:w-[72.1875rem]"
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
<ReviewGrid />
|
||||||
|
</Container>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
92
src/components/Archives/Companies copy.tsx
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { motion } from "framer-motion";
|
||||||
|
import { H2, P } from '@/components/Texts';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import Ai21 from '@/components/logos/Ai21';
|
||||||
|
import Claude from '@/components/logos/Claude';
|
||||||
|
import BaiduCloud from '@/components/logos/BaiduCloud';
|
||||||
|
import ByteDance from '@/components/logos/ByteDance';
|
||||||
|
import DeepSeek from '@/components/logos/DeepSeek';
|
||||||
|
import DeepMind from '@/components/logos/DeepMind';
|
||||||
|
import Minimax from '@/components/logos/Minimax';
|
||||||
|
import Mistral from '@/components/logos/Mistral';
|
||||||
|
import Moonshot from '@/components/logos/Moonshot';
|
||||||
|
import AlibabaCloud from '@/components/logos/AlibabaCloud';
|
||||||
|
import TencentCloud from '@/components/logos/TencentCloud';
|
||||||
|
import OpenAI from '@/components/logos/OpenAI';
|
||||||
|
import XAI from '@/components/logos/XAI';
|
||||||
|
|
||||||
|
const row1 = [Ai21, Claude, BaiduCloud, ByteDance];
|
||||||
|
const row2 = [DeepSeek, DeepMind, Minimax, Mistral];
|
||||||
|
const row3 = [Moonshot, AlibabaCloud];
|
||||||
|
const row4 = [TencentCloud, OpenAI, XAI];
|
||||||
|
|
||||||
|
export function Companies() {
|
||||||
|
return (
|
||||||
|
<div id="companies" className="relative flex h-screen w-full overflow-hidden rounded-md bg-transparent antialiased md:items-center md:justify-center">
|
||||||
|
<div className="relative z-10 mx-auto w-full max-w-6xl p-4 py-12">
|
||||||
|
|
||||||
|
{/* Heading */}
|
||||||
|
<motion.div
|
||||||
|
className="flex flex-col justify-center max-w-4xl items-center mb-6 mx-auto"
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 1 }}
|
||||||
|
>
|
||||||
|
<H2 className="text-center pb-6">
|
||||||
|
Deploy the World’s Leading AI Models
|
||||||
|
</H2>
|
||||||
|
<P className="pb-8 text-center" color="custom">
|
||||||
|
Deploy and scale AI from top global providers on a decentralized, privacy-first infrastructure.
|
||||||
|
</P>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Animated Line */}
|
||||||
|
<motion.div
|
||||||
|
className="h-[2px] bg-neutral-400 rounded-full mx-auto mb-12"
|
||||||
|
initial={{ width: 0 }}
|
||||||
|
animate={{ width: "100%" }}
|
||||||
|
transition={{ duration: 2, delay: 1 }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Logos grid */}
|
||||||
|
<div className="flex flex-col items-center gap-y-10">
|
||||||
|
{[row1, row2, row3, row4].map((row, rowIndex) => (
|
||||||
|
<motion.div
|
||||||
|
key={rowIndex}
|
||||||
|
className="flex flex-wrap justify-center items-center gap-x-8 sm:gap-x-10"
|
||||||
|
initial="hidden"
|
||||||
|
animate="visible"
|
||||||
|
variants={{
|
||||||
|
visible: {
|
||||||
|
transition: {
|
||||||
|
staggerChildren: 0.15,
|
||||||
|
delayChildren: 2.8 + rowIndex * 0.5, // Stagger rows
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{row.map((Logo, i) => (
|
||||||
|
<motion.div
|
||||||
|
key={i}
|
||||||
|
className="flex justify-center"
|
||||||
|
variants={{
|
||||||
|
hidden: { opacity: 0, y: 30 },
|
||||||
|
visible: { opacity: 1, y: 0 },
|
||||||
|
}}
|
||||||
|
transition={{ duration: 0.6, ease: "easeOut" }}
|
||||||
|
>
|
||||||
|
<div className="text-[#2F3178]"><Logo /></div>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
116
src/components/Archives/Cubec.tsx
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import Image from "next/image";
|
||||||
|
import { motion } from "framer-motion";
|
||||||
|
import { CT, CP } from '@/components/Texts';
|
||||||
|
|
||||||
|
interface CubeProps {
|
||||||
|
title: string;
|
||||||
|
descriptionTitle: string;
|
||||||
|
description: string;
|
||||||
|
isActive: boolean;
|
||||||
|
index: number;
|
||||||
|
onHover: () => void;
|
||||||
|
onLeave: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function Cube({ title, descriptionTitle, description, isActive, index, onHover, onLeave }: CubeProps) {
|
||||||
|
return (
|
||||||
|
<div className="relative flex flex-col items-center">
|
||||||
|
<motion.div
|
||||||
|
className="relative cursor-pointer pointer-events-none"
|
||||||
|
onMouseEnter={onHover}
|
||||||
|
onMouseLeave={onLeave}
|
||||||
|
style={{
|
||||||
|
zIndex: 10 - index,
|
||||||
|
}}
|
||||||
|
animate={{
|
||||||
|
scale: isActive ? 1.05 : 1,
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
duration: 0.3,
|
||||||
|
ease: "easeOut",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Image Cube */}
|
||||||
|
<Image
|
||||||
|
src="/images/cube.png"
|
||||||
|
alt="Cube"
|
||||||
|
width={507}
|
||||||
|
height={234}
|
||||||
|
className="w-60 sm:w-80 lg:w-96 h-auto drop-shadow-lg pointer-events-auto"
|
||||||
|
style={{
|
||||||
|
filter: isActive
|
||||||
|
? 'brightness(1.1) drop-shadow(0 25px 25px rgba(144, 137, 252, 0.4))'
|
||||||
|
: 'brightness(0.9) drop-shadow(0 10px 15px rgba(144, 137, 252, 0.2))',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Title overlay */}
|
||||||
|
<div className="absolute inset-0 flex items-center justify-center">
|
||||||
|
<CT as="h3" className="px-4 drop-shadow-lg" style={{ transform: 'rotate(0deg) skewX(0deg)', transformOrigin: 'center' }}>
|
||||||
|
{title}
|
||||||
|
</CT>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Description with arrow line - Desktop */}
|
||||||
|
{isActive && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
exit={{ opacity: 0 }}
|
||||||
|
transition={{ duration: 0.3 }}
|
||||||
|
className="hidden lg:block absolute left-full top-1/2 -translate-y-1/2 z-50"
|
||||||
|
>
|
||||||
|
{/* Arrow line */}
|
||||||
|
<svg
|
||||||
|
className="absolute left-0 top-1/2 -translate-y-1/2"
|
||||||
|
width="120"
|
||||||
|
height="2"
|
||||||
|
viewBox="0 0 120 2"
|
||||||
|
fill="none"
|
||||||
|
>
|
||||||
|
<line
|
||||||
|
x1="0"
|
||||||
|
y1="1"
|
||||||
|
x2="120"
|
||||||
|
y2="1"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="1"
|
||||||
|
opacity="0.6"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
{/* Description text */}
|
||||||
|
<div className="ml-32 w-80 text-[#2F3178]">
|
||||||
|
<h4 className="text-base font-semibold mb-2">
|
||||||
|
{descriptionTitle}
|
||||||
|
</h4>
|
||||||
|
<CP color="custom">{description}</CP>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Description for Mobile - Below cube */}
|
||||||
|
{isActive && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 10 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
exit={{ opacity: 0, y: 10 }}
|
||||||
|
transition={{ duration: 0.3 }}
|
||||||
|
className="lg:hidden absolute top-full left-1/2 -translate-x-1/2 mt-8 z-50"
|
||||||
|
>
|
||||||
|
<div className="w-64 sm:w-80 px-4 text-[#2F3178]">
|
||||||
|
<h4 className="text-base font-semibold mb-2 text-center">
|
||||||
|
{descriptionTitle}
|
||||||
|
</h4>
|
||||||
|
<CP className="text-center" color="custom">{description}</CP>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
117
src/components/Archives/GridStats copy.tsx
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import CountUp from "react-countup";
|
||||||
|
import React from "react";
|
||||||
|
import { Button } from "@/components/Button";
|
||||||
|
|
||||||
|
export function GridStats() {
|
||||||
|
return (
|
||||||
|
<div id="grid-stats" className="py-24 bg-transparent relative">
|
||||||
|
<div className="mx-auto max-w-2xl px-6 lg:max-w-7xl lg:px-8">
|
||||||
|
<div className="grid grid-cols-1 gap-8 lg:grid-cols-3">
|
||||||
|
{/* Column 1: Title & NODES */}
|
||||||
|
<div className="flex flex-col space-y-10">
|
||||||
|
{/* Title + Description */}
|
||||||
|
<div>
|
||||||
|
<h2 className="text-2xl font-semibold tracking-tight leading-tight text-black lg:text-4xl">
|
||||||
|
Powered by a Global Community
|
||||||
|
</h2>
|
||||||
|
<p className="mt-4 sm:mt-6 text-sm font-light text-pretty text-black lg:text-base">
|
||||||
|
ThreeFold’s groundbreaking technology enables anyone – individuals, organizations, and communities – to deploy their own Internet infrastructure.
|
||||||
|
</p>
|
||||||
|
<Button className="mt-8" variant="outline" href="https://threefold.io/build" >Explore TFGrid →</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Column 2: CORES (staggered) + SSD */}
|
||||||
|
<div className="flex flex-col space-y-10">
|
||||||
|
<StatCard
|
||||||
|
label="CORES"
|
||||||
|
description="A globally distributed mesh of CPU cores powering decentralized applications, AI workloads, and edge computing — without central bottlenecks."
|
||||||
|
value={<CountUp end={54_958} duration={2.5} separator="," />}
|
||||||
|
note="Total Central Processing Unit Cores available on the grid."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<StatCard
|
||||||
|
label="SSD CAPACITY"
|
||||||
|
description="A distributed network of storage capacity — ready to support Web3, AI, and edge computing workloads around the world."
|
||||||
|
value={<CountUp end={7_364_506} duration={2.5} separator="," />}
|
||||||
|
unit="GB"
|
||||||
|
note="The total amount of storage (SSD, HDD, & RAM) on the grid."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{/* Column 3: nodes countries */}
|
||||||
|
<div className="flex flex-col space-y-10 justify-start">
|
||||||
|
<StatCard
|
||||||
|
label="NODES"
|
||||||
|
description="A computer server 100% dedicated to the network. It is a building block of the ThreeFold Grid, providing compute, storage, and network resources."
|
||||||
|
value={<CountUp end={1778} duration={2.5} separator="," />}
|
||||||
|
note="The total number of nodes on the grid."
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
<StatCard
|
||||||
|
label="COUNTRIES"
|
||||||
|
description="The number of countries where at least one node is connected and operational on the grid."
|
||||||
|
value={<CountUp end={51} duration={2.5} separator="," />}
|
||||||
|
note="The total number of countries with active nodes."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🧱 Stat Card Component
|
||||||
|
function StatCard({
|
||||||
|
label,
|
||||||
|
description,
|
||||||
|
value,
|
||||||
|
unit,
|
||||||
|
note,
|
||||||
|
className = "",
|
||||||
|
}: {
|
||||||
|
label: string;
|
||||||
|
description: string;
|
||||||
|
value: React.ReactNode;
|
||||||
|
unit?: string;
|
||||||
|
note: string;
|
||||||
|
className?: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`relative flex flex-col overflow-hidden rounded-3xl bg-white shadow-md shadow-gray-900/5 p-8 transition-all duration-300 ease-out hover:scale-105 ${className}`}
|
||||||
|
style={{
|
||||||
|
filter: 'brightness(1)',
|
||||||
|
}}
|
||||||
|
onMouseEnter={(e) => {
|
||||||
|
e.currentTarget.style.filter = 'brightness(0.8)';
|
||||||
|
}}
|
||||||
|
onMouseLeave={(e) => {
|
||||||
|
e.currentTarget.style.filter = 'brightness(1)';
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<h3 className="text-lg font-semibold text-gradient-neutral-vertical" style={{ textShadow: '0 0 12px rgba(255, 255, 255, 0.4), 0 0 24px rgba(255, 255, 255, 0.2)' }}>{label}</h3>
|
||||||
|
<p className="mt-2 text-sm font-light text-pretty text-black lg:text-base">
|
||||||
|
{description}
|
||||||
|
</p>
|
||||||
|
<div className="mt-8 flex items-center space-x-3">
|
||||||
|
<span className="text-gradient-neutral-vertical text-3xl">•</span>
|
||||||
|
<div className="text-5xl font-semibold tracking-tight text-black tabular-nums">
|
||||||
|
{value}
|
||||||
|
{unit && (
|
||||||
|
<span className="ml-2 text-lg font-normal text-gray-800">{unit}</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p className="mt-2 text-sm text-gray-800 uppercase tracking-wider">
|
||||||
|
{note}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
90
src/components/Archives/HomeHero copy.tsx
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { motion } from 'framer-motion'
|
||||||
|
import { TypeAnimation } from 'react-type-animation'
|
||||||
|
import { Dialog, DialogPanel } from '@headlessui/react'
|
||||||
|
import { Bars3Icon, XMarkIcon, ChevronDoubleDownIcon } from '@heroicons/react/24/outline'
|
||||||
|
import { H1, PL } from '@/components/Texts'
|
||||||
|
|
||||||
|
const navigation = [
|
||||||
|
{ name: 'Product', href: '#' },
|
||||||
|
{ name: 'Features', href: '#' },
|
||||||
|
{ name: 'Marketplace', href: '#' },
|
||||||
|
{ name: 'Company', href: '#' },
|
||||||
|
]
|
||||||
|
|
||||||
|
export function HomeHero() {
|
||||||
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative h-screen -top-15">
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
transition={{ duration: 2 }}
|
||||||
|
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-[700px] h-[700px] -z-10 rounded-full overflow-hidden"
|
||||||
|
>
|
||||||
|
<video
|
||||||
|
autoPlay
|
||||||
|
loop
|
||||||
|
muted
|
||||||
|
playsInline
|
||||||
|
className="h-full w-full object-cover"
|
||||||
|
>
|
||||||
|
<source src="/videos/mycelium.mp4" type="video/mp4" />
|
||||||
|
</video>
|
||||||
|
</motion.div>
|
||||||
|
<div className="relative isolate px-6 lg:px-8">
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl lg:-top-80"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
clipPath:
|
||||||
|
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
||||||
|
}}
|
||||||
|
className="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#a4caf6] to-[#aaa4fa] opacity-15 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
className="absolute inset-x-0 bottom-10 -z-10 transform-gpu overflow-hidden blur-3xl lg:bottom-40"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
clipPath:
|
||||||
|
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
||||||
|
}}
|
||||||
|
className="relative bottom-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#93c5fd] to-[#9089fc] opacity-15 sm:left-[calc(50%+30rem)] sm:w-[72.1875rem]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="relative -top-15 mx-auto max-w-8xl h-screen flex items-center justify-center">
|
||||||
|
<div className="text-center max-w-5xl">
|
||||||
|
<H1>
|
||||||
|
<TypeAnimation
|
||||||
|
sequence={[
|
||||||
|
'Decentralized Autonomous Agentic Cloud.',
|
||||||
|
1000,
|
||||||
|
]}
|
||||||
|
wrapper="span"
|
||||||
|
speed={50}
|
||||||
|
repeat={0}
|
||||||
|
/>
|
||||||
|
</H1>
|
||||||
|
</div>
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
transition={{ duration: 1, delay: 1 }}
|
||||||
|
>
|
||||||
|
<PL className="absolute bottom-0 left-0 max-w-xl text-left" color="custom">
|
||||||
|
Mycelium's advancements in Agentic infrastructure supports private, secure and autonomous Agents that connect, learn and grow with you.
|
||||||
|
</PL>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
71
src/components/Archives/Steps copy.tsx
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import React, { useRef } from 'react'
|
||||||
|
import { motion, useInView } from 'framer-motion'
|
||||||
|
import { H2, P, CT, CP } from '@/components/Texts'
|
||||||
|
import { TbCircleNumber1Filled, TbCircleNumber2Filled, TbCircleNumber3Filled } from 'react-icons/tb'
|
||||||
|
|
||||||
|
const features = [
|
||||||
|
{
|
||||||
|
name: 'Choose Your Intelligence',
|
||||||
|
description: 'Explore a library of leading LLMs and agentic functions. Pick the ones that fit your use case, from general assistants to specialized reasoning models.',
|
||||||
|
icon: TbCircleNumber1Filled,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Add Your Knowledge',
|
||||||
|
description:
|
||||||
|
'Connect your data or knowledge base to enable personalized, context-aware results while keeping your information private.',
|
||||||
|
icon: TbCircleNumber2Filled,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Define Your Network',
|
||||||
|
description:
|
||||||
|
'Set up and manage your nodes with ease. Scale compute and storage as you grow, while staying fully sovereign and decentralized.',
|
||||||
|
icon: TbCircleNumber3Filled,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export function Steps() {
|
||||||
|
const ref = useRef(null);
|
||||||
|
const isInView = useInView(ref, { once: true });
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section id="benefits" ref={ref} className="bg-white pt-0 pb-24 dark:bg-gray-900">
|
||||||
|
<div className="mx-auto max-w-7xl px-6 lg:px-0">
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
||||||
|
transition={{ duration: 0.8, delay: 0.1 }}
|
||||||
|
className="mx-auto max-w-5xl lg:mx-0"
|
||||||
|
>
|
||||||
|
<H2 className="text-3xl font-medium tracking-tight">
|
||||||
|
Deploy Scalable LLMs and AI Agents in Seconds
|
||||||
|
</H2>
|
||||||
|
<P className="mt-6 text-lg" color="custom">
|
||||||
|
Launch and scale intelligence on your own terms. Mycelium Cloud makes it simple to deploy models, integrate knowledge, and run everything on a network you control.
|
||||||
|
</P>
|
||||||
|
</motion.div>
|
||||||
|
<motion.ul
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
||||||
|
transition={{ duration: 0.5, delay: 0.2, staggerChildren: 0.2 }}
|
||||||
|
className="mx-auto mt-16 grid max-w-2xl grid-cols-1 gap-x-8 gap-y-16 text-base/7 sm:grid-cols-2 lg:mx-0 lg:max-w-none lg:grid-cols-3"
|
||||||
|
>
|
||||||
|
{features.map((feature, index) => (
|
||||||
|
<motion.li
|
||||||
|
key={feature.name}
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
||||||
|
transition={{ duration: 0.5, delay: 0.3 + index * 0.2 }}
|
||||||
|
className="rounded-2xl border border-gray-200 p-8 dark:border-gray-700"
|
||||||
|
>
|
||||||
|
<feature.icon className="h-8 w-8 mb-4 text-[#2F3178]" />
|
||||||
|
<CT as="span" className="font-semibold">{feature.name}</CT>
|
||||||
|
<CP className="mt-2 text-sm" color="custom">{feature.description}</CP>
|
||||||
|
</motion.li>
|
||||||
|
))}
|
||||||
|
</motion.ul>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
263
src/components/Archives/UseCases copy.tsx
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import React, { useEffect, useMemo, useRef, useState } from 'react'
|
||||||
|
import clsx from 'clsx'
|
||||||
|
import {
|
||||||
|
ArchiveBoxIcon,
|
||||||
|
CodeBracketIcon,
|
||||||
|
CpuChipIcon,
|
||||||
|
GlobeAltIcon,
|
||||||
|
MagnifyingGlassIcon,
|
||||||
|
ShareIcon,
|
||||||
|
UserGroupIcon,
|
||||||
|
CheckBadgeIcon,
|
||||||
|
} from '@heroicons/react/24/solid'
|
||||||
|
|
||||||
|
import { Container } from '@/components/Container'
|
||||||
|
import { H2, P, CT, CP } from '@/components/Texts'
|
||||||
|
import { motion, useInView } from 'framer-motion'
|
||||||
|
|
||||||
|
interface Review {
|
||||||
|
title: string
|
||||||
|
body: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const reviews: Array<Review> = [
|
||||||
|
{
|
||||||
|
title: 'FungiStor: Long-Term AI Memory',
|
||||||
|
body: 'Quantum-safe permanent storage preserving AI knowledge forever. Zero-knowledge architecture with mathematical dispersal ensures immortality.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'HeroDB: Active AI Memory',
|
||||||
|
body: 'High-performance datastore for AI working memory. Multi-modal indexing enables vector search with global accessibility.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'MOS Sandboxes: Secure Agent Workspaces',
|
||||||
|
body: 'Lightweight isolated environments deploying globally in five seconds. Hardware-level isolation ensures maximum security for agents.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Mycelium Mesh: Secure Communication Network',
|
||||||
|
body: 'Peer-to-peer overlay network with end-to-end encryption. Self-healing shortest-path routing creates resilient agentic communication.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Deterministic Deployment: Verifiable Code Execution',
|
||||||
|
body: 'Cryptographic guarantee system ensuring deployed code matches specifications. Prevents supply-chain attacks with immutable trails.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Agent Coordination: Sovereign Workflow Management',
|
||||||
|
body: 'User-centric orchestration where HERO agents coordinate worker fleets. Planetary-scale coordination with instant spawning.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Universal Interface Layer: AI Service Gateway',
|
||||||
|
body: 'Unified broker connecting agents to LLMs, APIs, and services. Integrated micropayments simplify development.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Semantic Index & Search: Navigable Knowledge Fabric',
|
||||||
|
body: 'Transforms data chaos into unified knowledge graphs. Goes beyond keywords to understand meaning and context.',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
function getReviewIcon(title: string) {
|
||||||
|
if (title.startsWith('FungiStor')) return ArchiveBoxIcon;
|
||||||
|
if (title.startsWith('HeroDB')) return CpuChipIcon;
|
||||||
|
if (title.startsWith('MOS Sandboxes')) return CodeBracketIcon;
|
||||||
|
if (title.startsWith('Mycelium Mesh')) return ShareIcon;
|
||||||
|
if (title.startsWith('Deterministic Deployment')) return CheckBadgeIcon;
|
||||||
|
if (title.startsWith('Agent Coordination')) return UserGroupIcon;
|
||||||
|
if (title.startsWith('Universal Interface Layer')) return GlobeAltIcon;
|
||||||
|
if (title.startsWith('Semantic Index & Search')) return MagnifyingGlassIcon;
|
||||||
|
return GlobeAltIcon; // default
|
||||||
|
}
|
||||||
|
|
||||||
|
function Review({
|
||||||
|
title,
|
||||||
|
body,
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: Omit<React.ComponentPropsWithoutRef<'figure'>, keyof Review> & Review) {
|
||||||
|
let animationDelay = useMemo(() => {
|
||||||
|
let possibleAnimationDelays = ['0s', '0.1s', '0.2s', '0.3s', '0.4s', '0.5s']
|
||||||
|
return possibleAnimationDelays[
|
||||||
|
Math.floor(Math.random() * possibleAnimationDelays.length)
|
||||||
|
]
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<figure
|
||||||
|
className={clsx(
|
||||||
|
'animate-fade-in rounded-3xl bg-white p-6 opacity-0 shadow-md shadow-gray-900/5',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
style={{ animationDelay }}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<blockquote className="text-gray-900">
|
||||||
|
{React.createElement(getReviewIcon(title), { className: "h-6 w-6 text-[#2F3178] mb-2" })}
|
||||||
|
<CT color="primary" className="mt-4 text-lg/6 font-semibold">
|
||||||
|
{title}
|
||||||
|
</CT>
|
||||||
|
<CP color="custom" className="mt-3 text-sm">{body}</CP>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
</figure>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function splitArray<T>(array: Array<T>, numParts: number) {
|
||||||
|
let result: Array<Array<T>> = []
|
||||||
|
for (let i = 0; i < array.length; i++) {
|
||||||
|
let index = i % numParts
|
||||||
|
if (!result[index]) {
|
||||||
|
result[index] = []
|
||||||
|
}
|
||||||
|
result[index].push(array[i])
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
function ReviewColumn({
|
||||||
|
reviews,
|
||||||
|
className,
|
||||||
|
reviewClassName,
|
||||||
|
msPerPixel = 0,
|
||||||
|
}: {
|
||||||
|
reviews: Array<Review>
|
||||||
|
className?: string
|
||||||
|
reviewClassName?: (reviewIndex: number) => string
|
||||||
|
msPerPixel?: number
|
||||||
|
}) {
|
||||||
|
let columnRef = useRef<React.ElementRef<'div'>>(null)
|
||||||
|
let [columnHeight, setColumnHeight] = useState(0)
|
||||||
|
let duration = `${columnHeight * msPerPixel}ms`
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!columnRef.current) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let resizeObserver = new window.ResizeObserver(() => {
|
||||||
|
setColumnHeight(columnRef.current?.offsetHeight ?? 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
resizeObserver.observe(columnRef.current)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
resizeObserver.disconnect()
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={columnRef}
|
||||||
|
className={clsx('animate-marquee space-y-8 py-4', className)}
|
||||||
|
style={{ '--marquee-duration': duration } as React.CSSProperties}
|
||||||
|
>
|
||||||
|
{reviews.concat(reviews).map((review, reviewIndex) => (
|
||||||
|
<Review
|
||||||
|
key={reviewIndex}
|
||||||
|
aria-hidden={reviewIndex >= reviews.length}
|
||||||
|
className={reviewClassName?.(reviewIndex % reviews.length)}
|
||||||
|
{...review}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ReviewGrid() {
|
||||||
|
let containerRef = useRef<React.ElementRef<'div'>>(null)
|
||||||
|
let isInView = useInView(containerRef, { once: true, amount: 0.4 })
|
||||||
|
let columns = splitArray(reviews, 3)
|
||||||
|
let column1 = columns[0]
|
||||||
|
let column2 = columns[1]
|
||||||
|
let column3 = splitArray(columns[2], 2)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={containerRef}
|
||||||
|
className="relative -mx-4 mt-0 grid h-196 max-h-[150vh] grid-cols-1 items-start gap-8 overflow-hidden px-4 sm:mt-20 md:grid-cols-2 lg:grid-cols-3"
|
||||||
|
>
|
||||||
|
{isInView && (
|
||||||
|
<>
|
||||||
|
<ReviewColumn
|
||||||
|
reviews={[...column1, ...column3.flat(), ...column2]}
|
||||||
|
reviewClassName={(reviewIndex) =>
|
||||||
|
clsx(
|
||||||
|
reviewIndex >= column1.length + column3[0].length &&
|
||||||
|
'md:hidden',
|
||||||
|
reviewIndex >= column1.length && 'lg:hidden',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
msPerPixel={10}
|
||||||
|
/>
|
||||||
|
<ReviewColumn
|
||||||
|
reviews={[...column2, ...column3[1]]}
|
||||||
|
className="hidden md:block"
|
||||||
|
reviewClassName={(reviewIndex) =>
|
||||||
|
reviewIndex >= column2.length ? 'lg:hidden' : ''
|
||||||
|
}
|
||||||
|
msPerPixel={15}
|
||||||
|
/>
|
||||||
|
<ReviewColumn
|
||||||
|
reviews={column3.flat()}
|
||||||
|
className="hidden lg:block"
|
||||||
|
msPerPixel={10}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<div className="pointer-events-none absolute inset-x-0 top-0 h-32 bg-linear-to-b from-white" />
|
||||||
|
<div className="pointer-events-none absolute inset-x-0 bottom-0 h-32 bg-linear-to-t from-white" />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function UseCases() {
|
||||||
|
const ref = useRef(null);
|
||||||
|
const isInView = useInView(ref, { once: true });
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
id="usecases"
|
||||||
|
ref={ref}
|
||||||
|
aria-labelledby="usecases-title"
|
||||||
|
className="py-12"
|
||||||
|
>
|
||||||
|
<Container className=''>
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
||||||
|
transition={{ duration: 0.8, delay: 0.1 }}
|
||||||
|
className="mx-auto max-w-2xl lg:max-w-5xl"
|
||||||
|
>
|
||||||
|
<H2
|
||||||
|
id="usecases-title"
|
||||||
|
color="primary"
|
||||||
|
className="text-center"
|
||||||
|
>
|
||||||
|
Coming Soon: The Future of Mycelium
|
||||||
|
</H2>
|
||||||
|
<P className="mt-6 text-center" color="custom">
|
||||||
|
Mycelium Cloud is evolving to bring even more powerful decentralized features, designed to enhance your experience and expand possibilities. Be the first to explore what's coming next by staying connected with our latest updates.
|
||||||
|
</P>
|
||||||
|
</motion.div>
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
||||||
|
transition={{ duration: 1, delay: 0.2 }}
|
||||||
|
aria-hidden="true"
|
||||||
|
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
clipPath:
|
||||||
|
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
||||||
|
}}
|
||||||
|
className="relative left-[calc(50%-30rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#93c5fd] to-[#9089fc] opacity-30 sm:left-[calc(50%-36rem)] sm:w-[72.1875rem]"
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
<ReviewGrid />
|
||||||
|
</Container>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
111
src/components/Archives/WorldMap.tsx
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import { Globe } from "@/components/ui/globe"
|
||||||
|
import { motion } from "framer-motion"
|
||||||
|
import { H2, H4, CP, CT } from "@/components/Texts"
|
||||||
|
|
||||||
|
export function WorldMap() {
|
||||||
|
return (
|
||||||
|
<div className="relative h-screen max-w-full overflow-hidden -top-20">
|
||||||
|
{/* Background video */}
|
||||||
|
<video
|
||||||
|
autoPlay
|
||||||
|
loop
|
||||||
|
muted
|
||||||
|
playsInline
|
||||||
|
className="absolute inset-0 w-full h-full object-cover"
|
||||||
|
>
|
||||||
|
<source src="/videos/benefits.mp4" type="video/mp4" />
|
||||||
|
</video>
|
||||||
|
|
||||||
|
{/* Dark overlay */}
|
||||||
|
<div className="absolute inset-0 bg-black/60" />
|
||||||
|
|
||||||
|
{/* Top Left Intro Text */}
|
||||||
|
<div className="absolute top-0 left-0 px-6 py-24 z-10 max-w-lg">
|
||||||
|
<H4 color="light">Mycelium Network is Live.</H4>
|
||||||
|
<CP className="hidden mt-6 text-base leading-relaxed font-light" color="light">
|
||||||
|
Mycelium Cloud's advancement technology enables anyone to deploy
|
||||||
|
their own Internet infrastructure, anywhere.
|
||||||
|
</CP>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Globe Centered */}
|
||||||
|
<div className="absolute inset-0 flex items-center justify-center">
|
||||||
|
<Globe className="top-28" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right Side Stats Column */}
|
||||||
|
<div className="absolute right-0 top-0 bottom-0 flex flex-col justify-center gap-6 px-6 py-12 max-w-xs z-10">
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: 50 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.6, delay: 0.1 }}
|
||||||
|
className="rounded-2xl bg-white/5 backdrop-blur-md border border-white/10 p-4 shadow-md"
|
||||||
|
>
|
||||||
|
<CT color="light" className="uppercase tracking-wide">
|
||||||
|
CORES
|
||||||
|
</CT>
|
||||||
|
<H2 color="light" className="mt-2 text-3xl font-bold">
|
||||||
|
54,958
|
||||||
|
</H2>
|
||||||
|
<CP color="light" className="mt-2 text-sm">
|
||||||
|
Total Central Processing Unit Cores available on the grid.
|
||||||
|
</CP>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: 50 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.6, delay: 0.2 }}
|
||||||
|
className="rounded-2xl bg-white/5 backdrop-blur-md border border-white/10 p-4 shadow-md"
|
||||||
|
>
|
||||||
|
<CT color="light" className="uppercase tracking-wide">
|
||||||
|
NODES
|
||||||
|
</CT>
|
||||||
|
<H2 color="light" className="mt-2 text-3xl font-bold">
|
||||||
|
54,958
|
||||||
|
</H2>
|
||||||
|
<CP color="light" className="mt-2 text-sm">
|
||||||
|
Total number of nodes on the grid.
|
||||||
|
</CP>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: 50 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.6, delay: 0.3 }}
|
||||||
|
className="rounded-2xl bg-white/5 backdrop-blur-md border border-white/10 p-4 shadow-md"
|
||||||
|
>
|
||||||
|
<CT color="light" className="uppercase tracking-wide">
|
||||||
|
SSD CAPACITY
|
||||||
|
</CT>
|
||||||
|
<H2 color="light" className="mt-2 text-3xl font-bold">
|
||||||
|
54,958
|
||||||
|
</H2>
|
||||||
|
<CP color="light" className="mt-2 text-sm">
|
||||||
|
Total amount of storage (SSD, HDD, & RAM) on the grid.
|
||||||
|
</CP>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: 50 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.6, delay: 0.4 }}
|
||||||
|
className="rounded-2xl bg-white/5 backdrop-blur-md border border-white/10 p-4 shadow-md"
|
||||||
|
>
|
||||||
|
<CT color="light" className="uppercase tracking-wide">
|
||||||
|
COUNTRIES
|
||||||
|
</CT>
|
||||||
|
<H2 color="light" className="mt-2 text-3xl font-bold">
|
||||||
|
51
|
||||||
|
</H2>
|
||||||
|
<CP color="light" className="mt-2 text-sm">
|
||||||
|
Total number of countries with active nodes.
|
||||||
|
</CP>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Radial fade overlay */}
|
||||||
|
<div className="pointer-events-none absolute inset-0 h-full bg-[radial-gradient(circle_at_50%_200%,rgba(0,0,0,0.2),rgba(255,255,255,0))]" />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
170
src/components/BentoReviews.tsx
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { H2, P } from "@/components/Texts";
|
||||||
|
import React, { useState, useEffect, useRef } from "react";
|
||||||
|
import { BentoGrid, MotionBentoGridItem } from "@/components/ui/bento-grid";
|
||||||
|
import { AnimatePresence, motion } from "framer-motion";
|
||||||
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
|
import { FadeIn } from "./FadeIn";
|
||||||
|
|
||||||
|
const items = [
|
||||||
|
{
|
||||||
|
title: 'FungiStor',
|
||||||
|
subtitle: 'Long-Term AI Memory',
|
||||||
|
description: 'Erasure coding + compression slash storage bloat by up to 10× vs basic replication. Source-encrypted shards are geo-dispersed—lose pieces, rebuild perfectly from a quorum.',
|
||||||
|
video: "/videos/fungistor.mp4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'HeroDB',
|
||||||
|
subtitle: 'Active AI Memory',
|
||||||
|
description: 'Multimodal vector+keyword retrieval makes RAG feel instant across text, image, audio. Time-aware, policy-guarded context keeps results fresh while access stays governed.',
|
||||||
|
video: "/videos/herodb.mp4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'MOS Sandboxes',
|
||||||
|
subtitle: 'Secure Agent Workspaces',
|
||||||
|
description: 'Attested, signed workspaces spin up ≈5s worldwide—ready to execute. Hardware isolation and scoped egress: run hard, tear down clean, zero residue.',
|
||||||
|
video: "/videos/sandbox.mp4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Mycelium Mesh',
|
||||||
|
subtitle: 'Secure Communication Network',
|
||||||
|
description: 'A private, public-key fabric with self-healing multi-path routing. Glides through NATs and firewalls—direct, low-latency, no middlemen.',
|
||||||
|
video: "/videos/mesh.mp4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Deterministic Deployment',
|
||||||
|
subtitle: 'Verifiable Code Execution',
|
||||||
|
description: 'Declare intent, get a hash; remote attestation proves that’s what runs. Reproducible builds, signed artifacts, immutable logs—supply chain, sealed.',
|
||||||
|
video: "/videos/deterministic.mp4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Agent Coordination',
|
||||||
|
subtitle: 'Sovereign Workflow Management',
|
||||||
|
description: 'Your private agent conducts swarms of specialists in parallel. Policies fan out work; human checkpoints keep you in command.',
|
||||||
|
video: "/videos/agent.mp4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Universal Interface Layer',
|
||||||
|
subtitle: 'AI Service Gateway',
|
||||||
|
description: 'One gateway to open-source LLMs, tools, APIs, and data—bring your own models & keys. Semantic retrieval, function calling, and metered micropayments built in.',
|
||||||
|
video: "/videos/universal.mp4",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export function BentoReviews() {
|
||||||
|
const [activeIndex, setActiveIndex] = useState(0);
|
||||||
|
const [isPaused, setIsPaused] = useState(false);
|
||||||
|
const intervalRef = useRef<NodeJS.Timeout | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isPaused) {
|
||||||
|
intervalRef.current = setInterval(() => {
|
||||||
|
setActiveIndex((prevIndex) => (prevIndex + 1) % items.length);
|
||||||
|
}, 3000);
|
||||||
|
} else {
|
||||||
|
if (intervalRef.current) {
|
||||||
|
clearInterval(intervalRef.current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (intervalRef.current) {
|
||||||
|
clearInterval(intervalRef.current);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [isPaused]);
|
||||||
|
|
||||||
|
const handleCardTap = () => {
|
||||||
|
setIsPaused(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePrev = () => {
|
||||||
|
setActiveIndex((prevIndex) => (prevIndex - 1 + items.length) % items.length);
|
||||||
|
setIsPaused(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNext = () => {
|
||||||
|
setActiveIndex((prevIndex) => (prevIndex + 1) % items.length);
|
||||||
|
setIsPaused(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="relative isolate py-24 bg-black text-center w-full lg:px-0 px-4">
|
||||||
|
<FadeIn transition={{ duration: 0.8, delay: 0.1 }}>
|
||||||
|
<div className="mx-auto max-w-5xl ">
|
||||||
|
<H2 className="text-center">Augmented Intelligence Fabric</H2>
|
||||||
|
</div>
|
||||||
|
</FadeIn>
|
||||||
|
<FadeIn transition={{ duration: 0.8, delay: 0.2 }}>
|
||||||
|
<div className="mx-auto max-w-4xl mt-6 mb-8">
|
||||||
|
<P className="text-center" color="primary">
|
||||||
|
The sovereign substrate for autonomous AI. Stateless, geo-aware, end-to-end encrypted—and verifiable from intent to execution.
|
||||||
|
</P>
|
||||||
|
</div>
|
||||||
|
</FadeIn>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Desktop Grid */}
|
||||||
|
<div className="hidden lg:block">
|
||||||
|
<BentoGrid className="max-w-8xl lg:px-12 px-4 pb-12 lg:grid-cols-3">
|
||||||
|
{items.map((item, i) => (
|
||||||
|
<MotionBentoGridItem
|
||||||
|
key={i}
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
viewport={{ once: false, margin: '0px 0px -100px 0px' }}
|
||||||
|
transition={{ duration: 0.8, delay: 0.3 + i * 0.1 }}
|
||||||
|
className={cn(i === 3 || i === 6 ? "md:col-span-2" : "")}
|
||||||
|
rowHeight={i >= 3 ? "h-[22rem]" : ""}
|
||||||
|
title={item.title}
|
||||||
|
subtitle={item.subtitle}
|
||||||
|
description={item.description}
|
||||||
|
video={item.video}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</BentoGrid>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile Carousel */}
|
||||||
|
<div className="lg:hidden block px-4 pb-12">
|
||||||
|
<div className="relative h-[24rem] w-full overflow-hidden">
|
||||||
|
<div className="absolute inset-0" onTouchStart={handleCardTap} />
|
||||||
|
<AnimatePresence initial={false}>
|
||||||
|
<motion.div
|
||||||
|
key={activeIndex}
|
||||||
|
className="absolute h-full w-full"
|
||||||
|
initial={{ x: "100%", opacity: 0 }}
|
||||||
|
animate={{ x: 0, opacity: 1 }}
|
||||||
|
exit={{ x: "-100%", opacity: 0 }}
|
||||||
|
transition={{ type: "spring", stiffness: 300, damping: 30 }}
|
||||||
|
>
|
||||||
|
<MotionBentoGridItem
|
||||||
|
className="h-full"
|
||||||
|
title={items[activeIndex].title}
|
||||||
|
subtitle={items[activeIndex].subtitle}
|
||||||
|
description={items[activeIndex].description}
|
||||||
|
video={items[activeIndex].video}
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
</AnimatePresence>
|
||||||
|
<button
|
||||||
|
onClick={handlePrev}
|
||||||
|
className="absolute left-2 top-[58%] -translate-y-1/2 rounded-full bg-black/50 p-2 text-white z-10"
|
||||||
|
>
|
||||||
|
<ChevronLeft className="h-6 w-6" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={handleNext}
|
||||||
|
className="absolute right-2 top-[58%] -translate-y-1/2 rounded-full bg-black/50 p-2 text-white z-10"
|
||||||
|
>
|
||||||
|
<ChevronRight className="h-6 w-6" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -5,18 +5,19 @@ const baseStyles = {
|
|||||||
solid:
|
solid:
|
||||||
'inline-flex justify-center rounded-lg py-2 px-3 text-sm font-semibold transition-colors',
|
'inline-flex justify-center rounded-lg py-2 px-3 text-sm font-semibold transition-colors',
|
||||||
outline:
|
outline:
|
||||||
'inline-flex justify-center rounded-lg border py-[calc(--spacing(2)-1px)] px-[calc(--spacing(3)-1px)] text-sm transition-colors',
|
'inline-flex justify-center rounded-lg border py-[calc(theme(spacing.2)-1px)] px-[calc(theme(spacing.3)-1px)] text-sm transition-colors',
|
||||||
}
|
}
|
||||||
|
|
||||||
const variantStyles = {
|
const variantStyles = {
|
||||||
solid: {
|
solid: {
|
||||||
cyan: 'relative overflow-hidden bg-[#2F3178] text-white before:absolute before:inset-0 active:before:bg-transparent hover:before:bg-white/10 active:bg-[#2F3178] active:text-white/80 before:transition-colors',
|
cyan: 'relative overflow-hidden bg-[#005eff] text-white before:absolute before:inset-0 active:before:bg-transparent hover:before:bg-white/10 active:bg-[#005eff] active:text-white/80 before:transition-colors',
|
||||||
white:
|
white:
|
||||||
'bg-white text-cyan-900 hover:bg-white/90 active:bg-white/90 active:text-cyan-900/70',
|
'bg-white text-cyan-900 hover:bg-white/90 active:bg-white/90 active:text-cyan-900/70',
|
||||||
gray: 'bg-gray-800 text-white hover:bg-gray-900 active:bg-gray-800 active:text-white/80',
|
gray: 'bg-gray-800 text-white hover:bg-gray-900 active:bg-gray-800 active:text-white/80',
|
||||||
},
|
},
|
||||||
outline: {
|
outline: {
|
||||||
gray: 'border-gray-300 text-gray-700 hover:border-gray-400 active:bg-gray-100 active:text-gray-700/80',
|
gray: 'border-gray-300 text-gray-700 hover:border-gray-400 active:bg-gray-100 active:text-gray-700/80',
|
||||||
|
white: 'border-gray-300 text-white hover:border-gray-400 hover:text-gray-300 active:bg-gray-100 active:text-gray-800',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
import { H2, P } from '@/components/Texts'
|
import { H2, P } from '@/components/Texts'
|
||||||
|
|
||||||
export function CallTo() {
|
export function CallTo() {
|
||||||
@@ -6,19 +8,24 @@ export function CallTo() {
|
|||||||
<div className="relative isolate overflow-hidden bg-gray-50/10 px-6 py-24 text-center shadow-md shadow-gray-900/5 sm:rounded-3xl sm:px-16 border border-gray-200">
|
<div className="relative isolate overflow-hidden bg-gray-50/10 px-6 py-24 text-center shadow-md shadow-gray-900/5 sm:rounded-3xl sm:px-16 border border-gray-200">
|
||||||
<div className="mx-auto max-w-4xl text-center">
|
<div className="mx-auto max-w-4xl text-center">
|
||||||
<H2 color="primary">
|
<H2 color="primary">
|
||||||
Say hello to Decentralized AI Agents that are Truly Yours
|
Are you Ready?
|
||||||
</H2>
|
</H2>
|
||||||
<P color="custom" className="mt-8 max-w-3xl">
|
<P color="custom" className="mt-8 max-w-3xl">
|
||||||
Why hand out your intelligence to centralized giants when you can build your own?
|
Why hand out your intelligence to centralized giants when you can build your own?
|
||||||
</P>
|
</P>
|
||||||
<div className="mt-10 flex items-center justify-center gap-x-6">
|
<div className="mt-10 flex items-center justify-center gap-x-6">
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="https://calendly.com/sachao/30min"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
className="rounded-md bg-[#2F3178] px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-[#2F3178]/80 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#2F3178]"
|
className="rounded-md bg-[#2F3178] px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-[#2F3178]/80 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#2F3178]"
|
||||||
>
|
>
|
||||||
Book a Meeting
|
Book a Meeting
|
||||||
</a>
|
</a>
|
||||||
<a href="#" className="text-sm/6 font-semibold text-[#2F3178] hover:text-[#2F3178]/80">
|
<a
|
||||||
|
href="mailto:info@ourworld.tf"
|
||||||
|
className="text-sm/6 font-semibold text-[#2F3178] hover:text-[#2F3178]/80"
|
||||||
|
>
|
||||||
Join the Waitlist <span aria-hidden="true">→</span>
|
Join the Waitlist <span aria-hidden="true">→</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
60
src/components/CallToAction.tsx
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { CircleBackground } from '@/components/CircleBackground'
|
||||||
|
import { Container } from '@/components/Container'
|
||||||
|
import { Button } from '@/components/Button'
|
||||||
|
import { FadeIn } from '@/components/FadeIn'
|
||||||
|
|
||||||
|
export function CallToAction() {
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
id="get-free-shares-today"
|
||||||
|
className="relative overflow-hidden py-20 sm:py-28 border-t border-gray-800"
|
||||||
|
>
|
||||||
|
<video
|
||||||
|
autoPlay
|
||||||
|
loop
|
||||||
|
muted
|
||||||
|
playsInline
|
||||||
|
className="absolute top-0 left-0 w-full h-full object-cover z-0"
|
||||||
|
>
|
||||||
|
<source src="/videos/cta.mp4" type="video/mp4" />
|
||||||
|
</video>
|
||||||
|
<div className="absolute top-0 left-0 w-full h-full bg-black opacity-40 z-10"></div>
|
||||||
|
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 sm:left-1/2 sm:-translate-x-1/2 z-20">
|
||||||
|
<CircleBackground color="#fff" className="animate-spin-slower" />
|
||||||
|
</div>
|
||||||
|
<Container className="relative z-20">
|
||||||
|
<FadeIn>
|
||||||
|
<div className="mx-auto max-w-md text-center">
|
||||||
|
<h2 className="text-3xl font-medium tracking-tight text-white sm:text-4xl">
|
||||||
|
Decentralized AI Agents that are Truly Yours
|
||||||
|
</h2>
|
||||||
|
<p className="mt-4 text-lg text-gray-300">
|
||||||
|
Why hand out your intelligence to centralized giants when you can
|
||||||
|
build your own. Ready to own your intelligence?
|
||||||
|
</p>
|
||||||
|
<div className="mt-8 flex justify-center gap-x-6">
|
||||||
|
<Button
|
||||||
|
variant="solid"
|
||||||
|
color="cyan"
|
||||||
|
href="https://calendly.com/sachao/30min"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
Book a Meeting
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
color="white"
|
||||||
|
href="mailto:info@ourworld.tf"
|
||||||
|
>
|
||||||
|
Join the Waitlist
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</FadeIn>
|
||||||
|
</Container>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,41 +1,37 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useEffect, useMemo, useState, useRef } from 'react'
|
import { useEffect, useMemo, useState } from 'react'
|
||||||
|
import { useResponsiveCarousel } from '@/hooks/useResponsiveCarousel';
|
||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
import { motion, AnimatePresence, useInView } from 'framer-motion'
|
import { motion, AnimatePresence } from 'framer-motion'
|
||||||
import { wrap } from 'popmotion'
|
import { wrap } from 'popmotion'
|
||||||
import { Button } from '@/components/Button';
|
import { Button } from '@/components/Button';
|
||||||
import { H2, P, H4 } from '@/components/Texts';
|
import { H2, P, CT } from '@/components/Texts';
|
||||||
import { TypeAnimation } from 'react-type-animation'
|
import { TypeAnimation } from 'react-type-animation'
|
||||||
|
import { FadeIn } from './FadeIn';
|
||||||
|
|
||||||
const galleryItems = [
|
const galleryItems = [
|
||||||
{ text: 'Navigate and interact with any web interface', image: '/images/interface.png' },
|
{ text: 'Navigate and interact with any web interface', image: '/images/gallery/interface.jpg', width: 448, height: 277 },
|
||||||
{ text: 'Process documents across all formats', image: '/images/docs.png' },
|
{ text: 'Process documents across all formats', image: '/images/gallery/docs.jpg', width: 448, height: 277 },
|
||||||
{ text: 'Execute multi-step workflows autonomously', image: '/images/flow.png' },
|
{ text: 'Execute multi-step workflows autonomously', image: '/images/gallery/flow.jpg', width: 448, height: 277 },
|
||||||
{ text: 'Manage calendars, emails, and tasks', image: '/images/calendar.png' },
|
{ text: 'Manage calendars, emails, and tasks', image: '/images/gallery/calendar.jpg', width: 448, height: 277 },
|
||||||
{ text: 'Perform deep semantic search across all data sources', image: '/images/data.png' },
|
{ text: 'Perform deep semantic search across all data sources', image: '/images/gallery/data.jpg', width: 448, height: 277 },
|
||||||
{ text: 'Identify patterns in complex datasets', image: '/images/datasets.png' },
|
{ text: 'Identify patterns in complex datasets', image: '/images/gallery/datasets.jpg', width: 448, height: 277 },
|
||||||
{ text: 'Provide real-time market intelligence', image: '/images/market.png' },
|
{ text: 'Provide real-time market intelligence', image: '/images/gallery/market.jpg', width: 448, height: 277 },
|
||||||
{ text: 'Generate and debug code in multiple languages', image: '/images/code.png' },
|
{ text: 'Generate and debug code in multiple languages', image: '/images/gallery/code.jpg', width: 448, height: 277 },
|
||||||
{ text: 'Create consistent branded content', image: '/images/branding.png' },
|
{ text: 'Create consistent branded content', image: '/images/gallery/branding.jpg', width: 448, height: 277 },
|
||||||
{ text: 'Translate and localize materials', image: '/images/translate.png' },
|
{ text: 'Translate and localize materials', image: '/images/gallery/translate.jpg', width: 448, height: 277 },
|
||||||
{ text: 'Transform and migrate data structures', image: '/images/structure.png' },
|
{ text: 'Transform and migrate data structures', image: '/images/gallery/structure.jpg', width: 448, height: 277 },
|
||||||
]
|
]
|
||||||
|
|
||||||
// 🔧 Carousel Config
|
// 🔧 Carousel Config
|
||||||
const VISIBLE = 4
|
const VISIBLE = 4;
|
||||||
const CARD_SIZE = 360 // square size on desktop
|
const AUTOPLAY_MS = 3200;
|
||||||
const GAP = 300 // spacing for larger cards
|
|
||||||
const ROT_Y = 18
|
|
||||||
const DEPTH = 210
|
|
||||||
const SCALE_DROP = 0.12
|
|
||||||
const AUTOPLAY_MS = 3200
|
|
||||||
|
|
||||||
export function ClickableGallery() {
|
export function ClickableGallery() {
|
||||||
const [active, setActive] = useState(0)
|
const [active, setActive] = useState(0);
|
||||||
const [hovering, setHovering] = useState(false)
|
const [hovering, setHovering] = useState(false);
|
||||||
const ref = useRef(null);
|
const { GAP, ROT_Y, DEPTH, SCALE_DROP } = useResponsiveCarousel();
|
||||||
const isInView = useInView(ref, { once: true });
|
|
||||||
|
|
||||||
// autoplay
|
// autoplay
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -53,142 +49,132 @@ export function ClickableGallery() {
|
|||||||
const prev = () => setActive((i) => wrap(0, galleryItems.length, i - 1))
|
const prev = () => setActive((i) => wrap(0, galleryItems.length, i - 1))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref}>
|
<div>
|
||||||
<div className="relative isolate pt-24 pb-0 text-center w-full">
|
<div className="relative isolate pt-8 pb-0 bg-transparent text-center w-full">
|
||||||
<motion.div initial={{ opacity: 0, y: 20 }} animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }} transition={{ duration: 0.8, delay: 0.1 }} className="mx-auto max-w-5xl">
|
<FadeIn transition={{ duration: 0.8, delay: 0.1 }}>
|
||||||
<H2 className="text-center">One Agent, Endless Possibilities.</H2>
|
<div className="mx-auto max-w-5xl lg:mt-12">
|
||||||
</motion.div>
|
<H2 className="text-center">Agents with Endless Possibilities.</H2>
|
||||||
<motion.div initial={{ opacity: 0, y: 20 }} animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }} transition={{ duration: 0.8, delay: 0.2 }} className="mx-auto max-w-4xl mt-6">
|
</div>
|
||||||
<P className="text-center" color="custom">
|
</FadeIn>
|
||||||
The future isn’t about more tools. It’s about one intelligent partner that can do it all. This is your gateway to creativity, automation, and discovery.
|
<FadeIn transition={{ duration: 0.8, delay: 0.2 }}>
|
||||||
</P>
|
<div className="mx-auto max-w-4xl mt-6 lg:px-0 px-4">
|
||||||
</motion.div>
|
<P className="text-center" color="primary">
|
||||||
<motion.div
|
Your private agent coordinates a team of specialists that spin up on demand, collaborate across your world, and deliver end-to-end results.
|
||||||
initial={{ opacity: 0 }}
|
Many agents, one intelligence—yours.
|
||||||
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
</P>
|
||||||
transition={{ duration: 1, delay: 0.3 }}
|
</div>
|
||||||
aria-hidden="true"
|
</FadeIn>
|
||||||
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
|
</div>
|
||||||
|
<FadeIn transition={{ duration: 1, delay: 0.4 }}>
|
||||||
|
<section
|
||||||
|
className="relative w-full flex items-center justify-center overflow-hidden bg-transparent -mt-8 pt-0 pb-0"
|
||||||
|
onMouseEnter={() => setHovering(true)}
|
||||||
|
onMouseLeave={() => setHovering(false)}
|
||||||
>
|
>
|
||||||
<div
|
<div className="relative w-full max-w-[1800px] h-[300px] md:h-[500px]" style={{ perspective: '1600px' }}>
|
||||||
style={{
|
<div className="absolute inset-0" style={{ transformStyle: 'preserve-3d' }}>
|
||||||
clipPath:
|
<AnimatePresence initial={false}>
|
||||||
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
{indices.map((idx, i) => {
|
||||||
}}
|
const distance = i - VISIBLE;
|
||||||
className="relative left-[calc(50%-30rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#93c5fd] to-[#9089fc] opacity-30 sm:left-[calc(50%-36rem)] sm:w-[72.1875rem]"
|
const item = galleryItems[idx];
|
||||||
/>
|
|
||||||
</motion.div>
|
|
||||||
</div>
|
|
||||||
<motion.section
|
|
||||||
initial={{ opacity: 0 }}
|
|
||||||
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
|
||||||
transition={{ duration: 1, delay: 0.4 }}
|
|
||||||
className="relative w-full flex items-center justify-center overflow-hidden bg-background -mt-16 pt-0 pb-32"
|
|
||||||
onMouseEnter={() => setHovering(true)}
|
|
||||||
onMouseLeave={() => setHovering(false)}
|
|
||||||
>
|
|
||||||
{/* Soft edge fades */}
|
|
||||||
<div className="pointer-events-none absolute inset-y-0 left-0 w-32 bg-gradient-to-r from-background to-transparent" />
|
|
||||||
<div className="pointer-events-none absolute inset-y-0 right-0 w-32 bg-gradient-to-l from-background to-transparent" />
|
|
||||||
|
|
||||||
<div className="relative w-full max-w-[1800px] h-[500px]" style={{ perspective: '1600px' }}>
|
const x = distance * GAP;
|
||||||
<div
|
const z = -Math.abs(distance) * DEPTH;
|
||||||
aria-hidden="true"
|
const r = distance * ROT_Y;
|
||||||
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
|
const s = 1 - Math.abs(distance) * SCALE_DROP;
|
||||||
>
|
const o = distance === 0 ? 1 : 0.80;
|
||||||
<div
|
const zIndex = 100 - Math.abs(distance);
|
||||||
style={{
|
|
||||||
clipPath:
|
return (
|
||||||
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
<motion.div
|
||||||
}}
|
key={`${idx}-${i}`}
|
||||||
className="relative left-[calc(50%+4rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#93c5fd] to-[#9089fc] opacity-30 sm:left-[calc(50%+60rem)] sm:w-[72.1875rem]"
|
className={`absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 will-change-transform overflow-hidden ${distance === 0 ? 'rounded-xl' : ''}`}
|
||||||
/>
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{
|
||||||
|
transform: `translateX(${x}px) translateZ(${z}px) rotateY(${r}deg) scale(${s})`,
|
||||||
|
zIndex,
|
||||||
|
opacity: o,
|
||||||
|
boxShadow: distance === 0 ? '0 0 20px 5px rgba(255, 255, 255, 0.2)' : 'none',
|
||||||
|
}}
|
||||||
|
exit={{ opacity: 0 }}
|
||||||
|
transition={{ type: 'spring', stiffness: 220, damping: 26 }}
|
||||||
|
onClick={() => setActive(idx)}
|
||||||
|
>
|
||||||
|
<div className="relative bg-black flex items-center justify-center">
|
||||||
|
<Image
|
||||||
|
src={item.image}
|
||||||
|
alt={item.text}
|
||||||
|
width={item.width}
|
||||||
|
height={item.height}
|
||||||
|
className="object-contain text-white"
|
||||||
|
priority={i === VISIBLE}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</AnimatePresence>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="absolute inset-0" style={{ transformStyle: 'preserve-3d' }}>
|
|
||||||
<AnimatePresence initial={false}>
|
|
||||||
{indices.map((idx, i) => {
|
|
||||||
const distance = i - VISIBLE
|
|
||||||
const item = galleryItems[idx]
|
|
||||||
|
|
||||||
const x = distance * GAP
|
{/* Arrows */}
|
||||||
const z = -Math.abs(distance) * DEPTH
|
{/* Arrows */}
|
||||||
const r = distance * ROT_Y
|
<div className="absolute inset-y-0 left-8 hidden md:flex items-center z-50">
|
||||||
const s = 1 - Math.abs(distance) * SCALE_DROP
|
<button
|
||||||
const o = distance === 0 ? 1 : 0.90
|
onClick={prev}
|
||||||
const zIndex = 100 - Math.abs(distance)
|
className="bg-transparent rounded-full p-2 shadow-lg backdrop-blur-md"
|
||||||
|
aria-label="Previous"
|
||||||
return (
|
>
|
||||||
<motion.div
|
<svg className="size-8" viewBox="0 0 24 24" fill="none" dangerouslySetInnerHTML={{ __html: '<path d="M15 19L8 12l7-7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>' }} />
|
||||||
key={`${idx}-${i}`}
|
</button>
|
||||||
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 will-change-transform"
|
|
||||||
initial={{ opacity: 0 }}
|
|
||||||
animate={{
|
|
||||||
transform: `translateX(${x}px) translateZ(${z}px) rotateY(${r}deg) scale(${s})`,
|
|
||||||
zIndex,
|
|
||||||
opacity: o,
|
|
||||||
}}
|
|
||||||
exit={{ opacity: 0 }}
|
|
||||||
transition={{ type: 'spring', stiffness: 220, damping: 26 }}
|
|
||||||
onClick={() => setActive(idx)}
|
|
||||||
>
|
|
||||||
{/* Square container, keeps image ratio inside */}
|
|
||||||
<div
|
|
||||||
className="relative rounded-2xl overflow-hidden bg-white flex items-center justify-center"
|
|
||||||
style={{ width: CARD_SIZE, height: CARD_SIZE }}
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
src={item.image}
|
|
||||||
alt={item.text}
|
|
||||||
fill
|
|
||||||
className="object-contain rounded-2xl"
|
|
||||||
priority={i === VISIBLE}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</motion.div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</AnimatePresence>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Arrows */}
|
|
||||||
<div className="absolute inset-y-0 left-8 flex items-center z-50">
|
|
||||||
<button
|
|
||||||
onClick={prev}
|
|
||||||
className="bg-white/70 hover:bg-white rounded-full p-3 shadow-lg backdrop-blur-md"
|
|
||||||
aria-label="Previous"
|
|
||||||
>
|
|
||||||
<svg className="size-8" viewBox="0 0 24 24" fill="none" dangerouslySetInnerHTML={{ __html: '<path d="M15 19L8 12l7-7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>' }} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div className="absolute inset-y-0 right-8 flex items-center z-50">
|
|
||||||
<button
|
|
||||||
onClick={next}
|
|
||||||
className="bg-white/70 hover:bg-white rounded-full p-3 shadow-lg backdrop-blur-md"
|
|
||||||
aria-label="Next"
|
|
||||||
>
|
|
||||||
<svg className="size-8" viewBox="0 0 24 24" fill="none" dangerouslySetInnerHTML={{ __html: '<path d="M9 5l7 7-7 7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>' }} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Foreground pill */}
|
|
||||||
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-[60]">
|
|
||||||
<div className="flex items-center justify-between w-[1040px] gap-6 rounded-3xl bg-white/95 shadow-[0_8px_40px_rgba(0,0,0,0.15)] px-12 py-6 backdrop-blur">
|
|
||||||
<H4 as="h4" className="max-w-[820px] h-[72px]">
|
|
||||||
<TypeAnimation
|
|
||||||
key={active}
|
|
||||||
sequence={[galleryItems[active].text]}
|
|
||||||
wrapper="span"
|
|
||||||
speed={50}
|
|
||||||
repeat={0}
|
|
||||||
/>
|
|
||||||
</H4>
|
|
||||||
<Button href="#" color="cyan" className="text-sm px-4 py-2 lg:text-base">
|
|
||||||
Start
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className="absolute inset-y-0 right-8 hidden md:flex items-center z-50">
|
||||||
|
<button
|
||||||
|
onClick={next}
|
||||||
|
className="bg-transparent rounded-full p-2 shadow-lg backdrop-blur-md"
|
||||||
|
aria-label="Next"
|
||||||
|
>
|
||||||
|
<svg className="size-8" viewBox="0 0 24 24" fill="none" dangerouslySetInnerHTML={{ __html: '<path d="M9 5l7 7-7 7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>' }} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Foreground pill (Desktop) */}
|
||||||
|
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-[60] hidden md:block">
|
||||||
|
<div className="flex items-center justify-between w-[1040px] gap-6 rounded-2xl bg-black/30 shadow-[0_8px_40px_rgba(0,0,0,0.15)] px-12 backdrop-blur">
|
||||||
|
<CT as="h4" className="max-w-[820px] h-[72px] text-white flex items-center">
|
||||||
|
<TypeAnimation
|
||||||
|
key={active}
|
||||||
|
sequence={[galleryItems[active].text]}
|
||||||
|
wrapper="span"
|
||||||
|
speed={50}
|
||||||
|
repeat={0}
|
||||||
|
/>
|
||||||
|
</CT>
|
||||||
|
<Button href="#" color="cyan" className="text-sm px-4 py-2 lg:text-base whitespace-nowrap">
|
||||||
|
Start
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Text box (Mobile) */}
|
||||||
|
<div className="md:hidden w-full px-4 -mt-12 mb-16">
|
||||||
|
<div className="flex flex-row items-center justify-between w-full gap-x-4 rounded-2xl bg-white/10 bg-opacity-80 p-4 backdrop-blur-md">
|
||||||
|
<CT as="h4" className="w-full text-left h-[72px] text-white leading-tight flex items-center">
|
||||||
|
<TypeAnimation
|
||||||
|
key={active}
|
||||||
|
sequence={[galleryItems[active].text]}
|
||||||
|
wrapper="span"
|
||||||
|
speed={50}
|
||||||
|
repeat={0}
|
||||||
|
/>
|
||||||
|
</CT>
|
||||||
|
<Button href="#" color="cyan" className="text-xs px-3 py-1.5 whitespace-nowrap">
|
||||||
|
Start
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</FadeIn>
|
||||||
</motion.section>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { H2, P } from '@/components/Texts';
|
import { H2, P } from '@/components/Texts';
|
||||||
|
import { InfiniteMovingCards } from "@/components/magicui/infinite-moving-cards";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -15,76 +16,58 @@ import DeepMind from '@/components/logos/DeepMind';
|
|||||||
import Minimax from '@/components/logos/Minimax';
|
import Minimax from '@/components/logos/Minimax';
|
||||||
import Mistral from '@/components/logos/Mistral';
|
import Mistral from '@/components/logos/Mistral';
|
||||||
import Moonshot from '@/components/logos/Moonshot';
|
import Moonshot from '@/components/logos/Moonshot';
|
||||||
import AlibabaCloud from '@/components/logos/AlibabaCloud';
|
|
||||||
import TencentCloud from '@/components/logos/TencentCloud';
|
import TencentCloud from '@/components/logos/TencentCloud';
|
||||||
import OpenAI from '@/components/logos/OpenAI';
|
import OpenAI from '@/components/logos/OpenAI';
|
||||||
import XAI from '@/components/logos/XAI';
|
import XAI from '@/components/logos/XAI';
|
||||||
|
|
||||||
const row1 = [Ai21, Claude, BaiduCloud, ByteDance];
|
const logos = [
|
||||||
const row2 = [DeepSeek, DeepMind, Minimax, Mistral];
|
<Ai21 key="ai21" />,
|
||||||
const row3 = [Moonshot, AlibabaCloud];
|
<Claude key="claude" />,
|
||||||
const row4 = [TencentCloud, OpenAI, XAI];
|
<BaiduCloud key="baidu" />,
|
||||||
|
<ByteDance key="bytedance" />,
|
||||||
|
<DeepSeek key="deepseek" />,
|
||||||
|
<DeepMind key="deepmind" />,
|
||||||
|
<Minimax key="minimax" />,
|
||||||
|
<Mistral key="mistral" />,
|
||||||
|
<Moonshot key="moonshot" />,
|
||||||
|
<TencentCloud key="tencent" />,
|
||||||
|
<OpenAI key="openai" />,
|
||||||
|
<XAI key="xai" />,
|
||||||
|
];
|
||||||
|
|
||||||
|
const row1 = logos.slice(0, 6);
|
||||||
|
const row2 = logos.slice(6);
|
||||||
|
|
||||||
export function Companies() {
|
export function Companies() {
|
||||||
return (
|
return (
|
||||||
<div id="companies" className="relative flex h-screen w-full overflow-hidden rounded-md bg-transparent antialiased md:items-center md:justify-center">
|
<div id="companies" className="relative bg-black flex flex-col items-center justify-center w-full overflow-hidden antialiased py-4 mb-12">
|
||||||
<div className="relative z-10 mx-auto w-full max-w-6xl p-4 py-12">
|
<div className="relative z-10 mx-auto w-full max-w-6xl p-4">
|
||||||
|
|
||||||
{/* Heading */}
|
{/* Heading */}
|
||||||
<motion.div
|
<motion.div
|
||||||
className="flex flex-col justify-center max-w-4xl items-center mb-6 mx-auto"
|
className="flex flex-col justify-center max-w-4xl items-center mb-8 mx-auto"
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ duration: 1 }}
|
transition={{ duration: 1 }}
|
||||||
>
|
>
|
||||||
<H2 className="text-center pb-6">
|
<P className="hidden min-xl:text-gray-100 text-center mb-6">
|
||||||
Deploy the World’s Leading AI Models
|
Mycelium Cloud allows you to deploy and scale AI agents from top global providers on a decentralized, privacy-first infrastructure.
|
||||||
</H2>
|
|
||||||
<P className="pb-8 text-center" color="custom">
|
|
||||||
Deploy and scale AI from top global providers on a decentralized, privacy-first infrastructure. Mycelium Cloud lets you integrate state-of-the-art intelligence into your workflows with full control, sovereignty, and cost efficiency.
|
|
||||||
</P>
|
</P>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Animated Line */}
|
|
||||||
<motion.div
|
|
||||||
className="h-[2px] bg-neutral-400 rounded-full mx-auto mb-12"
|
|
||||||
initial={{ width: 0 }}
|
|
||||||
animate={{ width: "100%" }}
|
|
||||||
transition={{ duration: 2, delay: 1 }}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Logos grid */}
|
{/* Logos grid */}
|
||||||
<div className="flex flex-col items-center gap-y-10">
|
<div className="flex flex-col items-center gap-y-6 text-white">
|
||||||
{[row1, row2, row3, row4].map((row, rowIndex) => (
|
<InfiniteMovingCards
|
||||||
<motion.div
|
items={row1}
|
||||||
key={rowIndex}
|
direction="right"
|
||||||
className="flex flex-wrap justify-center items-center gap-x-8 sm:gap-x-10"
|
speed="slow"
|
||||||
initial="hidden"
|
/>
|
||||||
animate="visible"
|
<InfiniteMovingCards
|
||||||
variants={{
|
className=""
|
||||||
visible: {
|
items={row2}
|
||||||
transition: {
|
direction="left"
|
||||||
staggerChildren: 0.15,
|
speed="slow"
|
||||||
delayChildren: 2.8 + rowIndex * 0.5, // Stagger rows
|
/>
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{row.map((Logo, i) => (
|
|
||||||
<motion.div
|
|
||||||
key={i}
|
|
||||||
className="flex justify-center"
|
|
||||||
variants={{
|
|
||||||
hidden: { opacity: 0, y: 30 },
|
|
||||||
visible: { opacity: 1, y: 0 },
|
|
||||||
}}
|
|
||||||
transition={{ duration: 0.6, ease: "easeOut" }}
|
|
||||||
>
|
|
||||||
<div className="text-[#2F3178]"><Logo /></div>
|
|
||||||
</motion.div>
|
|
||||||
))}
|
|
||||||
</motion.div>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
18
src/components/CountUpNumber.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import CountUp from 'react-countup'
|
||||||
|
import { H2 } from './Texts'
|
||||||
|
|
||||||
|
interface CountUpNumberProps {
|
||||||
|
end: number
|
||||||
|
className?: string
|
||||||
|
color?: 'light' | 'primary' | 'secondary' | 'custom'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CountUpNumber({ end, className, color }: CountUpNumberProps) {
|
||||||
|
return (
|
||||||
|
<H2 color={color} className={className}>
|
||||||
|
<CountUp end={end} duration={2.75} separator="," />
|
||||||
|
</H2>
|
||||||
|
)
|
||||||
|
}
|
||||||
28
src/components/FadeIn.tsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { motion, Transition } from 'framer-motion'
|
||||||
|
import React from 'react'
|
||||||
|
import { useMediaQuery } from '@/hooks/useMediaQuery'
|
||||||
|
|
||||||
|
type FadeInProps = {
|
||||||
|
children: React.ReactNode
|
||||||
|
transition?: Transition
|
||||||
|
className?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function FadeIn({ children, transition, className }: FadeInProps) {
|
||||||
|
const isMobile = useMediaQuery('(max-width: 768px)')
|
||||||
|
|
||||||
|
return (
|
||||||
|
<motion.div
|
||||||
|
className={className}
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
viewport={{ once: false, margin: isMobile ? '0px 0px -50px 0px' : '0px 0px -100px 0px' }}
|
||||||
|
transition={transition || { duration: 0.5 }}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</motion.div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,14 +1,21 @@
|
|||||||
import { useId } from 'react'
|
import { useId } from 'react'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
|
|
||||||
const formClasses =
|
const formClasses = {
|
||||||
'block w-full appearance-none rounded-lg border border-gray-200 bg-white py-[calc(--spacing(2)-1px)] px-[calc(--spacing(3)-1px)] text-gray-900 placeholder:text-gray-400 focus:border-cyan-500 focus:outline-hidden focus:ring-cyan-500 sm:text-sm'
|
light:
|
||||||
|
'block w-full appearance-none rounded-lg border border-gray-200 bg-white py-[calc(--spacing(2)-1px)] px-[calc(--spacing(3)-1px)] text-gray-900 placeholder:text-gray-400 focus:border-cyan-500 focus:outline-none focus:ring-cyan-500 sm:text-sm',
|
||||||
|
dark:
|
||||||
|
'block w-full appearance-none rounded-lg border border-gray-600 bg-transparent py-[calc(--spacing(2)-1px)] px-[calc(--spacing(3)-1px)] text-white placeholder:text-gray-400 focus:border-cyan-500 focus:outline-none focus:ring-cyan-500 sm:text-sm',
|
||||||
|
}
|
||||||
|
|
||||||
function Label({ id, children }: { id: string; children: React.ReactNode }) {
|
function Label({ id, children, variant = 'light' }: { id: string; children: React.ReactNode, variant?: 'light' | 'dark' }) {
|
||||||
return (
|
return (
|
||||||
<label
|
<label
|
||||||
htmlFor={id}
|
htmlFor={id}
|
||||||
className="mb-2 block text-sm font-semibold text-gray-900"
|
className={clsx(
|
||||||
|
'mb-2 block text-sm font-semibold',
|
||||||
|
variant === 'light' ? 'text-gray-900' : 'text-white',
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</label>
|
</label>
|
||||||
@@ -19,14 +26,15 @@ export function TextField({
|
|||||||
label,
|
label,
|
||||||
type = 'text',
|
type = 'text',
|
||||||
className,
|
className,
|
||||||
|
variant = 'light',
|
||||||
...props
|
...props
|
||||||
}: Omit<React.ComponentPropsWithoutRef<'input'>, 'id'> & { label?: string }) {
|
}: Omit<React.ComponentPropsWithoutRef<'input'>, 'id'> & { label?: string; variant?: 'light' | 'dark' }) {
|
||||||
let id = useId()
|
let id = useId()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
{label && <Label id={id}>{label}</Label>}
|
{label && <Label id={id} variant={variant}>{label}</Label>}
|
||||||
<input id={id} type={type} {...props} className={formClasses} />
|
<input id={id} type={type} {...props} className={formClasses[variant]} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,56 +22,11 @@ function QrCodeBorder(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|||||||
|
|
||||||
export function Footer() {
|
export function Footer() {
|
||||||
return (
|
return (
|
||||||
<footer id="footer" className="border-t border-gray-200">
|
<footer id="footer" className="border-t border-gray-800">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="flex flex-col items-start justify-between gap-y-12 pt-16 pb-6 lg:flex-row lg:items-center lg:py-16">
|
<div className="flex justify-center py-8">
|
||||||
<div>
|
<p className="text-sm text-gray-400">
|
||||||
<div className="flex items-center text-gray-900">
|
© Copyright OurWorld Holdings, {new Date().getFullYear()}. All rights reserved.
|
||||||
<Logomark className="h-10 w-10 flex-none fill-cyan-500" />
|
|
||||||
<div className="ml-4">
|
|
||||||
<p className="text-base font-semibold">Project Mycelium</p>
|
|
||||||
<p className="mt-1 text-sm">Unleash the Power of Decentralized Networks</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<nav className="mt-11 flex gap-8">
|
|
||||||
<NavLinks />
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
<div className="group relative -mx-4 flex items-center self-stretch p-4 transition-colors hover:bg-gray-100 sm:self-auto sm:rounded-2xl lg:mx-0 lg:self-auto lg:p-6">
|
|
||||||
<div className="relative flex h-24 w-24 flex-none items-center justify-center">
|
|
||||||
<QrCodeBorder className="absolute inset-0 h-full w-full stroke-gray-300 transition-colors group-hover:stroke-cyan-500" />
|
|
||||||
<Image src={qrCode} alt="" unoptimized />
|
|
||||||
</div>
|
|
||||||
<div className="ml-8 lg:w-64">
|
|
||||||
<p className="text-base font-semibold text-gray-900">
|
|
||||||
<Link href="#">
|
|
||||||
<span className="absolute inset-0 sm:rounded-2xl" />
|
|
||||||
Download the app
|
|
||||||
</Link>
|
|
||||||
</p>
|
|
||||||
<p className="mt-1 text-sm text-gray-700">
|
|
||||||
Scan the QR code to download the app from the App Store.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col items-center border-t border-gray-200 pt-8 pb-12 md:flex-row-reverse md:justify-between md:pt-6">
|
|
||||||
<form className="flex w-full justify-center md:w-auto">
|
|
||||||
<TextField
|
|
||||||
type="email"
|
|
||||||
aria-label="Email address"
|
|
||||||
placeholder="Email address"
|
|
||||||
autoComplete="email"
|
|
||||||
required
|
|
||||||
className="w-60 min-w-0 shrink"
|
|
||||||
/>
|
|
||||||
<Button type="submit" color="cyan" className="ml-4 flex-none">
|
|
||||||
<span className="hidden lg:inline">Join our newsletter</span>
|
|
||||||
<span className="lg:hidden">Join newsletter</span>
|
|
||||||
</Button>
|
|
||||||
</form>
|
|
||||||
<p className="mt-6 text-sm text-gray-500 md:mt-0">
|
|
||||||
© Copyright ThreeFold {new Date().getFullYear()}. All rights reserved.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
75
src/components/GetStarted.tsx
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { H2, P, CP } from "@/components/Texts";
|
||||||
|
import { Button } from "@/components/Button";
|
||||||
|
|
||||||
|
export function GetStarted() {
|
||||||
|
const items = [
|
||||||
|
{
|
||||||
|
title: "Mycelium Docs",
|
||||||
|
description:
|
||||||
|
"Learn how Mycelium works and get a high-level understanding of its architecture, deployment, and API references.",
|
||||||
|
href: "/docs",
|
||||||
|
buttonText: "Docs",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Mycelium Repository",
|
||||||
|
description:
|
||||||
|
"Explore the official code repositories, contribute, and stay up-to-date with the latest changes.",
|
||||||
|
href: "https://github.com/your-repo", // replace with actual repo
|
||||||
|
buttonText: "Explore",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Mycelium Support",
|
||||||
|
description:
|
||||||
|
"Need help? Reach out to our support team or join the community to get your questions answered quickly.",
|
||||||
|
href: "/support",
|
||||||
|
buttonText: "Support",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
className="bg-cover bg-center text-white py-32 px-6 relative"
|
||||||
|
style={{
|
||||||
|
backgroundImage: `url('/images/getstarted.webp')`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="max-w-8xl mx-auto px-4 text-left mb-12">
|
||||||
|
<H2>Get Started</H2>
|
||||||
|
<P>Explore the documentation, code, and support channels to start building with Mycelium Cloud.</P>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid gap-4 md:grid-cols-3 max-w-8xl mx-auto px-4">
|
||||||
|
{items.map((item, idx) => (
|
||||||
|
<div
|
||||||
|
key={idx}
|
||||||
|
className="relative flex flex-col justify-between overflow-hidden rounded-2xl border border-white/10 bg-black/40 p-6 shadow-md shadow-gray-900/5 transition-all duration-300 ease-out hover:scale-105 hover:border-white/40 hover:bg-black/60"
|
||||||
|
style={{
|
||||||
|
filter: 'brightness(1)',
|
||||||
|
}}
|
||||||
|
onMouseEnter={(e) => {
|
||||||
|
e.currentTarget.style.filter = 'brightness(0.8)';
|
||||||
|
}}
|
||||||
|
onMouseLeave={(e) => {
|
||||||
|
e.currentTarget.style.filter = 'brightness(1)';
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Title + Button Row */}
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<h3 className="text-xl font-semibold">{item.title}</h3>
|
||||||
|
<Button variant="outline" href={item.href} color="white">
|
||||||
|
{item.buttonText}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Divider + Description */}
|
||||||
|
<div className="mt-4 border-t border-white/10"></div>
|
||||||
|
|
||||||
|
<CP className="mt-4">{item.description}</CP>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,63 +2,56 @@
|
|||||||
|
|
||||||
import CountUp from "react-countup";
|
import CountUp from "react-countup";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Button } from "./Button";
|
import { Button } from "@/components/Button";
|
||||||
|
import { H2, P } from "@/components/Texts";
|
||||||
|
|
||||||
export function GridStats() {
|
export function GridStats() {
|
||||||
return (
|
return (
|
||||||
<div id="grid-stats" className="py-24 bg-transparent relative">
|
<div
|
||||||
<div className="mx-auto max-w-2xl px-6 lg:max-w-7xl lg:px-8">
|
id="grid-stats"
|
||||||
<div className="grid grid-cols-1 gap-8 lg:grid-cols-3">
|
className="py-24 relative -top-20 "
|
||||||
{/* Column 1: Title & NODES */}
|
style={{
|
||||||
|
backgroundImage: "url(/images/benefits.webp)",
|
||||||
|
backgroundSize: "cover",
|
||||||
|
backgroundPosition: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="max-w-2xl px-6 lg:max-w-7xl lg:px-6">
|
||||||
|
<div className="grid grid-cols-1 gap-16 lg:grid-cols-3">
|
||||||
|
{/* Column 1: Title & Description */}
|
||||||
<div className="flex flex-col space-y-10">
|
<div className="flex flex-col space-y-10">
|
||||||
{/* Title + Description */}
|
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-2xl font-semibold tracking-tight leading-tight text-black lg:text-4xl">
|
<H2 color="light">
|
||||||
Powered by a Global Community
|
Robust Infrastructure for your Intellegence Needs
|
||||||
</h2>
|
</H2>
|
||||||
<p className="mt-4 sm:mt-6 text-sm font-light text-pretty text-black lg:text-base">
|
<P color="light" className="mt-6">
|
||||||
ThreeFold’s groundbreaking technology enables anyone – individuals, organizations, and communities – to deploy their own Internet infrastructure.
|
Mycelium's groundbreaking technology provides dedicated, performance-validated GPUs for your AI workloads.
|
||||||
</p>
|
</P>
|
||||||
<Button className="mt-8" variant="outline" href="https://threefold.io/build" >Explore TFGrid →</Button>
|
<Button className="mt-8" variant="outline" href="https://threefold.io/build" color="white">Explore TFGrid →</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Column 2: CORES (staggered) + SSD */}
|
{/* Column 2: StatCards */}
|
||||||
<div className="flex flex-col space-y-10">
|
<div className="flex flex-col space-y-10">
|
||||||
<StatCard
|
<StatCard
|
||||||
label="CORES"
|
label="Dedicated Hosting"
|
||||||
description="A globally distributed mesh of CPU cores powering decentralized applications, AI workloads, and edge computing — without central bottlenecks."
|
description="Run LLMs, VLMs, and diffusion models on single-tenant GPUs with private endpoints. Bring your own weights or deploy from a curated library of open models."
|
||||||
value={<CountUp end={54_958} duration={2.5} separator="," />}
|
|
||||||
note="Total Central Processing Unit Cores available on the grid."
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<StatCard
|
<StatCard
|
||||||
label="SSD CAPACITY"
|
label="Data Sovereignty"
|
||||||
description="A distributed network of storage capacity — ready to support Web3, AI, and edge computing workloads around the world."
|
description="Mycelium nodes run on trusted infrastructure you own or choose, ensuring that no third party can access, train on, or monetize your data."
|
||||||
value={<CountUp end={7_364_506} duration={2.5} separator="," />}
|
|
||||||
unit="GB"
|
|
||||||
note="The total amount of storage (SSD, HDD, & RAM) on the grid."
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Column 3: StatCards */}
|
||||||
|
<div className="flex flex-col space-y-10 justify-start mt-20">
|
||||||
{/* Column 3: nodes countries */}
|
|
||||||
<div className="flex flex-col space-y-10 justify-start">
|
|
||||||
<StatCard
|
<StatCard
|
||||||
label="NODES"
|
label="Seamless Scalability"
|
||||||
description="A computer server 100% dedicated to the network. It is a building block of the ThreeFold Grid, providing compute, storage, and network resources."
|
description="Mycelium’s decentralized infrastructure dynamically allocates compute, storage, and bandwidth across the network, so your AI workloads remain fast and resilient even under heavy demand."
|
||||||
value={<CountUp end={1778} duration={2.5} separator="," />}
|
|
||||||
note="The total number of nodes on the grid."
|
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<StatCard
|
<StatCard
|
||||||
label="COUNTRIES"
|
label="Composable Agent Ecosystem"
|
||||||
description="The number of countries where at least one node is connected and operational on the grid."
|
description="Mix and match agents for every part of your workflow: data ingestion, cleaning, orchestration, analysis, and reporting."
|
||||||
value={<CountUp end={51} duration={2.5} separator="," />}
|
|
||||||
note="The total number of countries with active nodes."
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -71,21 +64,15 @@ export function GridStats() {
|
|||||||
function StatCard({
|
function StatCard({
|
||||||
label,
|
label,
|
||||||
description,
|
description,
|
||||||
value,
|
className = "border border-white/10 hover:border-white/40 hover:bg-black/40",
|
||||||
unit,
|
|
||||||
note,
|
|
||||||
className = "",
|
|
||||||
}: {
|
}: {
|
||||||
label: string;
|
label: string;
|
||||||
description: string;
|
description: string;
|
||||||
value: React.ReactNode;
|
|
||||||
unit?: string;
|
|
||||||
note: string;
|
|
||||||
className?: string;
|
className?: string;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`relative flex flex-col overflow-hidden rounded-3xl bg-white shadow-md shadow-gray-900/5 p-8 transition-all duration-300 ease-out hover:scale-105 ${className}`}
|
className={`relative flex flex-col overflow-hidden rounded-3xl bg-gray-900/75 shadow-md shadow-gray-900/5 p-8 transition-all duration-300 ease-out hover:scale-105 ${className}`}
|
||||||
style={{
|
style={{
|
||||||
filter: 'brightness(1)',
|
filter: 'brightness(1)',
|
||||||
}}
|
}}
|
||||||
@@ -96,22 +83,10 @@ function StatCard({
|
|||||||
e.currentTarget.style.filter = 'brightness(1)';
|
e.currentTarget.style.filter = 'brightness(1)';
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<h3 className="text-lg font-semibold text-gradient-neutral-vertical" style={{ textShadow: '0 0 12px rgba(255, 255, 255, 0.4), 0 0 24px rgba(255, 255, 255, 0.2)' }}>{label}</h3>
|
<h3 className="text-lg font-semibold text-white" style={{ textShadow: '0 0 12px rgba(255, 255, 255, 0.4), 0 0 24px rgba(255, 255, 255, 0.2)' }}>{label}</h3>
|
||||||
<p className="mt-2 text-sm font-light text-pretty text-black lg:text-base">
|
<p className="mt-2 text-sm font-light text-pretty text-white lg:text-base">
|
||||||
{description}
|
{description}
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-8 flex items-center space-x-3">
|
|
||||||
<span className="text-gradient-neutral-vertical text-3xl">•</span>
|
|
||||||
<div className="text-5xl font-semibold tracking-tight text-black tabular-nums">
|
|
||||||
{value}
|
|
||||||
{unit && (
|
|
||||||
<span className="ml-2 text-lg font-normal text-gray-800">{unit}</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p className="mt-2 text-sm text-gray-800 uppercase tracking-wider">
|
|
||||||
{note}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ function MobileNavLink(
|
|||||||
return (
|
return (
|
||||||
<PopoverButton
|
<PopoverButton
|
||||||
as={Link}
|
as={Link}
|
||||||
className="block text-base/7 tracking-tight text-[#2F3178]"
|
className="block text-base/7 tracking-tight text-white"
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@@ -60,7 +60,7 @@ export function Header() {
|
|||||||
<nav>
|
<nav>
|
||||||
<Container className="relative z-50 flex justify-between py-4">
|
<Container className="relative z-50 flex justify-between py-4">
|
||||||
<div className="relative z-10 flex items-center gap-16">
|
<div className="relative z-10 flex items-center gap-16">
|
||||||
<Link href="/" aria-label="Home">
|
<Link href="/" aria-label="Home" className="hidden">
|
||||||
<img src="/images/logo.png" alt="Mycelium" className="h-10 w-auto" />
|
<img src="/images/logo.png" alt="Mycelium" className="h-10 w-auto" />
|
||||||
</Link>
|
</Link>
|
||||||
<div className="hidden lg:flex lg:gap-10">
|
<div className="hidden lg:flex lg:gap-10">
|
||||||
@@ -72,7 +72,7 @@ export function Header() {
|
|||||||
{({ open }) => (
|
{({ open }) => (
|
||||||
<>
|
<>
|
||||||
<PopoverButton
|
<PopoverButton
|
||||||
className="relative z-10 -m-2 inline-flex items-center rounded-lg stroke-gray-900 p-2 hover:bg-gray-200/50 hover:stroke-gray-600 focus:not-data-focus:outline-hidden active:stroke-gray-900"
|
className="relative z-10 -m-2 inline-flex items-center rounded-lg stroke-white p-2 hover:bg-gray-200/50 hover:stroke-gray-400 focus:not-data-focus:outline-hidden active:stroke-white"
|
||||||
aria-label="Toggle site navigation"
|
aria-label="Toggle site navigation"
|
||||||
>
|
>
|
||||||
{({ open }) =>
|
{({ open }) =>
|
||||||
@@ -104,28 +104,20 @@ export function Header() {
|
|||||||
y: -32,
|
y: -32,
|
||||||
transition: { duration: 0.2 },
|
transition: { duration: 0.2 },
|
||||||
}}
|
}}
|
||||||
className="absolute inset-x-0 top-0 z-0 origin-top rounded-b-2xl bg-white px-6 pt-32 pb-6 shadow-2xl shadow-gray-900/20"
|
className="absolute inset-x-0 top-0 z-0 origin-top rounded-b-2xl bg-gray-900 px-6 pt-32 pb-6 shadow-2xl shadow-gray-900/20"
|
||||||
>
|
>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<MobileNavLink href="/#about">
|
<NavLinks className="block text-base/7 tracking-tight" />
|
||||||
About
|
|
||||||
</MobileNavLink>
|
|
||||||
<MobileNavLink href="/#benefits">
|
|
||||||
Benefits
|
|
||||||
</MobileNavLink>
|
|
||||||
<MobileNavLink href="/#features">
|
|
||||||
Features
|
|
||||||
</MobileNavLink>
|
|
||||||
<MobileNavLink href="/#usecases">
|
|
||||||
Use Cases
|
|
||||||
</MobileNavLink>
|
|
||||||
<MobileNavLink href="/#faqs">FAQs</MobileNavLink>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-8 flex flex-col gap-4">
|
<div className="mt-8 flex flex-col gap-4">
|
||||||
<Button href="https://docs.ourworld.tf/mycelium_cloud/docs/" variant="outline">
|
<Button
|
||||||
Docs
|
variant="outline"
|
||||||
|
color="white"
|
||||||
|
href="mailto:info@ourworld.tf"
|
||||||
|
>
|
||||||
|
Join the Waitlist
|
||||||
</Button>
|
</Button>
|
||||||
<Button href="https://www.mycelium.threefold.io/download/" color="cyan">Get Started</Button>
|
<Button href="https://calendly.com/sachao/30min" color="cyan">Book a Meeting</Button>
|
||||||
</div>
|
</div>
|
||||||
</PopoverPanel>
|
</PopoverPanel>
|
||||||
</>
|
</>
|
||||||
@@ -135,10 +127,14 @@ export function Header() {
|
|||||||
)}
|
)}
|
||||||
</Popover>
|
</Popover>
|
||||||
<div className="flex items-center gap-6 max-lg:hidden">
|
<div className="flex items-center gap-6 max-lg:hidden">
|
||||||
<Button href="https://docs.ourworld.tf/mycelium_cloud/docs/" variant="outline">
|
<Button
|
||||||
Docs
|
variant="outline"
|
||||||
|
color="white"
|
||||||
|
href="mailto:info@ourworld.tf"
|
||||||
|
>
|
||||||
|
Join the Waitlist
|
||||||
</Button>
|
</Button>
|
||||||
<Button href="https://www.mycelium.threefold.io/download/" color="cyan">Get Started</Button>
|
<Button href="https://calendly.com/sachao/30min" color="cyan">Book a Meeting</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { motion } from 'framer-motion'
|
|||||||
import { TypeAnimation } from 'react-type-animation'
|
import { TypeAnimation } from 'react-type-animation'
|
||||||
import { Dialog, DialogPanel } from '@headlessui/react'
|
import { Dialog, DialogPanel } from '@headlessui/react'
|
||||||
import { Bars3Icon, XMarkIcon, ChevronDoubleDownIcon } from '@heroicons/react/24/outline'
|
import { Bars3Icon, XMarkIcon, ChevronDoubleDownIcon } from '@heroicons/react/24/outline'
|
||||||
import { H1, PL } from '@/components/Texts'
|
import { H1, H2, PL } from '@/components/Texts'
|
||||||
|
|
||||||
const navigation = [
|
const navigation = [
|
||||||
{ name: 'Product', href: '#' },
|
{ name: 'Product', href: '#' },
|
||||||
@@ -18,71 +18,47 @@ export function HomeHero() {
|
|||||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative h-screen -top-15">
|
<div className="relative h-screen -top-20">
|
||||||
<motion.div
|
<div className="absolute inset-0 -z-10">
|
||||||
initial={{ opacity: 0 }}
|
|
||||||
animate={{ opacity: 1 }}
|
|
||||||
transition={{ duration: 2 }}
|
|
||||||
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-[700px] h-[700px] -z-10 rounded-full overflow-hidden"
|
|
||||||
>
|
|
||||||
<video
|
<video
|
||||||
autoPlay
|
autoPlay
|
||||||
loop
|
loop
|
||||||
muted
|
muted
|
||||||
playsInline
|
playsInline
|
||||||
className="h-full w-full object-cover"
|
className="absolute inset-0 w-full h-full object-cover"
|
||||||
>
|
>
|
||||||
<source src="/videos/mycelium.mp4" type="video/mp4" />
|
<source src="/videos/mycelium2.mp4" type="video/mp4" />
|
||||||
</video>
|
</video>
|
||||||
</motion.div>
|
<div className="absolute inset-0 bg-black/60" />
|
||||||
<div className="relative isolate px-6 lg:px-8">
|
</div>
|
||||||
<div
|
<div className="relative px-6 lg:px-8">
|
||||||
aria-hidden="true"
|
<div className="relative mx-auto flex h-screen max-w-8xl items-center justify-center">
|
||||||
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl lg:-top-80"
|
<div className="text-center">
|
||||||
>
|
<div className="max-w-6xl">
|
||||||
<div
|
<H1 color="light">
|
||||||
style={{
|
<TypeAnimation
|
||||||
clipPath:
|
sequence={[
|
||||||
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
'Decentralized Autonomous Agentic Cloud.',
|
||||||
}}
|
1000,
|
||||||
className="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#a4caf6] to-[#aaa4fa] opacity-15 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
|
]}
|
||||||
/>
|
wrapper="span"
|
||||||
</div>
|
speed={50}
|
||||||
<div
|
repeat={0}
|
||||||
aria-hidden="true"
|
/>
|
||||||
className="absolute inset-x-0 bottom-10 -z-10 transform-gpu overflow-hidden blur-3xl lg:bottom-40"
|
</H1>
|
||||||
>
|
</div>
|
||||||
<div
|
|
||||||
style={{
|
<motion.div
|
||||||
clipPath:
|
initial={{ opacity: 0 }}
|
||||||
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
animate={{ opacity: 1 }}
|
||||||
}}
|
transition={{ duration: 1, delay: 1 }}
|
||||||
className="relative bottom-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#93c5fd] to-[#9089fc] opacity-15 sm:left-[calc(50%+30rem)] sm:w-[72.1875rem]"
|
className="mt-12"
|
||||||
/>
|
>
|
||||||
</div>
|
<PL className="mx-auto max-w-4xl text-center text-gray-100" color="light">
|
||||||
<div className="relative -top-15 mx-auto max-w-8xl h-screen flex items-center justify-center">
|
Mycelium's advancements in Agentic infrastructure supports private, secure and autonomous Agents that connect, learn and grow with you.
|
||||||
<div className="text-center max-w-5xl">
|
</PL>
|
||||||
<H1>
|
</motion.div>
|
||||||
<TypeAnimation
|
|
||||||
sequence={[
|
|
||||||
'Decentralized Autonomous Agentic Cloud.',
|
|
||||||
1000,
|
|
||||||
]}
|
|
||||||
wrapper="span"
|
|
||||||
speed={50}
|
|
||||||
repeat={0}
|
|
||||||
/>
|
|
||||||
</H1>
|
|
||||||
</div>
|
</div>
|
||||||
<motion.div
|
|
||||||
initial={{ opacity: 0 }}
|
|
||||||
animate={{ opacity: 1 }}
|
|
||||||
transition={{ duration: 1, delay: 1 }}
|
|
||||||
>
|
|
||||||
<PL className="absolute bottom-0 left-0 max-w-xl text-left" color="custom">
|
|
||||||
Mycelium's advancements in Agentic infrastructure supports private, secure and autonomous Agents that connect, learn and grow with you.
|
|
||||||
</PL>
|
|
||||||
</motion.div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,25 +3,40 @@
|
|||||||
import { useRef, useState } from 'react'
|
import { useRef, useState } from 'react'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { AnimatePresence, motion } from 'framer-motion'
|
import { AnimatePresence, motion } from 'framer-motion'
|
||||||
|
import clsx from 'clsx'
|
||||||
|
|
||||||
export function NavLinks() {
|
export function NavLinks({ className }: { className?: string }) {
|
||||||
let [hoveredIndex, setHoveredIndex] = useState<number | null>(null)
|
let [hoveredIndex, setHoveredIndex] = useState<number | null>(null)
|
||||||
let timeoutRef = useRef<number | null>(null)
|
let timeoutRef = useRef<number | null>(null)
|
||||||
|
|
||||||
|
const handleClick = (e: React.MouseEvent<HTMLAnchorElement>, href: string) => {
|
||||||
|
if (href.startsWith('/#')) {
|
||||||
|
e.preventDefault();
|
||||||
|
const targetId = href.substring(2);
|
||||||
|
const targetElement = document.getElementById(targetId);
|
||||||
|
|
||||||
|
if (targetElement) {
|
||||||
|
targetElement.scrollIntoView({
|
||||||
|
behavior: 'smooth',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return [
|
return [
|
||||||
['About', '/#home-about'],
|
['Technologies', '/#technologies'],
|
||||||
['Marketplace', '/#companies'],
|
['Network', '/#network'],
|
||||||
['Technology', '/#stack-section'],
|
['How it Works', '/#how-it-works'],
|
||||||
['How it works', '/#steps'],
|
['Get Started', '/#get-started'],
|
||||||
['Use Cases', '/#clickable-gallery'],
|
|
||||||
['Coming Soon', '/#use-cases'],
|
|
||||||
['Get Started', '/#call-to-action'],
|
|
||||||
['FAQs', '/#faqs'],
|
|
||||||
].map(([label, href], index) => (
|
].map(([label, href], index) => (
|
||||||
<Link
|
<Link
|
||||||
key={label}
|
key={label}
|
||||||
href={href}
|
href={href}
|
||||||
className="relative -mx-3 -my-2 rounded-lg px-3 py-2 text-sm text-[#2F3178] transition-colors delay-150 hover:text-[#2F3178] hover:delay-0"
|
className={clsx(
|
||||||
|
'relative -mx-3 -my-2 rounded-lg px-3 py-2 text-sm text-white transition-colors delay-150 hover:text-gray-300 hover:delay-0',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
onClick={(e) => handleClick(e, href)}
|
||||||
onMouseEnter={() => {
|
onMouseEnter={() => {
|
||||||
if (timeoutRef.current) {
|
if (timeoutRef.current) {
|
||||||
window.clearTimeout(timeoutRef.current)
|
window.clearTimeout(timeoutRef.current)
|
||||||
@@ -37,7 +52,7 @@ export function NavLinks() {
|
|||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{hoveredIndex === index && (
|
{hoveredIndex === index && (
|
||||||
<motion.span
|
<motion.span
|
||||||
className="absolute inset-0 rounded-lg bg-gray-100"
|
className="absolute inset-0 rounded-lg bg-white/10"
|
||||||
layoutId="hoverBackground"
|
layoutId="hoverBackground"
|
||||||
initial={{ opacity: 0 }}
|
initial={{ opacity: 0 }}
|
||||||
animate={{ opacity: 1, transition: { duration: 0.15 } }}
|
animate={{ opacity: 1, transition: { duration: 0.15 } }}
|
||||||
|
|||||||
@@ -1,63 +1,34 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { StackedCubes } from "@/components/ui/StackedCubes";
|
import { StackedCubes } from "@/components/ui/StackedCubes";
|
||||||
import { Button } from "@/components/Button";
|
import { H1, H2, P } from '@/components/Texts';
|
||||||
import { motion, useInView } from 'framer-motion';
|
import { FadeIn } from "./FadeIn";
|
||||||
import { H2, P } from '@/components/Texts';
|
|
||||||
import { useRef } from "react";
|
|
||||||
|
|
||||||
export function StackSectionPreview() {
|
export function StackSectionPreview() {
|
||||||
const ref = useRef(null);
|
|
||||||
const isInView = useInView(ref);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section ref={ref} className="w-full h-screen bg-transparent lg:px-0 pt-24 pb-12 px-6 relative">
|
<section className="w-full bg-transparent lg:px-0 py-12 lg:py-24 px-6 relative">
|
||||||
{/* Gradient Blob Component */}
|
|
||||||
<motion.div
|
|
||||||
initial={{ opacity: 0 }}
|
|
||||||
animate={isInView ? { opacity: 0.4 } : { opacity: 0 }}
|
|
||||||
transition={{ duration: 1, delay: 0.1 }}
|
|
||||||
className="absolute w-[400px] h-[200px] bg-gradient-to-br from-[#505050] to-[#7e7e7e] rounded-full blur-[150px] bottom-[200px] left-[-150px] z-0"
|
|
||||||
/>
|
|
||||||
<motion.div
|
|
||||||
initial={{ opacity: 0 }}
|
|
||||||
animate={isInView ? { opacity: 0.5 } : { opacity: 0 }}
|
|
||||||
transition={{ duration: 1, delay: 0.15 }}
|
|
||||||
className="absolute w-[200px] h-[100px] bg-gradient-to-br from-[#505050] to-[#7e7e7e] rounded-full blur-[150px] top-[200px] right-[-150px] z-0"
|
|
||||||
/>
|
|
||||||
<div className="mx-auto max-w-7xl">
|
<div className="mx-auto max-w-7xl">
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 lg:gap-16 items-center lg:items-start">
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 lg:gap-16 items-center lg:items-start">
|
||||||
{/* Left Column - Text (1/3 width) */}
|
{/* Left Column - Text (1/3 width) */}
|
||||||
<div className="text-left lg:text-left lg:col-span-1 order-1 lg:order-1">
|
<div className="text-center lg:text-left lg:col-span-1 order-1 lg:order-1">
|
||||||
<motion.div
|
<FadeIn>
|
||||||
initial={{ opacity: 0, y: 30 }}
|
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 30 }}
|
|
||||||
transition={{ duration: 0.8, delay: 0.2 }}
|
|
||||||
>
|
|
||||||
<H2 className="">
|
<H2 className="">
|
||||||
The Mycelium Stack
|
The Mycelium Stack
|
||||||
</H2>
|
</H2>
|
||||||
</motion.div>
|
</FadeIn>
|
||||||
|
|
||||||
<motion.div
|
<FadeIn>
|
||||||
initial={{ opacity: 0, y: 30 }}
|
<P className="mx-auto mt-8 max-w-3xl" color="light">
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 30 }}
|
|
||||||
transition={{ duration: 0.8, delay: 0.6 }}
|
|
||||||
>
|
|
||||||
<P className="mx-auto mt-8 max-w-3xl" color="custom">
|
|
||||||
Built with Mycelium technology, our AI infrastructure ensures unbreakable networks, complete data sovereignty, ultra-secure agent-human communication, and unhackable data storage systems.
|
Built with Mycelium technology, our AI infrastructure ensures unbreakable networks, complete data sovereignty, ultra-secure agent-human communication, and unhackable data storage systems.
|
||||||
</P>
|
</P>
|
||||||
</motion.div>
|
</FadeIn>
|
||||||
</div>
|
</div>
|
||||||
{/* Right Column - Stacked Cubes (2/3 width) */}
|
{/* Right Column - Stacked Cubes (2/3 width) */}
|
||||||
<div className="lg:col-span-2 flex items-center justify-center lg:justify-start order-2 lg:order-2">
|
<div className="lg:col-span-2 flex items-center justify-center lg:justify-start order-2 lg:order-2 mt-8 lg:mt-0">
|
||||||
<motion.div
|
<FadeIn>
|
||||||
initial={{ opacity: 0, y: 30 }}
|
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 30 }}
|
|
||||||
transition={{ duration: 0.8, delay: 0.3 }}
|
|
||||||
>
|
|
||||||
<StackedCubes />
|
<StackedCubes />
|
||||||
</motion.div>
|
</FadeIn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -30,18 +30,18 @@ export function Steps() {
|
|||||||
const isInView = useInView(ref, { once: true });
|
const isInView = useInView(ref, { once: true });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="benefits" ref={ref} className="bg-white pt-0 pb-24 dark:bg-gray-900">
|
<section id="benefits" ref={ref} className="relative pt-12 pb-4 px-4 lg:px-12 text-white">
|
||||||
<div className="mx-auto max-w-7xl px-6 lg:px-0">
|
<div className="relative px-6 lg:px-12">
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
||||||
transition={{ duration: 0.8, delay: 0.1 }}
|
transition={{ duration: 0.8, delay: 0.1 }}
|
||||||
className="mx-auto max-w-5xl lg:mx-0"
|
className="mx-auto max-w-5xl text-center"
|
||||||
>
|
>
|
||||||
<H2 className="text-3xl font-medium tracking-tight">
|
<H2 className="text-3xl font-medium tracking-tight" color="light">
|
||||||
Deploy Scalable LLMs and AI Agents in Seconds
|
Deploy Scalable LLMs and AI Agents in Seconds
|
||||||
</H2>
|
</H2>
|
||||||
<P className="mt-6 text-lg" color="custom">
|
<P className="mt-6" color="light">
|
||||||
Launch and scale intelligence on your own terms. Mycelium Cloud makes it simple to deploy models, integrate knowledge, and run everything on a network you control.
|
Launch and scale intelligence on your own terms. Mycelium Cloud makes it simple to deploy models, integrate knowledge, and run everything on a network you control.
|
||||||
</P>
|
</P>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@@ -49,7 +49,7 @@ export function Steps() {
|
|||||||
initial={{ opacity: 0 }}
|
initial={{ opacity: 0 }}
|
||||||
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
||||||
transition={{ duration: 0.5, delay: 0.2, staggerChildren: 0.2 }}
|
transition={{ duration: 0.5, delay: 0.2, staggerChildren: 0.2 }}
|
||||||
className="mx-auto mt-16 grid max-w-2xl grid-cols-1 gap-x-8 gap-y-16 text-base/7 sm:grid-cols-2 lg:mx-0 lg:max-w-none lg:grid-cols-3"
|
className="mx-auto lg:mt-12 mt-8 grid max-w-2xl grid-cols-1 gap-x-8 gap-y-8 text-base/7 sm:grid-cols-2 sm:gap-y-16 lg:mx-12 lg:max-w-7xl lg:grid-cols-3"
|
||||||
>
|
>
|
||||||
{features.map((feature, index) => (
|
{features.map((feature, index) => (
|
||||||
<motion.li
|
<motion.li
|
||||||
@@ -57,11 +57,11 @@ export function Steps() {
|
|||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
||||||
transition={{ duration: 0.5, delay: 0.3 + index * 0.2 }}
|
transition={{ duration: 0.5, delay: 0.3 + index * 0.2 }}
|
||||||
className="rounded-2xl border border-gray-200 p-8 dark:border-gray-700"
|
className="rounded-2xl border border-white/20 bg-black/30 lg:py-8 lg:px-8 py-6 px-6 backdrop-blur-sm transition-all duration-300 ease-in-out hover:scale-105 hover:border-white/40 hover:bg-black/40"
|
||||||
>
|
>
|
||||||
<feature.icon className="h-8 w-8 mb-4 text-[#2F3178]" />
|
<feature.icon className="h-8 w-8 mb-4 text-white" />
|
||||||
<CT as="span" className="font-semibold">{feature.name}</CT>
|
<CT as="span" className="font-semibold" color="light">{feature.name}</CT>
|
||||||
<CP className="mt-2 text-sm" color="custom">{feature.description}</CP>
|
<CP className="mt-2 text-sm" color="light">{feature.description}</CP>
|
||||||
</motion.li>
|
</motion.li>
|
||||||
))}
|
))}
|
||||||
</motion.ul>
|
</motion.ul>
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ import React from 'react'
|
|||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
const colorVariants = {
|
const colorVariants = {
|
||||||
primary: 'text-[#2F3178]',
|
primary: 'text-[#fffff]',
|
||||||
secondary: 'text-gray-600',
|
secondary: 'text-gray-200',
|
||||||
custom: 'text-[#1c1c49]',
|
custom: 'text-[#015eff]',
|
||||||
|
light: '[#fcfcfc]',
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
type TextOwnProps = {
|
type TextOwnProps = {
|
||||||
@@ -51,10 +52,10 @@ const createTextComponent = <DefaultElement extends React.ElementType>(
|
|||||||
// Exports
|
// Exports
|
||||||
export const H1 = createTextComponent('h1', 'text-5xl font-medium tracking-tight text-balance lg:text-8xl')
|
export const H1 = createTextComponent('h1', 'text-5xl font-medium tracking-tight text-balance lg:text-8xl')
|
||||||
export const PL = createTextComponent('p', 'text-2xl font-medium text-pretty leading-[1.2] lg:text-3xl')
|
export const PL = createTextComponent('p', 'text-2xl font-medium text-pretty leading-[1.2] lg:text-3xl')
|
||||||
export const H2 = createTextComponent('h2', 'text-4xl font-medium text-pretty lg:text-5xl')
|
export const H2 = createTextComponent('h2', 'text-3xl font-medium text-pretty lg:text-4xl')
|
||||||
export const P = createTextComponent('p', 'text-xl font-normal text-pretty lg:text-2xl')
|
export const P = createTextComponent('p', 'text-lg font-normal text-pretty leading-snug lg:text-xl lg:leading-normal')
|
||||||
export const H3 = createTextComponent('h3', 'text-3xl lg:text-4xl font-medium')
|
export const H3 = createTextComponent('h3', 'text-2xl lg:text-3xl font-medium')
|
||||||
export const H4 = createTextComponent('h4', 'text-2xl lg:text-3xl font-semibold leading-tight')
|
export const H4 = createTextComponent('h4', 'text-xl lg:text-2xl font-semibold leading-[1.15]')
|
||||||
export const CT = createTextComponent('span', 'text-base lg:text-xl font-semibold text-center')
|
export const CT = createTextComponent('span', 'text-lg lg:text-xl font-semibold text-center')
|
||||||
export const CP = createTextComponent('p', 'text-sm lg:text-base leading-relaxed font-light')
|
export const CP = createTextComponent('p', 'text-sm lg:text-base leading-[1.525] font-light')
|
||||||
export const NL = createTextComponent('span', 'text-lg font-semibold leading-6')
|
export const NL = createTextComponent('span', 'text-lg font-semibold leading-[1.23]')
|
||||||
|
|||||||
@@ -22,129 +22,75 @@ interface Review {
|
|||||||
body: string
|
body: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const reviews: Array<Review> = [
|
const reviews: Review[] = [
|
||||||
{
|
{ title: 'FungiStor: Long-Term AI Memory', body: 'Quantum-safe permanent storage preserving AI knowledge forever. Zero-knowledge architecture with mathematical dispersal ensures immortality.' },
|
||||||
title: 'FungiStor: Long-Term AI Memory',
|
{ title: 'HeroDB: Active AI Memory', body: 'High-performance datastore for AI working memory. Multi-modal indexing enables vector search with global accessibility.' },
|
||||||
body: 'Quantum-safe permanent storage preserving AI knowledge forever. Zero-knowledge architecture with mathematical dispersal ensures immortality.',
|
{ title: 'MOS Sandboxes: Secure Agent Workspaces', body: 'Lightweight isolated environments deploying globally in five seconds. Hardware-level isolation ensures maximum security for agents.' },
|
||||||
},
|
{ title: 'Mycelium Mesh: Secure Communication Network', body: 'Peer-to-peer overlay network with end-to-end encryption. Self-healing shortest-path routing creates resilient agentic communication.' },
|
||||||
{
|
{ title: 'Deterministic Deployment: Verifiable Code Execution', body: 'Cryptographic guarantee system ensuring deployed code matches specifications. Prevents supply-chain attacks with immutable trails.' },
|
||||||
title: 'HeroDB: Active AI Memory',
|
{ title: 'Agent Coordination: Sovereign Workflow Management', body: 'User-centric orchestration where HERO agents coordinate worker fleets. Planetary-scale coordination with instant spawning.' },
|
||||||
body: 'High-performance datastore for AI working memory. Multi-modal indexing enables vector search with global accessibility.',
|
{ title: 'Universal Interface Layer: AI Service Gateway', body: 'Unified broker connecting agents to LLMs, APIs, and services. Integrated micropayments simplify development.' },
|
||||||
},
|
{ title: 'Semantic Index & Search: Navigable Knowledge Fabric', body: 'Transforms data chaos into unified knowledge graphs. Goes beyond keywords to understand meaning and context.' },
|
||||||
{
|
|
||||||
title: 'MOS Sandboxes: Secure Agent Workspaces',
|
|
||||||
body: 'Lightweight isolated environments deploying globally in five seconds. Hardware-level isolation ensures maximum security for agents.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Mycelium Mesh: Secure Communication Network',
|
|
||||||
body: 'Peer-to-peer overlay network with end-to-end encryption. Self-healing shortest-path routing creates resilient agentic communication.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Deterministic Deployment: Verifiable Code Execution',
|
|
||||||
body: 'Cryptographic guarantee system ensuring deployed code matches specifications. Prevents supply-chain attacks with immutable trails.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Agent Coordination: Sovereign Workflow Management',
|
|
||||||
body: 'User-centric orchestration where HERO agents coordinate worker fleets. Planetary-scale coordination with instant spawning.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Universal Interface Layer: AI Service Gateway',
|
|
||||||
body: 'Unified broker connecting agents to LLMs, APIs, and services. Integrated micropayments simplify development.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Semantic Index & Search: Navigable Knowledge Fabric',
|
|
||||||
body: 'Transforms data chaos into unified knowledge graphs. Goes beyond keywords to understand meaning and context.',
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
function getReviewIcon(title: string) {
|
function getReviewIcon(title: string) {
|
||||||
if (title.startsWith('FungiStor')) return ArchiveBoxIcon;
|
if (title.startsWith('FungiStor')) return ArchiveBoxIcon
|
||||||
if (title.startsWith('HeroDB')) return CpuChipIcon;
|
if (title.startsWith('HeroDB')) return CpuChipIcon
|
||||||
if (title.startsWith('MOS Sandboxes')) return CodeBracketIcon;
|
if (title.startsWith('MOS Sandboxes')) return CodeBracketIcon
|
||||||
if (title.startsWith('Mycelium Mesh')) return ShareIcon;
|
if (title.startsWith('Mycelium Mesh')) return ShareIcon
|
||||||
if (title.startsWith('Deterministic Deployment')) return CheckBadgeIcon;
|
if (title.startsWith('Deterministic Deployment')) return CheckBadgeIcon
|
||||||
if (title.startsWith('Agent Coordination')) return UserGroupIcon;
|
if (title.startsWith('Agent Coordination')) return UserGroupIcon
|
||||||
if (title.startsWith('Universal Interface Layer')) return GlobeAltIcon;
|
if (title.startsWith('Universal Interface Layer')) return GlobeAltIcon
|
||||||
if (title.startsWith('Semantic Index & Search')) return MagnifyingGlassIcon;
|
if (title.startsWith('Semantic Index & Search')) return MagnifyingGlassIcon
|
||||||
return GlobeAltIcon; // default
|
return GlobeAltIcon
|
||||||
}
|
}
|
||||||
|
|
||||||
function Review({
|
function Review({ title, body, className, ...props }: Omit<React.ComponentPropsWithoutRef<'figure'>, keyof Review> & Review) {
|
||||||
title,
|
const animationDelay = useMemo(() => {
|
||||||
body,
|
const delays = ['0s', '0.1s', '0.2s', '0.3s', '0.4s', '0.5s']
|
||||||
className,
|
return delays[Math.floor(Math.random() * delays.length)]
|
||||||
...props
|
|
||||||
}: Omit<React.ComponentPropsWithoutRef<'figure'>, keyof Review> & Review) {
|
|
||||||
let animationDelay = useMemo(() => {
|
|
||||||
let possibleAnimationDelays = ['0s', '0.1s', '0.2s', '0.3s', '0.4s', '0.5s']
|
|
||||||
return possibleAnimationDelays[
|
|
||||||
Math.floor(Math.random() * possibleAnimationDelays.length)
|
|
||||||
]
|
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<figure
|
<figure
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'animate-fade-in rounded-3xl bg-white p-6 opacity-0 shadow-md shadow-gray-900/5',
|
'animate-fade-in rounded-3xl bg-gray-900/50 p-6 opacity-0 shadow-md shadow-gray-900/5',
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
style={{ animationDelay }}
|
style={{ animationDelay }}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<blockquote className="text-gray-900">
|
<blockquote className="text-white">
|
||||||
{React.createElement(getReviewIcon(title), { className: "h-6 w-6 text-[#2F3178] mb-2" })}
|
{React.createElement(getReviewIcon(title), { className: 'h-6 w-6 text-white mb-2' })}
|
||||||
<CT color="primary" className="mt-4 text-lg/6 font-semibold">
|
<CT color="light" className="mt-4 text-lg font-semibold">{title}</CT>
|
||||||
{title}
|
<CP color="light" className="mt-3 text-sm">{body}</CP>
|
||||||
</CT>
|
|
||||||
<CP color="custom" className="mt-3 text-sm">{body}</CP>
|
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
</figure>
|
</figure>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function splitArray<T>(array: Array<T>, numParts: number) {
|
function splitArray<T>(array: T[], numParts: number) {
|
||||||
let result: Array<Array<T>> = []
|
const result: T[][] = []
|
||||||
for (let i = 0; i < array.length; i++) {
|
for (let i = 0; i < array.length; i++) {
|
||||||
let index = i % numParts
|
const index = i % numParts
|
||||||
if (!result[index]) {
|
if (!result[index]) result[index] = []
|
||||||
result[index] = []
|
|
||||||
}
|
|
||||||
result[index].push(array[i])
|
result[index].push(array[i])
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReviewColumn({
|
function ReviewColumn({ reviews, className, msPerPixel = 0 }: { reviews: Review[], className?: string, msPerPixel?: number }) {
|
||||||
reviews,
|
const columnRef = useRef<HTMLDivElement>(null)
|
||||||
className,
|
const [columnHeight, setColumnHeight] = useState(0)
|
||||||
reviewClassName,
|
const duration = `${columnHeight * msPerPixel}ms`
|
||||||
msPerPixel = 0,
|
|
||||||
}: {
|
|
||||||
reviews: Array<Review>
|
|
||||||
className?: string
|
|
||||||
reviewClassName?: (reviewIndex: number) => string
|
|
||||||
msPerPixel?: number
|
|
||||||
}) {
|
|
||||||
let columnRef = useRef<React.ElementRef<'div'>>(null)
|
|
||||||
let [columnHeight, setColumnHeight] = useState(0)
|
|
||||||
let duration = `${columnHeight * msPerPixel}ms`
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!columnRef.current) {
|
if (!columnRef.current) return
|
||||||
return
|
const resizeObserver = new ResizeObserver(() =>
|
||||||
}
|
|
||||||
|
|
||||||
let resizeObserver = new window.ResizeObserver(() => {
|
|
||||||
setColumnHeight(columnRef.current?.offsetHeight ?? 0)
|
setColumnHeight(columnRef.current?.offsetHeight ?? 0)
|
||||||
})
|
)
|
||||||
|
|
||||||
resizeObserver.observe(columnRef.current)
|
resizeObserver.observe(columnRef.current)
|
||||||
|
return () => resizeObserver.disconnect()
|
||||||
return () => {
|
|
||||||
resizeObserver.disconnect()
|
|
||||||
}
|
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -153,110 +99,73 @@ function ReviewColumn({
|
|||||||
className={clsx('animate-marquee space-y-8 py-4', className)}
|
className={clsx('animate-marquee space-y-8 py-4', className)}
|
||||||
style={{ '--marquee-duration': duration } as React.CSSProperties}
|
style={{ '--marquee-duration': duration } as React.CSSProperties}
|
||||||
>
|
>
|
||||||
{reviews.concat(reviews).map((review, reviewIndex) => (
|
{reviews.concat(reviews).map((review, i) => (
|
||||||
<Review
|
<Review key={i} aria-hidden={i >= reviews.length} {...review} />
|
||||||
key={reviewIndex}
|
|
||||||
aria-hidden={reviewIndex >= reviews.length}
|
|
||||||
className={reviewClassName?.(reviewIndex % reviews.length)}
|
|
||||||
{...review}
|
|
||||||
/>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReviewGrid() {
|
function ReviewGrid() {
|
||||||
let containerRef = useRef<React.ElementRef<'div'>>(null)
|
const containerRef = useRef<HTMLDivElement>(null)
|
||||||
let isInView = useInView(containerRef, { once: true, amount: 0.4 })
|
const isInView = useInView(containerRef, { once: true, amount: 0.4 })
|
||||||
let columns = splitArray(reviews, 3)
|
const columns = splitArray(reviews, 2)
|
||||||
let column1 = columns[0]
|
|
||||||
let column2 = columns[1]
|
|
||||||
let column3 = splitArray(columns[2], 2)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div ref={containerRef} className="relative grid grid-cols-1 md:grid-cols-2 gap-8 overflow-hidden h-full">
|
||||||
ref={containerRef}
|
|
||||||
className="relative -mx-4 mt-0 grid h-196 max-h-[150vh] grid-cols-1 items-start gap-8 overflow-hidden px-4 sm:mt-20 md:grid-cols-2 lg:grid-cols-3"
|
|
||||||
>
|
|
||||||
{isInView && (
|
{isInView && (
|
||||||
<>
|
<>
|
||||||
<ReviewColumn
|
<ReviewColumn reviews={columns[0]} msPerPixel={10} />
|
||||||
reviews={[...column1, ...column3.flat(), ...column2]}
|
<ReviewColumn reviews={columns[1]} msPerPixel={15} />
|
||||||
reviewClassName={(reviewIndex) =>
|
|
||||||
clsx(
|
|
||||||
reviewIndex >= column1.length + column3[0].length &&
|
|
||||||
'md:hidden',
|
|
||||||
reviewIndex >= column1.length && 'lg:hidden',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
msPerPixel={10}
|
|
||||||
/>
|
|
||||||
<ReviewColumn
|
|
||||||
reviews={[...column2, ...column3[1]]}
|
|
||||||
className="hidden md:block"
|
|
||||||
reviewClassName={(reviewIndex) =>
|
|
||||||
reviewIndex >= column2.length ? 'lg:hidden' : ''
|
|
||||||
}
|
|
||||||
msPerPixel={15}
|
|
||||||
/>
|
|
||||||
<ReviewColumn
|
|
||||||
reviews={column3.flat()}
|
|
||||||
className="hidden lg:block"
|
|
||||||
msPerPixel={10}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<div className="pointer-events-none absolute inset-x-0 top-0 h-32 bg-linear-to-b from-white" />
|
{/* Top Gradient */}
|
||||||
<div className="pointer-events-none absolute inset-x-0 bottom-0 h-32 bg-linear-to-t from-white" />
|
<div className="pointer-events-none absolute inset-x-0 top-0 h-32 bg-gradient-to-b from-black/90 to-transparent z-10" />
|
||||||
|
{/* Bottom Gradient */}
|
||||||
|
<div className="pointer-events-none absolute inset-x-0 bottom-0 h-32 bg-gradient-to-t from-black/90 to-transparent z-10" />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function UseCases() {
|
export function UseCases() {
|
||||||
const ref = useRef(null);
|
const ref = useRef(null)
|
||||||
const isInView = useInView(ref, { once: true });
|
const isInView = useInView(ref, { once: true })
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
id="usecases"
|
id="usecases"
|
||||||
ref={ref}
|
ref={ref}
|
||||||
aria-labelledby="usecases-title"
|
aria-labelledby="usecases-title"
|
||||||
className="py-12"
|
className="bg-black h-screen relative flex items-start py-12 -top-20"
|
||||||
>
|
>
|
||||||
<Container className=''>
|
<Container className="h-full">
|
||||||
<motion.div
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-10 h-full">
|
||||||
initial={{ opacity: 0, y: 20 }}
|
{/* Left Column */}
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
<motion.div
|
||||||
transition={{ duration: 0.8, delay: 0.1 }}
|
initial={{ opacity: 0, y: 10 }}
|
||||||
className="mx-auto max-w-2xl lg:max-w-5xl"
|
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 10 }}
|
||||||
>
|
transition={{ duration: 0.8, delay: 0.1 }}
|
||||||
<H2
|
className="flex flex-col items-start justify-start pt-10 lg:pr-12"
|
||||||
id="usecases-title"
|
|
||||||
color="primary"
|
|
||||||
className="text-center"
|
|
||||||
>
|
>
|
||||||
Coming Soon: The Future of Mycelium
|
<H2 id="usecases-title" color="light" className="text-left">
|
||||||
</H2>
|
Augmented Intelligence Fabric
|
||||||
<P className="mt-6 text-center" color="custom">
|
</H2>
|
||||||
Mycelium Cloud is evolving to bring even more powerful decentralized features, designed to enhance your experience and expand possibilities. Be the first to explore what's coming next by staying connected with our latest updates.
|
<P className="mt-4 text-left" color="light">
|
||||||
</P>
|
The sovereign substrate for autonomous AI.
|
||||||
</motion.div>
|
Stateless, geo-aware, end-to-end encrypted—and verifiable from intent to execution.
|
||||||
<motion.div
|
</P>
|
||||||
initial={{ opacity: 0 }}
|
</motion.div>
|
||||||
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
|
||||||
transition={{ duration: 1, delay: 0.2 }}
|
{/* Right Columns */}
|
||||||
aria-hidden="true"
|
<motion.div
|
||||||
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
|
initial={{ opacity: 0 }}
|
||||||
>
|
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
||||||
<div
|
transition={{ duration: 1, delay: 0.2 }}
|
||||||
style={{
|
className="lg:col-span-2 h-full"
|
||||||
clipPath:
|
>
|
||||||
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
<ReviewGrid />
|
||||||
}}
|
</motion.div>
|
||||||
className="relative left-[calc(50%-30rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#93c5fd] to-[#9089fc] opacity-30 sm:left-[calc(50%-36rem)] sm:w-[72.1875rem]"
|
</div>
|
||||||
/>
|
|
||||||
</motion.div>
|
|
||||||
<ReviewGrid />
|
|
||||||
</Container>
|
</Container>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
|||||||
120
src/components/WorldMap.tsx
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { Globe } from "@/components/ui/globe"
|
||||||
|
import { motion } from "framer-motion"
|
||||||
|
import { H2, P, CT, CP } from "@/components/Texts"
|
||||||
|
import { CountUpNumber } from './CountUpNumber'
|
||||||
|
|
||||||
|
export function WorldMap() {
|
||||||
|
return (
|
||||||
|
<div className="relative min-h-screen w-full overflow-hidden top-0 flex py-12 flex-col">
|
||||||
|
{/* Background video */}
|
||||||
|
<video
|
||||||
|
autoPlay
|
||||||
|
loop
|
||||||
|
muted
|
||||||
|
playsInline
|
||||||
|
className="absolute inset-0 w-full h-full object-cover"
|
||||||
|
>
|
||||||
|
<source src="/videos/benefits.mp4" type="video/mp4" />
|
||||||
|
</video>
|
||||||
|
|
||||||
|
{/* Dark overlay */}
|
||||||
|
<div className="absolute inset-0 bg-black/10" />
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="relative z-10 flex flex-col h-full px-8 md:px-16 py-12">
|
||||||
|
{/* Title + Subtitle */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 0.5 }}
|
||||||
|
className="max-w-xl"
|
||||||
|
>
|
||||||
|
<H2 color="light">Mycelium Network is Live.</H2>
|
||||||
|
<P className="hidden mt-4 text-base leading-relaxed font-light" color="light">
|
||||||
|
Mycelium Cloud's advancement technology enables anyone to deploy
|
||||||
|
their own Internet infrastructure, anywhere.
|
||||||
|
</P>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Bottom Layout: Globe + Cards */}
|
||||||
|
<div className="mt-8 flex flex-1 flex-col lg:flex-row items-center lg:items-stretch gap-x-10">
|
||||||
|
{/* Globe Left Column */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, scale: 0.9 }}
|
||||||
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
|
transition={{ duration: 0.5, delay: 0.2 }}
|
||||||
|
className="flex-1 flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<div className="relative w-[450px] h-[450px] md:w-[600px] md:h-[600px]">
|
||||||
|
<Globe className="absolute inset-0 w-full h-full left-0 lg:-left-24" />
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Cards Right Column */}
|
||||||
|
<div className="relative flex-1 lg:h-auto h-[700px] flex flex-col lg:block items-center gap-y-4 mt-8 lg:mt-0">
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: -20 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.5, delay: 0.4 }}
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
className="lg:absolute lg:top-12 lg:-left-12 rounded-xl bg-white/5 backdrop-blur-md border border-white/10 px-4 lg:py-8 py-6 shadow-md w-80"
|
||||||
|
>
|
||||||
|
<CT color="light" className="uppercase tracking-wide">CORES</CT>
|
||||||
|
<CountUpNumber end={54958} color="light" className="mt-2 text-3xl font-bold" />
|
||||||
|
<CP color="light" className="mt-2 text-sm">
|
||||||
|
Total Central Processing Unit Cores available on the grid.
|
||||||
|
</CP>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: 20 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.5, delay: 0.5 }}
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
className="lg:absolute lg:-top-10 lg:right-0 rounded-xl bg-white/5 backdrop-blur-md border border-white/10 px-4 lg:py-8 py-6 shadow-md w-80"
|
||||||
|
>
|
||||||
|
<CT color="light" className="uppercase tracking-wide">NODES</CT>
|
||||||
|
<CountUpNumber end={1493} color="light" className="mt-2 text-3xl font-bold" />
|
||||||
|
<CP color="light" className="mt-2 text-sm">
|
||||||
|
Total number of nodes on the grid.
|
||||||
|
</CP>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: -20 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.5, delay: 0.6 }}
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
className="lg:absolute lg:bottom-28 lg:-left-12 rounded-xl bg-white/5 backdrop-blur-md border border-white/10 px-4 lg:py-8 py-6 shadow-md w-80"
|
||||||
|
>
|
||||||
|
<CT color="light" className="uppercase tracking-wide">SSD CAPACITY</CT>
|
||||||
|
<CountUpNumber end={5388956} color="light" className="mt-2 text-3xl font-bold" />
|
||||||
|
<CP color="light" className="mt-2 text-sm">
|
||||||
|
Total GB amount of storage (SSD, HDD, & RAM) on the grid.
|
||||||
|
</CP>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: 20 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ duration: 0.5, delay: 0.7 }}
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
className="lg:absolute lg:top-44 lg:right-0 rounded-xl bg-white/5 backdrop-blur-md border border-white/10 px-4 lg:py-8 py-6 shadow-md w-80"
|
||||||
|
>
|
||||||
|
<CT color="light" className="uppercase tracking-wide">COUNTRIES</CT>
|
||||||
|
<CountUpNumber end={44} color="light" className="mt-2 text-3xl font-bold" />
|
||||||
|
<CP color="light" className="mt-2 text-sm">
|
||||||
|
Total number of countries with active nodes.
|
||||||
|
</CP>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Radial fade overlay */}
|
||||||
|
<div className="pointer-events-none absolute inset-0 h-full bg-[radial-gradient(circle_at_50%_200%,rgba(0,0,0,0.2),rgba(255,255,255,0))]" />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
import { Ai21 } from '@lobehub/icons';
|
import { Ai21 } from '@lobehub/icons';
|
||||||
|
|
||||||
export default () => <Ai21.Brand size={40} />;
|
export default () => <Ai21.Brand size={30} />;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import { AlibabaCloud } from '@lobehub/icons';
|
import { AlibabaCloud } from '@lobehub/icons';
|
||||||
|
|
||||||
export default () => <AlibabaCloud.Text size={40} />;
|
export default () => <AlibabaCloud.Text size={30} />;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import { BaiduCloud } from '@lobehub/icons';
|
import { BaiduCloud } from '@lobehub/icons';
|
||||||
|
|
||||||
export default () => <BaiduCloud.Combine size={40} />;
|
export default () => <BaiduCloud.Combine size={30} />;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import { ByteDance } from '@lobehub/icons';
|
import { ByteDance } from '@lobehub/icons';
|
||||||
|
|
||||||
export default () => <ByteDance.Text size={40} />;
|
export default () => <ByteDance.Text size={30} />;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import { Claude } from '@lobehub/icons';
|
import { Claude } from '@lobehub/icons';
|
||||||
|
|
||||||
export default () => <Claude.Combine size={40} />;
|
export default () => <Claude.Combine size={30} />;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import { DeepMind } from '@lobehub/icons';
|
import { DeepMind } from '@lobehub/icons';
|
||||||
|
|
||||||
export default () => <DeepMind.Combine size={40} />;
|
export default () => <DeepMind.Combine size={30} />;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import { DeepSeek } from '@lobehub/icons';
|
import { DeepSeek } from '@lobehub/icons';
|
||||||
|
|
||||||
export default () => <DeepSeek.Combine size={40} />;
|
export default () => <DeepSeek.Combine size={30} />;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import { Minimax } from '@lobehub/icons';
|
import { Minimax } from '@lobehub/icons';
|
||||||
|
|
||||||
export default () => <Minimax.Combine size={40} />;
|
export default () => <Minimax.Combine size={30} />;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import { Mistral } from '@lobehub/icons';
|
import { Mistral } from '@lobehub/icons';
|
||||||
|
|
||||||
export default () => <Mistral.Combine size={40} />;
|
export default () => <Mistral.Combine size={30} />;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import { Moonshot } from '@lobehub/icons';
|
import { Moonshot } from '@lobehub/icons';
|
||||||
|
|
||||||
export default () => <Moonshot.Combine size={40} />;
|
export default () => <Moonshot.Combine size={30} />;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import { OpenAI } from '@lobehub/icons';
|
import { OpenAI } from '@lobehub/icons';
|
||||||
|
|
||||||
export default () => <OpenAI.Combine size={40} />;
|
export default () => <OpenAI.Combine size={30} />;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import { TencentCloud } from '@lobehub/icons';
|
import { TencentCloud } from '@lobehub/icons';
|
||||||
|
|
||||||
export default () => <TencentCloud.Combine size={40} />;
|
export default () => <TencentCloud.Combine size={30} />;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import { XAI } from '@lobehub/icons';
|
import { XAI } from '@lobehub/icons';
|
||||||
|
|
||||||
export default () => <XAI.Text size={40} />;
|
export default () => <XAI.Text size={30} />;
|
||||||
|
|||||||
96
src/components/magicui/infinite-moving-cards.tsx
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
export const InfiniteMovingCards = ({
|
||||||
|
items,
|
||||||
|
direction = "left",
|
||||||
|
speed = "fast",
|
||||||
|
pauseOnHover = true,
|
||||||
|
className,
|
||||||
|
}: {
|
||||||
|
items: React.ReactNode[];
|
||||||
|
direction?: "left" | "right";
|
||||||
|
speed?: "fast" | "normal" | "slow";
|
||||||
|
pauseOnHover?: boolean;
|
||||||
|
className?: string;
|
||||||
|
}) => {
|
||||||
|
const containerRef = React.useRef<HTMLDivElement>(null);
|
||||||
|
const scrollerRef = React.useRef<HTMLUListElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
addAnimation();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const [start, setStart] = useState(false);
|
||||||
|
function addAnimation() {
|
||||||
|
if (containerRef.current && scrollerRef.current) {
|
||||||
|
const scrollerContent = Array.from(scrollerRef.current.children);
|
||||||
|
|
||||||
|
scrollerContent.forEach((item) => {
|
||||||
|
const duplicatedItem = item.cloneNode(true);
|
||||||
|
if (scrollerRef.current) {
|
||||||
|
scrollerRef.current.appendChild(duplicatedItem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
getDirection();
|
||||||
|
getSpeed();
|
||||||
|
setStart(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const getDirection = () => {
|
||||||
|
if (containerRef.current) {
|
||||||
|
if (direction === "left") {
|
||||||
|
containerRef.current.style.setProperty(
|
||||||
|
"--animation-direction",
|
||||||
|
"forwards"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
containerRef.current.style.setProperty(
|
||||||
|
"--animation-direction",
|
||||||
|
"reverse"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getSpeed = () => {
|
||||||
|
if (containerRef.current) {
|
||||||
|
if (speed === "fast") {
|
||||||
|
containerRef.current.style.setProperty("--animation-duration", "20s");
|
||||||
|
} else if (speed === "normal") {
|
||||||
|
containerRef.current.style.setProperty("--animation-duration", "40s");
|
||||||
|
} else {
|
||||||
|
containerRef.current.style.setProperty("--animation-duration", "80s");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={containerRef}
|
||||||
|
className={cn(
|
||||||
|
"scroller relative z-20 max-w-7xl overflow-hidden [mask-image:linear-gradient(to_right,transparent,white_20%,white_80%,transparent)]",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<ul
|
||||||
|
ref={scrollerRef}
|
||||||
|
className={cn(
|
||||||
|
" flex min-w-full shrink-0 gap-4 py-0 w-max flex-nowrap",
|
||||||
|
start && "animate-scroll ",
|
||||||
|
pauseOnHover && "hover:[animation-play-state:paused]"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{items.map((item, idx) => (
|
||||||
|
<li
|
||||||
|
className="w-[160px] max-w-full relative flex-shrink-0 flex items-center justify-center px-8 py-0 md:w-[180px]"
|
||||||
|
key={idx}
|
||||||
|
>
|
||||||
|
{item}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
import Link from 'next/link'
|
|
||||||
import clsx from 'clsx'
|
|
||||||
|
|
||||||
const baseStyles = {
|
|
||||||
solid:
|
|
||||||
'inline-flex justify-center rounded-lg py-2 px-3 text-sm font-semibold transition-colors',
|
|
||||||
outline:
|
|
||||||
'inline-flex justify-center rounded-lg border py-[calc(theme(spacing.2)-1px)] px-[calc(theme(spacing.3)-1px)] text-sm transition-colors',
|
|
||||||
}
|
|
||||||
|
|
||||||
const variantStyles = {
|
|
||||||
solid: {
|
|
||||||
primary: 'bg-[#2F3178] text-white hover:bg-[#2F3178]/90 active:bg-[#2F3178]/80',
|
|
||||||
white: 'bg-white text-black hover:bg-white/90 active:bg-white/90 active:text-gray-400',
|
|
||||||
gray: 'bg-gray-800 text-white hover:bg-gray-900 active:bg-gray-800 active:text-white/80',
|
|
||||||
},
|
|
||||||
outline: {
|
|
||||||
primary: 'border-[#2F3178] text-[#2F3178] hover:border-[#2F3178]/80 hover:text-[#2F3178]/80 active:bg-gray-100 active:text-[#2F3178]/70',
|
|
||||||
gray: 'border-gray-300 text-gray-700 hover:border-gray-400 active:bg-gray-100 active:text-gray-700/80',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
type ButtonProps = (
|
|
||||||
| { variant?: 'solid'; color?: keyof typeof variantStyles.solid }
|
|
||||||
| { variant: 'outline'; color?: keyof typeof variantStyles.outline }
|
|
||||||
) & (
|
|
||||||
| Omit<React.ComponentPropsWithoutRef<typeof Link>, 'color'>
|
|
||||||
| (Omit<React.ComponentPropsWithoutRef<'button'>, 'color'> & {
|
|
||||||
href?: undefined
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
export function Button({ className, ...props }: ButtonProps) {
|
|
||||||
props.variant ??= 'solid'
|
|
||||||
if (props.variant === 'solid') {
|
|
||||||
props.color ??= 'primary'
|
|
||||||
} else {
|
|
||||||
props.color ??= 'gray'
|
|
||||||
}
|
|
||||||
|
|
||||||
let variantClass: string | undefined;
|
|
||||||
if (props.variant === 'outline') {
|
|
||||||
variantClass = variantStyles.outline[props.color as keyof typeof variantStyles.outline];
|
|
||||||
} else if (props.variant === 'solid') {
|
|
||||||
variantClass = variantStyles.solid[props.color as keyof typeof variantStyles.solid];
|
|
||||||
}
|
|
||||||
|
|
||||||
className = clsx(
|
|
||||||
baseStyles[props.variant],
|
|
||||||
variantClass,
|
|
||||||
className,
|
|
||||||
)
|
|
||||||
|
|
||||||
return typeof props.href === 'undefined' ? (
|
|
||||||
<button className={className} {...props} />
|
|
||||||
) : (
|
|
||||||
<Link className={className} {...props} />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import Image from "next/image";
|
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { CT, CP } from '@/components/Texts';
|
|
||||||
|
|
||||||
interface CubeProps {
|
interface CubeProps {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -13,16 +11,46 @@ interface CubeProps {
|
|||||||
index: number;
|
index: number;
|
||||||
onHover: () => void;
|
onHover: () => void;
|
||||||
onLeave: () => void;
|
onLeave: () => void;
|
||||||
|
onClick: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CubeSvg: React.FC<React.SVGProps<SVGSVGElement> & { index: number }> = ({ index, ...props }) => (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="507"
|
||||||
|
height="234"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 507 234"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill={`url(#cube-gradient-${index})`}
|
||||||
|
d="M491.651 144.747L287.198 227.339C265.219 236.22 241.783 236.22 219.802 227.339L15.3486 144.747C-5.11621 136.479 -5.11621 97.5191 15.3486 89.2539L219.802 6.65884C241.783 -2.21961 265.219 -2.21961 287.198 6.65884L491.651 89.2539C512.116 97.5191 512.116 136.479 491.651 144.747Z"
|
||||||
|
/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient
|
||||||
|
id={`cube-gradient-${index}`}
|
||||||
|
x1="185.298"
|
||||||
|
x2="185.298"
|
||||||
|
y1="-27.5515"
|
||||||
|
y2="206.448"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
>
|
||||||
|
<stop />
|
||||||
|
<stop offset="1" stopColor="#3F3B3E" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
export function Cube({ title, descriptionTitle, description, isActive, index, onHover, onLeave }: CubeProps) {
|
export function Cube({ title, descriptionTitle, description, isActive, index, onHover, onLeave, onClick }: CubeProps) {
|
||||||
return (
|
return (
|
||||||
<div className="relative flex flex-col items-center">
|
<div className="relative flex flex-col items-center">
|
||||||
<motion.div
|
<motion.div
|
||||||
className="relative cursor-pointer pointer-events-none"
|
className="relative cursor-pointer"
|
||||||
onMouseEnter={onHover}
|
onMouseEnter={onHover}
|
||||||
onMouseLeave={onLeave}
|
onMouseLeave={onLeave}
|
||||||
|
onClick={onClick}
|
||||||
style={{
|
style={{
|
||||||
zIndex: 10 - index,
|
zIndex: 10 - index,
|
||||||
}}
|
}}
|
||||||
@@ -34,25 +62,26 @@ export function Cube({ title, descriptionTitle, description, isActive, index, on
|
|||||||
ease: "easeOut",
|
ease: "easeOut",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Image Cube */}
|
{/* SVG Cube */}
|
||||||
<Image
|
<CubeSvg
|
||||||
src="/images/cube.png"
|
index={index}
|
||||||
alt="Cube"
|
className="w-48 sm:w-64 lg:w-80 h-auto drop-shadow-lg opacity-50"
|
||||||
width={507}
|
|
||||||
height={234}
|
|
||||||
className="w-60 sm:w-80 lg:w-96 h-auto drop-shadow-lg pointer-events-auto"
|
|
||||||
style={{
|
style={{
|
||||||
filter: isActive
|
filter: isActive ? 'brightness(1.2) drop-shadow(0 0 20px rgba(156, 163, 175, 0.5))' : 'brightness(0.9)',
|
||||||
? 'brightness(1.1) drop-shadow(0 25px 25px rgba(144, 137, 252, 0.4))'
|
|
||||||
: 'brightness(0.9) drop-shadow(0 10px 15px rgba(144, 137, 252, 0.2))',
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Title overlay */}
|
{/* Title overlay */}
|
||||||
<div className="absolute inset-0 flex items-center justify-center">
|
<div className="absolute inset-0 flex items-center justify-center">
|
||||||
<CT as="h3" className="px-4 drop-shadow-lg" style={{ transform: 'rotate(0deg) skewX(0deg)', transformOrigin: 'center' }}>
|
<h3
|
||||||
|
className="text-white text-sm lg:text-base font-medium text-center px-4 drop-shadow-lg"
|
||||||
|
style={{
|
||||||
|
transform: 'rotate(0deg) skewX(0deg)',
|
||||||
|
transformOrigin: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
{title}
|
{title}
|
||||||
</CT>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Description with arrow line - Desktop */}
|
{/* Description with arrow line - Desktop */}
|
||||||
@@ -77,40 +106,26 @@ export function Cube({ title, descriptionTitle, description, isActive, index, on
|
|||||||
y1="1"
|
y1="1"
|
||||||
x2="120"
|
x2="120"
|
||||||
y2="1"
|
y2="1"
|
||||||
stroke="currentColor"
|
stroke="white"
|
||||||
strokeWidth="1"
|
strokeWidth="1"
|
||||||
opacity="0.6"
|
opacity="0.6"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
{/* Description text */}
|
{/* Description text */}
|
||||||
<div className="ml-32 w-80 text-[#2F3178]">
|
<div className="ml-32 w-80">
|
||||||
<h4 className="text-base font-semibold mb-2">
|
<h4 className="text-white text-base font-semibold mb-2">
|
||||||
{descriptionTitle}
|
{descriptionTitle}
|
||||||
</h4>
|
</h4>
|
||||||
<CP color="custom">{description}</CP>
|
<p className="text-white text-sm leading-relaxed font-light">
|
||||||
|
{description}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Description for Mobile - Below cube */}
|
{/* Description for Mobile - Below cube */}
|
||||||
{isActive && (
|
</motion.div>
|
||||||
<motion.div
|
|
||||||
initial={{ opacity: 0, y: 10 }}
|
|
||||||
animate={{ opacity: 1, y: 0 }}
|
|
||||||
exit={{ opacity: 0, y: 10 }}
|
|
||||||
transition={{ duration: 0.3 }}
|
|
||||||
className="lg:hidden absolute top-full left-1/2 -translate-x-1/2 mt-8 z-50"
|
|
||||||
>
|
|
||||||
<div className="w-64 sm:w-80 px-4 text-[#2F3178]">
|
|
||||||
<h4 className="text-base font-semibold mb-2 text-center">
|
|
||||||
{descriptionTitle}
|
|
||||||
</h4>
|
|
||||||
<CP className="text-center" color="custom">{description}</CP>
|
|
||||||
</div>
|
|
||||||
</motion.div>
|
|
||||||
)}
|
|
||||||
</motion.div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export function ScrollDown() {
|
|||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
onClick={scrollToNext}
|
onClick={scrollToNext}
|
||||||
className="fixed bottom-8 right-8 z-50 flex items-center gap-x-2 text-2xl font-medium text-[#1c1c49] lg:text-3xl animate-blink"
|
className="fixed bottom-8 right-8 z-50 flex items-center gap-x-2 text-2xl font-medium text-white lg:text-3xl animate-blink"
|
||||||
>
|
>
|
||||||
<span>scroll</span>
|
<span>scroll</span>
|
||||||
<ChevronDoubleDownIcon className="h-6 w-6" />
|
<ChevronDoubleDownIcon className="h-6 w-6" />
|
||||||
|
|||||||
@@ -2,45 +2,53 @@
|
|||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { Cube } from "@/components/ui/Cube";
|
import { Cube } from "@/components/ui/Cube"
|
||||||
|
|
||||||
const stackData = [
|
const stackData = [
|
||||||
{
|
{
|
||||||
id: "agent",
|
id: "agent",
|
||||||
title: "Agent Layer",
|
title: "Agent Layer",
|
||||||
descriptionTitle: "Personal Agents - Secure & Sovereign",
|
descriptionTitle: "Your sovereign agent with private memory and permissioned data access—always under your control.",
|
||||||
description:
|
description:
|
||||||
"Personal AI agents operate as secure digital twins, providing tailored intelligent assistance. They interact with existing chat, MCP agents, and coding tools while maintaining sovereignty and ecosystem compatibility.",
|
"Choose from a wide library of open-source LLMs, paired with built-in semantic search and retrieval.\nIt coordinates across people, apps, and other agents to plan, create, and execute.\nIt operates inside a compliant legal & financial sandbox, ready for real-world transactions and operations.\nMore than just an assistant—an intelligent partner that learns and does your way.",
|
||||||
position: "top",
|
position: "top",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "ai",
|
id: "network",
|
||||||
title: "AI Layer",
|
title: "Network Layer",
|
||||||
descriptionTitle: "AI Agents & AI Brains + Mycelium Code & Compute Sandboxes",
|
descriptionTitle: "A global, end-to-end encrypted overlay that simply doesn’t break.",
|
||||||
description:
|
description:
|
||||||
"Intelligence core combining LLMs with specialized AI agents. Mycelium-powered sandboxes provide secure environments for development, testing, and compilation with active memory systems and unbreakable network architecture.",
|
"Shortest-path routing moves your traffic the fastest way, every time.\nInstant discovery with integrated DNS, semantic search, and indexing.\nA distributed CDN and edge delivery keep content available and tamper-resistant worldwide.\nBuilt-in tool services and secure coding sandboxes—seamless on phones, desktops, and edge.",
|
||||||
position: "middle",
|
position: "middle",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "cloud",
|
id: "cloud",
|
||||||
title: "Cloud Layer",
|
title: "Cloud Layer",
|
||||||
descriptionTitle: "Mycelium Compute & Storage - Decentralized Infrastructure Layer",
|
descriptionTitle: "An autonomous, stateless OS that enforces pre-deterministic deployments you define.",
|
||||||
description:
|
description:
|
||||||
"Foundation runs bare metal Zero OS enabling autonomous cloud. Decentralized infrastructure supports Web2, Web3, AI workloads with superior scalability. Built on twenty years cloud experience.",
|
"Workloads are cryptographically bound to your private key—location and access are yours.\nNo cloud vendor or middleman in the path: end-to-end ownership and isolation by default.\nGeo-aware placement delivers locality, compliance, and ultra-low latency where it matters.\nEncrypted, erasure-coded storage, decentralized compute and GPU on demand—including LLMs.",
|
||||||
position: "bottom",
|
position: "bottom",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export function StackedCubes() {
|
export function StackedCubes() {
|
||||||
const [active, setActive] = useState<string | null>("agent");
|
const [active, setActive] = useState<string | null>("agent");
|
||||||
|
const [selectedForMobile, setSelectedForMobile] = useState<string | null>("agent");
|
||||||
|
|
||||||
|
const handleCubeClick = (id: string) => {
|
||||||
|
setSelectedForMobile(prev => (prev === id ? null : id));
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectedMobileLayer = stackData.find(layer => layer.id === selectedForMobile);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
<div
|
<div
|
||||||
className="relative w-full flex items-center justify-center lg:justify-start min-h-[600px] sm:min-h-[700px] lg:min-h-[600px]"
|
className="relative w-full flex items-center justify-center lg:justify-center min-h-[450px] lg:min-h-[400px]"
|
||||||
onMouseLeave={() => setActive("agent")}
|
onMouseLeave={() => setActive("agent")}
|
||||||
>
|
>
|
||||||
<motion.div
|
<motion.div
|
||||||
className="relative ml-0 sm:ml-4 lg:ml-8 h-[600px] w-96"
|
className="relative lg:pl-0 pl-6 h-[300px] lg:h-[400px] w-64 sm:w-80 lg:w-96 scale-120 lg:scale-100"
|
||||||
animate={{ y: ["-8px", "8px"] }}
|
animate={{ y: ["-8px", "8px"] }}
|
||||||
transition={{
|
transition={{
|
||||||
duration: 4,
|
duration: 4,
|
||||||
@@ -54,7 +62,7 @@ export function StackedCubes() {
|
|||||||
key={layer.id}
|
key={layer.id}
|
||||||
className="absolute"
|
className="absolute"
|
||||||
style={{
|
style={{
|
||||||
top: `${index * 140}px`,
|
top: `calc(${index * 30}% - ${index * 10}px)`,
|
||||||
zIndex: active === layer.id ? 20 : 10 - index,
|
zIndex: active === layer.id ? 20 : 10 - index,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -66,10 +74,22 @@ export function StackedCubes() {
|
|||||||
index={index}
|
index={index}
|
||||||
onHover={() => setActive(layer.id)}
|
onHover={() => setActive(layer.id)}
|
||||||
onLeave={() => {}}
|
onLeave={() => {}}
|
||||||
|
onClick={() => handleCubeClick(layer.id)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
|
{selectedMobileLayer && (
|
||||||
|
<div className="lg:hidden w-full max-w-md p-6 -mt-8 bg-gray-800/50 rounded-lg">
|
||||||
|
<h4 className="text-white text-lg font-semibold mb-2 text-center">
|
||||||
|
{selectedMobileLayer.descriptionTitle}
|
||||||
|
</h4>
|
||||||
|
<p className="text-gray-300 text-sm leading-relaxed text-center">
|
||||||
|
{selectedMobileLayer.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
79
src/components/ui/bento-grid.tsx
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { CT, CP } from "@/components/Texts";
|
||||||
|
import Image from 'next/image';
|
||||||
|
import React from 'react';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
|
export const BentoGrid = ({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
className?: string;
|
||||||
|
children?: React.ReactNode;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"mx-4 grid max-w-6xl grid-cols-1 gap-4 lg:grid-cols-3",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
interface BentoGridItemProps {
|
||||||
|
className?: string;
|
||||||
|
title?: string | React.ReactNode;
|
||||||
|
subtitle?: string | React.ReactNode;
|
||||||
|
description?: string | React.ReactNode;
|
||||||
|
img?: string;
|
||||||
|
video?: string;
|
||||||
|
rowHeight?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BentoGridItem = React.forwardRef<HTMLDivElement, BentoGridItemProps>(
|
||||||
|
({ className, title, subtitle, description, img, video, rowHeight }, ref) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"group/bento shadow-input row-span-1 flex flex-col justify-between rounded-xl border border-black bg-black/10 backdrop-blur-md transition-all duration-300 ease-in-out hover:scale-105 hover:border-black hover:bg-black/40",
|
||||||
|
rowHeight ? rowHeight : "h-full",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className="relative w-full h-[65%] min-h-[6rem] bg-transparent overflow-hidden">
|
||||||
|
{video ? (
|
||||||
|
<video
|
||||||
|
src={video}
|
||||||
|
autoPlay
|
||||||
|
loop
|
||||||
|
muted
|
||||||
|
playsInline
|
||||||
|
className="w-full h-full object-cover opacity-90 group-hover/bento:opacity-100 transition-opacity duration-300"
|
||||||
|
/>
|
||||||
|
) : img ? (
|
||||||
|
<Image
|
||||||
|
src={img}
|
||||||
|
alt={title as string}
|
||||||
|
width={300}
|
||||||
|
height={300}
|
||||||
|
className="w-full h-full object-cover opacity-90 group-hover/bento:opacity-100 transition-opacity duration-300"
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<div className="p-4 transition bg-white/5 hover:bg-white/7 backdrop-blur-md duration-200 group-hover/bento:translate-x-2 ">
|
||||||
|
<CT>{title}</CT>
|
||||||
|
<CP className="font-medium">{subtitle}</CP>
|
||||||
|
<CP className="mt-2">{description}</CP>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
BentoGridItem.displayName = "BentoGridItem";
|
||||||
|
|
||||||
|
export const MotionBentoGridItem = motion(BentoGridItem);
|
||||||
158
src/components/ui/globe.tsx
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import createGlobe, { COBEOptions } from "cobe";
|
||||||
|
import { useMotionValue, useSpring } from "motion/react";
|
||||||
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
const MOVEMENT_DAMPING = 1400;
|
||||||
|
|
||||||
|
const GLOBE_CONFIG: COBEOptions = {
|
||||||
|
width: 800,
|
||||||
|
height: 800,
|
||||||
|
onRender: () => {},
|
||||||
|
devicePixelRatio: 2,
|
||||||
|
phi: 0,
|
||||||
|
theta: 0.3,
|
||||||
|
dark: 0,
|
||||||
|
diffuse: 0.25, // softer shading for premium look
|
||||||
|
mapSamples: 16000,
|
||||||
|
mapBrightness: 1.1,
|
||||||
|
baseColor: [0.8, 0.8, 0.8], // sleek dark gray globe
|
||||||
|
markerColor: [0.3, 0.6, 1], // soft, elegant blue
|
||||||
|
glowColor: [0.8, 0.8, 0.85], // subtle glow
|
||||||
|
markers: [
|
||||||
|
// --- Core Global Markers ---
|
||||||
|
{ location: [14.5995, 120.9842], size: 0.03 }, // Manila
|
||||||
|
{ location: [19.076, 72.8777], size: 0.1 }, // Mumbai
|
||||||
|
{ location: [23.8103, 90.4125], size: 0.05 }, // Dhaka
|
||||||
|
{ location: [30.0444, 31.2357], size: 0.07 }, // Cairo
|
||||||
|
{ location: [39.9042, 116.4074], size: 0.08 }, // Beijing
|
||||||
|
{ location: [-23.5505, -46.6333], size: 0.1 }, // São Paulo
|
||||||
|
{ location: [19.4326, -99.1332], size: 0.1 }, // Mexico City
|
||||||
|
{ location: [40.7128, -74.006], size: 0.1 }, // New York
|
||||||
|
{ location: [34.6937, 135.5022], size: 0.05 }, // Osaka
|
||||||
|
{ location: [41.0082, 28.9784], size: 0.06 }, // Istanbul
|
||||||
|
{ location: [48.8566, 2.3522], size: 0.08 }, // Paris
|
||||||
|
{ location: [51.5072, -0.1276], size: 0.08 }, // London
|
||||||
|
{ location: [52.52, 13.405], size: 0.07 }, // Berlin
|
||||||
|
{ location: [35.6895, 139.6917], size: 0.06 }, // Tokyo
|
||||||
|
{ location: [-33.8688, 151.2093], size: 0.06 }, // Sydney
|
||||||
|
{ location: [-1.2921, 36.8219], size: 0.05 }, // Nairobi
|
||||||
|
{ location: [-34.6037, -58.3816], size: 0.07 }, // Buenos Aires
|
||||||
|
{ location: [37.7749, -122.4194], size: 0.08 }, // San Francisco
|
||||||
|
{ location: [1.3521, 103.8198], size: 0.06 }, // Singapore
|
||||||
|
{ location: [28.6139, 77.2090], size: 0.08 }, // New Delhi
|
||||||
|
{ location: [13.7563, 100.5018], size: 0.06 }, // Bangkok
|
||||||
|
{ location: [59.9343, 30.3351], size: 0.05 }, // St. Petersburg
|
||||||
|
{ location: [33.6844, 73.0479], size: 0.05 }, // Islamabad
|
||||||
|
{ location: [25.276987, 55.296249], size: 0.07 }, // Dubai
|
||||||
|
{ location: [60.1699, 24.9384], size: 0.05 }, // Helsinki
|
||||||
|
{ location: [43.6532, -79.3832], size: 0.07 }, // Toronto
|
||||||
|
{ location: [6.5244, 3.3792], size: 0.08 }, // Lagos
|
||||||
|
{ location: [50.1109, 8.6821], size: 0.06 }, // Frankfurt
|
||||||
|
|
||||||
|
// --- 12 New US + European Cities ---
|
||||||
|
{ location: [34.0522, -118.2437], size: 0.08 }, // Los Angeles
|
||||||
|
{ location: [41.8781, -87.6298], size: 0.07 }, // Chicago
|
||||||
|
{ location: [29.7604, -95.3698], size: 0.07 }, // Houston
|
||||||
|
{ location: [25.7617, -80.1918], size: 0.07 }, // Miami
|
||||||
|
{ location: [45.5017, -73.5673], size: 0.06 }, // Montreal
|
||||||
|
{ location: [47.6062, -122.3321], size: 0.06 }, // Seattle
|
||||||
|
{ location: [40.4406, -79.9959], size: 0.05 }, // Pittsburgh
|
||||||
|
{ location: [41.3851, 2.1734], size: 0.06 }, // Barcelona
|
||||||
|
{ location: [45.4642, 9.19], size: 0.06 }, // Milan
|
||||||
|
{ location: [52.3676, 4.9041], size: 0.06 }, // Amsterdam
|
||||||
|
{ location: [38.7169, -9.139], size: 0.05 }, // Lisbon
|
||||||
|
{ location: [59.3293, 18.0686], size: 0.05 }, // Stockholmx
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Globe({
|
||||||
|
className,
|
||||||
|
config = GLOBE_CONFIG,
|
||||||
|
}: {
|
||||||
|
className?: string;
|
||||||
|
config?: COBEOptions;
|
||||||
|
}) {
|
||||||
|
let phi = 0;
|
||||||
|
let width = 0;
|
||||||
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
|
const pointerInteracting = useRef<number | null>(null);
|
||||||
|
|
||||||
|
const r = useMotionValue(0);
|
||||||
|
const rs = useSpring(r, {
|
||||||
|
mass: 1,
|
||||||
|
damping: 35, // slightly smoother motion
|
||||||
|
stiffness: 100,
|
||||||
|
});
|
||||||
|
|
||||||
|
const updatePointerInteraction = (value: number | null) => {
|
||||||
|
pointerInteracting.current = value;
|
||||||
|
if (canvasRef.current) {
|
||||||
|
canvasRef.current.style.cursor = value !== null ? "grabbing" : "grab";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateMovement = (clientX: number) => {
|
||||||
|
if (pointerInteracting.current !== null) {
|
||||||
|
const delta = clientX - pointerInteracting.current;
|
||||||
|
r.set(r.get() + delta / MOVEMENT_DAMPING);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const onResize = () => {
|
||||||
|
if (canvasRef.current) width = canvasRef.current.offsetWidth;
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener("resize", onResize);
|
||||||
|
onResize();
|
||||||
|
|
||||||
|
const globe = createGlobe(canvasRef.current!, {
|
||||||
|
...config,
|
||||||
|
width: width * 2,
|
||||||
|
height: width * 2,
|
||||||
|
onRender: (state) => {
|
||||||
|
if (!pointerInteracting.current) phi += 0.004; // slightly slower rotation for elegance
|
||||||
|
state.phi = phi + rs.get();
|
||||||
|
state.width = width * 2;
|
||||||
|
state.height = width * 2;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => (canvasRef.current!.style.opacity = "1"), 0);
|
||||||
|
return () => {
|
||||||
|
globe.destroy();
|
||||||
|
window.removeEventListener("resize", onResize);
|
||||||
|
};
|
||||||
|
}, [rs, config]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
// Radial gradient background that fades to pure black at edges
|
||||||
|
"absolute inset-0 mx-auto aspect-[1/1] w-full max-w-[600px] rounded-full",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<canvas
|
||||||
|
className={cn(
|
||||||
|
"size-full opacity-0 transition-opacity duration-500 [contain:layout_paint_size]",
|
||||||
|
)}
|
||||||
|
ref={canvasRef}
|
||||||
|
onPointerDown={(e) => {
|
||||||
|
pointerInteracting.current = e.clientX;
|
||||||
|
updatePointerInteraction(e.clientX);
|
||||||
|
}}
|
||||||
|
onPointerUp={() => updatePointerInteraction(null)}
|
||||||
|
onPointerOut={() => updatePointerInteraction(null)}
|
||||||
|
onMouseMove={(e) => updateMovement(e.clientX)}
|
||||||
|
onTouchMove={(e) =>
|
||||||
|
e.touches[0] && updateMovement(e.touches[0].clientX)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
21
src/hooks/useMediaQuery.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useState, useEffect } from 'react'
|
||||||
|
|
||||||
|
export function useMediaQuery(query: string) {
|
||||||
|
const [matches, setMatches] = useState(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const media = window.matchMedia(query)
|
||||||
|
if (media.matches !== matches) {
|
||||||
|
setMatches(media.matches)
|
||||||
|
}
|
||||||
|
const listener = () => {
|
||||||
|
setMatches(media.matches)
|
||||||
|
}
|
||||||
|
media.addEventListener('change', listener)
|
||||||
|
return () => media.removeEventListener('change', listener)
|
||||||
|
}, [matches, query])
|
||||||
|
|
||||||
|
return matches
|
||||||
|
}
|
||||||
39
src/hooks/useResponsiveCarousel.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
// 🔧 Carousel Config
|
||||||
|
const desktopConfig = {
|
||||||
|
GAP: 300,
|
||||||
|
ROT_Y: 18,
|
||||||
|
DEPTH: 210,
|
||||||
|
SCALE_DROP: 0.12,
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileConfig = {
|
||||||
|
GAP: 110, // Smaller gap for mobile
|
||||||
|
ROT_Y: 0, // Flatter view on mobile
|
||||||
|
DEPTH: 150, // Less depth
|
||||||
|
SCALE_DROP: 0.1, // Less aggressive scaling
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useResponsiveCarousel = () => {
|
||||||
|
const [config, setConfig] = useState(desktopConfig);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const checkScreenSize = () => {
|
||||||
|
if (window.innerWidth < 768) {
|
||||||
|
setConfig(mobileConfig);
|
||||||
|
} else {
|
||||||
|
setConfig(desktopConfig);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
checkScreenSize();
|
||||||
|
window.addEventListener('resize', checkScreenSize);
|
||||||
|
|
||||||
|
return () => window.removeEventListener('resize', checkScreenSize);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
};
|
||||||
@@ -1,118 +1 @@
|
|||||||
<svg width="80" height="80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="80" zoomAndPan="magnify" viewBox="0 0 60 60" height="80" preserveAspectRatio="xMidYMid meet" version="1.0"><defs><clipPath id="38e6314a1e"><path d="M 6 12.121094 L 31 12.121094 L 31 34 L 6 34 Z M 6 12.121094 " clip-rule="nonzero"/></clipPath><clipPath id="e1a7034db0"><path d="M 6 12.121094 L 31 12.121094 L 31 34 L 6 34 Z M 6 12.121094 " clip-rule="nonzero"/></clipPath></defs><g clip-path="url(#38e6314a1e)"><path fill="#5999f6" d="M 29.101562 28.996094 L 18.433594 28.996094 L 10.6875 33.613281 C 10.378906 33.820312 10.019531 33.511719 10.070312 33.152344 L 11.199219 28.945312 L 7.761719 28.945312 C 6.839844 28.945312 6.019531 28.125 6.019531 27.203125 L 6.019531 13.863281 C 6.019531 12.941406 6.839844 12.121094 7.761719 12.121094 L 29.101562 12.121094 C 30.027344 12.121094 30.847656 12.941406 30.847656 13.863281 L 30.847656 27.304688 C 30.847656 28.277344 30.078125 28.996094 29.101562 28.996094 Z M 29.101562 28.996094 " fill-opacity="1" fill-rule="nonzero"/></g><path fill="#015eff" d="M 23.921875 41.617188 L 37.824219 41.617188 L 47.929688 47.617188 C 48.339844 47.875 48.800781 47.464844 48.75 47.054688 L 47.261719 41.617188 L 51.722656 41.617188 C 52.957031 41.617188 53.980469 40.539062 53.980469 39.359375 L 53.980469 21.96875 C 53.980469 20.738281 52.902344 19.710938 51.722656 19.710938 L 24.023438 19.710938 C 22.792969 19.710938 21.765625 20.789062 21.765625 21.96875 L 21.765625 39.460938 C 21.613281 40.640625 22.691406 41.617188 23.921875 41.617188 Z M 23.921875 41.617188 " fill-opacity="1" fill-rule="nonzero"/><path fill="#ffffff" d="M 37.824219 28.945312 C 38.796875 28.945312 39.515625 29.765625 39.515625 30.636719 C 39.515625 31.511719 38.695312 32.332031 37.824219 32.332031 C 36.847656 32.332031 36.128906 31.511719 36.128906 30.636719 C 36.128906 29.765625 36.847656 28.945312 37.824219 28.945312 Z M 37.824219 28.945312 " fill-opacity="1" fill-rule="nonzero"/><path fill="#ffffff" d="M 44.800781 28.945312 C 45.773438 28.945312 46.492188 29.765625 46.492188 30.636719 C 46.492188 31.511719 45.671875 32.332031 44.800781 32.332031 C 43.824219 32.332031 43.105469 31.511719 43.105469 30.636719 C 43.105469 29.765625 43.824219 28.945312 44.800781 28.945312 Z M 44.800781 28.945312 " fill-opacity="1" fill-rule="nonzero"/><path fill="#ffffff" d="M 30.796875 28.945312 C 31.769531 28.945312 32.488281 29.765625 32.488281 30.636719 C 32.488281 31.511719 31.667969 32.332031 30.796875 32.332031 C 29.820312 32.332031 29.101562 31.511719 29.101562 30.636719 C 29.101562 29.765625 29.820312 28.945312 30.796875 28.945312 Z M 30.796875 28.945312 " fill-opacity="1" fill-rule="nonzero"/><g clip-path="url(#e1a7034db0)"><path fill="#5999f6" d="M 29.101562 28.996094 L 18.433594 28.996094 L 10.6875 33.613281 C 10.378906 33.820312 10.019531 33.511719 10.070312 33.152344 L 11.199219 28.945312 L 7.761719 28.945312 C 6.839844 28.945312 6.019531 28.125 6.019531 27.203125 L 6.019531 13.863281 C 6.019531 12.941406 6.839844 12.121094 7.761719 12.121094 L 29.101562 12.121094 C 30.027344 12.121094 30.847656 12.941406 30.847656 13.863281 L 30.847656 27.304688 C 30.847656 28.277344 30.078125 28.996094 29.101562 28.996094 Z M 29.101562 28.996094 " fill-opacity="1" fill-rule="nonzero"/></g><path fill="#015eff" d="M 23.921875 41.617188 L 37.824219 41.617188 L 47.929688 47.617188 C 48.339844 47.875 48.800781 47.464844 48.75 47.054688 L 47.261719 41.617188 L 51.722656 41.617188 C 52.957031 41.617188 53.980469 40.539062 53.980469 39.359375 L 53.980469 21.96875 C 53.980469 20.738281 52.902344 19.710938 51.722656 19.710938 L 24.023438 19.710938 C 22.792969 19.710938 21.765625 20.789062 21.765625 21.96875 L 21.765625 39.460938 C 21.613281 40.640625 22.691406 41.617188 23.921875 41.617188 Z M 23.921875 41.617188 " fill-opacity="1" fill-rule="nonzero"/><path fill="#ffffff" d="M 37.824219 28.945312 C 38.796875 28.945312 39.515625 29.765625 39.515625 30.636719 C 39.515625 31.511719 38.695312 32.332031 37.824219 32.332031 C 36.847656 32.332031 36.128906 31.511719 36.128906 30.636719 C 36.128906 29.765625 36.847656 28.945312 37.824219 28.945312 Z M 37.824219 28.945312 " fill-opacity="1" fill-rule="nonzero"/><path fill="#ffffff" d="M 44.800781 28.945312 C 45.773438 28.945312 46.492188 29.765625 46.492188 30.636719 C 46.492188 31.511719 45.671875 32.332031 44.800781 32.332031 C 43.824219 32.332031 43.105469 31.511719 43.105469 30.636719 C 43.105469 29.765625 43.824219 28.945312 44.800781 28.945312 Z M 44.800781 28.945312 " fill-opacity="1" fill-rule="nonzero"/><path fill="#ffffff" d="M 30.796875 28.945312 C 31.769531 28.945312 32.488281 29.765625 32.488281 30.636719 C 32.488281 31.511719 31.667969 32.332031 30.796875 32.332031 C 29.820312 32.332031 29.101562 31.511719 29.101562 30.636719 C 29.101562 29.765625 29.820312 28.945312 30.796875 28.945312 Z M 30.796875 28.945312 " fill-opacity="1" fill-rule="nonzero"/></svg>
|
||||||
<path d="M3.2 0H0v3.2h3.2V0ZM3.2 3.2H0v3.2h3.2V3.2ZM3.2 6.4H0v3.2h3.2V6.4Z" fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M3.2 9.6H0v3.2h3.2V9.6ZM3.2 12.8H0V16h3.2v-3.2ZM3.2 16H0v3.2h3.2V16ZM3.2 19.2H0v3.2h3.2v-3.2ZM3.2 25.6H0v3.2h3.2v-3.2ZM3.2 35.2H0v3.2h3.2v-3.2ZM3.2 57.6H0v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path d="M3.2 60.8H0V64h3.2v-3.2ZM3.2 64H0v3.2h3.2V64ZM3.2 67.2H0v3.2h3.2v-3.2ZM3.2 70.4H0v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M3.2 73.6H0v3.2h3.2v-3.2ZM3.2 76.8H0V80h3.2v-3.2ZM6.4 0H3.2v3.2h3.2V0ZM6.4 19.2H3.2v3.2h3.2v-3.2ZM6.4 25.6H3.2v3.2h3.2v-3.2ZM6.4 28.8H3.2V32h3.2v-3.2ZM6.4 32H3.2v3.2h3.2V32ZM6.4 35.2H3.2v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M6.4 38.4H3.2v3.2h3.2v-3.2ZM6.4 48H3.2v3.2h3.2V48ZM6.4 51.2H3.2v3.2h3.2v-3.2ZM6.4 57.6H3.2v3.2h3.2v-3.2ZM6.4 76.8H3.2V80h3.2v-3.2ZM9.6 0H6.4v3.2h3.2V0ZM9.6 6.4H6.4v3.2h3.2V6.4Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M9.6 9.6H6.4v3.2h3.2V9.6ZM9.6 12.8H6.4V16h3.2v-3.2ZM9.6 19.2H6.4v3.2h3.2v-3.2ZM9.6 28.8H6.4V32h3.2v-3.2ZM9.6 32H6.4v3.2h3.2V32ZM9.6 41.6H6.4v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M9.6 44.8H6.4V48h3.2v-3.2ZM9.6 57.6H6.4v3.2h3.2v-3.2ZM9.6 64H6.4v3.2h3.2V64ZM9.6 67.2H6.4v3.2h3.2v-3.2ZM9.6 70.4H6.4v3.2h3.2v-3.2ZM9.6 76.8H6.4V80h3.2v-3.2ZM12.8 0H9.6v3.2h3.2V0ZM12.8 6.4H9.6v3.2h3.2V6.4Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M12.8 9.6H9.6v3.2h3.2V9.6ZM12.8 12.8H9.6V16h3.2v-3.2ZM12.8 19.2H9.6v3.2h3.2v-3.2ZM12.8 25.6H9.6v3.2h3.2v-3.2ZM12.8 38.4H9.6v3.2h3.2v-3.2ZM12.8 48H9.6v3.2h3.2V48ZM12.8 51.2H9.6v3.2h3.2v-3.2ZM12.8 57.6H9.6v3.2h3.2v-3.2ZM12.8 64H9.6v3.2h3.2V64ZM12.8 67.2H9.6v3.2h3.2v-3.2ZM12.8 70.4H9.6v3.2h3.2v-3.2ZM12.8 76.8H9.6V80h3.2v-3.2ZM16 0h-3.2v3.2H16V0ZM16 6.4h-3.2v3.2H16V6.4Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M16 9.6h-3.2v3.2H16V9.6ZM16 12.8h-3.2V16H16v-3.2ZM16 19.2h-3.2v3.2H16v-3.2ZM16 25.6h-3.2v3.2H16v-3.2ZM16 41.6h-3.2v3.2H16v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M16 44.8h-3.2V48H16v-3.2ZM16 57.6h-3.2v3.2H16v-3.2ZM16 64h-3.2v3.2H16V64ZM16 67.2h-3.2v3.2H16v-3.2ZM16 70.4h-3.2v3.2H16v-3.2ZM16 76.8h-3.2V80H16v-3.2ZM19.2 0H16v3.2h3.2V0ZM19.2 19.2H16v3.2h3.2v-3.2ZM19.2 28.8H16V32h3.2v-3.2ZM19.2 44.8H16V48h3.2v-3.2ZM19.2 57.6H16v3.2h3.2v-3.2ZM19.2 76.8H16V80h3.2v-3.2ZM22.4 0h-3.2v3.2h3.2V0ZM22.4 3.2h-3.2v3.2h3.2V3.2ZM22.4 6.4h-3.2v3.2h3.2V6.4Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M22.4 9.6h-3.2v3.2h3.2V9.6ZM22.4 12.8h-3.2V16h3.2v-3.2ZM22.4 16h-3.2v3.2h3.2V16ZM22.4 19.2h-3.2v3.2h3.2v-3.2ZM22.4 25.6h-3.2v3.2h3.2v-3.2ZM22.4 32h-3.2v3.2h3.2V32ZM22.4 38.4h-3.2v3.2h3.2v-3.2ZM22.4 44.8h-3.2V48h3.2v-3.2ZM22.4 51.2h-3.2v3.2h3.2v-3.2ZM22.4 57.6h-3.2v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M22.4 60.8h-3.2V64h3.2v-3.2ZM22.4 64h-3.2v3.2h3.2V64ZM22.4 67.2h-3.2v3.2h3.2v-3.2ZM22.4 70.4h-3.2v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M22.4 73.6h-3.2v3.2h3.2v-3.2ZM22.4 76.8h-3.2V80h3.2v-3.2ZM25.6 28.8h-3.2V32h3.2v-3.2ZM25.6 32h-3.2v3.2h3.2V32ZM25.6 35.2h-3.2v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M25.6 38.4h-3.2v3.2h3.2v-3.2ZM25.6 44.8h-3.2V48h3.2v-3.2ZM25.6 48h-3.2v3.2h3.2V48ZM25.6 51.2h-3.2v3.2h3.2v-3.2ZM28.8 0h-3.2v3.2h3.2V0ZM28.8 19.2h-3.2v3.2h3.2v-3.2ZM28.8 22.4h-3.2v3.2h3.2v-3.2ZM28.8 28.8h-3.2V32h3.2v-3.2ZM28.8 32h-3.2v3.2h3.2V32ZM28.8 35.2h-3.2v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path d="M28.8 38.4h-3.2v3.2h3.2v-3.2ZM28.8 44.8h-3.2V48h3.2v-3.2ZM28.8 51.2h-3.2v3.2h3.2v-3.2Z" fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M28.8 54.4h-3.2v3.2h3.2v-3.2ZM28.8 64h-3.2v3.2h3.2V64ZM28.8 67.2h-3.2v3.2h3.2v-3.2ZM28.8 73.6h-3.2v3.2h3.2v-3.2ZM28.8 76.8h-3.2V80h3.2v-3.2ZM32 0h-3.2v3.2H32V0ZM32 6.4h-3.2v3.2H32V6.4ZM32 16h-3.2v3.2H32V16ZM32 22.4h-3.2v3.2H32v-3.2ZM32 25.6h-3.2v3.2H32v-3.2ZM32 32h-3.2v3.2H32V32ZM32 38.4h-3.2v3.2H32v-3.2ZM32 54.4h-3.2v3.2H32v-3.2ZM32 57.6h-3.2v3.2H32v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M32 60.8h-3.2V64H32v-3.2ZM32 76.8h-3.2V80H32v-3.2ZM35.2 0H32v3.2h3.2V0ZM35.2 9.6H32v3.2h3.2V9.6ZM35.2 12.8H32V16h3.2v-3.2ZM35.2 19.2H32v3.2h3.2v-3.2ZM35.2 28.8H32V32h3.2v-3.2ZM35.2 38.4H32v3.2h3.2v-3.2ZM35.2 41.6H32v3.2h3.2v-3.2ZM35.2 48H32v3.2h3.2V48ZM35.2 57.6H32v3.2h3.2v-3.2ZM35.2 64H32v3.2h3.2V64ZM35.2 76.8H32V80h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path d="M38.4 0h-3.2v3.2h3.2V0ZM38.4 3.2h-3.2v3.2h3.2V3.2ZM38.4 6.4h-3.2v3.2h3.2V6.4Z" fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M38.4 9.6h-3.2v3.2h3.2V9.6ZM38.4 12.8h-3.2V16h3.2v-3.2ZM38.4 16h-3.2v3.2h3.2V16ZM38.4 51.2h-3.2v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M38.4 54.4h-3.2v3.2h3.2v-3.2ZM38.4 60.8h-3.2V64h3.2v-3.2ZM38.4 64h-3.2v3.2h3.2V64ZM38.4 70.4h-3.2v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M38.4 73.6h-3.2v3.2h3.2v-3.2ZM38.4 76.8h-3.2V80h3.2v-3.2ZM41.6 3.2h-3.2v3.2h3.2V3.2ZM41.6 12.8h-3.2V16h3.2v-3.2ZM41.6 19.2h-3.2v3.2h3.2v-3.2ZM41.6 22.4h-3.2v3.2h3.2v-3.2ZM41.6 25.6h-3.2v3.2h3.2v-3.2ZM41.6 32h-3.2v3.2h3.2V32ZM41.6 41.6h-3.2v3.2h3.2v-3.2ZM41.6 48h-3.2v3.2h3.2V48ZM41.6 51.2h-3.2v3.2h3.2v-3.2ZM41.6 57.6h-3.2v3.2h3.2v-3.2ZM41.6 67.2h-3.2v3.2h3.2v-3.2ZM41.6 73.6h-3.2v3.2h3.2v-3.2ZM41.6 76.8h-3.2V80h3.2v-3.2ZM44.8 0h-3.2v3.2h3.2V0ZM44.8 6.4h-3.2v3.2h3.2V6.4Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path d="M44.8 22.4h-3.2v3.2h3.2v-3.2ZM44.8 32h-3.2v3.2h3.2V32ZM44.8 41.6h-3.2v3.2h3.2v-3.2Z" fill="#171717" />
|
|
||||||
<path d="M44.8 44.8h-3.2V48h3.2v-3.2ZM44.8 51.2h-3.2v3.2h3.2v-3.2Z" fill="#171717" />
|
|
||||||
<path d="M44.8 54.4h-3.2v3.2h3.2v-3.2ZM44.8 57.6h-3.2v3.2h3.2v-3.2Z" fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M44.8 60.8h-3.2V64h3.2v-3.2ZM44.8 64h-3.2v3.2h3.2V64ZM44.8 67.2h-3.2v3.2h3.2v-3.2ZM44.8 70.4h-3.2v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M44.8 73.6h-3.2v3.2h3.2v-3.2ZM44.8 76.8h-3.2V80h3.2v-3.2ZM48 0h-3.2v3.2H48V0ZM48 16h-3.2v3.2H48V16ZM48 19.2h-3.2v3.2H48v-3.2ZM48 25.6h-3.2v3.2H48v-3.2ZM48 44.8h-3.2V48H48v-3.2ZM48 54.4h-3.2v3.2H48v-3.2ZM48 57.6h-3.2v3.2H48v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M48 60.8h-3.2V64H48v-3.2ZM48 67.2h-3.2v3.2H48v-3.2ZM51.2 6.4H48v3.2h3.2V6.4ZM51.2 12.8H48V16h3.2v-3.2ZM51.2 22.4H48v3.2h3.2v-3.2ZM51.2 25.6H48v3.2h3.2v-3.2ZM51.2 28.8H48V32h3.2v-3.2ZM51.2 32H48v3.2h3.2V32ZM51.2 35.2H48v3.2h3.2v-3.2ZM51.2 41.6H48v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M51.2 44.8H48V48h3.2v-3.2ZM51.2 54.4H48v3.2h3.2v-3.2ZM51.2 60.8H48V64h3.2v-3.2ZM51.2 64H48v3.2h3.2V64ZM54.4 6.4h-3.2v3.2h3.2V6.4ZM54.4 12.8h-3.2V16h3.2v-3.2ZM54.4 19.2h-3.2v3.2h3.2v-3.2ZM54.4 28.8h-3.2V32h3.2v-3.2ZM54.4 32h-3.2v3.2h3.2V32ZM54.4 38.4h-3.2v3.2h3.2v-3.2ZM54.4 48h-3.2v3.2h3.2V48Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path d="M54.4 51.2h-3.2v3.2h3.2v-3.2Z" fill="#171717" />
|
|
||||||
<path d="M54.4 54.4h-3.2v3.2h3.2v-3.2ZM54.4 57.6h-3.2v3.2h3.2v-3.2Z" fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M54.4 60.8h-3.2V64h3.2v-3.2ZM54.4 64h-3.2v3.2h3.2V64ZM54.4 67.2h-3.2v3.2h3.2v-3.2ZM54.4 70.4h-3.2v3.2h3.2v-3.2ZM54.4 76.8h-3.2V80h3.2v-3.2ZM57.6 32h-3.2v3.2h3.2V32ZM57.6 41.6h-3.2v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M57.6 44.8h-3.2V48h3.2v-3.2ZM57.6 51.2h-3.2v3.2h3.2v-3.2ZM57.6 64h-3.2v3.2h3.2V64ZM57.6 70.4h-3.2v3.2h3.2v-3.2ZM57.6 76.8h-3.2V80h3.2v-3.2ZM60.8 0h-3.2v3.2h3.2V0ZM60.8 3.2h-3.2v3.2h3.2V3.2ZM60.8 6.4h-3.2v3.2h3.2V6.4Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M60.8 9.6h-3.2v3.2h3.2V9.6ZM60.8 12.8h-3.2V16h3.2v-3.2ZM60.8 16h-3.2v3.2h3.2V16ZM60.8 19.2h-3.2v3.2h3.2v-3.2ZM60.8 25.6h-3.2v3.2h3.2v-3.2ZM60.8 35.2h-3.2v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M60.8 38.4h-3.2v3.2h3.2v-3.2ZM60.8 44.8h-3.2V48h3.2v-3.2ZM60.8 48h-3.2v3.2h3.2V48ZM60.8 51.2h-3.2v3.2h3.2v-3.2ZM60.8 57.6h-3.2v3.2h3.2v-3.2ZM60.8 64h-3.2v3.2h3.2V64ZM60.8 67.2h-3.2v3.2h3.2v-3.2ZM64 0h-3.2v3.2H64V0ZM64 19.2h-3.2v3.2H64v-3.2ZM64 28.8h-3.2V32H64v-3.2ZM64 38.4h-3.2v3.2H64v-3.2ZM64 48h-3.2v3.2H64V48ZM64 51.2h-3.2v3.2H64v-3.2ZM64 64h-3.2v3.2H64V64ZM64 73.6h-3.2v3.2H64v-3.2ZM67.2 0H64v3.2h3.2V0ZM67.2 6.4H64v3.2h3.2V6.4Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M67.2 9.6H64v3.2h3.2V9.6ZM67.2 12.8H64V16h3.2v-3.2ZM67.2 19.2H64v3.2h3.2v-3.2ZM67.2 28.8H64V32h3.2v-3.2ZM67.2 41.6H64v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path d="M67.2 44.8H64V48h3.2v-3.2ZM67.2 51.2H64v3.2h3.2v-3.2Z" fill="#171717" />
|
|
||||||
<path d="M67.2 54.4H64v3.2h3.2v-3.2ZM67.2 57.6H64v3.2h3.2v-3.2Z" fill="#171717" />
|
|
||||||
<path d="M67.2 60.8H64V64h3.2v-3.2ZM67.2 64H64v3.2h3.2V64ZM67.2 70.4H64v3.2h3.2v-3.2Z" fill="#171717" />
|
|
||||||
<path d="M67.2 73.6H64v3.2h3.2v-3.2ZM70.4 0h-3.2v3.2h3.2V0ZM70.4 6.4h-3.2v3.2h3.2V6.4Z" fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M70.4 9.6h-3.2v3.2h3.2V9.6ZM70.4 12.8h-3.2V16h3.2v-3.2ZM70.4 19.2h-3.2v3.2h3.2v-3.2ZM70.4 28.8h-3.2V32h3.2v-3.2ZM70.4 32h-3.2v3.2h3.2V32ZM70.4 35.2h-3.2v3.2h3.2v-3.2ZM70.4 44.8h-3.2V48h3.2v-3.2ZM70.4 48h-3.2v3.2h3.2V48ZM70.4 70.4h-3.2v3.2h3.2v-3.2ZM70.4 76.8h-3.2V80h3.2v-3.2ZM73.6 0h-3.2v3.2h3.2V0Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path d="M73.6 6.4h-3.2v3.2h3.2V6.4Z" fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M73.6 9.6h-3.2v3.2h3.2V9.6ZM73.6 12.8h-3.2V16h3.2v-3.2ZM73.6 19.2h-3.2v3.2h3.2v-3.2ZM73.6 28.8h-3.2V32h3.2v-3.2ZM73.6 35.2h-3.2v3.2h3.2v-3.2ZM73.6 44.8h-3.2V48h3.2v-3.2ZM73.6 48h-3.2v3.2h3.2V48ZM73.6 51.2h-3.2v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path d="M73.6 54.4h-3.2v3.2h3.2v-3.2ZM73.6 70.4h-3.2v3.2h3.2v-3.2Z" fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M73.6 73.6h-3.2v3.2h3.2v-3.2ZM76.8 0h-3.2v3.2h3.2V0ZM76.8 19.2h-3.2v3.2h3.2v-3.2ZM76.8 28.8h-3.2V32h3.2v-3.2ZM76.8 35.2h-3.2v3.2h3.2v-3.2ZM76.8 41.6h-3.2v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path d="M76.8 44.8h-3.2V48h3.2v-3.2ZM76.8 51.2h-3.2v3.2h3.2v-3.2Z" fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M76.8 54.4h-3.2v3.2h3.2v-3.2ZM76.8 64h-3.2v3.2h3.2V64ZM76.8 67.2h-3.2v3.2h3.2v-3.2ZM76.8 70.4h-3.2v3.2h3.2v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path d="M76.8 73.6h-3.2v3.2h3.2v-3.2ZM80 0h-3.2v3.2H80V0ZM80 3.2h-3.2v3.2H80V3.2ZM80 6.4h-3.2v3.2H80V6.4Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M80 9.6h-3.2v3.2H80V9.6ZM80 12.8h-3.2V16H80v-3.2ZM80 16h-3.2v3.2H80V16ZM80 19.2h-3.2v3.2H80v-3.2ZM80 25.6h-3.2v3.2H80v-3.2ZM80 32h-3.2v3.2H80V32ZM80 35.2h-3.2v3.2H80v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M80 38.4h-3.2v3.2H80v-3.2ZM80 44.8h-3.2V48H80v-3.2ZM80 48h-3.2v3.2H80V48ZM80 57.6h-3.2v3.2H80v-3.2ZM80 64h-3.2v3.2H80V64ZM80 67.2h-3.2v3.2H80v-3.2ZM80 70.4h-3.2v3.2H80v-3.2Z"
|
|
||||||
fill="#171717" />
|
|
||||||
<path d="M80 73.6h-3.2v3.2H80v-3.2ZM80 76.8h-3.2V80H80v-3.2Z" fill="#171717" />
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 4.8 KiB |
@@ -1,6 +1,6 @@
|
|||||||
import { ClassValue, clsx } from "clsx";
|
import { clsx, type ClassValue } from "clsx"
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge"
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
return twMerge(clsx(inputs));
|
return twMerge(clsx(inputs))
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/pages/_document.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { Html, Head, Main, NextScript } from 'next/document'
|
||||||
|
|
||||||
|
export default function Document() {
|
||||||
|
return (
|
||||||
|
<Html lang="en">
|
||||||
|
<Head />
|
||||||
|
<body>
|
||||||
|
<Main />
|
||||||
|
<NextScript />
|
||||||
|
</body>
|
||||||
|
</Html>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,8 +1,17 @@
|
|||||||
@import 'tailwindcss';
|
@import 'tailwindcss';
|
||||||
|
@import "tw-animate-css";
|
||||||
|
|
||||||
|
@custom-variant dark (&:is(.dark *));
|
||||||
|
|
||||||
@plugin '@tailwindcss/forms';
|
@plugin '@tailwindcss/forms';
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
|
@keyframes scroll {
|
||||||
|
to {
|
||||||
|
transform: translate(calc(-50% - 0.5rem));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
--text-*: initial;
|
--text-*: initial;
|
||||||
--text-xs: 0.75rem;
|
--text-xs: 0.75rem;
|
||||||
--text-xs--line-height: 1rem;
|
--text-xs--line-height: 1rem;
|
||||||
@@ -39,7 +48,7 @@
|
|||||||
--animate-spin-reverse-slower: spin-reverse 6s linear infinite;
|
--animate-spin-reverse-slower: spin-reverse 6s linear infinite;
|
||||||
--animate-marquee-vertical: marquee-vertical 40s linear infinite;
|
--animate-marquee-vertical: marquee-vertical 40s linear infinite;
|
||||||
--animate-bounce-y: bounce-y 1.5s infinite;
|
--animate-bounce-y: bounce-y 1.5s infinite;
|
||||||
|
|
||||||
--radius-4xl: 2rem;
|
--radius-4xl: 2rem;
|
||||||
--radius-5xl: 2.5rem;
|
--radius-5xl: 2.5rem;
|
||||||
|
|
||||||
@@ -101,6 +110,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@layer utilities {
|
@layer utilities {
|
||||||
|
.animate-scroll {
|
||||||
|
animation: scroll var(--animation-duration, 40s) var(--animation-direction, forwards) linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
.animate-blink {
|
.animate-blink {
|
||||||
animation: blink 2s infinite;
|
animation: blink 2s infinite;
|
||||||
}
|
}
|
||||||
@@ -112,10 +125,132 @@
|
|||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
--animate-marquee: marquee var(--marquee-duration) linear infinite;
|
--animate-marquee: marquee var(--marquee-duration) linear infinite;
|
||||||
|
--color-sidebar-ring: var(--sidebar-ring);
|
||||||
|
--color-sidebar-border: var(--sidebar-border);
|
||||||
|
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||||
|
--color-sidebar-accent: var(--sidebar-accent);
|
||||||
|
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||||
|
--color-sidebar-primary: var(--sidebar-primary);
|
||||||
|
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||||
|
--color-sidebar: var(--sidebar);
|
||||||
|
--color-chart-5: var(--chart-5);
|
||||||
|
--color-chart-4: var(--chart-4);
|
||||||
|
--color-chart-3: var(--chart-3);
|
||||||
|
--color-chart-2: var(--chart-2);
|
||||||
|
--color-chart-1: var(--chart-1);
|
||||||
|
--color-ring: var(--ring);
|
||||||
|
--color-input: var(--input);
|
||||||
|
--color-border: var(--border);
|
||||||
|
--color-destructive: var(--destructive);
|
||||||
|
--color-accent-foreground: var(--accent-foreground);
|
||||||
|
--color-accent: var(--accent);
|
||||||
|
--color-muted-foreground: var(--muted-foreground);
|
||||||
|
--color-muted: var(--muted);
|
||||||
|
--color-secondary-foreground: var(--secondary-foreground);
|
||||||
|
--color-secondary: var(--secondary);
|
||||||
|
--color-primary-foreground: var(--primary-foreground);
|
||||||
|
--color-primary: var(--primary);
|
||||||
|
--color-popover-foreground: var(--popover-foreground);
|
||||||
|
--color-popover: var(--popover);
|
||||||
|
--color-card-foreground: var(--card-foreground);
|
||||||
|
--color-card: var(--card);
|
||||||
|
--color-foreground: var(--foreground);
|
||||||
|
--color-background: var(--background);
|
||||||
|
|
||||||
@keyframes marquee {
|
@keyframes marquee {
|
||||||
100% {
|
100% {
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--radius-sm: calc(var(--radius) - 4px);
|
||||||
|
|
||||||
|
--radius-md: calc(var(--radius) - 2px);
|
||||||
|
|
||||||
|
--radius-lg: var(--radius);
|
||||||
|
|
||||||
|
--radius-xl: calc(var(--radius) + 4px)
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--radius: 0.625rem;
|
||||||
|
--background: oklch(1 0 0);
|
||||||
|
--foreground: oklch(0.13 0.028 261.692);
|
||||||
|
--card: oklch(1 0 0);
|
||||||
|
--card-foreground: oklch(0.13 0.028 261.692);
|
||||||
|
--popover: oklch(1 0 0);
|
||||||
|
--popover-foreground: oklch(0.13 0.028 261.692);
|
||||||
|
--primary: oklch(0.21 0.034 264.665);
|
||||||
|
--primary-foreground: oklch(0.985 0.002 247.839);
|
||||||
|
--secondary: oklch(0.967 0.003 264.542);
|
||||||
|
--secondary-foreground: oklch(0.21 0.034 264.665);
|
||||||
|
--muted: oklch(0.967 0.003 264.542);
|
||||||
|
--muted-foreground: oklch(0.551 0.027 264.364);
|
||||||
|
--accent: oklch(0.967 0.003 264.542);
|
||||||
|
--accent-foreground: oklch(0.21 0.034 264.665);
|
||||||
|
--destructive: oklch(0.577 0.245 27.325);
|
||||||
|
--border: oklch(0.928 0.006 264.531);
|
||||||
|
--input: oklch(0.928 0.006 264.531);
|
||||||
|
--ring: oklch(0.707 0.022 261.325);
|
||||||
|
--chart-1: oklch(0.646 0.222 41.116);
|
||||||
|
--chart-2: oklch(0.6 0.118 184.704);
|
||||||
|
--chart-3: oklch(0.398 0.07 227.392);
|
||||||
|
--chart-4: oklch(0.828 0.189 84.429);
|
||||||
|
--chart-5: oklch(0.769 0.188 70.08);
|
||||||
|
--sidebar: oklch(0.985 0.002 247.839);
|
||||||
|
--sidebar-foreground: oklch(0.13 0.028 261.692);
|
||||||
|
--sidebar-primary: oklch(0.21 0.034 264.665);
|
||||||
|
--sidebar-primary-foreground: oklch(0.985 0.002 247.839);
|
||||||
|
--sidebar-accent: oklch(0.967 0.003 264.542);
|
||||||
|
--sidebar-accent-foreground: oklch(0.21 0.034 264.665);
|
||||||
|
--sidebar-border: oklch(0.928 0.006 264.531);
|
||||||
|
--sidebar-ring: oklch(0.707 0.022 261.325);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
--background: oklch(0.13 0.028 261.692);
|
||||||
|
--foreground: oklch(0.985 0.002 247.839);
|
||||||
|
--card: oklch(0.21 0.034 264.665);
|
||||||
|
--card-foreground: oklch(0.985 0.002 247.839);
|
||||||
|
--popover: oklch(0.21 0.034 264.665);
|
||||||
|
--popover-foreground: oklch(0.985 0.002 247.839);
|
||||||
|
--primary: oklch(0.928 0.006 264.531);
|
||||||
|
--primary-foreground: oklch(0.21 0.034 264.665);
|
||||||
|
--secondary: oklch(0.278 0.033 256.848);
|
||||||
|
--secondary-foreground: oklch(0.985 0.002 247.839);
|
||||||
|
--muted: oklch(0.278 0.033 256.848);
|
||||||
|
--muted-foreground: oklch(0.707 0.022 261.325);
|
||||||
|
--accent: oklch(0.278 0.033 256.848);
|
||||||
|
--accent-foreground: oklch(0.985 0.002 247.839);
|
||||||
|
--destructive: oklch(0.704 0.191 22.216);
|
||||||
|
--border: oklch(1 0 0 / 10%);
|
||||||
|
--input: oklch(1 0 0 / 15%);
|
||||||
|
--ring: oklch(0.551 0.027 264.364);
|
||||||
|
--chart-1: oklch(0.488 0.243 264.376);
|
||||||
|
--chart-2: oklch(0.696 0.17 162.48);
|
||||||
|
--chart-3: oklch(0.769 0.188 70.08);
|
||||||
|
--chart-4: oklch(0.627 0.265 303.9);
|
||||||
|
--chart-5: oklch(0.645 0.246 16.439);
|
||||||
|
--sidebar: oklch(0.21 0.034 264.665);
|
||||||
|
--sidebar-foreground: oklch(0.985 0.002 247.839);
|
||||||
|
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||||
|
--sidebar-primary-foreground: oklch(0.985 0.002 247.839);
|
||||||
|
--sidebar-accent: oklch(0.278 0.033 256.848);
|
||||||
|
--sidebar-accent-foreground: oklch(0.985 0.002 247.839);
|
||||||
|
--sidebar-border: oklch(1 0 0 / 10%);
|
||||||
|
--sidebar-ring: oklch(0.551 0.027 264.364);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
* {
|
||||||
|
@apply border-border outline-ring/50;
|
||||||
|
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
@apply bg-background text-foreground;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||