improvement

This commit is contained in:
Emre
2025-10-10 22:19:36 +03:00
parent bfd28b7fff
commit c2bce4902a
23 changed files with 488 additions and 196 deletions

10
package-lock.json generated
View File

@@ -9,6 +9,7 @@
"version": "0.0.0",
"dependencies": {
"framer-motion": "^12.23.23",
"lucide-react": "^0.545.0",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-router-dom": "^7.9.4"
@@ -3111,6 +3112,15 @@
"yallist": "^3.0.2"
}
},
"node_modules/lucide-react": {
"version": "0.545.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.545.0.tgz",
"integrity": "sha512-7r1/yUuflQDSt4f1bpn5ZAocyIxcTyVyBBChSVtBKn5M+392cPmI5YJMWOJKk/HUWGm5wg83chlAZtCcGbEZtw==",
"license": "ISC",
"peerDependencies": {
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",

View File

@@ -11,6 +11,7 @@
},
"dependencies": {
"framer-motion": "^12.23.23",
"lucide-react": "^0.545.0",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-router-dom": "^7.9.4"

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 KiB

View File

@@ -1,3 +1,3 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-white" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" width="24" height="24" >
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 2.25A.75.75 0 0 1 9 3v.75h2.25V3a.75.75 0 0 1 1.5 0v.75H15V3a.75.75 0 0 1 1.5 0v.75h.75a3 3 0 0 1 3 3v.75H21A.75.75 0 0 1 21 9h-.75v2.25H21a.75.75 0 0 1 0 1.5h-.75V15H21a.75.75 0 0 1 0 1.5h-.75v.75a3 3 0 0 1-3 3h-.75V21a.75.75 0 0 1-1.5 0v-.75h-2.25V21a.75.75 0 0 1-1.5 0v-.75H9V21a.75.75 0 0 1-1.5 0v-.75h-.75a3 3 0 0 1-3-3v-.75H3A.75.75 0 0 1 3 15h.75v-2.25H3a.75.75 0 0 1 0-1.5h.75V9H3a.75.75 0 0 1 0-1.5h.75v-.75a3 3 0 0 1 3-3h.75V3a.75.75 0 0 1 .75-.75ZM6 6.75A.75.75 0 0 1 6.75 6h10.5a.75.75 0 0 1 .75.75v10.5a.75.75 0 0 1-.75.75H6.75a.75.75 0 0 1-.75-.75V6.75Z" stroke="#FFFFFF" fill="none" stroke-width="1.5px"></path>
</svg>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-brand-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" width="24" height="24">
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 2.25A.75.75 0 0 1 9 3v.75h2.25V3a.75.75 0 0 1 1.5 0v.75H15V3a.75.75 0 0 1 1.5 0v.75h.75a3 3 0 0 1 3 3v.75H21A.75.75 0 0 1 21 9h-.75v2.25H21a.75.75 0 0 1 0 1.5h-.75V15H21a.75.75 0 0 1 0 1.5h-.75v.75a3 3 0 0 1-3 3h-.75V21a.75.75 0 0 1-1.5 0v-.75h-2.25V21a.75.75 0 0 1-1.5 0v-.75H9V21a.75.75 0 0 1-1.5 0v-.75h-.75a3 3 0 0 1-3-3v-.75H3A.75.75 0 0 1 3 15h.75v-2.25H3a.75.75 0 0 1 0-1.5h.75V9H3a.75.75 0 0 1 0-1.5h.75v-.75a3 3 0 0 1 3-3h.75V3a.75.75 0 0 1 .75-.75ZM6 6.75A.75.75 0 0 1 6.75 6h10.5a.75.75 0 0 1 .75.75v10.5a.75.75 0 0 1-.75.75H6.75a.75.75 0 0 1-.75-.75V6.75Z" stroke="#4350d7" fill="none" stroke-width="1.5px"></path>
</svg>

Before

Width:  |  Height:  |  Size: 957 B

After

Width:  |  Height:  |  Size: 928 B

View File

@@ -1,3 +1,3 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-white" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" width="24" height="24" >
<path stroke-linecap="round" stroke-linejoin="round" d="M11.622 1.602a.75.75 0 0 1 .756 0l2.25 1.313a.75.75 0 0 1-.756 1.295L12 3.118 10.128 4.21a.75.75 0 1 1-.756-1.295l2.25-1.313ZM5.898 5.81a.75.75 0 0 1-.27 1.025l-1.14.665 1.14.665a.75.75 0 1 1-.756 1.295L3.75 8.806v.944a.75.75 0 0 1-1.5 0V7.5a.75.75 0 0 1 .372-.648l2.25-1.312a.75.75 0 0 1 1.026.27Zm12.204 0a.75.75 0 0 1 1.026-.27l2.25 1.312a.75.75 0 0 1 .372.648v2.25a.75.75 0 0 1-1.5 0v-.944l-1.122.654a.75.75 0 1 1-.756-1.295l1.14-.665-1.14-.665a.75.75 0 0 1-.27-1.025Zm-9 5.25a.75.75 0 0 1 1.026-.27L12 11.882l1.872-1.092a.75.75 0 1 1 .756 1.295l-1.878 1.096V15a.75.75 0 0 1-1.5 0v-1.82l-1.878-1.095a.75.75 0 0 1-.27-1.025ZM3 13.5a.75.75 0 0 1 .75.75v1.82l1.878 1.095a.75.75 0 1 1-.756 1.295l-2.25-1.312a.75.75 0 0 1-.372-.648v-2.25A.75.75 0 0 1 3 13.5Zm18 0a.75.75 0 0 1 .75.75v2.25a.75.75 0 0 1-.372.648l-2.25 1.312a.75.75 0 1 1-.756-1.295l1.878-1.096V14.25a.75.75 0 0 1 .75-.75Zm-9 5.25a.75.75 0 0 1 .75.75v.944l1.122-.654a.75.75 0 1 1 .756 1.295l-2.25 1.313a.75.75 0 0 1-.756 0l-2.25-1.313a.75.75 0 1 1 .756-1.295l1.122.654V19.5a.75.75 0 0 1 .75-.75Z" stroke="#FFFFFF" fill="none" stroke-width="1.5px"></path>
</svg>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-brand-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" width="24" height="24">
<path stroke-linecap="round" stroke-linejoin="round" d="M11.622 1.602a.75.75 0 0 1 .756 0l2.25 1.313a.75.75 0 0 1-.756 1.295L12 3.118 10.128 4.21a.75.75 0 1 1-.756-1.295l2.25-1.313ZM5.898 5.81a.75.75 0 0 1-.27 1.025l-1.14.665 1.14.665a.75.75 0 1 1-.756 1.295L3.75 8.806v.944a.75.75 0 0 1-1.5 0V7.5a.75.75 0 0 1 .372-.648l2.25-1.312a.75.75 0 0 1 1.026.27Zm12.204 0a.75.75 0 0 1 1.026-.27l2.25 1.312a.75.75 0 0 1 .372.648v2.25a.75.75 0 0 1-1.5 0v-.944l-1.122.654a.75.75 0 1 1-.756-1.295l1.14-.665-1.14-.665a.75.75 0 0 1-.27-1.025Zm-9 5.25a.75.75 0 0 1 1.026-.27L12 11.882l1.872-1.092a.75.75 0 1 1 .756 1.295l-1.878 1.096V15a.75.75 0 0 1-1.5 0v-1.82l-1.878-1.095a.75.75 0 0 1-.27-1.025ZM3 13.5a.75.75 0 0 1 .75.75v1.82l1.878 1.095a.75.75 0 1 1-.756 1.295l-2.25-1.312a.75.75 0 0 1-.372-.648v-2.25A.75.75 0 0 1 3 13.5Zm18 0a.75.75 0 0 1 .75.75v2.25a.75.75 0 0 1-.372.648l-2.25 1.312a.75.75 0 1 1-.756-1.295l1.878-1.096V14.25a.75.75 0 0 1 .75-.75Zm-9 5.25a.75.75 0 0 1 .75.75v.944l1.122-.654a.75.75 0 1 1 .756 1.295l-2.25 1.313a.75.75 0 0 1-.756 0l-2.25-1.313a.75.75 0 1 1 .756-1.295l1.122.654V19.5a.75.75 0 0 1 .75-.75Z" stroke="#4350d7" fill="none" stroke-width="1.5px"></path>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,3 +1,3 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-white" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" width="24" height="24" >
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 3.75a6 6 0 0 0-5.98 6.496A5.25 5.25 0 0 0 6.75 20.25H18a4.5 4.5 0 0 0 2.206-8.423 3.75 3.75 0 0 0-4.133-4.303A6.001 6.001 0 0 0 10.5 3.75Zm2.03 5.47a.75.75 0 0 0-1.06 0l-3 3a.75.75 0 1 0 1.06 1.06l1.72-1.72v4.94a.75.75 0 0 0 1.5 0v-4.94l1.72 1.72a.75.75 0 1 0 1.06-1.06l-3-3Z" stroke="#FFFFFF" fill="none" stroke-width="1.5px"></path>
</svg>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-brand-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" width="24" height="24">
<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 3.75a6 6 0 0 0-5.98 6.496A5.25 5.25 0 0 0 6.75 20.25H18a4.5 4.5 0 0 0 2.206-8.423 3.75 3.75 0 0 0-4.133-4.303A6.001 6.001 0 0 0 10.5 3.75Zm2.03 5.47a.75.75 0 0 0-1.06 0l-3 3a.75.75 0 1 0 1.06 1.06l1.72-1.72v4.94a.75.75 0 0 0 1.5 0v-4.94l1.72 1.72a.75.75 0 1 0 1.06-1.06l-3-3Z" stroke="#4350d7" fill="none" stroke-width="1.5px"></path>
</svg>

Before

Width:  |  Height:  |  Size: 665 B

After

Width:  |  Height:  |  Size: 636 B

View File

@@ -1,3 +1,3 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-white" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" width="24" height="24" >
<path stroke-linecap="round" stroke-linejoin="round" d="M12 1.5a5.25 5.25 0 0 0-5.25 5.25v3a3 3 0 0 0-3 3v6.75a3 3 0 0 0 3 3h10.5a3 3 0 0 0 3-3v-6.75a3 3 0 0 0-3-3v-3c0-2.9-2.35-5.25-5.25-5.25Zm3.75 8.25v-3a3.75 3.75 0 1 0-7.5 0v3h7.5Z" stroke="#FFFFFF" fill="none" stroke-width="1.5px"></path>
</svg>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-brand-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" width="24" height="24">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 1.5a5.25 5.25 0 0 0-5.25 5.25v3a3 3 0 0 0-3 3v6.75a3 3 0 0 0 3 3h10.5a3 3 0 0 0 3-3v-6.75a3 3 0 0 0-3-3v-3c0-2.9-2.35-5.25-5.25-5.25Zm3.75 8.25v-3a3.75 3.75 0 1 0-7.5 0v3h7.5Z" stroke="#4350d7" fill="none" stroke-width="1.5px"></path>
</svg>

Before

Width:  |  Height:  |  Size: 563 B

After

Width:  |  Height:  |  Size: 534 B

View File

@@ -1,3 +1,3 @@
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-white" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" width="24" height="24" >
<path stroke-linecap="round" stroke-linejoin="round" d="M3 2.25a.75.75 0 0 1 .75.75v.54l1.838-.46a9.75 9.75 0 0 1 6.725.738l.108.054A8.25 8.25 0 0 0 18 4.524l3.11-.732a.75.75 0 0 1 .917.81 47.784 47.784 0 0 0 .005 10.337.75.75 0 0 1-.574.812l-3.114.733a9.75 9.75 0 0 1-6.594-.77l-.108-.054a8.25 8.25 0 0 0-5.69-.625l-2.202.55V21a.75.75 0 0 1-1.5 0V3A.75.75 0 0 1 3 2.25Z" stroke="#FFFFFF" fill="none" stroke-width="1.5px"></path>
</svg>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-brand-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" width="24" height="24">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 2.25a.75.75 0 0 1 .75.75v.54l1.838-.46a9.75 9.75 0 0 1 6.725.738l.108.054A8.25 8.25 0 0 0 18 4.524l3.11-.732a.75.75 0 0 1 .917.81 47.784 47.784 0 0 0 .005 10.337.75.75 0 0 1-.574.812l-3.114.733a9.75 9.75 0 0 1-6.594-.77l-.108-.054a8.25 8.25 0 0 0-5.69-.625l-2.202.55V21a.75.75 0 0 1-1.5 0V3A.75.75 0 0 1 3 2.25Z" stroke="#4350d7" fill="none" stroke-width="1.5px"></path>
</svg>

Before

Width:  |  Height:  |  Size: 698 B

After

Width:  |  Height:  |  Size: 669 B

View File

@@ -13,9 +13,10 @@ type FooterColumn = {
const footerColumns: FooterColumn[] = [
{
title: 'Affiliate Projects',
title: 'GeoMind',
links: [
{ label: 'Project Mycelium', href: 'https://project.mycelium.tf', target: '_blank' },
{ label: 'Technology', href: '/technology' },
{ label: 'Use Cases', href: '/usecases' },
],
},
{
@@ -25,13 +26,6 @@ const footerColumns: FooterColumn[] = [
{ label: 'Support', href: 'mailto:support@threefold.tech', target: '_blank' },
],
},
{
title: 'GeoMind',
links: [
{ label: 'Technology', href: '/technology' },
{ label: 'Use Cases', href: '/usecases' },
],
},
];
export const Footer = () => {
@@ -59,7 +53,7 @@ export const Footer = () => {
</p>
</div>
</div>
<div className="grid flex-1 grid-cols-1 gap-8 text-sm sm:grid-cols-2 lg:grid-cols-3">
<div className="grid flex-1 grid-cols-1 gap-8 text-sm sm:grid-cols-2 lg:grid-cols-2 lg:ml-auto lg:max-w-md">
{footerColumns.map((column) => (
<div key={column.title}>
<p className="text-xs font-semibold uppercase tracking-[0.25em] text-slate-400">

View File

@@ -37,15 +37,12 @@ export const Header = () => {
)}
>
<div className="mx-auto flex max-w-6xl items-center justify-between px-6 py-4 lg:px-8">
<Link to="/" className="flex items-center gap-2">
<Link to="/" className="flex items-center">
<img
src="/images/geomind_logo.png"
alt="Geomind logo"
className="h-10 w-10 rounded-full object-contain shadow-subtle"
className="h-12 w-auto object-contain"
/>
<span className="text-base font-semibold tracking-wider text-ink">
GEOMIND
</span>
</Link>
<nav className="hidden items-center gap-8 md:flex">
{navItems.map(({ label, to }) => (
@@ -64,7 +61,7 @@ export const Header = () => {
))}
<a
href="mailto:support@threefold.tech"
className="rounded-full border border-brand-200 bg-white px-4 py-2 text-sm font-semibold text-brand-700 shadow-subtle transition-all duration-300 hover:-translate-y-0.5 hover:bg-brand-600 hover:text-white"
className="rounded-full border border-brand-200 bg-white px-4 py-2 text-sm font-semibold text-brand-700 shadow-subtle transition-all duration-300 hover:-translate-y-0.5 hover:border-brand-700 hover:bg-brand-700 hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-300 focus-visible:ring-offset-2"
>
Contact
</a>
@@ -123,7 +120,7 @@ export const Header = () => {
))}
<a
href="mailto:support@threefold.tech"
className="rounded-full border border-brand-200 bg-brand-600 px-4 py-2 text-center text-sm font-semibold text-white shadow-subtle"
className="rounded-full border border-brand-200 bg-brand-600 px-4 py-2 text-center text-sm font-semibold text-white shadow-subtle transition-colors duration-300 hover:bg-brand-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-300 focus-visible:ring-offset-2"
>
Contact
</a>

View File

@@ -1,6 +1,7 @@
import { type ReactNode } from 'react';
import { Header } from './Header';
import { Footer } from './Footer';
import { ScrollToTop } from './ScrollToTop';
type LayoutProps = {
children: ReactNode;
@@ -8,9 +9,15 @@ type LayoutProps = {
export const Layout = ({ children }: LayoutProps) => {
return (
<div className="min-h-screen bg-gradient-to-b from-white via-mist to-white">
<div className="relative min-h-screen overflow-hidden bg-gradient-to-br from-slate-50 via-white to-brand-50/50">
<ScrollToTop />
{/* Decorative gradient blurs */}
<div className="pointer-events-none fixed -top-32 left-6 h-80 w-80 rounded-full bg-brand-200/40 blur-3xl lg:left-24" />
<div className="pointer-events-none fixed top-1/3 right-10 h-96 w-96 rounded-full bg-indigo-200/30 blur-3xl lg:right-24" />
<div className="pointer-events-none fixed bottom-1/4 left-1/4 h-72 w-72 rounded-full bg-brand-200/30 blur-3xl" />
<Header />
<main className="mx-auto max-w-6xl px-6 pb-24 pt-28 lg:px-8 lg:pt-32">{children}</main>
<main className="relative z-10 mx-auto max-w-6xl px-6 pb-24 pt-28 lg:px-8 lg:pt-32">{children}</main>
<Footer />
</div>
);

View File

@@ -0,0 +1,16 @@
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
export const ScrollToTop = () => {
const { pathname } = useLocation();
useEffect(() => {
const animationFrame = window.requestAnimationFrame(() => {
window.scrollTo({ top: 0, left: 0, behavior: 'auto' });
});
return () => window.cancelAnimationFrame(animationFrame);
}, [pathname]);
return null;
};

View File

@@ -16,11 +16,11 @@ const styles: Record<
string
> = {
solid:
'bg-brand-600 text-white shadow-subtle hover:bg-brand-500 hover:-translate-y-0.5',
'bg-brand-600 text-white shadow-subtle hover:bg-brand-500 hover:text-white hover:shadow-lg',
outline:
'border border-brand-200 bg-white text-brand-700 hover:border-brand-400 hover:-translate-y-0.5',
'border border-brand-200 bg-white text-brand-700 hover:border-brand-400 hover:bg-white/95 hover:text-brand-700 hover:shadow-md',
ghost:
'bg-transparent text-brand-600 hover:text-brand-500',
'bg-transparent text-brand-600 hover:bg-brand-50/80 hover:text-brand-700',
};
export const PrimaryButton = ({
@@ -32,7 +32,7 @@ export const PrimaryButton = ({
target,
}: PrimaryButtonProps) => {
const baseClasses =
'inline-flex items-center justify-center rounded-full px-5 py-2 text-sm font-semibold transition-all duration-300 focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-300 focus-visible:ring-offset-2';
'inline-flex items-center justify-center rounded-full px-5 py-2 text-sm font-semibold transition-all duration-300 hover:-translate-y-0.5 active:translate-y-0 focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-300 focus-visible:ring-offset-2';
if (to) {
return (

View File

@@ -1,44 +1,59 @@
import { motion } from 'framer-motion';
export const MissionVision = () => {
return (
<section className="py-16 lg:py-24">
<div className="relative overflow-hidden rounded-3xl border border-slate-100 bg-white/80 p-8 shadow-subtle backdrop-blur lg:p-16">
<div className="pointer-events-none absolute -top-36 right-10 h-72 w-72 rounded-full bg-brand-100 opacity-50 blur-3xl" />
<motion.div
initial={{ opacity: 0, y: 24 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.35 }}
transition={{ duration: 0.6, ease: 'easeOut' }}
className="relative z-10 space-y-12 lg:grid lg:grid-cols-2 lg:gap-16 lg:space-y-0"
<section className="relative py-20 lg:py-28">
<div className="relative mx-auto max-w-6xl px-6 lg:px-12">
<div className="flex flex-col gap-12 rounded-[32px] bg-gradient-to-br from-white via-white to-brand-50/40 p-8 shadow-xl ring-1 ring-brand-100/40 sm:p-12 lg:grid lg:grid-cols-[minmax(0,0.9fr)_1fr] lg:items-center">
<div className="order-1 lg:order-none">
<figure className="relative mx-auto max-w-sm overflow-hidden rounded-[28px] bg-gradient-to-br from-emerald-100/50 via-white to-brand-100/40 p-6 shadow-lg ring-1 ring-brand-200/40">
<div className="absolute inset-0 rounded-[24px] bg-[radial-gradient(circle_at_20%_20%,rgba(56,189,248,0.22),transparent_55%),radial-gradient(circle_at_80%_40%,rgba(59,130,246,0.18),transparent_60%)]" />
<img
src="/images/ceo-kristof.png"
alt="Kristof De Spiegeleer, Founder and CEO of GeoMind"
className="relative z-10 mx-auto w-full max-w-xs object-cover"
/>
<figcaption className="relative z-10 mt-6 text-center text-sm font-medium text-slate-500">
Kristof De Spiegeleer &mdash; Founder &amp; CEO
</figcaption>
</figure>
</div>
<div className="relative flex flex-col gap-8 rounded-3xl bg-white/90 p-8 shadow-inner ring-1 ring-brand-100/50 backdrop-blur">
<div className="flex items-center gap-4">
<div className="h-px flex-1 bg-gradient-to-r from-brand-500/50 via-brand-300/50 to-transparent" />
<span className="text-xs font-semibold uppercase tracking-[0.35em] text-brand-600">
Technology with Purpose
</span>
</div>
<div className="relative">
<span
aria-hidden="true"
className="float-left mr-3 -mt-3 text-6xl font-serif text-brand-500/25 leading-none"
>
<div>
<h2 className="text-xs font-semibold uppercase tracking-[0.35em] text-brand-600">
Our Mission
</h2>
<h3 className="mt-4 text-3xl font-semibold text-ink sm:text-4xl">
Building Inclusive Digital Infrastructure as a Fundamental Human Right
</h3>
<p className="mt-6 text-base text-slate-600 sm:text-lg">
GeoMind is committed to placing people and the planet at the forefront of our mission.
We believe that access to computing resources is a basic human right. By integrating
sustainable practices and innovative technologies, we aim to create an inclusive digital
infrastructure that empowers communities and fosters global equity.
</span>
<div className="space-y-6 text-base leading-8 text-slate-600 sm:text-lg sm:leading-8">
<p className="italic text-brand-700">
When we first started, our goal was simple, to build the foundation for the worlds digital future.
Over time, we realized that technology isnt just about performance or scale, its about purpose.
Its about people, communities, and the planet we share.
</p>
<p>
Today, were creating the next generation of datacenters, designed not only for the AI era but for a
sustainable, inclusive future. Our mission is clear: to make digital decentralized infrastructure a
universal right, accessible and responsible in equal measure.
</p>
<p>
Weve spent decades pioneering technologies that power the internet. Now, were redefining what
datacenters stand for, combining efficiency, sovereignty, and sustainability to serve both humanity and
innovation.
</p>
</div>
<div className="flex flex-col justify-between text-right">
<h2 className="text-xs font-semibold uppercase tracking-[0.35em] text-brand-600">
Our Journey
</h2>
<p className="mt-4 text-base text-slate-600 sm:text-lg">
We began by building the backbone of modern digital infrastructure. Over the years, we've
pioneered cloud computing, advanced storage systems, and scalable, secure datacenter
technologies. We're now creating the next generation of datacenters, a new standard built
for the demands of the AI era, offering efficiency, sovereignty, and profitability that
traditional datacenters simply can't deliver.
</p>
</div>
</motion.div>
<div className="border-t border-slate-200 pt-6 text-sm">
<p className="font-semibold text-brand-700">Kristof De Spiegeleer</p>
<p className="text-slate-500">Founder &amp; CEO, GeoMind</p>
</div>
</div>
</div>
</div>
</section>
);

View File

@@ -3,22 +3,27 @@ import { PrimaryButton } from '../../../components/ui/PrimaryButton';
export const FinalCallToAction = () => {
return (
<section className="pt-16 lg:pt-24">
<section className="py-20 lg:py-32">
<motion.div
initial={{ opacity: 0, scale: 0.98 }}
whileInView={{ opacity: 1, scale: 1 }}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.3 }}
transition={{ duration: 0.6, ease: 'easeOut' }}
className="rounded-3xl border border-brand-100 bg-white/80 p-10 text-center shadow-subtle backdrop-blur lg:p-16"
transition={{ duration: 0.7, ease: 'easeOut' }}
className="mx-auto max-w-4xl text-center"
>
<p className="text-xs font-semibold uppercase tracking-[0.45em] text-brand-500">
GeoMind
</p>
<h2 className="mt-4 text-3xl font-semibold text-ink sm:text-4xl">
The datacenter standard for the next era of cloud and AI.
<h2 className="text-3xl font-semibold text-ink sm:text-4xl lg:text-5xl">
{' '}
<span className="bg-gradient-to-r from-brand-500 via-brand-600 to-brand-700 bg-clip-text text-transparent">
The Datacenter Standard
</span>{' '}
<br />
for the next era of Cloud and AI.
</h2>
<div className="mt-8 flex justify-center">
<PrimaryButton to="/technology">Discover Technology</PrimaryButton>
<p className="mt-6 text-lg leading-relaxed text-ink/70 sm:text-xl">
For years we've been pioneering infrastructure technologies that power the world's most demanding cloud workloads. Learn more about our team and expertise behind our mission.
</p>
<div className="mt-10 flex justify-center">
<PrimaryButton to="/about">About Us</PrimaryButton>
</div>
</motion.div>
</section>

View File

@@ -16,21 +16,13 @@ export const HomeHero = () => {
</video>
<div className="absolute inset-0 bg-gradient-to-br from-[#0f172a]/70 via-[#1e1b4b]/60 to-[#312e81]/80" />
<div className="relative z-10 px-6 py-20 sm:px-10 lg:px-16">
<motion.p
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.1, duration: 0.6 }}
className="text-xs font-semibold uppercase tracking-[0.4em] text-white/70"
>
The Planet's Sovereign Agentic Cloud
</motion.p>
<motion.h1
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2, duration: 0.6 }}
className="mt-6 text-4xl font-semibold leading-tight sm:text-5xl lg:text-6xl"
className="text-3xl font-semibold leading-tight sm:text-4xl lg:text-5xl"
>
GeoMind
The planet&apos;s sovereign agentic cloud
</motion.h1>
<motion.p
initial={{ opacity: 0, y: 20 }}
@@ -52,7 +44,7 @@ export const HomeHero = () => {
<PrimaryButton
to="/usecases"
variant="ghost"
className="border border-white/40 text-white hover:bg-white/15"
className="border border-white/40 text-white hover:bg-white hover:text-brand-600"
>
Use Cases
</PrimaryButton>

View File

@@ -1,23 +1,110 @@
import { motion } from 'framer-motion';
import { useEffect, useRef } from 'react';
import { PrimaryButton } from '../../../components/ui/PrimaryButton';
export const ImpactBanner = () => {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext('2d');
if (!ctx) return;
// Set canvas size
const resizeCanvas = () => {
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
};
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
// Grid configuration
const gridSpacing = 40;
const dotRadius = 2;
const glowRadius = 8;
const dots: Array<{
x: number;
y: number;
baseX: number;
baseY: number;
phase: number;
speed: number;
}> = [];
// Create grid of dots
for (let x = 0; x < canvas.width; x += gridSpacing) {
for (let y = 0; y < canvas.height; y += gridSpacing) {
dots.push({
x,
y,
baseX: x,
baseY: y,
phase: Math.random() * Math.PI * 2,
speed: 0.5 + Math.random() * 0.5,
});
}
}
let animationFrameId: number;
let time = 0;
const animate = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
time += 0.01;
dots.forEach((dot) => {
// Subtle floating animation
const offsetX = Math.sin(time * dot.speed + dot.phase) * 3;
const offsetY = Math.cos(time * dot.speed * 0.8 + dot.phase) * 3;
dot.x = dot.baseX + offsetX;
dot.y = dot.baseY + offsetY;
// Pulsing opacity
const opacity = 0.15 + Math.sin(time * dot.speed + dot.phase) * 0.1;
// Draw glow
const gradient = ctx.createRadialGradient(dot.x, dot.y, 0, dot.x, dot.y, glowRadius);
gradient.addColorStop(0, `rgba(99, 102, 241, ${opacity * 0.3})`);
gradient.addColorStop(1, 'rgba(99, 102, 241, 0)');
ctx.fillStyle = gradient;
ctx.fillRect(dot.x - glowRadius, dot.y - glowRadius, glowRadius * 2, glowRadius * 2);
// Draw dot
ctx.beginPath();
ctx.arc(dot.x, dot.y, dotRadius, 0, Math.PI * 2);
ctx.fillStyle = `rgba(99, 102, 241, ${opacity + 0.2})`;
ctx.fill();
});
animationFrameId = requestAnimationFrame(animate);
};
animate();
return () => {
window.removeEventListener('resize', resizeCanvas);
cancelAnimationFrame(animationFrameId);
};
}, []);
return (
<section className="relative overflow-hidden rounded-3xl bg-white shadow-subtle">
<div className="absolute inset-0 -z-10">
<img
src="/images/mesh2.gif"
alt=""
className="h-full w-full object-cover opacity-50"
<section className="relative overflow-hidden py-16 text-center lg:py-20">
{/* Animated background canvas */}
<canvas
ref={canvasRef}
className="absolute inset-0 h-full w-full"
style={{ opacity: 0.6 }}
/>
<div className="absolute inset-0 bg-gradient-to-br from-white via-white/80 to-white/40 backdrop-blur" />
</div>
{/* Content */}
<motion.div
initial={{ opacity: 0, y: 28 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.3 }}
transition={{ duration: 0.6, ease: 'easeOut' }}
className="px-6 py-12 text-center sm:px-10 lg:px-16 lg:py-16"
className="relative z-10 px-6 sm:px-10"
>
<h2 className="text-3xl font-semibold text-ink sm:text-4xl">Designed for Real-World Impact</h2>
<p className="mx-auto mt-5 max-w-3xl text-base text-slate-600 sm:text-lg">

View File

@@ -29,30 +29,24 @@ const pillars = [
export const WhyGeomind = () => {
return (
<section className="relative overflow-hidden rounded-3xl">
<img
src="/images/hometech.jpg"
alt=""
className="absolute inset-0 h-full w-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-br from-[#0f172a]/80 via-[#111827]/85 to-[#020617]/80" />
<div className="relative z-10 px-6 py-16 text-white sm:px-10 lg:px-16 lg:py-24">
<section className="relative px-6 py-16 sm:px-10 lg:px-16 lg:py-24">
<div className="pointer-events-none absolute -left-32 top-0 h-56 w-56 rounded-full bg-brand-100 opacity-60 blur-3xl lg:-left-24" />
<div className="pointer-events-none absolute -right-24 bottom-0 h-64 w-64 rounded-full bg-brand-200 opacity-50 blur-3xl" />
<motion.div
initial={{ opacity: 0, y: 24 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.3 }}
transition={{ duration: 0.6, ease: 'easeOut' }}
className="max-w-3xl"
className="relative z-10 max-w-3xl"
>
<h2 className="text-3xl font-semibold sm:text-4xl">Why GeoMind</h2>
<p className="mt-5 text-base text-white/70 sm:text-lg">
Traditional datacenters are increasingly limited by geopolitics, inefficiency, and
energy waste. GeoMind eliminates those constraints with a resilient, autonomous
infrastructure that delivers planetary scalability and sovereign performance anywhere
in the world.
<h2 className="text-3xl font-semibold text-ink sm:text-4xl">Why GeoMind</h2>
<p className="mt-5 text-base text-slate-600 sm:text-lg">
Traditional datacenters are increasingly limited by geopolitics, inefficiency, and energy
waste. GeoMind eliminates those constraints with a resilient, autonomous infrastructure that
delivers planetary scalability and sovereign performance anywhere in the world.
</p>
</motion.div>
<div className="mt-12 grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
<div className="relative z-10 mt-12 grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
{pillars.map((pillar, index) => (
<motion.div
key={pillar.title}
@@ -60,10 +54,10 @@ export const WhyGeomind = () => {
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.25 }}
transition={{ duration: 0.5, delay: index * 0.1 }}
className="rounded-3xl bg-white/10 p-6 backdrop-blur-lg"
className="rounded-3xl border border-slate-100 bg-white/90 p-6 shadow-subtle"
>
<h3 className="text-lg font-semibold text-white">{pillar.title}</h3>
<ul className="mt-4 space-y-3 text-sm text-white/70">
<h3 className="text-lg font-semibold text-ink">{pillar.title}</h3>
<ul className="mt-4 space-y-3 text-sm text-slate-600">
{pillar.points.map((point) => (
<li key={point} className="flex gap-3">
<span className="mt-1 inline-block h-1.5 w-1.5 flex-shrink-0 rounded-full bg-brand-300" />
@@ -74,7 +68,6 @@ export const WhyGeomind = () => {
</motion.div>
))}
</div>
</div>
</section>
);
};

View File

@@ -1,30 +1,31 @@
import { motion } from 'framer-motion';
import { ShieldCheck, Globe, Leaf, LineChart, Layers } from 'lucide-react';
const benefits = [
{
title: 'Ultra-Secure',
description: 'Protect sensitive workloads with end-to-end security.',
icon: '/images/performance.svg',
icon: ShieldCheck,
},
{
title: 'Scales Globally',
description: 'Supports workloads anywhere, from local nodes to planetary scale.',
icon: '/images/security.svg',
icon: Globe,
},
{
title: 'Energy Efficient',
description: 'Up to 10x less energy for specific workloads.',
icon: '/images/sovereignty.svg',
icon: Leaf,
},
{
title: 'Profitable',
description: 'Monetize idle capacity; achieve ROI up to 3x higher.',
icon: '/images/computing.svg',
icon: LineChart,
},
{
title: 'Flexible',
description: 'Compatible with existing infrastructure and hyperscaler requirements.',
icon: '/images/decentralized.svg',
icon: Layers,
},
];
@@ -57,7 +58,7 @@ export const TechnologicalBenefits = () => {
className="flex h-full flex-col rounded-3xl border border-slate-100 bg-white/80 p-6 shadow-subtle backdrop-blur"
>
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-brand-50">
<img src={benefit.icon} alt="" className="h-7 w-7" />
<benefit.icon className="h-7 w-7 text-brand-600" />
</div>
<h3 className="mt-6 text-lg font-semibold text-ink">{benefit.title}</h3>
<p className="mt-3 text-sm leading-6 text-slate-600">{benefit.description}</p>

View File

@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
type Bullet = {
@@ -8,28 +8,52 @@ type Bullet = {
};
type Tab = {
id: 'compute' | 'data' | 'network';
id: 'zero-os' | 'compute' | 'data' | 'network';
label: string;
title: string;
description: string;
bullets: Bullet[];
cardText: string;
};
const tabs: Tab[] = [
{
id: 'zero-os',
label: 'Zero-OS',
title: 'Zero-OS',
description:
'Minimal, self-healing bare-metal OS that powers autonomous nodes across the ThreeFold Grid.',
cardText: 'Stateless architecture ensures every boot is secure and unmodified, eliminating configuration drift and security vulnerabilities.',
bullets: [
{
heading: 'Immutable by Design',
body: 'Boots statelessly from a signed image each time, removing drift and shrinking the attack surface.',
},
{
heading: 'Autonomous Operations',
body: 'Digital twin controllers redeploy workloads to healthy nodes and roll out updates with zero downtime.',
},
{
heading: 'Zero-Trust Networking',
body: 'Integrated WireGuard overlay and cryptographic identities secure every peer-to-peer connection.',
},
{
heading: 'Unified Resource Fabric',
body: 'Exposes compute, storage, and network primitives through a single API for edge, datacenter, or hybrid deployments.',
},
],
},
{
id: 'compute',
label: 'Compute',
title: 'Compute',
description: 'A self-healing compute fabric designed for resilience, decentralization, and scale.',
cardText: 'Autonomous workload orchestration across distributed nodes ensures maximum uptime and performance.',
bullets: [
{
heading: 'Autonomous Workload Management',
body: 'Workloads automatically migrate to healthy nodes to ensure fault tolerance and high availability.',
},
{
heading: 'P2P Compute Marketplace',
body: 'Individuals and enterprises can monetize spare compute and GPU resources through a decentralized network.',
},
{
heading: 'AI & Web3 Ready',
body: 'Run LLMs, autonomous agents, blockchain nodes, and immersive metaverse apps at the edge.',
@@ -54,6 +78,7 @@ const tabs: Tab[] = [
label: 'Data',
title: 'Data',
description: 'Private, distributed, and AI-native storage with user sovereignty at its core.',
cardText: 'Quantum-safe encryption and distributed redundancy protect your data while maintaining lightning-fast access.',
bullets: [
{
heading: 'Privacy-First',
@@ -75,6 +100,7 @@ const tabs: Tab[] = [
title: 'Network',
description:
'A secure, peer-to-peer internet backbone, self-sustaining, censorship-resistant, and optimized for performance.',
cardText: 'Mesh topology with intelligent routing creates a resilient network that adapts to changing conditions.',
bullets: [
{
heading: 'End-to-End Encryption',
@@ -96,10 +122,42 @@ const tabs: Tab[] = [
},
];
// Floating particle component
const FloatingParticle = ({ delay, index }: { delay: number; index: number }) => {
const startX = (index % 3) * 40 + 10;
const startY = Math.floor(index / 3) * 60 + 20;
return (
<motion.div
className="absolute h-3 w-3 rounded-full bg-blue-400"
style={{ left: `${startX}%`, top: `${startY}%` }}
initial={{ opacity: 0, scale: 0 }}
animate={{
y: [-10, -30, -10],
x: [0, Math.sin(index) * 15, 0],
opacity: [0, 0.7, 0],
scale: [0, 1.2, 0],
}}
transition={{
duration: 3,
delay,
repeat: Infinity,
ease: 'easeInOut',
}}
/>
);
};
export const TechnologyArchitecture = () => {
const [activeTab, setActiveTab] = useState<Tab['id']>('compute');
const [activeTab, setActiveTab] = useState<Tab['id']>('zero-os');
const [particles, setParticles] = useState<number[]>([]);
const current = tabs.find((tab) => tab.id === activeTab) ?? tabs[0];
useEffect(() => {
// Generate random particles on tab change
setParticles(Array.from({ length: 6 }, (_, i) => i));
}, [activeTab]);
return (
<section className="py-16 lg:py-24">
<div className="mx-auto max-w-4xl text-center">
@@ -110,17 +168,17 @@ export const TechnologyArchitecture = () => {
planetary scale.
</p>
</div>
<div className="mt-12 rounded-3xl border border-slate-200 bg-white/80 p-6 shadow-subtle backdrop-blur lg:p-10">
<div className="flex flex-wrap gap-3 border-b border-slate-200 pb-4">
<div className="mt-12 lg:mt-16">
<div className="flex flex-wrap gap-3 pb-4">
{tabs.map((tab) => (
<button
key={tab.id}
type="button"
onClick={() => setActiveTab(tab.id)}
className={`rounded-full px-4 py-2 text-sm font-semibold transition-all duration-300 ${
className={`rounded-full px-4 py-2 text-sm font-semibold transition-all duration-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-300 focus-visible:ring-offset-2 ${
activeTab === tab.id
? 'bg-brand-600 text-white shadow-subtle'
: 'bg-white text-slate-500 hover:text-brand-600'
? 'bg-brand-600 text-white shadow-subtle hover:bg-brand-700'
: 'border border-slate-200 bg-white text-slate-500 hover:border-brand-300 hover:bg-brand-50 hover:text-brand-700 hover:shadow-md'
}`}
>
{tab.label}
@@ -159,15 +217,131 @@ export const TechnologyArchitecture = () => {
))}
</ul>
</div>
<div className="hidden h-full rounded-3xl border border-dashed border-brand-100 bg-brand-50/50 p-6 lg:flex lg:flex-col lg:items-start lg:justify-between">
<p className="text-sm font-semibold uppercase tracking-[0.35em] text-brand-500">
<div className="hidden h-full rounded-3xl bg-brand-50/50 p-6 lg:flex lg:flex-col lg:items-start lg:justify-between">
<motion.p
key={`label-${current.id}`}
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3 }}
className="text-sm font-semibold uppercase tracking-[0.35em] text-brand-500"
>
{current.label}
</p>
<p className="mt-6 text-sm text-brand-700">
Intelligent agents orchestrate infrastructure layers to guarantee sovereignty and
resilience while maintaining the elegance of a single control plane.
</p>
<div className="mt-6 h-40 w-full rounded-2xl bg-gradient-to-br from-brand-100 via-white to-brand-200 opacity-80" />
</motion.p>
<motion.p
key={`text-${current.id}`}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.5, delay: 0.2 }}
className="mt-6 text-sm text-brand-700"
>
{current.cardText}
</motion.p>
<div className="relative mt-6 h-40 w-full overflow-hidden rounded-2xl bg-gradient-to-br from-blue-50 via-indigo-50 to-purple-50">
{/* Animated gradient overlay */}
<motion.div
className="absolute inset-0 bg-gradient-to-br from-blue-200/40 via-indigo-200/40 to-purple-200/40"
animate={{
opacity: [0.3, 0.6, 0.3],
scale: [1, 1.05, 1],
}}
transition={{
duration: 4,
repeat: Infinity,
ease: 'easeInOut',
}}
/>
{/* Floating particles */}
{particles.map((i) => (
<FloatingParticle key={`${current.id}-${i}`} delay={i * 0.4} index={i} />
))}
{/* Animated circles */}
<motion.div
className="absolute left-1/4 top-1/4 h-20 w-20 rounded-full bg-blue-300/30"
animate={{
scale: [1, 1.5, 1],
opacity: [0.3, 0.5, 0.3],
x: [0, 20, 0],
y: [0, -10, 0],
}}
transition={{
duration: 5,
repeat: Infinity,
ease: 'easeInOut',
}}
/>
<motion.div
className="absolute right-1/4 bottom-1/4 h-16 w-16 rounded-full bg-indigo-300/30"
animate={{
scale: [1, 1.3, 1],
opacity: [0.3, 0.6, 0.3],
x: [0, -15, 0],
y: [0, 10, 0],
}}
transition={{
duration: 4,
delay: 0.5,
repeat: Infinity,
ease: 'easeInOut',
}}
/>
{/* Central glowing orb */}
<motion.div
className="absolute left-1/2 top-1/2 h-24 w-24 -translate-x-1/2 -translate-y-1/2 rounded-full bg-gradient-to-br from-blue-400/40 to-purple-400/40 blur-2xl"
animate={{
scale: [1, 1.4, 1],
opacity: [0.4, 0.7, 0.4],
}}
transition={{
duration: 3,
repeat: Infinity,
ease: 'easeInOut',
}}
/>
{/* Animated lines */}
<svg className="absolute inset-0 h-full w-full opacity-30">
<motion.line
x1="10%"
y1="20%"
x2="90%"
y2="80%"
stroke="rgb(99, 102, 241)"
strokeWidth="2"
strokeDasharray="5,5"
animate={{
strokeDashoffset: [0, -20],
opacity: [0.3, 0.6, 0.3],
}}
transition={{
duration: 2,
repeat: Infinity,
ease: 'linear',
}}
/>
<motion.line
x1="90%"
y1="20%"
x2="10%"
y2="80%"
stroke="rgb(147, 51, 234)"
strokeWidth="2"
strokeDasharray="5,5"
animate={{
strokeDashoffset: [0, 20],
opacity: [0.3, 0.6, 0.3],
}}
transition={{
duration: 2.5,
repeat: Infinity,
ease: 'linear',
}}
/>
</svg>
</div>
</div>
</motion.div>
</AnimatePresence>

View File

@@ -17,20 +17,16 @@ const stackItems = [
export const TechnologyStack = () => {
return (
<section className="relative overflow-hidden rounded-3xl text-white">
<img
src="/images/hometech.jpg"
alt=""
className="absolute inset-0 h-full w-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-br from-[#0f172a]/85 via-[#312e81]/70 to-[#020617]/85" />
<div className="relative z-10 px-6 py-16 sm:px-10 lg:px-16 lg:py-24">
<section className="py-16 lg:py-24">
<div className="mx-auto max-w-6xl px-6 sm:px-10 lg:px-16">
<div className="mx-auto max-w-3xl text-center">
<p className="text-xs font-semibold uppercase tracking-[0.35em] text-white/60">
<p className="text-xs font-semibold uppercase tracking-[0.35em] text-slate-500">
Technology Stack
</p>
<h2 className="mt-4 text-3xl font-semibold sm:text-4xl">An Infrastructure Built for the AI Era</h2>
<p className="mt-5 text-base text-white/70 sm:text-lg">
<h2 className="mt-4 text-3xl font-semibold text-ink sm:text-4xl">
An Infrastructure Built for the AI Era
</h2>
<p className="mt-5 text-base text-slate-600 sm:text-lg">
Our unique technology stack delivers unmatched security, scalability, and flexibility,
preparing you for the AI workforce of the future.
</p>
@@ -43,14 +39,15 @@ export const TechnologyStack = () => {
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.3 }}
transition={{ duration: 0.5, delay: index * 0.1 }}
className="overflow-hidden rounded-3xl bg-white/10 backdrop-blur"
className="overflow-hidden rounded-3xl"
>
<div className="relative h-56 overflow-hidden">
<div className="h-56 overflow-hidden">
<img src={item.image} alt={item.title} className="h-full w-full object-cover" />
<div className="absolute inset-0 bg-gradient-to-t from-[#020617]/70 via-transparent to-transparent" />
<h3 className="absolute bottom-6 left-6 text-xl font-semibold">{item.title}</h3>
</div>
<p className="p-6 text-sm leading-6 text-white/75">{item.description}</p>
<div className="p-6">
<h3 className="text-xl font-semibold text-ink">{item.title}</h3>
<p className="mt-3 text-sm leading-6 text-slate-600">{item.description}</p>
</div>
</motion.div>
))}
</div>

View File

@@ -42,7 +42,7 @@ const useCases = [
export const UseCasesGrid = () => {
return (
<section className="py-16 lg:py-24">
<div className="relative overflow-hidden rounded-3xl border border-slate-100 bg-white/80 p-8 shadow-subtle backdrop-blur lg:p-16">
<div className="relative p-8 sm:rounded-3xl lg:p-16">
<div className="pointer-events-none absolute -bottom-20 -left-32 h-72 w-72 rounded-full bg-brand-100 opacity-50 blur-3xl" />
<div className="pointer-events-none absolute -top-24 right-12 h-48 w-48 rounded-full bg-brand-200 opacity-40 blur-3xl" />
<motion.div

View File

@@ -4,4 +4,7 @@ import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
server: {
allowedHosts: ['coucha-royal-nontannic.ngrok-free.dev'],
},
})