This commit is contained in:
Emre
2025-10-11 13:09:23 +03:00
parent 9451d22494
commit d3fd2db514
18 changed files with 443 additions and 154 deletions

View File

@@ -2,9 +2,9 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/png" href="/iconG.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>geomind2</title>
<title>GeoMind</title>
</head>
<body>
<div id="root"></div>

View File

@@ -1,5 +1,5 @@
{
"name": "geomind2",
"name": "geomind",
"private": true,
"version": "0.0.0",
"type": "module",

BIN
public/iconG.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,4 +1,6 @@
import { useState } from 'react';
import { Link } from 'react-router-dom';
import ContactForm from '../ui/ContactForm';
const footerLinksColumn1 = [
{ label: 'About', to: '/about' },
@@ -8,11 +10,11 @@ const footerLinksColumn1 = [
const footerLinksColumn2 = [
{ label: 'Manual', to: '/manual' },
{ label: 'Support', to: '/support' },
{ label: 'Privacy', to: '/privacy' },
];
export const Footer = () => {
const [isContactFormOpen, setIsContactFormOpen] = useState(false);
const year = new Date().getFullYear();
return (
@@ -39,6 +41,12 @@ export const Footer = () => {
{label}
</Link>
))}
<button
onClick={() => setIsContactFormOpen(true)}
className="text-white transition-colors duration-300 hover:text-brand-400 uppercase"
>
Support
</button>
</div>
</nav>
</div>
@@ -47,6 +55,12 @@ export const Footer = () => {
© {year}. <span className="text-brand-400">Built on Geomind.</span> All rights reserved.
</span>
</div>
<ContactForm
isOpen={isContactFormOpen}
onClose={() => setIsContactFormOpen(false)}
title="Get Support"
formType="contact"
/>
</footer>
);
};

View File

@@ -3,6 +3,7 @@ import { Link, NavLink, useLocation } from 'react-router-dom';
import { motion, AnimatePresence } from 'framer-motion';
import { cn } from '../../lib/cn';
import { buttonBaseClass } from '../../lib/buttonStyles';
import ContactForm from '../ui/ContactForm';
const navItems = [
{ label: 'About', to: '/about' },
@@ -13,6 +14,7 @@ const navItems = [
export const Header = () => {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [hoveredNav, setHoveredNav] = useState<string | null>(null);
const [isContactFormOpen, setIsContactFormOpen] = useState(false);
const location = useLocation();
const isHome = location.pathname === '/';
@@ -69,12 +71,12 @@ export const Header = () => {
</NavLink>
))}
</nav>
<a
href="mailto:support@threefold.tech"
<button
onClick={() => setIsContactFormOpen(true)}
className={cn(buttonBaseClass, 'px-4 py-2')}
>
GET IN TOUCH
</a>
</button>
<button
type="button"
aria-label="Toggle navigation"
@@ -134,16 +136,22 @@ export const Header = () => {
{label}
</NavLink>
))}
<a
href="mailto:support@threefold.tech"
<button
onClick={() => setIsContactFormOpen(true)}
className={cn(buttonBaseClass, 'flex w-full justify-center px-4 py-2 text-center')}
>
GET IN TOUCH
</a>
</button>
</div>
</motion.nav>
)}
</AnimatePresence>
<ContactForm
isOpen={isContactFormOpen}
onClose={() => setIsContactFormOpen(false)}
title="Get in Touch"
formType="contact"
/>
</motion.header>
);
};

View File

