updates
This commit is contained in:
@@ -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>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "geomind2",
|
||||
"name": "geomind",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
|
BIN
public/iconG.png
Normal file
BIN
public/iconG.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
@@ -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 |
@@ -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>
|
||||
);
|
||||
};
|
||||
|
@@ -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>
|
||||
);
|
||||
};
|
||||
|
@@ -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}
|
||||
|
199
src/components/ui/ContactForm.tsx
Normal file
199
src/components/ui/ContactForm.tsx
Normal 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'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>
|
||||
);
|
||||
}
|
@@ -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 }}
|
||||
|
@@ -1,37 +1,105 @@
|
||||
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)]">
|
||||
<img
|
||||
src="/images/hometech2.jpg"
|
||||
alt=""
|
||||
className="absolute inset-0 h-full w-full object-cover opacity-40 mix-blend-screen"
|
||||
/>
|
||||
<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" />
|
||||
<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"
|
||||
>
|
||||
<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" />
|
||||
About GeoMind
|
||||
<span className="h-px w-10 bg-white/40" />
|
||||
</span>
|
||||
<h1 className="mt-8 max-w-3xl text-3xl font-semibold leading-tight sm:text-4xl lg:text-5xl lg:leading-[1.1]">
|
||||
We Know a Thing or Two About Datacenters
|
||||
</h1>
|
||||
<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.
|
||||
</p>
|
||||
</motion.div>
|
||||
<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 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 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-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" />
|
||||
About GeoMind
|
||||
<span className="h-px w-10 bg-white/40" />
|
||||
</span>
|
||||
<h1 className="mt-8 max-w-3xl text-3xl font-semibold leading-tight sm:text-4xl lg:text-5xl lg:leading-[1.1]">
|
||||
We Know a Thing or Two About Datacenters
|
||||
</h1>
|
||||
<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. Here’s 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>
|
||||
);
|
||||
};
|
||||
|
@@ -1,38 +1,5 @@
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
const breakthroughs = [
|
||||
{
|
||||
title: 'World-Record Hosting (1997 – 2002)',
|
||||
description:
|
||||
'Launched Europe’s 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 world’s 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) => (
|
||||
<motion.div
|
||||
key={record.title}
|
||||
initial={{ opacity: 0, y: 24 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, amount: 0.25 }}
|
||||
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
|
||||
<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={exit.company}
|
||||
initial={{ opacity: 0, y: 24 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, amount: 0.2 }}
|
||||
transition={{ duration: 0.5, delay: index * 0.05 }}
|
||||
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>
|
||||
|
@@ -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,
|
||||
},
|
||||
{
|
||||
|
@@ -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"
|
||||
>
|
||||
Ready when you are
|
||||
</motion.span>
|
||||
<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
|
||||
</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 }}
|
||||
|
@@ -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">
|
||||
|
@@ -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 }}
|
||||
|
@@ -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="relative h-48 overflow-hidden">
|
||||
<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%]'
|
||||
)}
|
||||
>
|
||||
<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>
|
||||
);
|
||||
};
|
||||
|
@@ -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 }}
|
||||
|
@@ -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',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
Reference in New Issue
Block a user