Compare commits
60 Commits
developmen
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| c68b4e5de9 | |||
| c3b171e3b2 | |||
| ed995113df | |||
| 357b2f58c3 | |||
| 7d8ae1d26d | |||
| 3c4da26ecb | |||
| 023921a6cc | |||
| 8e033a3c21 | |||
| 01b1c20b60 | |||
| c962743737 | |||
| e62c4a5688 | |||
| 6b735b5a40 | |||
| 7b9cf135e4 | |||
| 544d7d541b | |||
| b21f874a05 | |||
| e6b194e8c7 | |||
| a8105a0551 | |||
| de5d990fc9 | |||
| 29d2b76db9 | |||
| a0beec808e | |||
| 96c445aa41 | |||
| ce4b4b3360 | |||
| c849c74a53 | |||
| 7bc895d8be | |||
| c0b84fd578 | |||
| 6d96ff9ea8 | |||
| f1e1721b25 | |||
| aed3e8ed25 | |||
| f126287018 | |||
| 9f1e78e116 | |||
| 97fdf3aa4f | |||
| c1ca5e35f0 | |||
| e5ed88b676 | |||
| 6beb9c1432 | |||
| a9f53224cf | |||
| 3df73ec418 | |||
| c6efc29ab6 | |||
| bec52e7185 | |||
| 29f713cd2f | |||
| d8a7a7331a | |||
| 00c5f7f880 | |||
| 2dbcda4997 | |||
| 979d151537 | |||
| 252e2335c2 | |||
| 9b2c406e9e | |||
| 791216433c | |||
| a4a6c95612 | |||
| da5cf2d4a2 | |||
| d2e2e87a0c | |||
| a8d91a1624 | |||
| f9ee299362 | |||
| 8509b80f47 | |||
| 7d6bbc2763 | |||
| 4cf6f63139 | |||
| ef9865862b | |||
| 503fe26303 | |||
| 39b20f30a4 | |||
| d53f2d943f | |||
| 3213179ff6 | |||
| c289c63856 |
1
google5dd3a8b700455c0e.html
Normal file
@@ -0,0 +1 @@
|
||||
google-site-verification: google5dd3a8b700455c0e.html
|
||||
@@ -4,8 +4,10 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Project Mycelium - Unleash the Power of Decentralized Networks</title>
|
||||
<meta name="description" content="Project Mycelium's technology enables anyone to deploy their own Internet infrastructure, anywhere." />
|
||||
<meta name="google-site-verification" content="rRrZkMEhdC4yFe_BrENEzYmy2bRfD-VE6RTRiDJNLkg" />
|
||||
<title>Project Mycelium - Built for Digital Sovereignty</title>
|
||||
<meta name="description" content="Discover Project Mycelium. A sovereign peer-to-peer network for private communication, storage, and compute. Build and run your digital environment on infrastructure you control." />
|
||||
<meta name="keywords" content="Project Mycelium, Mycelium, digital sovereignty, decentralized network, peer-to-peer infrastructure, private storage, secure compute, sovereign cloud, edge cloud" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Mulish:wght@400;500;700&display=swap" rel="stylesheet" />
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 922 KiB After Width: | Height: | Size: 618 KiB |
|
Before Width: | Height: | Size: 510 KiB After Width: | Height: | Size: 508 KiB |
|
Before Width: | Height: | Size: 988 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 780 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 796 KiB After Width: | Height: | Size: 792 KiB |
|
Before Width: | Height: | Size: 906 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 861 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 774 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
public/images/mainlogo.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
public/images/mobile/agents.jpg
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/images/mobile/cloudpage.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/images/mobile/homepage.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/images/mobile/nodes.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/images/mobile/pods.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 874 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 156 KiB |
@@ -3,9 +3,11 @@ import clsx from 'clsx'
|
||||
|
||||
const baseStyles = {
|
||||
solid:
|
||||
'inline-flex justify-center rounded-full py-2 px-5 text-base font-semibold transition-colors',
|
||||
'inline-flex justify-center rounded-full py-2 px-5 text-sm md:text-base font-semibold transition-colors',
|
||||
outline:
|
||||
'inline-flex justify-center bg-transparent rounded-full border py-[calc(--spacing(2)-1px)] px-[calc(--spacing(5)-1px)] text-base transition-colors',
|
||||
'inline-flex justify-center bg-transparent font-semibold rounded-full border border-2 py-[calc(--spacing(2)-1px)] px-[calc(--spacing(5)-1px)] text-sm md:text-base transition-colors',
|
||||
link:
|
||||
'inline-flex items-center text-sm md:text-base font-semibold transition-colors',
|
||||
}
|
||||
|
||||
const variantStyles = {
|
||||
@@ -18,8 +20,13 @@ const variantStyles = {
|
||||
},
|
||||
outline: {
|
||||
cyan: 'border-cyan-500 text-cyan-500',
|
||||
gray: 'border-gray-300 text-gray-700 hover:border-cyan-500 active:border-cyan-500',
|
||||
white: 'border-gray-300 text-white hover:border-cyan-500 active:border-cyan-500',
|
||||
gray: 'border-gray-200 text-gray-600 hover:text-cyan-500 hover:border-cyan-500 active:border-cyan-500',
|
||||
white: 'border-gray-300 text-white hover:text-cyan-500 hover:border-cyan-500 active:border-cyan-500',
|
||||
},
|
||||
link: {
|
||||
cyan: 'text-cyan-400 underline hover:text-cyan-300',
|
||||
white: 'text-white underline hover:text-cyan-300',
|
||||
dark: 'text-gray-900 underline hover:text-cyan-500',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -30,7 +37,11 @@ type ButtonProps = (
|
||||
}
|
||||
| {
|
||||
variant: 'outline'
|
||||
color?: (keyof typeof variantStyles.outline) | 'cyan'
|
||||
color?: keyof typeof variantStyles.outline
|
||||
}
|
||||
| {
|
||||
variant: 'link'
|
||||
color?: keyof typeof variantStyles.link
|
||||
}
|
||||
) &
|
||||
(
|
||||
@@ -43,15 +54,32 @@ type ButtonProps = (
|
||||
)
|
||||
|
||||
export function Button({ className, as, ...props }: ButtonProps) {
|
||||
props.variant ??= 'solid'
|
||||
props.color ??= 'gray'
|
||||
// Set safe defaults per variant so color always matches a valid palette key
|
||||
if (!props.variant) {
|
||||
props.variant = 'solid'
|
||||
}
|
||||
|
||||
if (!props.color) {
|
||||
if (props.variant === 'solid') {
|
||||
props.color = 'gray'
|
||||
} else if (props.variant === 'outline') {
|
||||
props.color = 'gray'
|
||||
} else if (props.variant === 'link') {
|
||||
props.color = 'cyan'
|
||||
}
|
||||
}
|
||||
|
||||
const variant = props.variant
|
||||
const color = props.color as string
|
||||
|
||||
className = clsx(
|
||||
baseStyles[props.variant],
|
||||
props.variant === 'outline'
|
||||
? variantStyles.outline[props.color]
|
||||
: props.variant === 'solid'
|
||||
? variantStyles.solid[props.color]
|
||||
baseStyles[variant],
|
||||
variant === 'outline'
|
||||
? variantStyles.outline[color as keyof typeof variantStyles.outline]
|
||||
: variant === 'solid'
|
||||
? variantStyles.solid[color as keyof typeof variantStyles.solid]
|
||||
: variant === 'link'
|
||||
? variantStyles.link[color as keyof typeof variantStyles.link]
|
||||
: undefined,
|
||||
className,
|
||||
)
|
||||
|
||||
@@ -8,10 +8,10 @@ export function Footer() {
|
||||
<div className="flex flex-col items-start justify-between gap-y-12 pt-16 pb-6 lg:flex-row lg:items-center lg:py-8">
|
||||
<div>
|
||||
<div className="flex items-center text-gray-900">
|
||||
<img src="/images/logomark.svg" alt="Mycelium Logomark" className="h-15 w-15 flex-none" />
|
||||
<img src="/images/logomark.svg" alt="Mycelium Logomark" className="h-13 w-13 flex-none" />
|
||||
<div className="ml-4">
|
||||
<p className="text-base font-semibold">Project Mycelium</p>
|
||||
<p className="mt-1 text-sm">Unleash the Power of Decentralization</p>
|
||||
<p className="text-base lg:text-lg font-semibold">Project Mycelium</p>
|
||||
<p className="mt-1 text-sm">Built for Digital Sovereignty</p>
|
||||
</div>
|
||||
</div>
|
||||
<nav className="mt-10 flex gap-8">
|
||||
@@ -49,11 +49,11 @@ export function Footer() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col items-center border-t border-gray-100 pt-8 pb-12 md:flex-row-reverse md:justify-between md:pt-6">
|
||||
<div className="flex flex-col items-center border-t border-gray-100 py-8 md:flex-row-reverse md:justify-between md:pt-6">
|
||||
<p className="mt-6 text-sm text-gray-500 md:mt-0">
|
||||
© Copyright{' '}
|
||||
<a href="https://www.threefold.io" target="_blank" rel="noopener noreferrer" className="hover:text-cyan-500 transition-colors">
|
||||
ThreeFold
|
||||
<a href="https://ourworld.tf/" target="_blank" rel="noopener noreferrer" className="font-semibold hover:text-cyan-500 transition-colors">
|
||||
OurWorld
|
||||
</a>{' '}
|
||||
{new Date().getFullYear()}. All rights reserved.
|
||||
</p>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Container } from './Container'
|
||||
import { Button } from './Button'
|
||||
import pmyceliumLogo from '../images/logos/logo_1.png'
|
||||
import pmyceliumLogo from '../images/logos/mainlogo.svg'
|
||||
import { Dialog } from '@headlessui/react'
|
||||
import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline'
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Container } from './Container'
|
||||
import { Button } from './Button'
|
||||
import pmyceliumLogo from '../images/logos/logo_1.png'
|
||||
import pmyceliumLogo from '../images/logos/mainlogo.svg'
|
||||
import { Dialog } from '@headlessui/react'
|
||||
import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline'
|
||||
|
||||
|
||||
@@ -162,5 +162,5 @@ export const DownloadCardDescription = createTextComponent(
|
||||
'text-base/7 leading-normal tracking-normal'
|
||||
)
|
||||
|
||||
export const CT = createTextComponent('span', 'text-base lg:text-lg font-medium')
|
||||
export const CP = createTextComponent('p', 'text-sm lg:text-base tracking-wide leading-tight font-light')
|
||||
export const CT = createTextComponent('span', 'text-base lg:text-lg leading-normal font-medium')
|
||||
export const CP = createTextComponent('p', 'text-sm lg:text-base tracking-wide leading-normal font-light')
|
||||
|
||||
@@ -58,7 +58,10 @@ export const InfiniteMovingCards = ({
|
||||
ref={scrollerRef}
|
||||
className={cn(
|
||||
"flex w-max shrink-0 gap-16 py-4",
|
||||
isReady && "animate-infinite-scroll",
|
||||
isReady &&
|
||||
(direction === "left"
|
||||
? "animate-infinite-scroll"
|
||||
: "animate-infinite-scroll-right"),
|
||||
pauseOnHover && "hover:[animation-play-state:paused]"
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -71,30 +71,27 @@ const clusterNodes = (nodeList: GeoNode[], cellSize = 2) => {
|
||||
function DynamicMapContainer() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [nodes, setNodes] = useState<GeoNode[]>([]);
|
||||
const API_URL = "https://gridproxy.grid.tf/nodes?healthy=true&size=99999";
|
||||
const API_URL = "https://gridproxy.grid.tf/nodes?healthy=true&size=500";
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchNodeData() {
|
||||
try {
|
||||
const response = await fetch(API_URL);
|
||||
const data: RawNode[] = await response.json(); // Type the incoming data
|
||||
const data: RawNode[] = await response.json();
|
||||
|
||||
// 🚨 Map the API response to your component's expected GeoNode format
|
||||
const geoNodes: GeoNode[] = data
|
||||
.filter((node: RawNode) => node.location && node.location.latitude && node.location.longitude)
|
||||
.map((node: RawNode) => ({
|
||||
// Convert string coordinates to numbers
|
||||
lat: parseFloat(node.location.latitude),
|
||||
lng: parseFloat(node.location.longitude),
|
||||
label: `${node.location.city}, ${node.location.country} (${node.node_id})`,
|
||||
// Optionally set color based on some node property if available
|
||||
}));
|
||||
|
||||
const clusteredNodes = clusterNodes(geoNodes);
|
||||
setNodes(clusteredNodes);
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch node data:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
@@ -102,10 +99,8 @@ function DynamicMapContainer() {
|
||||
fetchNodeData();
|
||||
}, []);
|
||||
|
||||
// --- RENDERING ---
|
||||
|
||||
// While fetching, show a loading state
|
||||
if (loading) {
|
||||
// Show a loading state while data is being fetched
|
||||
return (
|
||||
<div className="flex justify-center items-center w-full aspect-[2/1] bg-[#111111] rounded-lg text-cyan-500">
|
||||
<motion.span
|
||||
@@ -120,12 +115,8 @@ function DynamicMapContainer() {
|
||||
);
|
||||
}
|
||||
|
||||
// Pass the dynamically fetched nodes to your WorldMap component
|
||||
return (
|
||||
<WorldMap
|
||||
nodes={nodes}
|
||||
/>
|
||||
);
|
||||
// After data is loaded, render the map
|
||||
return <WorldMap nodes={nodes} />;
|
||||
}
|
||||
|
||||
export default DynamicMapContainer;
|
||||
1
src/images/logos/logomark.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="77" zoomAndPan="magnify" viewBox="0 0 57.75 54" height="72" preserveAspectRatio="xMidYMid meet" version="1.0"><defs><clipPath id="6b820d2194"><path d="M 0.402344 0 L 57.101562 0 L 57.101562 6 L 0.402344 6 Z M 0.402344 0 " clip-rule="nonzero"/></clipPath><clipPath id="3794aac157"><path d="M 0.402344 23 L 57 23 L 57 30 L 0.402344 30 Z M 0.402344 23 " clip-rule="nonzero"/></clipPath><clipPath id="a8068b094c"><path d="M 0.402344 46 L 57.101562 46 L 57.101562 53 L 0.402344 53 Z M 0.402344 46 " clip-rule="nonzero"/></clipPath></defs><g clip-path="url(#6b820d2194)"><path stroke-linecap="butt" transform="matrix(0.736364, 0, 0, 0.736364, 0.402273, 0.00000196364)" fill="none" stroke-linejoin="miter" d="M 0.000096737 3.999805 L 76.537522 3.999805 " stroke="#43d7ff" stroke-width="8" stroke-opacity="1" stroke-miterlimit="4"/></g><g clip-path="url(#3794aac157)"><path fill="#43d7ff" d="M 0.402344 23.136719 L 35.746094 23.136719 L 35.746094 29.027344 L 0.402344 29.027344 M 41.636719 23.136719 L 56.761719 23.136719 L 56.761719 29.027344 L 41.636719 29.027344 " fill-opacity="1" fill-rule="nonzero"/></g><g clip-path="url(#a8068b094c)"><path stroke-linecap="butt" transform="matrix(0.736364, 0, 0, 0.736364, 0.402273, 46.951043)" fill="none" stroke-linejoin="miter" d="M 0.000096737 4.002635 L 76.537522 4.002635 " stroke="#43d7ff" stroke-width="8" stroke-opacity="1" stroke-miterlimit="4"/></g></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
1
src/images/logos/mainlogo.svg
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
@@ -123,7 +123,7 @@ export function AgentBento() {
|
||||
<div className="w-full h-full object-cover"><card.animation /></div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="h-48 w-full flex items-center justify-center bg-transparent" />
|
||||
<div className="hidden md:flex md:h-48 w-full items-center justify-center bg-transparent" />
|
||||
)}
|
||||
|
||||
<div className="px-8 pt-4 pb-6">
|
||||
@@ -136,7 +136,7 @@ export function AgentBento() {
|
||||
) : (
|
||||
<>
|
||||
{/* ✅ NEW SUBTITLE */}
|
||||
<p className="text-sm text-cyan-400">{card.subtitle}</p>
|
||||
<p className="text-sm text-cyan-500">{card.subtitle}</p>
|
||||
|
||||
<p className="mt-1 text-lg font-medium lg:text-xl tracking-tight text-white">
|
||||
{card.title}
|
||||
@@ -161,6 +161,9 @@ export function AgentBento() {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
{/* ✅ Bottom horizontal line with spacing */}
|
||||
<div className="w-full border-b border-gray-800" />
|
||||
<div className="max-w-7xl bg-transparent mx-auto py-6 border border-t-0 border-b-0 border-gray-800"></div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import { Button } from '@/components/Button'
|
||||
import { Eyebrow, H3, P } from '@/components/Texts'
|
||||
|
||||
export function AgentHeroAlt() {
|
||||
@@ -8,28 +7,32 @@ export function AgentHeroAlt() {
|
||||
<div className="">
|
||||
{/* Boxed container */}
|
||||
<div
|
||||
className="relative mx-auto max-w-7xl border border-t-0 border-b-0 border-gray-100 bg-white overflow-hidden bg-contain bg-right bg-no-repeat"
|
||||
style={{ backgroundImage: "url('/images/agents.webp')", backgroundSize: "contain" }}
|
||||
className="relative mx-auto max-w-7xl border border-t-0 border-b-0 border-gray-100 bg-white overflow-hidden md:bg-[url('/images/agents.webp')] md:bg-contain md:bg-right md:bg-no-repeat"
|
||||
>
|
||||
{/* Inner padding */}
|
||||
<div className="px-6 py-16 lg:py-24">
|
||||
<div className="max-w-2xl lg:pl-6">
|
||||
<div className="px-6 pt-4 pb-12 lg:py-24">
|
||||
{/* Mobile-only hero image */}
|
||||
<img
|
||||
src="/images/mobile/agents.jpg"
|
||||
alt="Mycelium Agents visual"
|
||||
className="mb-8 w-full object-cover md:hidden"
|
||||
/>
|
||||
|
||||
<div className="max-w-xl lg:pl-6">
|
||||
<Eyebrow>MYCELIUM AGENTS - COMING IN 2026</Eyebrow>
|
||||
<H3 as="h1" className="mt-4">
|
||||
Private, Sovereign and Distributed AI You Control
|
||||
</H3>
|
||||
<P className="mt-6 text-gray-800">
|
||||
<P className="mt-6 text-gray-600">
|
||||
Mycelium Agents let you deploy and run intelligent systems on your own infrastructure.
|
||||
</P>
|
||||
<P className="mt-4 text-gray-600">
|
||||
Private, local, and autonomous by design, they give you everything you need to build, host, and connect AI agents without relying on centralized clouds.
|
||||
</P>
|
||||
|
||||
<div className="mt-10 flex items-center gap-x-6">
|
||||
<Button href="#" variant="solid" color="cyan">
|
||||
Follow Development
|
||||
</Button>
|
||||
<Button href="#" variant="outline">
|
||||
Explore Docs <span aria-hidden="true">→</span>
|
||||
</Button>
|
||||
{/* TODO: Hero CTAs (Follow Development / Explore Docs) to be added when links are ready.
|
||||
Previously two Buttons here with href="#". */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -36,9 +36,9 @@ export function AgentPro() {
|
||||
<div className="w-full border-t border-l border-r border-gray-100" />
|
||||
|
||||
{/* Intro Block */}
|
||||
<div className="bg-[#FDFDFD] w-full max-w-7xl mx-auto border border-t-0 border-b-0 border-gray-100">
|
||||
<div className="bg-white w-full max-w-7xl mx-auto border border-t-0 border-b-0 border-gray-100">
|
||||
<div className="px-8 py-12 max-w-4xl mx-auto flex flex-col items-center justify-center min-h-[220px] text-center">
|
||||
<Eyebrow className="uppercase tracking-[0.16em] text-cyan-600">
|
||||
<Eyebrow className="text-cyan-500">
|
||||
Advantages
|
||||
</Eyebrow>
|
||||
|
||||
@@ -73,7 +73,7 @@ export function AgentPro() {
|
||||
{item.title}
|
||||
</h3>
|
||||
|
||||
<p className="mt-4 text-sm leading-relaxed text-gray-600">
|
||||
<p className="mt-4 text-base leading-relaxed text-gray-600">
|
||||
{item.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { Eyebrow, SectionHeader, P } from "@/components/Texts";
|
||||
import { Eyebrow, P, CT, CP, H3} from "@/components/Texts";
|
||||
import {
|
||||
CpuChipIcon,
|
||||
GlobeAltIcon,
|
||||
@@ -63,19 +63,18 @@ export function AgentUsecase() {
|
||||
<div className="w-full border-t border-l border-r border-gray-100" />
|
||||
|
||||
{/* Main framed section */}
|
||||
<div className="border border-t-0 border-b-0 border-gray-100 bg-white">
|
||||
<div className="mx-auto max-w-4xl sm:text-center py-12">
|
||||
<div className="max-w-7xl bg-white mx-auto py-12 border border-t-0 border-b-0 border-gray-100">
|
||||
<div className="mx-auto max-w-3xl sm:text-center px-6 lg:px-8">
|
||||
{/* Intro block (from isIntro item) */}
|
||||
{networkUseCases[0].isIntro && (
|
||||
<>
|
||||
<Eyebrow className="text-cyan-600">{networkUseCases[0].eyebrow}</Eyebrow>
|
||||
<SectionHeader
|
||||
as="h3"
|
||||
className="mt-4 text-gray-900 text-3xl lg:text-4xl"
|
||||
<Eyebrow className="text-cyan-500">{networkUseCases[0].eyebrow}</Eyebrow>
|
||||
<H3
|
||||
className="mt-4 text-gray-900"
|
||||
>
|
||||
{networkUseCases[0].title}
|
||||
</SectionHeader>
|
||||
<P className="mt-6 text-lg text-gray-600">
|
||||
</H3>
|
||||
<P className="mt-4 text-lg text-gray-600">
|
||||
{networkUseCases[0].description}
|
||||
</P>
|
||||
</>
|
||||
@@ -85,7 +84,7 @@ export function AgentUsecase() {
|
||||
{/* Grid of features (excluding intro) */}
|
||||
<ul
|
||||
role="list"
|
||||
className="mx-auto mt-6 max-w-6xl grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 md:gap-y-10 px-6 pb-16"
|
||||
className="mx-auto mt-8 max-w-6xl grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 md:gap-y-10 px-6"
|
||||
>
|
||||
{networkUseCases.slice(1).map((item, idx) => (
|
||||
<li
|
||||
@@ -94,20 +93,20 @@ export function AgentUsecase() {
|
||||
>
|
||||
{/* Icon */}
|
||||
{item.icon && (
|
||||
<div className="h-10 w-10 flex items-center justify-center rounded-xl bg-gray-100">
|
||||
<item.icon className="h-6 w-6 text-cyan-600" />
|
||||
<div className="h-10 w-10 mb-2 flex items-center justify-center rounded-xl bg-gray-100">
|
||||
<item.icon className="h-6 w-6 text-cyan-500" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Title */}
|
||||
<p className="mt-6 text-lg font-semibold text-gray-900">
|
||||
<CT className="leading-normal text-gray-900">
|
||||
{item.title}
|
||||
</p>
|
||||
</CT>
|
||||
|
||||
{/* Description */}
|
||||
<p className="mt-2 text-gray-600 text-sm leading-snug">
|
||||
<CP className="mt-2 text-gray-600 text-sm leading-snug">
|
||||
{item.description}
|
||||
</p>
|
||||
</CP>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
@@ -13,7 +13,7 @@ export function CallToAction() {
|
||||
{/* ✅ Main boxed area */}
|
||||
<div
|
||||
id="get-started"
|
||||
className="relative py-18 max-w-7xl mx-auto bg-[#111111] border border-t-0 border-b-0 border-gray-800"
|
||||
className="relative py-18 max-w-7xl mx-auto overflow-hidden bg-[#111111] border border-t-0 border-b-0 border-gray-800"
|
||||
>
|
||||
{/* ✅ Cyan Radial Glow */}
|
||||
<svg
|
||||
@@ -26,7 +26,7 @@ export function CallToAction() {
|
||||
cx={512}
|
||||
cy={512}
|
||||
fill="url(#mycelium-cyan-glow)"
|
||||
fillOpacity="0.2"
|
||||
fillOpacity="0.3"
|
||||
/>
|
||||
<defs>
|
||||
<radialGradient id="mycelium-cyan-glow">
|
||||
@@ -41,38 +41,42 @@ export function CallToAction() {
|
||||
Start with Mycelium Today
|
||||
</h2>
|
||||
|
||||
<p className="mt-6 text-lg text-gray-300">
|
||||
<p className="mt-6 lg:text-lg text-base leading-normal text-gray-300">
|
||||
The Agent Framework launches in H1 2026, but the foundation is ready now.
|
||||
</p>
|
||||
<p className="mt-2 text-lg text-gray-300">
|
||||
<p className="mt-2 lg:text-lg text-base leading-normal text-gray-300">
|
||||
Use today’s components —models, storage, compute, and network— to deploy workloads, connect nodes, and prepare for the next generation of distributed AI.
|
||||
</p>
|
||||
|
||||
{/* ✅ Two cards, stacked center with spacing */}
|
||||
<div className="mt-8 flex flex-wrap justify-center gap-x-10 gap-y-8">
|
||||
<div className="flex flex-col items-center text-center max-w-xs">
|
||||
<Button to="/deploy" variant="solid" color="cyan" className="mt-4">
|
||||
Deploy a Model
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-center text-center max-w-xs">
|
||||
<Button to="/host" as="a" variant="outline" color="white" className="mt-4">
|
||||
Host a Node
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-center text-center max-w-xs">
|
||||
<a
|
||||
href="https://threefold.info/mycelium_network/docs/"
|
||||
{/* ✅ Button row – same structure as homepage CTA */}
|
||||
<div className="mt-10 flex flex-wrap justify-center items-center gap-x-6 gap-y-4">
|
||||
<Button
|
||||
as="a"
|
||||
to="https://myceliumcloud.tf"
|
||||
variant="solid"
|
||||
color="cyan"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Deploy a Model
|
||||
</Button>
|
||||
|
||||
<Button to="/nodes" variant="outline" color="white">
|
||||
Host a Node
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
as="a"
|
||||
to="https://threefold.info/mycelium_network/docs/"
|
||||
variant="link"
|
||||
color="white"
|
||||
className="inline-flex items-center gap-1.5"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="mt-5 font-semibold text-white underline underline-offset-4 decoration-white/70 hover:text-cyan-200 hover:decoration-cyan-200 transition-colors inline-flex items-center gap-1.5"
|
||||
>
|
||||
Follow Development
|
||||
<span aria-hidden="true">→</span>
|
||||
</a>
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useEffect, useMemo, useState } from 'react'
|
||||
import { useResponsiveCarousel } from '@/hooks/useResponsiveCarousel';
|
||||
import { motion, AnimatePresence } from 'framer-motion'
|
||||
import { wrap } from 'popmotion'
|
||||
import { Button } from '@/components/Button';
|
||||
import { SectionHeader, P, Eyebrow, CP } from '@/components/Texts';
|
||||
import { TypeAnimation } from 'react-type-animation'
|
||||
import { FadeIn } from '@/components/FadeIn';
|
||||
@@ -147,9 +146,8 @@ export function GallerySection() {
|
||||
repeat={0}
|
||||
/>
|
||||
</CP>
|
||||
<Button href="#" color="cyan" className="text-sm px-4 py-2 lg:text-base whitespace-nowrap">
|
||||
Start
|
||||
</Button>
|
||||
{/* TODO: Desktop CTA (Start) button to be added when link target is defined.
|
||||
Previously: <Button href="#" color="cyan">Start</Button> */}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -166,9 +164,8 @@ export function GallerySection() {
|
||||
repeat={0}
|
||||
/>
|
||||
</CP>
|
||||
<Button href="#" color="cyan" className="text-xs px-3 py-1.5 whitespace-nowrap">
|
||||
Start
|
||||
</Button>
|
||||
{/* TODO: Mobile CTA (Start) button to be added when link target is defined.
|
||||
Previously: <Button href="#" color="cyan">Start</Button> */}
|
||||
</div>
|
||||
</div>
|
||||
</FadeIn>
|
||||
|
||||
@@ -132,7 +132,7 @@ export default function AgentCoordination({
|
||||
aria-label="Agent coordination and sovereign workflow management"
|
||||
style={{ background: bg }}
|
||||
>
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full" preserveAspectRatio="xMidYMid slice">
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full lg:-translate-y-6" preserveAspectRatio="xMidYMid slice">
|
||||
|
||||
{/* background */}
|
||||
<defs>
|
||||
|
||||
@@ -103,7 +103,7 @@ export default function DeterministicExecution({
|
||||
aria-label="Deterministic deployment and verifiable code execution"
|
||||
style={{ background: bg }}
|
||||
>
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full" preserveAspectRatio="xMidYMid slice">
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full lg:-translate-y-6" preserveAspectRatio="xMidYMid slice">
|
||||
|
||||
{/* background grid */}
|
||||
<defs>
|
||||
|
||||
@@ -126,7 +126,7 @@ export default function FungiStor({
|
||||
aria-label="FungiStor, a distributed long-term AI memory"
|
||||
style={{ background: bg }}
|
||||
>
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full" preserveAspectRatio="xMidYMid slice">
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full lg:-translate-y-16" preserveAspectRatio="xMidYMid slice">
|
||||
{/* Background grid */}
|
||||
<defs>
|
||||
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
||||
|
||||
@@ -178,7 +178,7 @@ export default function Herodb({
|
||||
aria-label="HeroDB, active AI memory retrieval"
|
||||
style={{ background: bg }}
|
||||
>
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full" preserveAspectRatio="xMidYMid slice">
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full lg:-translate-y-18" preserveAspectRatio="xMidYMid slice">
|
||||
{/* Background grid */}
|
||||
<defs>
|
||||
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
||||
|
||||
@@ -124,7 +124,7 @@ export default function MOSSandboxes({
|
||||
aria-label="MOS Secure Agent Sandboxes"
|
||||
style={{ background: bg }}
|
||||
>
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full" preserveAspectRatio="xMidYMid slice">
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full lg:-translate-y-16" preserveAspectRatio="xMidYMid slice">
|
||||
{/* BACKGROUND GRID */}
|
||||
<defs>
|
||||
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
||||
|
||||
@@ -145,7 +145,7 @@ export default function MyceliumMesh({
|
||||
aria-label="Mycelium Mesh, a secure communication network"
|
||||
style={{ background: bg }}
|
||||
>
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full" preserveAspectRatio="xMidYMid slice">
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full lg:-translate-y-4" preserveAspectRatio="xMidYMid slice">
|
||||
{/* Background grid */}
|
||||
<defs>
|
||||
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
||||
|
||||
@@ -13,7 +13,7 @@ export function CallToAction() {
|
||||
{/* ✅ Main boxed area */}
|
||||
<div
|
||||
id="get-started"
|
||||
className="relative py-18 max-w-7xl mx-auto bg-[#111111] border border-t-0 border-b-0 border-gray-800"
|
||||
className="relative py-18 max-w-7xl overflow-hidden mx-auto bg-[#111111] border border-t-0 border-b-0 border-gray-800"
|
||||
>
|
||||
{/* ✅ Cyan Radial Glow */}
|
||||
<svg
|
||||
@@ -26,7 +26,7 @@ export function CallToAction() {
|
||||
cx={512}
|
||||
cy={512}
|
||||
fill="url(#mycelium-cyan-glow)"
|
||||
fillOpacity="0.2"
|
||||
fillOpacity="0.3"
|
||||
/>
|
||||
<defs>
|
||||
<radialGradient id="mycelium-cyan-glow">
|
||||
@@ -52,13 +52,21 @@ export function CallToAction() {
|
||||
{/* ✅ Two cards, stacked center with spacing */}
|
||||
<div className="mt-10 flex flex-wrap justify-center gap-x-10 gap-y-8">
|
||||
<div className="flex flex-col items-center text-center max-w-xs">
|
||||
<Button to="/host" variant="solid" color="cyan" className="mt-4">
|
||||
<Button to="/nodes" variant="solid" color="cyan" className="mt-4">
|
||||
Host a Node
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-center text-center max-w-xs">
|
||||
<Button to="/cloud" variant="outline" color="white" className="mt-4">
|
||||
<Button
|
||||
as="a"
|
||||
to="https://myceliumcloud.tf"
|
||||
variant="outline"
|
||||
color="white"
|
||||
className="mt-4"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Start Deploying
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -40,7 +40,7 @@ export function CloudArchitecture() {
|
||||
<div className="relative mx-auto max-w-7xl border border-t-0 border-b-0 border-gray-800 bg-[#111111] py-12">
|
||||
<Container>
|
||||
<div className="mx-auto max-w-4xl sm:text-center">
|
||||
<Eyebrow className="text-cyan-400">ARCHITECTURE</Eyebrow>
|
||||
<Eyebrow className="">ARCHITECTURE</Eyebrow>
|
||||
|
||||
<H3 className="text-3xl lg:text-4xl font-medium tracking-tight text-white">
|
||||
How Mycelium Cloud Works
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
import { H3, Eyebrow } from "@/components/Texts"
|
||||
import { H3, Eyebrow, P } from "@/components/Texts"
|
||||
import { Button } from "@/components/Button"
|
||||
|
||||
export function CloudHeroNew({ onGetStartedClick = () => {} }: { onGetStartedClick?: () => void }) {
|
||||
export function CloudHeroNew() {
|
||||
return (
|
||||
<div className="">
|
||||
{/* Boxed container */}
|
||||
<div
|
||||
className="relative mx-auto max-w-7xl border border-t-0 border-b-0 border-gray-100 bg-white overflow-hidden bg-contain bg-right bg-no-repeat"
|
||||
style={{ backgroundImage: "url('/images/cloudhero4.webp')", backgroundSize: "contain" }}
|
||||
className="relative mx-auto max-w-7xl border border-t-0 border-b-0 border-gray-100 bg-white overflow-hidden md:bg-[url('/images/cloudhero4.webp')] md:bg-contain md:bg-right md:bg-no-repeat"
|
||||
>
|
||||
{/* Inner padding */}
|
||||
<div className="px-6 py-16 lg:py-24">
|
||||
<div className="px-6 pt-4 pb-12 lg:py-24">
|
||||
{/* Mobile-only hero image */}
|
||||
<img
|
||||
src="/images/mobile/cloudpage.jpg"
|
||||
alt="Mycelium Cloud page visual"
|
||||
className="mb-8 w-full object-cover md:hidden"
|
||||
/>
|
||||
|
||||
<div className="max-w-2xl lg:pl-6">
|
||||
<Eyebrow>
|
||||
MYCELIUM CLOUD
|
||||
@@ -18,30 +24,36 @@ export function CloudHeroNew({ onGetStartedClick = () => {} }: { onGetStartedCli
|
||||
<H3 className="mt-4">
|
||||
Sovereign Edge Cloud Infrastructure
|
||||
</H3>
|
||||
<p className="mt-6 text-lg text-gray-600">
|
||||
<P className="mt-6 text-gray-600">
|
||||
Run compute, storage, and AI resources on infrastructure you control.
|
||||
</p>
|
||||
<p className="mt-2 text-lg text-gray-600">
|
||||
The Mycelium Cloud runs on a distributed grid of independent nodes,
|
||||
delivering secure, scalable performance wherever your users or data live.
|
||||
</p>
|
||||
</P>
|
||||
<div className="mt-10 flex items-center gap-x-6">
|
||||
<Button
|
||||
onClick={onGetStartedClick}
|
||||
as="a"
|
||||
to="https://myceliumcloud.tf"
|
||||
variant="solid"
|
||||
color="cyan"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Deploy Workloads
|
||||
</Button>
|
||||
<Button to="#" variant="outline">
|
||||
<Button
|
||||
as="a"
|
||||
to="https://myceliumcloud.tf/docs"
|
||||
variant="outline"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Explore Docs <span aria-hidden="true">→</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{/* ✅ Bottom horizontal line with spacing */}
|
||||
{/* Bottom horizontal line with spacing */}
|
||||
<div className="w-full border-b border-gray-100" />
|
||||
<div className="max-w-7xl bg-transparent mx-auto py-6 border border-t-0 border-b-0 border-gray-100"></div>
|
||||
</div>
|
||||
|
||||
@@ -79,6 +79,18 @@ export function CloudIntro() {
|
||||
const current = tabs.find((t) => t.id === active)!.content;
|
||||
const currentButtons = tabButtons[active as keyof typeof tabButtons];
|
||||
|
||||
const primaryLinks: Record<string, string | undefined> = {
|
||||
kubernetes: "https://myceliumcloud.tf",
|
||||
vdc: undefined,
|
||||
qsfs: undefined,
|
||||
};
|
||||
|
||||
const secondaryLinks: Record<string, string | undefined> = {
|
||||
kubernetes: "https://myceliumcloud.tf/docs",
|
||||
vdc: "https://threefold.info/mycelium_vdc/docs/",
|
||||
qsfs: undefined,
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="relative w-full bg-[#121212] overflow-hidden">
|
||||
{/* Top Spacing Border */}
|
||||
@@ -95,7 +107,7 @@ export function CloudIntro() {
|
||||
|
||||
<H3 color="white">What You Can Run on Mycelium Cloud</H3>
|
||||
|
||||
<P className="max-w-3xl text-gray-400 mt-6">
|
||||
<P className="max-w-3xl text-gray-200 mt-6">
|
||||
Host nodes, deploy workloads, or build private AI systems all on
|
||||
infrastructure you own and control. Mycelium gives you scalable compute,
|
||||
secure storage, and sovereign orchestration without depending on
|
||||
@@ -126,7 +138,7 @@ export function CloudIntro() {
|
||||
<button
|
||||
key={tab.id}
|
||||
onClick={() => setActive(tab.id)}
|
||||
className={`text-sm font-medium tracking-wide pb-2 ${
|
||||
className={`text-sm font-medium tracking-wide leading-tight pb-2 ${
|
||||
active === tab.id
|
||||
? "border-b-2 border-cyan-500 text-white"
|
||||
: "text-gray-400 hover:text-white"
|
||||
@@ -140,20 +152,20 @@ export function CloudIntro() {
|
||||
{/* Tab Content */}
|
||||
<div className="mt-6 space-y-6">
|
||||
<div>
|
||||
<p className="text-lg font-medium text-white">{current.item}</p>
|
||||
<p className="mt-2 text-base text-gray-400 leading-relaxed">
|
||||
<p className="text-lg lg:text-xl font-medium text-white">{current.item}</p>
|
||||
<p className="mt-2 text-base text-gray-300 leading-relaxed">
|
||||
{current.desc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 space-y-2">
|
||||
<p className="text-sm uppercase tracking-wide text-cyan-400 font-semibold">
|
||||
<p className="text-sm uppercase tracking-wide text-cyan-500 font-semibold">
|
||||
Key capabilities
|
||||
</p>
|
||||
|
||||
<ul className="space-y-2">
|
||||
{current.bullets.map((b, i) => (
|
||||
<li key={i} className="text-base text-gray-300 flex gap-2">
|
||||
<li key={i} className="text-base text-gray-400 flex gap-2">
|
||||
<span className="text-cyan-500">•</span>
|
||||
{b}
|
||||
</li>
|
||||
@@ -164,17 +176,25 @@ export function CloudIntro() {
|
||||
{currentButtons && (
|
||||
<div className="mt-8 flex flex-wrap gap-4">
|
||||
<Button
|
||||
to="#"
|
||||
as={primaryLinks[active] ? "a" : undefined}
|
||||
to={primaryLinks[active] ?? "#"}
|
||||
variant="solid"
|
||||
color="cyan"
|
||||
{...(primaryLinks[active]
|
||||
? { target: "_blank", rel: "noopener noreferrer" }
|
||||
: {})}
|
||||
>
|
||||
{currentButtons.primary}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
to="#"
|
||||
as={secondaryLinks[active] ? "a" : undefined}
|
||||
to={secondaryLinks[active] ?? "#"}
|
||||
variant="outline"
|
||||
color="white"
|
||||
{...(secondaryLinks[active]
|
||||
? { target: "_blank", rel: "noopener noreferrer" }
|
||||
: {})}
|
||||
>
|
||||
{currentButtons.secondary}
|
||||
</Button>
|
||||
|
||||
@@ -35,9 +35,9 @@ export function CloudPros() {
|
||||
<div className="w-full border-t border-l border-r border-gray-100" />
|
||||
|
||||
{/* Intro Block */}
|
||||
<div className="bg-[#FDFDFD] w-full max-w-7xl mx-auto border border-t-0 border-b-0 border-gray-100">
|
||||
<div className="bg-white w-full max-w-7xl mx-auto border border-t-0 border-b-0 border-gray-100">
|
||||
<div className="px-8 py-12 max-w-4xl">
|
||||
<Eyebrow className="uppercase tracking-[0.16em] text-cyan-600">
|
||||
<Eyebrow className="uppercase tracking-[0.16em] text-cyan-500">
|
||||
Cloud Advantages
|
||||
</Eyebrow>
|
||||
|
||||
@@ -72,7 +72,7 @@ export function CloudPros() {
|
||||
{item.title}
|
||||
</h3>
|
||||
|
||||
<p className="mt-4 text-sm leading-relaxed text-gray-600">
|
||||
<p className="mt-4 text-base leading-relaxed text-gray-600">
|
||||
{item.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,7 @@ export function CallToAction() {
|
||||
{/* ✅ Main boxed area */}
|
||||
<div
|
||||
id="get-started"
|
||||
className="relative py-18 max-w-7xl mx-auto bg-[#111111] border border-t-0 border-b-0 border-gray-800"
|
||||
className="relative py-18 max-w-7xl overflow-hidden mx-auto bg-[#111111] border border-t-0 border-b-0 border-gray-800"
|
||||
>
|
||||
{/* ✅ Cyan Radial Glow */}
|
||||
<svg
|
||||
@@ -26,7 +26,7 @@ export function CallToAction() {
|
||||
cx={512}
|
||||
cy={512}
|
||||
fill="url(#mycelium-cyan-glow)"
|
||||
fillOpacity="0.2"
|
||||
fillOpacity="0.3"
|
||||
/>
|
||||
<defs>
|
||||
<radialGradient id="mycelium-cyan-glow">
|
||||
@@ -43,7 +43,7 @@ export function CallToAction() {
|
||||
Choose How You Want to Start
|
||||
</h2>
|
||||
|
||||
<p className="mt-6 text-lg text-gray-300">
|
||||
<p className="mt-6 lg:text-lg text-base leading-normal text-gray-300">
|
||||
Host your own node to contribute capacity or deploy workloads using the Mycelium Cloud.
|
||||
You don’t need to host before deploying, and you don’t need to deploy before hosting.
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import { Container } from '@/components/Container'
|
||||
import { Eyebrow, H3, P } from '@/components/Texts'
|
||||
import { Button } from '@/components/Button'
|
||||
|
||||
const capabilities = [
|
||||
{
|
||||
@@ -48,7 +47,7 @@ export function ComputeCapabilities() {
|
||||
<div className="relative mx-auto max-w-7xl border border-t-0 border-b-0 border-gray-800 bg-[#111111] py-12">
|
||||
<Container>
|
||||
<div className="mx-auto max-w-4xl sm:text-center">
|
||||
<Eyebrow className="text-cyan-400">CAPABILITIES</Eyebrow>
|
||||
<Eyebrow className="text-cyan-500">CAPABILITIES</Eyebrow>
|
||||
<H3 className="text-3xl lg:text-4xl font-medium tracking-tight text-white">
|
||||
What You Can Run
|
||||
</H3>
|
||||
@@ -76,14 +75,8 @@ export function ComputeCapabilities() {
|
||||
</ul>
|
||||
|
||||
{/* Button section */}
|
||||
<div className="mx-auto mt-12 flex justify-center gap-6">
|
||||
<Button variant="solid" color="cyan" href="#">
|
||||
Get Started
|
||||
</Button>
|
||||
<Button variant="outline" color="white" href="#">
|
||||
Explore Docs
|
||||
</Button>
|
||||
</div>
|
||||
{/* TODO: CTA buttons (Get Started / Explore Docs) to be re-enabled when real links are available.
|
||||
Previously rendered here as two Buttons with href="#". */}
|
||||
</Container>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -78,12 +78,8 @@ export function ComputeCapabilitiesNew() {
|
||||
|
||||
{/* Arrows inside first card */}
|
||||
<div className="flex items-center gap-x-4 mt-2">
|
||||
<a
|
||||
href="#"
|
||||
className="inline-flex items-center gap-1 text-cyan-400 hover:text-cyan-300 text-sm font-medium mr-auto"
|
||||
>
|
||||
Learn more →
|
||||
</a>
|
||||
{/* TODO: Intro card CTA (Learn more) to be added here when destination is defined.
|
||||
Previously: <a href="#" className="inline-flex items-center ...">Learn more →</a> */}
|
||||
<button
|
||||
onClick={scrollLeft}
|
||||
className="h-8 w-8 flex items-center justify-center border border-gray-800 rounded-md hover:border-cyan-500 transition-colors"
|
||||
|
||||
@@ -35,9 +35,8 @@ export function ComputeHero({ onGetStartedClick = () => {} }: { onGetStartedClic
|
||||
>
|
||||
Get started
|
||||
</Button>
|
||||
<Button to="#" variant="outline">
|
||||
Documentation <span aria-hidden="true">→</span>
|
||||
</Button>
|
||||
{/* TODO: Secondary CTA (Documentation) link to be wired when docs route is ready.
|
||||
Previously: <Button to="#" variant="outline">Documentation →</Button> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -36,8 +36,12 @@ const features = [
|
||||
|
||||
export function DevHub() {
|
||||
return (
|
||||
<div className="bg-[#121212] py-24 sm:py-32">
|
||||
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
||||
<section className="bg-[#121212] w-full max-w-8xl mx-auto">
|
||||
{/* Top spacing + border */}
|
||||
<div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 border-gray-800" />
|
||||
<div className="w-full border-t border-l border-r border-gray-800" />
|
||||
|
||||
<div className="relative px-6 lg:px-6 py-12 bg-[#111111] border border-t-0 border-b-0 border-gray-800 max-w-7xl mx-auto">
|
||||
<div className="mx-auto grid max-w-2xl grid-cols-1 gap-x-8 gap-y-16 sm:gap-y-20 lg:mx-0 lg:max-w-none lg:grid-cols-5">
|
||||
<div className="col-span-2">
|
||||
<h2 className="mb-2 text-base font-semibold leading-7 text-cyan-500">Get Started</h2>
|
||||
@@ -64,6 +68,10 @@ export function DevHub() {
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom horizontal line with spacing (match NetworkDownload) */}
|
||||
<div className="w-full border-b border-gray-800" />
|
||||
<div className="max-w-7xl bg-transparent mx-auto py-6 border border-t-0 border-b-0 border-gray-800"></div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -40,14 +40,14 @@ const features = [
|
||||
|
||||
export function DownloadHero() {
|
||||
return (
|
||||
<div className="py-16 sm:py-32">
|
||||
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
||||
<section id="download" className="w-full max-w-8xl mx-auto bg-transparent">
|
||||
<div className="mx-auto max-w-7xl px-6 lg:px-8 bg-white pt-24 pb-12 border border-t-0 border-b-0 border-gray-100">
|
||||
<div className="mx-auto max-w-2xl lg:mx-0">
|
||||
<motion.h2
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="text-5xl font-medium tracking-tight text-gray-900 lg:text-6xl"
|
||||
className="text-4xl font-medium tracking-tight text-gray-900 lg:text-5xl"
|
||||
>
|
||||
Download Mycelium Network
|
||||
</motion.h2>
|
||||
@@ -55,7 +55,7 @@ export function DownloadHero() {
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5, delay: 0.2 }}
|
||||
className="mt-6 text-lg text-gray-600 lg:leading-8"
|
||||
className="mt-8 text-lg text-gray-600 lg:leading-8"
|
||||
>
|
||||
Get Mycelium Network for Android, Windows, macOS, and iOS to securely connect, store, and interact with the decentralized network—seamlessly and efficiently. Not sure how it works?{' '}
|
||||
<a
|
||||
@@ -68,8 +68,9 @@ export function DownloadHero() {
|
||||
</a>
|
||||
</motion.p>
|
||||
</div>
|
||||
<div className="mx-auto mt-16 max-w-2xl sm:mt-20 lg:mt-24 lg:max-w-none">
|
||||
<dl className="grid max-w-xl grid-cols-1 gap-x-8 gap-y-16 md:grid-cols-2 lg:max-w-none lg:grid-cols-4">
|
||||
|
||||
<div className="mx-auto mt-8 max-w-2xl lg:mt-12 lg:max-w-none">
|
||||
<dl className="grid max-w-xl grid-cols-1 gap-x-8 lg:gap-y-16 gap-y-8 md:grid-cols-2 lg:max-w-none lg:grid-cols-4">
|
||||
{features.map((feature) => (
|
||||
<div
|
||||
key={feature.name}
|
||||
@@ -99,6 +100,10 @@ export function DownloadHero() {
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom horizontal line with spacing (match NetworkDownload) */}
|
||||
<div className="w-full border-b border-gray-100" />
|
||||
<div className="max-w-7xl bg-transparent mx-auto py-6 border border-t-0 border-b-0 border-gray-100"></div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export function CallToAction() {
|
||||
{/* ✅ Main boxed area */}
|
||||
<div
|
||||
id="get-started"
|
||||
className="relative py-18 max-w-7xl mx-auto bg-[#111111] border border-t-0 border-b-0 border-gray-800"
|
||||
className="relative py-18 max-w-7xl overflow-hidden mx-auto bg-[#111111] border border-t-0 border-b-0 border-gray-800"
|
||||
>
|
||||
{/* ✅ Cyan Radial Glow */}
|
||||
<svg
|
||||
@@ -26,7 +26,7 @@ export function CallToAction() {
|
||||
cx={512}
|
||||
cy={512}
|
||||
fill="url(#mycelium-cyan-glow)"
|
||||
fillOpacity="0.2"
|
||||
fillOpacity="0.3"
|
||||
/>
|
||||
<defs>
|
||||
<radialGradient id="mycelium-cyan-glow">
|
||||
@@ -43,7 +43,7 @@ export function CallToAction() {
|
||||
Choose How You Want to Start
|
||||
</h2>
|
||||
|
||||
<p className="mt-6 text-lg text-gray-300">
|
||||
<p className="mt-6 lg:text-lg text-base leading-normal text-gray-300">
|
||||
Use GPUs through Mycelium Cloud, or contribute GPU nodes to the mesh and run your own workloads.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ export function GpuCapabilities() {
|
||||
<div className="flex items-center gap-x-4 mt-3">
|
||||
<a
|
||||
href="#"
|
||||
className="inline-flex items-center gap-1 text-cyan-400 hover:text-cyan-300 text-sm font-medium mr-auto"
|
||||
className="inline-flex items-center gap-1 text-cyan-500 hover:text-cyan-400 text-sm font-medium mr-auto"
|
||||
>
|
||||
Learn more →
|
||||
</a>
|
||||
|
||||
@@ -42,7 +42,7 @@ export function GpuOverview() {
|
||||
<div className="relative mx-auto max-w-7xl border border-t-0 border-b-0 border-gray-800 bg-[#111111] py-12">
|
||||
<Container>
|
||||
<div className="mx-auto max-w-3xl text-center">
|
||||
<Eyebrow className="text-cyan-400 tracking-[0.32em] uppercase">
|
||||
<Eyebrow className="text-cyan-500 tracking-[0.32em] uppercase">
|
||||
PLATFORM OVERVIEW
|
||||
</Eyebrow>
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Container } from '@/components/Container'
|
||||
import { Button } from '@/components/Button'
|
||||
import { H3, P } from '@/components/Texts'
|
||||
@@ -27,7 +26,7 @@ export function CallToAction() {
|
||||
cx={512}
|
||||
cy={512}
|
||||
fill="url(#mycelium-cyan-glow)"
|
||||
fillOpacity="0.2"
|
||||
fillOpacity="0.3"
|
||||
/>
|
||||
<defs>
|
||||
<radialGradient id="mycelium-cyan-glow">
|
||||
@@ -43,30 +42,33 @@ export function CallToAction() {
|
||||
Use the Mycelium Stack Your Way
|
||||
</H3>
|
||||
|
||||
<P className="mt-6 text-gray-300">
|
||||
<P className="mt-6 lg:text-lg text-base leading-normal text-gray-300">
|
||||
Deploy infrastructure, run workloads, connect environments, and build distributed AI systems, all on one network designed for autonomy and control.
|
||||
</P>
|
||||
|
||||
<P className="mt-4 text-gray-300">
|
||||
<P className="mt-4 lg:text-lg text-base leading-normal text-gray-300">
|
||||
Start wherever you are. Scale on your own terms.
|
||||
</P>
|
||||
|
||||
<div className="mt-10 flex flex-wrap justify-center items-center gap-x-6 gap-y-4">
|
||||
<Button to="/network" variant="solid" color="cyan">
|
||||
<Button to="/network#download" variant="solid" color="cyan">
|
||||
Join the Network
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
to="/cloud"
|
||||
as="a"
|
||||
to="https://myceliumcloud.tf"
|
||||
variant="outline"
|
||||
color="white"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Deploy in Cloud
|
||||
</Button>
|
||||
|
||||
<Link to="/nodes" className="text-cyan-400 hover:text-cyan-300 transition-colors">
|
||||
<Button to="/nodes" variant="link" color="white">
|
||||
Host a Node →
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
|
||||
@@ -24,7 +24,7 @@ const deterministicCards = [
|
||||
title: "No central servers.",
|
||||
description:
|
||||
"Your devices form a distributed network, eliminating reliance on centralized data centers.",
|
||||
animation: <NoCentral className="lg:-mt-12" />, // ✅ NEW
|
||||
animation: <NoCentral />, // ✅ NEW
|
||||
colSpan: "lg:col-span-3",
|
||||
rowSpan: "lg:row-span-1",
|
||||
rounded: "lg:rounded-tr-4xl max-lg:rounded-t-4xl",
|
||||
@@ -35,7 +35,7 @@ const deterministicCards = [
|
||||
title: "No data extraction.",
|
||||
description:
|
||||
"You own your data. Run services and AI models on your own devices, ensuring privacy and control.",
|
||||
animation: <NoExtraction className="lg:-mt-12" />, // ✅ NEW
|
||||
animation: <NoExtraction />, // ✅ NEW
|
||||
colSpan: "lg:col-span-2",
|
||||
rowSpan: "lg:row-span-1",
|
||||
rounded: "lg:rounded-bl-4xl max-lg:rounded-b-4xl",
|
||||
@@ -97,7 +97,7 @@ export function HomeArchitecture() {
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="h-48 w-full flex items-center justify-center bg-transparent" />
|
||||
<div className="h-48 w-full items-center justify-center bg-transparent hidden md:flex" />
|
||||
)}
|
||||
|
||||
<div className="px-8 pt-4 pb-6">
|
||||
|
||||
@@ -1,37 +1,50 @@
|
||||
import { H3, H5, Eyebrow } from "@/components/Texts"
|
||||
import { Button } from "@/components/Button"
|
||||
|
||||
export function HomeAurora({ onGetStartedClick }: { onGetStartedClick: () => void }) {
|
||||
export function HomeAurora() {
|
||||
return (
|
||||
<div className="px-4">
|
||||
{/* Boxed container */}
|
||||
<div
|
||||
className="relative mx-auto max-w-7xl border border-t-0 border-gray-100 bg-white overflow-hidden bg-size-[65%] bg-right bg-no-repeat"
|
||||
style={{ backgroundImage: "url('/images/hero11.webp')" }}
|
||||
className="relative mx-auto max-w-7xl border border-t-0 border-gray-100 bg-white overflow-hidden bg-size-[65%] bg-right bg-no-repeat bg-none md:bg-[url('/images/hero11.webp')]"
|
||||
>
|
||||
{/* Inner padding */}
|
||||
<div className="px-6 py-16 lg:py-32 ">
|
||||
<div className="px-6 pb-12 pt-8 lg:py-32 ">
|
||||
{/* Mobile-only hero image */}
|
||||
<img
|
||||
src="/images/mobile/homepage.jpg"
|
||||
alt="Mycelium homepage visual"
|
||||
className="mb-8 w-full object-cover md:hidden"
|
||||
/>
|
||||
|
||||
<div className="max-w-2xl lg:pl-6">
|
||||
<Eyebrow> Project MYCELIUM</Eyebrow>
|
||||
<H3 className="mt-4">
|
||||
Private, Distributed Infrastructure Built
|
||||
Secure, Distributed Infrastructure Built
|
||||
<br />
|
||||
for Digital Sovereignty
|
||||
</H3>
|
||||
|
||||
<H5 className="mt-4 text-lg text-gray-600 max-w-xl">
|
||||
<H5 className="mt-6 text-lg text-gray-600 max-w-xl">
|
||||
Run your apps, data, and intelligence on infrastructure that belongs to you
|
||||
</H5>
|
||||
|
||||
<div className="mt-8 flex items-center gap-x-6">
|
||||
<Button
|
||||
to="/nodes"
|
||||
variant="solid"
|
||||
color="cyan"
|
||||
onClick={onGetStartedClick}
|
||||
>
|
||||
Start Hosting
|
||||
</Button>
|
||||
<Button to="#" variant="outline">
|
||||
Deploy in Cloud →
|
||||
<Button
|
||||
as="a"
|
||||
to="https://myceliumcloud.tf"
|
||||
variant="outline"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Deploy in Cloud
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -30,14 +30,14 @@ export function HomeDesign() {
|
||||
return (
|
||||
<section className="w-full max-w-8xl mx-auto bg-white">
|
||||
{/* Top spacing line */}
|
||||
<div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 border-gray-200" />
|
||||
<div className="w-full border border-l border-r border-gray-200" />
|
||||
<div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 border-gray-100" />
|
||||
<div className="w-full border border-l border-r border-gray-100" />
|
||||
|
||||
{/* Content */}
|
||||
<div className="mx-auto max-w-7xl border border-t-0 border-b-0 border-gray-200">
|
||||
<div className="mx-auto max-w-7xl border border-t-0 border-b-0 bg-white border-gray-100">
|
||||
{/* Centered intro */}
|
||||
<div className="px-6 pt-12 pb-4 text-center max-w-4xl mx-auto ">
|
||||
<Eyebrow className="uppercase tracking-[0.16em] text-cyan-600">
|
||||
<Eyebrow className="text-cyan-500">
|
||||
Who's it For
|
||||
</Eyebrow>
|
||||
|
||||
@@ -50,11 +50,11 @@ export function HomeDesign() {
|
||||
</P>
|
||||
</div>
|
||||
|
||||
<dl className="grid grid-cols-1 lg:grid-cols-3 gap-4 lg:gap-0">
|
||||
<dl className="grid grid-cols-1 lg:grid-cols-3 gap-2 lg:gap-0">
|
||||
{benefits.map((item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
className="mt-8 group flex items-start gap-2 bg-white px-8 py-12 border border-gray-200 lg:border-t lg:border-b border-l-0.5 border-r-0.5"
|
||||
className="mt-8 group flex items-start gap-2 bg-white px-8 py-12 border border-gray-100 lg:border-t lg:border-b border-l-0.5 border-r-0.5 transition-all duration-300 ease-in-out hover:scale-[1.02] hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20"
|
||||
>
|
||||
{/* Image on the LEFT */}
|
||||
<img
|
||||
|
||||
@@ -67,7 +67,7 @@ export function WorldMap() {
|
||||
>
|
||||
<DarkCard>
|
||||
<div><CT color="light" className="uppercase tracking-wide ">CORES</CT></div>
|
||||
<div><CountUpNumber end={54958} className="mt-2 text-3xl font-bold text-white" /></div>
|
||||
<div><CountUpNumber end={31611} className="mt-2 text-3xl font-bold text-white" /></div>
|
||||
<CP color="light" className="mt-2 text-sm">
|
||||
Total Central Processing Unit Cores available on the grid.
|
||||
</CP>
|
||||
@@ -83,7 +83,7 @@ export function WorldMap() {
|
||||
>
|
||||
<DarkCard>
|
||||
<div><CT color="light" className="uppercase tracking-wide">NODES</CT></div>
|
||||
<div><CountUpNumber end={1493} className="mt-4 text-3xl font-bold text-white" /></div>
|
||||
<div><CountUpNumber end={1153} className="mt-4 text-3xl font-bold text-white" /></div>
|
||||
<CP color="light" className="mt-2 text-sm">
|
||||
Total number of nodes on the grid.
|
||||
</CP>
|
||||
@@ -99,7 +99,7 @@ export function WorldMap() {
|
||||
>
|
||||
<DarkCard>
|
||||
<div><CT color="light" className="uppercase tracking-wide">SSD CAPACITY</CT></div>
|
||||
<div><CountUpNumber end={5388956} className="mt-2 text-3xl font-bold text-white" /></div>
|
||||
<div><CountUpNumber end={4203991} className="mt-2 text-3xl font-bold text-white" /></div>
|
||||
<CP color="light" className="mt-2 text-sm">
|
||||
Total GB amount of storage (SSD, HDD, & RAM) on the grid.
|
||||
</CP>
|
||||
|
||||
@@ -103,7 +103,7 @@ export function HomeMap() {
|
||||
Mycelium runs on nodes hosted by people and organizations around the world.
|
||||
Each node adds compute, storage, and bandwidth, expanding the network’s capacity and resilience.
|
||||
</P>
|
||||
<P className="text-sm md:text-lg text-gray-200 max-w-3xl mx-auto py-4">
|
||||
<P className="text-sm md:text-lg text-gray-200 max-w-3xl mx-auto mt-2 mb-6">
|
||||
You can share your idle resources and earn rewards when they are used.
|
||||
Configure it once. Your node takes over from there.
|
||||
</P>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
|
||||
import { useRef } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { AnimatedSection } from '../../components/AnimatedSection'
|
||||
import { CallToAction } from './CallToAction'
|
||||
import { HomeTab } from './HomeTab'
|
||||
@@ -8,22 +7,60 @@ import { HomeAurora } from './HomeAurora'
|
||||
import { HomeArchitecture } from './HomeArchitecture';
|
||||
import { HomeDesign } from './HomeDesign';
|
||||
|
||||
function LazyHomeMapSection() {
|
||||
const [isVisible, setIsVisible] = useState(false)
|
||||
const containerRef = useRef<HTMLDivElement | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
const el = containerRef.current
|
||||
if (!el || isVisible) return
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
const [entry] = entries
|
||||
if (entry.isIntersecting) {
|
||||
setIsVisible(true)
|
||||
observer.disconnect()
|
||||
}
|
||||
},
|
||||
{
|
||||
root: null,
|
||||
rootMargin: '200px 0px',
|
||||
threshold: 0.1,
|
||||
},
|
||||
)
|
||||
|
||||
observer.observe(el)
|
||||
|
||||
return () => {
|
||||
observer.disconnect()
|
||||
}
|
||||
}, [isVisible])
|
||||
|
||||
return (
|
||||
<div ref={containerRef}>
|
||||
{isVisible ? (
|
||||
<HomeMap />
|
||||
) : (
|
||||
<div className="max-w-7xl mx-auto px-6 py-16 text-center text-gray-400">
|
||||
<p className="text-sm md:text-base">
|
||||
Loading live node map when you scroll here…
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function HomePage() {
|
||||
const sliderRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const handleScrollToSlider = () => {
|
||||
sliderRef.current?.scrollIntoView({ behavior: 'smooth' })
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<AnimatedSection>
|
||||
<HomeAurora onGetStartedClick={handleScrollToSlider} />
|
||||
<HomeAurora />
|
||||
</AnimatedSection>
|
||||
|
||||
<AnimatedSection>
|
||||
<HomeArchitecture/>
|
||||
<HomeArchitecture />
|
||||
</AnimatedSection>
|
||||
|
||||
<AnimatedSection>
|
||||
@@ -31,16 +68,16 @@ export default function HomePage() {
|
||||
</AnimatedSection>
|
||||
|
||||
<AnimatedSection>
|
||||
<HomeMap />
|
||||
<LazyHomeMapSection />
|
||||
</AnimatedSection>
|
||||
|
||||
<AnimatedSection>
|
||||
|
||||
<HomeDesign />
|
||||
</AnimatedSection>
|
||||
|
||||
<AnimatedSection>
|
||||
|
||||
|
||||
<CallToAction />
|
||||
</AnimatedSection>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export function HomeTab() {
|
||||
<section className="w-full max-w-8xl mx-auto bg-transparent">
|
||||
|
||||
{/* Top section separators */}
|
||||
<div className="max-w-7xl mx-auto py-6 border-x border-gray-100 bg-white border-t-0 border-b-0" />
|
||||
<div className="max-w-7xl mx-auto py-6 border-x border-gray-100 border-t-0 border-b-0" />
|
||||
<div className="w-full border-t border-l border-r border-gray-100" />
|
||||
|
||||
{/* Main content */}
|
||||
@@ -24,9 +24,9 @@ export function HomeTab() {
|
||||
<div className="mt-10 grid gap-4 sm:mt-16 lg:grid-cols-3 lg:grid-rows-2 pb-12">
|
||||
|
||||
{/* ------------------ LEFT TALL CARD ------------------ */}
|
||||
<Link to="/network" className="relative lg:row-span-2 cursor-pointer">
|
||||
<Link to="/network" className="relative lg:row-span-2 cursor-pointer transition-transform duration-300 ease-in-out hover:scale-105">
|
||||
<div className="absolute inset-px rounded-lg bg-white lg:rounded-l-4xl" />
|
||||
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] lg:rounded-l-[calc(2rem+1px)] transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20">
|
||||
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] lg:rounded-l-[calc(2rem+1px)]">
|
||||
|
||||
<div className="px-8 pt-8 pb-3 sm:px-10 sm:pt-10 sm:pb-0">
|
||||
<h3 className="text-sm/4 font-semibold text-cyan-500">LIVE</h3>
|
||||
@@ -50,13 +50,13 @@ export function HomeTab() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="pointer-events-none absolute inset-px rounded-lg shadow-sm outline outline-black/5 lg:rounded-l-4xl" />
|
||||
<div className="pointer-events-none absolute inset-px rounded-lg border border-transparent shadow-sm outline outline-black/5 lg:rounded-l-4xl hover:border-cyan-500" />
|
||||
</Link>
|
||||
|
||||
{/* ------------------ MIDDLE TOP ------------------ */}
|
||||
<Link to="/pods" className="relative cursor-pointer max-lg:row-start-1">
|
||||
<Link to="/pods" className="relative cursor-pointer max-lg:row-start-1 transition-transform duration-300 ease-in-out hover:scale-105">
|
||||
<div className="absolute inset-px rounded-lg bg-white max-lg:rounded-t-4xl" />
|
||||
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] max-lg:rounded-t-[calc(2rem+1px)] transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20">
|
||||
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] max-lg:rounded-t-[calc(2rem+1px)]">
|
||||
|
||||
<div className="px-8 pt-8 sm:px-10 sm:pt-10">
|
||||
<h3 className="text-sm/4 font-semibold text-cyan-500">Coming Soon</h3>
|
||||
@@ -75,13 +75,13 @@ export function HomeTab() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="pointer-events-none absolute inset-px rounded-lg shadow-sm outline outline-black/5 max-lg:rounded-t-4xl" />
|
||||
<div className="pointer-events-none absolute inset-px rounded-lg border border-transparent shadow-sm outline outline-black/5 max-lg:rounded-t-4xl hover:border-cyan-500" />
|
||||
</Link>
|
||||
|
||||
{/* ------------------ MIDDLE BOTTOM ------------------ */}
|
||||
<Link to="/agents" className="relative cursor-pointer max-lg:row-start-3 lg:col-start-2 lg:row-start-2">
|
||||
<Link to="/agents" className="relative cursor-pointer max-lg:row-start-3 lg:col-start-2 lg:row-start-2 transition-transform duration-300 ease-in-out hover:scale-105">
|
||||
<div className="absolute inset-px rounded-lg bg-white" />
|
||||
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20">
|
||||
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)]">
|
||||
|
||||
<div className="px-8 pt-8 sm:px-10 sm:pt-10">
|
||||
<h3 className="text-sm/4 font-semibold text-cyan-500">Q1 2026</h3>
|
||||
@@ -99,13 +99,13 @@ export function HomeTab() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="pointer-events-none absolute inset-px rounded-lg shadow-sm outline outline-black/5" />
|
||||
<div className="pointer-events-none absolute inset-px rounded-lg border border-transparent shadow-sm outline outline-black/5 hover:border-cyan-500" />
|
||||
</Link>
|
||||
|
||||
{/* ------------------ RIGHT TALL ------------------ */}
|
||||
<Link to="/cloud" className="relative lg:row-span-2 cursor-pointer">
|
||||
<Link to="/cloud" className="relative lg:row-span-2 cursor-pointer transition-transform duration-300 ease-in-out hover:scale-105">
|
||||
<div className="absolute inset-px rounded-lg bg-white max-lg:rounded-b-4xl lg:rounded-r-4xl" />
|
||||
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] max-lg:rounded-b-[calc(2rem+1px)] lg:rounded-r-[calc(2rem+1px)] transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20">
|
||||
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] max-lg:rounded-b-[calc(2rem+1px)] lg:rounded-r-[calc(2rem+1px)]">
|
||||
|
||||
<div className="px-8 pt-8 pb-3 sm:px-10 sm:pt-10 sm:pb-0">
|
||||
<h3 className="text-sm/4 font-semibold text-cyan-500">Early Access</h3>
|
||||
@@ -126,7 +126,7 @@ export function HomeTab() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="pointer-events-none absolute inset-px rounded-lg shadow-sm outline outline-black/5 max-lg:rounded-b-4xl lg:rounded-r-4xl" />
|
||||
<div className="pointer-events-none absolute inset-px rounded-lg border border-transparent shadow-sm outline outline-black/5 max-lg:rounded-b-4xl lg:rounded-r-4xl hover:border-cyan-500" />
|
||||
</Link>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -131,7 +131,7 @@ export default function NoCentral({
|
||||
aria-label="Distributed network illustration"
|
||||
style={{ background: bg }}
|
||||
>
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full">
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full lg:-translate-y-10">
|
||||
{/* Background grid */}
|
||||
<defs>
|
||||
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
||||
@@ -210,13 +210,13 @@ export default function NoCentral({
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* Faded red “no central” mark at middle */}
|
||||
{/* Faded grey “no central” mark at middle */}
|
||||
<motion.circle
|
||||
cx={center.x}
|
||||
cy={center.y}
|
||||
r={18}
|
||||
fill="none"
|
||||
stroke="#FF4D4D"
|
||||
stroke="#8B8B8B"
|
||||
strokeWidth={3}
|
||||
strokeDasharray="6 4"
|
||||
initial={{ scale: 0, opacity: 0 }}
|
||||
@@ -225,7 +225,7 @@ export default function NoCentral({
|
||||
/>
|
||||
<motion.path
|
||||
d={`M ${center.x - 10} ${center.y - 10} L ${center.x + 10} ${center.y + 10} M ${center.x - 10} ${center.y + 10} L ${center.x + 10} ${center.y - 10}`}
|
||||
stroke="#FF4D4D"
|
||||
stroke="#8B8B8B"
|
||||
strokeWidth={3}
|
||||
strokeLinecap="round"
|
||||
initial={{ opacity: 0, scale: 0 }}
|
||||
|
||||
@@ -162,7 +162,7 @@ export default function NoControl({
|
||||
{/* Cross mark over center node (control denied) */}
|
||||
<motion.path
|
||||
d={`M ${center.x - 12} ${center.y - 12} L ${center.x + 12} ${center.y + 12} M ${center.x - 12} ${center.y + 12} L ${center.x + 12} ${center.y - 12}`}
|
||||
stroke="#FF4D4D"
|
||||
stroke="#8B8B8B"
|
||||
strokeWidth={3}
|
||||
strokeLinecap="round"
|
||||
initial={{ opacity: 0, scale: 0 }}
|
||||
|
||||
@@ -230,7 +230,7 @@ export default function NoExtraction({
|
||||
cx={center.x + 130}
|
||||
cy={center.y - 10}
|
||||
r={10}
|
||||
fill="#FF4D4D"
|
||||
fill="#8B8B8B"
|
||||
initial={{ scale: 0, opacity: 0 }}
|
||||
animate={{ scale: [0, 1.2, 0.8], opacity: [0, 1, 0] }}
|
||||
transition={{
|
||||
|
||||
@@ -10,8 +10,8 @@ type Props = {
|
||||
gridStroke?: string;
|
||||
};
|
||||
|
||||
const W = 720; // 4:3
|
||||
const H = 540; // 4:3
|
||||
const W = 760; // match aspect ratio closer to other home animations
|
||||
const H = 420; // align visual height with other cards
|
||||
|
||||
export default function NoSinglePoint({
|
||||
className,
|
||||
|
||||
@@ -19,7 +19,14 @@ export function HomeHero() {
|
||||
Start Hosting
|
||||
</Button>
|
||||
|
||||
<Button href="#" variant="outline" color="white">
|
||||
<Button
|
||||
as="a"
|
||||
to="https://myceliumcloud.tf"
|
||||
variant="outline"
|
||||
color="white"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Deploy in Cloud <span aria-hidden="true">→</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -39,8 +39,14 @@ export function HomeAurora({ onGetStartedClick }: { onGetStartedClick: () => voi
|
||||
>
|
||||
Start Hosting
|
||||
</Button>
|
||||
<Button to="#" variant="outline">
|
||||
Deploy in Cloud →
|
||||
<Button
|
||||
as="a"
|
||||
to="https://myceliumcloud.tf"
|
||||
variant="outline"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Deploy in Cloud
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Container } from '@/components/Container'
|
||||
import { Button } from "@/components/Button";
|
||||
|
||||
@@ -14,7 +13,7 @@ export function CallToAction() {
|
||||
{/* ✅ Main boxed area */}
|
||||
<div
|
||||
id="get-started"
|
||||
className="relative py-18 max-w-7xl mx-auto bg-[#111111] border border-t-0 border-b-0 border-gray-800"
|
||||
className="relative py-18 max-w-7xl mx-auto overflow-hidden bg-[#111111] border border-t-0 border-b-0 border-gray-800"
|
||||
>
|
||||
{/* ✅ Cyan Radial Glow */}
|
||||
<svg
|
||||
@@ -27,7 +26,7 @@ export function CallToAction() {
|
||||
cx={512}
|
||||
cy={512}
|
||||
fill="url(#mycelium-cyan-glow)"
|
||||
fillOpacity="0.2"
|
||||
fillOpacity="0.3"
|
||||
/>
|
||||
<defs>
|
||||
<radialGradient id="mycelium-cyan-glow">
|
||||
@@ -44,7 +43,7 @@ export function CallToAction() {
|
||||
Choose How You Want to Connect
|
||||
</h2>
|
||||
|
||||
<p className="mt-6 text-lg text-gray-300">
|
||||
<p className="mt-6 lg:text-lg text-base leading-normal text-gray-300">
|
||||
Choose How You Want to Connect
|
||||
Use the network to link environments, deploy workloads, or host nodes to strengthen the mesh and run on your own hardware.
|
||||
</p>
|
||||
@@ -56,16 +55,19 @@ Use the network to link environments, deploy workloads, or host nodes to strengt
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
to="/cloud"
|
||||
as="a"
|
||||
to="https://myceliumcloud.tf"
|
||||
variant="outline"
|
||||
color="white"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Deploy in Cloud
|
||||
</Button>
|
||||
|
||||
<Link to="/nodes" className="text-cyan-400 hover:text-cyan-300 transition-colors">
|
||||
<Button to="/nodes" variant="link" color="white">
|
||||
Host a Node →
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
|
||||
@@ -76,38 +76,45 @@ function BackgroundIllustration(props: React.ComponentPropsWithoutRef<'div'>) {
|
||||
|
||||
export function Hero() {
|
||||
return (
|
||||
<div className="overflow-hidden pb-24 lg:py-12 mt-10 lg:pb-0 border border-t-0 border-b border-gray-100">
|
||||
<div className="overflow-hidden pb-12 lg:py-12 mt-10 lg:pb-0 border border-t-0 border-b border-gray-100">
|
||||
<Container>
|
||||
<div className="flex flex-col-reverse gap-y-16 lg:grid lg:grid-cols-12 lg:gap-x-8 lg:gap-y-20 px-6 lg:px-8">
|
||||
<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">
|
||||
<Eyebrow className="mb-4">
|
||||
MYCELIUM NETWORK
|
||||
</Eyebrow>
|
||||
<H3 className="mt-8 ">
|
||||
<H3 className="mt-4">
|
||||
The Network Stack for Private, Autonomous Networking
|
||||
</H3>
|
||||
<P className="mt-6 text-lg leading-tight text-gray-600 lg:text-xl lg:leading-normal">
|
||||
Connect once. Get private networking, censorship-resistant publishing, and on-network AI in one encrypted fabric.
|
||||
</P>
|
||||
<P className="mt-6 text-lg leading-tight text-gray-600 lg:text-xl lg:leading-normal">
|
||||
<P className="mt-4 text-lg leading-tight text-gray-600 lg:text-xl lg:leading-normal">
|
||||
Your Pod is your personal gateway to the network.
|
||||
</P>
|
||||
<div className="mt-8 flex flex-wrap gap-x-6 gap-y-4">
|
||||
<Button to="/download" variant="solid" color="cyan">
|
||||
Get Started
|
||||
</Button>
|
||||
<Button to="/download" variant="outline" color="cyan">
|
||||
<Button
|
||||
as="a"
|
||||
to="https://threefold.info/mycelium_network/docs/"
|
||||
variant="outline"
|
||||
color="gray"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Explore Docs
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative mt-0 lg:mt-10 lg:col-span-5 lg:row-span-2 xl:col-span-6">
|
||||
<BackgroundIllustration className="absolute left-1/2 top-4 h-[1026px] w-[1026px] -translate-x-1/2 stroke-gray-300/70 sm:top-16 lg:-top-12 lg:ml-12" />
|
||||
<div className="mx-auto h-[460px] max-w-[520px] mask-[linear-gradient(to_bottom,white_60%,transparent)] lg:absolute lg:-inset-x-10 lg:-top-24 lg:h-auto lg:pt-10 xl:-bottom-32">
|
||||
<div className="relative mt-8 lg:mt-10 lg:col-span-5 lg:row-span-2 xl:col-span-6">
|
||||
<BackgroundIllustration className="hidden md:block absolute left-1/2 top-4 h-[1026px] w-[1026px] -translate-x-1/2 stroke-gray-300/70 sm:top-16 lg:-top-12 lg:ml-12" />
|
||||
<div className="mx-auto max-w-[520px] flex items-center justify-center mask-[linear-gradient(to_bottom,white_60%,transparent)] lg:absolute lg:-inset-x-10 lg:-top-24 lg:h-auto lg:pt-10 xl:-bottom-32">
|
||||
<img
|
||||
src={phoneFrame}
|
||||
alt="Mycelium application demo"
|
||||
className="mx-auto w-auto max-w-[366px]"
|
||||
className="mx-auto w-full max-w-[366px] h-auto"
|
||||
width={366}
|
||||
height={729}
|
||||
/>
|
||||
|
||||
@@ -30,7 +30,7 @@ export function NetworkCapabilities() {
|
||||
One network for all your connectivity needs.
|
||||
</P>
|
||||
|
||||
<P className="mt-3 text-lg text-gray-200">
|
||||
<P className="mt-2 text-gray-200">
|
||||
Mycelium replaces separate layers like VPNs, hosting, and DNS with a single encrypted, peer-to-peer system that links devices, apps, and environments directly.
|
||||
</P>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@ import windowsIcon from '@/images/windows.svg'
|
||||
import androidIcon from '@/images/android.svg'
|
||||
import linuxIcon from '@/images/linux.svg'
|
||||
|
||||
import { CT, CP } from '@/components/Texts'
|
||||
import { CT, CP, Eyebrow } from '@/components/Texts'
|
||||
|
||||
const features = [
|
||||
{
|
||||
@@ -42,7 +42,7 @@ const features = [
|
||||
|
||||
export function NetworkDownload() {
|
||||
return (
|
||||
<section className="w-full max-w-8xl mx-auto bg-transparent">
|
||||
<section id="download" className="w-full max-w-8xl mx-auto bg-transparent">
|
||||
|
||||
{/* ✅ Top horizontal line with spacing */}
|
||||
<div className="max-w-7xl bg-transparent mx-auto py-6 border border-t-0 border-b-0 border-gray-100"></div>
|
||||
@@ -50,11 +50,12 @@ export function NetworkDownload() {
|
||||
|
||||
<div className="mx-auto max-w-7xl px-6 lg:px-8 bg-white py-12 border border-t-0 border-b-0 border-gray-100">
|
||||
<div className="mx-auto max-w-2xl lg:mx-0">
|
||||
<Eyebrow color="accent">Get Started</Eyebrow>
|
||||
<motion.h3
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="text-4xl font-medium tracking-tight text-gray-900 lg:text-5xl"
|
||||
className="text-4xl font-medium tracking-tight mt-2 text-gray-900 lg:text-5xl"
|
||||
>
|
||||
Download Mycelium Network
|
||||
</motion.h3>
|
||||
@@ -64,19 +65,11 @@ export function NetworkDownload() {
|
||||
transition={{ duration: 0.5, delay: 0.2 }}
|
||||
className="mt-8 text-lg text-gray-600 lg:leading-8"
|
||||
>
|
||||
Get Mycelium Network for Android, Windows, macOS, and iOS to securely connect, store, and interact with the decentralized network—seamlessly and efficiently. Not sure how it works?{' '}
|
||||
<a
|
||||
href="https://threefold.info/mycelium_network/docs/"
|
||||
className="font-semibold text-gray-900 underline transition-colors hover:text-cyan-500"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Read the manual.
|
||||
</a>
|
||||
Get Mycelium Network for Android, Windows, macOS, and iOS to securely connect, store, and interact with the decentralized network seamlessly and efficiently.
|
||||
</motion.p>
|
||||
</div>
|
||||
<div className="mx-auto mt-8 max-w-2xl lg:mt-12 lg:max-w-none">
|
||||
<dl className="grid max-w-xl grid-cols-1 gap-x-8 gap-y-16 md:grid-cols-2 lg:max-w-none lg:grid-cols-4">
|
||||
<dl className="grid max-w-xl grid-cols-1 gap-x-8 lg:gap-y-16 gap-y-8 md:grid-cols-2 lg:max-w-none lg:grid-cols-4">
|
||||
{features.map((feature) => (
|
||||
<div
|
||||
key={feature.name}
|
||||
|
||||
@@ -38,11 +38,11 @@ export function NetworkPros() {
|
||||
<div className="bg-[#121212] w-full max-w-7xl mx-auto border border-t-0 border-b-0 border-gray-800">
|
||||
{/* Centered intro */}
|
||||
<div className="px-6 pt-12 pb-4 text-center max-w-4xl mx-auto ">
|
||||
<Eyebrow className="uppercase tracking-[0.16em] text-cyan-600">
|
||||
<Eyebrow className="text-cyan-500">
|
||||
WHY
|
||||
</Eyebrow>
|
||||
|
||||
<H3 className="mt-4 text-white">
|
||||
<H3 className="mt-2 text-white">
|
||||
Why It’s Revolutionary
|
||||
</H3>
|
||||
|
||||
|
||||
@@ -369,7 +369,7 @@ function FeaturesMobile() {
|
||||
<MobileFeatureTitle color="white" className="mt-6">
|
||||
{feature.name}
|
||||
</MobileFeatureTitle>
|
||||
<FeatureDescription color="secondary" className="mt-2">
|
||||
<FeatureDescription className="mt- text-gray-200">
|
||||
{feature.description}
|
||||
</FeatureDescription>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useId } from 'react'
|
||||
import { Container } from '@/components/Container'
|
||||
import { CP } from '@/components/Texts'
|
||||
import { CP, H3, P, Eyebrow } from '@/components/Texts'
|
||||
|
||||
const features = [
|
||||
{
|
||||
@@ -197,13 +197,13 @@ export function SecondaryFeatures() {
|
||||
|
||||
<Container className="py-12 border border-t-0 border-b-0 border-gray-100">
|
||||
<div className="mx-auto max-w-4xl sm:text-center">
|
||||
<h2 className="text-base/7 font-semibold text-cyan-500">FEATURES</h2>
|
||||
<p className="text-3xl lg:text-4xl font-medium tracking-tight text-gray-900">
|
||||
<Eyebrow className="text-cyan-500 uppercase tracking-[0.16em]">FEATURES</Eyebrow>
|
||||
<H3 className="mt-2 text-black">
|
||||
Core Features
|
||||
</p>
|
||||
<p className="mt-6 text-lg text-gray-600">
|
||||
</H3>
|
||||
<P className="mt-4 text-gray-700 text-base leading-relaxed">
|
||||
The Mycelium Network is evolving with new features to support richer data movement, identity, and application connectivity across the mesh.
|
||||
</p>
|
||||
</P>
|
||||
</div>
|
||||
<ul
|
||||
role="list"
|
||||
@@ -212,7 +212,7 @@ export function SecondaryFeatures() {
|
||||
{features.map((feature) => (
|
||||
<li
|
||||
key={feature.name}
|
||||
className="rounded-2xl border border-gray-100 p-8 transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20"
|
||||
className="rounded-2xl border border-gray-200 p-8 transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20"
|
||||
>
|
||||
<feature.icon className="h-8 w-8" />
|
||||
<CP className="mt-6 font-semibold text-gray-900">
|
||||
|
||||
@@ -11,7 +11,7 @@ export function CallToAction() {
|
||||
|
||||
<div
|
||||
id="get-started"
|
||||
className="relative py-18 max-w-7xl mx-auto bg-[#111111] border border-t-0 border-b-0 border-gray-800"
|
||||
className="relative py-18 max-w-7xl overflow-hidden mx-auto bg-[#111111] border border-t-0 border-b-0 border-gray-800"
|
||||
>
|
||||
{/* ✅ Cyan Radial Glow */}
|
||||
<svg
|
||||
@@ -24,7 +24,7 @@ export function CallToAction() {
|
||||
cx={512}
|
||||
cy={512}
|
||||
fill="url(#mycelium-cyan-glow)"
|
||||
fillOpacity="0.2"
|
||||
fillOpacity="0.3"
|
||||
/>
|
||||
<defs>
|
||||
<radialGradient id="mycelium-cyan-glow">
|
||||
@@ -39,13 +39,13 @@ export function CallToAction() {
|
||||
Join Mycelium Grid
|
||||
</h2>
|
||||
|
||||
<p className="mt-6 text-lg text-gray-300">
|
||||
<p className="mt-6 lg:text-lg text-base leading-normal text-gray-300">
|
||||
Be part of a global network that powers private, distributed
|
||||
infrastructure. Host a node, contribute resources, and earn rewards
|
||||
while expanding the sovereign digital grid.
|
||||
</p>
|
||||
|
||||
<div className="mt-10 flex flex-wrap justify-center gap-x-10 gap-y-8">
|
||||
<div className="mt-6 flex flex-wrap justify-center gap-x-10 gap-y-8">
|
||||
<div className="flex flex-col items-center text-center max-w-xs">
|
||||
<Button to="/host" variant="solid" color="cyan" className="mt-4">
|
||||
Join Mycelium
|
||||
@@ -54,7 +54,7 @@ export function CallToAction() {
|
||||
|
||||
<div className="flex flex-col items-center text-center max-w-xs">
|
||||
<Button to="/docs" variant="outline" color="white" className="mt-4">
|
||||
Explore docs
|
||||
Explore Docs
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { motion } from "framer-motion";
|
||||
import { SectionHeader, P, Eyebrow, CT, CP } from "@/components/Texts";
|
||||
import { H3, P, Eyebrow, CT, CP } from "@/components/Texts";
|
||||
import type { ComponentPropsWithoutRef } from "react";
|
||||
|
||||
type CircleIconProps = ComponentPropsWithoutRef<"svg">;
|
||||
@@ -62,14 +62,13 @@ export function NodeBenefits() {
|
||||
className="mx-auto max-w-5xl text-center"
|
||||
>
|
||||
<Eyebrow color="accent">Host</Eyebrow>
|
||||
<SectionHeader
|
||||
className="text-3xl font-medium tracking-tight"
|
||||
color="light"
|
||||
<H3
|
||||
className="mt-2 text-white"
|
||||
>
|
||||
Benefits of Hosting Nodes
|
||||
</SectionHeader>
|
||||
</H3>
|
||||
|
||||
<P className="mt-6" color="light">
|
||||
<P className="mt-6 text-gray-200">
|
||||
Hosting a node gives you private compute, contributes to the global
|
||||
Mycelium infrastructure, and unlocks ways to earn from real network
|
||||
usage, all while keeping sovereignty and control.
|
||||
@@ -95,13 +94,13 @@ export function NodeBenefits() {
|
||||
delay: 0.3 + index * 0.15,
|
||||
ease: "easeOut",
|
||||
}}
|
||||
className="rounded-2xl border border-gray-300 bg-white/5 p-8 transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20 backdrop-blur-md"
|
||||
className="rounded-md border border-gray-100 bg-white/5 lg:p-8 p-6 transition-all duration-300 ease-in-out hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20 backdrop-blur-md"
|
||||
>
|
||||
<feature.icon className="mb-4 h-8 w-8 text-white" />
|
||||
<CT as="span" className="text-left font-semibold" color="light">
|
||||
{feature.name}
|
||||
</CT>
|
||||
<CP className="mt-2 text-left text-gray-200">
|
||||
<CP className="mt-2 text-left font-light text-gray-300">
|
||||
{feature.description}
|
||||
</CP>
|
||||
</motion.li>
|
||||
|
||||
@@ -1,32 +1,38 @@
|
||||
'use client'
|
||||
|
||||
import { Button } from '@/components/Button'
|
||||
import { Eyebrow, H3 } from '@/components/Texts'
|
||||
import { Eyebrow, H3, P } from '@/components/Texts'
|
||||
|
||||
export function NodeHero() {
|
||||
return (
|
||||
<div className="">
|
||||
{/* Boxed container */}
|
||||
<div
|
||||
className="relative mx-auto max-w-7xl border border-t-0 border-b-0 border-gray-100 bg-white overflow-hidden bg-contain bg-right bg-no-repeat"
|
||||
style={{ backgroundImage: "url('/images/gpuhero2.png')", backgroundSize: "contain" }}
|
||||
className="relative mx-auto max-w-7xl border border-t-0 border-b-0 border-gray-100 bg-white overflow-hidden md:bg-[url('/images/gpuhero2.png')] md:bg-contain md:bg-right md:bg-no-repeat"
|
||||
>
|
||||
{/* Inner padding */}
|
||||
<div className="px-6 py-16 lg:py-24">
|
||||
<div className="px-6 pt-4 pb-12 lg:py-24">
|
||||
{/* Mobile-only hero image */}
|
||||
<img
|
||||
src="/images/mobile/nodes.jpg"
|
||||
alt="Mycelium Nodes visual"
|
||||
className="mb-8 w-full object-cover md:hidden"
|
||||
/>
|
||||
|
||||
<div className="max-w-2xl lg:pl-6">
|
||||
<Eyebrow>MYCELIUM NODES</Eyebrow>
|
||||
<H3 as="h1" className="mt-4">
|
||||
Host a Node. Power the Network.
|
||||
</H3>
|
||||
<p className="mt-6 text-lg text-gray-800">
|
||||
<P className="mt-6 text-gray-600">
|
||||
The Mycelium Network runs on nodes hosted by people and organizations around the world. Each node adds capacity, resilience, and sovereignty, expanding a global network for private, distributed compute and AI.
|
||||
</p>
|
||||
</P>
|
||||
<div className="mt-10 flex items-center gap-x-6">
|
||||
<Button to="#node-getting-started" as="a" variant="solid" color="cyan">
|
||||
How it works
|
||||
</Button>
|
||||
<Button to="#node-architecture" as="a" variant="outline">
|
||||
Explore Docs <span aria-hidden="true">→</span>
|
||||
Explore Docs
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { useState } from "react";
|
||||
import { motion } from "framer-motion";
|
||||
import { Eyebrow, SectionHeader, P } from "@/components/Texts";
|
||||
import { Button } from "@/components/Button";
|
||||
import {
|
||||
QuestionMarkCircleIcon,
|
||||
CheckIcon,
|
||||
@@ -96,7 +97,7 @@ export function NodeProducts() {
|
||||
</P>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 lg:gap-24 max-w-6xl mx-auto">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4 lg:gap-24 max-w-6xl mx-auto">
|
||||
|
||||
{/* ------------------------------ */}
|
||||
{/* LEFT — TEXT AREA */}
|
||||
@@ -106,7 +107,7 @@ export function NodeProducts() {
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.4 }}
|
||||
className="flex flex-col justify-center"
|
||||
className="order-2 lg:order-1 flex flex-col justify-center"
|
||||
>
|
||||
<h1 className="text-3xl font-semibold text-white">
|
||||
{selectedNode.name}
|
||||
@@ -168,29 +169,35 @@ export function NodeProducts() {
|
||||
{/* ------------------------ */}
|
||||
{/* BUTTONS AREA */}
|
||||
{/* ------------------------ */}
|
||||
<div className="mt-10 flex flex-col sm:flex-row gap-4">
|
||||
|
||||
{/* Outline Button */}
|
||||
<a
|
||||
href={selectedNode.learnUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex-1 sm:flex-none text-center border border-gray-700 hover:border-gray-500
|
||||
text-gray-300 hover:text-white px-8 py-3 rounded-lg transition"
|
||||
>
|
||||
Learn More
|
||||
</a>
|
||||
<div className="mt-8 flex flex-col sm:flex-row gap-8">
|
||||
|
||||
{/* Solid Cyan Button */}
|
||||
<a
|
||||
href={selectedNode.buyUrl}
|
||||
<Button
|
||||
as="a"
|
||||
to={selectedNode.buyUrl}
|
||||
variant="solid"
|
||||
color="cyan"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex-1 sm:flex-none text-center bg-cyan-600 hover:bg-cyan-700
|
||||
text-white px-8 py-3 rounded-lg font-medium transition"
|
||||
className="flex-1 sm:flex-none text-center"
|
||||
>
|
||||
Purchase Node
|
||||
</a>
|
||||
</Button>
|
||||
|
||||
{/* Outline Button */}
|
||||
<Button
|
||||
as="a"
|
||||
to={selectedNode.learnUrl}
|
||||
variant="outline"
|
||||
color="white"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex-1 sm:flex-none text-center"
|
||||
>
|
||||
Learn More
|
||||
</Button>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -204,20 +211,20 @@ export function NodeProducts() {
|
||||
initial={{ opacity: 0, scale: 0.92 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.35 }}
|
||||
className="flex justify-center"
|
||||
className="order-1 lg:order-2 flex justify-center"
|
||||
>
|
||||
<img
|
||||
src={selectedNode.image}
|
||||
alt={selectedNode.name}
|
||||
className="max-w-md rounded-2xl "
|
||||
className="max-w-md rounded-2xl object-contain lg:px-0 px-6 lg:top-0 -top-10"
|
||||
/>
|
||||
</motion.div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom border */}
|
||||
<div className="w-full border-b border-gray-800 bg-[#121212]" />
|
||||
{/* ✅ Bottom horizontal line with spacing */}
|
||||
<div className="w-full border-b border-gray-800" />
|
||||
<div className="max-w-7xl bg-transparent mx-auto py-6 border border-t-0 border-b-0 border-gray-800"></div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Eyebrow, H3, P, Small, CT, CP } from "@/components/Texts";
|
||||
|
||||
const cards = [
|
||||
{
|
||||
category: "Autonomous",
|
||||
category: "AUTONOMY",
|
||||
title: "Autonomous Operation",
|
||||
description: "Runs autonomously with no central control.",
|
||||
image: "/images/autonomous.png",
|
||||
@@ -12,13 +12,13 @@ const cards = [
|
||||
innerRounded: "lg:rounded-tl-[calc(2rem+1px)]",
|
||||
},
|
||||
{
|
||||
category: "Security",
|
||||
category: "SECURITY",
|
||||
title: "Encrypted by Default",
|
||||
description: "Fully encrypted and identity-based.",
|
||||
image: "/images/encryptednode.png",
|
||||
},
|
||||
{
|
||||
category: "Efficiency",
|
||||
category: "EFFICIENCY",
|
||||
title: "Energy Efficient",
|
||||
description: "Energy-efficient and quiet, designed for 24/7 uptime.",
|
||||
image: "/images/energy.png",
|
||||
@@ -26,7 +26,7 @@ const cards = [
|
||||
innerRounded: "lg:rounded-tr-[calc(2rem+1px)]",
|
||||
},
|
||||
{
|
||||
category: "Monitoring",
|
||||
category: "MONITORING",
|
||||
title: "Measured Uptime",
|
||||
description: "Automatically measures uptime and contribution.",
|
||||
image: "/images/uptime.png",
|
||||
@@ -34,13 +34,13 @@ const cards = [
|
||||
innerRounded: "lg:rounded-bl-[calc(2rem+1px)]",
|
||||
},
|
||||
{
|
||||
category: "Full Stack",
|
||||
category: "SUPPORT",
|
||||
title: "Full Mycelium Stack Support",
|
||||
description: "Supports Mycelium Network, Cloud, Pods, and Agents.",
|
||||
image: "/images/fullstack.png",
|
||||
},
|
||||
{
|
||||
category: "Edge & Home",
|
||||
category: "DEPLOYMENT",
|
||||
title: "Edge & Home Ready",
|
||||
description:
|
||||
"Runs seamlessly on compact hardware for edge, home, or micro-datacenter deployments.",
|
||||
@@ -52,9 +52,15 @@ const cards = [
|
||||
|
||||
export function NodeSpecs() {
|
||||
return (
|
||||
<section className="bg-white py-24 sm:py-32">
|
||||
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
||||
<section className="w-full max-w-8xl mx-auto bg-transparent">
|
||||
|
||||
{/* ✅ Top horizontal line with spacing */}
|
||||
<div className="max-w-7xl bg-transparent mx-auto py-6 border border-t-0 border-b-0 border-gray-100"></div>
|
||||
<div className="w-full border-t border-l border-r border-gray-100" />
|
||||
|
||||
|
||||
{/* ✅ Inner content container */}
|
||||
<div className="max-w-7xl bg-white mx-auto py-12 border border-t-0 border-b-0 border-gray-100 px-6 lg:px-8">
|
||||
<Eyebrow>Node Specifications</Eyebrow>
|
||||
<H3 className="mt-2">Built for Reliability and Control</H3>
|
||||
<P className="mt-4 max-w-2xl">
|
||||
@@ -63,9 +69,9 @@ export function NodeSpecs() {
|
||||
</P>
|
||||
|
||||
{/* BENTO GRID */}
|
||||
<div className="mt-12 grid grid-cols-1 gap-4 sm:mt-16 lg:grid-cols-3 lg:grid-rows-2">
|
||||
<div className="mt-8 grid grid-cols-1 gap-4 lg:grid-cols-3 lg:grid-rows-2">
|
||||
{cards.map((item, index) => (
|
||||
<div key={index} className="relative">
|
||||
<div key={index} className="relative group">
|
||||
|
||||
{/* OUTER BACKPLATE */}
|
||||
<div
|
||||
@@ -76,7 +82,7 @@ export function NodeSpecs() {
|
||||
|
||||
{/* INNER CARD */}
|
||||
<div
|
||||
className={`relative flex h-full flex-row items-center gap-6 overflow-hidden rounded-[calc(var(--radius-lg)+1px)] p-8 ${
|
||||
className={`relative flex h-full flex-row items-center gap-3 overflow-hidden rounded-[calc(var(--radius-lg)+1px)] px-8 py-6 transition-transform duration-300 group-hover:scale-102 group-hover:shadow-lg group-hover:shadow-cyan-500/20 ${
|
||||
item.innerRounded || ""
|
||||
}`}
|
||||
>
|
||||
@@ -89,15 +95,15 @@ export function NodeSpecs() {
|
||||
|
||||
{/* RIGHT TEXT */}
|
||||
<div className="flex flex-col">
|
||||
<Small className="text-gray-500">{item.category}</Small>
|
||||
<Small className="text-cyan-500 uppercase tracking-[0.16em]">{item.category}</Small>
|
||||
<CT className="mt-1">{item.title}</CT>
|
||||
<CP className="mt-2 max-w-sm">{item.description}</CP>
|
||||
<CP className="mt-1 max-w-sm">{item.description}</CP>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* OUTLINE */}
|
||||
<div
|
||||
className={`pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 ${
|
||||
className={`pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 transition-transform duration-300 group-hover:scale-102 group-hover:shadow-lg group-hover:shadow-cyan-500/20 ${
|
||||
item.rounded || ""
|
||||
}`}
|
||||
/>
|
||||
@@ -105,6 +111,9 @@ export function NodeSpecs() {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
{/* ✅ Bottom horizontal line with spacing */}
|
||||
<div className="w-full border-b border-gray-100" />
|
||||
<div className="max-w-7xl bg-transparent mx-auto py-6 border border-t-0 border-b-0 border-gray-100"></div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { Eyebrow, H3, P, CT, CP } from "@/components/Texts";
|
||||
import { Eyebrow, H3, P, CT } from "@/components/Texts";
|
||||
import {
|
||||
CloudArrowDownIcon,
|
||||
CpuChipIcon,
|
||||
@@ -16,7 +16,7 @@ const steps = [
|
||||
icon: CpuChipIcon,
|
||||
},
|
||||
{
|
||||
name: "Download Mycelium OS",
|
||||
name: "Download Mycelium",
|
||||
description:
|
||||
"Install the Mycelium OS to prepare your node for network access.",
|
||||
icon: CloudArrowDownIcon,
|
||||
@@ -38,50 +38,74 @@ const steps = [
|
||||
export function NodeSteps() {
|
||||
return (
|
||||
<section className="w-full max-w-8xl mx-auto bg-transparent">
|
||||
{/* Top line */}
|
||||
|
||||
{/* Header spacing + borders */}
|
||||
<div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 border-gray-100" />
|
||||
<div className="w-full border-t border-l border-r border-gray-100" />
|
||||
|
||||
<div className="max-w-7xl bg-white mx-auto py-16 border border-t-0 border-b-0 border-gray-100">
|
||||
{/* Content */}
|
||||
<div className="max-w-7xl bg-white mx-auto px-6 lg:px-6 py-16 border border-t-0 border-b-0 border-gray-100">
|
||||
|
||||
{/* HEADER */}
|
||||
<div className="mx-auto max-w-4xl sm:text-center">
|
||||
<Eyebrow className="text-cyan-500">HOW IT WORKS</Eyebrow>
|
||||
|
||||
<H3 className="text-3xl lg:text-4xl font-medium tracking-tight text-gray-900">
|
||||
Host a Node
|
||||
</H3>
|
||||
|
||||
<P className="mt-6 text-lg text-gray-600">
|
||||
<H3 className="text-gray-900">Host a Node</H3>
|
||||
<P className="mt-4 text-gray-600">
|
||||
Hosting a node takes minutes, and it runs automatically once online.
|
||||
</P>
|
||||
</div>
|
||||
|
||||
{/* 🔹 Horizontal Stepper */}
|
||||
<div className="relative mt-16 px-6 flex flex-col gap-8 lg:flex-row lg:items-start lg:justify-between">
|
||||
{steps.map((step, i) => (
|
||||
<div key={step.name} className="relative flex-1 px-4">
|
||||
{/* 🔹 Horizontal connector line (desktop only) */}
|
||||
{i < steps.length - 1 && (
|
||||
<div className="hidden lg:block absolute top-5 left-[55%] w-full h-[4px] bg-gray-400 -z-10" />
|
||||
)}
|
||||
{/* STEPS */}
|
||||
<ul className="relative mt-12 flex flex-col gap-14 max-w-md mx-auto lg:max-w-none lg:flex-row lg:gap-6">
|
||||
|
||||
{/* 🔹 Step header with icon */}
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex items-center justify-center w-8 h-8 rounded-full bg-cyan-100 text-cyan-600">
|
||||
<step.icon className="w-5 h-5" />
|
||||
{steps.map((step, i) => (
|
||||
<li key={step.name} className="relative flex lg:flex-col lg:items-center">
|
||||
|
||||
{/* LEFT COLUMN — circle + MOBILE vertical line */}
|
||||
<div className="relative flex flex-col items-center">
|
||||
|
||||
{/* Circle */}
|
||||
<div className="w-10 h-10 text-black bg-white border border-gray-300 rounded-full shadow-sm flex items-center justify-center z-10">
|
||||
{i + 1}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* CONTENT */}
|
||||
<div className="ml-4 lg:ml-0 lg:mt-8 max-w-xs">
|
||||
<div className="flex items-center gap-2 lg:justify-center">
|
||||
<step.icon className="w-6 h-6 text-cyan-500" />
|
||||
<CT>{step.name}</CT>
|
||||
</div>
|
||||
<p className="mt-2 text-base leading-snug text-gray-600 lg:text-center">
|
||||
{step.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 🔹 Description */}
|
||||
<CP className="mt-3">{step.description}</CP>
|
||||
</div>
|
||||
{/* DESKTOP horizontal line — perfectly centered */}
|
||||
{i < steps.length - 1 && (
|
||||
<span
|
||||
className="
|
||||
hidden lg:block
|
||||
absolute
|
||||
top-[20px] /* Circle center */
|
||||
left-[50%]
|
||||
w-full
|
||||
h-[1px]
|
||||
bg-gray-200
|
||||
"
|
||||
/>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{/* bottom line */}
|
||||
{/* ✅ Bottom horizontal line with spacing */}
|
||||
|
||||
{/* Bottom border */}
|
||||
<div className="w-full border-b border-gray-100" />
|
||||
<div className="max-w-7xl bg-transparent mx-auto py-6 border border-t-0 border-b-0 border-gray-100"></div>
|
||||
<div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 border-gray-100" />
|
||||
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { AnimatedSection } from '@/components/AnimatedSection';
|
||||
import { NodeHero } from './NodeHero';
|
||||
import { NodeBenefits } from './NodeBenefits';
|
||||
import { NodeSteps } from './NodeSteps';
|
||||
@@ -9,12 +10,29 @@ import { CallToAction } from './CallToAction';
|
||||
const NodesPage: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<AnimatedSection>
|
||||
<NodeHero />
|
||||
</AnimatedSection>
|
||||
|
||||
<AnimatedSection>
|
||||
<NodeBenefits />
|
||||
</AnimatedSection>
|
||||
|
||||
<AnimatedSection>
|
||||
<NodeSteps />
|
||||
</AnimatedSection>
|
||||
|
||||
<AnimatedSection>
|
||||
<NodeProducts />
|
||||
</AnimatedSection>
|
||||
|
||||
<AnimatedSection>
|
||||
<NodeSpecs />
|
||||
</AnimatedSection>
|
||||
|
||||
<AnimatedSection>
|
||||
<CallToAction />
|
||||
</AnimatedSection>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ export function CallToAction() {
|
||||
{/* ✅ Main boxed area */}
|
||||
<div
|
||||
id="get-started"
|
||||
className="relative py-18 max-w-7xl mx-auto bg-[#111111] border border-t-0 border-b-0 border-gray-800"
|
||||
className="relative py-18 max-w-7xl overflow-hidden mx-auto bg-[#111111] border border-t-0 border-b-0 border-gray-800"
|
||||
>
|
||||
{/* ✅ Cyan Radial Glow */}
|
||||
<svg
|
||||
@@ -36,7 +36,7 @@ export function CallToAction() {
|
||||
cx={512}
|
||||
cy={512}
|
||||
fill="url(#mycelium-cyan-glow)"
|
||||
fillOpacity="0.2"
|
||||
fillOpacity="0.3"
|
||||
/>
|
||||
<defs>
|
||||
<radialGradient id="mycelium-cyan-glow">
|
||||
@@ -52,15 +52,15 @@ export function CallToAction() {
|
||||
|
||||
</h2>
|
||||
|
||||
<p className="mt-6 text-lg text-gray-300">
|
||||
<p className="mt-6 lg:text-lg text-base leading-normal text-gray-300">
|
||||
The first Pods are launching soon.
|
||||
10,000 early Pods will be available for early adopters.
|
||||
</p>
|
||||
|
||||
<div className="mt-10 flex items-center justify-center">
|
||||
<div className="mt-6 flex items-center justify-center">
|
||||
<ul
|
||||
role="list"
|
||||
className="grid grid-cols-1 gap-x-8 gap-y-3 text-left text-base/7 text-gray-200 sm:grid-cols-2"
|
||||
className="grid grid-cols-1 gap-x-8 gap-y-1 lg:gap-y-3 text-left text-base/7 text-gray-200 sm:grid-cols-2"
|
||||
>
|
||||
{benefits.map((benefit) => (
|
||||
<li key={benefit} className="flex items-start gap-x-3">
|
||||
@@ -74,14 +74,14 @@ export function CallToAction() {
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p className="mt-6 text-lg text-gray-300">
|
||||
<p className="mt-6 lg:text-lg text-base leading-normal text-gray-300">
|
||||
Next, Pods will support peer-to-peer AI Agents that live inside your environment.
|
||||
Your own AI, powered by your data without any data leaks. Be among the first to claim
|
||||
your private space on the Mycelium Network.
|
||||
</p>
|
||||
|
||||
{/* ✅ Two cards, stacked center with spacing */}
|
||||
<div className="mt-10 flex flex-wrap justify-center gap-x-10 gap-y-8">
|
||||
<div className="mt-6 flex flex-wrap justify-center gap-x-8 gap-y-8">
|
||||
<div className="flex flex-col items-center text-center max-w-xs">
|
||||
<Button to="#" variant="solid" color="cyan" className="mt-4">
|
||||
Join the Waitlist
|
||||
|
||||
@@ -1,22 +1,13 @@
|
||||
import { H3, Eyebrow, P } from "@/components/Texts"
|
||||
import { Button } from "@/components/Button"
|
||||
import React from 'react';
|
||||
|
||||
// NOTE: Ensure your global types file (global.d.ts) is set up
|
||||
// to avoid TypeScript errors on window.ml_account
|
||||
|
||||
export default function Homepod() {
|
||||
const onGetStartedClick = () => {
|
||||
// 1. Ensure we are in a browser environment (client-side)
|
||||
// and the ml_account function is available globally.
|
||||
if (typeof window !== 'undefined' && window.ml_account) {
|
||||
|
||||
// 2. Execute the MailerLite pop-up trigger function using the specific snippet you provided.
|
||||
// TypeScript is happy if you defined the global type in step 1.
|
||||
window.ml_account('webforms', '6108375', 'l9m8g1', 'show');
|
||||
|
||||
// Ensure we are in a browser environment and ml_account exists before calling it
|
||||
if (typeof window !== 'undefined' && typeof (window as any).ml_account === 'function') {
|
||||
(window as any).ml_account('webforms', '6108375', 'l9m8g1', 'show')
|
||||
} else {
|
||||
console.log("MailerLite script (ml_account) not fully loaded or not in browser.");
|
||||
console.log("MailerLite script (ml_account) not fully loaded or not in browser.")
|
||||
}
|
||||
};
|
||||
|
||||
@@ -24,11 +15,17 @@ export default function Homepod() {
|
||||
<div className="">
|
||||
{/* Boxed container */}
|
||||
<div
|
||||
className="relative mx-auto max-w-7xl border border-t-0 border-b-0 border-gray-100 bg-white overflow-hidden bg-contain bg-right bg-no-repeat"
|
||||
style={{ backgroundImage: "url('/images/computehero11.webp')", backgroundSize: "contain" }}
|
||||
className="relative mx-auto max-w-7xl border border-t-0 border-b-0 border-gray-100 bg-white overflow-hidden md:bg-[url('/images/computehero11.webp')] md:bg-contain md:bg-right md:bg-no-repeat"
|
||||
>
|
||||
{/* Inner padding */}
|
||||
<div className="px-6 py-16 lg:py-24">
|
||||
<div className="px-6 pt-4 pb-12 lg:py-24">
|
||||
{/* Mobile-only hero image */}
|
||||
<img
|
||||
src="/images/mobile/pods.jpg"
|
||||
alt="Mycelium Pods visual"
|
||||
className="mb-8 w-full object-cover md:hidden"
|
||||
/>
|
||||
|
||||
<div className="max-w-2xl lg:pl-6">
|
||||
<Eyebrow>
|
||||
Mycelium Pods - Coming Soon
|
||||
@@ -36,7 +33,7 @@ export default function Homepod() {
|
||||
<H3 className="mt-4">
|
||||
Your Private Space in the New Internet
|
||||
</H3>
|
||||
<P className="mt-6 text-gray-800">
|
||||
<P className="mt-6 text-gray-600">
|
||||
Pods are personal digital spaces on the Mycelium Network. They are private, persistent, and fully under your control. Run conversations, files, and tools directly on the network instead of through central servers
|
||||
</P>
|
||||
<div className="mt-8 flex items-center gap-x-6">
|
||||
@@ -49,7 +46,7 @@ export default function Homepod() {
|
||||
Join the Waitlist
|
||||
</Button>
|
||||
<Button to="#" variant="outline">
|
||||
Explore Docs →
|
||||
Explore Docs
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -108,7 +108,7 @@ export function PodsBento() {
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="h-48 w-full flex items-center justify-center bg-transparent" />
|
||||
<div className="hidden md:flex md:h-48 w-full items-center justify-center bg-transparent" />
|
||||
)}
|
||||
|
||||
{/* TEXT AREA */}
|
||||
|
||||
@@ -20,7 +20,7 @@ export function PodsCapabilities() {
|
||||
|
||||
{/* ✅ LEFT SIDE — Title + Intro */}
|
||||
<div className="max-w-xl ">
|
||||
<Eyebrow>What You Can Do</Eyebrow>
|
||||
<Eyebrow className="text-cyan-500 tracking-[0.16em]">What You Can Do</Eyebrow>
|
||||
|
||||
<H3 className="mt-6 text-white">
|
||||
Pods Features
|
||||
|
||||