@@ -15,6 +15,8 @@ export const Layout = ({ children }: LayoutProps) => {
const darkRoutes = ['/about', '/technology', '/usecases'];
const isDarkPage = darkRoutes.some((route) => pathname.startsWith(route));
const isAbout = pathname.startsWith('/about');
return (
<div
className={cn(
@@ -30,7 +32,10 @@ export const Layout = ({ children }: LayoutProps) => {
'relative z-10',
isHome
? 'h-screen overflow-x-hidden overflow-y-scroll scroll-smooth snap-y snap-mandatory'
: 'mx-auto max-w-6xl px-6 pb-24 pt-28 lg:px-8 lg:pt-32',
: cn(
'pb-24 pt-28 lg:pt-32',
isAbout ? 'w-full px-0' : 'mx-auto max-w-6xl px-6 lg:px-8',
),
)}
>
{children}

View File

@@ -0,0 +1,199 @@
import { motion, AnimatePresence } from 'framer-motion';
import { useState } from 'react';
import { X, Send, CheckCircle } from 'lucide-react';
interface ContactFormProps {
isOpen: boolean;
onClose: () => void;
title?: string;
formType?: 'investor' | 'partner' | 'contact' | 'deploy' | 'offtake';
}
export default function ContactForm({ isOpen, onClose, title = "Get in Touch", formType }: ContactFormProps) {
const [formData, setFormData] = useState({
name: '',
email: '',
company: '',
message: '',
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [isSubmitted, setIsSubmitted] = useState(false);
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value,
}));
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setIsSubmitting(true);
// TODO: Add emailjs integration later
// Simulate API call
setTimeout(() => {
console.log('Form submitted:', { ...formData, formType });
setIsSubmitted(true);
setTimeout(() => {
setIsSubmitted(false);
setFormData({ name: '', email: '', company: '', message: '' });
onClose();
}, 3000);
setIsSubmitting(false);
}, 1000);
};
const getPlaceholderMessage = () => {
switch (formType) {
case 'investor':
return "Tell us about your investment interests and how we can collaborate.";
case 'partner':
return "Tell us about your partnership interests and how we can work together.";
case 'deploy':
return "Tell us about your deployment capacity plans and requirements.";
case 'offtake':
return "Tell us about your capacity offtake requirements.";
default:
return "Let us know how we can help.";
}
};
return (
<AnimatePresence>
{isOpen && (
<motion.div
className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/70 backdrop-blur-sm"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onClick={onClose}
>
<motion.div
className="bg-slate-950 rounded-2xl shadow-2xl w-full max-w-md relative overflow-hidden border border-white/10"
initial={{ scale: 0.9, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0.9, opacity: 0 }}
transition={{ type: "spring", damping: 25, stiffness: 300 }}
onClick={(e) => e.stopPropagation()}
>
{/* Header */}
<div className="flex items-center justify-between p-6 border-b border-white/10">
<h3 className="text-xl font-bold text-white">
{title}
</h3>
<button
onClick={onClose}
className="p-2 hover:bg-slate-800 rounded-lg transition-colors"
>
<X className="w-5 h-5 text-slate-400" />
</button>
</div>
{/* Form */}
<div className="p-6">
{isSubmitted ? (
<motion.div
className="text-center py-8"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
>
<CheckCircle className="w-16 h-16 text-brand-400 mx-auto mb-4" />
<h4 className="text-lg font-semibold text-white mb-2">
Thank you!
</h4>
<p className="text-slate-300">
We&apos;ll get back to you soon.
</p>
</motion.div>
) : (
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label htmlFor="name" className="block text-sm font-medium text-slate-300 mb-1">
Full Name *
</label>
<input
type="text"
id="name"
name="name"
value={formData.name}
onChange={handleInputChange}
required
className="w-full px-4 py-3 border border-white/10 rounded-lg focus:ring-2 focus:ring-brand-400 focus:border-transparent bg-slate-900 text-white placeholder-slate-500"
placeholder="Your full name"
/>
</div>
<div>
<label htmlFor="email" className="block text-sm font-medium text-slate-300 mb-1">
Email Address *
</label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleInputChange}
required
className="w-full px-4 py-3 border border-white/10 rounded-lg focus:ring-2 focus:ring-brand-400 focus:border-transparent bg-slate-900 text-white placeholder-slate-500"
placeholder="your.email@company.com"
/>
</div>
<div>
<label htmlFor="company" className="block text-sm font-medium text-slate-300 mb-1">
Company
</label>
<input
type="text"
id="company"
name="company"
value={formData.company}
onChange={handleInputChange}
className="w-full px-4 py-3 border border-white/10 rounded-lg focus:ring-2 focus:ring-brand-400 focus:border-transparent bg-slate-900 text-white placeholder-slate-500"
placeholder="Your company name"
/>
</div>
<div>
<label htmlFor="message" className="block text-sm font-medium text-slate-300 mb-1">
Message
</label>
<textarea
id="message"
name="message"
value={formData.message}
onChange={handleInputChange}
rows={4}
className="w-full px-4 py-3 border border-white/10 rounded-lg focus:ring-2 focus:ring-brand-400 focus:border-transparent bg-slate-900 text-white placeholder-slate-500 resize-none"
placeholder={getPlaceholderMessage()}
/>
</div>
<button
type="submit"
disabled={isSubmitting}
className="w-full inline-flex items-center justify-center gap-2 rounded-full border border-brand-200/60 bg-white px-6 py-3 text-sm font-semibold text-black shadow-[0_18px_40px_-26px_rgba(15,23,42,0.55)] transition-all duration-300 hover:-translate-y-0.5 hover:border-black hover:bg-brand-600 hover:text-white hover:shadow-[0_26px_52px_-32px_rgba(90,107,241,0.55)] disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:translate-y-0 disabled:hover:bg-white disabled:hover:text-black"
>
{isSubmitting ? (
<>
<div className="w-5 h-5 border-2 border-black/30 border-t-black rounded-full animate-spin" />
<span>Sending...</span>
</>
) : (
<>
<Send className="w-5 h-5" />
<span>Send Message</span>
</>
)}
</button>
</form>
)}
</div>
</motion.div>
</motion.div>
)}
</AnimatePresence>
);
}

