forked from emre/www_projectmycelium_com
- 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
232 lines
5.3 KiB
TypeScript
232 lines
5.3 KiB
TypeScript
"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>
|
|
);
|
|
}
|