diff --git a/src/pages/cloud/CloudArchitecture.tsx b/src/pages/cloud/CloudArchitecture.tsx index 5aa0c57..7d4b1fc 100644 --- a/src/pages/cloud/CloudArchitecture.tsx +++ b/src/pages/cloud/CloudArchitecture.tsx @@ -1,65 +1,90 @@ +'use client'; + import { Container } from '@/components/Container' import { Eyebrow, H3, P } from '@/components/Texts' import { Button } from '@/components/Button' +import { MeshNetworkIcon } from './animations/MeshNetworkIcon' +import { SovereignComputer } from './animations/SovereignComputer' +import { DeterministicOrchestration } from './animations/DeterministicOrchestration' const architecture = [ { title: 'Mesh Networking Layer', description: 'Every node receives a cryptographic network identity and secure routing path.', + icon: , // ✅ stored as const JSX }, { title: 'Sovereign Compute Layer', description: 'Workloads run on hardware you authorize, no shared control, no exposed surfaces.', + icon: , }, { title: 'Deterministic Orchestration', description: 'K3s clusters deploy predictably, verifiably, and remain drift-free.', + icon: , }, ] export function CloudArchitecture() { return ( -
- -
- ARCHITECTURE -

- How Mycelium Cloud Works -

-

- Mycelium Cloud runs Kubernetes on a global encrypted mesh, with - identity, routing, and state verified at the protocol level. -

-
+
-
- {architecture.map((layer) => ( -
-

- {layer.title} -

-

- {layer.description} -

-
- ))} -
+ {/* ✅ Top horizontal spacer like HomeHosting */} +
+
-
- - -
- + {/* ✅ Boxed container with matching spacing */} +
+ +
+ ARCHITECTURE + +

+ How Mycelium Cloud Works +

+ +

+ Mycelium Cloud runs Kubernetes on a global encrypted mesh, with + identity, routing, and state verified at the protocol level. +

+
+ + {/* ✅ Card layout spacing & grid match HomeHosting */} +
    + {architecture.map((layer) => ( +
  • + {layer.icon} {/* ✅ this now works */} +

    {layer.title}

    +

    {layer.description}

    +
  • + ))} +
+ + {/* ✅ Matching button spacing and layout */} +
+ + +
+
+
+ + {/* ✅ bottom border + bottom spacer to match */} +
+
) } diff --git a/src/pages/cloud/animations/DeterministicOrchestration.tsx b/src/pages/cloud/animations/DeterministicOrchestration.tsx new file mode 100644 index 0000000..5e182e4 --- /dev/null +++ b/src/pages/cloud/animations/DeterministicOrchestration.tsx @@ -0,0 +1,103 @@ +"use client"; + +import { motion, useReducedMotion } from "framer-motion"; +import clsx from "clsx"; + +export function DeterministicOrchestration({ className }: { className?: string }) { + const prefersReducedMotion = useReducedMotion(); + + // Hex coordinates (simple honeycomb layout) + const hexes = [ + { x: 60, y: 25 }, + { x: 100, y: 25 }, + { x: 140, y: 25 }, + + { x: 40, y: 65 }, + { x: 80, y: 65 }, + { x: 120, y: 65 }, + { x: 160, y: 65 }, + + { x: 60, y: 105 }, + { x: 100, y: 105 }, + { x: 140, y: 105 }, + ]; + + // simple hex path generator + const hexPath = (cx: number, cy: number, r = 14) => { + const p = (a: number) => ({ + x: cx + r * Math.cos((Math.PI / 180) * a), + y: cy + r * Math.sin((Math.PI / 180) * a), + }); + const pts = [30, 90, 150, 210, 270, 330].map((a) => p(a)); + return `M ${pts[0].x} ${pts[0].y} L ${pts[1].x} ${pts[1].y} L ${pts[2].x} ${pts[2].y} + L ${pts[3].x} ${pts[3].y} L ${pts[4].x} ${pts[4].y} L ${pts[5].x} ${pts[5].y} Z`; + }; + + return ( + + ); +} diff --git a/src/pages/cloud/animations/MeshNetworkIcon.tsx b/src/pages/cloud/animations/MeshNetworkIcon.tsx new file mode 100644 index 0000000..2d3b67b --- /dev/null +++ b/src/pages/cloud/animations/MeshNetworkIcon.tsx @@ -0,0 +1,112 @@ +"use client"; + +import { motion, useReducedMotion } from "framer-motion"; +import clsx from "clsx"; + +export function MeshNetworkIcon({ className }: { className?: string }) { + const prefersReducedMotion = useReducedMotion(); + + const nodes = [ + { x: 50, y: 25 }, + { x: 120, y: 25 }, + { x: 150, y: 65 }, + { x: 120, y: 100 }, + { x: 60, y: 100 }, + { x: 30, y: 65 }, + { x: 90, y: 55 }, // center-ish node + ]; + + // Lines between nodes (pairs of indices) + const links: [number, number][] = [ + [0, 6], [6, 1], + [1, 2], [2, 3], + [3, 6], [6, 4], + [4, 5], [5, 0], + ]; + + return ( + + ); +} diff --git a/src/pages/cloud/animations/SovereignComputer.tsx b/src/pages/cloud/animations/SovereignComputer.tsx new file mode 100644 index 0000000..d2fde08 --- /dev/null +++ b/src/pages/cloud/animations/SovereignComputer.tsx @@ -0,0 +1,113 @@ +"use client"; + +import { motion, useReducedMotion } from "framer-motion"; +import clsx from "clsx"; + +export function SovereignComputer({ className }: { className?: string }) { + const prefersReducedMotion = useReducedMotion(); + + return ( + + ); +}