Compare commits
48 Commits
343b7ae22e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 28bef26fbc | |||
| 73fe0e7c8e | |||
| c59c09eee8 | |||
| 75b660d81e | |||
| 3f86c7e87f | |||
| 1c2c274848 | |||
| 74d5bae622 | |||
| 1577eb6c6c | |||
| f4519ec8bf | |||
| c09928018c | |||
| f5e5063ba1 | |||
| 54333f2bd5 | |||
| e646198255 | |||
| 5f1774f03c | |||
| d52190268a | |||
| 8b2bbb2536 | |||
| 6f8edae241 | |||
| acbbc7445d | |||
| 6c3f1afecf | |||
| 7b5afa588e | |||
| 4cc20ac13f | |||
| 6116c5b87c | |||
| 602b78b5bd | |||
| 9a4f347ee8 | |||
| 017fc41d2b | |||
| ab14a5a8e5 | |||
| 41d4c3a054 | |||
| a362985d4c | |||
| 1d66fd60a4 | |||
| 43d995bbc2 | |||
| 0dedde3592 | |||
| d5b9303d94 | |||
| 3a240177c4 | |||
| 0479b7330a | |||
| a78bc67ed3 | |||
| a035500c34 | |||
| 2b5c502724 | |||
| a462afc8b2 | |||
| bf78cde2d8 | |||
| cde6c90033 | |||
| f5ab743987 | |||
| 45364a7452 | |||
| b7f25d712f | |||
| 2fdcb3697d | |||
| 204625b9a8 | |||
| 02557fcb82 | |||
| 9277bc7105 | |||
| 3f6ffbe4ea |
158
README.md
@@ -1,35 +1,151 @@
|
|||||||
# Mycelium
|
# Project Mycelium Website
|
||||||
|
|
||||||
Mycelium is a [Tailwind Plus](https://tailwindcss.com/plus) site template built using [Tailwind CSS](https://tailwindcss.com) and [Next.js](https://nextjs.org).
|
- **Repository:** [https://git.ourworld.tf/ourworld_web/www_project_mycelium/](https://git.ourworld.tf/ourworld_web/www_project_mycelium/)
|
||||||
|
|
||||||
## Getting started
|
- **Main Branch (Production):** [https://project.mycelium.tf/](https://project.mycelium.tf/)
|
||||||
|
- **Dev Branch (Staging):** [https://www2.project.mycelium.tf/](https://www2.project.mycelium.tf/)
|
||||||
|
|
||||||
To get started with this template, first install the npm dependencies:
|
|
||||||
|
|
||||||
```bash
|
---
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
Next, run the development server:
|
## About
|
||||||
|
|
||||||
```bash
|
This is the official website for Mycelium Cloud, built using Next.js and Tailwind CSS.
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
Finally, open [http://localhost:3000](http://localhost:3000) in your browser to view the website.
|
---
|
||||||
|
|
||||||
## Customizing
|
## Technologies
|
||||||
|
|
||||||
You can start editing this template by modifying the files in the `/src` folder. The site will auto-update as you edit these files.
|
- **Framework**: [Next.js](https://nextjs.org/)
|
||||||
|
- **Language**: [TypeScript](https://www.typescriptlang.org/)
|
||||||
|
- **Styling**: [Tailwind CSS](https://tailwindcss.com/)
|
||||||
|
|
||||||
## License
|
---
|
||||||
|
|
||||||
This site template is a commercial product and is licensed under the [Tailwind Plus license](https://tailwindcss.com/plus/license).
|
## Dependencies
|
||||||
|
|
||||||
## Learn more
|
- **UI**: [@headlessui/react](https://headlessui.com/)
|
||||||
|
- **Animation**: [framer-motion](https://www.framer.com/motion/)
|
||||||
|
- **Utilities**: [clsx](https://github.com/lukeed/clsx), [use-debounce](https://github.com/xnimorz/use-debounce)
|
||||||
|
|
||||||
To learn more about the technologies used in this site template, see the following resources:
|
---
|
||||||
|
|
||||||
- [Tailwind CSS](https://tailwindcss.com/docs) - the official Tailwind CSS documentation
|
## File Structure
|
||||||
- [Next.js](https://nextjs.org/docs) - the official Next.js documentation
|
|
||||||
- [Headless UI](https://headlessui.dev) - the official Headless UI documentation
|
- **Pages**: To edit the content of a specific page, navigate to `src/app/(main)/`.
|
||||||
|
- **Components**: Reusable components are located in `src/components/`.
|
||||||
|
- **Images**: Add or modify images in the `public/images/` directory.
|
||||||
|
- **CSS**: Global styles can be found in `src/styles/tailwind.css`. Most styling is done using Tailwind CSS utility classes directly in the `.tsx` files.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Branding
|
||||||
|
|
||||||
|
- **Font**: The primary font used is [Mulish](https://fonts.google.com/specimen/Mulish).
|
||||||
|
- **Logos**: Project logos are stored in `public/images/logos/`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Get Started
|
||||||
|
|
||||||
|
Follow these steps to get the project running locally:
|
||||||
|
|
||||||
|
1. **Install Dependencies**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Build the Project**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Start the Development Server**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run start
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Development Guide
|
||||||
|
|
||||||
|
This project follows a modular, component-based architecture. Pages are assembled by combining reusable components into a single layout.
|
||||||
|
|
||||||
|
### Homepage Structure
|
||||||
|
|
||||||
|
The homepage (`src/app/(main)/page.tsx`) is composed of the following components:
|
||||||
|
|
||||||
|
- `HomeHero`
|
||||||
|
- `WorldMap`
|
||||||
|
- `StackSectionPreview`
|
||||||
|
- `Steps`
|
||||||
|
- `Companies`
|
||||||
|
- `ClickableGallery`
|
||||||
|
- `BentoReviews`
|
||||||
|
- `CallToAction`
|
||||||
|
|
||||||
|
To edit a specific section of the homepage, navigate to `src/components/` and modify the corresponding component file.
|
||||||
|
|
||||||
|
### Base Layout
|
||||||
|
|
||||||
|
The main layout for the application is defined in `src/components/Layout.tsx`. This file includes the `Header` and `Footer` and wraps the primary content of each page.
|
||||||
|
|
||||||
|
### Creating a New Page
|
||||||
|
|
||||||
|
To create a new page, follow these steps:
|
||||||
|
|
||||||
|
1. **Create a Folder**: Inside the `src/app/(main)/` directory, create a new folder with the desired URL slug for your page (e.g., `new-page`).
|
||||||
|
|
||||||
|
2. **Create the Page File**: Inside the new folder, create a `page.tsx` file.
|
||||||
|
|
||||||
|
3. **Add Page Content**: Compose your page by importing and using the reusable components from `src/components/`. For example:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { HomeHero } from '@/components/HomeHero'
|
||||||
|
import { Faqs } from '@/components/Faqs'
|
||||||
|
|
||||||
|
export default function NewPage() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<HomeHero />
|
||||||
|
<Faqs />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The new page will be accessible at `http://localhost:3000/new-page`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
- **Never update the `main` branch directly.** All changes must be reviewed and merged by the team through a pull request.
|
||||||
|
- **Always work on the `development` branch.** Create a feature branch from `development` and submit your pull request to `development`.
|
||||||
|
- **Request a review.** After submitting your pull request, ask the team to review and accept it into the `main` branch.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Report an Error
|
||||||
|
|
||||||
|
To report an issue, please use the following link and provide the requested information:
|
||||||
|
|
||||||
|
- **Issue Tracker**: [git.ourworld.tf/ourworld_web/HOME/issues/new](https://git.ourworld.tf/ourworld_web/HOME/issues/new) and tag **OW Website & Wiki Project 2025**
|
||||||
|
|
||||||
|
- See the current web rpoject on [OW Website & Wiki Project 2025](https://git.ourworld.tf/ourworld_web/-/projects/153)
|
||||||
|
|
||||||
|
When reporting an issue, please include:
|
||||||
|
|
||||||
|
- **URL**: The page where the error occurred.
|
||||||
|
- **Repo**: The repository you are working with.
|
||||||
|
- **Branch**: The specific branch you are on.
|
||||||
|
- **Problem**: A detailed description of the problem.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Questions
|
||||||
|
|
||||||
|
If you have any questions, you can reach out to [sashaastiadi](https://git.ourworld.tf/sashaastiadi).
|
||||||
|
|||||||
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.
|
||||||
|
|||||||
27
package-lock.json
generated
@@ -11,6 +11,7 @@
|
|||||||
"@headlessui/react": "^2.1.0",
|
"@headlessui/react": "^2.1.0",
|
||||||
"@heroicons/react": "^2.2.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",
|
||||||
@@ -2976,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",
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
"@headlessui/react": "^2.1.0",
|
"@headlessui/react": "^2.1.0",
|
||||||
"@heroicons/react": "^2.2.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",
|
||||||
|
|||||||
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/placeholder.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/videos/agent.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/sandbox.mp4
Normal file
BIN
public/videos/universal.mp4
Normal file
@@ -13,6 +13,7 @@ import { ScrollUp } from '@/components/ui/ScrollUp'
|
|||||||
import { GridStats } from '@/components/GridStats'
|
import { GridStats } from '@/components/GridStats'
|
||||||
import { WorldMap } from '@/components/WorldMap'
|
import { WorldMap } from '@/components/WorldMap'
|
||||||
import { GetStarted } from '@/components/GetStarted'
|
import { GetStarted } from '@/components/GetStarted'
|
||||||
|
import { BentoReviews } from '@/components/BentoReviews'
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
@@ -20,28 +21,25 @@ export default function Home() {
|
|||||||
<section id="home-hero">
|
<section id="home-hero">
|
||||||
<HomeHero />
|
<HomeHero />
|
||||||
</section>
|
</section>
|
||||||
<section id="about">
|
|
||||||
<StackSectionPreview />
|
|
||||||
</section>
|
|
||||||
<section id="network">
|
<section id="network">
|
||||||
<WorldMap />
|
<WorldMap />
|
||||||
</section>
|
</section>
|
||||||
<section id="deploy">
|
<section id="technologies">
|
||||||
|
<StackSectionPreview />
|
||||||
|
</section>
|
||||||
|
<section id="how-it-works">
|
||||||
<Steps />
|
<Steps />
|
||||||
</section>
|
</section>
|
||||||
<section id="llms">
|
<section id="llms">
|
||||||
<Companies />
|
<Companies />
|
||||||
</section>
|
</section>
|
||||||
<section id="features">
|
|
||||||
<UseCases />
|
|
||||||
</section>
|
|
||||||
<section id="clickable-gallery">
|
<section id="clickable-gallery">
|
||||||
<ClickableGallery />
|
<ClickableGallery />
|
||||||
</section>
|
</section>
|
||||||
<section id="get-started">
|
<section id="bento-reviews">
|
||||||
<GetStarted />
|
<BentoReviews />
|
||||||
</section>
|
</section>
|
||||||
<section id="call-to-action">
|
<section id="get-started">
|
||||||
<CallToAction />
|
<CallToAction />
|
||||||
</section>
|
</section>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|
||||||
@@ -26,6 +27,19 @@ export default function RootLayout({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<html lang="en" className={clsx('antialiased', mulish.variable)}>
|
<html lang="en" className={clsx('antialiased', mulish.variable)}>
|
||||||
|
<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>
|
<body className="bg-black text-white">{children}</body>
|
||||||
</html>
|
</html>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export function WorldMap() {
|
|||||||
{/* Top Left Intro Text */}
|
{/* Top Left Intro Text */}
|
||||||
<div className="absolute top-0 left-0 px-6 py-24 z-10 max-w-lg">
|
<div className="absolute top-0 left-0 px-6 py-24 z-10 max-w-lg">
|
||||||
<H4 color="light">Mycelium Network is Live.</H4>
|
<H4 color="light">Mycelium Network is Live.</H4>
|
||||||
<CP className="mt-6 text-base leading-relaxed font-light" color="light">
|
<CP className="hidden mt-6 text-base leading-relaxed font-light" color="light">
|
||||||
Mycelium Cloud's advancement technology enables anyone to deploy
|
Mycelium Cloud's advancement technology enables anyone to deploy
|
||||||
their own Internet infrastructure, anywhere.
|
their own Internet infrastructure, anywhere.
|
||||||
</CP>
|
</CP>
|
||||||
|
|||||||
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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ const variantStyles = {
|
|||||||
},
|
},
|
||||||
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 active:bg-gray-100 active:text-white',
|
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,12 +1,15 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
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 { 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 py-20 sm:py-28"
|
className="relative overflow-hidden py-20 sm:py-28 border-t border-gray-800"
|
||||||
>
|
>
|
||||||
<video
|
<video
|
||||||
autoPlay
|
autoPlay
|
||||||
@@ -18,11 +21,12 @@ export function CallToAction() {
|
|||||||
<source src="/videos/cta.mp4" type="video/mp4" />
|
<source src="/videos/cta.mp4" type="video/mp4" />
|
||||||
</video>
|
</video>
|
||||||
<div className="absolute top-0 left-0 w-full h-full bg-black opacity-40 z-10"></div>
|
<div className="absolute top-0 left-0 w-full h-full bg-black opacity-40 z-10"></div>
|
||||||
<div className="absolute left-20 top-1/2 -translate-y-1/2 sm:left-1/2 sm:-translate-x-1/2 z-20">
|
<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 z-20">
|
<Container className="relative z-20">
|
||||||
<div className="mx-auto max-w-md 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">
|
||||||
Decentralized AI Agents that are Truly Yours
|
Decentralized AI Agents that are Truly Yours
|
||||||
</h2>
|
</h2>
|
||||||
@@ -31,14 +35,25 @@ export function CallToAction() {
|
|||||||
build your own. Ready to own your intelligence?
|
build your own. Ready to own your intelligence?
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-8 flex justify-center gap-x-6">
|
<div className="mt-8 flex justify-center gap-x-6">
|
||||||
<Button variant="solid" color="cyan" href="#">
|
<Button
|
||||||
|
variant="solid"
|
||||||
|
color="cyan"
|
||||||
|
href="https://calendly.com/sachao/30min"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
Book a Meeting
|
Book a Meeting
|
||||||
</Button>
|
</Button>
|
||||||
<Button href="#" variant="outline" color="white">
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
color="white"
|
||||||
|
href="mailto:info@ourworld.tf"
|
||||||
|
>
|
||||||
Join the Waitlist
|
Join the Waitlist
|
||||||
</Button>
|
</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,113 +49,132 @@ export function ClickableGallery() {
|
|||||||
const prev = () => setActive((i) => wrap(0, galleryItems.length, i - 1))
|
const prev = () => setActive((i) => wrap(0, galleryItems.length, i - 1))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref}>
|
<div>
|
||||||
<div className="py-24 relative isolate pt-24 pb-0 bg-black 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 mt-12">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="primary">
|
|
||||||
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>
|
|
||||||
</div>
|
|
||||||
<motion.section
|
|
||||||
initial={{ opacity: 0 }}
|
|
||||||
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
|
||||||
transition={{ duration: 1, delay: 0.4 }}
|
|
||||||
className="relative w-full flex items-center justify-center overflow-hidden bg-black pt-0 pb-32"
|
|
||||||
onMouseEnter={() => setHovering(true)}
|
|
||||||
onMouseLeave={() => setHovering(false)}
|
|
||||||
>
|
|
||||||
|
|
||||||
|
|
||||||
<div className="relative w-full max-w-[1800px] h-[500px]" style={{ perspective: '1600px' }}>
|
|
||||||
<div className="absolute inset-0" style={{ transformStyle: 'preserve-3d' }}>
|
|
||||||
<AnimatePresence initial={false}>
|
|
||||||
{indices.map((idx, i) => {
|
|
||||||
const distance = i - VISIBLE
|
|
||||||
const item = galleryItems[idx]
|
|
||||||
|
|
||||||
const x = distance * GAP
|
|
||||||
const z = -Math.abs(distance) * DEPTH
|
|
||||||
const r = distance * ROT_Y
|
|
||||||
const s = 1 - Math.abs(distance) * SCALE_DROP
|
|
||||||
const o = distance === 0 ? 1 : 0.90
|
|
||||||
const zIndex = 100 - Math.abs(distance)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<motion.div
|
|
||||||
key={`${idx}-${i}`}
|
|
||||||
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 will-change-transform"
|
|
||||||
initial={{ opacity: 0 }}
|
|
||||||
animate={{
|
|
||||||
transform: `translateX(${x}px) translateZ(${z}px) rotateY(${r}deg) scale(${s})`,
|
|
||||||
zIndex,
|
|
||||||
opacity: o,
|
|
||||||
}}
|
|
||||||
exit={{ opacity: 0 }}
|
|
||||||
transition={{ type: 'spring', stiffness: 220, damping: 26 }}
|
|
||||||
onClick={() => setActive(idx)}
|
|
||||||
>
|
|
||||||
{/* Square container, keeps image ratio inside */}
|
|
||||||
<div
|
|
||||||
className="relative rounded-2xl overflow-hidden bg-white flex items-center justify-center"
|
|
||||||
style={{ width: CARD_SIZE, height: CARD_SIZE }}
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
src={item.image}
|
|
||||||
alt={item.text}
|
|
||||||
fill
|
|
||||||
className="object-contain rounded-2xl text-black"
|
|
||||||
priority={i === VISIBLE}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</motion.div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</AnimatePresence>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Arrows */}
|
|
||||||
<div className="absolute inset-y-0 left-8 flex items-center z-50">
|
|
||||||
<button
|
|
||||||
onClick={prev}
|
|
||||||
className="bg-white/70 hover:bg-white rounded-full p-3 shadow-lg backdrop-blur-md"
|
|
||||||
aria-label="Previous"
|
|
||||||
>
|
|
||||||
<svg className="size-8" viewBox="0 0 24 24" fill="none" dangerouslySetInnerHTML={{ __html: '<path d="M15 19L8 12l7-7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>' }} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div className="absolute inset-y-0 right-8 flex items-center z-50">
|
|
||||||
<button
|
|
||||||
onClick={next}
|
|
||||||
className="bg-white/70 hover:bg-white rounded-full p-3 shadow-lg backdrop-blur-md"
|
|
||||||
aria-label="Next"
|
|
||||||
>
|
|
||||||
<svg className="size-8" viewBox="0 0 24 24" fill="none" dangerouslySetInnerHTML={{ __html: '<path d="M9 5l7 7-7 7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>' }} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Foreground pill */}
|
|
||||||
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-[60]">
|
|
||||||
<div className="flex items-center justify-between w-[1040px] gap-6 rounded-3xl bg-white/95 shadow-[0_8px_40px_rgba(0,0,0,0.15)] px-12 py-6 backdrop-blur">
|
|
||||||
<H4 as="h4" className="max-w-[820px] h-[72px] text-black">
|
|
||||||
<TypeAnimation
|
|
||||||
key={active}
|
|
||||||
sequence={[galleryItems[active].text]}
|
|
||||||
wrapper="span"
|
|
||||||
speed={50}
|
|
||||||
repeat={0}
|
|
||||||
/>
|
|
||||||
</H4>
|
|
||||||
<Button href="#" color="cyan" className="text-sm px-4 py-2 lg:text-base">
|
|
||||||
Start
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</FadeIn>
|
||||||
|
<FadeIn transition={{ duration: 0.8, delay: 0.2 }}>
|
||||||
|
<div className="mx-auto max-w-4xl mt-6 lg:px-0 px-4">
|
||||||
|
<P className="text-center" color="primary">
|
||||||
|
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>
|
</div>
|
||||||
</motion.section>
|
<FadeIn transition={{ duration: 1, delay: 0.4 }}>
|
||||||
|
<section
|
||||||
|
className="relative w-full flex items-center justify-center overflow-hidden bg-transparent -mt-8 pt-0 pb-0"
|
||||||
|
onMouseEnter={() => setHovering(true)}
|
||||||
|
onMouseLeave={() => setHovering(false)}
|
||||||
|
>
|
||||||
|
<div className="relative w-full max-w-[1800px] h-[300px] md:h-[500px]" style={{ perspective: '1600px' }}>
|
||||||
|
<div className="absolute inset-0" style={{ transformStyle: 'preserve-3d' }}>
|
||||||
|
<AnimatePresence initial={false}>
|
||||||
|
{indices.map((idx, i) => {
|
||||||
|
const distance = i - VISIBLE;
|
||||||
|
const item = galleryItems[idx];
|
||||||
|
|
||||||
|
const x = distance * GAP;
|
||||||
|
const z = -Math.abs(distance) * DEPTH;
|
||||||
|
const r = distance * ROT_Y;
|
||||||
|
const s = 1 - Math.abs(distance) * SCALE_DROP;
|
||||||
|
const o = distance === 0 ? 1 : 0.80;
|
||||||
|
const zIndex = 100 - Math.abs(distance);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<motion.div
|
||||||
|
key={`${idx}-${i}`}
|
||||||
|
className={`absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 will-change-transform overflow-hidden ${distance === 0 ? 'rounded-xl' : ''}`}
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{
|
||||||
|
transform: `translateX(${x}px) translateZ(${z}px) rotateY(${r}deg) scale(${s})`,
|
||||||
|
zIndex,
|
||||||
|
opacity: o,
|
||||||
|
boxShadow: distance === 0 ? '0 0 20px 5px rgba(255, 255, 255, 0.2)' : 'none',
|
||||||
|
}}
|
||||||
|
exit={{ opacity: 0 }}
|
||||||
|
transition={{ type: 'spring', stiffness: 220, damping: 26 }}
|
||||||
|
onClick={() => setActive(idx)}
|
||||||
|
>
|
||||||
|
<div className="relative bg-black flex items-center justify-center">
|
||||||
|
<Image
|
||||||
|
src={item.image}
|
||||||
|
alt={item.text}
|
||||||
|
width={item.width}
|
||||||
|
height={item.height}
|
||||||
|
className="object-contain text-white"
|
||||||
|
priority={i === VISIBLE}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</AnimatePresence>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Arrows */}
|
||||||
|
{/* Arrows */}
|
||||||
|
<div className="absolute inset-y-0 left-8 hidden md:flex items-center z-50">
|
||||||
|
<button
|
||||||
|
onClick={prev}
|
||||||
|
className="bg-transparent rounded-full p-2 shadow-lg backdrop-blur-md"
|
||||||
|
aria-label="Previous"
|
||||||
|
>
|
||||||
|
<svg className="size-8" viewBox="0 0 24 24" fill="none" dangerouslySetInnerHTML={{ __html: '<path d="M15 19L8 12l7-7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>' }} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="absolute inset-y-0 right-8 hidden md:flex items-center z-50">
|
||||||
|
<button
|
||||||
|
onClick={next}
|
||||||
|
className="bg-transparent rounded-full p-2 shadow-lg backdrop-blur-md"
|
||||||
|
aria-label="Next"
|
||||||
|
>
|
||||||
|
<svg className="size-8" viewBox="0 0 24 24" fill="none" dangerouslySetInnerHTML={{ __html: '<path d="M9 5l7 7-7 7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>' }} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Foreground pill (Desktop) */}
|
||||||
|
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-[60] hidden md:block">
|
||||||
|
<div className="flex items-center justify-between w-[1040px] gap-6 rounded-2xl bg-black/30 shadow-[0_8px_40px_rgba(0,0,0,0.15)] px-12 backdrop-blur">
|
||||||
|
<CT as="h4" className="max-w-[820px] h-[72px] text-white flex items-center">
|
||||||
|
<TypeAnimation
|
||||||
|
key={active}
|
||||||
|
sequence={[galleryItems[active].text]}
|
||||||
|
wrapper="span"
|
||||||
|
speed={50}
|
||||||
|
repeat={0}
|
||||||
|
/>
|
||||||
|
</CT>
|
||||||
|
<Button href="#" color="cyan" className="text-sm px-4 py-2 lg:text-base whitespace-nowrap">
|
||||||
|
Start
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Text box (Mobile) */}
|
||||||
|
<div className="md:hidden w-full px-4 -mt-12 mb-16">
|
||||||
|
<div className="flex flex-row items-center justify-between w-full gap-x-4 rounded-2xl bg-white/10 bg-opacity-80 p-4 backdrop-blur-md">
|
||||||
|
<CT as="h4" className="w-full text-left h-[72px] text-white leading-tight flex items-center">
|
||||||
|
<TypeAnimation
|
||||||
|
key={active}
|
||||||
|
sequence={[galleryItems[active].text]}
|
||||||
|
wrapper="span"
|
||||||
|
speed={50}
|
||||||
|
repeat={0}
|
||||||
|
/>
|
||||||
|
</CT>
|
||||||
|
<Button href="#" color="cyan" className="text-xs px-3 py-1.5 whitespace-nowrap">
|
||||||
|
Start
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</FadeIn>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ const row2 = logos.slice(6);
|
|||||||
|
|
||||||
export function Companies() {
|
export function Companies() {
|
||||||
return (
|
return (
|
||||||
<div id="companies" className="relative bg-black flex flex-col items-center justify-center w-full overflow-hidden antialiased py-12 -top-20">
|
<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">
|
<div className="relative z-10 mx-auto w-full max-w-6xl p-4">
|
||||||
|
|
||||||
{/* Heading */}
|
{/* Heading */}
|
||||||
@@ -50,7 +50,7 @@ export function Companies() {
|
|||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ duration: 1 }}
|
transition={{ duration: 1 }}
|
||||||
>
|
>
|
||||||
<P className="text-gray-100 text-center mb-6">
|
<P className="hidden min-xl:text-gray-100 text-center mb-6">
|
||||||
Mycelium Cloud allows you to deploy and scale AI agents from top global providers on a decentralized, privacy-first infrastructure.
|
Mycelium Cloud allows you to deploy and scale AI agents from top global providers on a decentralized, privacy-first infrastructure.
|
||||||
</P>
|
</P>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|||||||
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>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@@ -24,55 +24,9 @@ export function Footer() {
|
|||||||
return (
|
return (
|
||||||
<footer id="footer" className="border-t border-gray-800">
|
<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-white">
|
© 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-800/50 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-700 transition-colors group-hover:stroke-[#015eff]" />
|
|
||||||
<Image src={qrCode} alt="" unoptimized />
|
|
||||||
</div>
|
|
||||||
<div className="ml-8 lg:w-64">
|
|
||||||
<p className="text-base font-semibold text-white">
|
|
||||||
<Link href="https://threefoldfaq.crisp.help/en/">
|
|
||||||
<span className="absolute inset-0 sm:rounded-2xl" />
|
|
||||||
Talk to a human
|
|
||||||
</Link>
|
|
||||||
</p>
|
|
||||||
<p className="mt-1 text-sm text-gray-400">
|
|
||||||
Get in touch with us for any inquiries or questions.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col items-center border-t border-gray-800 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
|
|
||||||
variant="dark"
|
|
||||||
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-400 md:mt-0">
|
|
||||||
© Copyright ThreeFold {new Date().getFullYear()}. All rights reserved.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -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" color="white">
|
<Button
|
||||||
Docs
|
variant="outline"
|
||||||
|
color="white"
|
||||||
|
href="mailto:info@ourworld.tf"
|
||||||
|
>
|
||||||
|
Join the Waitlist
|
||||||
</Button>
|
</Button>
|
||||||
<Button href="https://www.mycelium.threefold.io/download/" color="cyan">Get Started</Button>
|
<Button href="https://calendly.com/sachao/30min" color="cyan">Book a Meeting</Button>
|
||||||
</div>
|
</div>
|
||||||
</PopoverPanel>
|
</PopoverPanel>
|
||||||
</>
|
</>
|
||||||
@@ -135,10 +127,14 @@ export function Header() {
|
|||||||
)}
|
)}
|
||||||
</Popover>
|
</Popover>
|
||||||
<div className="flex items-center gap-6 max-lg:hidden">
|
<div className="flex items-center gap-6 max-lg:hidden">
|
||||||
<Button href="https://docs.ourworld.tf/mycelium_cloud/docs/" variant="outline">
|
<Button
|
||||||
Docs
|
variant="outline"
|
||||||
|
color="white"
|
||||||
|
href="mailto:info@ourworld.tf"
|
||||||
|
>
|
||||||
|
Join the Waitlist
|
||||||
</Button>
|
</Button>
|
||||||
<Button href="https://www.mycelium.threefold.io/download/" color="cyan">Get Started</Button>
|
<Button href="https://calendly.com/sachao/30min" color="cyan">Book a Meeting</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { motion } from 'framer-motion'
|
|||||||
import { TypeAnimation } from 'react-type-animation'
|
import { TypeAnimation } from 'react-type-animation'
|
||||||
import { Dialog, DialogPanel } from '@headlessui/react'
|
import { Dialog, DialogPanel } from '@headlessui/react'
|
||||||
import { Bars3Icon, XMarkIcon, ChevronDoubleDownIcon } from '@heroicons/react/24/outline'
|
import { Bars3Icon, XMarkIcon, ChevronDoubleDownIcon } from '@heroicons/react/24/outline'
|
||||||
import { H1, PL } from '@/components/Texts'
|
import { H1, H2, PL } from '@/components/Texts'
|
||||||
|
|
||||||
const navigation = [
|
const navigation = [
|
||||||
{ name: 'Product', href: '#' },
|
{ name: 'Product', href: '#' },
|
||||||
@@ -32,29 +32,33 @@ export function HomeHero() {
|
|||||||
<div className="absolute inset-0 bg-black/60" />
|
<div className="absolute inset-0 bg-black/60" />
|
||||||
</div>
|
</div>
|
||||||
<div className="relative px-6 lg:px-8">
|
<div className="relative px-6 lg:px-8">
|
||||||
<div className="relative -top-15 mx-auto max-w-8xl h-screen flex items-center justify-center">
|
<div className="relative mx-auto flex h-screen max-w-8xl items-center justify-center">
|
||||||
<div className="text-center max-w-5xl">
|
<div className="text-center">
|
||||||
<H1 color="light">
|
<div className="max-w-6xl">
|
||||||
<TypeAnimation
|
<H1 color="light">
|
||||||
sequence={[
|
<TypeAnimation
|
||||||
'Decentralized Autonomous Agentic Cloud.',
|
sequence={[
|
||||||
1000,
|
'Decentralized Autonomous Agentic Cloud.',
|
||||||
]}
|
1000,
|
||||||
wrapper="span"
|
]}
|
||||||
speed={50}
|
wrapper="span"
|
||||||
repeat={0}
|
speed={50}
|
||||||
/>
|
repeat={0}
|
||||||
</H1>
|
/>
|
||||||
|
</H1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
transition={{ duration: 1, delay: 1 }}
|
||||||
|
className="mt-12"
|
||||||
|
>
|
||||||
|
<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.
|
||||||
|
</PL>
|
||||||
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
<motion.div
|
|
||||||
initial={{ opacity: 0 }}
|
|
||||||
animate={{ opacity: 1 }}
|
|
||||||
transition={{ duration: 1, delay: 1 }}
|
|
||||||
>
|
|
||||||
<PL className="absolute bottom-0 left-0 max-w-xl text-left text-gray-100" color="light">
|
|
||||||
Mycelium's advancements in Agentic infrastructure supports private, secure and autonomous Agents that connect, learn and grow with you.
|
|
||||||
</PL>
|
|
||||||
</motion.div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
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)
|
||||||
|
|
||||||
@@ -23,17 +24,18 @@ export function NavLinks() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return [
|
return [
|
||||||
['About', '/#about'],
|
['Technologies', '/#technologies'],
|
||||||
['Network', '/#network'],
|
['Network', '/#network'],
|
||||||
['Deploy', '/#deploy'],
|
['How it Works', '/#how-it-works'],
|
||||||
['LLMs', '/#llms'],
|
|
||||||
['Features', '/#features'],
|
|
||||||
['Get Started', '/#get-started'],
|
['Get Started', '/#get-started'],
|
||||||
].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-white transition-colors delay-150 hover:text-gray-300 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)}
|
onClick={(e) => handleClick(e, href)}
|
||||||
onMouseEnter={() => {
|
onMouseEnter={() => {
|
||||||
if (timeoutRef.current) {
|
if (timeoutRef.current) {
|
||||||
|
|||||||
@@ -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 bg-transparent lg:px-0 py-24 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 }}
|
|
||||||
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="light">
|
<P className="mx-auto mt-8 max-w-3xl" color="light">
|
||||||
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,19 +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="relative bg-cover bg-center py-32 -top-20 text-white" style={{ backgroundImage: "url('/images/deployment.webp')" }}>
|
<section id="benefits" ref={ref} className="relative pt-12 pb-4 px-4 lg:px-12 text-white">
|
||||||
<div className="absolute inset-0 bg-black/60" />
|
<div className="relative px-6 lg:px-12">
|
||||||
<div className="relative px-6 lg:px-6">
|
|
||||||
<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" color="light">
|
<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="light">
|
<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>
|
||||||
@@ -50,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
|
||||||
@@ -58,7 +57,7 @@ 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-white/20 bg-black/20 p-8 backdrop-blur-sm transition-all duration-300 ease-in-out hover:scale-105 hover:border-white/40 hover:bg-black/40"
|
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-white" />
|
<feature.icon className="h-8 w-8 mb-4 text-white" />
|
||||||
<CT as="span" className="font-semibold" color="light">{feature.name}</CT>
|
<CT as="span" className="font-semibold" color="light">{feature.name}</CT>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const colorVariants = {
|
|||||||
primary: 'text-[#fffff]',
|
primary: 'text-[#fffff]',
|
||||||
secondary: 'text-gray-200',
|
secondary: 'text-gray-200',
|
||||||
custom: 'text-[#015eff]',
|
custom: 'text-[#015eff]',
|
||||||
light: 'text-white',
|
light: '[#fcfcfc]',
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
type TextOwnProps = {
|
type TextOwnProps = {
|
||||||
@@ -53,9 +53,9 @@ const createTextComponent = <DefaultElement extends React.ElementType>(
|
|||||||
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-3xl font-medium text-pretty lg:text-4xl')
|
export const H2 = createTextComponent('h2', 'text-3xl font-medium text-pretty lg:text-4xl')
|
||||||
export const P = createTextComponent('p', 'text-lg font-normal text-pretty lg:text-xl')
|
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-2xl lg:text-3xl font-medium')
|
export const H3 = createTextComponent('h3', 'text-2xl lg:text-3xl font-medium')
|
||||||
export const H4 = createTextComponent('h4', 'text-xl lg:text-2xl 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-lg 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]')
|
||||||
|
|||||||
@@ -148,11 +148,11 @@ export function UseCases() {
|
|||||||
className="flex flex-col items-start justify-start pt-10 lg:pr-12"
|
className="flex flex-col items-start justify-start pt-10 lg:pr-12"
|
||||||
>
|
>
|
||||||
<H2 id="usecases-title" color="light" className="text-left">
|
<H2 id="usecases-title" color="light" className="text-left">
|
||||||
Mycelium Technologies
|
Augmented Intelligence Fabric
|
||||||
</H2>
|
</H2>
|
||||||
<P className="mt-4 text-left" color="light">
|
<P className="mt-4 text-left" color="light">
|
||||||
A robust infrastructure layer for autonomous AI agents, our technology stack
|
The sovereign substrate for autonomous AI.
|
||||||
delivers a secure, efficient, and intuitive platform for deploying and managing AI agents at scale.
|
Stateless, geo-aware, end-to-end encrypted—and verifiable from intent to execution.
|
||||||
</P>
|
</P>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { CountUpNumber } from './CountUpNumber'
|
|||||||
|
|
||||||
export function WorldMap() {
|
export function WorldMap() {
|
||||||
return (
|
return (
|
||||||
<div className="relative min-h-screen w-full overflow-hidden -top-20 flex flex-col">
|
<div className="relative min-h-screen w-full overflow-hidden top-0 flex py-12 flex-col">
|
||||||
{/* Background video */}
|
{/* Background video */}
|
||||||
<video
|
<video
|
||||||
autoPlay
|
autoPlay
|
||||||
@@ -32,7 +32,7 @@ export function WorldMap() {
|
|||||||
className="max-w-xl"
|
className="max-w-xl"
|
||||||
>
|
>
|
||||||
<H2 color="light">Mycelium Network is Live.</H2>
|
<H2 color="light">Mycelium Network is Live.</H2>
|
||||||
<P className="mt-4 text-base leading-relaxed font-light" color="light">
|
<P className="hidden mt-4 text-base leading-relaxed font-light" color="light">
|
||||||
Mycelium Cloud's advancement technology enables anyone to deploy
|
Mycelium Cloud's advancement technology enables anyone to deploy
|
||||||
their own Internet infrastructure, anywhere.
|
their own Internet infrastructure, anywhere.
|
||||||
</P>
|
</P>
|
||||||
@@ -48,18 +48,18 @@ export function WorldMap() {
|
|||||||
className="flex-1 flex items-center justify-center"
|
className="flex-1 flex items-center justify-center"
|
||||||
>
|
>
|
||||||
<div className="relative w-[450px] h-[450px] md:w-[600px] md:h-[600px]">
|
<div className="relative w-[450px] h-[450px] md:w-[600px] md:h-[600px]">
|
||||||
<Globe className="absolute inset-0 w-full h-full -left-24" />
|
<Globe className="absolute inset-0 w-full h-full left-0 lg:-left-24" />
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Cards Right Column */}
|
{/* Cards Right Column */}
|
||||||
<div className="relative flex-1">
|
<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
|
<motion.div
|
||||||
initial={{ opacity: 0, x: -20 }}
|
initial={{ opacity: 0, x: -20 }}
|
||||||
animate={{ opacity: 1, x: 0 }}
|
animate={{ opacity: 1, x: 0 }}
|
||||||
transition={{ duration: 0.5, delay: 0.4 }}
|
transition={{ duration: 0.5, delay: 0.4 }}
|
||||||
whileHover={{ scale: 1.05 }}
|
whileHover={{ scale: 1.05 }}
|
||||||
className="absolute top-12 -left-12 rounded-2xl bg-white/5 backdrop-blur-md border border-white/10 px-4 py-8 shadow-md w-80"
|
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>
|
<CT color="light" className="uppercase tracking-wide">CORES</CT>
|
||||||
<CountUpNumber end={54958} color="light" className="mt-2 text-3xl font-bold" />
|
<CountUpNumber end={54958} color="light" className="mt-2 text-3xl font-bold" />
|
||||||
@@ -73,7 +73,7 @@ export function WorldMap() {
|
|||||||
animate={{ opacity: 1, x: 0 }}
|
animate={{ opacity: 1, x: 0 }}
|
||||||
transition={{ duration: 0.5, delay: 0.5 }}
|
transition={{ duration: 0.5, delay: 0.5 }}
|
||||||
whileHover={{ scale: 1.05 }}
|
whileHover={{ scale: 1.05 }}
|
||||||
className="absolute -top-10 right-0 rounded-2xl bg-white/5 backdrop-blur-md border border-white/10 px-4 py-8 shadow-md w-80"
|
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>
|
<CT color="light" className="uppercase tracking-wide">NODES</CT>
|
||||||
<CountUpNumber end={1493} color="light" className="mt-2 text-3xl font-bold" />
|
<CountUpNumber end={1493} color="light" className="mt-2 text-3xl font-bold" />
|
||||||
@@ -87,12 +87,12 @@ export function WorldMap() {
|
|||||||
animate={{ opacity: 1, x: 0 }}
|
animate={{ opacity: 1, x: 0 }}
|
||||||
transition={{ duration: 0.5, delay: 0.6 }}
|
transition={{ duration: 0.5, delay: 0.6 }}
|
||||||
whileHover={{ scale: 1.05 }}
|
whileHover={{ scale: 1.05 }}
|
||||||
className="absolute bottom-28 -left-12 rounded-2xl bg-white/5 backdrop-blur-md border border-white/10 px-4 py-8 shadow-md w-80"
|
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>
|
<CT color="light" className="uppercase tracking-wide">SSD CAPACITY</CT>
|
||||||
<CountUpNumber end={5388956} color="light" className="mt-2 text-3xl font-bold" />
|
<CountUpNumber end={5388956} color="light" className="mt-2 text-3xl font-bold" />
|
||||||
<CP color="light" className="mt-2 text-sm">
|
<CP color="light" className="mt-2 text-sm">
|
||||||
Total amount of storage (SSD, HDD, & RAM) on the grid.
|
Total GB amount of storage (SSD, HDD, & RAM) on the grid.
|
||||||
</CP>
|
</CP>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ export function WorldMap() {
|
|||||||
animate={{ opacity: 1, x: 0 }}
|
animate={{ opacity: 1, x: 0 }}
|
||||||
transition={{ duration: 0.5, delay: 0.7 }}
|
transition={{ duration: 0.5, delay: 0.7 }}
|
||||||
whileHover={{ scale: 1.05 }}
|
whileHover={{ scale: 1.05 }}
|
||||||
className="absolute top-44 right-0 rounded-2xl bg-white/5 backdrop-blur-md border border-white/10 px-4 py-8 shadow-md w-80"
|
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>
|
<CT color="light" className="uppercase tracking-wide">COUNTRIES</CT>
|
||||||
<CountUpNumber end={44} color="light" className="mt-2 text-3xl font-bold" />
|
<CountUpNumber end={44} color="light" className="mt-2 text-3xl font-bold" />
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ interface CubeProps {
|
|||||||
index: number;
|
index: number;
|
||||||
onHover: () => void;
|
onHover: () => void;
|
||||||
onLeave: () => void;
|
onLeave: () => void;
|
||||||
|
onClick: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CubeSvg: React.FC<React.SVGProps<SVGSVGElement> & { index: number }> = ({ index, ...props }) => (
|
const CubeSvg: React.FC<React.SVGProps<SVGSVGElement> & { index: number }> = ({ index, ...props }) => (
|
||||||
@@ -42,13 +43,14 @@ const CubeSvg: React.FC<React.SVGProps<SVGSVGElement> & { index: number }> = ({
|
|||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
export function Cube({ title, descriptionTitle, description, isActive, index, onHover, onLeave }: CubeProps) {
|
export function Cube({ title, descriptionTitle, description, isActive, index, onHover, onLeave, onClick }: CubeProps) {
|
||||||
return (
|
return (
|
||||||
<div className="relative flex flex-col items-center">
|
<div className="relative flex flex-col items-center">
|
||||||
<motion.div
|
<motion.div
|
||||||
className="relative cursor-pointer"
|
className="relative cursor-pointer"
|
||||||
onMouseEnter={onHover}
|
onMouseEnter={onHover}
|
||||||
onMouseLeave={onLeave}
|
onMouseLeave={onLeave}
|
||||||
|
onClick={onClick}
|
||||||
style={{
|
style={{
|
||||||
zIndex: 10 - index,
|
zIndex: 10 - index,
|
||||||
}}
|
}}
|
||||||
@@ -123,25 +125,7 @@ export function Cube({ title, descriptionTitle, description, isActive, index, on
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Description for Mobile - Below cube */}
|
{/* Description for Mobile - Below cube */}
|
||||||
{isActive && (
|
</motion.div>
|
||||||
<motion.div
|
|
||||||
initial={{ opacity: 0, y: 10 }}
|
|
||||||
animate={{ opacity: 1, y: 0 }}
|
|
||||||
exit={{ opacity: 0, y: 10 }}
|
|
||||||
transition={{ duration: 0.3 }}
|
|
||||||
className="lg:hidden absolute top-full left-1/2 -translate-x-1/2 mt-8 z-50"
|
|
||||||
>
|
|
||||||
<div className="w-64 sm:w-80 px-4">
|
|
||||||
<h4 className="text-white text-base font-semibold mb-2 text-center">
|
|
||||||
{descriptionTitle}
|
|
||||||
</h4>
|
|
||||||
<p className="text-white text-sm leading-relaxed font-light text-center">
|
|
||||||
{description}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</motion.div>
|
|
||||||
)}
|
|
||||||
</motion.div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,39 +8,47 @@ const stackData = [
|
|||||||
{
|
{
|
||||||
id: "agent",
|
id: "agent",
|
||||||
title: "Agent Layer",
|
title: "Agent Layer",
|
||||||
descriptionTitle: "Personal Agents - Secure & Sovereign",
|
descriptionTitle: "Your sovereign agent with private memory and permissioned data access—always under your control.",
|
||||||
description:
|
description:
|
||||||
"Personal AI agents operate as secure digital twins, providing tailored intelligent assistance. They interact with existing chat, MCP agents, and coding tools while maintaining sovereignty and ecosystem compatibility.",
|
"Choose from a wide library of open-source LLMs, paired with built-in semantic search and retrieval.\nIt coordinates across people, apps, and other agents to plan, create, and execute.\nIt operates inside a compliant legal & financial sandbox, ready for real-world transactions and operations.\nMore than just an assistant—an intelligent partner that learns and does your way.",
|
||||||
position: "top",
|
position: "top",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "ai",
|
id: "network",
|
||||||
title: "AI Layer",
|
title: "Network Layer",
|
||||||
descriptionTitle: "AI Agents & AI Brains + Mycelium Code & Compute Sandboxes",
|
descriptionTitle: "A global, end-to-end encrypted overlay that simply doesn’t break.",
|
||||||
description:
|
description:
|
||||||
"Intelligence core combining LLMs with specialized AI agents. Mycelium-powered sandboxes provide secure environments for development, testing, and compilation with active memory systems and unbreakable network architecture.",
|
"Shortest-path routing moves your traffic the fastest way, every time.\nInstant discovery with integrated DNS, semantic search, and indexing.\nA distributed CDN and edge delivery keep content available and tamper-resistant worldwide.\nBuilt-in tool services and secure coding sandboxes—seamless on phones, desktops, and edge.",
|
||||||
position: "middle",
|
position: "middle",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "cloud",
|
id: "cloud",
|
||||||
title: "Cloud Layer",
|
title: "Cloud Layer",
|
||||||
descriptionTitle: "Mycelium Compute & Storage - Decentralized Infrastructure Layer",
|
descriptionTitle: "An autonomous, stateless OS that enforces pre-deterministic deployments you define.",
|
||||||
description:
|
description:
|
||||||
"Foundation runs bare metal Zero OS enabling autonomous cloud. Decentralized infrastructure supports Web2, Web3, AI workloads with superior scalability. Built on twenty years cloud experience.",
|
"Workloads are cryptographically bound to your private key—location and access are yours.\nNo cloud vendor or middleman in the path: end-to-end ownership and isolation by default.\nGeo-aware placement delivers locality, compliance, and ultra-low latency where it matters.\nEncrypted, erasure-coded storage, decentralized compute and GPU on demand—including LLMs.",
|
||||||
position: "bottom",
|
position: "bottom",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export function StackedCubes() {
|
export function StackedCubes() {
|
||||||
const [active, setActive] = useState<string | null>("agent");
|
const [active, setActive] = useState<string | null>("agent");
|
||||||
|
const [selectedForMobile, setSelectedForMobile] = useState<string | null>("agent");
|
||||||
|
|
||||||
|
const handleCubeClick = (id: string) => {
|
||||||
|
setSelectedForMobile(prev => (prev === id ? null : id));
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectedMobileLayer = stackData.find(layer => layer.id === selectedForMobile);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
<div
|
<div
|
||||||
className="relative w-full flex items-center justify-center lg:justify-start min-h-[600px] sm:min-h-[700px] lg:min-h-[600px]"
|
className="relative w-full flex items-center justify-center lg:justify-center min-h-[450px] lg:min-h-[400px]"
|
||||||
onMouseLeave={() => setActive("agent")}
|
onMouseLeave={() => setActive("agent")}
|
||||||
>
|
>
|
||||||
<motion.div
|
<motion.div
|
||||||
className="relative ml-0 sm:ml-4 lg:ml-8 h-[600px] w-96"
|
className="relative lg:pl-0 pl-6 h-[300px] lg:h-[400px] w-64 sm:w-80 lg:w-96 scale-120 lg:scale-100"
|
||||||
animate={{ y: ["-8px", "8px"] }}
|
animate={{ y: ["-8px", "8px"] }}
|
||||||
transition={{
|
transition={{
|
||||||
duration: 4,
|
duration: 4,
|
||||||
@@ -54,7 +62,7 @@ export function StackedCubes() {
|
|||||||
key={layer.id}
|
key={layer.id}
|
||||||
className="absolute"
|
className="absolute"
|
||||||
style={{
|
style={{
|
||||||
top: `${index * 140}px`,
|
top: `calc(${index * 30}% - ${index * 10}px)`,
|
||||||
zIndex: active === layer.id ? 20 : 10 - index,
|
zIndex: active === layer.id ? 20 : 10 - index,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -66,10 +74,22 @@ export function StackedCubes() {
|
|||||||
index={index}
|
index={index}
|
||||||
onHover={() => setActive(layer.id)}
|
onHover={() => setActive(layer.id)}
|
||||||
onLeave={() => {}}
|
onLeave={() => {}}
|
||||||
|
onClick={() => handleCubeClick(layer.id)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
|
{selectedMobileLayer && (
|
||||||
|
<div className="lg:hidden w-full max-w-md p-6 -mt-8 bg-gray-800/50 rounded-lg">
|
||||||
|
<h4 className="text-white text-lg font-semibold mb-2 text-center">
|
||||||
|
{selectedMobileLayer.descriptionTitle}
|
||||||
|
</h4>
|
||||||
|
<p className="text-gray-300 text-sm leading-relaxed text-center">
|
||||||
|
{selectedMobileLayer.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
79
src/components/ui/bento-grid.tsx
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { CT, CP } from "@/components/Texts";
|
||||||
|
import Image from 'next/image';
|
||||||
|
import React from 'react';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
|
export const BentoGrid = ({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
className?: string;
|
||||||
|
children?: React.ReactNode;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"mx-4 grid max-w-6xl grid-cols-1 gap-4 lg:grid-cols-3",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
interface BentoGridItemProps {
|
||||||
|
className?: string;
|
||||||
|
title?: string | React.ReactNode;
|
||||||
|
subtitle?: string | React.ReactNode;
|
||||||
|
description?: string | React.ReactNode;
|
||||||
|
img?: string;
|
||||||
|
video?: string;
|
||||||
|
rowHeight?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BentoGridItem = React.forwardRef<HTMLDivElement, BentoGridItemProps>(
|
||||||
|
({ className, title, subtitle, description, img, video, rowHeight }, ref) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"group/bento shadow-input row-span-1 flex flex-col justify-between rounded-xl border border-black bg-black/10 backdrop-blur-md transition-all duration-300 ease-in-out hover:scale-105 hover:border-black hover:bg-black/40",
|
||||||
|
rowHeight ? rowHeight : "h-full",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className="relative w-full h-[65%] min-h-[6rem] bg-transparent overflow-hidden">
|
||||||
|
{video ? (
|
||||||
|
<video
|
||||||
|
src={video}
|
||||||
|
autoPlay
|
||||||
|
loop
|
||||||
|
muted
|
||||||
|
playsInline
|
||||||
|
className="w-full h-full object-cover opacity-90 group-hover/bento:opacity-100 transition-opacity duration-300"
|
||||||
|
/>
|
||||||
|
) : img ? (
|
||||||
|
<Image
|
||||||
|
src={img}
|
||||||
|
alt={title as string}
|
||||||
|
width={300}
|
||||||
|
height={300}
|
||||||
|
className="w-full h-full object-cover opacity-90 group-hover/bento:opacity-100 transition-opacity duration-300"
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<div className="p-4 transition bg-white/5 hover:bg-white/7 backdrop-blur-md duration-200 group-hover/bento:translate-x-2 ">
|
||||||
|
<CT>{title}</CT>
|
||||||
|
<CP className="font-medium">{subtitle}</CP>
|
||||||
|
<CP className="mt-2">{description}</CP>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
BentoGridItem.displayName = "BentoGridItem";
|
||||||
|
|
||||||
|
export const MotionBentoGridItem = motion(BentoGridItem);
|
||||||
21
src/hooks/useMediaQuery.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useState, useEffect } from 'react'
|
||||||
|
|
||||||
|
export function useMediaQuery(query: string) {
|
||||||
|
const [matches, setMatches] = useState(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const media = window.matchMedia(query)
|
||||||
|
if (media.matches !== matches) {
|
||||||
|
setMatches(media.matches)
|
||||||
|
}
|
||||||
|
const listener = () => {
|
||||||
|
setMatches(media.matches)
|
||||||
|
}
|
||||||
|
media.addEventListener('change', listener)
|
||||||
|
return () => media.removeEventListener('change', listener)
|
||||||
|
}, [matches, query])
|
||||||
|
|
||||||
|
return matches
|
||||||
|
}
|
||||||
39
src/hooks/useResponsiveCarousel.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
// 🔧 Carousel Config
|
||||||
|
const desktopConfig = {
|
||||||
|
GAP: 300,
|
||||||
|
ROT_Y: 18,
|
||||||
|
DEPTH: 210,
|
||||||
|
SCALE_DROP: 0.12,
|
||||||
|
};
|
||||||
|
|
||||||
|
const mobileConfig = {
|
||||||
|
GAP: 110, // Smaller gap for mobile
|
||||||
|
ROT_Y: 0, // Flatter view on mobile
|
||||||
|
DEPTH: 150, // Less depth
|
||||||
|
SCALE_DROP: 0.1, // Less aggressive scaling
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useResponsiveCarousel = () => {
|
||||||
|
const [config, setConfig] = useState(desktopConfig);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const checkScreenSize = () => {
|
||||||
|
if (window.innerWidth < 768) {
|
||||||
|
setConfig(mobileConfig);
|
||||||
|
} else {
|
||||||
|
setConfig(desktopConfig);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
checkScreenSize();
|
||||||
|
window.addEventListener('resize', checkScreenSize);
|
||||||
|
|
||||||
|
return () => window.removeEventListener('resize', checkScreenSize);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
};
|
||||||
13
src/pages/_document.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { Html, Head, Main, NextScript } from 'next/document'
|
||||||
|
|
||||||
|
export default function Document() {
|
||||||
|
return (
|
||||||
|
<Html lang="en">
|
||||||
|
<Head />
|
||||||
|
<body>
|
||||||
|
<Main />
|
||||||
|
<NextScript />
|
||||||
|
</body>
|
||||||
|
</Html>
|
||||||
|
)
|
||||||
|
}
|
||||||