Compare commits
62 Commits
developmen
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 1ec9741283 | |||
| 5d7272ff6c | |||
| 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" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Project Mycelium - Unleash the Power of Decentralized Networks</title>
|
<meta name="google-site-verification" content="rRrZkMEhdC4yFe_BrENEzYmy2bRfD-VE6RTRiDJNLkg" />
|
||||||
<meta name="description" content="Project Mycelium's technology enables anyone to deploy their own Internet infrastructure, anywhere." />
|
<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.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<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" />
|
<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,23 +3,30 @@ import clsx from 'clsx'
|
|||||||
|
|
||||||
const baseStyles = {
|
const baseStyles = {
|
||||||
solid:
|
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:
|
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 = {
|
const variantStyles = {
|
||||||
solid: {
|
solid: {
|
||||||
cyan: 'relative overflow-hidden bg-cyan-500 text-white before:absolute before:inset-0 active:before:bg-transparent hover:before:bg-white/10 active:bg-cyan-600 active:text-white/80 before:transition-colors',
|
cyan: 'relative overflow-hidden bg-cyan-500 text-white before:absolute before:inset-0 hover:bg-cyan-400 active:before:bg-transparent hover:before:bg-white/10 active:bg-cyan-500 active:text-white/80 before:transition-colors',
|
||||||
white:
|
white:
|
||||||
'bg-white text-cyan-900 hover:bg-white/90 active:bg-white/90 active:text-cyan-900/70',
|
'bg-white text-cyan-900 hover:bg-white/90 active:bg-white/90 active:text-cyan-900/70',
|
||||||
gray: 'bg-gray-800 text-white hover:bg-gray-900 active:bg-gray-800 active:text-white/80',
|
gray: 'bg-gray-800 text-white hover:bg-gray-900 active:bg-gray-800 active:text-white/80',
|
||||||
green: 'bg-green-500 text-white hover:bg-green-600',
|
green: 'bg-green-500 text-white hover:bg-green-600',
|
||||||
},
|
},
|
||||||
outline: {
|
outline: {
|
||||||
cyan: 'border-cyan-500 text-cyan-500',
|
cyan: 'border-cyan-500 text-cyan-500 hover:border-cyan-400 hover:text-cyan-400 active:border-cyan-400',
|
||||||
gray: 'border-gray-300 text-gray-700 hover:border-cyan-500 active:border-cyan-500',
|
gray: 'border-gray-200 text-gray-600 hover:text-cyan-400 hover:border-cyan-400 active:border-cyan-400',
|
||||||
white: 'border-gray-300 text-white hover:border-cyan-500 active:border-cyan-500',
|
white: 'border-gray-300 text-white hover:text-cyan-400 hover:border-cyan-400 active:border-cyan-400',
|
||||||
|
},
|
||||||
|
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-400',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +37,11 @@ type ButtonProps = (
|
|||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
variant: 'outline'
|
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) {
|
export function Button({ className, as, ...props }: ButtonProps) {
|
||||||
props.variant ??= 'solid'
|
// Set safe defaults per variant so color always matches a valid palette key
|
||||||
props.color ??= 'gray'
|
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(
|
className = clsx(
|
||||||
baseStyles[props.variant],
|
baseStyles[variant],
|
||||||
props.variant === 'outline'
|
variant === 'outline'
|
||||||
? variantStyles.outline[props.color]
|
? variantStyles.outline[color as keyof typeof variantStyles.outline]
|
||||||
: props.variant === 'solid'
|
: variant === 'solid'
|
||||||
? variantStyles.solid[props.color]
|
? variantStyles.solid[color as keyof typeof variantStyles.solid]
|
||||||
|
: variant === 'link'
|
||||||
|
? variantStyles.link[color as keyof typeof variantStyles.link]
|
||||||
: undefined,
|
: undefined,
|
||||||
className,
|
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 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>
|
||||||
<div className="flex items-center text-gray-900">
|
<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-20 w-20 flex-none" />
|
||||||
<div className="ml-4">
|
<div className="">
|
||||||
<p className="text-base font-semibold">Project Mycelium</p>
|
<p className="text-base lg:text-lg font-semibold">Project Mycelium</p>
|
||||||
<p className="mt-1 text-sm">Unleash the Power of Decentralization</p>
|
<p className="mt-1 text-sm">Built for Digital Sovereignty</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<nav className="mt-10 flex gap-8">
|
<nav className="mt-10 flex gap-8">
|
||||||
@@ -49,11 +49,11 @@ export function Footer() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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">
|
<p className="mt-6 text-sm text-gray-500 md:mt-0">
|
||||||
© Copyright{' '}
|
© Copyright{' '}
|
||||||
<a href="https://www.threefold.io" target="_blank" rel="noopener noreferrer" className="hover:text-cyan-500 transition-colors">
|
<a href="https://ourworld.tf/" target="_blank" rel="noopener noreferrer" className="font-semibold hover:text-cyan-500 transition-colors">
|
||||||
ThreeFold
|
OurWorld
|
||||||
</a>{' '}
|
</a>{' '}
|
||||||
{new Date().getFullYear()}. All rights reserved.
|
{new Date().getFullYear()}. All rights reserved.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useState } from 'react'
|
|||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { Container } from './Container'
|
import { Container } from './Container'
|
||||||
import { Button } from './Button'
|
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 { Dialog } from '@headlessui/react'
|
||||||
import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline'
|
import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline'
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useState } from 'react'
|
|||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { Container } from './Container'
|
import { Container } from './Container'
|
||||||
import { Button } from './Button'
|
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 { Dialog } from '@headlessui/react'
|
||||||
import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline'
|
import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline'
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ const colorVariants = {
|
|||||||
primary: 'text-gray-900',
|
primary: 'text-gray-900',
|
||||||
secondary: 'text-gray-600',
|
secondary: 'text-gray-600',
|
||||||
light: 'text-gray-50',
|
light: 'text-gray-50',
|
||||||
accent: 'text-cyan-500',
|
accent: 'text-cyan-400',
|
||||||
cyan: 'text-cyan-50',
|
cyan: 'text-cyan-400',
|
||||||
white: 'text-white',
|
white: 'text-white',
|
||||||
dark: 'text-gray-950',
|
dark: 'text-gray-950',
|
||||||
tertiary: 'text-gray-700',
|
tertiary: 'text-gray-700',
|
||||||
@@ -162,5 +162,5 @@ export const DownloadCardDescription = createTextComponent(
|
|||||||
'text-base/7 leading-normal tracking-normal'
|
'text-base/7 leading-normal tracking-normal'
|
||||||
)
|
)
|
||||||
|
|
||||||
export const CT = createTextComponent('span', 'text-base lg:text-lg font-medium')
|
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-tight font-light')
|
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}
|
ref={scrollerRef}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex w-max shrink-0 gap-16 py-4",
|
"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]"
|
pauseOnHover && "hover:[animation-play-state:paused]"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -71,30 +71,27 @@ const clusterNodes = (nodeList: GeoNode[], cellSize = 2) => {
|
|||||||
function DynamicMapContainer() {
|
function DynamicMapContainer() {
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [nodes, setNodes] = useState<GeoNode[]>([]);
|
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(() => {
|
useEffect(() => {
|
||||||
async function fetchNodeData() {
|
async function fetchNodeData() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(API_URL);
|
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
|
const geoNodes: GeoNode[] = data
|
||||||
.filter((node: RawNode) => node.location && node.location.latitude && node.location.longitude)
|
.filter((node: RawNode) => node.location && node.location.latitude && node.location.longitude)
|
||||||
.map((node: RawNode) => ({
|
.map((node: RawNode) => ({
|
||||||
// Convert string coordinates to numbers
|
|
||||||
lat: parseFloat(node.location.latitude),
|
lat: parseFloat(node.location.latitude),
|
||||||
lng: parseFloat(node.location.longitude),
|
lng: parseFloat(node.location.longitude),
|
||||||
label: `${node.location.city}, ${node.location.country} (${node.node_id})`,
|
label: `${node.location.city}, ${node.location.country} (${node.node_id})`,
|
||||||
// Optionally set color based on some node property if available
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const clusteredNodes = clusterNodes(geoNodes);
|
const clusteredNodes = clusterNodes(geoNodes);
|
||||||
setNodes(clusteredNodes);
|
setNodes(clusteredNodes);
|
||||||
setLoading(false);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch node data:", error);
|
console.error("Failed to fetch node data:", error);
|
||||||
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,10 +99,8 @@ function DynamicMapContainer() {
|
|||||||
fetchNodeData();
|
fetchNodeData();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// --- RENDERING ---
|
// While fetching, show a loading state
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
// Show a loading state while data is being fetched
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-center items-center w-full aspect-[2/1] bg-[#111111] rounded-lg text-cyan-500">
|
<div className="flex justify-center items-center w-full aspect-[2/1] bg-[#111111] rounded-lg text-cyan-500">
|
||||||
<motion.span
|
<motion.span
|
||||||
@@ -120,12 +115,8 @@ function DynamicMapContainer() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass the dynamically fetched nodes to your WorldMap component
|
// After data is loaded, render the map
|
||||||
return (
|
return <WorldMap nodes={nodes} />;
|
||||||
<WorldMap
|
|
||||||
nodes={nodes}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DynamicMapContainer;
|
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.0 KiB |
@@ -123,7 +123,7 @@ export function AgentBento() {
|
|||||||
<div className="w-full h-full object-cover"><card.animation /></div>
|
<div className="w-full h-full object-cover"><card.animation /></div>
|
||||||
</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">
|
<div className="px-8 pt-4 pb-6">
|
||||||
@@ -136,7 +136,7 @@ export function AgentBento() {
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{/* ✅ NEW SUBTITLE */}
|
{/* ✅ 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">
|
<p className="mt-1 text-lg font-medium lg:text-xl tracking-tight text-white">
|
||||||
{card.title}
|
{card.title}
|
||||||
@@ -161,6 +161,9 @@ export function AgentBento() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { Button } from '@/components/Button'
|
|
||||||
import { Eyebrow, H3, P } from '@/components/Texts'
|
import { Eyebrow, H3, P } from '@/components/Texts'
|
||||||
|
|
||||||
export function AgentHeroAlt() {
|
export function AgentHeroAlt() {
|
||||||
@@ -8,28 +7,32 @@ export function AgentHeroAlt() {
|
|||||||
<div className="">
|
<div className="">
|
||||||
{/* Boxed container */}
|
{/* Boxed container */}
|
||||||
<div
|
<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"
|
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"
|
||||||
style={{ backgroundImage: "url('/images/agents.webp')", backgroundSize: "contain" }}
|
|
||||||
>
|
>
|
||||||
{/* Inner padding */}
|
{/* Inner padding */}
|
||||||
<div className="px-6 py-16 lg:py-24">
|
<div className="px-6 pt-4 pb-12 lg:py-24">
|
||||||
<div className="max-w-2xl lg:pl-6">
|
{/* 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>
|
<Eyebrow>MYCELIUM AGENTS - COMING IN 2026</Eyebrow>
|
||||||
<H3 as="h1" className="mt-4">
|
<H3 as="h1" className="mt-4">
|
||||||
Private, Sovereign and Distributed AI You Control
|
Private, Sovereign and Distributed AI You Control
|
||||||
</H3>
|
</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.
|
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.
|
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>
|
</P>
|
||||||
|
|
||||||
<div className="mt-10 flex items-center gap-x-6">
|
<div className="mt-10 flex items-center gap-x-6">
|
||||||
<Button href="#" variant="solid" color="cyan">
|
{/* TODO: Hero CTAs (Follow Development / Explore Docs) to be added when links are ready.
|
||||||
Follow Development
|
Previously two Buttons here with href="#". */}
|
||||||
</Button>
|
|
||||||
<Button href="#" variant="outline">
|
|
||||||
Explore Docs <span aria-hidden="true">→</span>
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -36,9 +36,9 @@ export function AgentPro() {
|
|||||||
<div className="w-full border-t border-l border-r border-gray-100" />
|
<div className="w-full border-t border-l border-r border-gray-100" />
|
||||||
|
|
||||||
{/* Intro Block */}
|
{/* 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">
|
<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
|
Advantages
|
||||||
</Eyebrow>
|
</Eyebrow>
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ export function AgentPro() {
|
|||||||
{item.title}
|
{item.title}
|
||||||
</h3>
|
</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}
|
{item.description}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Eyebrow, SectionHeader, P } from "@/components/Texts";
|
import { Eyebrow, P, CT, CP, H3} from "@/components/Texts";
|
||||||
import {
|
import {
|
||||||
CpuChipIcon,
|
CpuChipIcon,
|
||||||
GlobeAltIcon,
|
GlobeAltIcon,
|
||||||
@@ -63,19 +63,18 @@ export function AgentUsecase() {
|
|||||||
<div className="w-full border-t border-l border-r border-gray-100" />
|
<div className="w-full border-t border-l border-r border-gray-100" />
|
||||||
|
|
||||||
{/* Main framed section */}
|
{/* Main framed section */}
|
||||||
<div className="border border-t-0 border-b-0 border-gray-100 bg-white">
|
<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-4xl sm:text-center py-12">
|
<div className="mx-auto max-w-3xl sm:text-center px-6 lg:px-8">
|
||||||
{/* Intro block (from isIntro item) */}
|
{/* Intro block (from isIntro item) */}
|
||||||
{networkUseCases[0].isIntro && (
|
{networkUseCases[0].isIntro && (
|
||||||
<>
|
<>
|
||||||
<Eyebrow className="text-cyan-600">{networkUseCases[0].eyebrow}</Eyebrow>
|
<Eyebrow className="text-cyan-500">{networkUseCases[0].eyebrow}</Eyebrow>
|
||||||
<SectionHeader
|
<H3
|
||||||
as="h3"
|
className="mt-4 text-gray-900"
|
||||||
className="mt-4 text-gray-900 text-3xl lg:text-4xl"
|
|
||||||
>
|
>
|
||||||
{networkUseCases[0].title}
|
{networkUseCases[0].title}
|
||||||
</SectionHeader>
|
</H3>
|
||||||
<P className="mt-6 text-lg text-gray-600">
|
<P className="mt-4 text-lg text-gray-600">
|
||||||
{networkUseCases[0].description}
|
{networkUseCases[0].description}
|
||||||
</P>
|
</P>
|
||||||
</>
|
</>
|
||||||
@@ -85,7 +84,7 @@ export function AgentUsecase() {
|
|||||||
{/* Grid of features (excluding intro) */}
|
{/* Grid of features (excluding intro) */}
|
||||||
<ul
|
<ul
|
||||||
role="list"
|
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) => (
|
{networkUseCases.slice(1).map((item, idx) => (
|
||||||
<li
|
<li
|
||||||
@@ -94,20 +93,20 @@ export function AgentUsecase() {
|
|||||||
>
|
>
|
||||||
{/* Icon */}
|
{/* Icon */}
|
||||||
{item.icon && (
|
{item.icon && (
|
||||||
<div className="h-10 w-10 flex items-center justify-center rounded-xl bg-gray-100">
|
<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-600" />
|
<item.icon className="h-6 w-6 text-cyan-500" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Title */}
|
{/* Title */}
|
||||||
<p className="mt-6 text-lg font-semibold text-gray-900">
|
<CT className="leading-normal text-gray-900">
|
||||||
{item.title}
|
{item.title}
|
||||||
</p>
|
</CT>
|
||||||
|
|
||||||
{/* Description */}
|
{/* 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}
|
{item.description}
|
||||||
</p>
|
</CP>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export function CallToAction() {
|
|||||||
{/* ✅ Main boxed area */}
|
{/* ✅ Main boxed area */}
|
||||||
<div
|
<div
|
||||||
id="get-started"
|
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 */}
|
{/* ✅ Cyan Radial Glow */}
|
||||||
<svg
|
<svg
|
||||||
@@ -26,7 +26,7 @@ export function CallToAction() {
|
|||||||
cx={512}
|
cx={512}
|
||||||
cy={512}
|
cy={512}
|
||||||
fill="url(#mycelium-cyan-glow)"
|
fill="url(#mycelium-cyan-glow)"
|
||||||
fillOpacity="0.2"
|
fillOpacity="0.3"
|
||||||
/>
|
/>
|
||||||
<defs>
|
<defs>
|
||||||
<radialGradient id="mycelium-cyan-glow">
|
<radialGradient id="mycelium-cyan-glow">
|
||||||
@@ -41,38 +41,42 @@ export function CallToAction() {
|
|||||||
Start with Mycelium Today
|
Start with Mycelium Today
|
||||||
</h2>
|
</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.
|
The Agent Framework launches in H1 2026, but the foundation is ready now.
|
||||||
</p>
|
</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.
|
Use today’s components —models, storage, compute, and network— to deploy workloads, connect nodes, and prepare for the next generation of distributed AI.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{/* ✅ Two cards, stacked center with spacing */}
|
{/* ✅ Button row – same structure as homepage CTA */}
|
||||||
<div className="mt-8 flex flex-wrap justify-center gap-x-10 gap-y-8">
|
<div className="mt-10 flex flex-wrap justify-center items-center gap-x-6 gap-y-4">
|
||||||
<div className="flex flex-col items-center text-center max-w-xs">
|
<Button
|
||||||
<Button to="/deploy" variant="solid" color="cyan" className="mt-4">
|
as="a"
|
||||||
Deploy a Model
|
to="https://myceliumcloud.tf"
|
||||||
</Button>
|
variant="solid"
|
||||||
</div>
|
color="cyan"
|
||||||
|
target="_blank"
|
||||||
<div className="flex flex-col items-center text-center max-w-xs">
|
rel="noopener noreferrer"
|
||||||
<Button to="/host" as="a" variant="outline" color="white" className="mt-4">
|
>
|
||||||
Host a Node
|
Deploy a Model
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
|
||||||
|
<Button to="/nodes" variant="outline" color="white">
|
||||||
<div className="flex flex-col items-center text-center max-w-xs">
|
Host a Node
|
||||||
<a
|
</Button>
|
||||||
href="https://threefold.info/mycelium_network/docs/"
|
|
||||||
|
<Button
|
||||||
|
as="a"
|
||||||
|
to="https://threefold.info/mycelium_network/docs/"
|
||||||
|
variant="link"
|
||||||
|
color="white"
|
||||||
|
className="inline-flex items-center gap-1.5"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
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
|
Follow Development
|
||||||
<span aria-hidden="true">→</span>
|
<span aria-hidden="true">→</span>
|
||||||
</a>
|
</Button>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { useEffect, useMemo, useState } from 'react'
|
|||||||
import { useResponsiveCarousel } from '@/hooks/useResponsiveCarousel';
|
import { useResponsiveCarousel } from '@/hooks/useResponsiveCarousel';
|
||||||
import { motion, AnimatePresence } from 'framer-motion'
|
import { motion, AnimatePresence } from 'framer-motion'
|
||||||
import { wrap } from 'popmotion'
|
import { wrap } from 'popmotion'
|
||||||
import { Button } from '@/components/Button';
|
|
||||||
import { SectionHeader, P, Eyebrow, CP } from '@/components/Texts';
|
import { SectionHeader, P, Eyebrow, CP } from '@/components/Texts';
|
||||||
import { TypeAnimation } from 'react-type-animation'
|
import { TypeAnimation } from 'react-type-animation'
|
||||||
import { FadeIn } from '@/components/FadeIn';
|
import { FadeIn } from '@/components/FadeIn';
|
||||||
@@ -147,9 +146,8 @@ export function GallerySection() {
|
|||||||
repeat={0}
|
repeat={0}
|
||||||
/>
|
/>
|
||||||
</CP>
|
</CP>
|
||||||
<Button href="#" color="cyan" className="text-sm px-4 py-2 lg:text-base whitespace-nowrap">
|
{/* TODO: Desktop CTA (Start) button to be added when link target is defined.
|
||||||
Start
|
Previously: <Button href="#" color="cyan">Start</Button> */}
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -166,9 +164,8 @@ export function GallerySection() {
|
|||||||
repeat={0}
|
repeat={0}
|
||||||
/>
|
/>
|
||||||
</CP>
|
</CP>
|
||||||
<Button href="#" color="cyan" className="text-xs px-3 py-1.5 whitespace-nowrap">
|
{/* TODO: Mobile CTA (Start) button to be added when link target is defined.
|
||||||
Start
|
Previously: <Button href="#" color="cyan">Start</Button> */}
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</FadeIn>
|
</FadeIn>
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ export default function AgentCoordination({
|
|||||||
aria-label="Agent coordination and sovereign workflow management"
|
aria-label="Agent coordination and sovereign workflow management"
|
||||||
style={{ background: bg }}
|
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 */}
|
{/* background */}
|
||||||
<defs>
|
<defs>
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export default function DeterministicExecution({
|
|||||||
aria-label="Deterministic deployment and verifiable code execution"
|
aria-label="Deterministic deployment and verifiable code execution"
|
||||||
style={{ background: bg }}
|
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 */}
|
{/* background grid */}
|
||||||
<defs>
|
<defs>
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ export default function FungiStor({
|
|||||||
aria-label="FungiStor, a distributed long-term AI memory"
|
aria-label="FungiStor, a distributed long-term AI memory"
|
||||||
style={{ background: bg }}
|
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 */}
|
{/* Background grid */}
|
||||||
<defs>
|
<defs>
|
||||||
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
<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"
|
aria-label="HeroDB, active AI memory retrieval"
|
||||||
style={{ background: bg }}
|
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 */}
|
{/* Background grid */}
|
||||||
<defs>
|
<defs>
|
||||||
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ export default function MOSSandboxes({
|
|||||||
aria-label="MOS Secure Agent Sandboxes"
|
aria-label="MOS Secure Agent Sandboxes"
|
||||||
style={{ background: bg }}
|
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 */}
|
{/* BACKGROUND GRID */}
|
||||||
<defs>
|
<defs>
|
||||||
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
<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"
|
aria-label="Mycelium Mesh, a secure communication network"
|
||||||
style={{ background: bg }}
|
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 */}
|
{/* Background grid */}
|
||||||
<defs>
|
<defs>
|
||||||
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export function CallToAction() {
|
|||||||
{/* ✅ Main boxed area */}
|
{/* ✅ Main boxed area */}
|
||||||
<div
|
<div
|
||||||
id="get-started"
|
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 */}
|
{/* ✅ Cyan Radial Glow */}
|
||||||
<svg
|
<svg
|
||||||
@@ -26,7 +26,7 @@ export function CallToAction() {
|
|||||||
cx={512}
|
cx={512}
|
||||||
cy={512}
|
cy={512}
|
||||||
fill="url(#mycelium-cyan-glow)"
|
fill="url(#mycelium-cyan-glow)"
|
||||||
fillOpacity="0.2"
|
fillOpacity="0.3"
|
||||||
/>
|
/>
|
||||||
<defs>
|
<defs>
|
||||||
<radialGradient id="mycelium-cyan-glow">
|
<radialGradient id="mycelium-cyan-glow">
|
||||||
@@ -52,13 +52,21 @@ export function CallToAction() {
|
|||||||
{/* ✅ Two cards, stacked center with spacing */}
|
{/* ✅ Two cards, stacked center with spacing */}
|
||||||
<div className="mt-10 flex flex-wrap justify-center gap-x-10 gap-y-8">
|
<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">
|
<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
|
Host a Node
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col items-center text-center max-w-xs">
|
<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
|
Start Deploying
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</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">
|
<div className="relative mx-auto max-w-7xl border border-t-0 border-b-0 border-gray-800 bg-[#111111] py-12">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="mx-auto max-w-4xl sm:text-center">
|
<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">
|
<H3 className="text-3xl lg:text-4xl font-medium tracking-tight text-white">
|
||||||
How Mycelium Cloud Works
|
How Mycelium Cloud Works
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export function CloudBluePrint() {
|
|||||||
<div className="max-w-7xl bg-white mx-auto py-12 border border-t-0 border-b-0 border-gray-100">
|
<div className="max-w-7xl bg-white mx-auto py-12 border border-t-0 border-b-0 border-gray-100">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="mx-auto max-w-4xl sm:text-center">
|
<div className="mx-auto max-w-4xl sm:text-center">
|
||||||
<Eyebrow className="text-cyan-500">Featured Blueprint</Eyebrow>
|
<Eyebrow className="text-cyan-400">Featured Blueprint</Eyebrow>
|
||||||
|
|
||||||
<H3 className="text-3xl lg:text-4xl font-medium tracking-tight text-gray-900 mt-2">
|
<H3 className="text-3xl lg:text-4xl font-medium tracking-tight text-gray-900 mt-2">
|
||||||
Your Personal Sovereign Cloud Workspace
|
Your Personal Sovereign Cloud Workspace
|
||||||
|
|||||||
@@ -254,8 +254,8 @@ function CloudFeaturesDesktop() {
|
|||||||
className={clsx(
|
className={clsx(
|
||||||
'relative rounded-2xl outline-2 transition-all duration-300 ease-in-out hover:scale-105 hover:bg-gray-800/30 ml-16',
|
'relative rounded-2xl outline-2 transition-all duration-300 ease-in-out hover:scale-105 hover:bg-gray-800/30 ml-16',
|
||||||
selectedIndex === featureIndex
|
selectedIndex === featureIndex
|
||||||
? 'outline-cyan-500'
|
? 'outline-cyan-400'
|
||||||
: 'outline-transparent hover:outline-cyan-500',
|
: 'outline-transparent hover:outline-cyan-400',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{featureIndex === selectedIndex && (
|
{featureIndex === selectedIndex && (
|
||||||
|
|||||||
@@ -153,8 +153,8 @@ function CloudFeaturesDesktop() {
|
|||||||
className={clsx(
|
className={clsx(
|
||||||
'relative rounded-2xl outline-2 transition-all duration-300 ease-in-out hover:scale-105 hover:bg-gray-100',
|
'relative rounded-2xl outline-2 transition-all duration-300 ease-in-out hover:scale-105 hover:bg-gray-100',
|
||||||
selectedIndex === featureIndex
|
selectedIndex === featureIndex
|
||||||
? 'outline-cyan-500'
|
? 'outline-cyan-400'
|
||||||
: 'outline-transparent hover:outline-cyan-500',
|
: 'outline-transparent hover:outline-cyan-400',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{featureIndex === selectedIndex && (
|
{featureIndex === selectedIndex && (
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
import { H3, Eyebrow } from "@/components/Texts"
|
import { H3, Eyebrow, P } from "@/components/Texts"
|
||||||
import { Button } from "@/components/Button"
|
import { Button } from "@/components/Button"
|
||||||
|
|
||||||
export function CloudHeroNew({ onGetStartedClick = () => {} }: { onGetStartedClick?: () => void }) {
|
export function CloudHeroNew() {
|
||||||
return (
|
return (
|
||||||
<div className="">
|
<div className="">
|
||||||
{/* Boxed container */}
|
{/* Boxed container */}
|
||||||
<div
|
<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"
|
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"
|
||||||
style={{ backgroundImage: "url('/images/cloudhero4.webp')", backgroundSize: "contain" }}
|
|
||||||
>
|
>
|
||||||
{/* Inner padding */}
|
{/* 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">
|
<div className="max-w-2xl lg:pl-6">
|
||||||
<Eyebrow>
|
<Eyebrow>
|
||||||
MYCELIUM CLOUD
|
MYCELIUM CLOUD
|
||||||
@@ -18,30 +24,36 @@ export function CloudHeroNew({ onGetStartedClick = () => {} }: { onGetStartedCli
|
|||||||
<H3 className="mt-4">
|
<H3 className="mt-4">
|
||||||
Sovereign Edge Cloud Infrastructure
|
Sovereign Edge Cloud Infrastructure
|
||||||
</H3>
|
</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.
|
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,
|
The Mycelium Cloud runs on a distributed grid of independent nodes,
|
||||||
delivering secure, scalable performance wherever your users or data live.
|
delivering secure, scalable performance wherever your users or data live.
|
||||||
</p>
|
</P>
|
||||||
<div className="mt-10 flex items-center gap-x-6">
|
<div className="mt-10 flex items-center gap-x-6">
|
||||||
<Button
|
<Button
|
||||||
onClick={onGetStartedClick}
|
as="a"
|
||||||
|
to="https://myceliumcloud.tf"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color="cyan"
|
color="cyan"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
Deploy Workloads
|
Deploy Workloads
|
||||||
</Button>
|
</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>
|
Explore Docs <span aria-hidden="true">→</span>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</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="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 bg-transparent mx-auto py-6 border border-t-0 border-b-0 border-gray-100"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -79,6 +79,18 @@ export function CloudIntro() {
|
|||||||
const current = tabs.find((t) => t.id === active)!.content;
|
const current = tabs.find((t) => t.id === active)!.content;
|
||||||
const currentButtons = tabButtons[active as keyof typeof tabButtons];
|
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 (
|
return (
|
||||||
<section className="relative w-full bg-[#121212] overflow-hidden">
|
<section className="relative w-full bg-[#121212] overflow-hidden">
|
||||||
{/* Top Spacing Border */}
|
{/* Top Spacing Border */}
|
||||||
@@ -95,7 +107,7 @@ export function CloudIntro() {
|
|||||||
|
|
||||||
<H3 color="white">What You Can Run on Mycelium Cloud</H3>
|
<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
|
Host nodes, deploy workloads, or build private AI systems all on
|
||||||
infrastructure you own and control. Mycelium gives you scalable compute,
|
infrastructure you own and control. Mycelium gives you scalable compute,
|
||||||
secure storage, and sovereign orchestration without depending on
|
secure storage, and sovereign orchestration without depending on
|
||||||
@@ -126,7 +138,7 @@ export function CloudIntro() {
|
|||||||
<button
|
<button
|
||||||
key={tab.id}
|
key={tab.id}
|
||||||
onClick={() => setActive(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
|
active === tab.id
|
||||||
? "border-b-2 border-cyan-500 text-white"
|
? "border-b-2 border-cyan-500 text-white"
|
||||||
: "text-gray-400 hover:text-white"
|
: "text-gray-400 hover:text-white"
|
||||||
@@ -140,20 +152,20 @@ export function CloudIntro() {
|
|||||||
{/* Tab Content */}
|
{/* Tab Content */}
|
||||||
<div className="mt-6 space-y-6">
|
<div className="mt-6 space-y-6">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-lg font-medium text-white">{current.item}</p>
|
<p className="text-lg lg:text-xl font-medium text-white">{current.item}</p>
|
||||||
<p className="mt-2 text-base text-gray-400 leading-relaxed">
|
<p className="mt-2 text-base text-gray-300 leading-relaxed">
|
||||||
{current.desc}
|
{current.desc}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-4 space-y-2">
|
<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
|
Key capabilities
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul className="space-y-2">
|
<ul className="space-y-2">
|
||||||
{current.bullets.map((b, i) => (
|
{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>
|
<span className="text-cyan-500">•</span>
|
||||||
{b}
|
{b}
|
||||||
</li>
|
</li>
|
||||||
@@ -164,17 +176,25 @@ export function CloudIntro() {
|
|||||||
{currentButtons && (
|
{currentButtons && (
|
||||||
<div className="mt-8 flex flex-wrap gap-4">
|
<div className="mt-8 flex flex-wrap gap-4">
|
||||||
<Button
|
<Button
|
||||||
to="#"
|
as={primaryLinks[active] ? "a" : undefined}
|
||||||
|
to={primaryLinks[active] ?? "#"}
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color="cyan"
|
color="cyan"
|
||||||
|
{...(primaryLinks[active]
|
||||||
|
? { target: "_blank", rel: "noopener noreferrer" }
|
||||||
|
: {})}
|
||||||
>
|
>
|
||||||
{currentButtons.primary}
|
{currentButtons.primary}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
to="#"
|
as={secondaryLinks[active] ? "a" : undefined}
|
||||||
|
to={secondaryLinks[active] ?? "#"}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
color="white"
|
color="white"
|
||||||
|
{...(secondaryLinks[active]
|
||||||
|
? { target: "_blank", rel: "noopener noreferrer" }
|
||||||
|
: {})}
|
||||||
>
|
>
|
||||||
{currentButtons.secondary}
|
{currentButtons.secondary}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ export function CloudPros() {
|
|||||||
<div className="w-full border-t border-l border-r border-gray-100" />
|
<div className="w-full border-t border-l border-r border-gray-100" />
|
||||||
|
|
||||||
{/* Intro Block */}
|
{/* 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">
|
<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-400">
|
||||||
Cloud Advantages
|
Cloud Advantages
|
||||||
</Eyebrow>
|
</Eyebrow>
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ export function CloudPros() {
|
|||||||
{item.title}
|
{item.title}
|
||||||
</h3>
|
</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}
|
{item.description}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export function CloudUseCases() {
|
|||||||
<div className="max-w-7xl bg-white mx-auto py-12 border border-t-0 border-b-0 border-gray-100">
|
<div className="max-w-7xl bg-white mx-auto py-12 border border-t-0 border-b-0 border-gray-100">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="mx-auto max-w-4xl sm:text-center">
|
<div className="mx-auto max-w-4xl sm:text-center">
|
||||||
<Eyebrow className="text-cyan-500">USE CASES</Eyebrow>
|
<Eyebrow className="text-cyan-400">USE CASES</Eyebrow>
|
||||||
|
|
||||||
<H3 className="text-3xl lg:text-4xl font-medium tracking-tight text-gray-900">
|
<H3 className="text-3xl lg:text-4xl font-medium tracking-tight text-gray-900">
|
||||||
Built for intelligent workloads across every edge.
|
Built for intelligent workloads across every edge.
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export function CallToAction() {
|
|||||||
{/* ✅ Main boxed area */}
|
{/* ✅ Main boxed area */}
|
||||||
<div
|
<div
|
||||||
id="get-started"
|
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 */}
|
{/* ✅ Cyan Radial Glow */}
|
||||||
<svg
|
<svg
|
||||||
@@ -26,7 +26,7 @@ export function CallToAction() {
|
|||||||
cx={512}
|
cx={512}
|
||||||
cy={512}
|
cy={512}
|
||||||
fill="url(#mycelium-cyan-glow)"
|
fill="url(#mycelium-cyan-glow)"
|
||||||
fillOpacity="0.2"
|
fillOpacity="0.3"
|
||||||
/>
|
/>
|
||||||
<defs>
|
<defs>
|
||||||
<radialGradient id="mycelium-cyan-glow">
|
<radialGradient id="mycelium-cyan-glow">
|
||||||
@@ -43,7 +43,7 @@ export function CallToAction() {
|
|||||||
Choose How You Want to Start
|
Choose How You Want to Start
|
||||||
</h2>
|
</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.
|
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.
|
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 { Container } from '@/components/Container'
|
||||||
import { Eyebrow, H3, P } from '@/components/Texts'
|
import { Eyebrow, H3, P } from '@/components/Texts'
|
||||||
import { Button } from '@/components/Button'
|
|
||||||
|
|
||||||
const capabilities = [
|
const capabilities = [
|
||||||
{
|
{
|
||||||
@@ -76,14 +75,8 @@ export function ComputeCapabilities() {
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{/* Button section */}
|
{/* Button section */}
|
||||||
<div className="mx-auto mt-12 flex justify-center gap-6">
|
{/* TODO: CTA buttons (Get Started / Explore Docs) to be re-enabled when real links are available.
|
||||||
<Button variant="solid" color="cyan" href="#">
|
Previously rendered here as two Buttons with href="#". */}
|
||||||
Get Started
|
|
||||||
</Button>
|
|
||||||
<Button variant="outline" color="white" href="#">
|
|
||||||
Explore Docs
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -78,12 +78,8 @@ export function ComputeCapabilitiesNew() {
|
|||||||
|
|
||||||
{/* Arrows inside first card */}
|
{/* Arrows inside first card */}
|
||||||
<div className="flex items-center gap-x-4 mt-2">
|
<div className="flex items-center gap-x-4 mt-2">
|
||||||
<a
|
{/* TODO: Intro card CTA (Learn more) to be added here when destination is defined.
|
||||||
href="#"
|
Previously: <a href="#" className="inline-flex items-center ...">Learn more →</a> */}
|
||||||
className="inline-flex items-center gap-1 text-cyan-400 hover:text-cyan-300 text-sm font-medium mr-auto"
|
|
||||||
>
|
|
||||||
Learn more →
|
|
||||||
</a>
|
|
||||||
<button
|
<button
|
||||||
onClick={scrollLeft}
|
onClick={scrollLeft}
|
||||||
className="h-8 w-8 flex items-center justify-center border border-gray-800 rounded-md hover:border-cyan-500 transition-colors"
|
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
|
Get started
|
||||||
</Button>
|
</Button>
|
||||||
<Button to="#" variant="outline">
|
{/* TODO: Secondary CTA (Documentation) link to be wired when docs route is ready.
|
||||||
Documentation <span aria-hidden="true">→</span>
|
Previously: <Button to="#" variant="outline">Documentation →</Button> */}
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -36,8 +36,12 @@ const features = [
|
|||||||
|
|
||||||
export function DevHub() {
|
export function DevHub() {
|
||||||
return (
|
return (
|
||||||
<div className="bg-[#121212] py-24 sm:py-32">
|
<section className="bg-[#121212] w-full max-w-8xl mx-auto">
|
||||||
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
{/* 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="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">
|
<div className="col-span-2">
|
||||||
<h2 className="mb-2 text-base font-semibold leading-7 text-cyan-500">Get Started</h2>
|
<h2 className="mb-2 text-base font-semibold leading-7 text-cyan-500">Get Started</h2>
|
||||||
@@ -64,6 +68,10 @@ export function DevHub() {
|
|||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</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() {
|
export function DownloadHero() {
|
||||||
return (
|
return (
|
||||||
<div className="py-16 sm:py-32">
|
<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">
|
<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">
|
<div className="mx-auto max-w-2xl lg:mx-0">
|
||||||
<motion.h2
|
<motion.h2
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ duration: 0.5 }}
|
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
|
Download Mycelium Network
|
||||||
</motion.h2>
|
</motion.h2>
|
||||||
@@ -55,7 +55,7 @@ export function DownloadHero() {
|
|||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ duration: 0.5, delay: 0.2 }}
|
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?{' '}
|
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
|
<a
|
||||||
@@ -68,8 +68,9 @@ export function DownloadHero() {
|
|||||||
</a>
|
</a>
|
||||||
</motion.p>
|
</motion.p>
|
||||||
</div>
|
</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) => (
|
{features.map((feature) => (
|
||||||
<div
|
<div
|
||||||
key={feature.name}
|
key={feature.name}
|
||||||
@@ -99,6 +100,10 @@ export function DownloadHero() {
|
|||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</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 */}
|
{/* ✅ Main boxed area */}
|
||||||
<div
|
<div
|
||||||
id="get-started"
|
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 */}
|
{/* ✅ Cyan Radial Glow */}
|
||||||
<svg
|
<svg
|
||||||
@@ -26,7 +26,7 @@ export function CallToAction() {
|
|||||||
cx={512}
|
cx={512}
|
||||||
cy={512}
|
cy={512}
|
||||||
fill="url(#mycelium-cyan-glow)"
|
fill="url(#mycelium-cyan-glow)"
|
||||||
fillOpacity="0.2"
|
fillOpacity="0.3"
|
||||||
/>
|
/>
|
||||||
<defs>
|
<defs>
|
||||||
<radialGradient id="mycelium-cyan-glow">
|
<radialGradient id="mycelium-cyan-glow">
|
||||||
@@ -43,7 +43,7 @@ export function CallToAction() {
|
|||||||
Choose How You Want to Start
|
Choose How You Want to Start
|
||||||
</h2>
|
</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.
|
Use GPUs through Mycelium Cloud, or contribute GPU nodes to the mesh and run your own workloads.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ export function GpuCapabilities() {
|
|||||||
<div className="flex items-center gap-x-4 mt-3">
|
<div className="flex items-center gap-x-4 mt-3">
|
||||||
<a
|
<a
|
||||||
href="#"
|
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 →
|
Learn more →
|
||||||
</a>
|
</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">
|
<div className="relative mx-auto max-w-7xl border border-t-0 border-b-0 border-gray-800 bg-[#111111] py-12">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="mx-auto max-w-3xl text-center">
|
<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
|
PLATFORM OVERVIEW
|
||||||
</Eyebrow>
|
</Eyebrow>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { Container } from '@/components/Container'
|
import { Container } from '@/components/Container'
|
||||||
import { Button } from '@/components/Button'
|
import { Button } from '@/components/Button'
|
||||||
import { H3, P } from '@/components/Texts'
|
import { H3, P } from '@/components/Texts'
|
||||||
@@ -27,7 +26,7 @@ export function CallToAction() {
|
|||||||
cx={512}
|
cx={512}
|
||||||
cy={512}
|
cy={512}
|
||||||
fill="url(#mycelium-cyan-glow)"
|
fill="url(#mycelium-cyan-glow)"
|
||||||
fillOpacity="0.2"
|
fillOpacity="0.3"
|
||||||
/>
|
/>
|
||||||
<defs>
|
<defs>
|
||||||
<radialGradient id="mycelium-cyan-glow">
|
<radialGradient id="mycelium-cyan-glow">
|
||||||
@@ -43,30 +42,33 @@ export function CallToAction() {
|
|||||||
Use the Mycelium Stack Your Way
|
Use the Mycelium Stack Your Way
|
||||||
</H3>
|
</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.
|
Deploy infrastructure, run workloads, connect environments, and build distributed AI systems, all on one network designed for autonomy and control.
|
||||||
</P>
|
</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.
|
Start wherever you are. Scale on your own terms.
|
||||||
</P>
|
</P>
|
||||||
|
|
||||||
<div className="mt-10 flex flex-wrap justify-center items-center gap-x-6 gap-y-4">
|
<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
|
Join the Network
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
to="/cloud"
|
as="a"
|
||||||
|
to="https://myceliumcloud.tf"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
color="white"
|
color="white"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
Deploy in Cloud
|
Deploy in Cloud
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Link to="/nodes" className="text-cyan-400 hover:text-cyan-300 transition-colors">
|
<Button to="/nodes" variant="link" color="white">
|
||||||
Host a Node →
|
Host a Node →
|
||||||
</Link>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const deterministicCards = [
|
|||||||
title: "No central servers.",
|
title: "No central servers.",
|
||||||
description:
|
description:
|
||||||
"Your devices form a distributed network, eliminating reliance on centralized data centers.",
|
"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",
|
colSpan: "lg:col-span-3",
|
||||||
rowSpan: "lg:row-span-1",
|
rowSpan: "lg:row-span-1",
|
||||||
rounded: "lg:rounded-tr-4xl max-lg:rounded-t-4xl",
|
rounded: "lg:rounded-tr-4xl max-lg:rounded-t-4xl",
|
||||||
@@ -35,7 +35,7 @@ const deterministicCards = [
|
|||||||
title: "No data extraction.",
|
title: "No data extraction.",
|
||||||
description:
|
description:
|
||||||
"You own your data. Run services and AI models on your own devices, ensuring privacy and control.",
|
"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",
|
colSpan: "lg:col-span-2",
|
||||||
rowSpan: "lg:row-span-1",
|
rowSpan: "lg:row-span-1",
|
||||||
rounded: "lg:rounded-bl-4xl max-lg:rounded-b-4xl",
|
rounded: "lg:rounded-bl-4xl max-lg:rounded-b-4xl",
|
||||||
@@ -97,7 +97,7 @@ export function HomeArchitecture() {
|
|||||||
</div>
|
</div>
|
||||||
</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">
|
<div className="px-8 pt-4 pb-6">
|
||||||
|
|||||||
@@ -1,37 +1,50 @@
|
|||||||
import { H3, H5, Eyebrow } from "@/components/Texts"
|
import { H3, H5, Eyebrow } from "@/components/Texts"
|
||||||
import { Button } from "@/components/Button"
|
import { Button } from "@/components/Button"
|
||||||
|
|
||||||
export function HomeAurora({ onGetStartedClick }: { onGetStartedClick: () => void }) {
|
export function HomeAurora() {
|
||||||
return (
|
return (
|
||||||
<div className="px-4">
|
<div className="px-4">
|
||||||
{/* Boxed container */}
|
{/* Boxed container */}
|
||||||
<div
|
<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"
|
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')]"
|
||||||
style={{ backgroundImage: "url('/images/hero11.webp')" }}
|
|
||||||
>
|
>
|
||||||
{/* Inner padding */}
|
{/* 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">
|
<div className="max-w-2xl lg:pl-6">
|
||||||
<Eyebrow> Project MYCELIUM</Eyebrow>
|
<Eyebrow> Project MYCELIUM</Eyebrow>
|
||||||
<H3 className="mt-4">
|
<H3 className="mt-4">
|
||||||
Private, Distributed Infrastructure Built
|
Secure, Distributed Infrastructure Built
|
||||||
|
<br />
|
||||||
for Digital Sovereignty
|
for Digital Sovereignty
|
||||||
</H3>
|
</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
|
Run your apps, data, and intelligence on infrastructure that belongs to you
|
||||||
</H5>
|
</H5>
|
||||||
|
|
||||||
<div className="mt-8 flex items-center gap-x-6">
|
<div className="mt-8 flex items-center gap-x-6">
|
||||||
<Button
|
<Button
|
||||||
|
to="/nodes"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color="cyan"
|
color="cyan"
|
||||||
onClick={onGetStartedClick}
|
|
||||||
>
|
>
|
||||||
Start Hosting
|
Start Hosting
|
||||||
</Button>
|
</Button>
|
||||||
<Button to="#" variant="outline">
|
<Button
|
||||||
Deploy in Cloud →
|
as="a"
|
||||||
|
to="https://myceliumcloud.tf"
|
||||||
|
variant="outline"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
Deploy in Cloud
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -30,14 +30,14 @@ export function HomeDesign() {
|
|||||||
return (
|
return (
|
||||||
<section className="w-full max-w-8xl mx-auto bg-white">
|
<section className="w-full max-w-8xl mx-auto bg-white">
|
||||||
{/* Top spacing line */}
|
{/* Top spacing line */}
|
||||||
<div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 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-200" />
|
<div className="w-full border border-l border-r border-gray-100" />
|
||||||
|
|
||||||
{/* Content */}
|
{/* 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 */}
|
{/* Centered intro */}
|
||||||
<div className="px-6 pt-12 pb-4 text-center max-w-4xl mx-auto ">
|
<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
|
Who's it For
|
||||||
</Eyebrow>
|
</Eyebrow>
|
||||||
|
|
||||||
@@ -50,11 +50,11 @@ export function HomeDesign() {
|
|||||||
</P>
|
</P>
|
||||||
</div>
|
</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) => (
|
{benefits.map((item) => (
|
||||||
<div
|
<div
|
||||||
key={item.id}
|
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 */}
|
{/* Image on the LEFT */}
|
||||||
<img
|
<img
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export function WorldMap() {
|
|||||||
>
|
>
|
||||||
<DarkCard>
|
<DarkCard>
|
||||||
<div><CT color="light" className="uppercase tracking-wide ">CORES</CT></div>
|
<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">
|
<CP color="light" className="mt-2 text-sm">
|
||||||
Total Central Processing Unit Cores available on the grid.
|
Total Central Processing Unit Cores available on the grid.
|
||||||
</CP>
|
</CP>
|
||||||
@@ -83,7 +83,7 @@ export function WorldMap() {
|
|||||||
>
|
>
|
||||||
<DarkCard>
|
<DarkCard>
|
||||||
<div><CT color="light" className="uppercase tracking-wide">NODES</CT></div>
|
<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">
|
<CP color="light" className="mt-2 text-sm">
|
||||||
Total number of nodes on the grid.
|
Total number of nodes on the grid.
|
||||||
</CP>
|
</CP>
|
||||||
@@ -99,7 +99,7 @@ export function WorldMap() {
|
|||||||
>
|
>
|
||||||
<DarkCard>
|
<DarkCard>
|
||||||
<div><CT color="light" className="uppercase tracking-wide">SSD CAPACITY</CT></div>
|
<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">
|
<CP color="light" className="mt-2 text-sm">
|
||||||
Total GB amount of storage (SSD, HDD, & RAM) on the grid.
|
Total GB amount of storage (SSD, HDD, & RAM) on the grid.
|
||||||
</CP>
|
</CP>
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export function HomeMap() {
|
|||||||
Mycelium runs on nodes hosted by people and organizations around the world.
|
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.
|
Each node adds compute, storage, and bandwidth, expanding the network’s capacity and resilience.
|
||||||
</P>
|
</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.
|
You can share your idle resources and earn rewards when they are used.
|
||||||
Configure it once. Your node takes over from there.
|
Configure it once. Your node takes over from there.
|
||||||
</P>
|
</P>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import { useRef } from 'react'
|
|
||||||
import { AnimatedSection } from '../../components/AnimatedSection'
|
import { AnimatedSection } from '../../components/AnimatedSection'
|
||||||
import { CallToAction } from './CallToAction'
|
import { CallToAction } from './CallToAction'
|
||||||
import { HomeTab } from './HomeTab'
|
import { HomeTab } from './HomeTab'
|
||||||
@@ -8,18 +7,56 @@ import { HomeAurora } from './HomeAurora'
|
|||||||
import { HomeArchitecture } from './HomeArchitecture';
|
import { HomeArchitecture } from './HomeArchitecture';
|
||||||
import { HomeDesign } from './HomeDesign';
|
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() {
|
export default function HomePage() {
|
||||||
const sliderRef = useRef<HTMLDivElement>(null)
|
|
||||||
|
|
||||||
const handleScrollToSlider = () => {
|
|
||||||
sliderRef.current?.scrollIntoView({ behavior: 'smooth' })
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AnimatedSection>
|
<AnimatedSection>
|
||||||
<HomeAurora onGetStartedClick={handleScrollToSlider} />
|
<HomeAurora />
|
||||||
</AnimatedSection>
|
</AnimatedSection>
|
||||||
|
|
||||||
<AnimatedSection>
|
<AnimatedSection>
|
||||||
@@ -31,16 +68,16 @@ export default function HomePage() {
|
|||||||
</AnimatedSection>
|
</AnimatedSection>
|
||||||
|
|
||||||
<AnimatedSection>
|
<AnimatedSection>
|
||||||
<HomeMap />
|
<LazyHomeMapSection />
|
||||||
</AnimatedSection>
|
</AnimatedSection>
|
||||||
|
|
||||||
<AnimatedSection>
|
|
||||||
<HomeDesign />
|
<HomeDesign />
|
||||||
</AnimatedSection>
|
|
||||||
|
|
||||||
<AnimatedSection>
|
|
||||||
|
|
||||||
<CallToAction />
|
<CallToAction />
|
||||||
</AnimatedSection>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export function HomeTab() {
|
|||||||
<section className="w-full max-w-8xl mx-auto bg-transparent">
|
<section className="w-full max-w-8xl mx-auto bg-transparent">
|
||||||
|
|
||||||
{/* Top section separators */}
|
{/* 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" />
|
<div className="w-full border-t border-l border-r border-gray-100" />
|
||||||
|
|
||||||
{/* Main content */}
|
{/* 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">
|
<div className="mt-10 grid gap-4 sm:mt-16 lg:grid-cols-3 lg:grid-rows-2 pb-12">
|
||||||
|
|
||||||
{/* ------------------ LEFT TALL CARD ------------------ */}
|
{/* ------------------ 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="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">
|
<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>
|
<h3 className="text-sm/4 font-semibold text-cyan-500">LIVE</h3>
|
||||||
@@ -50,13 +50,13 @@ export function HomeTab() {
|
|||||||
</div>
|
</div>
|
||||||
</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>
|
</Link>
|
||||||
|
|
||||||
{/* ------------------ MIDDLE TOP ------------------ */}
|
{/* ------------------ 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="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">
|
<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>
|
<h3 className="text-sm/4 font-semibold text-cyan-500">Coming Soon</h3>
|
||||||
@@ -75,13 +75,13 @@ export function HomeTab() {
|
|||||||
</div>
|
</div>
|
||||||
</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>
|
</Link>
|
||||||
|
|
||||||
{/* ------------------ MIDDLE BOTTOM ------------------ */}
|
{/* ------------------ 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="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">
|
<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>
|
<h3 className="text-sm/4 font-semibold text-cyan-500">Q1 2026</h3>
|
||||||
@@ -99,13 +99,13 @@ export function HomeTab() {
|
|||||||
</div>
|
</div>
|
||||||
</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>
|
</Link>
|
||||||
|
|
||||||
{/* ------------------ RIGHT TALL ------------------ */}
|
{/* ------------------ 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="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">
|
<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>
|
<h3 className="text-sm/4 font-semibold text-cyan-500">Early Access</h3>
|
||||||
@@ -126,7 +126,7 @@ export function HomeTab() {
|
|||||||
</div>
|
</div>
|
||||||
</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>
|
</Link>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ export default function NoCentral({
|
|||||||
aria-label="Distributed network illustration"
|
aria-label="Distributed network illustration"
|
||||||
style={{ background: bg }}
|
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 */}
|
{/* Background grid */}
|
||||||
<defs>
|
<defs>
|
||||||
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
<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
|
<motion.circle
|
||||||
cx={center.x}
|
cx={center.x}
|
||||||
cy={center.y}
|
cy={center.y}
|
||||||
r={18}
|
r={18}
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke="#FF4D4D"
|
stroke="#8B8B8B"
|
||||||
strokeWidth={3}
|
strokeWidth={3}
|
||||||
strokeDasharray="6 4"
|
strokeDasharray="6 4"
|
||||||
initial={{ scale: 0, opacity: 0 }}
|
initial={{ scale: 0, opacity: 0 }}
|
||||||
@@ -225,7 +225,7 @@ export default function NoCentral({
|
|||||||
/>
|
/>
|
||||||
<motion.path
|
<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}`}
|
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}
|
strokeWidth={3}
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
initial={{ opacity: 0, scale: 0 }}
|
initial={{ opacity: 0, scale: 0 }}
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ export default function NoControl({
|
|||||||
{/* Cross mark over center node (control denied) */}
|
{/* Cross mark over center node (control denied) */}
|
||||||
<motion.path
|
<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}`}
|
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}
|
strokeWidth={3}
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
initial={{ opacity: 0, scale: 0 }}
|
initial={{ opacity: 0, scale: 0 }}
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ export default function NoExtraction({
|
|||||||
cx={center.x + 130}
|
cx={center.x + 130}
|
||||||
cy={center.y - 10}
|
cy={center.y - 10}
|
||||||
r={10}
|
r={10}
|
||||||
fill="#FF4D4D"
|
fill="#8B8B8B"
|
||||||
initial={{ scale: 0, opacity: 0 }}
|
initial={{ scale: 0, opacity: 0 }}
|
||||||
animate={{ scale: [0, 1.2, 0.8], opacity: [0, 1, 0] }}
|
animate={{ scale: [0, 1.2, 0.8], opacity: [0, 1, 0] }}
|
||||||
transition={{
|
transition={{
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ type Props = {
|
|||||||
gridStroke?: string;
|
gridStroke?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const W = 720; // 4:3
|
const W = 760; // match aspect ratio closer to other home animations
|
||||||
const H = 540; // 4:3
|
const H = 420; // align visual height with other cards
|
||||||
|
|
||||||
export default function NoSinglePoint({
|
export default function NoSinglePoint({
|
||||||
className,
|
className,
|
||||||
|
|||||||
@@ -19,7 +19,14 @@ export function HomeHero() {
|
|||||||
Start Hosting
|
Start Hosting
|
||||||
</Button>
|
</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>
|
Deploy in Cloud <span aria-hidden="true">→</span>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -39,8 +39,14 @@ export function HomeAurora({ onGetStartedClick }: { onGetStartedClick: () => voi
|
|||||||
>
|
>
|
||||||
Start Hosting
|
Start Hosting
|
||||||
</Button>
|
</Button>
|
||||||
<Button to="#" variant="outline">
|
<Button
|
||||||
Deploy in Cloud →
|
as="a"
|
||||||
|
to="https://myceliumcloud.tf"
|
||||||
|
variant="outline"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
Deploy in Cloud
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { Container } from '@/components/Container'
|
import { Container } from '@/components/Container'
|
||||||
import { Button } from "@/components/Button";
|
import { Button } from "@/components/Button";
|
||||||
|
|
||||||
@@ -14,7 +13,7 @@ export function CallToAction() {
|
|||||||
{/* ✅ Main boxed area */}
|
{/* ✅ Main boxed area */}
|
||||||
<div
|
<div
|
||||||
id="get-started"
|
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 */}
|
{/* ✅ Cyan Radial Glow */}
|
||||||
<svg
|
<svg
|
||||||
@@ -27,7 +26,7 @@ export function CallToAction() {
|
|||||||
cx={512}
|
cx={512}
|
||||||
cy={512}
|
cy={512}
|
||||||
fill="url(#mycelium-cyan-glow)"
|
fill="url(#mycelium-cyan-glow)"
|
||||||
fillOpacity="0.2"
|
fillOpacity="0.3"
|
||||||
/>
|
/>
|
||||||
<defs>
|
<defs>
|
||||||
<radialGradient id="mycelium-cyan-glow">
|
<radialGradient id="mycelium-cyan-glow">
|
||||||
@@ -44,7 +43,7 @@ export function CallToAction() {
|
|||||||
Choose How You Want to Connect
|
Choose How You Want to Connect
|
||||||
</h2>
|
</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
|
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.
|
Use the network to link environments, deploy workloads, or host nodes to strengthen the mesh and run on your own hardware.
|
||||||
</p>
|
</p>
|
||||||
@@ -56,16 +55,19 @@ Use the network to link environments, deploy workloads, or host nodes to strengt
|
|||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
to="/cloud"
|
as="a"
|
||||||
|
to="https://myceliumcloud.tf"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
color="white"
|
color="white"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
Deploy in Cloud
|
Deploy in Cloud
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Link to="/nodes" className="text-cyan-400 hover:text-cyan-300 transition-colors">
|
<Button to="/nodes" variant="link" color="white">
|
||||||
Host a Node →
|
Host a Node →
|
||||||
</Link>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -76,38 +76,45 @@ function BackgroundIllustration(props: React.ComponentPropsWithoutRef<'div'>) {
|
|||||||
|
|
||||||
export function Hero() {
|
export function Hero() {
|
||||||
return (
|
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>
|
<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="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">
|
<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">
|
<Eyebrow className="mb-4">
|
||||||
MYCELIUM NETWORK
|
MYCELIUM NETWORK
|
||||||
</Eyebrow>
|
</Eyebrow>
|
||||||
<H3 className="mt-8 ">
|
<H3 className="mt-4">
|
||||||
The Network Stack for Private, Autonomous Networking
|
The Network Stack for Private, Autonomous Networking
|
||||||
</H3>
|
</H3>
|
||||||
<P className="mt-6 text-lg leading-tight text-gray-600 lg:text-xl lg:leading-normal">
|
<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.
|
Connect once. Get private networking, censorship-resistant publishing, and on-network AI in one encrypted fabric.
|
||||||
</P>
|
</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.
|
Your Pod is your personal gateway to the network.
|
||||||
</P>
|
</P>
|
||||||
<div className="mt-8 flex flex-wrap gap-x-6 gap-y-4">
|
<div className="mt-8 flex flex-wrap gap-x-6 gap-y-4">
|
||||||
<Button to="/download" variant="solid" color="cyan">
|
<Button to="/download" variant="solid" color="cyan">
|
||||||
Get Started
|
Get Started
|
||||||
</Button>
|
</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
|
Explore Docs
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative mt-0 lg:mt-10 lg:col-span-5 lg:row-span-2 xl:col-span-6">
|
<div className="relative mt-8 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" />
|
<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 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="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
|
<img
|
||||||
src={phoneFrame}
|
src={phoneFrame}
|
||||||
alt="Mycelium application demo"
|
alt="Mycelium application demo"
|
||||||
className="mx-auto w-auto max-w-[366px]"
|
className="mx-auto w-full max-w-[366px] h-auto"
|
||||||
width={366}
|
width={366}
|
||||||
height={729}
|
height={729}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export function NetworkCapabilities() {
|
|||||||
One network for all your connectivity needs.
|
One network for all your connectivity needs.
|
||||||
</P>
|
</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.
|
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>
|
</P>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import windowsIcon from '@/images/windows.svg'
|
|||||||
import androidIcon from '@/images/android.svg'
|
import androidIcon from '@/images/android.svg'
|
||||||
import linuxIcon from '@/images/linux.svg'
|
import linuxIcon from '@/images/linux.svg'
|
||||||
|
|
||||||
import { CT, CP } from '@/components/Texts'
|
import { CT, CP, Eyebrow } from '@/components/Texts'
|
||||||
|
|
||||||
const features = [
|
const features = [
|
||||||
{
|
{
|
||||||
@@ -42,7 +42,7 @@ const features = [
|
|||||||
|
|
||||||
export function NetworkDownload() {
|
export function NetworkDownload() {
|
||||||
return (
|
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 */}
|
{/* ✅ 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="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-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">
|
<div className="mx-auto max-w-2xl lg:mx-0">
|
||||||
|
<Eyebrow color="accent">Get Started</Eyebrow>
|
||||||
<motion.h3
|
<motion.h3
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ duration: 0.5 }}
|
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
|
Download Mycelium Network
|
||||||
</motion.h3>
|
</motion.h3>
|
||||||
@@ -64,19 +65,11 @@ export function NetworkDownload() {
|
|||||||
transition={{ duration: 0.5, delay: 0.2 }}
|
transition={{ duration: 0.5, delay: 0.2 }}
|
||||||
className="mt-8 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?{' '}
|
Get Mycelium Network for Android, Windows, macOS, and iOS to securely connect, store, and interact with the decentralized network seamlessly and efficiently.
|
||||||
<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>
|
|
||||||
</motion.p>
|
</motion.p>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx-auto mt-8 max-w-2xl lg:mt-12 lg:max-w-none">
|
<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) => (
|
{features.map((feature) => (
|
||||||
<div
|
<div
|
||||||
key={feature.name}
|
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">
|
<div className="bg-[#121212] w-full max-w-7xl mx-auto border border-t-0 border-b-0 border-gray-800">
|
||||||
{/* Centered intro */}
|
{/* Centered intro */}
|
||||||
<div className="px-6 pt-12 pb-4 text-center max-w-4xl mx-auto ">
|
<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
|
WHY
|
||||||
</Eyebrow>
|
</Eyebrow>
|
||||||
|
|
||||||
<H3 className="mt-4 text-white">
|
<H3 className="mt-2 text-white">
|
||||||
Why It’s Revolutionary
|
Why It’s Revolutionary
|
||||||
</H3>
|
</H3>
|
||||||
|
|
||||||
|
|||||||
@@ -369,7 +369,7 @@ function FeaturesMobile() {
|
|||||||
<MobileFeatureTitle color="white" className="mt-6">
|
<MobileFeatureTitle color="white" className="mt-6">
|
||||||
{feature.name}
|
{feature.name}
|
||||||
</MobileFeatureTitle>
|
</MobileFeatureTitle>
|
||||||
<FeatureDescription color="secondary" className="mt-2">
|
<FeatureDescription className="mt- text-gray-200">
|
||||||
{feature.description}
|
{feature.description}
|
||||||
</FeatureDescription>
|
</FeatureDescription>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useId } from 'react'
|
import { useId } from 'react'
|
||||||
import { Container } from '@/components/Container'
|
import { Container } from '@/components/Container'
|
||||||
import { CP } from '@/components/Texts'
|
import { CP, H3, P, Eyebrow } from '@/components/Texts'
|
||||||
|
|
||||||
const features = [
|
const features = [
|
||||||
{
|
{
|
||||||
@@ -197,13 +197,13 @@ export function SecondaryFeatures() {
|
|||||||
|
|
||||||
<Container className="py-12 border border-t-0 border-b-0 border-gray-100">
|
<Container className="py-12 border border-t-0 border-b-0 border-gray-100">
|
||||||
<div className="mx-auto max-w-4xl sm:text-center">
|
<div className="mx-auto max-w-4xl sm:text-center">
|
||||||
<h2 className="text-base/7 font-semibold text-cyan-500">FEATURES</h2>
|
<Eyebrow className="text-cyan-500 uppercase tracking-[0.16em]">FEATURES</Eyebrow>
|
||||||
<p className="text-3xl lg:text-4xl font-medium tracking-tight text-gray-900">
|
<H3 className="mt-2 text-black">
|
||||||
Core Features
|
Core Features
|
||||||
</p>
|
</H3>
|
||||||
<p className="mt-6 text-lg text-gray-600">
|
<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.
|
The Mycelium Network is evolving with new features to support richer data movement, identity, and application connectivity across the mesh.
|
||||||
</p>
|
</P>
|
||||||
</div>
|
</div>
|
||||||
<ul
|
<ul
|
||||||
role="list"
|
role="list"
|
||||||
@@ -212,7 +212,7 @@ export function SecondaryFeatures() {
|
|||||||
{features.map((feature) => (
|
{features.map((feature) => (
|
||||||
<li
|
<li
|
||||||
key={feature.name}
|
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" />
|
<feature.icon className="h-8 w-8" />
|
||||||
<CP className="mt-6 font-semibold text-gray-900">
|
<CP className="mt-6 font-semibold text-gray-900">
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export function CallToAction() {
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
id="get-started"
|
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 */}
|
{/* ✅ Cyan Radial Glow */}
|
||||||
<svg
|
<svg
|
||||||
@@ -24,7 +24,7 @@ export function CallToAction() {
|
|||||||
cx={512}
|
cx={512}
|
||||||
cy={512}
|
cy={512}
|
||||||
fill="url(#mycelium-cyan-glow)"
|
fill="url(#mycelium-cyan-glow)"
|
||||||
fillOpacity="0.2"
|
fillOpacity="0.3"
|
||||||
/>
|
/>
|
||||||
<defs>
|
<defs>
|
||||||
<radialGradient id="mycelium-cyan-glow">
|
<radialGradient id="mycelium-cyan-glow">
|
||||||
@@ -39,13 +39,13 @@ export function CallToAction() {
|
|||||||
Join Mycelium Grid
|
Join Mycelium Grid
|
||||||
</h2>
|
</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
|
Be part of a global network that powers private, distributed
|
||||||
infrastructure. Host a node, contribute resources, and earn rewards
|
infrastructure. Host a node, contribute resources, and earn rewards
|
||||||
while expanding the sovereign digital grid.
|
while expanding the sovereign digital grid.
|
||||||
</p>
|
</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">
|
<div className="flex flex-col items-center text-center max-w-xs">
|
||||||
<Button to="/host" variant="solid" color="cyan" className="mt-4">
|
<Button to="/host" variant="solid" color="cyan" className="mt-4">
|
||||||
Join Mycelium
|
Join Mycelium
|
||||||
@@ -54,7 +54,7 @@ export function CallToAction() {
|
|||||||
|
|
||||||
<div className="flex flex-col items-center text-center max-w-xs">
|
<div className="flex flex-col items-center text-center max-w-xs">
|
||||||
<Button to="/docs" variant="outline" color="white" className="mt-4">
|
<Button to="/docs" variant="outline" color="white" className="mt-4">
|
||||||
Explore docs
|
Explore Docs
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { motion } from "framer-motion";
|
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";
|
import type { ComponentPropsWithoutRef } from "react";
|
||||||
|
|
||||||
type CircleIconProps = ComponentPropsWithoutRef<"svg">;
|
type CircleIconProps = ComponentPropsWithoutRef<"svg">;
|
||||||
@@ -62,14 +62,13 @@ export function NodeBenefits() {
|
|||||||
className="mx-auto max-w-5xl text-center"
|
className="mx-auto max-w-5xl text-center"
|
||||||
>
|
>
|
||||||
<Eyebrow color="accent">Host</Eyebrow>
|
<Eyebrow color="accent">Host</Eyebrow>
|
||||||
<SectionHeader
|
<H3
|
||||||
className="text-3xl font-medium tracking-tight"
|
className="mt-2 text-white"
|
||||||
color="light"
|
|
||||||
>
|
>
|
||||||
Benefits of Hosting Nodes
|
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
|
Hosting a node gives you private compute, contributes to the global
|
||||||
Mycelium infrastructure, and unlocks ways to earn from real network
|
Mycelium infrastructure, and unlocks ways to earn from real network
|
||||||
usage, all while keeping sovereignty and control.
|
usage, all while keeping sovereignty and control.
|
||||||
@@ -95,13 +94,13 @@ export function NodeBenefits() {
|
|||||||
delay: 0.3 + index * 0.15,
|
delay: 0.3 + index * 0.15,
|
||||||
ease: "easeOut",
|
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" />
|
<feature.icon className="mb-4 h-8 w-8 text-white" />
|
||||||
<CT as="span" className="text-left font-semibold" color="light">
|
<CT as="span" className="text-left font-semibold" color="light">
|
||||||
{feature.name}
|
{feature.name}
|
||||||
</CT>
|
</CT>
|
||||||
<CP className="mt-2 text-left text-gray-200">
|
<CP className="mt-2 text-left font-light text-gray-300">
|
||||||
{feature.description}
|
{feature.description}
|
||||||
</CP>
|
</CP>
|
||||||
</motion.li>
|
</motion.li>
|
||||||
|
|||||||
@@ -1,32 +1,38 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { Button } from '@/components/Button'
|
import { Button } from '@/components/Button'
|
||||||
import { Eyebrow, H3 } from '@/components/Texts'
|
import { Eyebrow, H3, P } from '@/components/Texts'
|
||||||
|
|
||||||
export function NodeHero() {
|
export function NodeHero() {
|
||||||
return (
|
return (
|
||||||
<div className="">
|
<div className="">
|
||||||
{/* Boxed container */}
|
{/* Boxed container */}
|
||||||
<div
|
<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"
|
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"
|
||||||
style={{ backgroundImage: "url('/images/gpuhero2.png')", backgroundSize: "contain" }}
|
|
||||||
>
|
>
|
||||||
{/* Inner padding */}
|
{/* 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">
|
<div className="max-w-2xl lg:pl-6">
|
||||||
<Eyebrow>MYCELIUM NODES</Eyebrow>
|
<Eyebrow>MYCELIUM NODES</Eyebrow>
|
||||||
<H3 as="h1" className="mt-4">
|
<H3 as="h1" className="mt-4">
|
||||||
Host a Node. Power the Network.
|
Host a Node. Power the Network.
|
||||||
</H3>
|
</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.
|
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">
|
<div className="mt-10 flex items-center gap-x-6">
|
||||||
<Button to="#node-getting-started" as="a" variant="solid" color="cyan">
|
<Button to="#node-getting-started" as="a" variant="solid" color="cyan">
|
||||||
How it works
|
How it works
|
||||||
</Button>
|
</Button>
|
||||||
<Button to="#node-architecture" as="a" variant="outline">
|
<Button to="#node-architecture" as="a" variant="outline">
|
||||||
Explore Docs <span aria-hidden="true">→</span>
|
Explore Docs
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { Eyebrow, SectionHeader, P } from "@/components/Texts";
|
import { Eyebrow, SectionHeader, P } from "@/components/Texts";
|
||||||
|
import { Button } from "@/components/Button";
|
||||||
import {
|
import {
|
||||||
QuestionMarkCircleIcon,
|
QuestionMarkCircleIcon,
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
@@ -96,7 +97,7 @@ export function NodeProducts() {
|
|||||||
</P>
|
</P>
|
||||||
</div>
|
</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 */}
|
{/* LEFT — TEXT AREA */}
|
||||||
@@ -106,7 +107,7 @@ export function NodeProducts() {
|
|||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ duration: 0.4 }}
|
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">
|
<h1 className="text-3xl font-semibold text-white">
|
||||||
{selectedNode.name}
|
{selectedNode.name}
|
||||||
@@ -168,29 +169,35 @@ export function NodeProducts() {
|
|||||||
{/* ------------------------ */}
|
{/* ------------------------ */}
|
||||||
{/* BUTTONS AREA */}
|
{/* BUTTONS AREA */}
|
||||||
{/* ------------------------ */}
|
{/* ------------------------ */}
|
||||||
<div className="mt-10 flex flex-col sm:flex-row gap-4">
|
<div className="mt-8 flex flex-col sm:flex-row gap-8">
|
||||||
|
|
||||||
{/* 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>
|
|
||||||
|
|
||||||
{/* Solid Cyan Button */}
|
{/* Solid Cyan Button */}
|
||||||
<a
|
<Button
|
||||||
href={selectedNode.buyUrl}
|
as="a"
|
||||||
|
to={selectedNode.buyUrl}
|
||||||
|
variant="solid"
|
||||||
|
color="cyan"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="flex-1 sm:flex-none text-center bg-cyan-600 hover:bg-cyan-700
|
className="flex-1 sm:flex-none text-center"
|
||||||
text-white px-8 py-3 rounded-lg font-medium transition"
|
|
||||||
>
|
>
|
||||||
Purchase Node
|
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>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@@ -204,20 +211,20 @@ export function NodeProducts() {
|
|||||||
initial={{ opacity: 0, scale: 0.92 }}
|
initial={{ opacity: 0, scale: 0.92 }}
|
||||||
animate={{ opacity: 1, scale: 1 }}
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
transition={{ duration: 0.35 }}
|
transition={{ duration: 0.35 }}
|
||||||
className="flex justify-center"
|
className="order-1 lg:order-2 flex justify-center"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={selectedNode.image}
|
src={selectedNode.image}
|
||||||
alt={selectedNode.name}
|
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>
|
</motion.div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{/* ✅ Bottom horizontal line with spacing */}
|
||||||
{/* Bottom border */}
|
<div className="w-full border-b border-gray-800" />
|
||||||
<div className="w-full border-b border-gray-800 bg-[#121212]" />
|
<div className="max-w-7xl bg-transparent mx-auto py-6 border border-t-0 border-b-0 border-gray-800"></div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Eyebrow, H3, P, Small, CT, CP } from "@/components/Texts";
|
|||||||
|
|
||||||
const cards = [
|
const cards = [
|
||||||
{
|
{
|
||||||
category: "Autonomous",
|
category: "AUTONOMY",
|
||||||
title: "Autonomous Operation",
|
title: "Autonomous Operation",
|
||||||
description: "Runs autonomously with no central control.",
|
description: "Runs autonomously with no central control.",
|
||||||
image: "/images/autonomous.png",
|
image: "/images/autonomous.png",
|
||||||
@@ -12,13 +12,13 @@ const cards = [
|
|||||||
innerRounded: "lg:rounded-tl-[calc(2rem+1px)]",
|
innerRounded: "lg:rounded-tl-[calc(2rem+1px)]",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: "Security",
|
category: "SECURITY",
|
||||||
title: "Encrypted by Default",
|
title: "Encrypted by Default",
|
||||||
description: "Fully encrypted and identity-based.",
|
description: "Fully encrypted and identity-based.",
|
||||||
image: "/images/encryptednode.png",
|
image: "/images/encryptednode.png",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: "Efficiency",
|
category: "EFFICIENCY",
|
||||||
title: "Energy Efficient",
|
title: "Energy Efficient",
|
||||||
description: "Energy-efficient and quiet, designed for 24/7 uptime.",
|
description: "Energy-efficient and quiet, designed for 24/7 uptime.",
|
||||||
image: "/images/energy.png",
|
image: "/images/energy.png",
|
||||||
@@ -26,7 +26,7 @@ const cards = [
|
|||||||
innerRounded: "lg:rounded-tr-[calc(2rem+1px)]",
|
innerRounded: "lg:rounded-tr-[calc(2rem+1px)]",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: "Monitoring",
|
category: "MONITORING",
|
||||||
title: "Measured Uptime",
|
title: "Measured Uptime",
|
||||||
description: "Automatically measures uptime and contribution.",
|
description: "Automatically measures uptime and contribution.",
|
||||||
image: "/images/uptime.png",
|
image: "/images/uptime.png",
|
||||||
@@ -34,13 +34,13 @@ const cards = [
|
|||||||
innerRounded: "lg:rounded-bl-[calc(2rem+1px)]",
|
innerRounded: "lg:rounded-bl-[calc(2rem+1px)]",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: "Full Stack",
|
category: "SUPPORT",
|
||||||
title: "Full Mycelium Stack Support",
|
title: "Full Mycelium Stack Support",
|
||||||
description: "Supports Mycelium Network, Cloud, Pods, and Agents.",
|
description: "Supports Mycelium Network, Cloud, Pods, and Agents.",
|
||||||
image: "/images/fullstack.png",
|
image: "/images/fullstack.png",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: "Edge & Home",
|
category: "DEPLOYMENT",
|
||||||
title: "Edge & Home Ready",
|
title: "Edge & Home Ready",
|
||||||
description:
|
description:
|
||||||
"Runs seamlessly on compact hardware for edge, home, or micro-datacenter deployments.",
|
"Runs seamlessly on compact hardware for edge, home, or micro-datacenter deployments.",
|
||||||
@@ -52,9 +52,15 @@ const cards = [
|
|||||||
|
|
||||||
export function NodeSpecs() {
|
export function NodeSpecs() {
|
||||||
return (
|
return (
|
||||||
<section className="bg-white py-24 sm:py-32">
|
<section className="w-full max-w-8xl mx-auto bg-transparent">
|
||||||
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
|
||||||
|
|
||||||
|
{/* ✅ 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>
|
<Eyebrow>Node Specifications</Eyebrow>
|
||||||
<H3 className="mt-2">Built for Reliability and Control</H3>
|
<H3 className="mt-2">Built for Reliability and Control</H3>
|
||||||
<P className="mt-4 max-w-2xl">
|
<P className="mt-4 max-w-2xl">
|
||||||
@@ -63,9 +69,9 @@ export function NodeSpecs() {
|
|||||||
</P>
|
</P>
|
||||||
|
|
||||||
{/* BENTO GRID */}
|
{/* 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) => (
|
{cards.map((item, index) => (
|
||||||
<div key={index} className="relative">
|
<div key={index} className="relative group">
|
||||||
|
|
||||||
{/* OUTER BACKPLATE */}
|
{/* OUTER BACKPLATE */}
|
||||||
<div
|
<div
|
||||||
@@ -76,7 +82,7 @@ export function NodeSpecs() {
|
|||||||
|
|
||||||
{/* INNER CARD */}
|
{/* INNER CARD */}
|
||||||
<div
|
<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 || ""
|
item.innerRounded || ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
@@ -89,15 +95,15 @@ export function NodeSpecs() {
|
|||||||
|
|
||||||
{/* RIGHT TEXT */}
|
{/* RIGHT TEXT */}
|
||||||
<div className="flex flex-col">
|
<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>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* OUTLINE */}
|
{/* OUTLINE */}
|
||||||
<div
|
<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 || ""
|
item.rounded || ""
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
@@ -105,6 +111,9 @@ export function NodeSpecs() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Eyebrow, H3, P, CT, CP } from "@/components/Texts";
|
import { Eyebrow, H3, P, CT } from "@/components/Texts";
|
||||||
import {
|
import {
|
||||||
CloudArrowDownIcon,
|
CloudArrowDownIcon,
|
||||||
CpuChipIcon,
|
CpuChipIcon,
|
||||||
@@ -16,7 +16,7 @@ const steps = [
|
|||||||
icon: CpuChipIcon,
|
icon: CpuChipIcon,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Download Mycelium OS",
|
name: "Download Mycelium",
|
||||||
description:
|
description:
|
||||||
"Install the Mycelium OS to prepare your node for network access.",
|
"Install the Mycelium OS to prepare your node for network access.",
|
||||||
icon: CloudArrowDownIcon,
|
icon: CloudArrowDownIcon,
|
||||||
@@ -38,50 +38,74 @@ const steps = [
|
|||||||
export function NodeSteps() {
|
export function NodeSteps() {
|
||||||
return (
|
return (
|
||||||
<section className="w-full max-w-8xl mx-auto bg-transparent">
|
<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="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="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">
|
<div className="mx-auto max-w-4xl sm:text-center">
|
||||||
<Eyebrow className="text-cyan-500">HOW IT WORKS</Eyebrow>
|
<Eyebrow className="text-cyan-500">HOW IT WORKS</Eyebrow>
|
||||||
|
<H3 className="text-gray-900">Host a Node</H3>
|
||||||
<H3 className="text-3xl lg:text-4xl font-medium tracking-tight text-gray-900">
|
<P className="mt-4 text-gray-600">
|
||||||
Host a Node
|
|
||||||
</H3>
|
|
||||||
|
|
||||||
<P className="mt-6 text-lg text-gray-600">
|
|
||||||
Hosting a node takes minutes, and it runs automatically once online.
|
Hosting a node takes minutes, and it runs automatically once online.
|
||||||
</P>
|
</P>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 🔹 Horizontal Stepper */}
|
{/* STEPS */}
|
||||||
<div className="relative mt-16 px-6 flex flex-col gap-8 lg:flex-row lg:items-start lg:justify-between">
|
<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">
|
||||||
{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" />
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* 🔹 Step header with icon */}
|
{steps.map((step, i) => (
|
||||||
<div className="flex items-center gap-3">
|
<li key={step.name} className="relative flex lg:flex-col lg:items-center">
|
||||||
<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" />
|
{/* 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>
|
||||||
|
|
||||||
|
</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>
|
<CT>{step.name}</CT>
|
||||||
</div>
|
</div>
|
||||||
|
<p className="mt-2 text-base leading-snug text-gray-600 lg:text-center">
|
||||||
|
{step.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* 🔹 Description */}
|
{/* DESKTOP horizontal line — perfectly centered */}
|
||||||
<CP className="mt-3">{step.description}</CP>
|
{i < steps.length - 1 && (
|
||||||
</div>
|
<span
|
||||||
|
className="
|
||||||
|
hidden lg:block
|
||||||
|
absolute
|
||||||
|
top-[20px] /* Circle center */
|
||||||
|
left-[50%]
|
||||||
|
w-full
|
||||||
|
h-[1px]
|
||||||
|
bg-gray-200
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{/* bottom line */}
|
{/* Bottom border */}
|
||||||
{/* ✅ Bottom horizontal line with spacing */}
|
|
||||||
<div className="w-full border-b border-gray-100" />
|
<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>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { AnimatedSection } from '@/components/AnimatedSection';
|
||||||
import { NodeHero } from './NodeHero';
|
import { NodeHero } from './NodeHero';
|
||||||
import { NodeBenefits } from './NodeBenefits';
|
import { NodeBenefits } from './NodeBenefits';
|
||||||
import { NodeSteps } from './NodeSteps';
|
import { NodeSteps } from './NodeSteps';
|
||||||
@@ -9,12 +10,29 @@ import { CallToAction } from './CallToAction';
|
|||||||
const NodesPage: React.FC = () => {
|
const NodesPage: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<AnimatedSection>
|
||||||
<NodeHero />
|
<NodeHero />
|
||||||
|
</AnimatedSection>
|
||||||
|
|
||||||
|
<AnimatedSection>
|
||||||
<NodeBenefits />
|
<NodeBenefits />
|
||||||
|
</AnimatedSection>
|
||||||
|
|
||||||
|
<AnimatedSection>
|
||||||
<NodeSteps />
|
<NodeSteps />
|
||||||
|
</AnimatedSection>
|
||||||
|
|
||||||
|
<AnimatedSection>
|
||||||
<NodeProducts />
|
<NodeProducts />
|
||||||
|
</AnimatedSection>
|
||||||
|
|
||||||
|
<AnimatedSection>
|
||||||
<NodeSpecs />
|
<NodeSpecs />
|
||||||
|
</AnimatedSection>
|
||||||
|
|
||||||
|
<AnimatedSection>
|
||||||
<CallToAction />
|
<CallToAction />
|
||||||
|
</AnimatedSection>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||