forked from emre/www_projectmycelium_com
- Increased CloudHeroNew vertical padding on large screens (lg:py-16 to lg:py-24) - Reduced spacing between description paragraphs in CloudHeroNew (mt-4 to mt-2) - Created PodsBento component with animated bento grid showcasing pod benefits - Added animations for data control, connectivity, security, and resilience features - Refactored PodsDesign from accordion layout to centered intro with 4-column grid - Create
190 lines
5.4 KiB
TypeScript
190 lines
5.4 KiB
TypeScript
"use client";
|
|
|
|
import { motion, useReducedMotion } from "framer-motion";
|
|
import clsx from "clsx";
|
|
|
|
type Props = {
|
|
className?: string;
|
|
accent?: string;
|
|
gridStroke?: string;
|
|
};
|
|
|
|
const W = 760;
|
|
const H = 420;
|
|
|
|
export default function Deterministic({
|
|
className,
|
|
accent = "#00b8db",
|
|
gridStroke = "#2b2a2a",
|
|
}: Props) {
|
|
const prefers = useReducedMotion();
|
|
|
|
const stages = [
|
|
{ x: 180, y: 180, w: 120, h: 80, label: "Build" },
|
|
{ x: 330, y: 180, w: 120, h: 80, label: "Package" },
|
|
{ x: 480, y: 180, w: 120, h: 80, label: "Deploy" },
|
|
];
|
|
|
|
// Packet path (deterministic flow)
|
|
const packetPath = `M ${stages[0].x + 120} ${stages[0].y + 40}
|
|
L ${stages[1].x + 0} ${stages[1].y + 40}
|
|
L ${stages[1].x + 120} ${stages[1].y + 40}
|
|
L ${stages[2].x + 0} ${stages[2].y + 40}`;
|
|
|
|
// tiny arrow for each transition
|
|
const arrows = [
|
|
`M ${stages[0].x + 120} ${stages[0].y + 40} L ${stages[1].x + 6} ${stages[1].y + 40}`,
|
|
`M ${stages[1].x + 120} ${stages[1].y + 40} L ${stages[2].x + 6} ${stages[2].y + 40}`
|
|
];
|
|
|
|
return (
|
|
<div
|
|
className={clsx("relative overflow-hidden", className)}
|
|
aria-hidden="true"
|
|
role="img"
|
|
aria-label="Deterministic orchestration: predictable deployments"
|
|
style={{ background: "transparent" }}
|
|
>
|
|
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full">
|
|
|
|
{/* BACKGROUND GRID */}
|
|
<defs>
|
|
<pattern id="grid-orch" width="28" height="28" patternUnits="userSpaceOnUse">
|
|
<path d="M 28 0 L 0 0 0 28"
|
|
fill="none"
|
|
stroke={gridStroke}
|
|
strokeWidth="1"
|
|
opacity="0.45"
|
|
/>
|
|
</pattern>
|
|
|
|
{/* Soft glow for highlight */}
|
|
<filter id="orch-glow">
|
|
<feGaussianBlur stdDeviation="4" result="blur" />
|
|
<feMerge>
|
|
<feMergeNode in="blur" />
|
|
<feMergeNode in="SourceGraphic" />
|
|
</feMerge>
|
|
</filter>
|
|
</defs>
|
|
|
|
<rect width={W} height={H} fill="url(#grid-orch)" />
|
|
|
|
{/* STAGE BOXES */}
|
|
{stages.map((s, i) => (
|
|
<motion.rect
|
|
key={`stage-${i}`}
|
|
x={s.x}
|
|
y={s.y}
|
|
width={s.w}
|
|
height={s.h}
|
|
rx={14}
|
|
fill="#0d0d0d"
|
|
stroke="#1a1a1a"
|
|
strokeWidth={2}
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 0.9 }}
|
|
transition={{ duration: 0.6 + i * 0.1 }}
|
|
/>
|
|
))}
|
|
|
|
{/* Stage labels (subtle, not text-heavy) */}
|
|
{stages.map((s, i) => (
|
|
<motion.text
|
|
key={`label-${i}`}
|
|
x={s.x + s.w / 2}
|
|
y={s.y + s.h / 2 + 6}
|
|
fill="#9ca3af"
|
|
textAnchor="middle"
|
|
fontSize="14"
|
|
fontFamily="Inter, sans-serif"
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 0.9 }}
|
|
transition={{ delay: 0.1 * i, duration: 0.6 }}
|
|
>
|
|
{s.label}
|
|
</motion.text>
|
|
))}
|
|
|
|
{/* CONSISTENT ORCHESTRATION LINES */}
|
|
{arrows.map((d, i) => (
|
|
<motion.path
|
|
key={`arrow-${i}`}
|
|
d={d}
|
|
stroke="#3a3a3a"
|
|
strokeWidth={4}
|
|
strokeLinecap="round"
|
|
fill="none"
|
|
initial={{ pathLength: 0, opacity: 0 }}
|
|
animate={{ pathLength: 1, opacity: 0.8 }}
|
|
transition={{ delay: 0.15 * i, duration: 0.8, ease: [0.22, 1, 0.36, 1] }}
|
|
/>
|
|
))}
|
|
|
|
{/* CYAN ACCENT OVERLAY ON LINES (predictable updates) */}
|
|
{arrows.map((d, i) => (
|
|
<motion.path
|
|
key={`arrow-accent-${i}`}
|
|
d={d}
|
|
stroke={accent}
|
|
strokeWidth={2}
|
|
strokeLinecap="round"
|
|
strokeDasharray="10"
|
|
fill="none"
|
|
initial={{ pathLength: 0, opacity: 0 }}
|
|
animate={{ pathLength: 1, opacity: 1 }}
|
|
transition={{
|
|
delay: 0.25 * i,
|
|
duration: 0.8,
|
|
ease: [0.22, 1, 0.36, 1]
|
|
}}
|
|
/>
|
|
))}
|
|
|
|
{/* MOVING PACKET SHOWING DETERMINISTIC FLOW */}
|
|
{!prefers && (
|
|
<motion.circle
|
|
r={6}
|
|
fill={accent}
|
|
filter="url(#orch-glow)"
|
|
style={{
|
|
offsetPath: `path('${packetPath}')`,
|
|
}}
|
|
initial={{ offsetDistance: "0%", opacity: 0 }}
|
|
animate={{
|
|
offsetDistance: ["0%", "100%"],
|
|
opacity: [0.2, 1, 0.2],
|
|
}}
|
|
transition={{
|
|
duration: 2.3,
|
|
repeat: Infinity,
|
|
repeatType: "loop",
|
|
ease: "linear",
|
|
}}
|
|
/>
|
|
)}
|
|
|
|
{/* FINAL CONFIRMATION PULSE AT DEPLOY STAGE */}
|
|
{!prefers && (
|
|
<motion.circle
|
|
cx={stages[2].x + stages[2].w / 2}
|
|
cy={stages[2].y + stages[2].h / 2}
|
|
r={24}
|
|
fill={accent}
|
|
opacity={0.1}
|
|
initial={{ scale: 0.9, opacity: 0 }}
|
|
animate={{ scale: [1, 1.15, 1], opacity: [0.05, 0.3, 0.05] }}
|
|
transition={{
|
|
duration: 1.8,
|
|
repeat: Infinity,
|
|
repeatType: "mirror",
|
|
ease: [0.22, 1, 0.36, 1],
|
|
}}
|
|
filter="url(#orch-glow)"
|
|
/>
|
|
)}
|
|
</svg>
|
|
</div>
|
|
);
|
|
}
|