chore: archive unused images and add storage feature components

- Moved 35 legacy image assets to archive directory for cleanup
- Created StorageCoreValue component showcasing Digital Me blueprint with logo grid
- Added Encrypted animation component visualizing secure storage with data movement
This commit is contained in:
2025-11-07 20:53:56 +01:00
parent 9bccc89309
commit 0b6bcfedd0
34 changed files with 254 additions and 0 deletions

View File

Before

Width:  |  Height:  |  Size: 497 KiB

After

Width:  |  Height:  |  Size: 497 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

View File

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 MiB

After

Width:  |  Height:  |  Size: 1.9 MiB

View File

Before

Width:  |  Height:  |  Size: 431 KiB

After

Width:  |  Height:  |  Size: 431 KiB

View File

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 114 KiB

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

Before

Width:  |  Height:  |  Size: 878 KiB

After

Width:  |  Height:  |  Size: 878 KiB

View File

Before

Width:  |  Height:  |  Size: 223 KiB

After

Width:  |  Height:  |  Size: 223 KiB

View File

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 65 KiB

View File

Before

Width:  |  Height:  |  Size: 111 KiB

After

Width:  |  Height:  |  Size: 111 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

Before

Width:  |  Height:  |  Size: 938 KiB

After

Width:  |  Height:  |  Size: 938 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 MiB

After

Width:  |  Height:  |  Size: 2.0 MiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 316 KiB

After

Width:  |  Height:  |  Size: 316 KiB

View File

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 116 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 327 KiB

After

Width:  |  Height:  |  Size: 327 KiB

View File

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 140 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -0,0 +1,61 @@
"use client";
import { Container } from "@/components/Container";
import { H3, P, Eyebrow } from "@/components/Texts";
export function StorageCoreValue() {
const logos = [
{ src: '/images/logo/cryptpad.png', href: 'https://cryptpad.fr' },
{ src: '/images/logo/gitea.png', href: 'https://about.gitea.com' },
{ src: '/images/logo/lifekit.png', href: '#' }, // No link available
{ src: '/images/logo/matrix.png', href: 'https://matrix.org' },
{ src: '/images/logo/nextcloud.png', href: 'https://nextcloud.com' },
{ src: '/images/logo/stalwart.png', href: 'https://stalw.art' },
];
return (
<section className="w-full max-w-8xl mx-auto bg-transparent">
{/* ✅ Boxed container */}
<div className="max-w-7xl bg-white mx-auto py-12 border border-t-0 border-b-0 border-gray-100">
<Container>
<div className="mx-auto max-w-4xl sm:text-center">
<Eyebrow className="text-cyan-500">Featured Blueprint</Eyebrow>
<H3 className="text-3xl lg:text-4xl font-medium tracking-tight text-gray-900 mt-2">
Your Personal Sovereign Cloud Workspace
</H3>
<P className="mt-6 text-lg text-gray-600">
Digital Me is an example environment built to demonstrate whats possible on top of the Mycelium Stack a full personal cloud you can deploy, customize, or extend. Your files, communication, apps, and optional AI agent, all running privately on infrastructure you choose.
</P>
</div>
{/* ✅ 3x2 logo grid */}
<div className="mt-12 grid grid-cols-3 gap-x-8 gap-y-12">
{logos.map((logo, i) => (
<div key={i} className="flex justify-center">
<a
href={logo.href}
target="_blank"
rel="noopener noreferrer"
className="transition-transform duration-300 hover:scale-105"
>
<img
src={logo.src}
alt={`Logo ${i + 1}`}
className="max-h-12 w-auto object-contain"
/>
</a>
</div>
))}
</div>
</Container>
</div>
{/* ✅ Bottom line + bottom spacer */}
<div className="w-full border-b border-gray-100" />
<div className="max-w-7xl mx-auto py-6 border border-t-0 border-b-0 border-gray-100 bg-transparent" />
</section>
);
}

View File