View File

@@ -5,8 +5,8 @@ import { buttonBaseClass } from '../../../lib/buttonStyles';
export const AboutCta = () => {
return (
<section className="snap-start bg-black">
<div className="mx-auto flex w-full max-w-5xl flex-col items-center gap-10 px-6 py-32 text-center sm:px-10 sm:py-40">
<section className="snap-start bg-black pt-12 sm:pt-16 lg:pt-20">
<div className="mx-auto flex w-full max-w-5xl flex-col items-center gap-10 px-6 pb-32 text-center sm:px-10 sm:pb-40">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}

View File

@@ -1,21 +1,60 @@
import { motion } from 'framer-motion';
const records = [
{
title: 'World Records for Web Hosting (1997-2002)',
description: 'Kept UEFA, NASA, and World Cup traffic online with continent-scale uptime.',
layout: 'lg:col-span-3 lg:row-span-2',
showStream: true,
},
{
title: 'The First Backup Data Duplication System in the World (2005)',
description: 'Cut enterprise backup footprints by up to 100× before dedupe was mainstream.',
layout: 'lg:col-span-3',
},
{
title: 'One of the First Cloud Systems (2008)',
description: 'Shipped the first Virtual Private Data Center and proved elastic compute trust.',
layout: 'lg:col-span-3',
},
{
title: 'The First Multi-site Consistent Database (2010)',
description: 'Delivered failover that preserved every transaction across sovereign sites.',
layout: 'lg:col-span-3 lg:row-span-2',
showStream: true,
},
{
title: 'The First Unbreakable and Distributed Storage System (2012)',
description: 'Built tamper-proof storage that used 10× less energy and never went dark.',
layout: 'lg:col-span-3',
},
{
title: 'Probably the First Proof of Block Stake Blockchain (2017)',
description: 'Merged staking and settlement in one move—years before the market caught up.',
layout: 'lg:col-span-3',
},
] as const;
export const AboutHero = () => {
return (
<section className="relative overflow-hidden rounded-[32px] border border-white/10 bg-gradient-to-br from-[#06091d] via-[#0e1540] to-[#1c1448] text-white shadow-[0_35px_90px_-45px_rgba(15,23,42,0.95)]">
<section className="relative isolate bg-black px-6 pb-16 pt-0 sm:px-10 sm:pb-20 sm:pt-2 lg:px-16 lg:pb-24 lg:pt-4">
<div className="mx-auto w-full max-w-7xl">
<div className="grid gap-8 sm:gap-10 lg:grid-cols-[minmax(360px,420px)_minmax(0,1fr)] lg:items-stretch lg:gap-12 xl:grid-cols-[minmax(400px,500px)_minmax(0,1fr)]">
<div className="relative h-full">
<div className="group relative overflow-hidden rounded-[32px] border border-white/10 bg-gradient-to-br from-[#06091d] via-[#0e1540] to-[#1c1448] text-white shadow-[0_35px_90px_-45px_rgba(15,23,42,0.95)] transition-all duration-500 hover:-translate-y-1.5 hover:border-brand-400/60 hover:shadow-[0_40px_120px_-45px_rgba(99,102,241,0.55)]">
<img
src="/images/hometech2.jpg"
alt=""
className="absolute inset-0 h-full w-full object-cover opacity-40 mix-blend-screen"
className="absolute inset-0 h-full w-full object-cover opacity-40 mix-blend-screen transition-transform duration-700 group-hover:scale-105"
/>
<div className="absolute inset-0 bg-gradient-to-br from-white/10 via-white/5 to-transparent mix-blend-overlay" />
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top,_rgba(79,70,229,0.4),_transparent_60%)] opacity-90" />
<div className="absolute top-[-25%] right-[-5%] h-[420px] w-[420px] rounded-full bg-[#6366f1]/30 blur-3xl" />
<div className="absolute inset-0 bg-gradient-to-br from-white/10 via-white/5 to-transparent mix-blend-overlay transition-opacity duration-500 group-hover:opacity-90" />
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top,_rgba(79,70,229,0.4),_transparent_60%)] opacity-90 transition-opacity duration-500 group-hover:opacity-100" />
<div className="absolute top-[-25%] right-[-5%] h-[420px] w-[420px] rounded-full bg-[#6366f1]/30 blur-3xl transition-transform duration-700 group-hover:scale-110" />
<motion.div
initial={{ opacity: 0, y: 32 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, ease: 'easeOut' }}
className="relative z-10 px-6 py-24 sm:px-12 lg:px-20 lg:py-28"
className="relative z-10 px-6 py-20 sm:px-12 lg:px-16 lg:py-24"
>
<span className="inline-flex items-center gap-3 text-[0.68rem] uppercase tracking-[0.42em] text-white/70">
<span className="h-px w-10 bg-white/40" />
@@ -28,10 +67,39 @@ export const AboutHero = () => {
<p className="mt-6 max-w-3xl text-base text-white/80 sm:text-lg">
For decades, we've built the technologies that power the internet, from record-breaking
web hosting to unbreakable cloud systems. Now, we're redefining what datacenters stand
for: secure, sovereign, and profitable infrastructure designed for people, the planet,
and the AI-powered future.
for: secure, sovereign, and profitable infrastructure designed for people, the planet. Heres the short list of milestones that still guide our build.
</p>
</motion.div>
</div>
</div>
<div className="grid h-full grid-cols-1 gap-3 sm:grid-cols-2 lg:auto-rows-[minmax(120px,_1fr)] lg:grid-cols-6">
{records.map((record, index) => (
<motion.article
key={record.title}
initial={{ opacity: 0, y: 24 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: index * 0.05 }}
className={`group relative overflow-hidden rounded-3xl border border-white/10 bg-white/[0.04] p-5 backdrop-blur transition-all duration-300 hover:-translate-y-1.5 hover:border-brand-400/60 hover:bg-white/[0.08] hover:shadow-[0_32px_80px_-50px_rgba(56,189,248,0.55)] ${record.layout}`}
>
<h3 className="text-lg font-semibold leading-snug text-white">{record.title}</h3>
<p className="mt-3 text-sm leading-6 text-slate-200">{record.description}</p>
{record.showStream && (
<div className="pointer-events-none absolute inset-x-5 bottom-5 h-3 overflow-hidden rounded-full border border-white/10 bg-white/[0.06]">
<div className="absolute inset-0 bg-[radial-gradient(circle_at_center,rgba(59,130,246,0.45),transparent_72%)] opacity-70" />
<div className="absolute inset-0 bg-[linear-gradient(90deg,rgba(56,189,248,0)_0%,rgba(99,102,241,0.75)_50%,rgba(56,189,248,0)_100%)] opacity-90 [background-size:200%_100%] animate-data-stream" />
<div
className="absolute inset-0 bg-[linear-gradient(90deg,rgba(255,255,255,0)_0%,rgba(255,255,255,0.55)_12%,rgba(255,255,255,0)_40%)] mix-blend-screen opacity-70 [background-size:220%_100%] animate-data-stream"
style={{ animationDelay: '1.4s' }}
/>
</div>
)}
<div className="absolute -right-12 -top-12 h-24 w-24 rounded-full bg-brand-500/10 blur-3xl transition-transform duration-500 group-hover:scale-110" />
</motion.article>
))}
</div>
</div>
</div>
</section>
);
};

