updates
This commit is contained in:
@@ -4,9 +4,8 @@ import { motion, AnimatePresence } from 'framer-motion';
|
|||||||
import { cn } from '../../lib/cn';
|
import { cn } from '../../lib/cn';
|
||||||
|
|
||||||
const navItems = [
|
const navItems = [
|
||||||
{ label: 'Home', to: '/' },
|
|
||||||
{ label: 'About', to: '/about' },
|
{ label: 'About', to: '/about' },
|
||||||
{ label: 'Technology', to: '/technology' },
|
{ label: 'Solutions', to: '/technology' },
|
||||||
{ label: 'Use Cases', to: '/usecases' },
|
{ label: 'Use Cases', to: '/usecases' },
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -36,12 +35,13 @@ export const Header = () => {
|
|||||||
isScrolled ? 'bg-mist/95 shadow-lg backdrop-blur-sm' : 'bg-transparent',
|
isScrolled ? 'bg-mist/95 shadow-lg backdrop-blur-sm' : 'bg-transparent',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="mx-auto flex max-w-6xl items-center justify-between px-6 py-4 lg:px-8">
|
<div className="mx-auto flex max-w-6xl items-center justify-between py-4">
|
||||||
|
<div className="flex items-center gap-8">
|
||||||
<Link to="/" className="flex items-center">
|
<Link to="/" className="flex items-center">
|
||||||
<img
|
<img
|
||||||
src="/images/geomind_logo.png"
|
src="/images/geomind_logo.png"
|
||||||
alt="Geomind logo"
|
alt="Geomind logo"
|
||||||
className="h-12 w-auto object-contain"
|
className="h-8 w-auto object-contain"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<nav className="hidden items-center gap-8 md:flex">
|
<nav className="hidden items-center gap-8 md:flex">
|
||||||
@@ -59,13 +59,14 @@ export const Header = () => {
|
|||||||
{label}
|
{label}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
))}
|
))}
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
<a
|
<a
|
||||||
href="mailto:support@threefold.tech"
|
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: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"
|
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
|
Contact
|
||||||
</a>
|
</a>
|
||||||
</nav>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
aria-label="Toggle navigation"
|
aria-label="Toggle navigation"
|
||||||
|
@@ -2,7 +2,7 @@ import { motion } from 'framer-motion';
|
|||||||
|
|
||||||
export const CtaSection = () => {
|
export const CtaSection = () => {
|
||||||
return (
|
return (
|
||||||
<section className="snap-start bg-mist">
|
<section className="snap-start bg-[rgb(172,173,175)]">
|
||||||
<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">
|
<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.span
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
@@ -10,7 +10,7 @@ export const FooterSection = () => {
|
|||||||
const year = new Date().getFullYear();
|
const year = new Date().getFullYear();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className="bg-mist px-6 pb-16 pt-12 sm:px-10 lg:px-20">
|
<footer className="bg-[rgb(172,173,175)] px-6 pb-16 pt-12 sm:px-10 lg:px-20">
|
||||||
<div className="mx-auto flex w-full max-w-7xl flex-col gap-12 border-t border-ink/10 pt-12 md:flex-row md:items-center md:justify-between">
|
<div className="mx-auto flex w-full max-w-7xl flex-col gap-12 border-t border-ink/10 pt-12 md:flex-row md:items-center md:justify-between">
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<span className="text-xs font-semibold uppercase tracking-[0.35em] text-ink/60">
|
<span className="text-xs font-semibold uppercase tracking-[0.35em] text-ink/60">
|
||||||
|
@@ -17,15 +17,14 @@ export const HeroSection = () => {
|
|||||||
transition={{ duration: 0.8, ease: 'easeOut' }}
|
transition={{ duration: 0.8, ease: 'easeOut' }}
|
||||||
className="max-w-3xl space-y-6"
|
className="max-w-3xl space-y-6"
|
||||||
>
|
>
|
||||||
<span className="text-xs font-semibold uppercase tracking-[0.4em] text-ink/70">
|
|
||||||
Geomind
|
|
||||||
</span>
|
|
||||||
<h1 className="text-4xl font-medium leading-tight text-ink sm:text-5xl md:text-6xl">
|
<h1 className="text-4xl font-medium leading-tight text-ink sm:text-5xl md:text-6xl">
|
||||||
Geospatial intelligence for real-world momentum.
|
The Planet's Sovereign Agentic Cloud
|
||||||
</h1>
|
</h1>
|
||||||
<p className="max-w-xl text-lg text-ink/80">
|
<p className="max-w-xl text-lg text-ink/80">
|
||||||
Introduce a compelling statement here that speaks to the transformation you deliver.
|
A new generation of decentralized cloud and AI infrastructure.
|
||||||
Keep it short, grounded, and ready for future storytelling.
|
<br />
|
||||||
|
Secure, scalable, efficient, and sovereign by design. Deploy your own datacenter, scale globally, and turn infrastructure into profit.
|
||||||
</p>
|
</p>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { motion, useScroll, useSpring, useTransform, useMotionValueEvent } from 'framer-motion';
|
import { motion, useScroll, useSpring, useMotionValueEvent } from 'framer-motion';
|
||||||
import { useRef, useState } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
|
|
||||||
type ScrollLockedSectionProps = {
|
type ScrollLockedSectionProps = {
|
||||||
@@ -8,6 +8,8 @@ type ScrollLockedSectionProps = {
|
|||||||
description: string;
|
description: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const TAB_ITEMS = ['Inbox 24', 'Meetings 8', 'Subscriptions 2', 'Newsletters 6', 'Shopping 8'];
|
||||||
|
|
||||||
export const ScrollLockedSection = ({
|
export const ScrollLockedSection = ({
|
||||||
id,
|
id,
|
||||||
eyebrow,
|
eyebrow,
|
||||||
@@ -20,77 +22,72 @@ export const ScrollLockedSection = ({
|
|||||||
offset: ['start start', 'end end'],
|
offset: ['start start', 'end end'],
|
||||||
});
|
});
|
||||||
const smoothProgress = useSpring(scrollYProgress, { stiffness: 120, damping: 30, mass: 0.4 });
|
const smoothProgress = useSpring(scrollYProgress, { stiffness: 120, damping: 30, mass: 0.4 });
|
||||||
const cardFillWidth = useTransform(smoothProgress, [0, 1], ['12%', '100%']);
|
|
||||||
const cardFillOpacity = useTransform(smoothProgress, [0, 1], [0.25, 0.85]);
|
|
||||||
const barScale = useTransform(smoothProgress, [0, 1], [0.3, 1]);
|
|
||||||
const [percent, setPercent] = useState(0);
|
const [percent, setPercent] = useState(0);
|
||||||
|
const [activeIndex, setActiveIndex] = useState(0);
|
||||||
|
|
||||||
useMotionValueEvent(smoothProgress, 'change', (value) => {
|
useMotionValueEvent(smoothProgress, 'change', (value) => {
|
||||||
setPercent(Math.round(value * 100));
|
const percentage = Math.round(value * 100);
|
||||||
|
setPercent(percentage);
|
||||||
|
const nextIndex = Math.min(
|
||||||
|
TAB_ITEMS.length - 1,
|
||||||
|
Math.round(value * (TAB_ITEMS.length - 1)),
|
||||||
|
);
|
||||||
|
setActiveIndex(nextIndex);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id={id} ref={sectionRef} className="relative h-[200vh] snap-start">
|
<section id={id} ref={sectionRef} className="relative h-[200vh] snap-start bg-[rgb(172,173,175)]">
|
||||||
<div className="sticky top-0 flex h-screen flex-col">
|
<div className="sticky top-0 flex h-screen flex-col">
|
||||||
<div className="mx-auto flex h-full w-full max-w-7xl flex-col justify-between px-6 py-24 sm:px-10 lg:px-20">
|
<div className="mx-auto flex h-full w-full max-w-7xl flex-col justify-between px-6 py-24 sm:px-10 lg:px-20">
|
||||||
<div className="space-y-4">
|
<div className="space-y-6">
|
||||||
<span className="text-xs font-semibold uppercase tracking-[0.45em] text-ink/50">
|
<span className="text-[11px] font-semibold uppercase tracking-[0.45em] text-ink/45">
|
||||||
{eyebrow}
|
{eyebrow}
|
||||||
</span>
|
</span>
|
||||||
<div className="max-w-3xl space-y-4">
|
<div className="max-w-3xl space-y-3">
|
||||||
<h2 className="text-3xl font-medium leading-tight text-ink sm:text-4xl md:text-5xl">
|
<p className="text-3xl font-semibold leading-tight text-ink sm:text-[2.25rem] sm:leading-[1.2]">
|
||||||
{title}
|
{title}
|
||||||
</h2>
|
</p>
|
||||||
<p className="text-lg text-ink/75">{description}</p>
|
<p className="text-lg leading-relaxed text-ink/70">{description}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-16 flex flex-1 flex-col justify-end">
|
<div className="mt-20 flex flex-1 flex-col justify-start">
|
||||||
<div className="space-y-8 rounded-3xl border border-ink/10 bg-white/60 p-8 shadow-[0_22px_48px_-32px_rgba(0,0,0,0.28)] backdrop-blur">
|
<div className="flex w-full flex-1 flex-col overflow-hidden rounded-[36px] border border-ink/10 bg-mist/70 shadow-[0_26px_64px_-48px_rgba(0,0,0,0.6)] backdrop-blur">
|
||||||
<div className="space-y-4">
|
<div className="flex items-center justify-between px-10 pt-10 text-[11px] font-semibold uppercase tracking-[0.35em] text-ink/45">
|
||||||
<div className="flex items-center justify-between">
|
<span>Animation Placeholder</span>
|
||||||
<p className="text-sm font-semibold uppercase tracking-[0.35em] text-ink/60">
|
<motion.span initial={false} animate={{ opacity: percent > 0 ? 1 : 0.3 }}>
|
||||||
Animation Placeholder
|
|
||||||
</p>
|
|
||||||
<motion.span
|
|
||||||
className="text-xs font-medium uppercase tracking-[0.35em] text-ink/50"
|
|
||||||
style={{ opacity: smoothProgress }}
|
|
||||||
>
|
|
||||||
{percent}%
|
{percent}%
|
||||||
</motion.span>
|
</motion.span>
|
||||||
</div>
|
</div>
|
||||||
<div className="h-1.5 w-full overflow-hidden rounded-full bg-ink/10">
|
<div className="flex-1 px-10 pb-12">
|
||||||
<motion.div
|
<div className="flex h-full items-center justify-center rounded-[28px] border border-dashed border-ink/15 bg-white/50 text-xs font-semibold uppercase tracking-[0.4em] text-ink/25">
|
||||||
className="h-full origin-left rounded-full bg-ink"
|
Content Canvas
|
||||||
style={{ scaleX: smoothProgress }}
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="border-t border-ink/10 bg-mist/80 px-8 py-6">
|
||||||
|
<div className="flex items-center justify-between text-[11px] font-medium uppercase tracking-[0.3em] text-ink/35">
|
||||||
|
{TAB_ITEMS.map((tab, index) => (
|
||||||
|
<div key={tab} className="relative flex flex-1 justify-center">
|
||||||
|
<span className={index === activeIndex ? 'text-ink' : 'text-ink/40'}>{tab}</span>
|
||||||
|
<motion.span
|
||||||
|
initial={false}
|
||||||
|
animate={{ opacity: index === activeIndex ? 1 : 0 }}
|
||||||
|
transition={{ duration: 0.3, ease: 'easeOut' }}
|
||||||
|
className="absolute -bottom-3 left-1/2 h-1 w-16 -translate-x-1/2 rounded-full bg-ink"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="relative h-56 w-full overflow-hidden rounded-2xl border border-ink/10 bg-mist/70">
|
|
||||||
<div className="absolute inset-0 grid grid-cols-12 gap-2 px-8 py-10">
|
|
||||||
{Array.from({ length: 12 }).map((_, index) => (
|
|
||||||
<motion.span
|
|
||||||
key={index}
|
|
||||||
className="flex h-full w-full origin-bottom items-end justify-center rounded-full bg-ink/15"
|
|
||||||
style={{ opacity: cardFillOpacity, scaleY: barScale }}
|
|
||||||
>
|
|
||||||
<span className="sr-only">Placeholder animation bar</span>
|
|
||||||
</motion.span>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="absolute bottom-8 left-1/2 flex w-11/12 -translate-x-1/2 items-center gap-3">
|
|
||||||
<div className="h-1 w-full rounded-full bg-ink/10">
|
|
||||||
<motion.div
|
|
||||||
className="h-full rounded-full bg-ink"
|
|
||||||
style={{ width: cardFillWidth, opacity: cardFillOpacity }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<motion.span className="text-[10px] font-semibold uppercase tracking-[0.3em] text-ink/50">
|
|
||||||
{percent}%
|
|
||||||
</motion.span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="mt-10 flex justify-center">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="flex items-center gap-2 rounded-full border border-ink/15 bg-white/70 px-6 py-2 text-[11px] font-semibold uppercase tracking-[0.35em] text-ink/50 shadow-[0_16px_32px_-28px_rgba(0,0,0,0.65)] transition-colors duration-300 hover:border-ink/30 hover:text-ink/70"
|
||||||
|
>
|
||||||
|
Directory
|
||||||
|
<span className="text-ink/30">Info</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Reference in New Issue
Block a user