9 Commits

Author SHA1 Message Date
4f63c20aa6 make 2 directions 2025-11-17 14:21:58 +02:00
74dd974da5 fix logo animation 2025-11-17 13:47:27 +02:00
0eef2cd013 feat: add scroll-to-top behavior and hash anchor navigation
- Added ScrollToTop component to handle navigation scroll behavior
- Implemented smooth scrolling to hash anchors when present in URL
- Added automatic scroll to top on route changes
- Imported useLocation and useEffect hooks for scroll management
2025-11-17 12:27:24 +01:00
3cd41ab1d9 refactor: simplify hero section with updated typography and spacing
- Replaced H1 with H3 and added Eyebrow component for "Project MYCELIUM" label
- Removed promotional banner about booking a call
- Improved text hierarchy and reduced vertical spacing (mt-8 to mt-4)
- Added max-width constraint to description text for better readability
- Removed unused H3Icon import
2025-11-17 12:23:27 +01:00
3121251272 refactor: remove unused imports and add icon null check
- Removed unused ShieldCheckIcon import from NodeProducts
- Removed unused Small component import from NodeSpecs
- Added conditional rendering for Icon in PodsWhat to prevent errors when icon is undefined
2025-11-14 22:59:24 +01:00
56ceac1319 refactor: remove dark mode styling from agent and home pages
- Simplified styling by removing dark mode classes (dark:bg-*, dark:text-*, dark:border-*)
- Added explicit text color classes for better consistency
- Fixed animation container layout with proper centering and sizing
2025-11-14 22:51:19 +01:00
a3028ff448 feat: add cyan glow effects and new network resilience animation
- Added cyan radial glow SVG to CallToAction components across all product pages for visual consistency
- Created NoSinglePoint animation demonstrating redundant network paths and resilience against single point failures
- Updated HomeArchitecture layout to better center and display animations with improved flex positioning
2025-11-14 22:23:11 +01:00
33821987aa refactor: streamline page components and simplify UI elements
- Removed unused HomeAudience component from HomePage
- Renamed NetworkPros to CloudPros for clarity
- Removed bullet point lists from PodsFeatures to simplify presentation
- Replaced PodCapabilities with PodsWhat and removed PodsComing section
2025-11-14 21:53:21 +01:00
678da4b66c feat: redesign cloud page with improved content structure and visual hierarchy
- Replaced CloudHostingNew with new CloudIntro component featuring tabbed interface for Kubernetes, VDC, and QSFS capabilities
- Added CloudCodeTabs component with interactive code examples and syntax highlighting
- Created CloudPros section highlighting platform architecture, reliability, compatibility, and scalability
- Updated hero section copy to emphasize sovereign edge infrastructure and simplified messaging
- Remove
2025-11-14 18:15:04 +01:00
42 changed files with 1169 additions and 208 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
public/images/pod1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@@ -1,6 +1,6 @@
import { HashRouter, Routes, Route } from 'react-router-dom'; import { HashRouter, Routes, Route, useLocation } from 'react-router-dom';
import { Layout } from './components/Layout'; import { Layout } from './components/Layout';
import { lazy, Suspense } from 'react'; import { lazy, Suspense, useEffect } from 'react';
const HomePage = lazy(() => import('./pages/home/HomePage')); const HomePage = lazy(() => import('./pages/home/HomePage'));
const CloudPage = lazy(() => import('./pages/cloud/CloudPage')); const CloudPage = lazy(() => import('./pages/cloud/CloudPage'));
@@ -13,9 +13,29 @@ const GpuPage = lazy(() => import('./pages/gpu/GpuPage'));
const PodsPage = lazy(() => import('./pages/pods/PodsPage')); const PodsPage = lazy(() => import('./pages/pods/PodsPage'));
const NodesPage = lazy(() => import('./pages/nodes/NodesPage')); const NodesPage = lazy(() => import('./pages/nodes/NodesPage'));
function ScrollToTop() {
const { pathname, hash } = useLocation();
useEffect(() => {
if (hash) {
const id = hash.replace('#', '');
const element = document.getElementById(id);
if (element) {
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
return;
}
}
window.scrollTo({ top: 0, left: 0, behavior: 'auto' });
}, [pathname, hash]);
return null;
}
function App() { function App() {
return ( return (
<HashRouter> <HashRouter>
<ScrollToTop />
<Suspense fallback={<div>Loading...</div>}> <Suspense fallback={<div>Loading...</div>}>
<Routes> <Routes>
<Route path="/" element={<Layout />}> <Route path="/" element={<Layout />}>

View File

@@ -0,0 +1 @@

View File

@@ -10,6 +10,7 @@ const XAILogo = () => (
xmlSpace="preserve" xmlSpace="preserve"
width="30" width="30"
height="30" height="30"
fill="white"
> >
<g> <g>
<polygon points="557.09,211.99 565.4,538.36 631.96,538.36 640.28,93.18 " /> <polygon points="557.09,211.99 565.4,538.36 631.96,538.36 640.28,93.18 " />

View File

@@ -62,12 +62,9 @@ export const InfiniteMovingCards = ({
ref={scrollerRef} ref={scrollerRef}
className={cn( className={cn(
"flex min-w-full shrink-0 gap-16 py-4 w-max flex-nowrap", "flex min-w-full shrink-0 gap-16 py-4 w-max flex-nowrap",
start && "animate-scroll", start && (direction === "left" ? "animate-scroll-left" : "animate-scroll-right"),
pauseOnHover && "hover:[animation-play-state:paused]", pauseOnHover && "hover:[animation-play-state:paused]"
)} )}
style={{
"--animation-direction": direction === "left" ? "forwards" : "reverse",
} as React.CSSProperties}
> >
{items.map((item, idx) => ( {items.map((item, idx) => (
<li className="relative flex-shrink-0" key={idx}> <li className="relative flex-shrink-0" key={idx}>

View File

@@ -119,8 +119,8 @@ export function AgentBento() {
className={`relative flex lg:h-90 flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] `} className={`relative flex lg:h-90 flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] `}
> >
{card.animation ? ( {card.animation ? (
<div className="lg:h-64 h-48 w-full overflow-hidden bg-transparent flex items-center"> <div className="lg:h-64 h-48 w-full overflow-hidden bg-transparent flex items-center justify-center">
<card.animation /> <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="h-48 w-full flex items-center justify-center bg-transparent" />

View File

@@ -36,10 +36,10 @@ export function AgentDesign() {
{benefits.map((item) => ( {benefits.map((item) => (
<div <div
key={item.id} key={item.id}
className="flex flex-col items-center bg-white dark:bg-black/40 py-10 px-4 border border-gray-100 dark:border-gray-800 lg:border-t-0 lg:border-b-0" className="flex flex-col items-center bg-white py-10 px-4 border border-gray-100 lg:border-t-0 lg:border-b-0"
> >
<item.icon className="h-10 w-10 text-cyan-500 mb-4" /> <item.icon className="h-10 w-10 text-cyan-500 mb-4" />
<h3 className="text-base font-medium text-black dark:text-white max-w-xs"> <h3 className="text-base font-medium text-black max-w-xs">
{item.title} {item.title}
</h3> </h3>
</div> </div>

View File

@@ -0,0 +1,65 @@
import { InfiniteMovingCards } from "@/components/magicui/infinite-moving-cards";
import Ai21Logo from "@/components/logos/Ai21";
import ClaudeLogo from "@/components/logos/Claude";
import BaiduCloudLogo from "@/components/logos/BaiduCloud";
import ByteDanceLogo from "@/components/logos/ByteDance";
import DeepSeekLogo from "@/components/logos/DeepSeek";
import DeepMindLogo from "@/components/logos/DeepMind";
import MinimaxLogo from "@/components/logos/Minimax";
import MistralLogo from "@/components/logos/Mistral";
import MoonshotLogo from "@/components/logos/Moonshot";
import TencentCloudLogo from "@/components/logos/TencentCloud";
import OpenAILogo from "@/components/logos/OpenAI";
import XAILogo from "@/components/logos/XAI";
const logos = [
{ id: "ai21", Component: Ai21Logo, label: "AI21" },
{ id: "claude", Component: ClaudeLogo, label: "Claude" },
{ id: "baidu", Component: BaiduCloudLogo, label: "Baidu Cloud" },
{ id: "bytedance", Component: ByteDanceLogo, label: "ByteDance" },
{ id: "deepseek", Component: DeepSeekLogo, label: "DeepSeek" },
{ id: "deepmind", Component: DeepMindLogo, label: "DeepMind" },
{ id: "minimax", Component: MinimaxLogo, label: "Minimax" },
{ id: "mistral", Component: MistralLogo, label: "Mistral" },
{ id: "moonshot", Component: MoonshotLogo, label: "Moonshot" },
{ id: "tencent", Component: TencentCloudLogo, label: "Tencent Cloud" },
{ id: "openai", Component: OpenAILogo, label: "OpenAI" },
{ id: "xai", Component: XAILogo, label: "xAI" },
];
const splitLogoRows = () => {
const midpoint = Math.ceil(logos.length / 2);
return [logos.slice(0, midpoint), logos.slice(midpoint)];
};
export const AgentLogos = () => {
const rows = splitLogoRows();
return (
<section className="relative isolate overflow-hidden bg-[#121212] py-4">
<div className="pointer-events-none absolute inset-y-0 left-0 w-32 bg-gradient-to-r from-black to-transparent" />
<div className="pointer-events-none absolute inset-y-0 right-0 w-32 bg-gradient-to-l from-black to-transparent" />
<div className="flex w-full flex-col gap-1 px-0">
{rows.map((row, idx) => (
<InfiniteMovingCards
key={`logos-row-${idx}`}
items={row.map(({ id, Component, label }) => (
<div
key={id}
className="flex h-24 w-36 items-center justify-center bg-transparent px-4"
aria-label={label}
>
<Component />
</div>
))}
direction={idx % 2 === 0 ? "left" : "right"}
speed="slow"
pauseOnHover={true}
className="w-full"
/>
))}
</div>
</section>
);
};

View File

@@ -1,6 +1,6 @@
import { AnimatedSection } from '../../components/AnimatedSection' import { AnimatedSection } from '../../components/AnimatedSection'
import { DeploySection } from './DeploySection' import { DeploySection } from './DeploySection'
import { Companies } from './Companies' import { AgentLogos } from './AgentLogos'
import { AgentBento } from './AgentBento' import { AgentBento } from './AgentBento'
import { AgentHeroAlt } from './AgentHeroAlt' import { AgentHeroAlt } from './AgentHeroAlt'
import { CallToAction } from './CallToAction' import { CallToAction } from './CallToAction'
@@ -19,7 +19,7 @@ export default function AgentsPage() {
</AnimatedSection> </AnimatedSection>
<AnimatedSection> <AnimatedSection>
<Companies /> <AgentLogos />
</AnimatedSection> </AnimatedSection>
<AnimatedSection> <AnimatedSection>

View File

@@ -15,6 +15,26 @@ export function CallToAction() {
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 bg-[#111111] border border-t-0 border-b-0 border-gray-800"
> >
{/* ✅ Cyan Radial Glow */}
<svg
viewBox="0 0 1024 1024"
aria-hidden="true"
className="absolute top-full left-1/2 w-7xl h-320 -translate-x-1/2 -translate-y-1/2 mask-image mask-[radial-gradient(circle,white,transparent)]"
>
<circle
r={512}
cx={512}
cy={512}
fill="url(#mycelium-cyan-glow)"
fillOpacity="0.2"
/>
<defs>
<radialGradient id="mycelium-cyan-glow">
<stop stopColor="#00e5ff" />
<stop offset="1" stopColor="transparent" />
</radialGradient>
</defs>
</svg>
<Container className="relative"> <Container className="relative">
<div className="mx-auto max-w-3xl text-center"> <div className="mx-auto max-w-3xl text-center">
<h2 className="text-3xl lg:text-4xl font-medium tracking-tight text-white sm:text-4xl"> <h2 className="text-3xl lg:text-4xl font-medium tracking-tight text-white sm:text-4xl">

View File

@@ -15,6 +15,26 @@ export function CallToAction() {
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 bg-[#111111] border border-t-0 border-b-0 border-gray-800"
> >
{/* ✅ Cyan Radial Glow */}
<svg
viewBox="0 0 1024 1024"
aria-hidden="true"
className="absolute top-full left-1/2 w-7xl h-320 -translate-x-1/2 -translate-y-1/2 mask-image mask-[radial-gradient(circle,white,transparent)]"
>
<circle
r={512}
cx={512}
cy={512}
fill="url(#mycelium-cyan-glow)"
fillOpacity="0.2"
/>
<defs>
<radialGradient id="mycelium-cyan-glow">
<stop stopColor="#00e5ff" />
<stop offset="1" stopColor="transparent" />
</radialGradient>
</defs>
</svg>
<Container className="relative"> <Container className="relative">

View File

@@ -0,0 +1,112 @@
"use client";
import { useState } from "react";
const files = [
{
id: "kube",
label: "kubernetes.yaml",
code: `apiVersion: apps/v1
kind: Deployment
metadata:
name: mycelium-app
spec:
replicas: 3
selector:
matchLabels:
app: mycelium-app
template:
metadata:
labels:
app: mycelium-app`,
},
{
id: "vdc",
label: "vdc.tf",
code: `provider "mycelium" {
identity = "~/.mycelium/id"
}
resource "mycelium_vdc" "production" {
name = "prod-vdc"
region = "eu-central"
nodes = 6
cpu_cores = 24
ram_gb = 128
storage = "10TB"
network_policies = ["private", "encrypted"]
}`,
},
{
id: "qsfs",
label: "qsfs.py",
code: `from qsfs import QSFS
# mount encrypted distributed filesystem
fs = QSFS.mount("/mnt/secure", key="my-private-key")
# write protected research data
with fs.open("dataset/raw-images/img001.png", "wb") as f:
f.write(b"...binary data...")
# list stored files via S3/IPFS/WebDAV compatibility layer
files = fs.list("dataset/raw-images/")
print("Stored files:", files)`,
},
];
export function CloudCodeTabs() {
const [active, setActive] = useState("kube");
const file = files.find((f) => f.id === active)!;
return (
<div className="sm:px-6 lg:px-0">
<div className="relative isolate overflow-hidden bg-cyan-600 px-6 pt-8 sm:mx-auto sm:max-w-2xl sm:rounded-md sm:pt-16 sm:pr-0 sm:pl-16 lg:mx-0 lg:max-w-none">
{/* Cyan skew background */}
<div
aria-hidden="true"
className="absolute -inset-y-px -left-3 -z-10 w-full origin-bottom-left skew-x-[-30deg] bg-cyan-500 opacity-20 ring-1 ring-white ring-inset"
/>
<div className="mx-auto max-w-2xl sm:mx-0 sm:max-w-none">
<div className="w-screen overflow-hidden rounded-tl-xl bg-[#121212] ring-1 ring-white/10">
{/* File Tabs */}
<div className="flex bg-gray-800/40 ring-1 ring-white/5">
<div className="-mb-px flex text-sm font-medium text-gray-400">
{files.map((f) => (
<button
key={f.id}
onClick={() => setActive(f.id)}
className={`px-4 py-2 border-r border-white/10 transition ${
active === f.id
? "border-b border-b-white/20 bg-white/5 text-white"
: "hover:text-white"
}`}
>
{f.label}
</button>
))}
</div>
</div>
{/* Code Block */}
<div className="px-6 pt-6 pb-14 font-mono text-xs leading-relaxed text-gray-200 whitespace-pre overflow-x-auto">
{file.code}
</div>
</div>
</div>
{/* Outer ring */}
<div
aria-hidden="true"
className="pointer-events-none absolute inset-0 ring-1 ring-white/10 ring-inset sm:rounded-3xl"
/>
</div>
</div>
);
}

View File

@@ -13,19 +13,17 @@ export function CloudHeroNew({ onGetStartedClick = () => {} }: { onGetStartedCli
<div className="px-6 py-16 lg:py-16"> <div className="px-6 py-16 lg:py-16">
<div className="max-w-2xl lg:pl-6"> <div className="max-w-2xl lg:pl-6">
<Eyebrow> <Eyebrow>
Mycelium Cloud MYCELIUM CLOUD
</Eyebrow> </Eyebrow>
<H3 className="mt-4"> <H3 className="mt-4">
Run Kubernetes on the Sovereign Agentic Cloud Sovereign Edge Cloud Infrastructure
</H3> </H3>
<p className="mt-6 text-lg"> <p className="mt-6 text-lg text-gray-600">
Deploy K3s clusters on a global, self-healing mesh network. Run compute, storage, and AI resources on infrastructure you control.
Your workloads run on sovereign, encrypted infrastructure, without centralized cloud control.
</p> </p>
<p className="mt-4 lg:text-base italic text-gray-600 text-sm"> <p className="mt-4 text-lg text-gray-600">
Works Alone. Works Together. The Mycelium Cloud runs on a distributed grid of independent nodes,
Mycelium Cloud can run on any network fabric, or pair with Mycelium Network delivering secure, scalable performance wherever your users or data live.
for sovereign connectivity.
</p> </p>
<div className="mt-10 flex items-center gap-x-6"> <div className="mt-10 flex items-center gap-x-6">
<Button <Button
@@ -33,10 +31,10 @@ export function CloudHeroNew({ onGetStartedClick = () => {} }: { onGetStartedCli
variant="solid" variant="solid"
color="cyan" color="cyan"
> >
Get started Deploy Workloads
</Button> </Button>
<Button to="#" variant="outline"> <Button to="#" variant="outline">
Documentation <span aria-hidden="true"></span> Explore Docs <span aria-hidden="true"></span>
</Button> </Button>
</div> </div>
</div> </div>

View File

@@ -13,7 +13,6 @@ import { Eyebrow, H3, H4 } from "@/components/Texts"
const product = { const product = {
subtitle: 'capabilities', subtitle: 'capabilities',
name: 'What You Can Run on Mycelium Cloud', name: 'What You Can Run on Mycelium Cloud',
description: '<p>Host nodes, deploy workloads, or build private AI systems, all on infrastructure you own and control.</p>',
details: [ details: [
{ {
name: 'Kubernetes Clusters', name: 'Kubernetes Clusters',
@@ -64,9 +63,6 @@ export function CloudHostingNew() {
<div className="mt-4 text-gray-300 text-xl"
dangerouslySetInnerHTML={{ __html: product.description }}
/>
{/* ✅ Details accordion */} {/* ✅ Details accordion */}

View File

@@ -0,0 +1,154 @@
"use client";
import { useState } from "react";
import { CloudCodeTabs } from "./CloudCodeTabs";
import { Eyebrow, H3, P } from "@/components/Texts";
const tabs = [
{
id: "kubernetes",
label: "Managed Kubernetes",
content: {
item: "Managed Kubernetes",
desc:
"Create and manage clusters across distributed environments using standard Kubernetes tools.",
bullets: [
"Create and manage clusters on distributed nodes",
"Run workloads at the edge or across enterprise sites",
"Keep full ownership of data and orchestration",
"Use the Kubernetes ecosystem without modification",
],
},
},
{
id: "vdc",
label: "Virtual Data Centers",
content: {
item: "Virtual Data Centers",
desc:
"Provision and manage full cloud environments without owning or maintaining servers.",
bullets: [
"Create dedicated environments for applications, databases, and internal services",
"Add or remove compute and storage resources instantly",
"Migrate workloads from cloud or on-prem systems",
"Meet compliance requirements by selecting where data resides",
"Benefit from continuous monitoring and automated recovery",
],
},
},
{
id: "qsfs",
label: "Quantum Safe File System (QSFS)",
content: {
item: "Quantum Safe File System (QSFS)",
desc:
"Encrypted, redundant storage designed for high-security and high-availability workloads. Data is distributed across independent nodes and remains accessible even during failures or outages.",
bullets: [
"Secure file storage with quantum-safe encryption",
"Distributed replication for durability",
"Standard protocol support: S3, IPFS, WebDAV",
"Automatic scaling as data grows",
"Consistent performance for research, enterprise, and AI workloads",
],
},
},
];
export function CloudIntro() {
const [active, setActive] = useState("kubernetes");
const current = tabs.find((t) => t.id === active)!.content;
return (
<section className="relative w-full bg-[#121212] overflow-hidden">
{/* Top Spacing Border */}
<div className="max-w-7xl bg-[#121212] mx-auto py-6 border border-t-0 border-b-0 border-gray-800"></div>
<div className="w-full border-t border-l border-r border-gray-800" />
<div className="max-w-7xl mx-auto px-6 lg:px-8 py-12 border border-t-0 border-b-0 border-gray-800 bg-[#111111] overflow-hidden">
{/* ================================
Header
================================= */}
<div className="mb-16">
<Eyebrow color="accent">Capabilities</Eyebrow>
<H3 color="white">What You Can Run on Mycelium Cloud</H3>
<P className="max-w-3xl text-gray-400 mt-6">
Host nodes, deploy workloads, or build private AI systems all on
infrastructure you own and control. Mycelium gives you scalable compute,
secure storage, and sovereign orchestration without depending on
hyperscalers.
</P>
</div>
{/* ================================
Two-column layout
================================= */}
<div className="flex flex-col lg:flex-row gap-16">
{/* Left: Code UI */}
<div className="w-full lg:w-1/2">
<CloudCodeTabs />
</div>
{/* Right: Tabs */}
<div className="w-full lg:w-1/2 text-white">
{/* Tabs Navigation */}
<div className="flex gap-6 border-b border-white/10 pb-2">
{tabs.map((tab) => (
<button
key={tab.id}
onClick={() => setActive(tab.id)}
className={`text-sm font-medium tracking-wide pb-2 ${
active === tab.id
? "border-b-2 border-cyan-500 text-white"
: "text-gray-400 hover:text-white"
}`}
>
{tab.label}
</button>
))}
</div>
{/* Tab Content */}
<div className="mt-6 space-y-6">
<div>
<p className="text-lg font-medium text-white">{current.item}</p>
<p className="mt-2 text-base text-gray-400 leading-relaxed">
{current.desc}
</p>
</div>
<div className="mt-4 space-y-2">
<p className="text-sm uppercase tracking-wide text-cyan-400 font-semibold">
Key capabilities
</p>
<ul className="space-y-2">
{current.bullets.map((b, i) => (
<li key={i} className="text-base text-gray-300 flex gap-2">
<span className="text-cyan-500"></span>
{b}
</li>
))}
</ul>
</div>
</div>
</div>
</div>
</div>
{/* Bottom Borders */}
<div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 border-gray-800" />
<div className="w-full border-b border-gray-800" />
</section>
);
}

View File

@@ -1,11 +1,9 @@
import { AnimatedSection } from '../../components/AnimatedSection' import { AnimatedSection } from '../../components/AnimatedSection'
import { CloudArchitecture } from './CloudArchitecture'
import { CloudUseCases } from './CloudUseCases'
import { CloudHeroNew } from './CloudHeroNew' import { CloudHeroNew } from './CloudHeroNew'
import { CloudBluePrint } from './CloudBluePrint'
import { CallToAction } from './CalltoAction' import { CallToAction } from './CalltoAction'
import { CloudHostingNew } from './CloudHostingNew' import { CloudIntro } from './CloudIntro'
import { CloudFeaturesLight } from './CloudFeaturesLight' import { CloudFeaturesLight } from './CloudFeaturesLight'
import { CloudPros } from './CloudPros'
export default function CloudPage() { export default function CloudPage() {
@@ -17,7 +15,7 @@ export default function CloudPage() {
</AnimatedSection> </AnimatedSection>
<AnimatedSection> <AnimatedSection>
<CloudHostingNew /> <CloudIntro />
</AnimatedSection> </AnimatedSection>
<AnimatedSection> <AnimatedSection>
@@ -25,15 +23,7 @@ export default function CloudPage() {
</AnimatedSection> </AnimatedSection>
<AnimatedSection> <AnimatedSection>
<CloudArchitecture /> <CloudPros />
</AnimatedSection>
<AnimatedSection>
<CloudUseCases />
</AnimatedSection>
<AnimatedSection>
<CloudBluePrint />
</AnimatedSection> </AnimatedSection>
<AnimatedSection> <AnimatedSection>

View File

@@ -0,0 +1,69 @@
import { Small } from '@/components/Texts'
const highlights = [
{
label: 'Platform Architecture',
title: 'Unified compute, storage & orchestration.',
description:
'One unified platform for compute, storage, and orchestration.',
},
{
label: 'Reliability',
title: 'Consistent performance everywhere.',
description:
'Runs reliably across distributed environments.',
},
{
label: 'Compatibility',
title: 'Works with your existing stack.',
description:
'Works with your existing tools and workflows.',
},
{
label: 'Scalability',
title: 'Grows with your needs.',
description:
'Scales from small projects to full environments.',
},
]
export function CloudPros() {
return (
<section className="relative w-full bg-[#FDFDFD] overflow-hidden">
{/* Top spacing line */}
<div className="max-w-7xl bg-[#FDFDFD] 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" />
<div className="bg-[#FDFDFD] w-full max-w-7xl mx-auto border border-t-0 border-b-0 border-gray-100">
<div className="grid lg:grid-cols-4">
{highlights.map((item) => (
<div
key={item.title}
className="group relative overflow-hidden border border-gray-100 bg-white p-8 transition hover:border-cyan-400/40 hover:bg-white"
>
{/* Hover glow */}
<div className="absolute inset-0 bg-linear-to-br from-cyan-200/0 via-cyan-100/20 to-cyan-300/20 opacity-0 transition group-hover:opacity-100" />
<div className="relative">
<Small className="text-xs uppercase tracking-[0.16em] text-cyan-600">
{item.label}
</Small>
<h3 className="mt-4 text-lg font-semibold leading-tight text-black">
{item.title}
</h3>
<p className="mt-4 text-sm leading-relaxed text-gray-600">
{item.description}
</p>
</div>
</div>
))}
</div>
</div>
<div className="w-full border-b border-gray-100 bg-[#FDFDFD]" />
<div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 border-gray-100" />
</section>
)
}

View File

@@ -15,6 +15,26 @@ export function CallToAction() {
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 bg-[#111111] border border-t-0 border-b-0 border-gray-800"
> >
{/* ✅ Cyan Radial Glow */}
<svg
viewBox="0 0 1024 1024"
aria-hidden="true"
className="absolute top-full left-1/2 w-7xl h-320 -translate-x-1/2 -translate-y-1/2 mask-image mask-[radial-gradient(circle,white,transparent)]"
>
<circle
r={512}
cx={512}
cy={512}
fill="url(#mycelium-cyan-glow)"
fillOpacity="0.2"
/>
<defs>
<radialGradient id="mycelium-cyan-glow">
<stop stopColor="#00e5ff" />
<stop offset="1" stopColor="transparent" />
</radialGradient>
</defs>
</svg>
<Container className="relative"> <Container className="relative">

View File

@@ -15,6 +15,26 @@ export function CallToAction() {
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 bg-[#111111] border border-t-0 border-b-0 border-gray-800"
> >
{/* ✅ Cyan Radial Glow */}
<svg
viewBox="0 0 1024 1024"
aria-hidden="true"
className="absolute top-full left-1/2 w-7xl h-320 -translate-x-1/2 -translate-y-1/2 mask-image mask-[radial-gradient(circle,white,transparent)]"
>
<circle
r={512}
cx={512}
cy={512}
fill="url(#mycelium-cyan-glow)"
fillOpacity="0.2"
/>
<defs>
<radialGradient id="mycelium-cyan-glow">
<stop stopColor="#00e5ff" />
<stop offset="1" stopColor="transparent" />
</radialGradient>
</defs>
</svg>
<Container className="relative"> <Container className="relative">

View File

@@ -4,6 +4,7 @@ import { Eyebrow, H3, P } from "@/components/Texts";
import NoExtraction from "./animations/NoExtraction"; import NoExtraction from "./animations/NoExtraction";
import NoControl from "./animations/NoControl"; import NoControl from "./animations/NoControl";
import NoCentral from "./animations/NoCentral"; import NoCentral from "./animations/NoCentral";
import NoSinglePoint from "./animations/NoSinglePoint";
const deterministicCards = [ const deterministicCards = [
{ {
@@ -45,7 +46,7 @@ const deterministicCards = [
title: "No single point of failure.", title: "No single point of failure.",
description: description:
"No single entity can dictate or censor your online experience.", "No single entity can dictate or censor your online experience.",
animation: <NoControl />, // ✅ NEW animation: <NoSinglePoint />, // ✅ NEW
colSpan: "lg:col-span-2", colSpan: "lg:col-span-2",
rowSpan: "lg:row-span-1", rowSpan: "lg:row-span-1",
rounded: "", rounded: "",
@@ -76,7 +77,7 @@ export function HomeArchitecture() {
{deterministicCards.map((card) => ( {deterministicCards.map((card) => (
<div <div
key={card.id} key={card.id}
className={`relative ${card.colSpan} ${card.rowSpan} transition-transform duration-300 hover:scale-102 group`} className={`relative flex flex-col ${card.colSpan} ${card.rowSpan} transition-transform duration-300 hover:scale-102 group`}
> >
{/* ✅ Disable wrapper on first card */} {/* ✅ Disable wrapper on first card */}
{!card.noBorder && ( {!card.noBorder && (
@@ -90,8 +91,8 @@ export function HomeArchitecture() {
> >
{/* ✅ SVG Animation instead of images */} {/* ✅ SVG Animation instead of images */}
{card.animation ? ( {card.animation ? (
<div className="lg:h-64 h-48 w-full overflow-hidden bg-transparent flex items-center"> <div className="lg:h-64 h-48 w-full overflow-hidden bg-transparent flex items-center justify-center">
<div className="w-full h-full"> <div className="w-full h-full object-cover">
{card.animation} {card.animation}
</div> </div>
</div> </div>

View File

@@ -1,5 +1,6 @@
import { H1, H4, H5 } from "@/components/Texts" import { H1, H4, H3, H5, Eyebrow } from "@/components/Texts"
import { Button } from "@/components/Button" import { Button } from "@/components/Button"
import { H3Icon } from "@heroicons/react/20/solid"
export function HomeAurora({ onGetStartedClick }: { onGetStartedClick: () => void }) { export function HomeAurora({ onGetStartedClick }: { onGetStartedClick: () => void }) {
return ( return (
@@ -12,33 +13,17 @@ export function HomeAurora({ onGetStartedClick }: { onGetStartedClick: () => voi
{/* Inner padding */} {/* Inner padding */}
<div className="px-6 py-16 lg:py-32 "> <div className="px-6 py-16 lg:py-32 ">
<div className="max-w-2xl lg:pl-6"> <div className="max-w-2xl lg:pl-6">
<div className="hidden sm:flex"> <Eyebrow> Project MYCELIUM</Eyebrow>
<div className="relative rounded-full px-3 py-1 text-sm/6 text-gray-500 ring-1 ring-gray-900/10 hover:ring-gray-900/20"> <H3 className="mt-4">
Deploying at scale?{' '} Private, Distributed Infrastructure Built
<a href="#" className="font-semibold whitespace-nowrap text-cyan-600"> for Digital Sovereignty
<span aria-hidden="true" className="absolute inset-0" /> </H3>
Book a call <span>&rarr;</span>
</a>
</div>
</div>
<H1 className="mt-8">
MYCELIUM
</H1>
<H4 className="mt-8">
Private, distributed infrastructure built
for digital sovereignty
</H4>
<H5 className="mt-8 text-lg text-gray-600">
<H5 className="mt-4 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-10 flex items-center gap-x-6"> <div className="mt-8 flex items-center gap-x-6">
<Button <Button
variant="solid" variant="solid"
color="cyan" color="cyan"

View File

@@ -0,0 +1,69 @@
"use client";
const benefits = [
{
id: 1,
title: "For Integrators & Builders",
description:
"Deploy sovereign infrastructure for organizations, governments, and large-scale systems.",
image: "/images/dev.png",
},
{
id: 2,
title: "For Enterprises & Institutions",
description:
"Protect data, meet local compliance, and unlock new AI capabilities across distributed environments.",
image: "/images/cons.png",
},
{
id: 3,
title: "For Sovereignty Seekers",
description:
"Run nodes, build applications, and connect directly without relying on centralized platforms.",
image: "/images/seekers.png",
},
];
export function HomeDesign() {
return (
<section className="w-full max-w-8xl mx-auto bg-white">
{/* Top spacing line */}
<div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 border-gray-200" />
<div className="w-full border border-l border-r border-gray-200" />
{/* Content */}
<div className="mx-auto max-w-7xl border-gray-200">
<dl className="grid grid-cols-1 lg:grid-cols-3 gap-4 lg:gap-0">
{benefits.map((item) => (
<div
key={item.id}
className="group flex items-start gap-2 bg-white px-8 py-12 border border-gray-200 0 lg:border-t-0 lg:border-b-0"
>
{/* Image on the LEFT */}
<img
src={item.image}
alt={item.title}
className="h-30 w-30 object-contain opacity-90"
/>
{/* Text on the RIGHT */}
<div className="text-left">
<h3 className="text-base font-semibold tracking-wide text-gray-900 mb-2">
{item.title}
</h3>
<p className="text-sm text-gray-600 leading-relaxed max-w-xs">
{item.description}
</p>
</div>
</div>
))}
</dl>
</div>
{/* ✅ Bottom horizontal line with spacing */}
<div className="w-full border-b border-t 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>
);
}

View File

@@ -4,9 +4,9 @@ import { AnimatedSection } from '../../components/AnimatedSection'
import { CallToAction } from './CallToAction' import { CallToAction } from './CallToAction'
import { HomeTab } from './HomeTab' import { HomeTab } from './HomeTab'
import { HomeMap } from './HomeMap' import { HomeMap } from './HomeMap'
import { HomeAudience } from './HomeAudience'
import { HomeAurora } from './HomeAurora' import { HomeAurora } from './HomeAurora'
import { HomeArchitecture } from './HomeArchitecture'; import { HomeArchitecture } from './HomeArchitecture';
import { HomeDesign } from './HomeDesign';
@@ -35,7 +35,7 @@ export default function HomePage() {
</AnimatedSection> </AnimatedSection>
<AnimatedSection> <AnimatedSection>
<HomeAudience /> <HomeDesign />
</AnimatedSection> </AnimatedSection>
<AnimatedSection> <AnimatedSection>

View File

@@ -0,0 +1,225 @@
"use client";
import { motion, useReducedMotion } from "framer-motion";
import clsx from "clsx";
type Props = {
className?: string;
accent?: string; // cyan
bg?: string; // solid dark background
gridStroke?: string;
};
const W = 720; // 4:3
const H = 540; // 4:3
export default function NoSinglePoint({
className,
accent = "#00b8db",
bg = "#0b0b0b",
gridStroke = "#2b2a2a",
}: Props) {
const prefers = useReducedMotion();
// Nodes (left source, right dest, top hub, bottom hub, plus two relays)
const nodes = {
left: { x: 120, y: H / 2 },
right: { x: W - 120, y: H / 2 },
top: { x: W / 2, y: 160 },
bot: { x: W / 2, y: H - 160 },
tl: { x: 240, y: 200 },
br: { x: W - 240, y: H - 200 },
};
// Redundant paths from left → right
const upperPath = `M ${nodes.left.x} ${nodes.left.y}
L ${nodes.tl.x} ${nodes.tl.y}
L ${nodes.top.x} ${nodes.top.y}
L ${nodes.right.x} ${nodes.right.y}`;
const lowerPath = `M ${nodes.left.x} ${nodes.left.y}
L ${nodes.bot.x} ${nodes.bot.y}
L ${nodes.br.x} ${nodes.br.y}
L ${nodes.right.x} ${nodes.right.y}`;
return (
<div
className={clsx("relative overflow-hidden", className)}
aria-hidden="true"
role="img"
style={{ background: bg }}
>
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full">
{/* Subtle dark grid */}
<defs>
<pattern id="grid-dark-4x3" width="28" height="28" patternUnits="userSpaceOnUse">
<path d="M 28 0 L 0 0 0 28" fill="none" stroke={gridStroke} strokeWidth="1" opacity="0.35" />
</pattern>
<filter id="glow">
<feGaussianBlur stdDeviation="3" result="b" />
<feMerge>
<feMergeNode in="b" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<rect width={W} height={H} fill="url(#grid-dark-4x3)" />
{/* Base links (all potential connectivity) */}
{[
`M ${nodes.left.x} ${nodes.left.y} L ${nodes.tl.x} ${nodes.tl.y}`,
`M ${nodes.tl.x} ${nodes.tl.y} L ${nodes.top.x} ${nodes.top.y}`,
`M ${nodes.top.x} ${nodes.top.y} L ${nodes.right.x} ${nodes.right.y}`,
`M ${nodes.left.x} ${nodes.left.y} L ${nodes.bot.x} ${nodes.bot.y}`,
`M ${nodes.bot.x} ${nodes.bot.y} L ${nodes.br.x} ${nodes.br.y}`,
`M ${nodes.br.x} ${nodes.br.y} L ${nodes.right.x} ${nodes.right.y}`,
// cross edges (mesh redundancy)
`M ${nodes.tl.x} ${nodes.tl.y} L ${nodes.bot.x} ${nodes.bot.y}`,
`M ${nodes.top.x} ${nodes.top.y} L ${nodes.br.x} ${nodes.br.y}`,
].map((d, i) => (
<motion.path
key={`base-${i}`}
d={d}
stroke="#1e1e1e"
strokeWidth={3}
strokeLinecap="round"
fill="none"
initial={{ pathLength: 0, opacity: 0.2 }}
animate={{ pathLength: 1, opacity: 0.5 }}
transition={{ duration: 0.8, delay: i * 0.05, ease: [0.22, 1, 0.36, 1] }}
/>
))}
{/* Highlight the two redundant main routes */}
<motion.path
d={upperPath}
fill="none"
stroke="#3a3a3a"
strokeWidth={4}
strokeLinecap="round"
initial={{ pathLength: 0, opacity: 0.6 }}
animate={{ pathLength: 1, opacity: 0.6 }}
transition={{ duration: 0.9 }}
/>
<motion.path
d={lowerPath}
fill="none"
stroke="#3a3a3a"
strokeWidth={4}
strokeLinecap="round"
initial={{ pathLength: 0, opacity: 0.6 }}
animate={{ pathLength: 1, opacity: 0.6 }}
transition={{ duration: 0.9, delay: 0.1 }}
/>
{/* Cyan accent dash showing “preferred/active” path(s) */}
<motion.path
d={upperPath}
fill="none"
stroke={accent}
strokeWidth={2}
strokeDasharray="10 8"
initial={{ pathLength: 0, opacity: 0.8 }}
animate={{ pathLength: 1, opacity: [0.8, 0.2, 0.8] }} // will fade as "blocked"
transition={{ duration: 1.1, repeat: Infinity, repeatType: "reverse" }}
filter="url(#glow)"
/>
<motion.path
d={lowerPath}
fill="none"
stroke={accent}
strokeWidth={2}
strokeDasharray="10 8"
initial={{ pathLength: 0, opacity: 1 }}
animate={{ pathLength: 1, opacity: 1 }}
transition={{ duration: 1 }}
filter="url(#glow)"
/>
{/* Moving packets: one tries upper (gets dimmed at top hub), one uses lower and continues */}
{!prefers && (
<>
{/* Upper path packet (dims near top hub to suggest block/censor but NOT stopping overall flow) */}
<motion.circle
r={5}
fill={accent}
style={{ offsetPath: `path('${upperPath}')` }}
initial={{ offsetDistance: "0%", opacity: 0.9 }}
animate={{
offsetDistance: ["0%", "100%"],
opacity: [0.9, 0.4, 0.9], // subtle dimming cycle
}}
transition={{ duration: 3.0, repeat: Infinity, ease: "linear" }}
filter="url(#glow)"
/>
{/* Lower path packet (stable flow) */}
<motion.circle
r={6}
fill={accent}
style={{ offsetPath: `path('${lowerPath}')` }}
initial={{ offsetDistance: "0%", opacity: 1 }}
animate={{ offsetDistance: ["0%", "100%"] }}
transition={{ duration: 2.4, repeat: Infinity, ease: "linear" }}
filter="url(#glow)"
/>
</>
)}
{/* Nodes */}
{Object.values(nodes).map((n, i) => (
<g key={`node-${i}`}>
<circle cx={n.x} cy={n.y} r={20} fill="#0f0f0f" stroke="#1f1f1f" strokeWidth={2} />
<motion.circle
cx={n.x}
cy={n.y}
r={8}
fill={i === 2 ? "#0f0f0f" : accent} // top hub inner is dark (to hint “blocked” moment)
stroke="#222"
strokeWidth={2}
animate={
!prefers
? i === 2 // top node (potential choke/attack point) pulses differently
? { opacity: [0.5, 0.25, 0.5], scale: [1, 0.95, 1] }
: { opacity: [0.9, 1, 0.9], scale: [1, 1.06, 1] }
: { opacity: 1 }
}
transition={{
duration: 2.2,
repeat: prefers ? 0 : Infinity,
ease: [0.22, 1, 0.36, 1],
delay: i * 0.05,
}}
filter="url(#glow)"
/>
</g>
))}
{/* A subtle “block” overlay on the top hub (appears/disappears) */}
{!prefers && (
<motion.g
initial={{ opacity: 0 }}
animate={{ opacity: [0, 0.7, 0] }}
transition={{ duration: 3.2, repeat: Infinity, ease: "easeInOut", delay: 0.8 }}
>
<circle
cx={nodes.top.x}
cy={nodes.top.y}
r={18}
fill="none"
stroke="#8b8b8b"
strokeWidth={2}
/>
<path
d={`M ${nodes.top.x - 10} ${nodes.top.y - 10} L ${nodes.top.x + 10} ${nodes.top.y + 10}
M ${nodes.top.x + 10} ${nodes.top.y - 10} L ${nodes.top.x - 10} ${nodes.top.y + 10}`}
stroke="#8b8b8b"
strokeWidth={2}
strokeLinecap="round"
/>
</motion.g>
)}
</svg>
</div>
);
}

View File

@@ -16,6 +16,26 @@ export function CallToAction() {
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 bg-[#111111] border border-t-0 border-b-0 border-gray-800"
> >
{/* ✅ Cyan Radial Glow */}
<svg
viewBox="0 0 1024 1024"
aria-hidden="true"
className="absolute top-full left-1/2 w-7xl h-320 -translate-x-1/2 -translate-y-1/2 mask-image mask-[radial-gradient(circle,white,transparent)]"
>
<circle
r={512}
cx={512}
cy={512}
fill="url(#mycelium-cyan-glow)"
fillOpacity="0.2"
/>
<defs>
<radialGradient id="mycelium-cyan-glow">
<stop stopColor="#00e5ff" />
<stop offset="1" stopColor="transparent" />
</radialGradient>
</defs>
</svg>
<Container className="relative"> <Container className="relative">

View File

@@ -2,7 +2,8 @@ import { useId } from 'react'
import { Container } from '@/components/Container' import { Container } from '@/components/Container'
import { Button } from '@/components/Button' import { Button } from '@/components/Button'
import phoneFrame from '../../images/phoneframe.png' import phoneFrame from '../../images/phoneframe.png'
import { H3, P, CT } from "@/components/Texts"; import { H3, P
, Eyebrow } from "@/components/Texts";
function BackgroundIllustration(props: React.ComponentPropsWithoutRef<'div'>) { function BackgroundIllustration(props: React.ComponentPropsWithoutRef<'div'>) {
let id = useId() let id = useId()
@@ -79,12 +80,12 @@ export function Hero() {
<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">
<H3 className="mb-4"> <Eyebrow className="mb-4">
MYCELIUM NETWORK MYCELIUM NETWORK
</H3> </Eyebrow>
<CT className="mt-8 font-medium text-gray-600 "> <H3 className="mt-8 ">
The Network Stack for Private, Autonomous Networking The Network Stack for Private, Autonomous Networking
</CT> </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>

View File

@@ -6,7 +6,7 @@ import { SecondaryFeatures } from './SecondaryFeatures'
import { CallToAction } from './CallToAction' import { CallToAction } from './CallToAction'
import { NetworkCapabilities } from './NetworkCapabilities' import { NetworkCapabilities } from './NetworkCapabilities'
import { NetworkUsecases } from './NetworkUsecases' import { NetworkUsecases } from './NetworkUsecases'
import { NetworkPros } from './NetworkPros' import { CloudPros } from './NetworkPros'
export default function NetworkPage() { export default function NetworkPage() {
@@ -33,7 +33,7 @@ export default function NetworkPage() {
</AnimatedSection> </AnimatedSection>
<AnimatedSection> <AnimatedSection>
<NetworkPros /> <CloudPros />
</AnimatedSection> </AnimatedSection>
<AnimatedSection> <AnimatedSection>

View File

@@ -8,10 +8,10 @@ const highlights = [
'Connectivity flows directly between users, nodes, and services without platform ownership.', 'Connectivity flows directly between users, nodes, and services without platform ownership.',
}, },
{ {
label: 'Identity', label: 'Platform',
title: 'One identity across all capabilities.', title: 'One unified platform for compute, storage, and orchestration.',
description: description:
'A single cryptographic identity governs your network, storage, agents, and deployments.', 'Runs reliably across distributed environments. Works with your existing tools and workflows. Scales from small projects to full environments.',
}, },
{ {
label: 'Scale', label: 'Scale',
@@ -27,32 +27,33 @@ const highlights = [
}, },
] ]
export function NetworkPros() { export function CloudPros() {
return ( return (
<section className="relative w-full bg-[#121212] overflow-hidden"> <section className="relative w-full bg-[#FDFDFD] overflow-hidden">
{/* Top horizontal line with spacing */} {/* Top spacing line */}
<div className="max-w-7xl bg-[#111111] mx-auto py-6 border border-t-0 border-b-0 border-gray-800"></div> <div className="max-w-7xl bg-[#FDFDFD] mx-auto py-6 border border-t-0 border-b-0 border-gray-200"></div>
<div className="w-full border-t border-l border-r border-gray-800" /> <div className="w-full border-t border-l border-r border-gray-200" />
<div className="bg-[#121212] w-full max-w-7xl mx-auto border border-t-0 border-b-0 border-gray-800"> <div className="bg-[#FDFDFD] w-full max-w-7xl mx-auto border border-t-0 border-b-0 border-gray-200">
<div className="grid lg:grid-cols-4"> <div className="grid lg:grid-cols-4">
{highlights.map((item) => ( {highlights.map((item) => (
<div <div
key={item.title} key={item.title}
className="group relative overflow-hidden border border-white/10 bg-white/4 p-8 backdrop-blur-sm transition hover:border-cyan-300/50 hover:bg-white/8" className="group relative overflow-hidden border border-gray-200 bg-white p-8 transition hover:border-cyan-400/40 hover:bg-white"
> >
<div className="absolute inset-0 bg-linear-to-br from-cyan-500/0 via-white/5 to-cyan-300/20 opacity-0 transition group-hover:opacity-100" /> {/* Hover glow */}
<div className="absolute inset-0 bg-linear-to-br from-cyan-200/0 via-cyan-100/20 to-cyan-300/20 opacity-0 transition group-hover:opacity-100" />
<div className="relative"> <div className="relative">
<Small className="text-xs uppercase tracking-[0.16em] text-cyan-200"> <Small className="text-xs uppercase tracking-[0.16em] text-cyan-600">
{item.label} {item.label}
</Small> </Small>
<h3 className="mt-4 text-lg font-semibold leading-tight text-white"> <h3 className="mt-4 text-lg font-semibold leading-tight text-black">
{item.title} {item.title}
</h3> </h3>
<p className="mt-4 text-sm leading-relaxed text-gray-300"> <p className="mt-4 text-sm leading-relaxed text-gray-600">
{item.description} {item.description}
</p> </p>
</div> </div>
@@ -61,8 +62,8 @@ export function NetworkPros() {
</div> </div>
</div> </div>
<div className="w-full border-b border-gray-800 bg-[#121212]" /> <div className="w-full border-b border-gray-200 bg-[#FDFDFD]" />
<div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 border-gray-800" /> <div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 border-gray-200" />
</section> </section>
) )
} }

View File

@@ -13,6 +13,26 @@ export function CallToAction() {
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 bg-[#111111] border border-t-0 border-b-0 border-gray-800"
> >
{/* ✅ Cyan Radial Glow */}
<svg
viewBox="0 0 1024 1024"
aria-hidden="true"
className="absolute top-full left-1/2 w-7xl h-320 -translate-x-1/2 -translate-y-1/2 mask-image mask-[radial-gradient(circle,white,transparent)]"
>
<circle
r={512}
cx={512}
cy={512}
fill="url(#mycelium-cyan-glow)"
fillOpacity="0.2"
/>
<defs>
<radialGradient id="mycelium-cyan-glow">
<stop stopColor="#00e5ff" />
<stop offset="1" stopColor="transparent" />
</radialGradient>
</defs>
</svg>
<Container className="relative"> <Container className="relative">
<div className="mx-auto max-w-3xl text-center"> <div className="mx-auto max-w-3xl text-center">
<h2 className="text-3xl lg:text-4xl font-medium tracking-tight text-white sm:text-4xl"> <h2 className="text-3xl lg:text-4xl font-medium tracking-tight text-white sm:text-4xl">

View File

@@ -52,7 +52,7 @@ export function NodeBenefits() {
<div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 border-gray-800" /> <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="w-full border-t border-l border-r border-gray-800" />
<div className="relative px-6 lg:px-12 py-12 bg-[#111111] border border-t-0 border-b-0 border-gray-800 max-w-7xl mx-auto"> <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">
{/* Header */} {/* Header */}
<motion.div <motion.div
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}

View File

@@ -1,32 +1,32 @@
'use client' 'use client'
import { Button } from '@/components/Button' import { Button } from '@/components/Button'
import { Eyebrow, H3, P } from '@/components/Texts' import { Eyebrow, H3 } 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" className="relative mx-auto max-w-7xl border border-t-0 border-b-0 border-gray-100 bg-white overflow-hidden bg-contain bg-right bg-no-repeat"
style={{ backgroundImage: "url('/images/gpuhero2.png')", backgroundSize: "contain" }}
> >
{/* Inner padding */} {/* Inner padding */}
<div className="px-6 py-16 lg:py-16"> <div className="px-6 py-16 lg:py-16">
<div className="max-w-3xl mx-auto text-center"> <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-gray-800"> <p className="mt-6 text-lg text-gray-800">
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 justify-center gap-x-6"> <Button to="#node-getting-started" as="a" variant="solid" color="cyan">
<Button href="/host" variant="solid" color="cyan"> How it works
Host a Node
</Button> </Button>
<Button href="#" variant="outline"> <Button to="#node-architecture" as="a" variant="outline">
Learn More Explore Docs <span aria-hidden="true"></span>
</Button> </Button>
</div> </div>
</div> </div>

View File

@@ -5,7 +5,6 @@ import { motion } from "framer-motion";
import { Eyebrow, SectionHeader, P } from "@/components/Texts"; import { Eyebrow, SectionHeader, P } from "@/components/Texts";
import { import {
QuestionMarkCircleIcon, QuestionMarkCircleIcon,
ShieldCheckIcon,
CheckIcon, CheckIcon,
} from "@heroicons/react/20/solid"; } from "@heroicons/react/20/solid";
@@ -137,7 +136,7 @@ export function NodeProducts() {
{/* CONFIG SELECTOR */} {/* CONFIG SELECTOR */}
<fieldset className="mt-10"> <fieldset className="mt-10">
<legend className="text-sm font-medium text-gray-200"> <legend className="text-sm font-medium text-gray-200">
Configuration Choose Your Node Type
</legend> </legend>
<div className="mt-3 grid grid-cols-1 sm:grid-cols-2 gap-4"> <div className="mt-3 grid grid-cols-1 sm:grid-cols-2 gap-4">
@@ -160,7 +159,7 @@ export function NodeProducts() {
</fieldset> </fieldset>
<div className="mt-4"> <div className="mt-4">
<a className="inline-flex text-sm text-gray-500 hover:text-gray-300 transition"> <a href="https://threefold.info/mycelium_economics/docs/category/recommended-nodes" target="_blank" rel="noopener noreferrer" className="inline-flex text-sm text-gray-500 hover:text-gray-300 transition">
What config should I choose? What config should I choose?
<QuestionMarkCircleIcon className="ml-1 w-5 h-5 text-gray-500" /> <QuestionMarkCircleIcon className="ml-1 w-5 h-5 text-gray-500" />
</a> </a>
@@ -194,11 +193,7 @@ export function NodeProducts() {
</a> </a>
</div> </div>
{/* Guarantee */}
<div className="mt-6 flex items-center text-gray-400 text-sm">
<ShieldCheckIcon className="w-6 h-6 text-gray-500 mr-2" />
Lifetime Guarantee
</div>
</motion.div> </motion.div>
{/* ------------------------------ */} {/* ------------------------------ */}
@@ -214,7 +209,7 @@ export function NodeProducts() {
<img <img
src={selectedNode.image} src={selectedNode.image}
alt={selectedNode.name} alt={selectedNode.name}
className="w-full max-w-md rounded-2xl border border-gray-800 object-cover" className="max-w-md rounded-2xl "
/> />
</motion.div> </motion.div>

View File

@@ -1,97 +1,114 @@
"use client"; "use client";
import { Eyebrow, H3, CT, CP, P } from "@/components/Texts"; import { Container } from "@/components/Container";
// Heroicons
import {
ShieldCheckIcon,
BoltIcon,
GlobeAltIcon,
ServerStackIcon,
CheckBadgeIcon,
CpuChipIcon,
} from "@heroicons/react/24/solid";
const nodeSpecs = [ const nodeSpecs = [
{ {
id: "autonomous",
eyebrow: "Self-Running",
title: "Autonomous Operation", title: "Autonomous Operation",
description: "Runs autonomously with no central control.", description: "Runs autonomously with no central control.",
colSpan: "lg:col-span-3", icon: ServerStackIcon,
rounded: "max-lg:rounded-t-4xl lg:rounded-tl-4xl",
innerRounded: "max-lg:rounded-t-[calc(2rem+1px)] lg:rounded-tl-[calc(2rem+1px)]",
}, },
{ {
id: "encrypted",
eyebrow: "Security",
title: "Encrypted by Default", title: "Encrypted by Default",
description: "Fully encrypted and identity-based.", description: "Fully encrypted and identity-based.",
colSpan: "lg:col-span-3", icon: ShieldCheckIcon,
rounded: "lg:rounded-tr-4xl",
innerRounded: "lg:rounded-tr-[calc(2rem+1px)]",
}, },
{ {
id: "efficient",
eyebrow: "Performance",
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.",
colSpan: "lg:col-span-2", icon: BoltIcon,
rounded: "lg:rounded-bl-4xl",
innerRounded: "lg:rounded-bl-[calc(2rem+1px)]",
}, },
{ {
id: "uptime",
eyebrow: "Reliability",
title: "Measured Uptime", title: "Measured Uptime",
description: "Automatically measures uptime and contribution.", description: "Automatically measures uptime and contribution.",
colSpan: "lg:col-span-2", icon: CheckBadgeIcon,
rounded: "",
innerRounded: "",
}, },
{ {
id: "fullstack",
eyebrow: "Compatibility",
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.",
colSpan: "lg:col-span-2", icon: GlobeAltIcon,
rounded: "max-lg:rounded-b-4xl lg:rounded-br-4xl", },
innerRounded: "max-lg:rounded-b-[calc(2rem+1px)] lg:rounded-br-[calc(2rem+1px)]",
// ✅ NEW 6th card (to complete the grid)
{
title: "Edge & Home Ready",
description:
"Runs seamlessly on compact hardware for edge, home, or micro-datacenter deployments.",
icon: CpuChipIcon,
}, },
]; ];
export function NodeSpecs() { export function NodeSpecs() {
return ( return (
<div 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-2xl px-6 lg:max-w-7xl lg:px-8"> {/* Top horizontal spacing */}
<Eyebrow>Node Specifications</Eyebrow> <div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 border-gray-100"></div>
<H3 className="mt-2">Built for Reliability and Control</H3> <div className="w-full border-t border-l border-r border-gray-100" />
<P className="mt-6 max-w-xl">
Each node strengthens the network and helps build a more open, sovereign and
distributed internet.
</P>
<div className="mt-10 grid grid-cols-1 gap-4 sm:mt-16 lg:grid-cols-6 lg:grid-rows-2"> <Container className="py-12 border border-t-0 border-b-0 border-gray-100">
{nodeSpecs.map((item) => ( {/* Header */}
<div key={item.id} className={`relative ${item.colSpan}`}> <div className="mx-auto max-w-4xl sm:text-center">
{/* BG LAYER */} <h2 className="text-base/7 font-semibold text-cyan-500">
<div NODE SPECIFICATIONS
className={`absolute inset-0 rounded-lg bg-white ${item.rounded}`} </h2>
/>
{/* CONTENT LAYER */} <p className="text-3xl lg:text-4xl font-medium tracking-tight text-gray-900">
<div Built for Reliability and Control
className={`relative flex h-full flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] ${item.innerRounded}`} </p>
<p className="mt-6 text-lg text-gray-600">
Each node strengthens the network and helps build a more open,
sovereign and distributed internet.
</p>
</div>
{/* Cards */}
<ul
role="list"
className="mx-auto mt-12 grid max-w-2xl grid-cols-1 gap-6
sm:grid-cols-2 lg:max-w-none lg:grid-cols-3 md:gap-y-10"
> >
<div className="p-10 pt-6"> {nodeSpecs.map((item) => {
<h3 className="text-sm/4 font-semibold text-cyan-600">{item.eyebrow}</h3> const Icon = item.icon;
<CT className="mt-2 text-lg font-medium tracking-tight text-gray-950">
return (
<li
key={item.title}
className="rounded-md border border-gray-100 bg-white p-6 transition-all duration-300
hover:scale-105 hover:border-cyan-500 hover:shadow-lg hover:shadow-cyan-500/20 flex flex-col"
>
{/* Title + label */}
<div className="flex items-center justify-between">
<h3 className="font-semibold text-gray-900">
{item.title} {item.title}
</CT> </h3>
<CP className="mt-2 max-w-lg text-sm/6 text-gray-600">
{item.description} <Icon className="h-6 w-6 text-cyan-500" />
</CP>
</div>
</div> </div>
{/* OUTLINE OVERLAY */} {/* Short description */}
<div <p className="mt-4 text-gray-700 leading-snug">
className={`pointer-events-none absolute inset-0 rounded-lg shadow-sm outline outline-black/5 ${item.rounded}`} {item.description}
/> </p>
</div> </li>
))} );
</div> })}
</div> </ul>
</div> </Container>
{/* Bottom spacing */}
<div className="w-full border-b border-gray-100" />
<div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 border-gray-100"></div>
</section>
); );
} }

View File

@@ -15,6 +15,26 @@ export function CallToAction() {
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 bg-[#111111] border border-t-0 border-b-0 border-gray-800"
> >
{/* ✅ Cyan Radial Glow */}
<svg
viewBox="0 0 1024 1024"
aria-hidden="true"
className="absolute top-full left-1/2 w-7xl h-320 -translate-x-1/2 -translate-y-1/2 mask-image mask-[radial-gradient(circle,white,transparent)]"
>
<circle
r={512}
cx={512}
cy={512}
fill="url(#mycelium-cyan-glow)"
fillOpacity="0.2"
/>
<defs>
<radialGradient id="mycelium-cyan-glow">
<stop stopColor="#00e5ff" />
<stop offset="1" stopColor="transparent" />
</radialGradient>
</defs>
</svg>
<Container className="relative"> <Container className="relative">
<div className="mx-auto max-w-3xl text-center"> <div className="mx-auto max-w-3xl text-center">
<h2 className="text-3xl lg:text-4xl font-medium tracking-tight text-white sm:text-4xl"> <h2 className="text-3xl lg:text-4xl font-medium tracking-tight text-white sm:text-4xl">

View File

@@ -6,7 +6,7 @@ export default function Homepod() {
{/* 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 bg-contain bg-right bg-no-repeat"
style={{ backgroundImage: "url('/images/pods.png')", backgroundSize: "contain" }} style={{ backgroundImage: "url('/images/computehero11.webp')", backgroundSize: "contain" }}
> >
{/* Inner padding */} {/* Inner padding */}
<div className="px-6 py-16 lg:py-16"> <div className="px-6 py-16 lg:py-16">

View File

@@ -49,10 +49,10 @@ export function PodsDesign() {
return ( return (
<div className="bg-white text-gray-900"> <div className="bg-white text-gray-900">
{/* TOP LINE */} {/* TOP 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-t border-l border-r border-gray-200" /> <div className="w-full border-t border-l border-r border-gray-100" />
<main className="mx-auto max-w-7xl px-6 lg:px-12 py-12 border border-t-0 border-b-0 border-gray-200"> <main className="mx-auto max-w-7xl px-6 lg:px-12 py-12 border border-t-0 border-b-0 border-gray-100">
<div className="mx-auto max-w-2xl lg:max-w-none"> <div className="mx-auto max-w-2xl lg:max-w-none">
<div className="lg:grid lg:grid-cols-5 lg:items-start lg:gap-x-8"> <div className="lg:grid lg:grid-cols-5 lg:items-start lg:gap-x-8">
@@ -61,7 +61,7 @@ export function PodsDesign() {
<div className="lg:col-span-2 lg:mt-8 mt-2"> <div className="lg:col-span-2 lg:mt-8 mt-2">
<img <img
alt="Mycelium Federation" alt="Mycelium Federation"
src="/images/cloudhosting.webp" src="/images/pod1.png"
className="aspect-square w-full object-cover rounded-md" className="aspect-square w-full object-cover rounded-md"
/> />
</div> </div>
@@ -114,8 +114,8 @@ export function PodsDesign() {
</main> </main>
{/* BOTTOM LINE */} {/* BOTTOM LINE */}
<div className="w-full border-b border-gray-200" /> <div className="w-full border-b border-gray-100" />
<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> </div>
) )
} }

View File

@@ -115,19 +115,6 @@ export function PodsFeatures() {
<p className="mt-4 text-gray-700 leading-snug"> <p className="mt-4 text-gray-700 leading-snug">
{useCase.description} {useCase.description}
</p> </p>
{/* Bullet list */}
<ul className="mt-6 space-y-3 text-sm text-gray-600">
{useCase.bullets.map((bullet) => (
<li
key={bullet}
className="flex items-start gap-3 rounded-2xl border border-cyan-100 bg-cyan-50/60 p-3 leading-relaxed"
>
<span className="mt-1 inline-block size-2 rounded-full bg-cyan-500" />
<span>{bullet}</span>
</li>
))}
</ul>
</li> </li>
))} ))}
</ul> </ul>

View File

@@ -1,22 +1,20 @@
import Homepod from './Homepod'; import Homepod from './Homepod';
import { PodCapabilities } from './PodCapabilities';
import { PodsHow } from './PodsHow'; import { PodsHow } from './PodsHow';
import { PodsFeatures } from './PodsFeatures'; import { PodsFeatures } from './PodsFeatures';
import { PodsDesign } from './PodsDesign'; import { PodsDesign } from './PodsDesign';
import { PodsBenefits } from './PodsBenefits'; import { PodsBenefits } from './PodsBenefits';
import { PodsComing } from './PodsComing';
import { CallToAction } from './CallToAction'; import { CallToAction } from './CallToAction';
import { PodsWhat } from './PodsWhat';
const PodsPage = () => { const PodsPage = () => {
return ( return (
<> <>
<Homepod /> <Homepod />
<PodCapabilities /> <PodsWhat />
<PodsFeatures /> <PodsFeatures />
<PodsHow /> <PodsHow />
<PodsDesign /> <PodsDesign />
<PodsBenefits /> <PodsBenefits />
<PodsComing />
<CallToAction /> <CallToAction />
</> </>
); );

106
src/pages/pods/PodsWhat.tsx Normal file
View File

@@ -0,0 +1,106 @@
"use client";
import {
ServerIcon,
ShieldCheckIcon,
BoltIcon,
GlobeAltIcon,
} from "@heroicons/react/24/solid";
import { Eyebrow, H3 } from "@/components/Texts";
const podCards = [
{
id: "intro",
eyebrow: "Capabilities",
title: "What is a Pod?",
description: null,
icon: null,
custom: true,
noBorder: true,
colSpan: "lg:col-span-4",
},
{
id: "home",
title: "Your private digital home on the decentralized internet",
description:
"Your Pod is a private digital home where apps, data, and identity live independently of Big Tech and central servers.",
icon: ServerIcon,
},
{
id: "control",
title: "An always-on space you fully control",
description:
"A dedicated, always-on environment you fully command — your own sovereign slice of the network that never goes offline.",
icon: ShieldCheckIcon,
},
{
id: "tools",
title: "Runs communication, storage, and collaboration tools",
description:
"Runs your communication, storage, and collaboration tools in a secure local environment without reliance on outside platforms.",
icon: BoltIcon,
},
{
id: "networking",
title: "Fully encrypted, federated peer-to-peer network",
description:
"Encrypted, federated peer-to-peer networking that links your Pod directly with trusted devices without intermediaries.",
icon: GlobeAltIcon,
},
];
export function PodsWhat() {
return (
<section className="relative w-full bg-[#121212] overflow-hidden">
{/* Top horizontal line */}
<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" />
{/* Content container */}
<div className="mx-auto bg-[#111111] max-w-7xl px-6 lg:px-10 border border-t-0 border-b-0 border-gray-800">
{/* 4-column grid */}
<div className="grid grid-cols-1 gap-12 pt-12 lg:grid-cols-4 pb-20">
{podCards.map((card) => {
const Icon = card.icon;
return (
<div
key={card.id}
className={`${card.colSpan || ""} flex flex-col ${
card.custom ? "" : "transition-transform duration-300 hover:scale-[1.02]"
}`}
>
{/* Custom Intro Card */}
{card.custom ? (
<>
<Eyebrow>{card.eyebrow}</Eyebrow>
<H3 className="mt-2 text-white">{card.title}</H3>
</>
) : (
<>
{/* TITLE WITH ICON (matching the TL example) */}
<dt className="flex items-center gap-x-3 text-base font-semibold text-white">
{Icon && <Icon className="h-6 w-6 text-cyan-500" aria-hidden="true" />}
{card.title}
</dt>
{/* DESCRIPTION */}
<dd className="mt-4 text-base text-gray-300">
{card.description}
</dd>
</>
)}
</div>
);
})}
</div>
</div>
{/* Bottom border */}
<div className="w-full border-b border-gray-800" />
<div className="max-w-7xl mx-auto py-6 border-x border-gray-800 border-t-0 border-b-0" />
</section>
);
}

View File

@@ -15,6 +15,26 @@ export function CallToAction() {
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 bg-[#111111] border border-t-0 border-b-0 border-gray-800"
> >
{/* ✅ Cyan Radial Glow */}
<svg
viewBox="0 0 1024 1024"
aria-hidden="true"
className="absolute top-full left-1/2 w-7xl h-320 -translate-x-1/2 -translate-y-1/2 mask-image mask-[radial-gradient(circle,white,transparent)]"
>
<circle
r={512}
cx={512}
cy={512}
fill="url(#mycelium-cyan-glow)"
fillOpacity="0.2"
/>
<defs>
<radialGradient id="mycelium-cyan-glow">
<stop stopColor="#00e5ff" />
<stop offset="1" stopColor="transparent" />
</radialGradient>
</defs>
</svg>
<Container className="relative"> <Container className="relative">
<div className="mx-auto max-w-3xl text-center"> <div className="mx-auto max-w-3xl text-center">
<h2 className="text-3xl lg:text-4xl font-medium tracking-tight text-white sm:text-4xl"> <h2 className="text-3xl lg:text-4xl font-medium tracking-tight text-white sm:text-4xl">

View File

@@ -4,11 +4,24 @@
@custom-variant dark (&:is(.dark *)); @custom-variant dark (&:is(.dark *));
@theme { @theme {
--animate-scroll: scroll var(--animation-duration, 40s) var(--animation-direction, forwards) linear infinite; --animate-scroll-left: scroll-left var(--animation-duration, 40s) linear infinite;
--animate-scroll-right: scroll-right var(--animation-duration, 40s) linear infinite;
@keyframes scroll { @keyframes scroll-left {
from {
transform: translateX(0);
}
to { to {
transform: translate(calc(-50% - 0.5rem)); transform: translateX(calc(-50% - 0.5rem));
}
}
@keyframes scroll-right {
from {
transform: translateX(calc(-50% - 0.5rem));
}
to {
transform: translateX(0);
} }
} }