View File

@@ -1,38 +1,5 @@
import { motion } from 'framer-motion';
const breakthroughs = [
{
title: 'World-Record Hosting (1997 2002)',
description:
'Launched Europes earliest internet hosting platforms, keeping UEFA, NASA, and World Cup fans online with unprecedented scale and uptime.',
},
{
title: 'Backup Duplication Reinvented (2005)',
description:
'Created data reduction tech that delivered up to 100× efficiency gains for enterprise backup long before it was industry standard.',
},
{
title: 'Cloud Before “Cloud” (2008)',
description:
'Built one of the first virtual data centers, coining “Virtual Private Data Center” and proving that elastic, on-demand compute could be trusted by Tier-1 customers.',
},
{
title: 'Multi-site Consistency (2010)',
description:
'Engineered an always-on, multi-site database so workloads could fail over seamlessly without losing a single transaction.',
},
{
title: 'Unbreakable Distributed Storage (2012)',
description:
'Delivered tamper-proof storage that used 10× less energy, setting the benchmark for resilient, sovereign data services.',
},
{
title: 'Sustainable Proof-of-Stake (2017)',
description:
'Pioneered a block-stake blockchain that paired financial and staking transactions in one move—years before the rest of the market caught up.',
},
];
const exits = [
{
year: '2005',
@@ -73,7 +40,7 @@ const exits = [
export const TrackRecord = () => {
return (
<section className="pt-16 pb-12 text-slate-100 lg:pt-24 lg:pb-16">
<section className="px-6 pt-16 pb-12 text-slate-100 sm:px-10 lg:px-16 lg:pt-24 lg:pb-16">
<div className="mx-auto max-w-4xl text-center">
<div className="flex items-center justify-center gap-4">
<span
@@ -92,49 +59,19 @@ export const TrackRecord = () => {
Our team has been at the forefront of datacenter and cloud innovation for over two decades, building systems that were faster, safer, and more scalable than anything before.
</p>
<p className="mt-4 text-base text-slate-300 sm:text-lg">
From web-scale hosting to autonomous storage, our team has consistently introduced the
firsts that became benchmarks. Those wins fund our next chapter: a sovereign, agentic
cloud designed for the AI era.
Our team has built some of the worlds most advanced Internet and cloud technologies which were acquired by some of the biggest names in the space.
</p>
</div>
<div className="mt-12 grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
{breakthroughs.map((record, index) => (
<div className="mt-12 rounded-3xl border border-white/10 bg-black/60 p-8 shadow-[0_26px_64px_-48px_rgba(0,0,0,0.6)] transition-all duration-300 hover:border-brand-300/40 hover:shadow-[0_36px_90px_-50px_rgba(56,189,248,0.35)]">
<div className="grid gap-6 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5">
{exits.map((exit, index) => (
<motion.div
key={record.title}
key={exit.company}
initial={{ opacity: 0, y: 24 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.25 }}
viewport={{ once: true, amount: 0.2 }}
transition={{ duration: 0.5, delay: index * 0.05 }}
className="group relative flex h-full flex-col rounded-3xl border border-white/10 bg-black/80 p-8 transition-all duration-300 hover:-translate-y-1.5 hover:border-brand-400/50 hover:bg-white/5 hover:shadow-[0_28px_64px_-42px_rgba(56,189,248,0.55)] backdrop-blur"
>
<div className="inline-flex h-10 w-10 items-center justify-center rounded-full bg-brand-500/15 font-semibold text-brand-200">
{index + 1}
</div>
<h3 className="mt-6 text-lg font-semibold text-white">{record.title}</h3>
<p className="mt-3 text-sm leading-6 text-slate-300">{record.description}</p>
</motion.div>
))}
</div>
<div className="mt-16 flex items-center justify-center gap-4">
<span
aria-hidden="true"
className="hidden h-px w-16 bg-gradient-to-r from-transparent via-brand-500/40 to-brand-300/70 sm:block"
/>
<h2 className="text-center text-xs font-semibold uppercase tracking-[0.35em] text-brand-300">
Exits
</h2>
<span
aria-hidden="true"
className="hidden h-px w-16 bg-gradient-to-l from-transparent via-brand-500/40 to-brand-300/70 sm:block"
/>
</div>
<div className="mt-6 rounded-3xl border border-white/10 bg-black/60 p-8 shadow-[0_26px_64px_-48px_rgba(0,0,0,0.6)] transition-all duration-300 hover:border-brand-300/40 hover:shadow-[0_36px_90px_-50px_rgba(56,189,248,0.35)]">
<div className="mt-6 grid gap-6 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5">
{exits.map((exit) => (
<div
key={exit.company}
className="group relative flex flex-col items-center rounded-2xl bg-black/40 p-6 text-center transition-all duration-300 hover:-translate-y-1.5 hover:bg-white/5 hover:shadow-[0_22px_50px_-38px_rgba(56,189,248,0.45)]"
>
<span className="text-xs font-semibold uppercase tracking-[0.24em] text-brand-300">
@@ -161,7 +98,7 @@ export const TrackRecord = () => {
</p>
<p className="mt-1 text-sm text-white/80">{exit.acquiredBy}</p>
</div>
</div>
</motion.div>
))}
</div>
</div>

View File

@@ -83,7 +83,7 @@ const sections = [
</>
),
description:
'Minimal datacenter build costs. Energy-efficient autonomous operation. No enterprise maintenance overhead. Your competitive advantage is built in.',
'Minimal datacenter build costs. Energy-efficient autonomous operation. No enterprise maintenance overhead. Lower OPEX and CAPEX. Your competitive advantage is built in.',
showButton: false,
},
{

View File

@@ -7,15 +7,25 @@ export const CtaSection = () => {
return (
<section className="snap-start bg-black">
<div className="mx-auto flex w-full max-w-5xl flex-col items-center gap-10 px-6 py-40 text-center sm:px-10">
<motion.span
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-20%' }}
transition={{ duration: 0.6, ease: 'easeOut' }}
className="text-xs font-semibold uppercase tracking-[0.4em] text-white"
className="flex items-center justify-center gap-4"
>
<span
aria-hidden="true"
className="hidden h-px w-16 bg-gradient-to-r from-transparent via-brand-500/40 to-brand-300/70 sm:block"
/>
<span className="text-xs font-semibold uppercase tracking-[0.4em] text-white">
Ready when you are
</motion.span>
</span>
<span
aria-hidden="true"
className="hidden h-px w-16 bg-gradient-to-l from-transparent via-brand-500/40 to-brand-300/70 sm:block"
/>
</motion.div>
<motion.h3
initial={{ opacity: 0, y: 24 }}
whileInView={{ opacity: 1, y: 0 }}

View File

@@ -45,7 +45,11 @@ export const ScrollLockedSection = ({
{/* Animation Section - Takes ~80% of vertical space */}
<div className="flex flex-col items-center gap-6 py-10 sm:gap-8 sm:py-12 lg:gap-10">
<div className="mx-auto w-full border border-white/10 bg-black shadow-[0_26px_64px_-48px_rgba(0,0,0,0.6)] aspect-[28/8]" />
<div className="mx-auto flex aspect-[28/8] w-full items-center justify-center border border-white/30 bg-black/75 text-center shadow-[0_26px_64px_-48px_rgba(0,0,0,0.6)]">
<p className="px-8 text-xs font-semibold uppercase tracking-[0.35em] text-white/70 sm:text-sm">
Scroll triggered animation · Work in progress...
</p>
</div>
{/* Button below animation card */}
{showButton && buttonLink && (
<div className="flex justify-center">

View File

@@ -2,15 +2,15 @@ import { motion } from 'framer-motion';
export const TechnologyHero = () => {
return (
<section className="relative overflow-hidden rounded-[32px] border border-white/10 bg-gradient-to-br from-[#040b24] via-[#0a1842] to-[#211d61] text-white shadow-[0_35px_90px_-45px_rgba(17,24,39,0.95)]">
<section className="group relative overflow-hidden rounded-[32px] border border-white/10 bg-gradient-to-br from-[#040b24] via-[#0a1842] to-[#211d61] text-white shadow-[0_35px_90px_-45px_rgba(17,24,39,0.95)] transition-all duration-500 hover:-translate-y-1.5 hover:border-teal-300/60 hover:shadow-[0_40px_120px_-45px_rgba(45,212,191,0.55)]">
<img
src="/images/hometech.jpg"
alt=""
className="absolute inset-0 h-full w-full object-cover opacity-40 mix-blend-screen"
className="absolute inset-0 h-full w-full object-cover opacity-40 mix-blend-screen transition-transform duration-700 group-hover:scale-105"
/>
<div className="absolute inset-0 bg-gradient-to-br from-white/10 via-white/5 to-transparent mix-blend-overlay" />
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top,_rgba(94,234,212,0.45),_transparent_60%)] opacity-90" />
<div className="absolute top-[-30%] left-[-10%] h-[360px] w-[360px] rounded-full bg-[#22d3ee]/25 blur-3xl" />
<div className="absolute inset-0 bg-gradient-to-br from-white/10 via-white/5 to-transparent mix-blend-overlay transition-opacity duration-500 group-hover:opacity-90" />
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top,_rgba(94,234,212,0.45),_transparent_60%)] opacity-90 transition-opacity duration-500 group-hover:opacity-100" />
<div className="absolute top-[-30%] left-[-10%] h-[360px] w-[360px] rounded-full bg-[#22d3ee]/25 blur-3xl transition-transform duration-700 group-hover:scale-110" />
<motion.div
initial={{ opacity: 0, y: 32 }}
animate={{ opacity: 1, y: 0 }}

View File

@@ -1,39 +1,57 @@
import { useState } from 'react';
import { motion } from 'framer-motion';
import { cn } from '../../../lib/cn';
import { buttonBaseClass, buttonGhostLightClass } from '../../../lib/buttonStyles';
import { buttonGhostLightClass } from '../../../lib/buttonStyles';
import ContactForm from '../../../components/ui/ContactForm';
const useCases = [
{
title: 'Project Mycelium',
highlight: 'Decentralized Core',
description:
'A self-healing compute mesh that lets organizations and communities spin up sovereign cloud capacity instantly while sharing economics across the network.',
'Project Mycelium turns GeoMind primitives into community services, giving underserved regions, nomads, and privacy seekers decentralized storage, secure networking, and personal agents while sustaining host demand.',
image: '/images/mycelium.jpeg',
},
{
title: 'Zanzibar Digital Free Zone',
title: 'Digital Free Zone',
highlight: 'Sovereign Innovation',
description:
'An economic bridge for digital assets with dedicated governance, regulation, and dispute resolution so builders can deploy compliant Web3, AI, and fintech products.',
'An economic bridge for digital assets with dedicated governance, regulation, and dispute resolution so builders deploy compliant Web3, AI, and fintech products on GeoMind-powered infrastructure.',
image: '/images/freezone.jpeg',
},
{
title: 'COOP Cloud',
highlight: 'People-Powered Cloud',
description:
'A member-owned platform where every participant contributes nodes, earns rewards, and governs the roadmap as GeoMind scales toward a million-node collective.',
'COOP Cloud teams with the International Cooperative Alliance so 1.2 billion co-op members can run shared infrastructure, earn rewards, and launch services together on GeoMind.',
image: '/images/coop.jpeg',
},
{
title: 'Sovereign Cloud for Nations',
highlight: 'National Capacity',
title: 'Cloud for Nations',
highlight: 'Digital Sovereignty',
description:
'Independent hyperscale-to-edge infrastructure that gives governments full control over data, AI, and digital services while retaining economic value locally.',
'Most governments and citizens rely on foreign clouds, exposing finances and national security. GeoMind equips physical and digital states with sovereign infrastructure so they control data, AI, and services on their own terms.',
image: '/images/countries.jpeg',
},
{
title: 'Real Estate Deployments',
highlight: 'Underutilized Spaces',
description:
'Deploy GeoMind capacity inside underutilized properties with rapid integration into building utilities. Turn idle rooms into revenue generating data centers at minimal additional cost. Deliver residents and employees data sovereignty tools while relying on passive liquid cooling that requires little maintenance and keeps operating expenses highly competitive.',
image: '/images/hometech2.jpg',
featured: true,
},
];
export const UseCasesGrid = () => {
const [isContactFormOpen, setIsContactFormOpen] = useState(false);
const [formType, setFormType] = useState<'deploy' | 'offtake' | 'investor'>('deploy');
const handleOpenForm = (type: 'deploy' | 'offtake' | 'investor') => {
setFormType(type);
setIsContactFormOpen(true);
};
return (
<section className="py-16 text-slate-100 lg:py-24">
<motion.div
@@ -57,9 +75,20 @@ export const UseCasesGrid = () => {
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.25 }}
transition={{ duration: 0.5, delay: index * 0.05 }}
className="group relative overflow-hidden rounded-[28px] border border-white/10 bg-white/[0.02] shadow-[0_30px_80px_-40px_rgba(15,23,42,0.9)] transition-all duration-300 hover:-translate-y-1.5 hover:border-brand-400/50 hover:bg-white/10 hover:shadow-[0_36px_96px_-48px_rgba(79,70,229,0.55)] backdrop-blur"
className={cn(
'group relative flex h-full flex-col overflow-hidden rounded-3xl border border-white/10 bg-slate-950/80 transition-all duration-300 hover:-translate-y-1 hover:border-brand-400/50 hover:shadow-[0_25px_40px_-24px_rgba(15,118,230,0.45)]',
useCase.featured && 'sm:col-span-2 xl:col-span-4 sm:flex sm:flex-row sm:items-center sm:gap-8'
)}
>
<div className="pointer-events-none absolute inset-0 opacity-0 transition-opacity duration-300 group-hover:opacity-100">
<div className="absolute inset-0 bg-gradient-to-br from-brand-500/15 via-transparent to-brand-200/10" />
</div>
<div
className={cn(
'relative h-48 overflow-hidden',
useCase.featured && 'sm:h-full sm:w-[42%] lg:w-[38%]'
)}
>
<div className="relative h-48 overflow-hidden">
<img
src={useCase.image}
alt={useCase.title}
@@ -67,7 +96,12 @@ export const UseCasesGrid = () => {
/>
<div className="absolute inset-0 bg-gradient-to-t from-ink/80 via-transparent to-transparent" />
</div>
<div className="relative flex h-full flex-col gap-4 p-8">
<div
className={cn(
'relative flex h-full flex-col gap-4 p-8',
useCase.featured && 'sm:flex-1 sm:p-10 lg:p-12'
)}
>
<span className="inline-flex items-center gap-2 text-xs font-semibold uppercase tracking-[0.3em] text-sky-200/80">
<span className="h-px w-6 bg-sky-200/60" />
{useCase.highlight}
@@ -99,28 +133,34 @@ export const UseCasesGrid = () => {
</p>
</div>
<div className="grid w-full gap-4 sm:grid-cols-2 lg:w-auto lg:grid-cols-1">
<a
href="mailto:support@threefold.tech?subject=Deploy%20Capacity"
<button
onClick={() => handleOpenForm('deploy')}
className={cn(buttonGhostLightClass, 'flex w-full uppercase tracking-[0.25em]')}
>
Deploy Capacity
</a>
<a
href="mailto:support@threefold.tech?subject=Offtake%20Capacity"
</button>
<button
onClick={() => handleOpenForm('offtake')}
className={cn(buttonGhostLightClass, 'flex w-full uppercase tracking-[0.25em]')}
>
Offtake Capacity
</a>
<a
href="mailto:support@threefold.tech?subject=Invest%20in%20the%20Tech"
</button>
<button
onClick={() => handleOpenForm('investor')}
className={cn(buttonGhostLightClass, 'flex w-full uppercase tracking-[0.25em]')}
>
Invest in the Tech
</a>
</button>
</div>
</div>
</motion.div>
</motion.div>
<ContactForm
isOpen={isContactFormOpen}
onClose={() => setIsContactFormOpen(false)}
title={formType === 'deploy' ? 'Deploy Capacity' : formType === 'offtake' ? 'Offtake Capacity' : 'Invest in the Tech'}
formType={formType}
/>
</section>
);
};

View File

@@ -2,15 +2,15 @@ import { motion } from 'framer-motion';
export const UseCasesHero = () => {
return (
<section className="relative overflow-hidden rounded-[32px] border border-white/10 bg-gradient-to-br from-[#050a21] via-[#11173a] to-[#221852] text-white shadow-[0_35px_90px_-45px_rgba(17,24,39,0.95)]">
<section className="group relative overflow-hidden rounded-[32px] border border-white/10 bg-gradient-to-br from-[#050a21] via-[#11173a] to-[#221852] text-white shadow-[0_35px_90px_-45px_rgba(17,24,39,0.95)] transition-all duration-500 hover:-translate-y-1.5 hover:border-orange-300/60 hover:shadow-[0_40px_120px_-45px_rgba(249,115,22,0.45)]">
<img
src="/images/uscase_BG.png"
alt=""
className="absolute inset-0 h-full w-full object-cover opacity-40 mix-blend-screen"
className="absolute inset-0 h-full w-full object-cover opacity-40 mix-blend-screen transition-transform duration-700 group-hover:scale-105"
/>
<div className="absolute inset-0 bg-gradient-to-br from-white/10 via-white/5 to-transparent mix-blend-overlay" />
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top,_rgba(249,115,22,0.3),_transparent_60%)] opacity-90" />
<div className="absolute bottom-[-35%] right-[-5%] h-[380px] w-[380px] rounded-full bg-[#f97316]/25 blur-3xl" />
<div className="absolute inset-0 bg-gradient-to-br from-white/10 via-white/5 to-transparent mix-blend-overlay transition-opacity duration-500 group-hover:opacity-90" />
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top,_rgba(249,115,22,0.3),_transparent_60%)] opacity-90 transition-opacity duration-500 group-hover:opacity-100" />
<div className="absolute bottom-[-35%] right-[-5%] h-[380px] w-[380px] rounded-full bg-[#f97316]/25 blur-3xl transition-transform duration-700 group-hover:scale-110" />
<motion.div
initial={{ opacity: 0, y: 32 }}
animate={{ opacity: 1, y: 0 }}

View File

@@ -31,9 +31,14 @@ export default {
'0%, 100%': { opacity: 1 },
'50%': { opacity: 0.35 },
},
'data-stream': {
'0%': { backgroundPosition: '0% 50%' },
'100%': { backgroundPosition: '200% 50%' },
},
},
animation: {
blink: 'blink 0.9s steps(2, start) infinite',
'data-stream': 'data-stream 2.75s linear infinite',
},
},
},