forked from emre/www_projectmycelium_com
refactor: convert agent bento cards from videos to React animation components
- Replaced video paths with imported animation components (Fungistor, Herodb, MOSSandboxes, etc.) - Added new AgentDesign and AgentUseCase sections to agents page - Updated hero copy to emphasize private, sovereign AI and 2026 timeline - Reorganized page layout with new sections between existing components
This commit is contained in:
@@ -1,15 +1,32 @@
|
||||
"use client";
|
||||
|
||||
import { Eyebrow, H3, P } from "@/components/Texts";
|
||||
import AgentCoordination from "./animations/AgentCoordination";
|
||||
import DeterministicExecution from "./animations/DeterministicExecution";
|
||||
import Fungistor from "./animations/Fungistor";
|
||||
import Herodb from "./animations/Herodb";
|
||||
import MOSSandboxes from "./animations/MOSSandboxes";
|
||||
import MyceliumMesh from "./animations/MyceliumMesh";
|
||||
|
||||
const bentos = [
|
||||
const bentos: {
|
||||
id: string;
|
||||
eyebrow?: string;
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
description: string;
|
||||
animation: React.ComponentType | null;
|
||||
colSpan: string;
|
||||
rowSpan: string;
|
||||
custom?: boolean;
|
||||
noBorder?: boolean;
|
||||
}[] = [
|
||||
{
|
||||
id: "core",
|
||||
eyebrow: "ARCHITECTURE",
|
||||
title: "Deterministic by Design",
|
||||
title: "Augmented Intelligence Fabric",
|
||||
description:
|
||||
"Every workload runs exactly as declared: no drift, no hidden state, no surprises.",
|
||||
video: null,
|
||||
"The sovereign substrate for autonomous AI. Stateless, geo-aware, end-to-end encrypted—and verifiable from intent to execution.",
|
||||
animation: null,
|
||||
colSpan: "lg:col-span-3",
|
||||
rowSpan: "lg:row-span-1",
|
||||
custom: true,
|
||||
@@ -23,7 +40,7 @@ const bentos = [
|
||||
subtitle: "Long-Term AI Memory",
|
||||
description:
|
||||
"Erasure coding + compression slash storage bloat by up to 10× vs basic replication. Source-encrypted shards are geo-dispersed—lose pieces, rebuild perfectly from a quorum.",
|
||||
video: "/videos/fungistor.mp4",
|
||||
animation: Fungistor,
|
||||
colSpan: "lg:col-span-3",
|
||||
rowSpan: "lg:row-span-1",
|
||||
},
|
||||
@@ -33,7 +50,7 @@ const bentos = [
|
||||
subtitle: "Active AI Memory",
|
||||
description:
|
||||
"Multimodal vector+keyword retrieval makes RAG feel instant across text, image, audio. Time-aware, policy-guarded context keeps results fresh while access stays governed.",
|
||||
video: "/videos/herodb.mp4",
|
||||
animation: Herodb,
|
||||
colSpan: "lg:col-span-3",
|
||||
rowSpan: "lg:row-span-1",
|
||||
},
|
||||
@@ -43,7 +60,7 @@ const bentos = [
|
||||
subtitle: "Secure Agent Workspaces",
|
||||
description:
|
||||
"Attested, signed workspaces spin up ≈5s worldwide—ready to execute. Hardware isolation and scoped egress: run hard, tear down clean, zero residue.",
|
||||
video: "/videos/herodb.mp4",
|
||||
animation: MOSSandboxes,
|
||||
colSpan: "lg:col-span-3",
|
||||
rowSpan: "lg:row-span-1",
|
||||
},
|
||||
@@ -53,7 +70,7 @@ const bentos = [
|
||||
subtitle: "Secure Communication Network",
|
||||
description:
|
||||
"A private, public-key fabric with self-healing multi-path routing. Glides through NATs and firewalls—direct, low-latency, no middlemen.",
|
||||
video: "/videos/mesh.mp4",
|
||||
animation: MyceliumMesh,
|
||||
colSpan: "lg:col-span-2",
|
||||
rowSpan: "lg:row-span-1",
|
||||
},
|
||||
@@ -63,7 +80,7 @@ const bentos = [
|
||||
subtitle: "Verifiable Code Execution",
|
||||
description:
|
||||
"Declare intent, get a hash; remote attestation proves that is what runs. Reproducible builds, signed artifacts, immutable logs—supply chain, sealed.",
|
||||
video: "/videos/deterministic.mp4",
|
||||
animation: DeterministicExecution,
|
||||
colSpan: "lg:col-span-2",
|
||||
rowSpan: "lg:row-span-1",
|
||||
},
|
||||
@@ -73,7 +90,7 @@ const bentos = [
|
||||
subtitle: "Sovereign Workflow Management",
|
||||
description:
|
||||
"Your private agent conducts swarms of specialists in parallel. Policies fan out work; human checkpoints keep you in command.",
|
||||
video: "/videos/agent.mp4",
|
||||
animation: AgentCoordination,
|
||||
colSpan: "lg:col-span-2",
|
||||
rowSpan: "lg:row-span-1",
|
||||
},
|
||||
@@ -101,17 +118,9 @@ export function AgentBento() {
|
||||
<div
|
||||
className={`relative flex lg:h-90 flex-col overflow-hidden rounded-[calc(var(--radius-lg)+1px)] `}
|
||||
>
|
||||
{/* ✅ VIDEO instead of animation */}
|
||||
{card.video ? (
|
||||
{card.animation ? (
|
||||
<div className="lg:h-64 h-48 w-full overflow-hidden bg-transparent flex items-center">
|
||||
<video
|
||||
src={card.video}
|
||||
autoPlay
|
||||
loop
|
||||
muted
|
||||
playsInline
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
<card.animation />
|
||||
</div>
|
||||
) : (
|
||||
<div className="h-48 w-full flex items-center justify-center bg-transparent" />
|
||||
|
||||
56
src/pages/agents/AgentDesign.tsx
Normal file
56
src/pages/agents/AgentDesign.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import {
|
||||
ComputerDesktopIcon,
|
||||
ArrowsRightLeftIcon,
|
||||
CircleStackIcon,
|
||||
} from '@heroicons/react/24/solid'
|
||||
|
||||
const benefits = [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Each agent operates entirely inside your environment',
|
||||
icon: ComputerDesktopIcon,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'They communicate peer-to-peer across trusted nodes',
|
||||
icon: ArrowsRightLeftIcon,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'They access data locally without exposing it to external providers',
|
||||
icon: CircleStackIcon,
|
||||
},
|
||||
]
|
||||
|
||||
export function AgentDesign() {
|
||||
return (
|
||||
<section className="w-full max-w-8xl mx-auto bg-transparent">
|
||||
|
||||
{/* ✅ Top horizontal line with spacing */}
|
||||
<div className="max-w-7xl bg-transparent mx-auto py-6 border border-t-0 border-b-0 border-gray-100"></div>
|
||||
<div className="w-full border border-l border-r border-gray-100" />
|
||||
|
||||
{/* ✅ Main content */}
|
||||
<div className="mx-auto max-w-7xl border-gray-100 ">
|
||||
<dl className="grid grid-cols-1 gap-4 lg:gap-6 lg:grid-cols-3 text-center ">
|
||||
{benefits.map((item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
className="flex flex-col items-center bg-white/40 dark:bg-black/40 py-10 px-4 border border-gray-100 dark:border-gray-800 lg:border-t-0 lg:border-b-0"
|
||||
>
|
||||
<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">
|
||||
{item.title}
|
||||
</h3>
|
||||
</div>
|
||||
))}
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
{/* ✅ Bottom horizontal line with spacing */}
|
||||
<div className="w-full border 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>
|
||||
|
||||
)
|
||||
}
|
||||
@@ -14,19 +14,18 @@ export function AgentHeroAlt() {
|
||||
{/* Inner padding */}
|
||||
<div className="px-6 py-16 lg:py-16">
|
||||
<div className="max-w-2xl lg:pl-6">
|
||||
<Eyebrow>MYCELIUM AGENTS</Eyebrow>
|
||||
<Eyebrow>MYCELIUM AGENTS - COMING IN 2026</Eyebrow>
|
||||
<H3 as="h1" className="mt-4">
|
||||
Sovereign AI Agents, Coming Soon.
|
||||
Private, Sovereign and Distributed AI You Control
|
||||
</H3>
|
||||
<p className="mt-6 text-lg">
|
||||
The Agent layer will allow you to run autonomous, policy-governed AI that operates on infrastructure you control, with private memory, verifiable execution, and coordination across your personal or organizational environment.
|
||||
</p>
|
||||
<p className="mt-4 lg:text-base italic text-gray-600 text-sm">
|
||||
Works Alone. Works Together. Use Agents on top of any Mycelium Cloud deployment or pair them with the Mycelium Network for private, encrypted collaboration across users and systems.
|
||||
Mycelium Agents let you deploy and run intelligent systems on your own infrastructure.
|
||||
Private, local, and autonomous by design, they give you everything you need to build, host, and connect AI agents without relying on centralized clouds.
|
||||
</p>
|
||||
|
||||
<div className="mt-10 flex items-center gap-x-6">
|
||||
<Button href="#" variant="solid" color="cyan">
|
||||
Follow Deployment
|
||||
Follow Development
|
||||
</Button>
|
||||
<Button href="#" variant="outline">
|
||||
Explore Docs <span aria-hidden="true">→</span>
|
||||
|
||||
147
src/pages/agents/AgentUseCase.tsx
Normal file
147
src/pages/agents/AgentUseCase.tsx
Normal file
@@ -0,0 +1,147 @@
|
||||
"use client";
|
||||
|
||||
import { useRef } from "react";
|
||||
import { Eyebrow, SectionHeader, P } from "@/components/Texts";
|
||||
import { IoArrowBackOutline, IoArrowForwardOutline } from "react-icons/io5";
|
||||
|
||||
import {
|
||||
CpuChipIcon,
|
||||
GlobeAltIcon,
|
||||
LockClosedIcon,
|
||||
ArrowPathIcon,
|
||||
ShieldCheckIcon,
|
||||
} from "@heroicons/react/24/solid";
|
||||
|
||||
const networkUseCases = [
|
||||
{
|
||||
isIntro: true,
|
||||
eyebrow: "WHAT IT ENABLES",
|
||||
title: "What It Enables",
|
||||
description:
|
||||
"The framework gives you full control over where agents live, how they connect, and what data they use.",
|
||||
},
|
||||
{
|
||||
title: "Run agents on your own hardware",
|
||||
description:
|
||||
"Deploy AI processes on laptops, homelabs, edge nodes, or full clusters — no cloud dependency.",
|
||||
icon: CpuChipIcon,
|
||||
},
|
||||
{
|
||||
title: "Connect them over the secure Mycelium network",
|
||||
description:
|
||||
"Agents communicate privately across homes, clouds, countries, and environments in one address space.",
|
||||
icon: GlobeAltIcon,
|
||||
},
|
||||
{
|
||||
title: "Keep data and memory private by default",
|
||||
description:
|
||||
"Your datasets, tools, prompts, embeddings, and memory stay local unless you choose otherwise.",
|
||||
icon: LockClosedIcon,
|
||||
},
|
||||
{
|
||||
title: "Build workflows across cloud + edge",
|
||||
description:
|
||||
"Orchestrate multi-node jobs, pipelines, and real-time systems that live anywhere in your infrastructure.",
|
||||
icon: ArrowPathIcon,
|
||||
},
|
||||
{
|
||||
title: "Operate securely in regulated contexts",
|
||||
description:
|
||||
"Run agents in sectors requiring strict data residency, verified identity, and controlled connectivity.",
|
||||
icon: ShieldCheckIcon,
|
||||
},
|
||||
];
|
||||
|
||||
export function AgentUsecase() {
|
||||
const sliderRef = useRef<HTMLUListElement>(null);
|
||||
|
||||
const scrollLeft = () =>
|
||||
sliderRef.current?.scrollBy({ left: -400, behavior: "smooth" });
|
||||
|
||||
const scrollRight = () =>
|
||||
sliderRef.current?.scrollBy({ left: 400, behavior: "smooth" });
|
||||
|
||||
return (
|
||||
<section className="w-full max-w-8xl mx-auto bg-transparent">
|
||||
|
||||
{/* ✅ Top horizontal line with spacing */}
|
||||
<div className="max-w-7xl bg-transparent mx-auto py-6 border border-t-0 border-b-0 border-gray-100"></div>
|
||||
<div className="w-full border-t border-l border-r border-gray-100" />
|
||||
|
||||
<div className="relative mx-auto max-w-7xl border border-t-0 border-b-0 border-slate-200 bg-white overflow-hidden">
|
||||
<ul
|
||||
ref={sliderRef}
|
||||
className="flex overflow-x-auto snap-x snap-mandatory scroll-smooth no-scrollbar"
|
||||
>
|
||||
{networkUseCases.map((item, idx) => (
|
||||
<li
|
||||
key={idx}
|
||||
className={`snap-start shrink-0 w-[85%] sm:w-[50%] lg:w-[33%]
|
||||
border border-slate-200 px-10 py-12 relative
|
||||
${item.isIntro ? "bg-gray-50/80" : "bg-white"}`}
|
||||
>
|
||||
{/* INTRO CARD */}
|
||||
{item.isIntro ? (
|
||||
<div className="flex flex-col justify-between h-full">
|
||||
<div>
|
||||
<Eyebrow>{item.eyebrow}</Eyebrow>
|
||||
<SectionHeader
|
||||
as="h3"
|
||||
className="mt-4 text-gray-900 text-xl lg:text-2xl"
|
||||
>
|
||||
{item.title}
|
||||
</SectionHeader>
|
||||
<P className="mt-4 text-gray-600 text-sm lg:text-base">
|
||||
{item.description}
|
||||
</P>
|
||||
</div>
|
||||
|
||||
{/* slider buttons */}
|
||||
<div className="flex items-center gap-x-4 mt-6">
|
||||
<button
|
||||
onClick={scrollLeft}
|
||||
className="h-8 w-8 flex items-center justify-center
|
||||
border border-slate-300 rounded-md
|
||||
hover:border-cyan-500 transition-colors"
|
||||
>
|
||||
<IoArrowBackOutline className="text-gray-600" size={16} />
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={scrollRight}
|
||||
className="h-8 w-8 flex items-center justify-center
|
||||
border border-slate-300 rounded-md
|
||||
hover:border-cyan-500 transition-colors"
|
||||
>
|
||||
<IoArrowForwardOutline className="text-gray-600" size={16} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
/* REGULAR CARD */
|
||||
<div className="flex flex-col h-full">
|
||||
{item.icon && (
|
||||
<div className="h-12 w-12 flex items-center justify-center rounded-xl bg-gray-100 mb-6">
|
||||
<item.icon className="h-6 w-6 text-cyan-600" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<p className="text-lg font-semibold text-gray-900">
|
||||
{item.title}
|
||||
</p>
|
||||
|
||||
<p className="mt-2 text-gray-600 leading-snug">
|
||||
{item.description}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
{/* ✅ Bottom horizontal line with spacing */}
|
||||
<div className="w-full border-b border-gray-100" />
|
||||
<div className="max-w-7xl bg-transparent mx-auto py-6 border border-t-0 border-b-0 border-gray-100"></div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
import { AnimatedSection } from '../../components/AnimatedSection'
|
||||
import { DeploySection } from './DeploySection'
|
||||
import { GallerySection } from './GallerySection'
|
||||
import { Companies } from './Companies'
|
||||
import { AgentBento } from './AgentBento'
|
||||
import { AgentHeroAlt } from './AgentHeroAlt'
|
||||
import { CallToAction } from './CallToAction'
|
||||
import { AgentUsecase } from './AgentUseCase'
|
||||
import { AgentDesign } from './AgentDesign'
|
||||
|
||||
export default function AgentsPage() {
|
||||
return (
|
||||
@@ -22,13 +23,17 @@ export default function AgentsPage() {
|
||||
</AnimatedSection>
|
||||
|
||||
<AnimatedSection>
|
||||
<GallerySection />
|
||||
<AgentUsecase />
|
||||
</AnimatedSection>
|
||||
|
||||
<AnimatedSection>
|
||||
<AgentBento />
|
||||
</AnimatedSection>
|
||||
|
||||
<AnimatedSection>
|
||||
<AgentDesign />
|
||||
</AnimatedSection>
|
||||
|
||||
<AnimatedSection>
|
||||
<CallToAction />
|
||||
</AnimatedSection>
|
||||
|
||||
@@ -18,11 +18,14 @@ export function CallToAction() {
|
||||
<Container className="relative">
|
||||
<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">
|
||||
Start Building the Future of Sovereign AI
|
||||
Start with Mycelium Today
|
||||
</h2>
|
||||
|
||||
<p className="mt-6 text-lg text-gray-300">
|
||||
Use today’s components — models, storage, compute, mesh — and step into agents as they arrive.
|
||||
The Agent Framework launches in H1 2026, but the foundation is ready now.
|
||||
</p>
|
||||
<p className="mt-6 text-lg text-gray-300">
|
||||
Use today’s components —models, storage, compute, and network— to deploy workloads, connect nodes, and prepare for the next generation of distributed AI.
|
||||
</p>
|
||||
|
||||
{/* ✅ Two cards, stacked center with spacing */}
|
||||
|
||||
@@ -37,7 +37,7 @@ const row2 = logos.slice(6);
|
||||
|
||||
export function Companies() {
|
||||
return (
|
||||
<div id="companies" className="relative bg-[#121212] flex flex-col items-center justify-center w-full overflow-hidden antialiased py-4 mb-12">
|
||||
<div id="companies" className="relative bg-[#121212] flex flex-col items-center justify-center w-full overflow-hidden antialiased py-4">
|
||||
<div className="relative z-10 mx-auto w-full max-w-7xl p-4">
|
||||
{/* Logos grid */}
|
||||
<div className="flex flex-col items-center gap-y-6 text-white ">
|
||||
|
||||
264
src/pages/agents/animations/AgentCoordination.tsx
Normal file
264
src/pages/agents/animations/AgentCoordination.tsx
Normal file
@@ -0,0 +1,264 @@
|
||||
"use client";
|
||||
|
||||
import { motion, useReducedMotion } from "framer-motion";
|
||||
import clsx from "clsx";
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
accent?: string;
|
||||
bg?: string;
|
||||
};
|
||||
|
||||
const W = 760;
|
||||
const H = 420;
|
||||
|
||||
const AgentNode = ({
|
||||
x,
|
||||
y,
|
||||
r = 12,
|
||||
accent = "#00b8db",
|
||||
pulse = false,
|
||||
delay = 0,
|
||||
}: {
|
||||
x: number;
|
||||
y: number;
|
||||
r?: number;
|
||||
accent?: string;
|
||||
pulse?: boolean;
|
||||
delay?: number;
|
||||
}) => {
|
||||
const prefers = useReducedMotion();
|
||||
return (
|
||||
<>
|
||||
<motion.circle
|
||||
cx={x}
|
||||
cy={y}
|
||||
r={r + 10}
|
||||
stroke="#1F2937"
|
||||
strokeWidth={2}
|
||||
fill="none"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 0.7 }}
|
||||
transition={{ delay, duration: 0.6 }}
|
||||
/>
|
||||
|
||||
<motion.circle
|
||||
cx={x}
|
||||
cy={y}
|
||||
r={r}
|
||||
fill={accent}
|
||||
initial={{ opacity: 0, scale: 0.85 }}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
scale: pulse && !prefers ? [1, 1.12, 1] : 1,
|
||||
}}
|
||||
transition={{
|
||||
delay,
|
||||
duration: pulse ? 1.8 : 0.6,
|
||||
repeat: pulse && !prefers ? Infinity : 0,
|
||||
repeatType: "mirror",
|
||||
ease: [0.22, 1, 0.36, 1],
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const Packet = ({
|
||||
path,
|
||||
delay = 0,
|
||||
accent = "#00b8db",
|
||||
duration = 2.2,
|
||||
reverse = false,
|
||||
}: {
|
||||
path: string;
|
||||
delay?: number;
|
||||
accent?: string;
|
||||
duration?: number;
|
||||
reverse?: boolean;
|
||||
}) => {
|
||||
const prefers = useReducedMotion();
|
||||
return (
|
||||
<motion.circle
|
||||
r={4}
|
||||
fill={accent}
|
||||
initial={{ offsetDistance: reverse ? "100%" : "0%", opacity: 0 }}
|
||||
animate={{
|
||||
offsetDistance: reverse ? ["100%", "0%"] : ["0%", "100%"],
|
||||
opacity: [0, 1, 0],
|
||||
}}
|
||||
transition={{
|
||||
delay,
|
||||
duration,
|
||||
repeat: !prefers ? Infinity : 0,
|
||||
repeatType: "loop",
|
||||
ease: "linear",
|
||||
}}
|
||||
style={{
|
||||
offsetPath: `path('${path}')`,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default function AgentCoordination({
|
||||
className,
|
||||
accent = "#00b8db",
|
||||
bg = "#0a0a0a",
|
||||
}: Props) {
|
||||
const center = { x: 380, y: 210 };
|
||||
|
||||
// Specialist agents placed in a controlled orbit
|
||||
const agents = [
|
||||
{ x: 200, y: 120 },
|
||||
{ x: 560, y: 120 },
|
||||
{ x: 620, y: 260 },
|
||||
{ x: 500, y: 330 },
|
||||
{ x: 260, y: 330 },
|
||||
{ x: 140, y: 260 },
|
||||
];
|
||||
|
||||
const paths = agents.map(
|
||||
(a) => `M ${center.x} ${center.y} Q ${(center.x + a.x) / 2} ${(center.y + a.y) / 2 - 40} ${a.x} ${a.y}`
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx("relative overflow-hidden", className)}
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
aria-label="Agent coordination and sovereign workflow management"
|
||||
style={{ background: bg }}
|
||||
>
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full" preserveAspectRatio="xMidYMid slice">
|
||||
|
||||
{/* background */}
|
||||
<defs>
|
||||
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
||||
<path d="M 28 0 L 0 0 0 28" stroke="#0f0f0f" strokeWidth="1" />
|
||||
</pattern>
|
||||
|
||||
<radialGradient id="glow" cx="50%" cy="50%" r="50%">
|
||||
<stop offset="0%" stopColor={accent} stopOpacity="0.20" />
|
||||
<stop offset="100%" stopColor={accent} stopOpacity="0" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
|
||||
<rect width={W} height={H} fill="url(#grid-dark)" />
|
||||
|
||||
{/* global glow */}
|
||||
<circle cx={center.x} cy={center.y} r={240} fill="url(#glow)" opacity={0.45} />
|
||||
|
||||
{/* POLICY RING */}
|
||||
<motion.circle
|
||||
cx={center.x}
|
||||
cy={center.y}
|
||||
r={110}
|
||||
stroke={accent}
|
||||
strokeWidth={2}
|
||||
fill="none"
|
||||
strokeDasharray="14 10"
|
||||
animate={{ opacity: [0.25, 0.7, 0.25] }}
|
||||
transition={{
|
||||
duration: 3,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* CHECKPOINT GATE */}
|
||||
<motion.rect
|
||||
x={center.x - 50}
|
||||
y={center.y - 130}
|
||||
width={100}
|
||||
height={22}
|
||||
rx={6}
|
||||
stroke={accent}
|
||||
strokeWidth={2}
|
||||
fill="none"
|
||||
animate={{ opacity: [0.2, 0.7, 0.2] }}
|
||||
transition={{
|
||||
duration: 2.4,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* central conductor agent */}
|
||||
<motion.circle
|
||||
cx={center.x}
|
||||
cy={center.y}
|
||||
r={26}
|
||||
fill={accent}
|
||||
initial={{ opacity: 0, scale: 0.85 }}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
scale: [1, 1.06, 1],
|
||||
}}
|
||||
transition={{
|
||||
duration: 1.8,
|
||||
repeat: Infinity,
|
||||
repeatType: "mirror",
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* inward → outward routing lines */}
|
||||
{paths.map((p, i) => (
|
||||
<motion.path
|
||||
key={`p-${i}`}
|
||||
d={p}
|
||||
stroke="#1F2937"
|
||||
strokeWidth={3}
|
||||
strokeLinecap="round"
|
||||
fill="none"
|
||||
initial={{ pathLength: 0, opacity: 0 }}
|
||||
animate={{ pathLength: 1, opacity: 0.4 }}
|
||||
transition={{
|
||||
delay: i * 0.1,
|
||||
duration: 0.8,
|
||||
ease: [0.22, 1, 0.36, 1],
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* OUTBOUND tasks */}
|
||||
{paths.map((p, i) => (
|
||||
<Packet
|
||||
key={`out-${i}`}
|
||||
path={p}
|
||||
delay={0.3 * i}
|
||||
accent={accent}
|
||||
duration={2}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* INBOUND results */}
|
||||
{paths.map((p, i) => (
|
||||
<Packet
|
||||
key={`in-${i}`}
|
||||
path={p}
|
||||
reverse
|
||||
delay={0.5 * i}
|
||||
accent={accent}
|
||||
duration={2.2}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* specialist agents */}
|
||||
{agents.map((a, i) => (
|
||||
<AgentNode
|
||||
key={`agent-${i}`}
|
||||
x={a.x}
|
||||
y={a.y}
|
||||
pulse={i % 2 === 0}
|
||||
delay={i * 0.1}
|
||||
accent={accent}
|
||||
/>
|
||||
))}
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
263
src/pages/agents/animations/DeterministicExecution.tsx
Normal file
263
src/pages/agents/animations/DeterministicExecution.tsx
Normal file
@@ -0,0 +1,263 @@
|
||||
"use client";
|
||||
|
||||
import { motion, useReducedMotion } from "framer-motion";
|
||||
import clsx from "clsx";
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
accent?: string;
|
||||
bg?: string;
|
||||
};
|
||||
|
||||
const W = 760;
|
||||
const H = 420;
|
||||
|
||||
const PulseCircle = ({
|
||||
x,
|
||||
y,
|
||||
r,
|
||||
accent,
|
||||
delay = 0,
|
||||
}: {
|
||||
x: number;
|
||||
y: number;
|
||||
r: number;
|
||||
accent: string;
|
||||
delay?: number;
|
||||
}) => {
|
||||
const prefers = useReducedMotion();
|
||||
return (
|
||||
<motion.circle
|
||||
cx={x}
|
||||
cy={y}
|
||||
r={r}
|
||||
stroke={accent}
|
||||
strokeWidth={2}
|
||||
fill="none"
|
||||
initial={{ scale: 0.8, opacity: 0 }}
|
||||
animate={{
|
||||
scale: !prefers ? [1, 1.25, 1] : 1,
|
||||
opacity: !prefers ? [0.4, 0.9, 0.4] : 1,
|
||||
}}
|
||||
transition={{
|
||||
delay,
|
||||
duration: 2.2,
|
||||
repeat: !prefers ? Infinity : 0,
|
||||
repeatType: "mirror",
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const Packet = ({
|
||||
path,
|
||||
delay = 0,
|
||||
duration = 2,
|
||||
accent = "#00b8db",
|
||||
}: {
|
||||
path: string;
|
||||
delay?: number;
|
||||
duration?: number;
|
||||
accent?: string;
|
||||
}) => {
|
||||
const prefers = useReducedMotion();
|
||||
return (
|
||||
<motion.circle
|
||||
r={4}
|
||||
fill={accent}
|
||||
initial={{ offsetDistance: "0%", opacity: 0 }}
|
||||
animate={{
|
||||
offsetDistance: ["0%", "100%"],
|
||||
opacity: [0, 1, 0],
|
||||
}}
|
||||
transition={{
|
||||
delay,
|
||||
duration,
|
||||
repeat: !prefers ? Infinity : 0,
|
||||
repeatType: "loop",
|
||||
ease: "linear",
|
||||
}}
|
||||
style={{ offsetPath: `path('${path}')` }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default function DeterministicExecution({
|
||||
className,
|
||||
accent = "#00b8db",
|
||||
bg = "#0a0a0a",
|
||||
}: Props) {
|
||||
const left = { x: 200, y: 210 };
|
||||
const center = { x: 380, y: 210 };
|
||||
const right = { x: 560, y: 210 };
|
||||
|
||||
const leftToCenter = `M ${left.x} ${left.y} L ${center.x} ${center.y}`;
|
||||
const centerToRight = `M ${center.x} ${center.y} L ${right.x} ${right.y}`;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx("relative overflow-hidden", className)}
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
aria-label="Deterministic deployment and verifiable code execution"
|
||||
style={{ background: bg }}
|
||||
>
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full" preserveAspectRatio="xMidYMid slice">
|
||||
|
||||
{/* background grid */}
|
||||
<defs>
|
||||
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
||||
<path d="M 28 0 L 0 0 0 28" stroke="#0f0f0f" strokeWidth="1" />
|
||||
</pattern>
|
||||
|
||||
<radialGradient id="glow" cx="50%" cy="50%" r="50%">
|
||||
<stop offset="0%" stopColor={accent} stopOpacity="0.18" />
|
||||
<stop offset="100%" stopColor={accent} stopOpacity="0" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
|
||||
<rect width={W} height={H} fill="url(#grid-dark)" />
|
||||
|
||||
{/* global glow */}
|
||||
<circle cx={center.x} cy={center.y} r={230} fill="url(#glow)" opacity={0.4} />
|
||||
|
||||
{/* LEFT: Declare Intent block */}
|
||||
<motion.rect
|
||||
x={left.x - 60}
|
||||
y={left.y - 40}
|
||||
width={120}
|
||||
height={80}
|
||||
rx={10}
|
||||
stroke="#1F2937"
|
||||
strokeWidth={3}
|
||||
fill="none"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 0.8 }}
|
||||
transition={{ duration: 0.6 }}
|
||||
/>
|
||||
<motion.rect
|
||||
x={left.x - 45}
|
||||
y={left.y - 25}
|
||||
width={90}
|
||||
height={50}
|
||||
rx={6}
|
||||
fill={accent}
|
||||
initial={{ opacity: 0, scale: 0.85 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
/>
|
||||
|
||||
{/* CENTER: Cryptographic hash */}
|
||||
<motion.rect
|
||||
x={center.x - 40}
|
||||
y={center.y - 40}
|
||||
width={80}
|
||||
height={80}
|
||||
rx={12}
|
||||
stroke={accent}
|
||||
strokeWidth={2}
|
||||
strokeDasharray="10 6"
|
||||
fill="none"
|
||||
animate={{ opacity: [0.4, 0.9, 0.4] }}
|
||||
transition={{
|
||||
duration: 2,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* hash print */}
|
||||
<motion.text
|
||||
x={center.x}
|
||||
y={center.y + 5}
|
||||
textAnchor="middle"
|
||||
fill={accent}
|
||||
fontFamily="monospace"
|
||||
fontSize="14"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 0.9 }}
|
||||
transition={{ delay: 0.3 }}
|
||||
>
|
||||
9f1a..42c7
|
||||
</motion.text>
|
||||
|
||||
{/* signature stamp */}
|
||||
<motion.circle
|
||||
cx={center.x + 55}
|
||||
cy={center.y - 55}
|
||||
r={14}
|
||||
stroke={accent}
|
||||
strokeWidth={2}
|
||||
fill="none"
|
||||
initial={{ scale: 0, opacity: 0 }}
|
||||
animate={{ scale: 1, opacity: 1 }}
|
||||
transition={{ delay: 0.4, duration: 0.6 }}
|
||||
/>
|
||||
|
||||
{/* RIGHT: Verified Execution Node */}
|
||||
<motion.circle
|
||||
cx={right.x}
|
||||
cy={right.y}
|
||||
r={24}
|
||||
fill={accent}
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
scale: [1, 1.06, 1],
|
||||
}}
|
||||
transition={{
|
||||
duration: 1.8,
|
||||
repeat: Infinity,
|
||||
repeatType: "mirror",
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* outer attestation ring */}
|
||||
<PulseCircle x={right.x} y={right.y} r={40} accent={accent} delay={0.2} />
|
||||
|
||||
{/* immutable logs ring */}
|
||||
<motion.circle
|
||||
cx={right.x}
|
||||
cy={right.y}
|
||||
r={70}
|
||||
stroke={accent}
|
||||
strokeWidth={2}
|
||||
strokeDasharray="14 12"
|
||||
fill="none"
|
||||
animate={{ opacity: [0.2, 0.6, 0.2] }}
|
||||
transition={{
|
||||
duration: 3,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* deterministic path lines */}
|
||||
<motion.path
|
||||
d={leftToCenter}
|
||||
stroke="#1F2937"
|
||||
strokeWidth={3}
|
||||
fill="none"
|
||||
initial={{ pathLength: 0 }}
|
||||
animate={{ pathLength: 1 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
/>
|
||||
<motion.path
|
||||
d={centerToRight}
|
||||
stroke="#1F2937"
|
||||
strokeWidth={3}
|
||||
fill="none"
|
||||
initial={{ pathLength: 0 }}
|
||||
animate={{ pathLength: 1 }}
|
||||
transition={{ duration: 0.8, delay: 0.2 }}
|
||||
/>
|
||||
|
||||
{/* active cryptographic pulses */}
|
||||
<Packet path={leftToCenter} delay={0.4} accent={accent} duration={1.8} />
|
||||
<Packet path={centerToRight} delay={0.8} accent={accent} duration={1.8} />
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
238
src/pages/agents/animations/Fungistor.tsx
Normal file
238
src/pages/agents/animations/Fungistor.tsx
Normal file
@@ -0,0 +1,238 @@
|
||||
"use client";
|
||||
|
||||
import { motion, useReducedMotion } from "framer-motion";
|
||||
import clsx from "clsx";
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
accent?: string;
|
||||
bg?: string;
|
||||
};
|
||||
|
||||
const W = 760;
|
||||
const H = 420;
|
||||
|
||||
const Node = ({
|
||||
x,
|
||||
y,
|
||||
r = 10,
|
||||
accent = "#00b8db",
|
||||
pulse = false,
|
||||
delay = 0,
|
||||
}: {
|
||||
x: number;
|
||||
y: number;
|
||||
r?: number;
|
||||
accent?: string;
|
||||
pulse?: boolean;
|
||||
delay?: number;
|
||||
}) => {
|
||||
const prefers = useReducedMotion();
|
||||
return (
|
||||
<>
|
||||
{/* outer faint ring */}
|
||||
<motion.circle
|
||||
cx={x}
|
||||
cy={y}
|
||||
r={r + 10}
|
||||
stroke="#1F2937"
|
||||
strokeWidth={2}
|
||||
fill="none"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 0.6 }}
|
||||
transition={{ delay, duration: 0.6 }}
|
||||
/>
|
||||
{/* glowing shard node */}
|
||||
<motion.circle
|
||||
cx={x}
|
||||
cy={y}
|
||||
r={r}
|
||||
fill={accent}
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
scale: pulse && !prefers ? [1, 1.12, 1] : 1,
|
||||
}}
|
||||
transition={{
|
||||
delay,
|
||||
duration: pulse && !prefers ? 1.8 : 0.6,
|
||||
repeat: pulse && !prefers ? Infinity : 0,
|
||||
repeatType: "mirror",
|
||||
ease: [0.22, 1, 0.36, 1],
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const Shard = ({
|
||||
path,
|
||||
delay = 0,
|
||||
accent = "#00b8db",
|
||||
duration = 2,
|
||||
}: {
|
||||
path: string;
|
||||
delay?: number;
|
||||
accent?: string;
|
||||
duration?: number;
|
||||
}) => {
|
||||
const prefers = useReducedMotion();
|
||||
return (
|
||||
<motion.circle
|
||||
r={4}
|
||||
fill={accent}
|
||||
initial={{ offsetDistance: "0%", opacity: 0 }}
|
||||
animate={{
|
||||
offsetDistance: ["0%", "100%"],
|
||||
opacity: [0, 1, 0],
|
||||
}}
|
||||
transition={{
|
||||
delay,
|
||||
duration,
|
||||
repeat: !prefers ? Infinity : 0,
|
||||
repeatType: "loop",
|
||||
ease: "linear",
|
||||
}}
|
||||
style={{ offsetPath: `path('${path}')` }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default function FungiStor({
|
||||
className,
|
||||
accent = "#00b8db",
|
||||
bg = "#0a0a0a",
|
||||
}: Props) {
|
||||
const center = { x: 380, y: 210 };
|
||||
const shardNodes = [
|
||||
{ x: 160, y: 100 },
|
||||
{ x: 260, y: 70 },
|
||||
{ x: 580, y: 100 },
|
||||
{ x: 620, y: 250 },
|
||||
{ x: 500, y: 330 },
|
||||
{ x: 240, y: 320 },
|
||||
];
|
||||
|
||||
// outgoing shard paths
|
||||
const paths = shardNodes.map(
|
||||
(n) => `M ${center.x} ${center.y} Q ${(n.x + center.x) / 2} ${(n.y + center.y) / 2 - 40} ${n.x} ${n.y}`
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx("relative overflow-hidden", className)}
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
aria-label="FungiStor — distributed long-term AI memory"
|
||||
style={{ background: bg }}
|
||||
>
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full" preserveAspectRatio="xMidYMid slice">
|
||||
{/* Background grid */}
|
||||
<defs>
|
||||
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
||||
<path d="M 28 0 L 0 0 0 28" fill="none" stroke="#0f0f0f" strokeWidth="1" />
|
||||
</pattern>
|
||||
<radialGradient id="glow" cx="50%" cy="50%" r="50%">
|
||||
<stop offset="0%" stopColor={accent} stopOpacity="0.15" />
|
||||
<stop offset="100%" stopColor={accent} stopOpacity="0" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
|
||||
<rect width={W} height={H} fill="url(#grid-dark)" />
|
||||
|
||||
{/* Soft global network glow */}
|
||||
<circle cx={center.x} cy={center.y} r={180} fill="url(#glow)" opacity={0.4} />
|
||||
|
||||
{/* Source data core */}
|
||||
<motion.rect
|
||||
x={center.x - 40}
|
||||
y={center.y - 40}
|
||||
width={80}
|
||||
height={80}
|
||||
rx={12}
|
||||
fill="none"
|
||||
stroke={accent}
|
||||
strokeWidth={2}
|
||||
strokeDasharray="10 6"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: [0.4, 0.9, 0.4] }}
|
||||
transition={{ duration: 2, repeat: Infinity, ease: "easeInOut" }}
|
||||
/>
|
||||
<motion.rect
|
||||
x={center.x - 20}
|
||||
y={center.y - 20}
|
||||
width={40}
|
||||
height={40}
|
||||
rx={6}
|
||||
fill={accent}
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
scale: [1, 1.08, 1],
|
||||
}}
|
||||
transition={{
|
||||
duration: 1.8,
|
||||
repeat: Infinity,
|
||||
repeatType: "mirror",
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Outgoing shard connections */}
|
||||
{paths.map((p, i) => (
|
||||
<motion.path
|
||||
key={`path-${i}`}
|
||||
d={p}
|
||||
stroke="#1F2937"
|
||||
strokeWidth={2}
|
||||
fill="none"
|
||||
initial={{ pathLength: 0, opacity: 0 }}
|
||||
animate={{ pathLength: 1, opacity: 0.4 }}
|
||||
transition={{
|
||||
delay: 0.05 * i,
|
||||
duration: 0.8,
|
||||
ease: [0.22, 1, 0.36, 1],
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* Animated data shards traveling */}
|
||||
{paths.map((p, i) => (
|
||||
<Shard key={`shard-${i}`} path={p} delay={i * 0.4} accent={accent} duration={2.6} />
|
||||
))}
|
||||
|
||||
{/* Destination storage nodes */}
|
||||
{shardNodes.map((n, i) => (
|
||||
<Node
|
||||
key={`node-${i}`}
|
||||
x={n.x}
|
||||
y={n.y}
|
||||
accent={accent}
|
||||
pulse={i % 2 === 0}
|
||||
delay={i * 0.1}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* “Reconstruction glow” pulse ring */}
|
||||
<motion.circle
|
||||
cx={center.x}
|
||||
cy={center.y}
|
||||
r={110}
|
||||
stroke={accent}
|
||||
strokeWidth={2}
|
||||
fill="none"
|
||||
initial={{ scale: 0.9, opacity: 0 }}
|
||||
animate={{
|
||||
scale: [0.9, 1.2, 0.9],
|
||||
opacity: [0.2, 0.6, 0.2],
|
||||
}}
|
||||
transition={{
|
||||
duration: 3.2,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
286
src/pages/agents/animations/Herodb.tsx
Normal file
286
src/pages/agents/animations/Herodb.tsx
Normal file
@@ -0,0 +1,286 @@
|
||||
"use client";
|
||||
|
||||
import { motion, useReducedMotion } from "framer-motion";
|
||||
import clsx from "clsx";
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
accent?: string;
|
||||
bg?: string;
|
||||
};
|
||||
|
||||
const W = 760;
|
||||
const H = 420;
|
||||
|
||||
const Node = ({
|
||||
x,
|
||||
y,
|
||||
r = 12,
|
||||
accent = "#00b8db",
|
||||
pulse = false,
|
||||
delay = 0,
|
||||
type = "dot",
|
||||
}: {
|
||||
x: number;
|
||||
y: number;
|
||||
r?: number;
|
||||
accent?: string;
|
||||
pulse?: boolean;
|
||||
delay?: number;
|
||||
type?: "dot" | "text" | "image" | "audio";
|
||||
}) => {
|
||||
const prefers = useReducedMotion();
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* faint ring */}
|
||||
<motion.circle
|
||||
cx={x}
|
||||
cy={y}
|
||||
r={r + 10}
|
||||
stroke="#1F2937"
|
||||
strokeWidth={2}
|
||||
fill="none"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 0.7 }}
|
||||
transition={{ delay, duration: 0.6 }}
|
||||
/>
|
||||
|
||||
{/* inner icon shape to represent modality */}
|
||||
{type === "text" && (
|
||||
<motion.rect
|
||||
x={x - r}
|
||||
y={y - r / 2}
|
||||
width={r * 2}
|
||||
height={r}
|
||||
rx={3}
|
||||
fill={accent}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay }}
|
||||
/>
|
||||
)}
|
||||
{type === "image" && (
|
||||
<motion.path
|
||||
d={`M ${x - r} ${y + r/2} L ${x - r} ${y - r/2} L ${x + r} ${y - r/2} L ${x + r} ${y + r/2} Z`}
|
||||
stroke={accent}
|
||||
strokeWidth={2}
|
||||
fill="none"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay }}
|
||||
/>
|
||||
)}
|
||||
{type === "audio" && (
|
||||
<motion.path
|
||||
d={`
|
||||
M ${x - r/2} ${y - r/2}
|
||||
L ${x - r/2} ${y + r/2}
|
||||
M ${x} ${y - r/3}
|
||||
L ${x} ${y + r/3}
|
||||
M ${x + r/2} ${y - r/4}
|
||||
L ${x + r/2} ${y + r/4}
|
||||
`}
|
||||
stroke={accent}
|
||||
strokeWidth={2}
|
||||
strokeLinecap="round"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay }}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* standard pulsing circle fallback */}
|
||||
{type === "dot" && (
|
||||
<motion.circle
|
||||
cx={x}
|
||||
cy={y}
|
||||
r={r}
|
||||
fill={accent}
|
||||
initial={{ opacity: 0, scale: 0.85 }}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
scale: pulse && !prefers ? [1, 1.12, 1] : 1,
|
||||
}}
|
||||
transition={{
|
||||
delay,
|
||||
duration: pulse && !prefers ? 1.6 : 0.6,
|
||||
repeat: pulse && !prefers ? Infinity : 0,
|
||||
repeatType: "mirror",
|
||||
ease: [0.22, 1, 0.36, 1],
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
// inward pulse particle
|
||||
const Packet = ({
|
||||
path,
|
||||
delay = 0,
|
||||
accent = "#00b8db",
|
||||
duration = 1.8,
|
||||
}: {
|
||||
path: string;
|
||||
delay?: number;
|
||||
accent?: string;
|
||||
duration?: number;
|
||||
}) => {
|
||||
const prefers = useReducedMotion();
|
||||
return (
|
||||
<motion.circle
|
||||
r={4}
|
||||
fill={accent}
|
||||
initial={{ offsetDistance: "100%", opacity: 0 }}
|
||||
animate={{
|
||||
offsetDistance: ["100%", "0%"],
|
||||
opacity: [0, 1, 0],
|
||||
}}
|
||||
transition={{
|
||||
delay,
|
||||
duration,
|
||||
repeat: !prefers ? Infinity : 0,
|
||||
repeatType: "loop",
|
||||
ease: "linear",
|
||||
}}
|
||||
style={{ offsetPath: `path('${path}')` }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default function Herodb({
|
||||
className,
|
||||
accent = "#00b8db",
|
||||
bg = "#0a0a0a",
|
||||
}: Props) {
|
||||
const center = { x: 380, y: 210 };
|
||||
|
||||
const shardNodes = [
|
||||
{ x: 160, y: 100, type: "text" },
|
||||
{ x: 580, y: 120, type: "image" },
|
||||
{ x: 620, y: 280, type: "audio" },
|
||||
{ x: 420, y: 330, type: "text" },
|
||||
{ x: 240, y: 320, type: "image" },
|
||||
{ x: 150, y: 220, type: "dot" },
|
||||
];
|
||||
|
||||
const paths = shardNodes.map(
|
||||
(n) =>
|
||||
`M ${n.x} ${n.y} Q ${(n.x + center.x) / 2} ${(n.y + center.y) / 2 - 40} ${center.x} ${center.y}`
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx("relative overflow-hidden", className)}
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
aria-label="HeroDB — active AI memory retrieval"
|
||||
style={{ background: bg }}
|
||||
>
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full" preserveAspectRatio="xMidYMid slice">
|
||||
{/* Background grid */}
|
||||
<defs>
|
||||
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
||||
<path d="M 28 0 L 0 0 0 28" fill="none" stroke="#0f0f0f" strokeWidth="1" />
|
||||
</pattern>
|
||||
<radialGradient id="glow" cx="50%" cy="50%" r="50%">
|
||||
<stop offset="0%" stopColor={accent} stopOpacity="0.18" />
|
||||
<stop offset="100%" stopColor={accent} stopOpacity="0" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
|
||||
<rect width={W} height={H} fill="url(#grid-dark)" />
|
||||
|
||||
{/* global halo */}
|
||||
<circle
|
||||
cx={center.x}
|
||||
cy={center.y}
|
||||
r={200}
|
||||
fill="url(#glow)"
|
||||
opacity={0.45}
|
||||
/>
|
||||
|
||||
{/* core retrieval sphere */}
|
||||
<motion.circle
|
||||
cx={center.x}
|
||||
cy={center.y}
|
||||
r={22}
|
||||
fill={accent}
|
||||
initial={{ opacity: 0, scale: 0.85 }}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
scale: [1, 1.05, 1],
|
||||
}}
|
||||
transition={{
|
||||
duration: 1.6,
|
||||
repeat: Infinity,
|
||||
repeatType: "mirror",
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* core aura ring */}
|
||||
<motion.circle
|
||||
cx={center.x}
|
||||
cy={center.y}
|
||||
r={40}
|
||||
stroke={accent}
|
||||
strokeWidth={2}
|
||||
fill="none"
|
||||
animate={{
|
||||
opacity: [0.2, 0.7, 0.2],
|
||||
}}
|
||||
transition={{
|
||||
duration: 2.2,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* inward paths */}
|
||||
{paths.map((p, i) => (
|
||||
<motion.path
|
||||
key={`path-${i}`}
|
||||
d={p}
|
||||
stroke="#1F2937"
|
||||
strokeWidth={2}
|
||||
fill="none"
|
||||
initial={{ pathLength: 0, opacity: 0 }}
|
||||
animate={{ pathLength: 1, opacity: 0.4 }}
|
||||
transition={{
|
||||
delay: 0.05 * i,
|
||||
duration: 0.7,
|
||||
ease: [0.22, 1, 0.36, 1],
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* packets flowing inward */}
|
||||
{paths.map((p, i) => (
|
||||
<Packet
|
||||
key={`pkt-${i}`}
|
||||
path={p}
|
||||
delay={i * 0.3}
|
||||
accent={accent}
|
||||
duration={1.8}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* modality nodes */}
|
||||
{shardNodes.map((n, i) => (
|
||||
<Node
|
||||
key={`node-${i}`}
|
||||
x={n.x}
|
||||
y={n.y}
|
||||
type={n.type as any}
|
||||
r={12}
|
||||
accent={accent}
|
||||
pulse={i % 2 === 0}
|
||||
delay={i * 0.1}
|
||||
/>
|
||||
))}
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
231
src/pages/agents/animations/MOSSandboxes.tsx
Normal file
231
src/pages/agents/animations/MOSSandboxes.tsx
Normal file
@@ -0,0 +1,231 @@
|
||||
"use client";
|
||||
|
||||
import { motion, useReducedMotion } from "framer-motion";
|
||||
import clsx from "clsx";
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
accent?: string;
|
||||
bg?: string;
|
||||
};
|
||||
|
||||
const W = 760;
|
||||
const H = 420;
|
||||
|
||||
const PulseRing = ({
|
||||
x,
|
||||
y,
|
||||
accent,
|
||||
delay = 0,
|
||||
}: {
|
||||
x: number;
|
||||
y: number;
|
||||
accent: string;
|
||||
delay?: number;
|
||||
}) => {
|
||||
const prefers = useReducedMotion();
|
||||
return (
|
||||
<motion.circle
|
||||
cx={x}
|
||||
cy={y}
|
||||
r={42}
|
||||
stroke={accent}
|
||||
strokeWidth={2}
|
||||
fill="none"
|
||||
initial={{ scale: 0.85, opacity: 0 }}
|
||||
animate={{
|
||||
scale: !prefers ? [1, 1.12, 1] : 1,
|
||||
opacity: !prefers ? [0.15, 0.6, 0.15] : 0.4,
|
||||
}}
|
||||
transition={{
|
||||
delay,
|
||||
duration: 2,
|
||||
repeat: !prefers ? Infinity : 0,
|
||||
repeatType: "mirror",
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const Egress = ({
|
||||
from,
|
||||
to,
|
||||
delay = 0,
|
||||
accent = "#00b8db",
|
||||
}: {
|
||||
from: { x: number; y: number };
|
||||
to: { x: number; y: number };
|
||||
delay?: number;
|
||||
accent?: string;
|
||||
}) => {
|
||||
const path = `M ${from.x} ${from.y} L ${to.x} ${to.y}`;
|
||||
const prefers = useReducedMotion();
|
||||
|
||||
return (
|
||||
<>
|
||||
<motion.path
|
||||
d={path}
|
||||
stroke="#1F2937"
|
||||
strokeWidth={3}
|
||||
strokeLinecap="round"
|
||||
fill="none"
|
||||
initial={{ pathLength: 0, opacity: 0 }}
|
||||
animate={{ pathLength: 1, opacity: 0.4 }}
|
||||
transition={{
|
||||
delay,
|
||||
duration: 0.8,
|
||||
ease: [0.22, 1, 0.36, 1],
|
||||
}}
|
||||
/>
|
||||
|
||||
<motion.circle
|
||||
r={4}
|
||||
fill={accent}
|
||||
initial={{ offsetDistance: "0%", opacity: 0 }}
|
||||
animate={{
|
||||
offsetDistance: ["0%", "100%"],
|
||||
opacity: [0, 1, 0],
|
||||
}}
|
||||
transition={{
|
||||
delay,
|
||||
duration: 1.6,
|
||||
repeat: !prefers ? Infinity : 0,
|
||||
repeatType: "loop",
|
||||
ease: "linear",
|
||||
}}
|
||||
style={{
|
||||
offsetPath: `path('${path}')`,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default function MOSSandboxes({
|
||||
className,
|
||||
accent = "#00b8db",
|
||||
bg = "#0a0a0a",
|
||||
}: Props) {
|
||||
const center = { x: 380, y: 210 };
|
||||
|
||||
// scoped egress ports
|
||||
const egress = [
|
||||
{ from: center, to: { x: 520, y: 140 } },
|
||||
{ from: center, to: { x: 520, y: 280 } },
|
||||
{ from: center, to: { x: 260, y: 320 } },
|
||||
];
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx("relative overflow-hidden", className)}
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
aria-label="MOS Secure Agent Sandboxes"
|
||||
style={{ background: bg }}
|
||||
>
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full" preserveAspectRatio="xMidYMid slice">
|
||||
{/* BACKGROUND GRID */}
|
||||
<defs>
|
||||
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
||||
<path d="M 28 0 L 0 0 0 28" stroke="#0f0f0f" strokeWidth="1" />
|
||||
</pattern>
|
||||
|
||||
<radialGradient id="glow" cx="50%" cy="50%" r="50%">
|
||||
<stop offset="0%" stopColor={accent} stopOpacity="0.20" />
|
||||
<stop offset="100%" stopColor={accent} stopOpacity="0" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
|
||||
<rect width={W} height={H} fill="url(#grid-dark)" />
|
||||
|
||||
{/* GLOBAL GLOW */}
|
||||
<circle cx={center.x} cy={center.y} r={200} fill="url(#glow)" opacity={0.45} />
|
||||
|
||||
{/* SANDBOX OUTER ENCLAVE */}
|
||||
<motion.rect
|
||||
x={center.x - 90}
|
||||
y={center.y - 60}
|
||||
width={180}
|
||||
height={120}
|
||||
rx={16}
|
||||
stroke="#1F2937"
|
||||
strokeWidth={3}
|
||||
fill="none"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 0.7 }}
|
||||
transition={{ duration: 0.6 }}
|
||||
/>
|
||||
|
||||
{/* ATTESTATION RING */}
|
||||
<PulseRing x={center.x} y={center.y} accent={accent} delay={0.3} />
|
||||
|
||||
{/* SIGNED WORKSPACE CORE */}
|
||||
<motion.rect
|
||||
x={center.x - 40}
|
||||
y={center.y - 30}
|
||||
width={80}
|
||||
height={60}
|
||||
rx={10}
|
||||
stroke={accent}
|
||||
strokeWidth={2}
|
||||
strokeDasharray="10 6"
|
||||
fill="none"
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
animate={{
|
||||
opacity: [0.4, 0.9, 0.4],
|
||||
scale: [1, 1.06, 1],
|
||||
}}
|
||||
transition={{
|
||||
duration: 2,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* SANDBOX ACTIVE PAYLOAD */}
|
||||
<motion.circle
|
||||
cx={center.x}
|
||||
cy={center.y}
|
||||
r={18}
|
||||
fill={accent}
|
||||
initial={{ scale: 0.6, opacity: 0 }}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
scale: [1, 1.1, 1],
|
||||
}}
|
||||
transition={{
|
||||
duration: 1.8,
|
||||
repeat: Infinity,
|
||||
repeatType: "mirror",
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* EGRESS PATHS */}
|
||||
{egress.map((e, i) => (
|
||||
<Egress key={i} from={e.from} to={e.to} delay={i * 0.2} accent={accent} />
|
||||
))}
|
||||
|
||||
{/* “TEAR DOWN” FADE — ephemeral sandbox lifecycle */}
|
||||
<motion.rect
|
||||
x={center.x - 90}
|
||||
y={center.y - 60}
|
||||
width={180}
|
||||
height={120}
|
||||
rx={16}
|
||||
fill={accent}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{
|
||||
opacity: [0, 0, 0.12, 0],
|
||||
}}
|
||||
transition={{
|
||||
duration: 4,
|
||||
repeat: Infinity,
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
231
src/pages/agents/animations/MyceliumMesh.tsx
Normal file
231
src/pages/agents/animations/MyceliumMesh.tsx
Normal file
@@ -0,0 +1,231 @@
|
||||
"use client";
|
||||
|
||||
import { motion, useReducedMotion } from "framer-motion";
|
||||
import clsx from "clsx";
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
accent?: string;
|
||||
bg?: string;
|
||||
};
|
||||
|
||||
const W = 760;
|
||||
const H = 420;
|
||||
|
||||
const Node = ({
|
||||
x,
|
||||
y,
|
||||
r = 12,
|
||||
accent = "#00b8db",
|
||||
pulse = false,
|
||||
delay = 0,
|
||||
}: {
|
||||
x: number;
|
||||
y: number;
|
||||
r?: number;
|
||||
accent?: string;
|
||||
pulse?: boolean;
|
||||
delay?: number;
|
||||
}) => {
|
||||
const prefers = useReducedMotion();
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Outer ring */}
|
||||
<motion.circle
|
||||
cx={x}
|
||||
cy={y}
|
||||
r={r + 8}
|
||||
stroke="#1F2937"
|
||||
strokeWidth={2}
|
||||
fill="none"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 0.8 }}
|
||||
transition={{ duration: 0.6, delay }}
|
||||
/>
|
||||
|
||||
{/* Core node */}
|
||||
<motion.circle
|
||||
cx={x}
|
||||
cy={y}
|
||||
r={r}
|
||||
fill={accent}
|
||||
initial={{ opacity: 0, scale: 0.85 }}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
scale: pulse && !prefers ? [1, 1.1, 1] : 1,
|
||||
}}
|
||||
transition={{
|
||||
duration: pulse ? 1.6 : 0.6,
|
||||
repeat: pulse && !prefers ? Infinity : 0,
|
||||
repeatType: "mirror",
|
||||
ease: [0.22, 1, 0.36, 1],
|
||||
delay,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
/* Animated encrypted packet */
|
||||
const Packet = ({
|
||||
path,
|
||||
delay = 0,
|
||||
accent = "#00b8db",
|
||||
duration = 2.4,
|
||||
}: {
|
||||
path: string;
|
||||
delay?: number;
|
||||
accent?: string;
|
||||
duration?: number;
|
||||
}) => {
|
||||
const prefers = useReducedMotion();
|
||||
|
||||
return (
|
||||
<motion.circle
|
||||
r={5}
|
||||
fill={accent}
|
||||
initial={{ offsetDistance: "0%", opacity: 0 }}
|
||||
animate={{
|
||||
offsetDistance: ["0%", "100%"],
|
||||
opacity: [0, 1, 0],
|
||||
}}
|
||||
transition={{
|
||||
delay,
|
||||
duration,
|
||||
repeat: !prefers ? Infinity : 0,
|
||||
repeatType: "loop",
|
||||
ease: "linear",
|
||||
}}
|
||||
style={{ offsetPath: `path('${path}')` }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default function MyceliumMesh({
|
||||
className,
|
||||
accent = "#00b8db",
|
||||
bg = "#0a0a0a",
|
||||
}: Props) {
|
||||
const center = { x: 380, y: 210 };
|
||||
|
||||
// Peer nodes forming a mesh
|
||||
const nodes = [
|
||||
{ x: 180, y: 120 },
|
||||
{ x: 580, y: 100 },
|
||||
{ x: 620, y: 260 },
|
||||
{ x: 460, y: 330 },
|
||||
{ x: 240, y: 320 },
|
||||
{ x: 140, y: 240 },
|
||||
];
|
||||
|
||||
// Multi-path routing (3 routes to illustrate "self-healing")
|
||||
const routes = [
|
||||
[nodes[0], nodes[1], nodes[2]], // path A→B→C
|
||||
[nodes[0], nodes[5], nodes[4], nodes[3]], // path A→F→E→D
|
||||
[nodes[1], nodes[4], nodes[3]], // path B→E→D
|
||||
];
|
||||
|
||||
// Convert list of nodes → SVG path
|
||||
const toPath = (list: any[]) =>
|
||||
list
|
||||
.map((p: any, i: number) =>
|
||||
i === 0 ? `M ${p.x} ${p.y}` : `L ${p.x} ${p.y}`
|
||||
)
|
||||
.join(" ");
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"relative overflow-hidden",
|
||||
className
|
||||
)}
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
aria-label="Mycelium Mesh — secure communication network"
|
||||
style={{ background: bg }}
|
||||
>
|
||||
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full" preserveAspectRatio="xMidYMid slice">
|
||||
{/* Background grid */}
|
||||
<defs>
|
||||
<pattern id="grid-dark" width="28" height="28" patternUnits="userSpaceOnUse">
|
||||
<path d="M 28 0 L 0 0 0 28" stroke="#0f0f0f" strokeWidth="1" />
|
||||
</pattern>
|
||||
|
||||
<radialGradient id="glow" cx="50%" cy="50%" r="50%">
|
||||
<stop offset="0%" stopColor={accent} stopOpacity="0.18" />
|
||||
<stop offset="100%" stopColor={accent} stopOpacity="0" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
|
||||
<rect width={W} height={H} fill="url(#grid-dark)" />
|
||||
|
||||
{/* Wide ambient glow */}
|
||||
<circle cx={center.x} cy={center.y} r={240} fill="url(#glow)" opacity={0.45} />
|
||||
|
||||
{/* Multi-path routing lines */}
|
||||
{routes.map((pathNodes, i) => (
|
||||
<motion.path
|
||||
key={`line-${i}`}
|
||||
d={toPath(pathNodes)}
|
||||
stroke="#1F2937"
|
||||
strokeWidth={3}
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
initial={{ pathLength: 0, opacity: 0 }}
|
||||
animate={{ pathLength: 1, opacity: 0.4 }}
|
||||
transition={{
|
||||
delay: 0.2 * i,
|
||||
duration: 1,
|
||||
ease: [0.22, 1, 0.36, 1],
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* Cyan “active” encrypted routing */}
|
||||
{routes.map((pathNodes, i) => (
|
||||
<motion.path
|
||||
key={`signal-${i}`}
|
||||
d={toPath(pathNodes)}
|
||||
stroke={accent}
|
||||
strokeWidth={2.5}
|
||||
strokeDasharray="12 10"
|
||||
strokeLinecap="round"
|
||||
fill="none"
|
||||
animate={{ opacity: [0.25, 0.8, 0.25] }}
|
||||
transition={{
|
||||
duration: 2.4,
|
||||
repeat: Infinity,
|
||||
delay: i * 0.3,
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* Moving encrypted packets */}
|
||||
{routes.map((pathNodes, i) => (
|
||||
<Packet
|
||||
key={`pkt-${i}`}
|
||||
path={toPath(pathNodes)}
|
||||
delay={i * 0.5}
|
||||
duration={2.6}
|
||||
accent={accent}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* Pulse nodes */}
|
||||
{nodes.map((n, i) => (
|
||||
<Node
|
||||
key={`node-${i}`}
|
||||
x={n.x}
|
||||
y={n.y}
|
||||
r={12}
|
||||
accent={accent}
|
||||
pulse={i % 2 === 0}
|
||||
delay={i * 0.15}
|
||||
/>
|
||||
))}
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user