Compare commits
90 Commits
6e06d215fa
...
developmen
| 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 | |||
| 28fa04afc0 | |||
| 6343a22a8c | |||
| 7efede267d | |||
| 6b9b27fab9 | |||
| d3e30eaa9f |
148
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:
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
This is the official website for Mycelium Cloud, built using Next.js and Tailwind CSS.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technologies
|
||||||
|
|
||||||
|
- **Framework**: [Next.js](https://nextjs.org/)
|
||||||
|
- **Language**: [TypeScript](https://www.typescriptlang.org/)
|
||||||
|
- **Styling**: [Tailwind CSS](https://tailwindcss.com/)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- **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)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
|
||||||
|
- **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
|
```bash
|
||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, run the development server:
|
2. **Build the Project**:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run dev
|
npm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
Finally, open [http://localhost:3000](http://localhost:3000) in your browser to view the website.
|
3. **Start the Development Server**:
|
||||||
|
|
||||||
## Customizing
|
```bash
|
||||||
|
npm run start
|
||||||
|
```
|
||||||
|
|
||||||
You can start editing this template by modifying the files in the `/src` folder. The site will auto-update as you edit these files.
|
---
|
||||||
|
|
||||||
## License
|
## Development Guide
|
||||||
|
|
||||||
This site template is a commercial product and is licensed under the [Tailwind Plus license](https://tailwindcss.com/plus/license).
|
This project follows a modular, component-based architecture. Pages are assembled by combining reusable components into a single layout.
|
||||||
|
|
||||||
## Learn more
|
### Homepage Structure
|
||||||
|
|
||||||
To learn more about the technologies used in this site template, see the following resources:
|
The homepage (`src/app/(main)/page.tsx`) is composed of the following components:
|
||||||
|
|
||||||
- [Tailwind CSS](https://tailwindcss.com/docs) - the official Tailwind CSS documentation
|
- `HomeHero`
|
||||||
- [Next.js](https://nextjs.org/docs) - the official Next.js documentation
|
- `WorldMap`
|
||||||
- [Headless UI](https://headlessui.dev) - the official Headless UI documentation
|
- `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
|
||||||
|
|||||||
182
package-lock.json
generated
@@ -9,16 +9,23 @@
|
|||||||
"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",
|
||||||
"@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",
|
||||||
|
"react-countup": "^6.5.3",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
"react-type-animation": "^3.2.0",
|
"react-type-animation": "^3.2.0",
|
||||||
@@ -33,7 +40,8 @@
|
|||||||
"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": {
|
||||||
@@ -1023,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",
|
||||||
@@ -1717,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",
|
||||||
@@ -1735,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",
|
||||||
@@ -2942,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",
|
||||||
@@ -5026,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",
|
||||||
@@ -5180,6 +5250,12 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/countup.js": {
|
||||||
|
"version": "2.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/countup.js/-/countup.js-2.9.0.tgz",
|
||||||
|
"integrity": "sha512-llqrvyXztRFPp6+i8jx25phHWcVWhrHO4Nlt0uAOSKHB8778zzQswa4MU3qKBvkXfJKftRYFJuVHez67lyKdHg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/cross-spawn": {
|
"node_modules/cross-spawn": {
|
||||||
"version": "7.0.6",
|
"version": "7.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||||
@@ -8990,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"
|
||||||
@@ -10300,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",
|
||||||
@@ -10315,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",
|
||||||
@@ -10841,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",
|
||||||
@@ -11860,6 +12010,18 @@
|
|||||||
"react-dom": ">=16.8.0"
|
"react-dom": ">=16.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-countup": {
|
||||||
|
"version": "6.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-countup/-/react-countup-6.5.3.tgz",
|
||||||
|
"integrity": "sha512-udnqVQitxC7QWADSPDOxVWULkLvKUWrDapn5i53HE4DPRVgs+Y5rr4bo25qEl8jSh+0l2cToJgGMx+clxPM3+w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"countup.js": "^2.8.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">= 16.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-dom": {
|
"node_modules/react-dom": {
|
||||||
"version": "18.3.1",
|
"version": "18.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||||
@@ -13517,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",
|
||||||
|
|||||||
12
package.json
@@ -11,16 +11,23 @@
|
|||||||
"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",
|
||||||
"@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",
|
||||||
|
"react-countup": "^6.5.3",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
"react-type-animation": "^3.2.0",
|
"react-type-animation": "^3.2.0",
|
||||||
@@ -35,6 +42,7 @@
|
|||||||
"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
@@ -1,49 +0,0 @@
|
|||||||
import { type Metadata } from 'next'
|
|
||||||
import Link from 'next/link'
|
|
||||||
|
|
||||||
import { AuthLayout } from '@/components/AuthLayout'
|
|
||||||
import { Button } from '@/components/Button'
|
|
||||||
import { TextField } from '@/components/Fields'
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: 'Sign In',
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Login() {
|
|
||||||
return (
|
|
||||||
<AuthLayout
|
|
||||||
title="Sign in to account"
|
|
||||||
subtitle={
|
|
||||||
<>
|
|
||||||
Don’t have an account?{' '}
|
|
||||||
<Link href="/register" className="text-cyan-600">
|
|
||||||
Sign up
|
|
||||||
</Link>{' '}
|
|
||||||
for a free trial.
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<form>
|
|
||||||
<div className="space-y-6">
|
|
||||||
<TextField
|
|
||||||
label="Email address"
|
|
||||||
name="email"
|
|
||||||
type="email"
|
|
||||||
autoComplete="email"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
label="Password"
|
|
||||||
name="password"
|
|
||||||
type="password"
|
|
||||||
autoComplete="current-password"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Button type="submit" color="cyan" className="mt-8 w-full">
|
|
||||||
Sign in to account
|
|
||||||
</Button>
|
|
||||||
</form>
|
|
||||||
</AuthLayout>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
import { type Metadata } from 'next'
|
|
||||||
import Link from 'next/link'
|
|
||||||
|
|
||||||
import { AuthLayout } from '@/components/AuthLayout'
|
|
||||||
import { Button } from '@/components/Button'
|
|
||||||
import { SelectField, TextField } from '@/components/Fields'
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: 'Sign Up',
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Register() {
|
|
||||||
return (
|
|
||||||
<AuthLayout
|
|
||||||
title="Sign up for an account"
|
|
||||||
subtitle={
|
|
||||||
<>
|
|
||||||
Already registered?{' '}
|
|
||||||
<Link href="/login" className="text-cyan-600">
|
|
||||||
Sign in
|
|
||||||
</Link>{' '}
|
|
||||||
to your account.
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<form>
|
|
||||||
<div className="grid grid-cols-2 gap-6">
|
|
||||||
<TextField
|
|
||||||
label="First name"
|
|
||||||
name="first_name"
|
|
||||||
type="text"
|
|
||||||
autoComplete="given-name"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
label="Last name"
|
|
||||||
name="last_name"
|
|
||||||
type="text"
|
|
||||||
autoComplete="family-name"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
className="col-span-full"
|
|
||||||
label="Email address"
|
|
||||||
name="email"
|
|
||||||
type="email"
|
|
||||||
autoComplete="email"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
className="col-span-full"
|
|
||||||
label="Password"
|
|
||||||
name="password"
|
|
||||||
type="password"
|
|
||||||
autoComplete="new-password"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<SelectField
|
|
||||||
className="col-span-full"
|
|
||||||
label="How did you hear about us?"
|
|
||||||
name="referral_source"
|
|
||||||
>
|
|
||||||
<option>AltaVista search</option>
|
|
||||||
<option>Super Bowl commercial</option>
|
|
||||||
<option>Our route 34 city bus ad</option>
|
|
||||||
<option>The “Never Use This” podcast</option>
|
|
||||||
</SelectField>
|
|
||||||
</div>
|
|
||||||
<Button type="submit" color="cyan" className="mt-8 w-full">
|
|
||||||
Get started today
|
|
||||||
</Button>
|
|
||||||
</form>
|
|
||||||
</AuthLayout>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -7,9 +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 { WorldMap } from '@/components/WorldMap'
|
||||||
|
import { GetStarted } from '@/components/GetStarted'
|
||||||
|
import { BentoReviews } from '@/components/BentoReviews'
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
@@ -17,32 +21,27 @@ export default function Home() {
|
|||||||
<section id="home-hero">
|
<section id="home-hero">
|
||||||
<HomeHero />
|
<HomeHero />
|
||||||
</section>
|
</section>
|
||||||
<section id="companies">
|
<section id="network">
|
||||||
<Companies />
|
<WorldMap />
|
||||||
</section>
|
</section>
|
||||||
<section id="home-about">
|
<section id="technologies">
|
||||||
<HomeAbout />
|
|
||||||
</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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
import { AppStoreLink } from '@/components/AppStoreLink'
|
|
||||||
import { CircleBackground } from '@/components/CircleBackground'
|
|
||||||
import { Container } from '@/components/Container'
|
|
||||||
|
|
||||||
export function About() {
|
|
||||||
return (
|
|
||||||
<section
|
|
||||||
id="about"
|
|
||||||
className="relative overflow-hidden bg-gray-900 py-20 sm:py-28"
|
|
||||||
>
|
|
||||||
<div className="absolute top-1/2 left-20 -translate-y-1/2 sm:left-1/2 sm:-translate-x-1/2">
|
|
||||||
<CircleBackground color="#fff" className="animate-spin-slower" />
|
|
||||||
</div>
|
|
||||||
<Container className="relative">
|
|
||||||
<div className="mx-auto max-w-3xl sm:text-center">
|
|
||||||
<h2 className="text-3xl font-medium tracking-tight text-white sm:text-4xl">
|
|
||||||
Discover Mycelium
|
|
||||||
</h2>
|
|
||||||
<p className="mt-6 text-lg text-gray-300">
|
|
||||||
Mycelium is an unbreakable network, always finding the shortest path and providing 100% secure, peer-to-peer communication. But this is just the beginning.
|
|
||||||
</p>
|
|
||||||
<p className="mt-6 text-lg text-gray-300">
|
|
||||||
Our mission is to create a sustainable digital ecosystem where communication is seamless, data is secure, and scalability knows no bounds.
|
|
||||||
</p>
|
|
||||||
<div className="mt-8 flex justify-center">
|
|
||||||
<AppStoreLink color="white" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Container>
|
|
||||||
</section>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
import Link from 'next/link'
|
|
||||||
import clsx from 'clsx'
|
|
||||||
|
|
||||||
export function AndroidLink({
|
|
||||||
color = 'black',
|
|
||||||
}: {
|
|
||||||
color?: 'black' | 'white'
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
href="#"
|
|
||||||
aria-label="Download for Android"
|
|
||||||
className={clsx(
|
|
||||||
'flex items-center rounded-lg transition-colors px-4 py-2',
|
|
||||||
color === 'black'
|
|
||||||
? 'bg-gray-800 text-white hover:bg-gray-900'
|
|
||||||
: 'bg-white text-gray-900 hover:bg-gray-50',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{/* Android SVG (converted for JSX) */}
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 60 60"
|
|
||||||
aria-hidden="true"
|
|
||||||
className="h-5 w-5 mr-3"
|
|
||||||
>
|
|
||||||
<defs>
|
|
||||||
<clipPath id="android_clip_a">
|
|
||||||
<path d="M 1.566406 25 L 8 25 L 8 43 L 1.566406 43 Z M 1.566406 25 " clipRule="nonzero" />
|
|
||||||
</clipPath>
|
|
||||||
<clipPath id="android_clip_b">
|
|
||||||
<path d="M 10 25 L 34 25 L 34 53.640625 L 10 53.640625 Z M 10 25 " clipRule="nonzero" />
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
<g clipPath="url(#android_clip_a)">
|
|
||||||
<path
|
|
||||||
fill="currentColor"
|
|
||||||
d="M 4.445312 25.296875 C 2.855469 25.296875 1.5625 26.582031 1.5625 28.164062 L 1.5625 39.636719 C 1.5625 41.21875 2.855469 42.503906 4.445312 42.503906 C 6.035156 42.503906 7.324219 41.21875 7.324219 39.636719 L 7.324219 28.164062 C 7.324219 26.582031 6.035156 25.296875 4.445312 25.296875 Z M 4.445312 25.296875 "
|
|
||||||
fillOpacity="1"
|
|
||||||
fillRule="nonzero"
|
|
||||||
/>
|
|
||||||
</g>
|
|
||||||
<path
|
|
||||||
fill="currentColor"
|
|
||||||
d="M 39.015625 25.296875 C 37.425781 25.296875 36.132812 26.582031 36.132812 28.164062 L 36.132812 39.636719 C 36.132812 41.21875 37.425781 42.503906 39.015625 42.503906 C 40.605469 42.503906 41.894531 41.21875 41.894531 39.636719 L 41.894531 28.164062 C 41.894531 26.582031 40.605469 25.296875 39.015625 25.296875 Z M 39.015625 25.296875 "
|
|
||||||
fillOpacity="1"
|
|
||||||
fillRule="nonzero"
|
|
||||||
/>
|
|
||||||
<g clipPath="url(#android_clip_b)">
|
|
||||||
<path
|
|
||||||
fill="currentColor"
|
|
||||||
d="M 10.207031 42.667969 C 10.207031 44.253906 11.496094 45.535156 13.085938 45.535156 L 13.085938 51.105469 C 13.085938 52.6875 14.378906 53.972656 15.96875 53.972656 C 17.558594 53.972656 18.847656 52.6875 18.847656 51.105469 L 18.847656 45.535156 L 24.609375 45.535156 L 24.609375 51.105469 C 24.609375 52.6875 25.902344 53.972656 27.492188 53.972656 C 29.082031 53.972656 30.371094 52.6875 30.371094 51.105469 L 30.371094 45.535156 C 31.960938 45.535156 33.253906 44.253906 33.253906 42.667969 L 33.253906 25.464844 L 10.207031 25.464844 Z M 10.207031 42.667969 "
|
|
||||||
fillOpacity="1"
|
|
||||||
fillRule="nonzero"
|
|
||||||
/>
|
|
||||||
</g>
|
|
||||||
<path
|
|
||||||
fill="currentColor"
|
|
||||||
d="M 28.921875 13.53125 L 31.484375 10.4375 C 31.992188 9.824219 31.90625 8.921875 31.292969 8.417969 C 30.675781 7.914062 29.769531 8 29.261719 8.609375 L 26.460938 11.992188 C 25.015625 11.339844 23.421875 10.957031 21.730469 10.957031 C 20.015625 10.957031 18.402344 11.355469 16.941406 12.023438 L 14.214844 8.628906 C 13.714844 8.011719 12.808594 7.910156 12.1875 8.40625 C 11.570312 8.902344 11.46875 9.804688 11.964844 10.421875 L 14.492188 13.570312 C 11.898438 15.671875 10.207031 18.839844 10.207031 22.429688 L 33.253906 22.429688 C 33.253906 18.816406 31.542969 15.632812 28.921875 13.53125 Z M 18.847656 18.128906 C 18.054688 18.128906 17.410156 17.484375 17.410156 16.695312 C 17.410156 15.902344 18.054688 15.261719 18.847656 15.261719 C 19.644531 15.261719 20.289062 15.902344 20.289062 16.695312 C 20.289062 17.484375 19.644531 18.128906 18.847656 18.128906 Z M 24.609375 18.128906 C 23.816406 18.128906 23.171875 17.484375 23.171875 16.695312 C 23.171875 15.902344 23.816406 15.261719 24.609375 15.261719 C 25.40625 15.261719 26.050781 15.902344 26.050781 16.695312 C 26.050781 17.484375 25.40625 18.128906 24.609375 18.128906 Z M 24.609375 18.128906 "
|
|
||||||
fillOpacity="1"
|
|
||||||
fillRule="nonzero"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
|
|
||||||
{/* Text */}
|
|
||||||
<div className="flex flex-col text-left leading-tight">
|
|
||||||
<span className="text-[9px] mt-0">Download for</span>
|
|
||||||
<span className="text-sm font-semibold -mt-1.5">Android</span>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,250 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import { useId, useRef, useState } from 'react'
|
|
||||||
import clsx from 'clsx'
|
|
||||||
import { motion, useInView, useMotionValue } from 'framer-motion'
|
|
||||||
|
|
||||||
import { AppScreen } from '@/components/AppScreen'
|
|
||||||
|
|
||||||
const prices = [
|
|
||||||
997.56, 944.34, 972.25, 832.4, 888.76, 834.8, 805.56, 767.38, 861.21, 669.6,
|
|
||||||
694.39, 721.32, 694.03, 610.1, 502.2, 549.56, 611.03, 583.4, 610.14, 660.6,
|
|
||||||
752.11, 721.19, 638.89, 661.7, 694.51, 580.3, 638.0, 613.3, 651.64, 560.51,
|
|
||||||
611.45, 670.68, 752.56,
|
|
||||||
]
|
|
||||||
const maxPrice = Math.max(...prices)
|
|
||||||
const minPrice = Math.min(...prices)
|
|
||||||
|
|
||||||
function Chart({
|
|
||||||
className,
|
|
||||||
activePointIndex,
|
|
||||||
onChangeActivePointIndex,
|
|
||||||
width: totalWidth,
|
|
||||||
height: totalHeight,
|
|
||||||
paddingX = 0,
|
|
||||||
paddingY = 0,
|
|
||||||
gridLines = 6,
|
|
||||||
...props
|
|
||||||
}: React.ComponentPropsWithoutRef<'svg'> & {
|
|
||||||
activePointIndex: number | null
|
|
||||||
onChangeActivePointIndex: (index: number | null) => void
|
|
||||||
width: number
|
|
||||||
height: number
|
|
||||||
paddingX?: number
|
|
||||||
paddingY?: number
|
|
||||||
gridLines?: number
|
|
||||||
}) {
|
|
||||||
let width = totalWidth - paddingX * 2
|
|
||||||
let height = totalHeight - paddingY * 2
|
|
||||||
|
|
||||||
let id = useId()
|
|
||||||
let svgRef = useRef<React.ElementRef<'svg'>>(null)
|
|
||||||
let pathRef = useRef<React.ElementRef<'path'>>(null)
|
|
||||||
let isInView = useInView(svgRef as React.RefObject<Element>, { amount: 0.5, once: true })
|
|
||||||
let pathWidth = useMotionValue(0)
|
|
||||||
let [interactionEnabled, setInteractionEnabled] = useState(false)
|
|
||||||
|
|
||||||
let path = ''
|
|
||||||
let points: Array<{ x: number; y: number }> = []
|
|
||||||
|
|
||||||
for (let index = 0; index < prices.length; index++) {
|
|
||||||
let x = paddingX + (index / (prices.length - 1)) * width
|
|
||||||
let y =
|
|
||||||
paddingY +
|
|
||||||
(1 - (prices[index] - minPrice) / (maxPrice - minPrice)) * height
|
|
||||||
points.push({ x, y })
|
|
||||||
path += `${index === 0 ? 'M' : 'L'} ${x.toFixed(4)} ${y.toFixed(4)}`
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
ref={svgRef}
|
|
||||||
viewBox={`0 0 ${totalWidth} ${totalHeight}`}
|
|
||||||
className={clsx(className, 'overflow-visible')}
|
|
||||||
{...(interactionEnabled
|
|
||||||
? {
|
|
||||||
onPointerLeave: () => onChangeActivePointIndex(null),
|
|
||||||
onPointerMove: (event) => {
|
|
||||||
let x = event.nativeEvent.offsetX
|
|
||||||
let closestPointIndex: number | null = null
|
|
||||||
let closestDistance = Infinity
|
|
||||||
for (
|
|
||||||
let pointIndex = 0;
|
|
||||||
pointIndex < points.length;
|
|
||||||
pointIndex++
|
|
||||||
) {
|
|
||||||
let point = points[pointIndex]
|
|
||||||
let distance = Math.abs(point.x - x)
|
|
||||||
if (distance < closestDistance) {
|
|
||||||
closestDistance = distance
|
|
||||||
closestPointIndex = pointIndex
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onChangeActivePointIndex(closestPointIndex)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
: {})}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<defs>
|
|
||||||
<clipPath id={`${id}-clip`}>
|
|
||||||
<path d={`${path} V ${height + paddingY} H ${paddingX} Z`} />
|
|
||||||
</clipPath>
|
|
||||||
<linearGradient id={`${id}-gradient`} x1="0" x2="0" y1="0" y2="1">
|
|
||||||
<stop offset="0%" stopColor="#13B5C8" />
|
|
||||||
<stop offset="100%" stopColor="#13B5C8" stopOpacity="0" />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
{[...Array(gridLines - 1).keys()].map((index) => (
|
|
||||||
<line
|
|
||||||
key={index}
|
|
||||||
stroke="#a3a3a3"
|
|
||||||
opacity="0.1"
|
|
||||||
x1="0"
|
|
||||||
y1={(totalHeight / gridLines) * (index + 1)}
|
|
||||||
x2={totalWidth}
|
|
||||||
y2={(totalHeight / gridLines) * (index + 1)}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
<motion.rect
|
|
||||||
y={paddingY}
|
|
||||||
width={pathWidth}
|
|
||||||
height={height}
|
|
||||||
fill={`url(#${id}-gradient)`}
|
|
||||||
clipPath={`url(#${id}-clip)`}
|
|
||||||
opacity="0.5"
|
|
||||||
/>
|
|
||||||
<motion.path
|
|
||||||
ref={pathRef}
|
|
||||||
d={path}
|
|
||||||
fill="none"
|
|
||||||
strokeWidth="2"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
initial={{ pathLength: 0 }}
|
|
||||||
transition={{ duration: 1 }}
|
|
||||||
{...(isInView ? { stroke: '#06b6d4', animate: { pathLength: 1 } } : {})}
|
|
||||||
onUpdate={({ pathLength }) => {
|
|
||||||
if (pathRef.current && typeof pathLength === 'number') {
|
|
||||||
pathWidth.set(
|
|
||||||
pathRef.current.getPointAtLength(
|
|
||||||
pathLength * pathRef.current.getTotalLength(),
|
|
||||||
).x,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onAnimationComplete={() => setInteractionEnabled(true)}
|
|
||||||
/>
|
|
||||||
{activePointIndex !== null && (
|
|
||||||
<>
|
|
||||||
<line
|
|
||||||
x1="0"
|
|
||||||
y1={points[activePointIndex].y}
|
|
||||||
x2={totalWidth}
|
|
||||||
y2={points[activePointIndex].y}
|
|
||||||
stroke="#06b6d4"
|
|
||||||
strokeDasharray="1 3"
|
|
||||||
/>
|
|
||||||
<circle
|
|
||||||
r="4"
|
|
||||||
cx={points[activePointIndex].x}
|
|
||||||
cy={points[activePointIndex].y}
|
|
||||||
fill="#fff"
|
|
||||||
strokeWidth="2"
|
|
||||||
stroke="#06b6d4"
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function AppDemo() {
|
|
||||||
let [activePointIndex, setActivePointIndex] = useState<number | null>(null)
|
|
||||||
let activePriceIndex = activePointIndex ?? prices.length - 1
|
|
||||||
let activeValue = prices[activePriceIndex]
|
|
||||||
let previousValue = prices[activePriceIndex - 1]
|
|
||||||
let percentageChange =
|
|
||||||
activePriceIndex === 0
|
|
||||||
? null
|
|
||||||
: ((activeValue - previousValue) / previousValue) * 100
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AppScreen>
|
|
||||||
<AppScreen.Body>
|
|
||||||
<div className="p-4">
|
|
||||||
<div className="flex gap-2">
|
|
||||||
<div className="text-xs/6 text-gray-500">Tailwind Labs, Inc.</div>
|
|
||||||
<div className="text-sm text-gray-900">$CSS</div>
|
|
||||||
<svg viewBox="0 0 24 24" className="ml-auto h-6 w-6" fill="none">
|
|
||||||
<path
|
|
||||||
d="M5 12a7 7 0 1 1 14 0 7 7 0 0 1-14 0ZM12 9v6M15 12H9"
|
|
||||||
stroke="#171717"
|
|
||||||
strokeWidth="2"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div className="mt-3 border-t border-gray-200 pt-5">
|
|
||||||
<div className="flex items-baseline gap-2">
|
|
||||||
<div className="text-2xl tracking-tight text-gray-900 tabular-nums">
|
|
||||||
{activeValue.toFixed(2)}
|
|
||||||
</div>
|
|
||||||
<div className="text-sm text-gray-900">USD</div>
|
|
||||||
{percentageChange && (
|
|
||||||
<div
|
|
||||||
className={clsx(
|
|
||||||
'ml-auto text-sm tracking-tight tabular-nums',
|
|
||||||
percentageChange >= 0 ? 'text-cyan-500' : 'text-gray-500',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{`${
|
|
||||||
percentageChange >= 0 ? '+' : ''
|
|
||||||
}${percentageChange.toFixed(2)}%`}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="mt-6 flex gap-4 text-xs text-gray-500">
|
|
||||||
<div>1D</div>
|
|
||||||
<div>5D</div>
|
|
||||||
<div className="font-semibold text-cyan-600">1M</div>
|
|
||||||
<div>6M</div>
|
|
||||||
<div>1Y</div>
|
|
||||||
<div>5Y</div>
|
|
||||||
</div>
|
|
||||||
<div className="mt-3 rounded-lg bg-gray-50 ring-1 ring-black/5 ring-inset">
|
|
||||||
<Chart
|
|
||||||
width={286}
|
|
||||||
height={208}
|
|
||||||
paddingX={16}
|
|
||||||
paddingY={32}
|
|
||||||
activePointIndex={activePointIndex}
|
|
||||||
onChangeActivePointIndex={setActivePointIndex}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mt-4 rounded-lg bg-cyan-500 px-4 py-2 text-center text-sm font-semibold text-white">
|
|
||||||
Trade
|
|
||||||
</div>
|
|
||||||
<div className="mt-3 divide-y divide-gray-100 text-sm">
|
|
||||||
<div className="flex justify-between py-1">
|
|
||||||
<div className="text-gray-500">Open</div>
|
|
||||||
<div className="font-medium text-gray-900">6,387.55</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between py-1">
|
|
||||||
<div className="text-gray-500">Closed</div>
|
|
||||||
<div className="font-medium text-gray-900">6,487.09</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between py-1">
|
|
||||||
<div className="text-gray-500">Low</div>
|
|
||||||
<div className="font-medium text-gray-900">6,322.01</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</AppScreen.Body>
|
|
||||||
</AppScreen>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
import { forwardRef } from 'react'
|
|
||||||
import clsx from 'clsx'
|
|
||||||
|
|
||||||
function Logo(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 79 24" fill="none" aria-hidden="true" {...props}>
|
|
||||||
<path
|
|
||||||
d="M12 24C5.373 24 0 18.627 0 12S5.373 0 12 0s12 5.373 12 12-5.373 12-12 12ZM2.4 12a9.004 9.004 0 0 0 6.055 8.507c1.565.542 2.945-.85 2.945-2.507V6c0-1.657-1.38-3.049-2.945-2.507A9.004 9.004 0 0 0 2.4 12Z"
|
|
||||||
fill="#06B6D4"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M33.004 17V6.818h3.818c.783 0 1.439.146 1.97.438.533.291.935.692 1.207 1.203.275.507.413 1.084.413 1.73 0 .653-.138 1.233-.413 1.74a2.948 2.948 0 0 1-1.218 1.198c-.537.288-1.198.433-1.983.433h-2.531v-1.517h2.282c.457 0 .832-.08 1.124-.238.291-.16.507-.378.646-.657.142-.278.214-.598.214-.96 0-.36-.072-.679-.214-.954a1.452 1.452 0 0 0-.651-.641c-.292-.156-.668-.234-1.129-.234h-1.69V17h-1.845Zm12.152.15c-.746 0-1.392-.165-1.939-.493a3.343 3.343 0 0 1-1.273-1.377c-.298-.59-.447-1.28-.447-2.068 0-.79.15-1.48.447-2.073a3.335 3.335 0 0 1 1.273-1.383c.547-.328 1.193-.492 1.94-.492.745 0 1.391.164 1.938.492.547.329.97.79 1.268 1.383.301.593.452 1.284.452 2.073 0 .789-.15 1.478-.452 2.068a3.309 3.309 0 0 1-1.268 1.377c-.547.328-1.193.492-1.939.492Zm.01-1.443c.404 0 .742-.11 1.014-.333.272-.225.474-.527.607-.905.136-.377.204-.798.204-1.262 0-.468-.068-.89-.204-1.268a2.007 2.007 0 0 0-.607-.91c-.272-.225-.61-.338-1.014-.338-.414 0-.759.113-1.034.338a2.041 2.041 0 0 0-.612.91 3.81 3.81 0 0 0-.198 1.268c0 .464.066.885.198 1.262.136.378.34.68.612.905.275.222.62.333 1.034.333Zm8.508 1.442c-.763 0-1.417-.167-1.964-.502a3.352 3.352 0 0 1-1.258-1.387c-.292-.593-.437-1.276-.437-2.048 0-.776.149-1.46.447-2.054a3.34 3.34 0 0 1 1.263-1.392c.547-.334 1.193-.502 1.939-.502.62 0 1.168.115 1.645.343.48.226.864.546 1.149.96.285.41.447.891.487 1.441h-1.72a1.644 1.644 0 0 0-.497-.92c-.259-.248-.605-.372-1.04-.372-.367 0-.69.1-.969.298-.278.196-.495.478-.651.845-.153.368-.229.81-.229 1.323 0 .52.076.968.229 1.342.152.371.366.658.641.86.279.2.605.298.98.298.265 0 .502-.05.71-.149.213-.102.39-.25.532-.442.143-.192.24-.426.294-.701h1.72a2.999 2.999 0 0 1-.477 1.437c-.275.414-.65.739-1.124.974-.474.232-1.03.348-1.67.348Zm6.39-2.545-.006-2.173h.289l2.744-3.067h2.103l-3.376 3.758h-.372l-1.383 1.482ZM58.422 17V6.818h1.8V17h-1.8Zm4.792 0-2.485-3.475 1.213-1.268L65.368 17h-2.153Zm6.245.15c-.766 0-1.427-.16-1.984-.478a3.233 3.233 0 0 1-1.278-1.362c-.298-.59-.447-1.285-.447-2.083 0-.786.149-1.475.447-2.069a3.384 3.384 0 0 1 1.263-1.392c.54-.334 1.175-.502 1.904-.502.47 0 .915.076 1.333.229.42.149.792.381 1.113.696.325.315.58.716.766 1.203.186.484.278 1.06.278 1.73v.552h-6.259v-1.213h4.534a1.935 1.935 0 0 0-.224-.92 1.625 1.625 0 0 0-.611-.641 1.719 1.719 0 0 0-.905-.234c-.368 0-.691.09-.97.269a1.848 1.848 0 0 0-.65.696c-.153.285-.231.598-.234.94v1.058c0 .444.08.825.243 1.144.163.315.39.556.681.726.292.165.634.248 1.025.248.261 0 .498-.036.71-.11.213-.075.397-.187.552-.332.156-.146.274-.327.353-.542l1.68.189a2.62 2.62 0 0 1-.606 1.163 2.958 2.958 0 0 1-1.133.766c-.461.179-.988.268-1.581.268Zm8.731-7.786v1.392h-4.39V9.364h4.39Zm-3.306-1.83h1.8v7.17c0 .241.036.427.109.556a.59.59 0 0 0 .298.258c.123.047.259.07.408.07.113 0 .215-.008.308-.025.096-.016.17-.031.219-.045l.303 1.407c-.096.034-.233.07-.412.11-.176.04-.392.063-.647.07a2.934 2.934 0 0 1-1.218-.204 1.895 1.895 0 0 1-.86-.706c-.209-.319-.311-.716-.308-1.194V7.534Z"
|
|
||||||
fill="#fff"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function MenuIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" {...props}>
|
|
||||||
<path
|
|
||||||
d="M5 6h14M5 18h14M5 12h14"
|
|
||||||
stroke="#fff"
|
|
||||||
strokeWidth="2"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function UserIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" {...props}>
|
|
||||||
<path
|
|
||||||
d="M15 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0ZM6.696 19h10.608c1.175 0 2.08-.935 1.532-1.897C18.028 15.69 16.187 14 12 14s-6.028 1.689-6.836 3.103C4.616 18.065 5.521 19 6.696 19Z"
|
|
||||||
stroke="#fff"
|
|
||||||
strokeWidth="2"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function AppScreen({
|
|
||||||
children,
|
|
||||||
className,
|
|
||||||
...props
|
|
||||||
}: React.ComponentPropsWithoutRef<'div'>) {
|
|
||||||
return (
|
|
||||||
<div className={clsx('flex flex-col', className)} {...props}>
|
|
||||||
<div className="flex justify-between px-4 pt-4">
|
|
||||||
<MenuIcon className="h-6 w-6 flex-none" />
|
|
||||||
<Logo className="h-6 flex-none" />
|
|
||||||
<UserIcon className="h-6 w-6 flex-none" />
|
|
||||||
</div>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
AppScreen.Header = forwardRef<
|
|
||||||
React.ElementRef<'div'>,
|
|
||||||
{ children: React.ReactNode }
|
|
||||||
>(function AppScreenHeader({ children }, ref) {
|
|
||||||
return (
|
|
||||||
<div ref={ref} className="mt-6 px-4 text-white">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
AppScreen.Title = forwardRef<
|
|
||||||
React.ElementRef<'div'>,
|
|
||||||
{ children: React.ReactNode }
|
|
||||||
>(function AppScreenTitle({ children }, ref) {
|
|
||||||
return (
|
|
||||||
<div ref={ref} className="text-2xl text-white">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
AppScreen.Subtitle = forwardRef<
|
|
||||||
React.ElementRef<'div'>,
|
|
||||||
{ children: React.ReactNode }
|
|
||||||
>(function AppScreenSubtitle({ children }, ref) {
|
|
||||||
return (
|
|
||||||
<div ref={ref} className="text-sm text-gray-500">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
AppScreen.Body = forwardRef<
|
|
||||||
React.ElementRef<'div'>,
|
|
||||||
{ className?: string; children: React.ReactNode }
|
|
||||||
>(function AppScreenBody({ children, className }, ref) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
ref={ref}
|
|
||||||
className={clsx('mt-6 flex-auto rounded-t-2xl bg-white', className)}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
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>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
import Link from 'next/link'
|
|
||||||
|
|
||||||
import { CirclesBackground } from '@/components/CirclesBackground'
|
|
||||||
import { Logo } from '@/components/Logo'
|
|
||||||
|
|
||||||
export function AuthLayout({
|
|
||||||
title,
|
|
||||||
subtitle,
|
|
||||||
children,
|
|
||||||
}: {
|
|
||||||
title: string
|
|
||||||
subtitle: React.ReactNode
|
|
||||||
children: React.ReactNode
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<main className="flex min-h-full overflow-hidden pt-16 sm:py-28">
|
|
||||||
<div className="mx-auto flex w-full max-w-2xl flex-col px-4 sm:px-6">
|
|
||||||
<Link href="/" aria-label="Home">
|
|
||||||
<Logo className="mx-auto h-10 w-auto" />
|
|
||||||
</Link>
|
|
||||||
<div className="relative mt-12 sm:mt-16">
|
|
||||||
<CirclesBackground
|
|
||||||
width="1090"
|
|
||||||
height="1090"
|
|
||||||
className="absolute -top-7 left-1/2 -z-10 h-[788px] -translate-x-1/2 mask-[linear-gradient(to_bottom,white_20%,transparent_75%)] stroke-gray-300/30 sm:-top-9 sm:h-auto"
|
|
||||||
/>
|
|
||||||
<h1 className="text-center text-2xl font-medium tracking-tight text-gray-900">
|
|
||||||
{title}
|
|
||||||
</h1>
|
|
||||||
{subtitle && (
|
|
||||||
<p className="mt-3 text-center text-lg text-gray-600">{subtitle}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="-mx-4 mt-10 flex-auto bg-white px-4 py-10 shadow-2xl shadow-gray-900/10 sm:mx-0 sm:flex-none sm:rounded-5xl sm:p-24">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
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>
|
||||||
|
|||||||
@@ -1,34 +1,59 @@
|
|||||||
import { AppStoreLink } from '@/components/AppStoreLink'
|
'use client'
|
||||||
import { WindowsLink } from '@/components/WindowsLink'
|
|
||||||
import { AndroidLink } from './AndroidLink'
|
|
||||||
import { LinuxLink } from '@/components/LinuxLink'
|
|
||||||
import { CircleBackground } from '@/components/CircleBackground'
|
import { CircleBackground } from '@/components/CircleBackground'
|
||||||
import { Container } from '@/components/Container'
|
import { Container } from '@/components/Container'
|
||||||
|
import { Button } from '@/components/Button'
|
||||||
|
import { FadeIn } from '@/components/FadeIn'
|
||||||
|
|
||||||
export function CallToAction() {
|
export function CallToAction() {
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
id="get-free-shares-today"
|
id="get-free-shares-today"
|
||||||
className="relative overflow-hidden bg-gray-900 py-20 sm:py-28"
|
className="relative overflow-hidden py-20 sm:py-28 border-t border-gray-800"
|
||||||
>
|
>
|
||||||
<div className="absolute top-1/2 left-20 -translate-y-1/2 sm:left-1/2 sm:-translate-x-1/2">
|
<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" />
|
<CircleBackground color="#fff" className="animate-spin-slower" />
|
||||||
</div>
|
</div>
|
||||||
<Container className="relative">
|
<Container className="relative z-20">
|
||||||
<div className="mx-auto max-w-2xl sm:text-center">
|
<FadeIn>
|
||||||
|
<div className="mx-auto max-w-md text-center">
|
||||||
<h2 className="text-3xl font-medium tracking-tight text-white sm:text-4xl">
|
<h2 className="text-3xl font-medium tracking-tight text-white sm:text-4xl">
|
||||||
Get Started Today
|
Decentralized AI Agents that are Truly Yours
|
||||||
</h2>
|
</h2>
|
||||||
<p className="mt-6 text-lg text-gray-300">
|
<p className="mt-4 text-lg text-gray-300">
|
||||||
Download the Mycelium app and step into the future of secure, peer-to-peer networking; fast, private, and decentralized.
|
Why hand out your intelligence to centralized giants when you can
|
||||||
|
build your own. Ready to own your intelligence?
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-8 flex justify-center gap-4">
|
<div className="mt-8 flex justify-center gap-x-6">
|
||||||
<AppStoreLink color="white" />
|
<Button
|
||||||
<WindowsLink color="white" />
|
variant="solid"
|
||||||
<AndroidLink color="white" />
|
color="cyan"
|
||||||
<LinuxLink color="white" />
|
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>
|
||||||
</div>
|
</div>
|
||||||
|
</FadeIn>
|
||||||
</Container>
|
</Container>
|
||||||
</section>
|
</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,127 +49,99 @@ 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">
|
|
||||||
<P className="text-center" color="custom">
|
|
||||||
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.
|
|
||||||
</P>
|
|
||||||
</motion.div>
|
|
||||||
<motion.div
|
|
||||||
initial={{ opacity: 0 }}
|
|
||||||
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
|
||||||
transition={{ duration: 1, delay: 0.3 }}
|
|
||||||
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>
|
|
||||||
</div>
|
</div>
|
||||||
<motion.section
|
</FadeIn>
|
||||||
initial={{ opacity: 0 }}
|
<FadeIn transition={{ duration: 0.8, delay: 0.2 }}>
|
||||||
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
<div className="mx-auto max-w-4xl mt-6 lg:px-0 px-4">
|
||||||
transition={{ duration: 1, delay: 0.4 }}
|
<P className="text-center" color="primary">
|
||||||
className="relative w-full flex items-center justify-center overflow-hidden bg-background -mt-16 pt-0 pb-32"
|
Your private agent coordinates a team of specialists that spin up on demand, collaborate across your world, and deliver end-to-end results.
|
||||||
|
Many agents, one intelligence—yours.
|
||||||
|
</P>
|
||||||
|
</div>
|
||||||
|
</FadeIn>
|
||||||
|
</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)}
|
onMouseEnter={() => setHovering(true)}
|
||||||
onMouseLeave={() => setHovering(false)}
|
onMouseLeave={() => setHovering(false)}
|
||||||
>
|
>
|
||||||
{/* Soft edge fades */}
|
<div className="relative w-full max-w-[1800px] h-[300px] md:h-[500px]" style={{ perspective: '1600px' }}>
|
||||||
<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' }}>
|
|
||||||
<div
|
|
||||||
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%+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]"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="absolute inset-0" style={{ transformStyle: 'preserve-3d' }}>
|
<div className="absolute inset-0" style={{ transformStyle: 'preserve-3d' }}>
|
||||||
<AnimatePresence initial={false}>
|
<AnimatePresence initial={false}>
|
||||||
{indices.map((idx, i) => {
|
{indices.map((idx, i) => {
|
||||||
const distance = i - VISIBLE
|
const distance = i - VISIBLE;
|
||||||
const item = galleryItems[idx]
|
const item = galleryItems[idx];
|
||||||
|
|
||||||
const x = distance * GAP
|
const x = distance * GAP;
|
||||||
const z = -Math.abs(distance) * DEPTH
|
const z = -Math.abs(distance) * DEPTH;
|
||||||
const r = distance * ROT_Y
|
const r = distance * ROT_Y;
|
||||||
const s = 1 - Math.abs(distance) * SCALE_DROP
|
const s = 1 - Math.abs(distance) * SCALE_DROP;
|
||||||
const o = distance === 0 ? 1 : 0.90
|
const o = distance === 0 ? 1 : 0.80;
|
||||||
const zIndex = 100 - Math.abs(distance)
|
const zIndex = 100 - Math.abs(distance);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
key={`${idx}-${i}`}
|
key={`${idx}-${i}`}
|
||||||
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 will-change-transform"
|
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 }}
|
initial={{ opacity: 0 }}
|
||||||
animate={{
|
animate={{
|
||||||
transform: `translateX(${x}px) translateZ(${z}px) rotateY(${r}deg) scale(${s})`,
|
transform: `translateX(${x}px) translateZ(${z}px) rotateY(${r}deg) scale(${s})`,
|
||||||
zIndex,
|
zIndex,
|
||||||
opacity: o,
|
opacity: o,
|
||||||
|
boxShadow: distance === 0 ? '0 0 20px 5px rgba(255, 255, 255, 0.2)' : 'none',
|
||||||
}}
|
}}
|
||||||
exit={{ opacity: 0 }}
|
exit={{ opacity: 0 }}
|
||||||
transition={{ type: 'spring', stiffness: 220, damping: 26 }}
|
transition={{ type: 'spring', stiffness: 220, damping: 26 }}
|
||||||
onClick={() => setActive(idx)}
|
onClick={() => setActive(idx)}
|
||||||
>
|
>
|
||||||
{/* Square container, keeps image ratio inside */}
|
<div className="relative bg-black flex items-center justify-center">
|
||||||
<div
|
|
||||||
className="relative rounded-2xl overflow-hidden bg-white flex items-center justify-center"
|
|
||||||
style={{ width: CARD_SIZE, height: CARD_SIZE }}
|
|
||||||
>
|
|
||||||
<Image
|
<Image
|
||||||
src={item.image}
|
src={item.image}
|
||||||
alt={item.text}
|
alt={item.text}
|
||||||
fill
|
width={item.width}
|
||||||
className="object-contain rounded-2xl"
|
height={item.height}
|
||||||
|
className="object-contain text-white"
|
||||||
priority={i === VISIBLE}
|
priority={i === VISIBLE}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
)
|
);
|
||||||
})}
|
})}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Arrows */}
|
{/* Arrows */}
|
||||||
<div className="absolute inset-y-0 left-8 flex items-center z-50">
|
{/* Arrows */}
|
||||||
|
<div className="absolute inset-y-0 left-8 hidden md:flex items-center z-50">
|
||||||
<button
|
<button
|
||||||
onClick={prev}
|
onClick={prev}
|
||||||
className="bg-white/70 hover:bg-white rounded-full p-3 shadow-lg backdrop-blur-md"
|
className="bg-transparent rounded-full p-2 shadow-lg backdrop-blur-md"
|
||||||
aria-label="Previous"
|
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"/>' }} />
|
<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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="absolute inset-y-0 right-8 flex items-center z-50">
|
<div className="absolute inset-y-0 right-8 hidden md:flex items-center z-50">
|
||||||
<button
|
<button
|
||||||
onClick={next}
|
onClick={next}
|
||||||
className="bg-white/70 hover:bg-white rounded-full p-3 shadow-lg backdrop-blur-md"
|
className="bg-transparent rounded-full p-2 shadow-lg backdrop-blur-md"
|
||||||
aria-label="Next"
|
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"/>' }} />
|
<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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Foreground pill */}
|
{/* Foreground pill (Desktop) */}
|
||||||
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-[60]">
|
<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-3xl bg-white/95 shadow-[0_8px_40px_rgba(0,0,0,0.15)] px-12 py-6 backdrop-blur">
|
<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">
|
||||||
<H4 as="h4" className="max-w-[820px] h-[72px]">
|
<CT as="h4" className="max-w-[820px] h-[72px] text-white flex items-center">
|
||||||
<TypeAnimation
|
<TypeAnimation
|
||||||
key={active}
|
key={active}
|
||||||
sequence={[galleryItems[active].text]}
|
sequence={[galleryItems[active].text]}
|
||||||
@@ -181,14 +149,32 @@ export function ClickableGallery() {
|
|||||||
speed={50}
|
speed={50}
|
||||||
repeat={0}
|
repeat={0}
|
||||||
/>
|
/>
|
||||||
</H4>
|
</CT>
|
||||||
<Button href="#" color="cyan" className="text-sm px-4 py-2 lg:text-base">
|
<Button href="#" color="cyan" className="text-sm px-4 py-2 lg:text-base whitespace-nowrap">
|
||||||
Start
|
Start
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
||||||
</motion.section>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
</FadeIn>
|
||||||
|
</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>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ export function DownloadLink() {
|
|||||||
className="inline-flex items-center rounded-lg bg-gray-800 px-4 py-2 text-sm font-semibold text-white hover:bg-gray-900 transition-colors"
|
className="inline-flex items-center rounded-lg bg-gray-800 px-4 py-2 text-sm font-semibold text-white hover:bg-gray-900 transition-colors"
|
||||||
>
|
>
|
||||||
<ArrowDownTrayIcon className="h-5 w-5 mr-2" />
|
<ArrowDownTrayIcon className="h-5 w-5 mr-2" />
|
||||||
Get Mycelium
|
Get Started
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
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>
|
||||||
|
);
|
||||||
|
}
|
||||||
92
src/components/GridStats.tsx
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import CountUp from "react-countup";
|
||||||
|
import React from "react";
|
||||||
|
import { Button } from "@/components/Button";
|
||||||
|
import { H2, P } from "@/components/Texts";
|
||||||
|
|
||||||
|
export function GridStats() {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id="grid-stats"
|
||||||
|
className="py-24 relative -top-20 "
|
||||||
|
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>
|
||||||
|
<H2 color="light">
|
||||||
|
Robust Infrastructure for your Intellegence Needs
|
||||||
|
</H2>
|
||||||
|
<P color="light" className="mt-6">
|
||||||
|
Mycelium's groundbreaking technology provides dedicated, performance-validated GPUs for your AI workloads.
|
||||||
|
</P>
|
||||||
|
<Button className="mt-8" variant="outline" href="https://threefold.io/build" color="white">Explore TFGrid →</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Column 2: StatCards */}
|
||||||
|
<div className="flex flex-col space-y-10">
|
||||||
|
<StatCard
|
||||||
|
label="Dedicated Hosting"
|
||||||
|
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."
|
||||||
|
/>
|
||||||
|
<StatCard
|
||||||
|
label="Data Sovereignty"
|
||||||
|
description="Mycelium nodes run on trusted infrastructure you own or choose, ensuring that no third party can access, train on, or monetize your data."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Column 3: StatCards */}
|
||||||
|
<div className="flex flex-col space-y-10 justify-start mt-20">
|
||||||
|
<StatCard
|
||||||
|
label="Seamless Scalability"
|
||||||
|
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."
|
||||||
|
/>
|
||||||
|
<StatCard
|
||||||
|
label="Composable Agent Ecosystem"
|
||||||
|
description="Mix and match agents for every part of your workflow: data ingestion, cleaning, orchestration, analysis, and reporting."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🧱 Stat Card Component
|
||||||
|
function StatCard({
|
||||||
|
label,
|
||||||
|
description,
|
||||||
|
className = "border border-white/10 hover:border-white/40 hover:bg-black/40",
|
||||||
|
}: {
|
||||||
|
label: string;
|
||||||
|
description: string;
|
||||||
|
className?: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
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={{
|
||||||
|
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-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-white lg:text-base">
|
||||||
|
{description}
|
||||||
|
</p>
|
||||||
|
</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 Mycelium</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 Mycelium</Button>
|
<Button href="https://calendly.com/sachao/30min" color="cyan">Book a Meeting</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -1,166 +0,0 @@
|
|||||||
import { useId } from 'react'
|
|
||||||
import Image from 'next/image'
|
|
||||||
import clsx from 'clsx'
|
|
||||||
|
|
||||||
import { AppDemo } from '@/components/AppDemo'
|
|
||||||
import { DownloadLink } from '@/components/DownloadLink'
|
|
||||||
import { Button } from '@/components/Button'
|
|
||||||
import { Container } from '@/components/Container'
|
|
||||||
import { PhoneFrame } from '@/components/PhoneFrame'
|
|
||||||
import logoBbc from '@/images/logos/bbc.svg'
|
|
||||||
import logoCbs from '@/images/logos/cbs.svg'
|
|
||||||
import logoCnn from '@/images/logos/cnn.svg'
|
|
||||||
import logoFastCompany from '@/images/logos/fast-company.svg'
|
|
||||||
import logoForbes from '@/images/logos/forbes.svg'
|
|
||||||
import logoHuffpost from '@/images/logos/huffpost.svg'
|
|
||||||
import logoTechcrunch from '@/images/logos/techcrunch.svg'
|
|
||||||
import logoWired from '@/images/logos/wired.svg'
|
|
||||||
|
|
||||||
function BackgroundIllustration(props: React.ComponentPropsWithoutRef<'div'>) {
|
|
||||||
let id = useId()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div {...props}>
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 1026 1026"
|
|
||||||
fill="none"
|
|
||||||
aria-hidden="true"
|
|
||||||
className="absolute inset-0 h-full w-full animate-spin-slow"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M1025 513c0 282.77-229.23 512-512 512S1 795.77 1 513 230.23 1 513 1s512 229.23 512 512Z"
|
|
||||||
stroke="#D4D4D4"
|
|
||||||
strokeOpacity="0.7"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M513 1025C230.23 1025 1 795.77 1 513"
|
|
||||||
stroke={`url(#${id}-gradient-1)`}
|
|
||||||
strokeLinecap="round"
|
|
||||||
/>
|
|
||||||
<defs>
|
|
||||||
<linearGradient
|
|
||||||
id={`${id}-gradient-1`}
|
|
||||||
x1="1"
|
|
||||||
y1="513"
|
|
||||||
x2="1"
|
|
||||||
y2="1025"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
>
|
|
||||||
<stop stopColor="#06b6d4" />
|
|
||||||
<stop offset="1" stopColor="#06b6d4" stopOpacity="0" />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 1026 1026"
|
|
||||||
fill="none"
|
|
||||||
aria-hidden="true"
|
|
||||||
className="absolute inset-0 h-full w-full animate-spin-reverse-slower"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M913 513c0 220.914-179.086 400-400 400S113 733.914 113 513s179.086-400 400-400 400 179.086 400 400Z"
|
|
||||||
stroke="#D4D4D4"
|
|
||||||
strokeOpacity="0.7"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M913 513c0 220.914-179.086 400-400 400"
|
|
||||||
stroke={`url(#${id}-gradient-2)`}
|
|
||||||
strokeLinecap="round"
|
|
||||||
/>
|
|
||||||
<defs>
|
|
||||||
<linearGradient
|
|
||||||
id={`${id}-gradient-2`}
|
|
||||||
x1="913"
|
|
||||||
y1="513"
|
|
||||||
x2="913"
|
|
||||||
y2="913"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
>
|
|
||||||
<stop stopColor="#06b6d4" />
|
|
||||||
<stop offset="1" stopColor="#06b6d4" stopOpacity="0" />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function PlayIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" {...props}>
|
|
||||||
<circle cx="12" cy="12" r="11.5" stroke="#D4D4D4" />
|
|
||||||
<path
|
|
||||||
d="M9.5 14.382V9.618a.5.5 0 0 1 .724-.447l4.764 2.382a.5.5 0 0 1 0 .894l-4.764 2.382a.5.5 0 0 1-.724-.447Z"
|
|
||||||
fill="#A3A3A3"
|
|
||||||
stroke="#A3A3A3"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Hero() {
|
|
||||||
return (
|
|
||||||
<div className="overflow-hidden py-20 sm:py-32 lg:pb-32 xl:pb-36">
|
|
||||||
<Container>
|
|
||||||
<div className="lg:grid lg:grid-cols-12 lg:gap-x-8 lg:gap-y-20">
|
|
||||||
<div className="relative z-10 mx-auto max-w-2xl lg:col-span-7 lg:max-w-none lg:pt-6 xl:col-span-6">
|
|
||||||
<h1 className="text-4xl font-medium tracking-tight text-gray-900">
|
|
||||||
Mycelium
|
|
||||||
</h1>
|
|
||||||
<h2 className="mt-6 text-2xl tracking-tight text-gray-600">
|
|
||||||
Unleashing the Power of Decentralized Networks
|
|
||||||
</h2>
|
|
||||||
<p className="mt-6 text-lg text-gray-600">
|
|
||||||
Discover Mycelium, an end-to-end encrypted IPv6 overlay network. The future of secure, efficient, and scalable networking.
|
|
||||||
</p>
|
|
||||||
<p className="mt-6 text-lg text-gray-600">
|
|
||||||
Coming Soon: New Decentralized Features
|
|
||||||
</p>
|
|
||||||
<div className="mt-8 flex flex-wrap gap-x-6 gap-y-4">
|
|
||||||
<DownloadLink />
|
|
||||||
<Button
|
|
||||||
href="https://youtu.be/4oq15lxvkts?si=Heh_8DHqHaNpy3_F"
|
|
||||||
variant="outline"
|
|
||||||
>
|
|
||||||
<PlayIcon className="h-6 w-6 flex-none" />
|
|
||||||
<span className="ml-2.5">Watch the Demo</span>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="relative mt-10 sm:mt-20 lg:col-span-5 lg:row-span-2 lg:mt-0 xl:col-span-6">
|
|
||||||
<BackgroundIllustration className="absolute top-4 left-1/2 h-[1026px] w-[1026px] -translate-x-1/3 mask-[linear-gradient(to_bottom,white_20%,transparent_75%)] stroke-gray-300/70 sm:top-16 sm:-translate-x-1/2 lg:-top-16 lg:ml-12 xl:-top-14 xl:ml-0" />
|
|
||||||
<div className="-mx-4 h-[448px] mask-[linear-gradient(to_bottom,white_60%,transparent)] px-9 sm:mx-0 lg:absolute lg:-inset-x-10 lg:-top-10 lg:-bottom-20 lg:h-auto lg:px-0 lg:pt-10 xl:-bottom-32">
|
|
||||||
<PhoneFrame className="mx-auto max-w-[366px]" priority>
|
|
||||||
<AppDemo />
|
|
||||||
</PhoneFrame>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="relative -mt-4 lg:col-span-7 lg:mt-0 xl:col-span-6">
|
|
||||||
<p className="text-center text-sm font-semibold text-gray-900 lg:text-left">
|
|
||||||
As featured in
|
|
||||||
</p>
|
|
||||||
<ul
|
|
||||||
role="list"
|
|
||||||
className="mx-auto mt-8 flex max-w-xl flex-wrap justify-center gap-x-10 gap-y-8 lg:mx-0 lg:justify-start"
|
|
||||||
>
|
|
||||||
{[
|
|
||||||
['Forbes', logoForbes],
|
|
||||||
['TechCrunch', logoTechcrunch],
|
|
||||||
['Wired', logoWired],
|
|
||||||
['CNN', logoCnn, 'hidden xl:block'],
|
|
||||||
['BBC', logoBbc],
|
|
||||||
['CBS', logoCbs],
|
|
||||||
['Fast Company', logoFastCompany],
|
|
||||||
['HuffPost', logoHuffpost, 'hidden xl:block'],
|
|
||||||
].map(([name, logo, className]) => (
|
|
||||||
<li key={name} className={clsx('flex', className)}>
|
|
||||||
<Image src={logo} alt={name} className="h-8" unoptimized />
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Container>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -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,51 +18,24 @@ 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
|
|
||||||
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>
|
||||||
<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 bottom-10 -z-10 transform-gpu overflow-hidden blur-3xl lg:bottom-40"
|
<div className="text-center">
|
||||||
>
|
<div className="max-w-6xl">
|
||||||
<div
|
<H1 color="light">
|
||||||
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
|
<TypeAnimation
|
||||||
sequence={[
|
sequence={[
|
||||||
'Decentralized Autonomous Agentic Cloud.',
|
'Decentralized Autonomous Agentic Cloud.',
|
||||||
@@ -74,17 +47,20 @@ export function HomeHero() {
|
|||||||
/>
|
/>
|
||||||
</H1>
|
</H1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0 }}
|
initial={{ opacity: 0 }}
|
||||||
animate={{ opacity: 1 }}
|
animate={{ opacity: 1 }}
|
||||||
transition={{ duration: 1, delay: 1 }}
|
transition={{ duration: 1, delay: 1 }}
|
||||||
|
className="mt-12"
|
||||||
>
|
>
|
||||||
<PL className="absolute bottom-0 left-0 max-w-xl text-left" color="custom">
|
<PL className="mx-auto max-w-4xl text-center text-gray-100" color="light">
|
||||||
Mycelium's advancements in Agentic infrastructure supports private, secure and autonomous Agents that connect, learn and grow with you.
|
Mycelium's advancements in Agentic infrastructure supports private, secure and autonomous Agents that connect, learn and grow with you.
|
||||||
</PL>
|
</PL>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
import Link from 'next/link'
|
|
||||||
import clsx from 'clsx'
|
|
||||||
|
|
||||||
export function LinuxLink({
|
|
||||||
color = 'black',
|
|
||||||
}: {
|
|
||||||
color?: 'black' | 'white'
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
href="#"
|
|
||||||
aria-label="Download for Linux"
|
|
||||||
className={clsx(
|
|
||||||
'flex items-center rounded-lg transition-colors px-4 py-2',
|
|
||||||
color === 'black'
|
|
||||||
? 'bg-gray-800 text-white hover:bg-gray-900'
|
|
||||||
: 'bg-white text-gray-900 hover:bg-gray-50',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{/* Linux SVG */}
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 266 312"
|
|
||||||
aria-hidden="true"
|
|
||||||
className="h-5 w-5 mr-3"
|
|
||||||
>
|
|
||||||
<path d="M128.6640625 79.2793c0 1-1 1-1 1h-1c-1 0-1-1-2-2 0 0-1-1-1-2s0-1 1-1l2 1c1 1 2 2 2 3m-18-10c0-5-2-8-5-8 0 0 0 1-1 1v2h3c0 2 1 3 1 5h2m35-5c2 0 3 2 4 5h2c-1-1-1-2-1-3s0-2-1-3-2-2-3-2c0 0-1 1-2 1 0 1 1 1 1 2m-30 16c-1 0-1 0-1-1s0-2 1-3c2 0 3-1 3-1 1 0 1 1 1 1 0 1-1 2-3 4h-1m-11-1c-4-2-5-5-5-10 0-3 0-5 2-7 1-2 3-3 5-3s3 1 5 3c1 3 2 6 2 9v2h1v-1c1 0 1-2 1-6 0-3 0-6-2-9s-4-5-8-5c-3 0-6 2-7 5-2 4-2.4 7-2.4 12 0 4 1.4 8 5.4 12 1-1 2-1 3-2m125 141c1 0 1-.4 1-1.3 0-2.2-1-4.8-4-7.7-3-3-8-4.9-14-5.7-1-.1-2-.1-2-.1-1-.2-1-.2-2-.2-1-.1-3-.3-4-.5 3-9.3 4-17.5 4-24.7 0-10-2-17-6-23s-8-9-13-10c-1 1-1 1-1 2 5 2 10 6 13 12 3 7 4 13 4 20 0 5.6-1 13.9-5 24.5-4 1.6-8 5.3-11 11.1 0 .9 0 1.4 1 1.4 0 0 1-.9 2-2.6 2-1.7 3-3.4 5-5.1 3-1.7 5-2.6 8-2.6 5 0 10 .7 13 2.1 4 1.3 6 2.7 7 4.3 1 1.5 2 2.9 3 4.2 0 1.3 1 1.9 1 1.9m-92-145c-1-1-1-3-1-5 0-4 0-6 2-9 2-2 4-3 6-3 3 0 5 2 7 4 1 3 2 5 2 8 0 5-2 8-6 9 0 0 1 1 2 1 2 0 3 1 5 2 1-6 2-10 2-15 0-6-1-10-3-13-3-3-6-4-10-4-3 0-6 1-9 3-2 3-3 5-3 8 0 5 1 9 3 13 1 0 2 1 3 1m12 16c-13 9-23 13-31 13-7 0-14-3-20-8 1 2 2 4 3 5l6 6c4 4 9 6 14 6 7 0 15-4 25-11l9-6c2-2 4-4 4-7 0-1 0-2-1-2-1-2-6-5-16-8-9-4-16-6-20-6-3 0-8 2-15 6-6 4-10 8-10 12 0 0 1 1 2 3 6 5 12 8 18 8 8 0 18-4 31-14v2c1 0 1 1 1 1m23 202c4 7.52 11 11.3 19 11.3 2 0 4-.3 6-.9 2-.4 4-1.1 5-1.9 1-.7 2-1.4 3-2.2 2-.7 2-1.2 3-1.7l17-14.7c4-3.19 8-5.98 13-8.4 4-2.4 8-4 10-4.9 3-.8 5-2 7-3.6 1-1.5 2-3.4 2-5.8 0-2.9-2-5.1-4-6.7s-4-2.7-6-3.4-4-2.3-7-5c-2-2.6-4-6.2-5-10.9l-1-5.8c-1-2.7-1-4.7-2-5.8 0-.3 0-.4-1-.4s-3 .9-4 2.6c-2 1.7-4 3.6-6 5.6-1 2-4 3.8-6 5.5-3 1.7-6 2.6-8 2.6-8 0-12-2.2-15-6.5-2-3.2-3-6.9-4-11.1-2-1.7-3-2.6-5-2.6-5 0-7 5.2-7 15.7v31.1c0 .9-1 2.9-1 6-1 3.1-1 6.62-1 10.6l-2 11.1v.17m-145-5.29c9.3 1.36 20 4.27 32.1 8.71 12.1 4.4 19.5 6.7 22.2 6.7 7 0 12.8-3.1 17.6-9.09 1-1.94 1-4.22 1-6.84 0-9.45-5.7-21.4-17.1-35.9l-6.8-9.1c-1.4-1.9-3.1-4.8-5.3-8.7-2.1-3.9-4-6.9-5.5-9-1.3-2.3-3.4-4.6-6.1-6.9-2.6-2.3-5.6-3.8-8.9-4.6-4.2.8-7.1 2.2-8.5 4.1s-2.2 4-2.4 6.2c-.3 2.1-.9 3.5-1.9 4.2-1 .6-2.7 1.1-5 1.6-.5 0-1.4 0-2.7.1h-2.7c-5.3 0-8.9.6-10.8 1.6-2.5 2.9-3.8 6.2-3.8 9.7 0 1.6.4 4.3 1.2 8.1.8 3.7 1.2 6.7 1.2 8.8 0 4.1-1.2 8.2-3.7 12.3-2.5 4.3-3.8 7.5-3.8 9.78 1 3.88 7.6 6.61 19.7 8.21m33.3-90.9c0-6.9 1.8-14.5 5.5-23.5 3.6-9 7.2-15 10.7-19-.2-1-.7-1-1.5-1l-1-1c-2.9 3-6.4 10-10.6 20-4.2 9-6.4 17.3-6.4 23.4 0 4.5 1.1 8.4 3.1 11.8 2.2 3.3 7.5 8.1 15.9 14.2l10.6 6.9c11.3 9.8 17.3 16.6 17.3 20.6 0 2.1-1 4.2-4 6.5-2 2.4-4.7 3.6-7 3.6-.2 0-.3.2-.3.7 0 .1 1 2.1 3.1 6 4.2 5.7 13.2 8.5 25.2 8.5 22 0 39-9 52-27 0-5 0-8.1-1-9.4v-3.7c0-6.5 1-11.4 3-14.6s4-4.7 7-4.7c2 0 4 .7 6 2.2 1-7.7 1-14.4 1-20.4 0-9.1 0-16.6-2-23.6-1-6-3-11-5-15l-6-9c-2-3-3-6-5-9-1-4-2-7-2-12-3-5-5-10-8-15-2-5-4-10-6-14l-9 7c-10 7-18 10-25 10-6 0-11-1-14-5l-6-5c0 3-1 7-3 11l-6.3 12c-2.8 7-4.3 11-4.6 14-.4 2-.7 4-.9 4l-7.5 15c-8.1 15-12.2 28.9-12.2 40.4 0 2.3.2 4.7.6 7.1-4.5-3.1-6.7-7.4-6.7-13m71.6 94.6c-13 0-23 1.76-30 5.25v-.3c-5 6-10.6 9.1-18.4 9.1-4.9 0-12.6-1.9-23-5.7-10.5-3.6-19.8-6.36-27.9-8.18-.8-.23-2.6-.57-5.5-1.03-2.8-.45-5.4-.91-7.7-1.37-2.1-.45-4.5-1.13-7.1-2.05-2.5-.79-4.5-1.82-6-3.07-1.38-1.26-2.06-2.68-2.06-4.27 0-1.6.34-3.31 1.02-5.13.64-1.1 1.34-2.2 2.04-3.2.7-1.1 1.3-2.1 1.7-3.1.6-.9 1-1.8 1.4-2.8.4-.9.8-1.8 1-2.9.2-1 .4-2 .4-3s-.4-4-1.2-9.3c-.8-5.2-1.2-8.5-1.2-9.9 0-4.4 1-7.9 3.2-10.4s4.3-3.8 6.5-3.8h11.5c.9 0 2.3-.5 4.4-1.7.7-1.6 1.3-2.9 1.7-4.1.5-1.2.7-2.1.9-2.5.2-.6.4-1.2.6-1.7.4-.7.9-1.5 1.6-2.3-.8-1-1.2-2.3-1.2-3.9 0-1.1 0-2.1.2-2.7 0-3.6 1.7-8.7 5.3-15.4l3.5-6.3c2.9-5.4 5.1-9.4 6.7-13.4 1.7-4 3.5-10 5.5-18 1.6-7 5.4-14 11.4-21l7.5-9c5.2-6 8.6-11 10.5-15s2.9-9 2.9-13c0-2-.5-8-1.6-18-1-10-1.5-20-1.5-29 0-7 .6-12 1.9-17s3.6-10 7-14c3-4 7-8 13-10s13-3 21-3c3 0 6 0 9 1 3 0 7 1 12 3 4 2 8 4 11 7 4 3 7 8 10 13 2 6 4 12 5 20 1 5 1 10 2 17 0 6 1 10 1 13 1 3 1 7 2 12 1 4 2 8 4 11 2 4 4 8 7 12 3 5 7 10 11 16 9 10 16 21 20 32 5 10 8 23 8 36.9 0 6.9-1 13.6-3 20.1 2 0 3 .8 4 2.2s2 4.4 3 9.1l1 7.4c1 2.2 2 4.3 5 6.1 2 1.8 4 3.3 7 4.5 2 1 5 2.4 7 4.2 2 2 3 4.1 3 6.3 0 3.4-1 5.9-3 7.7-2 2-4 3.4-7 4.3-2 1-6 3-12 5.82-5 2.96-10 6.55-15 10.8l-10 8.51c-4 3.9-8 6.7-11 8.4-3 1.8-7 2.7-11 2.7l-7-.8c-8-2.1-13-6.1-16-12.2-16-1.94-29-2.9-37-2.9" fill="currentColor" />
|
|
||||||
</svg>
|
|
||||||
|
|
||||||
{/* Text */}
|
|
||||||
<div className="flex flex-col text-left leading-tight">
|
|
||||||
<span className="text-[9px] mt-0">Download for</span>
|
|
||||||
<span className="text-sm font-semibold -mt-1.5">Linux</span>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -3,22 +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', '/#about'],
|
['Technologies', '/#technologies'],
|
||||||
['Benefits', '/#benefits'],
|
['Network', '/#network'],
|
||||||
['Features', '/#features'],
|
['How it Works', '/#how-it-works'],
|
||||||
['Use Cases', '/#usecases'],
|
['Get Started', '/#get-started'],
|
||||||
['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)
|
||||||
@@ -34,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,42 +0,0 @@
|
|||||||
import Image from 'next/image'
|
|
||||||
import clsx from 'clsx'
|
|
||||||
|
|
||||||
import frame from '@/images/phone-frame.svg'
|
|
||||||
|
|
||||||
function PlaceholderFrame(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 366 729" aria-hidden="true" {...props}>
|
|
||||||
<path
|
|
||||||
fill="#F2F2F2"
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M300.092 1c41.22 0 63.223 21.99 63.223 63.213V184.94c-.173.184-.329.476-.458.851.188-.282.404-.547.647-.791.844-.073 2.496.257 2.496 2.157V268.719c-.406 2.023-2.605 2.023-2.605 2.023a7.119 7.119 0 0 1-.08-.102v394.462c0 41.213-22.001 63.212-63.223 63.212h-95.074c-.881-.468-2.474-.795-4.323-.838l-33.704-.005-.049.001h-.231l-.141-.001c-2.028 0-3.798.339-4.745.843H66.751c-41.223 0-63.223-21.995-63.223-63.208V287.739c-.402-.024-2.165-.23-2.524-2.02v-.973A2.039 2.039 0 0 1 1 284.62v-47.611c0-.042.001-.084.004-.126v-.726c0-1.9 1.652-2.23 2.496-2.157l.028.028v-16.289c-.402-.024-2.165-.23-2.524-2.02v-.973A2.039 2.039 0 0 1 1 214.62v-47.611c0-.042.001-.084.004-.126v-.726c0-1.9 1.652-2.23 2.496-2.157l.028.028v-26.041a2.26 2.26 0 0 0 .093-.236l-.064-.01a3.337 3.337 0 0 1-.72-.12l-.166-.028A2 2 0 0 1 1 135.62v-24.611a2 2 0 0 1 1.671-1.973l.857-.143v-44.68C3.528 22.99 25.53 1 66.75 1h233.341ZM3.952 234.516a5.481 5.481 0 0 0-.229-.278c.082.071.159.163.228.278Zm89.99-206.304A4.213 4.213 0 0 0 89.727 24H56.864C38.714 24 24 38.708 24 56.852v618.296C24 693.292 38.714 708 56.864 708h250.272c18.15 0 32.864-14.708 32.864-32.852V56.852C340 38.708 325.286 24 307.136 24h-32.864a4.212 4.212 0 0 0-4.213 4.212v2.527c0 10.235-8.3 18.532-18.539 18.532H112.48c-10.239 0-18.539-8.297-18.539-18.532v-2.527Z"
|
|
||||||
/>
|
|
||||||
<rect x="154" y="29" width="56" height="5" rx="2.5" fill="#D4D4D4" />
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function PhoneFrame({
|
|
||||||
className,
|
|
||||||
children,
|
|
||||||
priority = false,
|
|
||||||
...props
|
|
||||||
}: React.ComponentPropsWithoutRef<'div'> & { priority?: boolean }) {
|
|
||||||
return (
|
|
||||||
<div className={clsx('relative aspect-366/729', className)} {...props}>
|
|
||||||
<div className="absolute inset-y-[calc(1/729*100%)] right-[calc(5/729*100%)] left-[calc(7/729*100%)] rounded-[calc(58/366*100%)/calc(58/729*100%)] shadow-2xl" />
|
|
||||||
<div className="absolute top-[calc(23/729*100%)] left-[calc(23/366*100%)] grid h-[calc(686/729*100%)] w-[calc(318/366*100%)] transform grid-cols-1 overflow-hidden bg-gray-900 pt-[calc(23/318*100%)]">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
<PlaceholderFrame className="pointer-events-none absolute inset-0 h-full w-full fill-gray-100" />
|
|
||||||
<Image
|
|
||||||
src={frame}
|
|
||||||
alt=""
|
|
||||||
className="pointer-events-none absolute inset-0 h-full w-full"
|
|
||||||
unoptimized
|
|
||||||
priority={priority}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,288 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import { useState } from 'react'
|
|
||||||
import { Radio, RadioGroup } from '@headlessui/react'
|
|
||||||
import clsx from 'clsx'
|
|
||||||
|
|
||||||
import { Button } from '@/components/Button'
|
|
||||||
import { Container } from '@/components/Container'
|
|
||||||
import { Logomark } from '@/components/Logo'
|
|
||||||
|
|
||||||
const plans = [
|
|
||||||
{
|
|
||||||
name: 'Starter',
|
|
||||||
featured: false,
|
|
||||||
price: { Monthly: '$0', Annually: '$0' },
|
|
||||||
description:
|
|
||||||
'You’re new to investing but want to do it right. Get started for free.',
|
|
||||||
button: {
|
|
||||||
label: 'Get started for free',
|
|
||||||
href: '/register',
|
|
||||||
},
|
|
||||||
features: [
|
|
||||||
'Commission-free trading',
|
|
||||||
'Multi-layered encryption',
|
|
||||||
'One tip every day',
|
|
||||||
'Invest up to $1,500 each month',
|
|
||||||
],
|
|
||||||
logomarkClassName: 'fill-gray-300',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Investor',
|
|
||||||
featured: false,
|
|
||||||
price: { Monthly: '$7', Annually: '$70' },
|
|
||||||
description:
|
|
||||||
'You’ve been investing for a while. Invest more and grow your wealth faster.',
|
|
||||||
button: {
|
|
||||||
label: 'Subscribe',
|
|
||||||
href: '/register',
|
|
||||||
},
|
|
||||||
features: [
|
|
||||||
'Commission-free trading',
|
|
||||||
'Multi-layered encryption',
|
|
||||||
'One tip every hour',
|
|
||||||
'Invest up to $15,000 each month',
|
|
||||||
'Basic transaction anonymization',
|
|
||||||
],
|
|
||||||
logomarkClassName: 'fill-gray-500',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'VIP',
|
|
||||||
featured: true,
|
|
||||||
price: { Monthly: '$199', Annually: '$1,990' },
|
|
||||||
description:
|
|
||||||
'You’ve got a huge amount of assets but it’s not enough. To the moon.',
|
|
||||||
button: {
|
|
||||||
label: 'Subscribe',
|
|
||||||
href: '/register',
|
|
||||||
},
|
|
||||||
features: [
|
|
||||||
'Commission-free trading',
|
|
||||||
'Multi-layered encryption',
|
|
||||||
'Real-time tip notifications',
|
|
||||||
'No investment limits',
|
|
||||||
'Advanced transaction anonymization',
|
|
||||||
'Automated tax-loss harvesting',
|
|
||||||
],
|
|
||||||
logomarkClassName: 'fill-cyan-500',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
function CheckIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 24 24" aria-hidden="true" {...props}>
|
|
||||||
<path
|
|
||||||
d="M9.307 12.248a.75.75 0 1 0-1.114 1.004l1.114-1.004ZM11 15.25l-.557.502a.75.75 0 0 0 1.15-.043L11 15.25Zm4.844-5.041a.75.75 0 0 0-1.188-.918l1.188.918Zm-7.651 3.043 2.25 2.5 1.114-1.004-2.25-2.5-1.114 1.004Zm3.4 2.457 4.25-5.5-1.187-.918-4.25 5.5 1.188.918Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
<circle
|
|
||||||
cx="12"
|
|
||||||
cy="12"
|
|
||||||
r="8.25"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="1.5"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function Plan({
|
|
||||||
name,
|
|
||||||
price,
|
|
||||||
description,
|
|
||||||
button,
|
|
||||||
features,
|
|
||||||
activePeriod,
|
|
||||||
logomarkClassName,
|
|
||||||
featured = false,
|
|
||||||
}: {
|
|
||||||
name: string
|
|
||||||
price: {
|
|
||||||
Monthly: string
|
|
||||||
Annually: string
|
|
||||||
}
|
|
||||||
description: string
|
|
||||||
button: {
|
|
||||||
label: string
|
|
||||||
href: string
|
|
||||||
}
|
|
||||||
features: Array<string>
|
|
||||||
activePeriod: 'Monthly' | 'Annually'
|
|
||||||
logomarkClassName?: string
|
|
||||||
featured?: boolean
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<section
|
|
||||||
className={clsx(
|
|
||||||
'flex flex-col overflow-hidden rounded-3xl p-6 shadow-lg shadow-gray-900/5',
|
|
||||||
featured ? 'order-first bg-gray-900 lg:order-none' : 'bg-white',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<h3
|
|
||||||
className={clsx(
|
|
||||||
'flex items-center text-sm font-semibold',
|
|
||||||
featured ? 'text-white' : 'text-gray-900',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Logomark className={clsx('h-6 w-6 flex-none', logomarkClassName)} />
|
|
||||||
<span className="ml-4">{name}</span>
|
|
||||||
</h3>
|
|
||||||
<p
|
|
||||||
className={clsx(
|
|
||||||
'relative mt-5 flex text-3xl tracking-tight',
|
|
||||||
featured ? 'text-white' : 'text-gray-900',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{price.Monthly === price.Annually ? (
|
|
||||||
price.Monthly
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<span
|
|
||||||
aria-hidden={activePeriod === 'Annually'}
|
|
||||||
className={clsx(
|
|
||||||
'transition duration-300',
|
|
||||||
activePeriod === 'Annually' &&
|
|
||||||
'pointer-events-none translate-x-6 opacity-0 select-none',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{price.Monthly}
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
aria-hidden={activePeriod === 'Monthly'}
|
|
||||||
className={clsx(
|
|
||||||
'absolute top-0 left-0 transition duration-300',
|
|
||||||
activePeriod === 'Monthly' &&
|
|
||||||
'pointer-events-none -translate-x-6 opacity-0 select-none',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{price.Annually}
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
<p
|
|
||||||
className={clsx(
|
|
||||||
'mt-3 text-sm',
|
|
||||||
featured ? 'text-gray-300' : 'text-gray-700',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{description}
|
|
||||||
</p>
|
|
||||||
<div className="order-last mt-6">
|
|
||||||
<ul
|
|
||||||
role="list"
|
|
||||||
className={clsx(
|
|
||||||
'-my-2 divide-y text-sm',
|
|
||||||
featured
|
|
||||||
? 'divide-gray-800 text-gray-300'
|
|
||||||
: 'divide-gray-200 text-gray-700',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{features.map((feature) => (
|
|
||||||
<li key={feature} className="flex py-2">
|
|
||||||
<CheckIcon
|
|
||||||
className={clsx(
|
|
||||||
'h-6 w-6 flex-none',
|
|
||||||
featured ? 'text-white' : 'text-cyan-500',
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<span className="ml-4">{feature}</span>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
href={button.href}
|
|
||||||
color={featured ? 'cyan' : 'gray'}
|
|
||||||
className="mt-6"
|
|
||||||
aria-label={`Get started with the ${name} plan for ${price}`}
|
|
||||||
>
|
|
||||||
{button.label}
|
|
||||||
</Button>
|
|
||||||
</section>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Pricing() {
|
|
||||||
let [activePeriod, setActivePeriod] = useState<'Monthly' | 'Annually'>(
|
|
||||||
'Monthly',
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section
|
|
||||||
id="pricing"
|
|
||||||
aria-labelledby="pricing-title"
|
|
||||||
className="border-t border-gray-200 bg-gray-100 py-20 sm:py-32"
|
|
||||||
>
|
|
||||||
<Container>
|
|
||||||
<div className="mx-auto max-w-2xl text-center">
|
|
||||||
<h2
|
|
||||||
id="pricing-title"
|
|
||||||
className="text-3xl font-medium tracking-tight text-gray-900"
|
|
||||||
>
|
|
||||||
Flat pricing, no management fees.
|
|
||||||
</h2>
|
|
||||||
<p className="mt-2 text-lg text-gray-600">
|
|
||||||
Whether you’re one person trying to get ahead or a big firm trying
|
|
||||||
to take over the world, we’ve got a plan for you.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-8 flex justify-center">
|
|
||||||
<div className="relative">
|
|
||||||
<RadioGroup
|
|
||||||
value={activePeriod}
|
|
||||||
onChange={setActivePeriod}
|
|
||||||
className="grid grid-cols-2"
|
|
||||||
>
|
|
||||||
{['Monthly', 'Annually'].map((period) => (
|
|
||||||
<Radio
|
|
||||||
key={period}
|
|
||||||
value={period}
|
|
||||||
className={clsx(
|
|
||||||
'cursor-pointer border border-gray-300 px-[calc(--spacing(3)-1px)] py-[calc(--spacing(2)-1px)] text-sm text-gray-700 transition-colors hover:border-gray-400 data-focus:outline-2 data-focus:outline-offset-2',
|
|
||||||
period === 'Monthly'
|
|
||||||
? 'rounded-l-lg'
|
|
||||||
: '-ml-px rounded-r-lg',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{period}
|
|
||||||
</Radio>
|
|
||||||
))}
|
|
||||||
</RadioGroup>
|
|
||||||
<div
|
|
||||||
aria-hidden="true"
|
|
||||||
className={clsx(
|
|
||||||
'pointer-events-none absolute inset-0 z-10 grid grid-cols-2 overflow-hidden rounded-lg bg-cyan-500 transition-all duration-300',
|
|
||||||
activePeriod === 'Monthly'
|
|
||||||
? '[clip-path:inset(0_50%_0_0)]'
|
|
||||||
: '[clip-path:inset(0_0_0_calc(50%-1px))]',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{['Monthly', 'Annually'].map((period) => (
|
|
||||||
<div
|
|
||||||
key={period}
|
|
||||||
className={clsx(
|
|
||||||
'py-2 text-center text-sm font-semibold text-white',
|
|
||||||
period === 'Annually' && '-ml-px',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{period}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mx-auto mt-16 grid max-w-2xl grid-cols-1 items-start gap-x-8 gap-y-10 sm:mt-20 lg:max-w-none lg:grid-cols-3">
|
|
||||||
{plans.map((plan) => (
|
|
||||||
<Plan key={plan.name} {...plan} activePeriod={activePeriod} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</Container>
|
|
||||||
</section>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,599 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import { Fragment, useEffect, useId, useRef, useState } from 'react'
|
|
||||||
import { Tab, TabGroup, TabList, TabPanel, TabPanels } from '@headlessui/react'
|
|
||||||
import clsx from 'clsx'
|
|
||||||
import {
|
|
||||||
type MotionProps,
|
|
||||||
type Variant,
|
|
||||||
type Variants,
|
|
||||||
AnimatePresence,
|
|
||||||
motion,
|
|
||||||
} from 'framer-motion'
|
|
||||||
import { useDebouncedCallback } from 'use-debounce'
|
|
||||||
|
|
||||||
import { AppScreen } from '@/components/AppScreen'
|
|
||||||
import { CircleBackground } from '@/components/CircleBackground'
|
|
||||||
import { Container } from '@/components/Container'
|
|
||||||
import { PhoneFrame } from '@/components/PhoneFrame'
|
|
||||||
import {
|
|
||||||
DiageoLogo,
|
|
||||||
LaravelLogo,
|
|
||||||
MirageLogo,
|
|
||||||
ReversableLogo,
|
|
||||||
StatamicLogo,
|
|
||||||
StaticKitLogo,
|
|
||||||
TransistorLogo,
|
|
||||||
TupleLogo,
|
|
||||||
} from '@/components/StockLogos'
|
|
||||||
|
|
||||||
const MotionAppScreenHeader = motion(AppScreen.Header)
|
|
||||||
const MotionAppScreenBody = motion(AppScreen.Body)
|
|
||||||
|
|
||||||
interface CustomAnimationProps {
|
|
||||||
isForwards: boolean
|
|
||||||
changeCount: number
|
|
||||||
}
|
|
||||||
|
|
||||||
const features = [
|
|
||||||
{
|
|
||||||
name: 'Decentralized Nodes',
|
|
||||||
description:
|
|
||||||
"Mycelium operates through a network of decentralized nodes, similar to how nature's mycelium forms a decentralized network of threads. Each node acts as a connection point in the overall digital ecosystem.",
|
|
||||||
icon: DeviceUserIcon,
|
|
||||||
screen: InviteScreen,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Efficient Data Routing',
|
|
||||||
description:
|
|
||||||
'Mycelium optimizes data routing by choosing the most efficient path for communication. Data travels along the shortest path in terms of latency, ensuring that information reaches its destination swiftly.',
|
|
||||||
icon: DeviceNotificationIcon,
|
|
||||||
screen: StocksScreen,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'End-to-End Encryption',
|
|
||||||
description:
|
|
||||||
'Each node in the system is identified by a unique key pair. Data between nodes is encrypted using secret keys derived from these pairs. This ensures that data remains confidential, enhancing the privacy of the network.',
|
|
||||||
icon: DeviceTouchIcon,
|
|
||||||
screen: InvestScreen,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
function DeviceUserIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 32 32" aria-hidden="true" {...props}>
|
|
||||||
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M16 23a3 3 0 100-6 3 3 0 000 6zm-1 2a4 4 0 00-4 4v1a2 2 0 002 2h6a2 2 0 002-2v-1a4 4 0 00-4-4h-2z"
|
|
||||||
fill="#737373"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M5 4a4 4 0 014-4h14a4 4 0 014 4v24a4.002 4.002 0 01-3.01 3.877c-.535.136-.99-.325-.99-.877s.474-.98.959-1.244A2 2 0 0025 28V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9a2 2 0 00-2 2v24a2 2 0 001.041 1.756C8.525 30.02 9 30.448 9 31s-.455 1.013-.99.877A4.002 4.002 0 015 28V4z"
|
|
||||||
fill="#A3A3A3"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function DeviceNotificationIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 32 32" aria-hidden="true" {...props}>
|
|
||||||
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M9 0a4 4 0 00-4 4v24a4 4 0 004 4h14a4 4 0 004-4V4a4 4 0 00-4-4H9zm0 2a2 2 0 00-2 2v24a2 2 0 002 2h14a2 2 0 002-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9z"
|
|
||||||
fill="#A3A3A3"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M9 8a2 2 0 012-2h10a2 2 0 012 2v2a2 2 0 01-2 2H11a2 2 0 01-2-2V8z"
|
|
||||||
fill="#737373"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function DeviceTouchIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
let id = useId()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 32 32" fill="none" aria-hidden="true" {...props}>
|
|
||||||
<defs>
|
|
||||||
<linearGradient
|
|
||||||
id={`${id}-gradient`}
|
|
||||||
x1={14}
|
|
||||||
y1={14.5}
|
|
||||||
x2={7}
|
|
||||||
y2={17}
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
>
|
|
||||||
<stop stopColor="#737373" />
|
|
||||||
<stop offset={1} stopColor="#D4D4D4" stopOpacity={0} />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M5 4a4 4 0 014-4h14a4 4 0 014 4v13h-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9a2 2 0 00-2 2v24a2 2 0 002 2h4v2H9a4 4 0 01-4-4V4z"
|
|
||||||
fill="#A3A3A3"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M7 22c0-4.694 3.5-8 8-8"
|
|
||||||
stroke={`url(#${id}-gradient)`}
|
|
||||||
strokeWidth={2}
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M21 20l.217-5.513a1.431 1.431 0 00-2.85-.226L17.5 21.5l-1.51-1.51a2.107 2.107 0 00-2.98 0 .024.024 0 00-.005.024l3.083 9.25A4 4 0 0019.883 32H25a4 4 0 004-4v-5a3 3 0 00-3-3h-5z"
|
|
||||||
fill="#A3A3A3"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const headerAnimation: Variants = {
|
|
||||||
initial: { opacity: 0, transition: { duration: 0.3 } },
|
|
||||||
animate: { opacity: 1, transition: { duration: 0.3, delay: 0.3 } },
|
|
||||||
exit: { opacity: 0, transition: { duration: 0.3 } },
|
|
||||||
}
|
|
||||||
|
|
||||||
const maxZIndex = 2147483647
|
|
||||||
|
|
||||||
const bodyVariantBackwards: Variant = {
|
|
||||||
opacity: 0.4,
|
|
||||||
scale: 0.8,
|
|
||||||
zIndex: 0,
|
|
||||||
filter: 'blur(4px)',
|
|
||||||
transition: { duration: 0.4 },
|
|
||||||
}
|
|
||||||
|
|
||||||
const bodyVariantForwards: Variant = (custom: CustomAnimationProps) => ({
|
|
||||||
y: '100%',
|
|
||||||
zIndex: maxZIndex - custom.changeCount,
|
|
||||||
transition: { duration: 0.4 },
|
|
||||||
})
|
|
||||||
|
|
||||||
const bodyAnimation: MotionProps = {
|
|
||||||
initial: 'initial',
|
|
||||||
animate: 'animate',
|
|
||||||
exit: 'exit',
|
|
||||||
variants: {
|
|
||||||
initial: (custom: CustomAnimationProps, ...props) =>
|
|
||||||
custom.isForwards
|
|
||||||
? bodyVariantForwards(custom, ...props)
|
|
||||||
: bodyVariantBackwards,
|
|
||||||
animate: (custom: CustomAnimationProps) => ({
|
|
||||||
y: '0%',
|
|
||||||
opacity: 1,
|
|
||||||
scale: 1,
|
|
||||||
zIndex: maxZIndex / 2 - custom.changeCount,
|
|
||||||
filter: 'blur(0px)',
|
|
||||||
transition: { duration: 0.4 },
|
|
||||||
}),
|
|
||||||
exit: (custom: CustomAnimationProps, ...props) =>
|
|
||||||
custom.isForwards
|
|
||||||
? bodyVariantBackwards
|
|
||||||
: bodyVariantForwards(custom, ...props),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
type ScreenProps =
|
|
||||||
| {
|
|
||||||
animated: true
|
|
||||||
custom: CustomAnimationProps
|
|
||||||
}
|
|
||||||
| { animated?: false }
|
|
||||||
|
|
||||||
function InviteScreen(props: ScreenProps) {
|
|
||||||
return (
|
|
||||||
<AppScreen className="w-full">
|
|
||||||
<MotionAppScreenHeader {...(props.animated ? headerAnimation : {})}>
|
|
||||||
<AppScreen.Title>Invite people</AppScreen.Title>
|
|
||||||
<AppScreen.Subtitle>
|
|
||||||
Get tips <span className="text-white">5s sooner</span> for every
|
|
||||||
invite.
|
|
||||||
</AppScreen.Subtitle>
|
|
||||||
</MotionAppScreenHeader>
|
|
||||||
<MotionAppScreenBody
|
|
||||||
{...(props.animated ? { ...bodyAnimation, custom: props.custom } : {})}
|
|
||||||
>
|
|
||||||
<div className="px-4 py-6">
|
|
||||||
<div className="space-y-6">
|
|
||||||
{[
|
|
||||||
{ label: 'Full name', value: 'Albert H. Wiggin' },
|
|
||||||
{ label: 'Email address', value: 'awiggin@chase.com' },
|
|
||||||
].map((field) => (
|
|
||||||
<div key={field.label}>
|
|
||||||
<div className="text-sm text-gray-500">{field.label}</div>
|
|
||||||
<div className="mt-2 border-b border-gray-200 pb-2 text-sm text-gray-900">
|
|
||||||
{field.value}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className="mt-6 rounded-lg bg-cyan-500 px-3 py-2 text-center text-sm font-semibold text-white">
|
|
||||||
Invite person
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</MotionAppScreenBody>
|
|
||||||
</AppScreen>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function StocksScreen(props: ScreenProps) {
|
|
||||||
return (
|
|
||||||
<AppScreen className="w-full">
|
|
||||||
<MotionAppScreenHeader {...(props.animated ? headerAnimation : {})}>
|
|
||||||
<AppScreen.Title>Stocks</AppScreen.Title>
|
|
||||||
<AppScreen.Subtitle>March 9, 2022</AppScreen.Subtitle>
|
|
||||||
</MotionAppScreenHeader>
|
|
||||||
<MotionAppScreenBody
|
|
||||||
{...(props.animated ? { ...bodyAnimation, custom: props.custom } : {})}
|
|
||||||
>
|
|
||||||
<div className="divide-y divide-gray-100">
|
|
||||||
{[
|
|
||||||
{
|
|
||||||
name: 'Laravel',
|
|
||||||
price: '4,098.01',
|
|
||||||
change: '+4.98%',
|
|
||||||
color: '#F9322C',
|
|
||||||
logo: LaravelLogo,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Tuple',
|
|
||||||
price: '5,451.10',
|
|
||||||
change: '-3.38%',
|
|
||||||
color: '#5A67D8',
|
|
||||||
logo: TupleLogo,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Transistor',
|
|
||||||
price: '4,098.41',
|
|
||||||
change: '+6.25%',
|
|
||||||
color: '#2A5B94',
|
|
||||||
logo: TransistorLogo,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Diageo',
|
|
||||||
price: '250.65',
|
|
||||||
change: '+1.25%',
|
|
||||||
color: '#3320A7',
|
|
||||||
logo: DiageoLogo,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'StaticKit',
|
|
||||||
price: '250.65',
|
|
||||||
change: '-3.38%',
|
|
||||||
color: '#2A3034',
|
|
||||||
logo: StaticKitLogo,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Statamic',
|
|
||||||
price: '5,040.85',
|
|
||||||
change: '-3.11%',
|
|
||||||
color: '#0EA5E9',
|
|
||||||
logo: StatamicLogo,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Mirage',
|
|
||||||
price: '140.44',
|
|
||||||
change: '+9.09%',
|
|
||||||
color: '#16A34A',
|
|
||||||
logo: MirageLogo,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Reversable',
|
|
||||||
price: '550.60',
|
|
||||||
change: '-1.25%',
|
|
||||||
color: '#8D8D8D',
|
|
||||||
logo: ReversableLogo,
|
|
||||||
},
|
|
||||||
].map((stock) => (
|
|
||||||
<div key={stock.name} className="flex items-center gap-4 px-4 py-3">
|
|
||||||
<div
|
|
||||||
className="flex-none rounded-full"
|
|
||||||
style={{ backgroundColor: stock.color }}
|
|
||||||
>
|
|
||||||
<stock.logo className="h-10 w-10" />
|
|
||||||
</div>
|
|
||||||
<div className="flex-auto text-sm text-gray-900">
|
|
||||||
{stock.name}
|
|
||||||
</div>
|
|
||||||
<div className="flex-none text-right">
|
|
||||||
<div className="text-sm font-medium text-gray-900">
|
|
||||||
{stock.price}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={clsx(
|
|
||||||
'text-xs/5',
|
|
||||||
stock.change.startsWith('+')
|
|
||||||
? 'text-cyan-500'
|
|
||||||
: 'text-gray-500',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{stock.change}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</MotionAppScreenBody>
|
|
||||||
</AppScreen>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function InvestScreen(props: ScreenProps) {
|
|
||||||
return (
|
|
||||||
<AppScreen className="w-full">
|
|
||||||
<MotionAppScreenHeader {...(props.animated ? headerAnimation : {})}>
|
|
||||||
<AppScreen.Title>Buy $LA</AppScreen.Title>
|
|
||||||
<AppScreen.Subtitle>
|
|
||||||
<span className="text-white">$34.28</span> per share
|
|
||||||
</AppScreen.Subtitle>
|
|
||||||
</MotionAppScreenHeader>
|
|
||||||
<MotionAppScreenBody
|
|
||||||
{...(props.animated ? { ...bodyAnimation, custom: props.custom } : {})}
|
|
||||||
>
|
|
||||||
<div className="px-4 py-6">
|
|
||||||
<div className="space-y-4">
|
|
||||||
{[
|
|
||||||
{ label: 'Number of shares', value: '100' },
|
|
||||||
{
|
|
||||||
label: 'Current market price',
|
|
||||||
value: (
|
|
||||||
<div className="flex">
|
|
||||||
$34.28
|
|
||||||
<svg viewBox="0 0 24 24" fill="none" className="h-6 w-6">
|
|
||||||
<path
|
|
||||||
d="M17 15V7H9M17 7 7 17"
|
|
||||||
stroke="#06B6D4"
|
|
||||||
strokeWidth="2"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{ label: 'Estimated cost', value: '$3,428.00' },
|
|
||||||
].map((item) => (
|
|
||||||
<div
|
|
||||||
key={item.label}
|
|
||||||
className="flex justify-between border-b border-gray-100 pb-4"
|
|
||||||
>
|
|
||||||
<div className="text-sm text-gray-500">{item.label}</div>
|
|
||||||
<div className="text-sm font-semibold text-gray-900">
|
|
||||||
{item.value}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
<div className="rounded-lg bg-cyan-500 px-3 py-2 text-center text-sm font-semibold text-white">
|
|
||||||
Buy shares
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</MotionAppScreenBody>
|
|
||||||
</AppScreen>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function usePrevious<T>(value: T) {
|
|
||||||
let ref = useRef<T>()
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
ref.current = value
|
|
||||||
}, [value])
|
|
||||||
|
|
||||||
return ref.current
|
|
||||||
}
|
|
||||||
|
|
||||||
function FeaturesDesktop() {
|
|
||||||
let [changeCount, setChangeCount] = useState(0)
|
|
||||||
let [selectedIndex, setSelectedIndex] = useState(0)
|
|
||||||
let prevIndex = usePrevious(selectedIndex)
|
|
||||||
let isForwards = prevIndex === undefined ? true : selectedIndex > prevIndex
|
|
||||||
|
|
||||||
let onChange = useDebouncedCallback(
|
|
||||||
(selectedIndex) => {
|
|
||||||
setSelectedIndex(selectedIndex)
|
|
||||||
setChangeCount((changeCount) => changeCount + 1)
|
|
||||||
},
|
|
||||||
100,
|
|
||||||
{ leading: true },
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TabGroup
|
|
||||||
className="grid grid-cols-12 items-center gap-8 lg:gap-16 xl:gap-24"
|
|
||||||
selectedIndex={selectedIndex}
|
|
||||||
onChange={onChange}
|
|
||||||
vertical
|
|
||||||
>
|
|
||||||
<TabList className="relative z-10 order-last col-span-6 space-y-6">
|
|
||||||
{features.map((feature, featureIndex) => (
|
|
||||||
<div
|
|
||||||
key={feature.name}
|
|
||||||
className="relative rounded-2xl transition-colors hover:bg-gray-800/30"
|
|
||||||
>
|
|
||||||
{featureIndex === selectedIndex && (
|
|
||||||
<motion.div
|
|
||||||
layoutId="activeBackground"
|
|
||||||
className="absolute inset-0 bg-gray-800"
|
|
||||||
initial={{ borderRadius: 16 }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<div className="relative z-10 p-8">
|
|
||||||
<feature.icon className="h-8 w-8" />
|
|
||||||
<h3 className="mt-6 text-lg font-semibold text-white">
|
|
||||||
<Tab className="text-left data-selected:not-data-focus:outline-hidden">
|
|
||||||
<span className="absolute inset-0 rounded-2xl" />
|
|
||||||
{feature.name}
|
|
||||||
</Tab>
|
|
||||||
</h3>
|
|
||||||
<p className="mt-2 text-sm text-gray-400">
|
|
||||||
{feature.description}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</TabList>
|
|
||||||
<div className="relative col-span-6">
|
|
||||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
|
|
||||||
<CircleBackground color="#13B5C8" className="animate-spin-slower" />
|
|
||||||
</div>
|
|
||||||
<PhoneFrame className="z-10 mx-auto w-full max-w-[366px]">
|
|
||||||
<TabPanels as={Fragment}>
|
|
||||||
<AnimatePresence
|
|
||||||
initial={false}
|
|
||||||
custom={{ isForwards, changeCount }}
|
|
||||||
>
|
|
||||||
{features.map((feature, featureIndex) =>
|
|
||||||
selectedIndex === featureIndex ? (
|
|
||||||
<TabPanel
|
|
||||||
static
|
|
||||||
key={feature.name + changeCount}
|
|
||||||
className="col-start-1 row-start-1 flex focus:outline-offset-32 data-selected:not-data-focus:outline-hidden"
|
|
||||||
>
|
|
||||||
<feature.screen
|
|
||||||
animated
|
|
||||||
custom={{ isForwards, changeCount }}
|
|
||||||
/>
|
|
||||||
</TabPanel>
|
|
||||||
) : null,
|
|
||||||
)}
|
|
||||||
</AnimatePresence>
|
|
||||||
</TabPanels>
|
|
||||||
</PhoneFrame>
|
|
||||||
</div>
|
|
||||||
</TabGroup>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function FeaturesMobile() {
|
|
||||||
let [activeIndex, setActiveIndex] = useState(0)
|
|
||||||
let slideContainerRef = useRef<React.ElementRef<'div'>>(null)
|
|
||||||
let slideRefs = useRef<Array<React.ElementRef<'div'>>>([])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let observer = new window.IntersectionObserver(
|
|
||||||
(entries) => {
|
|
||||||
for (let entry of entries) {
|
|
||||||
if (entry.isIntersecting && entry.target instanceof HTMLDivElement) {
|
|
||||||
setActiveIndex(slideRefs.current.indexOf(entry.target))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
root: slideContainerRef.current,
|
|
||||||
threshold: 0.6,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
for (let slide of slideRefs.current) {
|
|
||||||
if (slide) {
|
|
||||||
observer.observe(slide)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
observer.disconnect()
|
|
||||||
}
|
|
||||||
}, [slideContainerRef, slideRefs])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div
|
|
||||||
ref={slideContainerRef}
|
|
||||||
className="-mb-4 flex snap-x snap-mandatory -space-x-4 overflow-x-auto overscroll-x-contain scroll-smooth pb-4 [scrollbar-width:none] sm:-space-x-6 [&::-webkit-scrollbar]:hidden"
|
|
||||||
>
|
|
||||||
{features.map((feature, featureIndex) => (
|
|
||||||
<div
|
|
||||||
key={featureIndex}
|
|
||||||
ref={(ref) => {
|
|
||||||
if (ref) {
|
|
||||||
slideRefs.current[featureIndex] = ref
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
className="w-full flex-none snap-center px-4 sm:px-6"
|
|
||||||
>
|
|
||||||
<div className="relative transform overflow-hidden rounded-2xl bg-gray-800 px-5 py-6">
|
|
||||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
|
|
||||||
<CircleBackground
|
|
||||||
color="#13B5C8"
|
|
||||||
className={featureIndex % 2 === 1 ? 'rotate-180' : undefined}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<PhoneFrame className="relative mx-auto w-full max-w-[366px]">
|
|
||||||
<feature.screen />
|
|
||||||
</PhoneFrame>
|
|
||||||
<div className="absolute inset-x-0 bottom-0 bg-gray-800/95 p-6 backdrop-blur-sm sm:p-10">
|
|
||||||
<feature.icon className="h-8 w-8" />
|
|
||||||
<h3 className="mt-6 text-sm font-semibold text-white sm:text-lg">
|
|
||||||
{feature.name}
|
|
||||||
</h3>
|
|
||||||
<p className="mt-2 text-sm text-gray-400">
|
|
||||||
{feature.description}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className="mt-6 flex justify-center gap-3">
|
|
||||||
{features.map((_, featureIndex) => (
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
key={featureIndex}
|
|
||||||
className={clsx(
|
|
||||||
'relative h-0.5 w-4 rounded-full',
|
|
||||||
featureIndex === activeIndex ? 'bg-gray-300' : 'bg-gray-500',
|
|
||||||
)}
|
|
||||||
aria-label={`Go to slide ${featureIndex + 1}`}
|
|
||||||
onClick={() => {
|
|
||||||
slideRefs.current[featureIndex].scrollIntoView({
|
|
||||||
block: 'nearest',
|
|
||||||
inline: 'nearest',
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span className="absolute -inset-x-1.5 -inset-y-3" />
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function PrimaryFeatures() {
|
|
||||||
return (
|
|
||||||
<section
|
|
||||||
id="features"
|
|
||||||
aria-label="Features for investing all your money"
|
|
||||||
className="bg-gray-900 py-20 sm:py-32"
|
|
||||||
>
|
|
||||||
<Container>
|
|
||||||
<div className="mx-auto max-w-2xl lg:mx-0 lg:max-w-3xl">
|
|
||||||
<h2 className="text-3xl font-medium tracking-tight text-white">
|
|
||||||
How Mycelium Operates
|
|
||||||
</h2>
|
|
||||||
<p className="mt-6 text-lg text-gray-300">
|
|
||||||
Mycelium, like its natural namesake, thrives on decentralization, efficiency, and security, making it a truly powerful force in the world of decentralized networks.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</Container>
|
|
||||||
<div className="mt-16 md:hidden">
|
|
||||||
<FeaturesMobile />
|
|
||||||
</div>
|
|
||||||
<Container className="hidden md:mt-20 md:block">
|
|
||||||
<FeaturesDesktop />
|
|
||||||
</Container>
|
|
||||||
</section>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,225 +0,0 @@
|
|||||||
import { useId } from 'react'
|
|
||||||
|
|
||||||
import { Container } from '@/components/Container'
|
|
||||||
|
|
||||||
const features = [
|
|
||||||
{
|
|
||||||
name: 'Quantum Safe Storage Functionality',
|
|
||||||
description:
|
|
||||||
"Mycelium's quantum safe storage enables flexible, scalable, and efficient data distribution across a decentralized network, ensuring redundancy and security.",
|
|
||||||
icon: DeviceArrowIcon,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Entry and Exit Points for AI Workloads',
|
|
||||||
description:
|
|
||||||
'Seamlessly connect AI applications to Mycelium, providing optimized and secured data pipelines for training, inference, and real-time processing.',
|
|
||||||
icon: DeviceCardsIcon,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Data Storage and Retrieval Mechanisms',
|
|
||||||
description:
|
|
||||||
'Users can choose between storing data locally for quick access or utilizing the distributed grid for enhanced scalability and resilience.',
|
|
||||||
icon: DeviceClockIcon,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Integrated Name Services (DNS)',
|
|
||||||
description:
|
|
||||||
'The Integrated DNS system efficiently finds the shortest path between users and websites, automatically balancing loads and identifying alternative routes in case of internet issues.',
|
|
||||||
icon: DeviceListIcon,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Frontend/Backend Integration',
|
|
||||||
description:
|
|
||||||
'Mycelium provides seamless integration with existing applications, enabling developers to leverage decentralized storage across both frontend and backend architectures.',
|
|
||||||
icon: DeviceLockIcon,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'CDN (Content Delivery Network)',
|
|
||||||
description:
|
|
||||||
'Mycelium accelerates data distribution by acting as a decentralized CDN, ensuring fast, secure, and efficient content delivery across global nodes with minimal latency.',
|
|
||||||
icon: DeviceChartIcon,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
function DeviceArrowIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 32 32" aria-hidden="true" {...props}>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M9 0a4 4 0 00-4 4v24a4 4 0 004 4h14a4 4 0 004-4V4a4 4 0 00-4-4H9zm0 2a2 2 0 00-2 2v24a2 2 0 002 2h14a2 2 0 002-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9z"
|
|
||||||
fill="#737373"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M12 25l8-8m0 0h-6m6 0v6"
|
|
||||||
stroke="#171717"
|
|
||||||
strokeWidth={2}
|
|
||||||
strokeLinecap="round"
|
|
||||||
/>
|
|
||||||
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function DeviceCardsIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
let id = useId()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 32 32" aria-hidden="true" {...props}>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M9 0a4 4 0 00-4 4v24a4 4 0 004 4h14a4 4 0 004-4V4a4 4 0 00-4-4H9zm0 2a2 2 0 00-2 2v24a2 2 0 002 2h14a2 2 0 002-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9z"
|
|
||||||
fill="#737373"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M9 13a1 1 0 011-1h12a1 1 0 011 1v2a1 1 0 01-1 1H10a1 1 0 01-1-1v-2zm0 6a1 1 0 011-1h12a1 1 0 011 1v2a1 1 0 01-1 1H10a1 1 0 01-1-1v-2zm1 5a1 1 0 00-1 1v2a1 1 0 001 1h12a1 1 0 001-1v-2a1 1 0 00-1-1H10z"
|
|
||||||
fill={`url(#${id}-gradient)`}
|
|
||||||
/>
|
|
||||||
<rect x={9} y={6} width={14} height={4} rx={1} fill="#171717" />
|
|
||||||
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
|
|
||||||
<defs>
|
|
||||||
<linearGradient
|
|
||||||
id={`${id}-gradient`}
|
|
||||||
x1={16}
|
|
||||||
y1={12}
|
|
||||||
x2={16}
|
|
||||||
y2={28}
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
>
|
|
||||||
<stop stopColor="#737373" />
|
|
||||||
<stop offset={1} stopColor="#737373" stopOpacity={0} />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function DeviceClockIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 32 32" aria-hidden="true" {...props}>
|
|
||||||
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M5 4a4 4 0 014-4h14a4 4 0 014 4v10h-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9a2 2 0 00-2 2v24a2 2 0 002 2h5v2H9a4 4 0 01-4-4V4z"
|
|
||||||
fill="#737373"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M24 32a8 8 0 100-16 8 8 0 000 16zm1-8.414V19h-2v5.414l4 4L28.414 27 25 23.586z"
|
|
||||||
fill="#171717"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function DeviceListIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 32 32" fill="none" aria-hidden="true" {...props}>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M9 0a4 4 0 00-4 4v24a4 4 0 004 4h14a4 4 0 004-4V4a4 4 0 00-4-4H9zm0 2a2 2 0 00-2 2v24a2 2 0 002 2h14a2 2 0 002-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9z"
|
|
||||||
fill="#737373"
|
|
||||||
/>
|
|
||||||
<circle cx={11} cy={14} r={2} fill="#171717" />
|
|
||||||
<circle cx={11} cy={20} r={2} fill="#171717" />
|
|
||||||
<circle cx={11} cy={26} r={2} fill="#171717" />
|
|
||||||
<path
|
|
||||||
d="M16 14h6M16 20h6M16 26h6"
|
|
||||||
stroke="#737373"
|
|
||||||
strokeWidth={2}
|
|
||||||
strokeLinecap="square"
|
|
||||||
/>
|
|
||||||
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function DeviceLockIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 32 32" aria-hidden="true" {...props}>
|
|
||||||
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M5 4a4 4 0 014-4h14a4 4 0 014 4v10h-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9a2 2 0 00-2 2v24a2 2 0 002 2h5v2H9a4 4 0 01-4-4V4z"
|
|
||||||
fill="#737373"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M18 19.5a3.5 3.5 0 117 0V22a2 2 0 012 2v6a2 2 0 01-2 2h-7a2 2 0 01-2-2v-6a2 2 0 012-2v-2.5zm2 2.5h3v-2.5a1.5 1.5 0 00-3 0V22z"
|
|
||||||
fill="#171717"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function DeviceChartIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 32 32" fill="none" aria-hidden="true" {...props}>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M9 0a4 4 0 00-4 4v24a4 4 0 004 4h14a4 4 0 004-4V4a4 4 0 00-4-4H9zm0 2a2 2 0 00-2 2v24a2 2 0 002 2h14a2 2 0 002-2V4a2 2 0 00-2-2h-1.382a1 1 0 00-.894.553l-.448.894a1 1 0 01-.894.553h-6.764a1 1 0 01-.894-.553l-.448-.894A1 1 0 0010.382 2H9z"
|
|
||||||
fill="#737373"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M23 13.838V26a2 2 0 01-2 2H11a2 2 0 01-2-2V15.65l2.57 3.212a1 1 0 001.38.175L15.4 17.2a1 1 0 011.494.353l1.841 3.681c.399.797 1.562.714 1.843-.13L23 13.837z"
|
|
||||||
fill="#171717"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M10 12h12"
|
|
||||||
stroke="#737373"
|
|
||||||
strokeWidth={2}
|
|
||||||
strokeLinecap="square"
|
|
||||||
/>
|
|
||||||
<circle cx={16} cy={16} r={16} fill="#A3A3A3" fillOpacity={0.2} />
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function SecondaryFeatures() {
|
|
||||||
return (
|
|
||||||
<section
|
|
||||||
id="secondary-features"
|
|
||||||
aria-label="Features for building a portfolio"
|
|
||||||
className="py-20 sm:py-32"
|
|
||||||
>
|
|
||||||
<Container>
|
|
||||||
<div className="mx-auto max-w-4xl sm:text-center">
|
|
||||||
<h2 className="text-3xl font-medium tracking-tight text-gray-900">
|
|
||||||
Coming Soon: The Future of Mycelium
|
|
||||||
</h2>
|
|
||||||
<p className="mt-6 text-lg text-gray-600">
|
|
||||||
Mycelium 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>
|
|
||||||
</div>
|
|
||||||
<ul
|
|
||||||
role="list"
|
|
||||||
className="mx-auto mt-16 grid max-w-2xl grid-cols-1 gap-6 text-sm sm:mt-20 sm:grid-cols-2 md:gap-y-10 lg:max-w-none lg:grid-cols-3"
|
|
||||||
>
|
|
||||||
{features.map((feature) => (
|
|
||||||
<li
|
|
||||||
key={feature.name}
|
|
||||||
className="rounded-2xl border border-gray-200 p-8"
|
|
||||||
>
|
|
||||||
<feature.icon className="h-8 w-8" />
|
|
||||||
<h3 className="mt-6 font-semibold text-gray-900">
|
|
||||||
{feature.name}
|
|
||||||
</h3>
|
|
||||||
<p className="mt-2 text-gray-700">{feature.description}</p>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</Container>
|
|
||||||
</section>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
export function LaravelLogo(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 40 40" fill="#fff" aria-hidden="true" {...props}>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M29.982 14.509c.002.005.006.01.007.015a.316.316 0 0 1 .011.082v4.293a.304.304 0 0 1-.043.156.32.32 0 0 1-.119.115l-3.709 2.075v4.112a.305.305 0 0 1-.043.157.32.32 0 0 1-.119.114l-7.742 4.33a.286.286 0 0 1-.056.023l-.022.008a.33.33 0 0 1-.18-.005l-.01-.005c-.018-.006-.036-.011-.053-.021l-7.742-4.33a.32.32 0 0 1-.119-.115.304.304 0 0 1-.043-.156v-12.88a.33.33 0 0 1 .01-.08c.004-.01.01-.018.012-.027l.01-.027a.158.158 0 0 1 .011-.022c.006-.01.015-.018.023-.028.009-.012.017-.025.028-.036.01-.01.02-.016.031-.024.012-.009.023-.019.036-.026l3.871-2.165a.33.33 0 0 1 .322 0l3.872 2.165c.013.007.024.017.036.026l.01.008c.008.005.015.01.021.016a.175.175 0 0 1 .021.025l.008.011.022.028c.008.015.014.032.02.049l.006.01.006.016a.307.307 0 0 1 .01.082v8.044l3.227-1.804v-4.112c0-.028.004-.055.011-.082.003-.01.008-.017.011-.026l.004-.01a.228.228 0 0 1 .017-.039.132.132 0 0 1 .013-.018.203.203 0 0 0 .01-.01c.009-.012.017-.025.028-.036l.015-.013.016-.01.019-.016a.126.126 0 0 1 .017-.011l3.871-2.165a.33.33 0 0 1 .322 0l3.871 2.165c.014.007.024.018.036.026l.012.008.02.016a.162.162 0 0 1 .02.026l.009.01.008.01c.005.006.01.012.013.018a.254.254 0 0 1 .018.04l.003.009.005.01Zm-15.138 8.717 3.22 1.77 7.094-3.933-3.223-1.803-7.091 3.966Zm10.64-2.704v-3.57l-3.226-1.804v3.57l3.225 1.804Zm3.547-5.916-3.225-1.803-3.224 1.803 3.224 1.803 3.225-1.803Zm-14.515.218v7.863l3.226-1.805V13.02l-3.226 1.804Zm2.902-2.346-3.225-1.803-3.224 1.803 3.224 1.803 3.225-1.803Zm-3.547 2.347-3.226-1.805v12.155l7.098 3.97V25.54l-3.708-2.038h-.001l-.002-.002c-.013-.008-.024-.018-.035-.027a.28.28 0 0 0-.011-.007.133.133 0 0 1-.02-.015v-.001l-.019-.022a.452.452 0 0 0-.008-.011l-.016-.02a.086.086 0 0 1-.008-.01v-.002a.123.123 0 0 1-.013-.027l-.005-.012-.008-.016a.115.115 0 0 1-.007-.02.18.18 0 0 1-.005-.033l-.002-.013a.293.293 0 0 0-.002-.013l-.002-.022v-8.405Zm4.516 10.715v3.605l7.096-3.969v-3.572l-7.096 3.935Zm7.742-5.019 3.226-1.804v-3.57l-3.226 1.805v3.57Z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function TupleLogo(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 40 40" fill="#fff" aria-hidden="true" {...props}>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M22.5 8 12 11.692v12l3.5 1.231v3.385L26 32V12.615l-3.5 1.231V8Zm-5.833 17.334 5.833 2.05v-12.24l2.333-.82v15.968l-8.166-2.87v-2.088Z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function TransistorLogo(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 40 40" fill="#fff" aria-hidden="true" {...props}>
|
|
||||||
<path d="M20 32c-6.617 0-12-5.383-12-12S13.383 8 20 8s12 5.383 12 12-5.383 12-12 12Zm0-22.4C14.267 9.6 9.6 14.266 9.6 20S14.267 30.4 20 30.4c5.734 0 10.4-4.666 10.4-10.4S25.734 9.6 20 9.6Z" />
|
|
||||||
<path d="M19.434 27.749c.15.15.354.234.566.235.433 0 .8-.368.8-.8V12.815a.8.8 0 0 0-1.6 0v14.368c0 .212.084.415.234.565ZM12.833 20.8h3.833a.802.802 0 0 0 .802-.8.8.8 0 0 0-.801-.8h-3.834c-.45 0-.8.35-.8.8a.8.8 0 0 0 .8.8ZM23.333 20.8h3.85c.433 0 .783-.35.783-.8a.799.799 0 0 0-.8-.8h-3.833c-.45 0-.8.35-.8.8a.8.8 0 0 0 .8.8Z" />
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function DiageoLogo(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 40 40"
|
|
||||||
fill="#fff"
|
|
||||||
stroke="#fff"
|
|
||||||
strokeWidth="2"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
aria-hidden="true"
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<path d="M22.16 19 26 13H14l3.84 6" fill="none" />
|
|
||||||
<path d="M25 24a5 5 0 1 1-10 0 5 5 0 0 1 10 0Z" />
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function StaticKitLogo(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 40 40" fill="#fff" aria-hidden="true" {...props}>
|
|
||||||
<path d="m26.068 10.555-11.49 13.089L12 21.089 23.489 8l2.58 2.555ZM28 18.91 16.512 32l-2.579-2.555 11.489-13.089L28 18.911Z" />
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function StatamicLogo(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 40 40" fill="#fff" aria-hidden="true" {...props}>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M30.177 27.293c0 1.921-.644 2.707-2.398 2.707H12.22c-1.754 0-2.397-.786-2.397-2.707v-3.741c0-1.805-.837-2.824-1.642-3.291a.385.385 0 0 1-.133-.143.403.403 0 0 1 .133-.526c.837-.551 1.642-1.704 1.642-3.241v-3.677c0-2.072.547-2.674 2.3-2.674h15.754c1.754 0 2.3.602 2.3 2.674v3.675c0 1.537.805 2.69 1.641 3.24.243.168.243.52 0 .67-.804.484-1.64 1.503-1.64 3.29v3.743h-.001Zm-14.739-2.455c1.271 1.152 2.64 1.737 4.522 1.737 2.96 0 4.891-1.537 4.891-4.026 0-2.637-2.3-3.31-4.17-3.856-1.282-.375-2.363-.691-2.363-1.54 0-.551.564-1.086 1.513-1.086.917 0 1.674.2 2.397.584.242.117.467.2.676.2.306 0 .547-.15.756-.45l.29-.451a.955.955 0 0 0 .161-.55c0-.336-.161-.67-.402-.837-.966-.635-2.27-1.17-4.039-1.17-2.51 0-4.44 1.37-4.44 3.826 0 2.746 2.349 3.443 4.23 4h.001c1.255.372 2.3.681 2.3 1.497 0 .785-.707 1.17-1.592 1.17a5.19 5.19 0 0 1-2.992-.92c-.274-.183-.532-.3-.805-.3-.242 0-.451.117-.644.368l-.387.517a.888.888 0 0 0-.192.585c0 .25.08.501.29.702Z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function MirageLogo(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg viewBox="0 0 40 40" fill="#fff" aria-hidden="true" {...props}>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M24.05 9c2.307 0 4.177 1.885 4.177 4.21a4.21 4.21 0 0 1-2.762 3.964l3.366 6.057h2.304c.355 0 .642.29.642.647a.645.645 0 0 1-.642.647H7.142a.645.645 0 0 1-.642-.647c0-.358.288-.647.643-.647h2.304l5.994-10.747a.641.641 0 0 1 1.097-.036l3.444 5.32 1.071-1.627a4.214 4.214 0 0 1-1.178-2.93c0-2.326 1.87-4.211 4.176-4.211Zm-3.304 9.948 2.772 4.283h3.84l-4.317-7.769-2.295 3.486Zm1.239 4.283-5.944-9.183-5.121 9.183h11.065Zm5.038-10.02a2.995 2.995 0 0 1-2.159 2.883l-1.216-2.19a.64.64 0 0 0-1.096-.04l-.811 1.232a3 3 0 0 1-.663-1.885c0-1.655 1.332-2.997 2.973-2.997 1.641 0 2.972 1.341 2.972 2.997Z"
|
|
||||||
/>
|
|
||||||
<path d="M12.069 26.469c-.354 0-.641.289-.641.646 0 .358.287.646.64.646h14.139c.354 0 .641-.29.641-.646a.644.644 0 0 0-.64-.646h-14.14Zm4.928 3.236a.645.645 0 0 0-.642.648c0 .357.288.647.642.647h4.282c.355 0 .643-.29.643-.647a.645.645 0 0 0-.643-.648h-4.282Z" />
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ReversableLogo(props: React.ComponentPropsWithoutRef<'svg'>) {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 40 40"
|
|
||||||
fill="none"
|
|
||||||
stroke="#fff"
|
|
||||||
strokeWidth="2"
|
|
||||||
strokeLinecap="square"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
aria-hidden="true"
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<path d="M15 26v-5.25m0 0V16a2 2 0 0 1 2-2h4.21c.968 0 1.37 1.24.587 1.809L15 20.75Zm0 0L25 26" />
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -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">
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-10 h-full">
|
||||||
|
{/* Left Column */}
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 10 }}
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 10 }}
|
||||||
transition={{ duration: 0.8, delay: 0.1 }}
|
transition={{ duration: 0.8, delay: 0.1 }}
|
||||||
className="mx-auto max-w-2xl lg:max-w-5xl"
|
className="flex flex-col items-start justify-start pt-10 lg:pr-12"
|
||||||
>
|
>
|
||||||
<H2
|
<H2 id="usecases-title" color="light" className="text-left">
|
||||||
id="usecases-title"
|
Augmented Intelligence Fabric
|
||||||
color="primary"
|
|
||||||
className="text-center"
|
|
||||||
>
|
|
||||||
Coming Soon: The Future of Mycelium
|
|
||||||
</H2>
|
</H2>
|
||||||
<P className="mt-6 text-center" color="custom">
|
<P className="mt-4 text-left" 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.
|
The sovereign substrate for autonomous AI.
|
||||||
|
Stateless, geo-aware, end-to-end encrypted—and verifiable from intent to execution.
|
||||||
</P>
|
</P>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Right Columns */}
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0 }}
|
initial={{ opacity: 0 }}
|
||||||
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
||||||
transition={{ duration: 1, delay: 0.2 }}
|
transition={{ duration: 1, delay: 0.2 }}
|
||||||
aria-hidden="true"
|
className="lg:col-span-2 h-full"
|
||||||
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 />
|
<ReviewGrid />
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
import Link from 'next/link'
|
|
||||||
import clsx from 'clsx'
|
|
||||||
|
|
||||||
export function WindowsLink({
|
|
||||||
color = 'black',
|
|
||||||
}: {
|
|
||||||
color?: 'black' | 'white'
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
href="#"
|
|
||||||
aria-label="Download for Windows"
|
|
||||||
className={clsx(
|
|
||||||
'flex items-center rounded-lg transition-colors px-4 py-2',
|
|
||||||
color === 'black'
|
|
||||||
? 'bg-gray-800 text-white hover:bg-gray-900'
|
|
||||||
: 'bg-white text-gray-900 hover:bg-gray-50',
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{/* Windows logo */}
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 88 88"
|
|
||||||
aria-hidden="true"
|
|
||||||
className="h-5 w-5 mr-3"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fill="currentColor"
|
|
||||||
d="M0 12.2L35.6 7v34.2H0V12.2Zm0 63.6L35.6 76V44.8H0v31ZM41.2 6l46.8-6v41.2H41.2V6Zm0 76l46.8 6V46.8H41.2V82Z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
|
|
||||||
{/* Text */}
|
|
||||||
<div className="flex flex-col text-left leading-tight">
|
|
||||||
<span className="text-[9px] mt-0">Download for</span>
|
|
||||||
<span className="text-sm font-semibold -mt-1.5">Windows</span>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
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={45} />;
|
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={45} />;
|
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={45} />;
|
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={45} />;
|
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={45} />;
|
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={45} />;
|
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={45} />;
|
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={45} />;
|
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={45} />;
|
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={45} />;
|
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={45} />;
|
export default () => <OpenAI.Combine size={30} />;
|
||||||
|
|||||||