refactor: rename and update pod animations with improved visuals and consistency

- Renamed NoCentral to DataControl with enhanced data ownership visualization
- Renamed NoExtraction to Connectivity with full mesh P2P topology
- Renamed NoSinglePoint to Security with improved styling
- Renamed NoControl to Resilience with consistent styling
- Added lg:-mt-12 margin to Security and Resilience animations for alignment
- Updated DataControl to show explicit permission gates and bi-directional replication
This commit is contained in:
2025-11-17 15:12:55 +01:00
parent 97da7ba907
commit 1a34508699
9 changed files with 909 additions and 893 deletions

View File

@@ -0,0 +1,176 @@
"use client";
import { motion, useReducedMotion } from "framer-motion";
import clsx from "clsx";
type Props = {
className?: string;
accent?: string;
bg?: string;
gridStroke?: string;
};
const W = 720; // 4:3 width
const H = 540; // 4:3 height
export default function Connectivity({
className,
accent = "#00b8db",
bg = "#0b0b0b",
gridStroke = "#2b2a2a",
}: Props) {
const prefers = useReducedMotion();
// Hex-like P2P topology — all peers connect *directly*
const pods = [
{ x: 250, y: 160 },
{ x: 470, y: 160 },
{ x: 580, y: 290 },
{ x: 470, y: 420 },
{ x: 250, y: 420 },
{ x: 140, y: 290 },
];
// Every pod connects to every other pod = full direct mesh
const links: [number, number][] = [];
for (let i = 0; i < pods.length; i++) {
for (let j = i + 1; j < pods.length; j++) links.push([i, j]);
}
const line = (i: number, j: number) => {
const a = pods[i], b = pods[j];
return `M ${a.x} ${a.y} L ${b.x} ${b.y}`;
};
return (
<div className={clsx("relative overflow-hidden", className)}>
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full" style={{ background: bg }}>
{/* ========= GRID + FILTERS ========= */}
<defs>
<pattern id="conn-grid" 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="conn-glow">
<feGaussianBlur stdDeviation="3" result="b" />
<feMerge>
<feMergeNode in="b" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
{/* Cyan soft gradient for pods */}
<radialGradient id="conn-pod" cx="50%" cy="50%" r="60%">
<stop offset="0%" stopColor={accent} stopOpacity="0.9" />
<stop offset="100%" stopColor={accent} stopOpacity="0.06" />
</radialGradient>
</defs>
<rect width={W} height={H} fill="url(#conn-grid)" />
{/* ========= BASE CONNECTION LINES (Full Mesh) ========= */}
{links.map(([i, j], idx) => (
<motion.path
key={`base-${idx}`}
d={line(i, j)}
stroke="#1f1f1f"
strokeWidth={3}
strokeLinecap="round"
fill="none"
initial={{ pathLength: 0, opacity: 0.2 }}
animate={{ pathLength: 1, opacity: 0.5 }}
transition={{ duration: 0.6, delay: idx * 0.03 }}
/>
))}
{/* ========= ACCENT DASH (Active P2P links) ========= */}
{links.map(([i, j], idx) => (
<motion.path
key={`dash-${idx}`}
d={line(i, j)}
stroke={accent}
strokeWidth={2}
fill="none"
strokeDasharray="12 10"
initial={{ pathLength: 0, opacity: 0.9 }}
animate={{ pathLength: 1, opacity: [0.9, 0.6, 0.9] }}
transition={{
duration: 1,
delay: idx * 0.04,
repeat: Infinity,
repeatType: "reverse",
}}
filter="url(#conn-glow)"
/>
))}
{/* ========= MOVING SIGNALS (Direct P2P) ========= */}
{!prefers &&
links.map(([i, j], idx) => (
<motion.circle
key={`pulse-${idx}`}
r={5}
fill={accent}
style={{ offsetPath: `path('${line(i, j)}')` }}
initial={{ offsetDistance: "0%", opacity: 0 }}
animate={{
offsetDistance: ["0%", "100%"],
opacity: [0.2, 1, 0.2],
}}
transition={{
duration: 2.3,
delay: idx * 0.2,
repeat: Infinity,
ease: "linear",
}}
filter="url(#conn-glow)"
/>
))}
{/* ========= CLOUD PODS ========= */}
{pods.map((p, i) => (
<g key={`pod-${i}`}>
{/* Outer soft cyan aura */}
{!prefers && (
<motion.ellipse
cx={p.x}
cy={p.y}
rx={42}
ry={28}
fill="none"
stroke={accent}
strokeWidth={2}
opacity={0.15}
animate={{ scale: [1, 1.1, 1] , opacity: [0.1, 0.25, 0.1] }}
transition={{ duration: 2.3, delay: i * 0.15, repeat: Infinity }}
filter="url(#conn-glow)"
/>
)}
{/* Pod body */}
<ellipse
cx={p.x}
cy={p.y}
rx={36}
ry={24}
fill="url(#conn-pod)"
stroke="#1f1f1f"
strokeWidth={2}
filter="url(#conn-glow)"
/>
{/* Inner dark core */}
<ellipse cx={p.x} cy={p.y} rx={18} ry={12} fill="#0f0f0f" stroke="#292929" strokeWidth={1.5} />
</g>
))}
</svg>
</div>
);
}