@@ -0,0 +1,193 @@
"use client";
import { motion, useReducedMotion } from "framer-motion";
import clsx from "clsx";
type Props = {
className?: string;
accent?: string;
gridStroke?: string;
stroke?: string;
};
const W = 760;
const H = 420;
export default function Encrypted({
className,
accent = "#00b8db",
gridStroke = "#e5e7eb",
stroke = "#111111",
}: Props) {
const prefers = useReducedMotion();
// positions of storage vaults (cylindrical stack illusion)
const vaults = [
{ x: 200, y: 220 },
{ x: 380, y: 180 },
{ x: 560, y: 220 },
];
// path representing encrypted data moving across storage nodes
const dataPath = `M ${vaults[0].x + 60} ${vaults[0].y}
C 280 160, 480 160, ${vaults[2].x} ${vaults[2].y}`;
return (
<div
className={clsx("relative overflow-hidden", className)}
aria-hidden="true"
role="img"
aria-label="Mycelium Storage: encrypted and verifiable at rest and in motion"
style={{ background: "transparent" }}
>
<svg viewBox={`0 0 ${W} ${H}`} className="w-full h-full">
{/* === Background Grid (light mode) === */}
<defs>
<pattern id="grid-light" width="28" height="28" patternUnits="userSpaceOnUse">
<path d="M 28 0 L 0 0 0 28" fill="none" stroke={gridStroke} strokeWidth="1" opacity="0.6" />
</pattern>
<filter id="cyan-glow">
<feGaussianBlur stdDeviation="3" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<rect width={W} height={H} fill="url(#grid-light)" />
{/* === Storage Vaults (cylinders) === */}
{vaults.map((v, i) => (
<g key={i} transform={`translate(${v.x}, ${v.y})`}>
{/* Top ellipse */}
<ellipse cx="0" cy="-30" rx="50" ry="14" fill="none" stroke={stroke} strokeWidth="2" />
{/* Body */}
<rect
x="-50"
y="-30"
width="100"
height="60"
rx="12"
fill="none"
stroke={stroke}
strokeWidth="2"
/>
{/* Bottom ellipse (front face) */}
<ellipse cx="0" cy="30" rx="50" ry="14" fill="none" stroke={stroke} strokeWidth="2" />
{/* subtle cyan glow ring to mark encryption */}
<motion.ellipse
cx="0"
cy="0"
rx="55"
ry="18"
fill="none"
stroke={accent}
strokeWidth="2"
initial={{ opacity: 0 }}
animate={{ opacity: [0.15, 0.4, 0.15] }}
transition={{
delay: i * 0.3,
duration: 2.2,
repeat: Infinity,
ease: [0.22, 1, 0.36, 1],
}}
/>
</g>
))}
{/* === Encrypted data movement path === */}
<motion.path
d={dataPath}
fill="none"
stroke={stroke}
strokeWidth={2}
strokeLinecap="round"
strokeDasharray="6"
opacity="0.5"
initial={{ pathLength: 0 }}
animate={{ pathLength: 1 }}
transition={{ duration: 1.2, ease: [0.22, 1, 0.36, 1] }}
/>
{/* === Encrypted packets traveling === */}
{!prefers && (
<motion.circle
r={6}
fill={accent}
style={{ offsetPath: `path('${dataPath}')` }}
initial={{ offsetDistance: "0%", opacity: 0 }}
animate={{
offsetDistance: ["0%", "100%"],
opacity: [0.3, 1, 0.3],
}}
transition={{
duration: 2.8,
repeat: Infinity,
repeatType: "loop",
ease: "linear",
}}
filter="url(#cyan-glow)"
/>
)}
{/* === Verification shield (top-right) === */}
<motion.path
d={`M 620 120
L 645 135
L 640 165
L 620 175
L 600 165
L 595 135
Z`}
fill="none"
stroke={accent}
strokeWidth={2.5}
strokeLinecap="round"
strokeLinejoin="round"
initial={{ pathLength: 0, opacity: 0 }}
animate={{ pathLength: 1, opacity: 1 }}
transition={{ duration: 1, delay: 0.6, ease: [0.22, 1, 0.36, 1] }}
filter="url(#cyan-glow)"
/>
{/* === Verification checkmark === */}
<motion.path
d="M 606 150 L 617 162 L 635 140"
fill="none"
stroke={accent}
strokeWidth={3}
strokeLinecap="round"
strokeLinejoin="round"
initial={{ pathLength: 0 }}
animate={{ pathLength: 1 }}
transition={{ duration: 0.8, delay: 1.2 }}
filter="url(#cyan-glow)"
/>
{/* === Cyan verification pulse === */}
{!prefers && (
<motion.circle
cx="620"
cy="150"
r="24"
stroke={accent}
strokeWidth="2"
fill="none"
initial={{ scale: 1, opacity: 0 }}
animate={{
scale: [1, 1.25, 1.4],
opacity: [0.25, 0.6, 0],
}}
transition={{
duration: 1.8,
repeat: Infinity,
ease: [0.22, 1, 0.36, 1],
}}
/>
)}
</svg>
</div>
);
}