Files
www_projectmycelium_com/src/pages/home/HomeBenefits.tsx
sasha-astiadi 363b822d8b feat: refine benefits section messaging and ordering
- Reordered features to lead with "Unbreakable by Design" for stronger impact
- Simplified benefit descriptions for clarity and conciseness
- Updated section heading from "Why It Changes Everything" to "Why It Matters"
2025-11-04 13:35:22 +01:00

310 lines
12 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import createGlobe from "cobe";
import { useEffect, useRef } from "react";
import { motion } from "motion/react";
import { IconBrandYoutubeFilled } from "@tabler/icons-react";
import { H2, P, CP, Eyebrow } from '@/components/Texts'
export function HomeBenefits() {
const features = [
{
title: "Unbreakable by Design",
description:
"No central cloud to censor or fail. The network heals itself.",
image: "/images/benefits/energy.webp",
},
{
title: "Sovereign by Default",
description:
"Identity, compute, and data belong to you cryptographically.",
image: "/images/benefits/sovereign.webp",
},
{
title: "Hackable & Open",
description:
"Learn, build, and experiment without permission.",
image: "/images/benefits/autonomous.webp",
},
{
title: "Cost & Energy Efficient",
description:
"Distributed hardware eliminates hyperscale overhead.",
image: "/images/benefits/cost.webp",
},
];
return (
<div className="relative z-20 py-10 lg:py-24 max-w-7xl mx-auto">
<div className="px-12">
<Eyebrow className="text-center text-cyan-500">
Benefits
</Eyebrow>
<H2 className="text-3xl lg:text-5xl lg:leading-tight max-w-5xl mx-auto text-center tracking-tight font-medium text-black dark:text-white">
Why It Matters
</H2>
<P className=" max-w-3xl my-4 mx-auto text-center text-gray-600">
Project Mycelium is a new foundation for digital independence. A self-governing, AI-powered infrastructure that gives you control, efficiency, and trust without compromise.
</P>
</div>
<div className="mt-10 grid grid-cols-1 gap-4 sm:mt-16 lg:grid-cols-7 lg:grid-rows-2 lg:px-12 px-6">
<div className="flex p-px lg:col-span-4">
<div className="w-full overflow-hidden rounded-lg bg-white/40 dark:bg-black/40 shadow-sm border border-transparent transition-all duration-300 hover:scale-105 hover:shadow-lg hover:shadow-cyan-500/50 hover:border-cyan-500 max-lg:rounded-t-4xl lg:rounded-tl-4xl">
<div className="flex items-center">
<div className="w-1/3 p-2">
<img
alt={features[0].title}
src={features[0].image}
className="w-40 h-40 object-contain"
/>
</div>
<div className="w-2/3 p-2 pr-12">
<h3 className="text-lg font-semibold text-black dark:text-white">{features[0].title}</h3>
<CP className="mt-2 text-gray-600 dark:text-gray-300">
{features[0].description}
</CP>
</div>
</div>
</div>
</div>
<div className="flex p-px lg:col-span-3">
<div className="w-full overflow-hidden rounded-lg bg-white/40 dark:bg-black/40 shadow-sm border border-transparent transition-all duration-300 hover:scale-105 hover:shadow-lg hover:shadow-cyan-500/50 hover:border-cyan-500 lg:rounded-tr-4xl">
<div className="flex items-center">
<div className="w-1/3 p-4">
<img
alt={features[1].title}
src={features[1].image}
className="w-40 h-40 object-contain"
/>
</div>
<div className="w-2/3 p-4">
<h3 className="text-lg font-semibold text-black dark:text-white">{features[1].title}</h3>
<CP className="mt-2 text-gray-600 dark:text-gray-300">
{features[1].description}
</CP>
</div>
</div>
</div>
</div>
<div className="flex p-px lg:col-span-3">
<div className="w-full overflow-hidden rounded-lg bg-white/40 dark:bg-black/40 shadow-sm border border-transparent transition-all duration-300 hover:scale-105 hover:shadow-lg hover:shadow-cyan-500/50 hover:border-cyan-500 lg:rounded-bl-4xl">
<div className="flex items-center">
<div className="w-1/3 p-4">
<img
alt={features[2].title}
src={features[2].image}
className="w-40 h-40 object-contain"
/>
</div>
<div className="w-2/3 p-4">
<h3 className="text-lg font-semibold text-black dark:text-white">{features[2].title}</h3>
<CP className="mt-2 text-gray-600 dark:text-gray-300">
{features[2].description}
</CP>
</div>
</div>
</div>
</div>
<div className="flex p-px lg:col-span-4">
<div className="w-full overflow-hidden rounded-lg bg-white/40 dark:bg-black/40 shadow-sm border border-transparent transition-all duration-300 hover:scale-105 hover:shadow-lg hover:shadow-cyan-500/50 hover:border-cyan-500 max-lg:rounded-b-4xl lg:rounded-br-4xl">
<div className="flex items-center">
<div className="w-1/3 p-2">
<img
alt={features[3].title}
src={features[3].image}
className="w-40 h-40 object-contain"
/>
</div>
<div className="w-2/3 p-2 pr-12">
<h3 className="text-lg font-semibold text-black dark:text-white">{features[3].title}</h3>
<CP className="mt-2 text-gray-600 dark:text-gray-300">
{features[3].description}
</CP>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
export const SkeletonOne = () => {
return (
<div className="relative flex py-8 px-2 gap-10 h-full">
<div className="w-full p-5 mx-auto bg-white dark:bg-neutral-900 shadow-2xl group h-full">
<div className="flex flex-1 w-full h-full flex-col space-y-2 ">
{/* TODO */}
<img
src="/linear.webp"
alt="header"
width={800}
height={800}
className="h-full w-full aspect-square object-cover object-left-top rounded-sm"
/>
</div>
</div>
<div className="absolute bottom-0 z-40 inset-x-0 h-60 bg-gradient-to-t from-white dark:from-black via-white dark:via-black to-transparent w-full pointer-events-none" />
<div className="absolute top-0 z-40 inset-x-0 h-60 bg-gradient-to-b from-white dark:from-black via-transparent to-transparent w-full pointer-events-none" />
</div>
);
};
export const SkeletonThree = () => {
return (
<a
href="https://www.youtube.com/watch?v=RPa3_AD1_Vs"
target="__blank"
className="relative flex gap-10 h-full group/image"
>
<div className="w-full mx-auto bg-transparent dark:bg-transparent group h-full">
<div className="flex flex-1 w-full h-full flex-col space-y-2 relative">
{/* TODO */}
<IconBrandYoutubeFilled className="h-20 w-20 absolute z-10 inset-0 text-red-500 m-auto " />
<img
src="https://assets.aceternity.com/fireship.jpg"
alt="header"
width={800}
height={800}
className="h-full w-full aspect-square object-cover object-center rounded-sm blur-none group-hover/image:blur-md transition-all duration-200"
/>
</div>
</div>
</a>
);
};
export const SkeletonTwo = () => {
const images = [
"https://images.unsplash.com/photo-1517322048670-4fba75cbbb62?q=80&w=3000&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1573790387438-4da905039392?q=80&w=3425&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1555400038-63f5ba517a47?q=80&w=3540&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1554931670-4ebfabf6e7a9?q=80&w=3387&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"https://images.unsplash.com/photo-1546484475-7f7bd55792da?q=80&w=2581&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
];
const imageVariants = {
whileHover: {
scale: 1.1,
rotate: 0,
zIndex: 100,
},
whileTap: {
scale: 1.1,
rotate: 0,
zIndex: 100,
},
};
return (
<div className="relative flex flex-col items-start p-8 gap-10 h-full overflow-hidden">
{/* TODO */}
<div className="flex flex-row -ml-20">
{images.map((image, idx) => (
<motion.div
variants={imageVariants}
key={"images-first" + idx}
style={{
rotate: Math.random() * 20 - 10,
}}
whileHover="whileHover"
whileTap="whileTap"
className="rounded-xl -mr-4 mt-4 p-1 bg-white dark:bg-neutral-800 dark:border-neutral-700 border border-neutral-100 shrink-0 overflow-hidden"
>
<img
src={image}
alt="bali images"
width="500"
height="500"
className="rounded-lg h-20 w-20 md:h-40 md:w-40 object-cover shrink-0"
/>
</motion.div>
))}
</div>
<div className="flex flex-row">
{images.map((image, idx) => (
<motion.div
key={"images-second" + idx}
style={{
rotate: Math.random() * 20 - 10,
}}
variants={imageVariants}
whileHover="whileHover"
whileTap="whileTap"
className="rounded-xl -mr-4 mt-4 p-1 bg-white dark:bg-neutral-800 dark:border-neutral-700 border border-neutral-100 shrink-0 overflow-hidden"
>
<img
src={image}
alt="bali images"
width="500"
height="500"
className="rounded-lg h-20 w-20 md:h-40 md:w-40 object-cover shrink-0"
/>
</motion.div>
))}
</div>
<div className="absolute left-0 z-[100] inset-y-0 w-20 bg-gradient-to-r from-white dark:from-black to-transparent h-full pointer-events-none" />
<div className="absolute right-0 z-[100] inset-y-0 w-20 bg-gradient-to-l from-white dark:from-black to-transparent h-full pointer-events-none" />
</div>
);
};
export const SkeletonFour = () => {
return (
<div className="h-60 md:h-60 flex flex-col items-center relative bg-transparent dark:bg-transparent mt-10">
<Globe className="absolute -right-10 md:-right-10 -bottom-80 md:-bottom-72" />
</div>
);
};
export const Globe = ({ className }: { className?: string }) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
let phi = 0;
if (!canvasRef.current) return;
const globe = createGlobe(canvasRef.current, {
devicePixelRatio: 2,
width: 600 * 2,
height: 600 * 2,
phi: 0,
theta: 0,
dark: 1,
diffuse: 1.2,
mapSamples: 16000,
mapBrightness: 6,
baseColor: [0.3, 0.3, 0.3],
markerColor: [0.1, 0.8, 1],
glowColor: [1, 1, 1],
markers: [
// longitude latitude
{ location: [37.7595, -122.4367], size: 0.03 },
{ location: [40.7128, -74.006], size: 0.1 },
],
onRender: (state) => {
// Called on every animation frame.
// `state` will be an empty object, return updated params.
state.phi = phi;
phi += 0.01;
},
});
return () => {
globe.destroy();
};
}, []);
return (
<canvas
ref={canvasRef}
style={{ width: 600, height: 600, maxWidth: "100%", aspectRatio: 1 }}
className={className}
/>
);
};