This commit is contained in:
2025-09-12 22:02:16 +02:00
parent 92e5c36ddc
commit 3e79ab7ab8
25 changed files with 3169 additions and 1280 deletions

2
next-env.d.ts vendored
View File

@@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.

4218
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -15,13 +15,14 @@
"@tailwindcss/postcss": "^4.1.7",
"@types/node": "^20.10.8",
"@types/react": "^18.2.55",
"react-type-animation": "^3.2.0",
"@types/react-dom": "^18.2.18",
"clsx": "^2.1.0",
"framer-motion": "^10.15.0",
"next": "^14.0.4",
"popmotion": "^11.0.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-type-animation": "^3.2.0",
"tailwindcss": "^4.1.7",
"typescript": "^5.3.3",
"use-debounce": "^10.0.0"

BIN
public/images/branding.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

BIN
public/images/calendar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
public/images/calk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

BIN
public/images/code.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 KiB

BIN
public/images/data.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 KiB

BIN
public/images/datasets.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

View File

@@ -1,76 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 50 50">
<defs>
<style>
.cls-1 {
fill: #000;
}
.cls-1, .cls-2, .cls-3 {
stroke-width: 0px;
}
.cls-4 {
clip-path: url(#clippath-2);
}
.cls-2 {
fill: #a6a6a6;
}
.cls-3 {
fill: none;
}
.cls-5 {
clip-path: url(#clippath-1);
}
.cls-6 {
clip-path: url(#clippath-4);
}
.cls-7 {
clip-path: url(#clippath);
}
.cls-8 {
clip-path: url(#clippath-3);
}
</style>
<clipPath id="clippath">
<rect class="cls-3" x="9.6" y="9.5" width="31.3" height="31.3"/>
</clipPath>
<clipPath id="clippath-1">
<rect class="cls-3" x="21.1" y="4.7" width="8.3" height="8.6"/>
</clipPath>
<clipPath id="clippath-2">
<rect class="cls-3" x="21.1" y="36.6" width="8.3" height="8.7"/>
</clipPath>
<clipPath id="clippath-3">
<rect class="cls-3" x="37" y="27.4" width="7.7" height="9.2"/>
</clipPath>
<clipPath id="clippath-4">
<rect class="cls-3" x="37" y="12.4" width="7.7" height="10"/>
</clipPath>
</defs>
<g class="cls-7">
<path class="cls-2" d="M40.5,24.9c0,1-.1,2-.3,3,0,.5-.2,1-.4,1.5-.1.5-.3,1-.5,1.4-.4.9-.9,1.8-1.4,2.7-.6.8-1.2,1.6-1.9,2.3-.4.4-.7.7-1.1,1-.4.3-.8.6-1.2.9-3,2-6.5,2.9-10.1,2.5-.5,0-1-.1-1.5-.2-.5-.1-1-.2-1.5-.4-.5-.1-1-.3-1.4-.5-.9-.4-1.8-.9-2.7-1.4-.4-.3-.8-.6-1.2-.9-.8-.6-1.5-1.4-2.1-2.1-.3-.4-.6-.8-.9-1.2-.6-.8-1-1.7-1.4-2.7-.2-.5-.4-.9-.5-1.4-.1-.5-.3-1-.4-1.5-.1-.5-.2-1-.2-1.5,0-.5,0-1,0-1.5s0-1,0-1.5c0-.5.1-1,.2-1.5,0-.5.2-1,.4-1.5.6-1.9,1.6-3.8,2.8-5.3.3-.4.7-.8,1-1.1.4-.4.7-.7,1.1-1,1.2-1,2.5-1.8,3.9-2.3.5-.2.9-.4,1.4-.5,1.5-.4,3-.7,4.5-.7,1,0,2,.1,3,.3.5.1,1,.2,1.5.4,1,.3,1.9.7,2.8,1.2.4.2.9.5,1.3.8.4.3.8.6,1.2.9.4.3.8.7,1.1,1,.4.4.7.7,1,1.1.3.4.6.8.9,1.2,1.7,2.5,2.6,5.5,2.6,8.6Z"/>
</g>
<path class="cls-1" d="M28.5,22.5l-3.2-1.8c-.2-.1-.4-.1-.6,0l-3.2,1.8c-.2.1-.3.3-.3.5v3.6c0,.2.1.4.3.5l3.2,1.8c0,0,.2,0,.3,0,.1,0,.2,0,.3,0l3.2-1.8c.2-.1.3-.3.3-.5v-3.6c0-.2-.1-.4-.3-.5ZM27.6,26.4l-2.5,1.5-2.5-1.5v-2.9l2.5-1.5,2.5,1.5v2.9Z"/>
<g class="cls-5">
<path class="cls-1" d="M28.5,6.6l-3.2-1.8c-.2-.1-.4-.1-.6,0l-3.1,1.8c-.2.1-.3.3-.3.5v3.6c0,.2.1.4.3.5l3.2,1.8c0,0,.2,0,.3,0,.1,0,.2,0,.3,0l3.2-1.8c.2-.1.3-.3.3-.5v-3.6c0-.2-.1-.4-.3-.5ZM27.6,10.5l-2.5,1.5-2.5-1.5v-2.9l2.5-1.5,2.5,1.5v2.9Z"/>
</g>
<g class="cls-4">
<path class="cls-1" d="M28.5,38.6l-3.2-1.8c-.2-.1-.4-.1-.6,0l-3.2,1.8c-.2.1-.3.3-.3.5v3.6c0,.2.1.4.3.5l3.2,1.8c0,0,.2,0,.3,0,.1,0,.2,0,.3,0l3.2-1.8c.2-.1.3-.3.3-.5v-3.6c0-.2-.1-.4-.3-.5ZM27.6,42.4l-2.5,1.5-2.5-1.5v-2.9l2.5-1.5,2.5,1.5v2.9Z"/>
</g>
<path class="cls-1" d="M12.5,29.9l-3.2-1.8c-.2-.1-.4-.1-.6,0l-3.2,1.8c-.2.1-.3.3-.3.5v3.6c0,.2.1.4.3.5l3.2,1.8c.2.1.4.1.6,0l3.2-1.8c.2-.1.3-.3.3-.5v-3.6c0-.2-.1-.4-.3-.5ZM11.6,33.7l-2.5,1.5-2.5-1.5v-2.9l2.5-1.5,2.5,1.5v2.9Z"/>
<g class="cls-8">
<path class="cls-1" d="M44.5,29.9l-3.2-1.8c-.2-.1-.4-.1-.6,0l-3.2,1.8c-.2.1-.3.3-.3.5v3.6c0,.2.1.4.3.5l3.2,1.8c.2.1.4.1.6,0l3.2-1.8c.2-.1.3-.3.3-.5v-3.6c0-.2-.1-.4-.3-.5ZM43.6,33.7l-2.5,1.5-2.5-1.5v-2.9l2.5-1.5,2.5,1.5v2.9Z"/>
</g>
<path class="cls-1" d="M12.5,15.1l-3.2-1.8c-.2-.1-.4-.1-.6,0l-3.2,1.8c-.2.1-.3.3-.3.5v3.6c0,.2.1.4.3.5l3.2,1.8c.2.1.4.1.6,0l3.2-1.8c.2-.1.3-.3.3-.5v-3.6c0-.2-.1-.4-.3-.5h0ZM11.6,19l-2.5,1.5-2.5-1.5v-2.9l2.5-1.5,2.5,1.5v2.9Z"/>
<g class="cls-6">
<path class="cls-1" d="M44.5,15.1l-3.2-1.8c-.2-.1-.4-.1-.6,0l-3.2,1.8c-.2.1-.3.3-.3.5v3.6c0,.2.1.4.3.5l3.2,1.8c.2.1.4.1.6,0l3.2-1.8c.2-.1.3-.3.3-.5v-3.6c0-.2-.1-.4-.3-.5h0ZM43.6,19l-2.5,1.5-2.5-1.5v-2.9l2.5-1.5,2.5,1.5v2.9Z"/>
</g>
<path class="cls-1" d="M9.7,26.5v-3.1c0-.3-.3-.6-.6-.6s-.6.3-.6.6v3.1c0,.3.3.6.6.6s.6-.3.6-.6h0ZM25.7,34.4v-3.1c0-.3-.3-.6-.6-.6-.3,0-.6.3-.6.6h0v3.1c0,.3.3.6.6.6.3,0,.6-.3.6-.6,0,0,0,0,0,0ZM18.9,37.4l-3.7-2.3c-.3-.2-.7,0-.9.2s0,.7.2.9h0l3.7,2.3c.3.2.7,0,.9-.2.2-.3,0-.7-.2-.9ZM34.7,35.1l-3.7,2.3c-.3.2-.4.6-.2.9.1.2.3.3.5.3.1,0,.2,0,.3,0l3.7-2.3c.3-.2.4-.6.2-.9-.2-.3-.6-.4-.8-.2ZM31,12.5l3.7,2.3c0,0,.2,0,.3,0,.2,0,.4-.1.5-.3.2-.3,0-.7-.2-.9l-3.7-2.3c-.3-.2-.7,0-.9.2,0,0,0,0,0,0-.2.3,0,.7.2.9ZM15.1,14.8c.1,0,.2,0,.3,0l3.7-2.3c.3-.2.4-.6.2-.9-.2-.3-.6-.4-.9-.2l-3.7,2.3c-.3.2-.4.6-.2.9.1.2.3.3.5.3ZM25.7,18.5v-3.1c0-.3-.3-.6-.6-.6s-.6.3-.6.6v3.1c0,.3.3.6.6.6.3,0,.6-.3.6-.6,0,0,0,0,0,0ZM41.7,26.5v-3.1c0-.3-.3-.6-.6-.6s-.6.3-.6.6v3.1c0,.3.3.6.6.6s.6-.3.6-.6h0ZM19.2,21.6l-3.7-1.8c-.3-.1-.7,0-.8.3,0,0,0,0,0,0-.1.3,0,.7.3.8l3.7,1.8c0,0,.2,0,.3,0,.2,0,.5-.1.6-.4.1-.3,0-.7-.3-.8ZM31.3,22.8c0,0,.2,0,.3,0l3.7-1.8c.3-.1.5-.5.3-.8-.1-.3-.5-.5-.8-.3,0,0,0,0,0,0l-3.7,1.8c-.3.1-.4.5-.3.8.1.2.3.4.6.4ZM35.3,29.2l-3.7-1.8c-.3-.1-.7,0-.8.3,0,0,0,0,0,0-.1.3,0,.7.3.8h0s3.7,1.8,3.7,1.8c0,0,.2,0,.3,0,.3,0,.6-.3.6-.6,0-.2-.1-.5-.4-.6ZM18.6,27.4l-3.7,1.8c-.3.1-.4.5-.3.8.1.2.3.4.6.4,0,0,.2,0,.3,0l3.7-1.8c.3-.1.4-.5.3-.8-.1-.3-.5-.4-.8-.3,0,0,0,0,0,0Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 5.0 KiB

BIN
public/images/docs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

BIN
public/images/dummy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 KiB

BIN
public/images/flow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

BIN
public/images/interface.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

BIN
public/images/market.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

BIN
public/images/report.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

BIN
public/images/structure.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 KiB

BIN
public/images/translate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

View File

@@ -9,12 +9,14 @@ import { Benefits } from '@/components/Benefits'
import { About } from '@/components/About'
import { HomeHero } from '@/components/HomeHero'
import { HomeAbout } from '@/components/HomeAbout'
import { ClickableGallery } from '@/components/ClickableGallery'
export default function Home() {
return (
<>
<HomeHero />
<HomeAbout />
<ClickableGallery />
<Benefits />
<PrimaryFeatures />
<UseCases />

View File

@@ -0,0 +1,142 @@
'use client'
import { useEffect, useMemo, useState } from 'react'
import Image from 'next/image'
import { motion, AnimatePresence } from 'framer-motion'
import { wrap } from 'popmotion'
import { Button } from '@/components/Button'
const galleryItems = [
{ text: 'Navigate and interact with any web interface', image: '/images/interface.png' },
{ text: 'Process documents across all formats', image: '/images/docs.png' },
{ text: 'Execute multi-step workflows autonomously', image: '/images/flow.png' },
{ text: 'Manage calendars, emails, and tasks', image: '/images/calendar.png' },
{ text: 'Perform deep semantic search across all data sources', image: '/images/data.png' },
{ text: 'Identify patterns in complex datasets', image: '/images/datasets.png' },
{ text: 'Provide real-time market intelligence', image: '/images/market.png' },
{ text: 'Generate and debug code in multiple languages', image: '/images/code.png' },
{ text: 'Create consistent branded content', image: '/images/branding.png' },
{ text: 'Translate and localize materials', image: '/images/translate.png' },
{ text: 'Transform and migrate data structures', image: '/images/structure.png' },
]
// 🔧 Carousel Config
const VISIBLE = 4
const CARD_SIZE = 450 // square size on desktop
const GAP = 380 // spacing for larger cards
const ROT_Y = 18
const DEPTH = 260
const SCALE_DROP = 0.12
const AUTOPLAY_MS = 3200
export function ClickableGallery() {
const [active, setActive] = useState(0)
const [hovering, setHovering] = useState(false)
// autoplay
useEffect(() => {
if (hovering) return
const id = setInterval(() => setActive((i) => wrap(0, galleryItems.length, i + 1)), AUTOPLAY_MS)
return () => clearInterval(id)
}, [hovering])
const indices = useMemo(
() => [...Array(VISIBLE * 2 + 1)].map((_, i) => wrap(0, galleryItems.length, active + i - VISIBLE)),
[active]
)
const next = () => setActive((i) => wrap(0, galleryItems.length, i + 1))
const prev = () => setActive((i) => wrap(0, galleryItems.length, i - 1))
return (
<section
className="relative w-full h-[92vh] flex items-center justify-center overflow-hidden bg-background"
onMouseEnter={() => setHovering(true)}
onMouseLeave={() => setHovering(false)}
>
{/* Soft edge fades */}
<div className="pointer-events-none absolute inset-y-0 left-0 w-32 bg-gradient-to-r from-background to-transparent" />
<div className="pointer-events-none absolute inset-y-0 right-0 w-32 bg-gradient-to-l from-background to-transparent" />
<div className="relative w-full max-w-[1800px] h-[900px]" style={{ perspective: '1600px' }}>
<div className="absolute inset-0" style={{ transformStyle: 'preserve-3d' }}>
<AnimatePresence initial={false}>
{indices.map((idx, i) => {
const distance = i - VISIBLE
const item = galleryItems[idx]
const x = distance * GAP
const z = -Math.abs(distance) * DEPTH
const r = distance * ROT_Y
const s = 1 - Math.abs(distance) * SCALE_DROP
const o = distance === 0 ? 1 : 0.85
const zIndex = 100 - Math.abs(distance)
return (
<motion.div
key={`${idx}-${i}`}
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 will-change-transform"
initial={{ opacity: 0 }}
animate={{
transform: `translateX(${x}px) translateZ(${z}px) rotateY(${r}deg) scale(${s})`,
zIndex,
opacity: o,
}}
exit={{ opacity: 0 }}
transition={{ type: 'spring', stiffness: 220, damping: 26 }}
onClick={() => setActive(idx)}
>
{/* Square container, keeps image ratio inside */}
<div
className="relative rounded-2xl overflow-hidden bg-white flex items-center justify-center"
style={{ width: CARD_SIZE, height: CARD_SIZE }}
>
<Image
src={item.image}
alt={item.text}
fill
className="object-contain rounded-2xl"
priority={i === VISIBLE}
/>
</div>
</motion.div>
)
})}
</AnimatePresence>
</div>
{/* Arrows */}
<div className="absolute inset-y-0 left-8 flex items-center z-50">
<button
onClick={prev}
className="bg-white/70 hover:bg-white rounded-full p-3 shadow-lg backdrop-blur-md"
aria-label="Previous"
>
<svg className="size-8" viewBox="0 0 24 24" fill="none"><path d="M15 19L8 12l7-7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>
</button>
</div>
<div className="absolute inset-y-0 right-8 flex items-center z-50">
<button
onClick={next}
className="bg-white/70 hover:bg-white rounded-full p-3 shadow-lg backdrop-blur-md"
aria-label="Next"
>
<svg className="size-8" viewBox="0 0 24 24" fill="none"><path d="M9 5l7 7-7 7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>
</button>
</div>
{/* Foreground pill */}
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-[60]">
<div className="flex items-center gap-6 rounded-3xl bg-white/95 shadow-[0_8px_40px_rgba(0,0,0,0.15)] px-12 py-6 backdrop-blur">
<h2 className="text-2xl lg:text-3xl font-semibold leading-tight text-black max-w-[820px]">
{galleryItems[active].text}
</h2>
<Button href="#" color="cyan" className="text-sm px-4 py-2 lg:text-base">
Start
</Button>
</div>
</div>
</div>
</section>
)
}

View File

@@ -516,7 +516,11 @@ function FeaturesMobile() {
{features.map((feature, featureIndex) => (
<div
key={featureIndex}
ref={(ref) => ref && (slideRefs.current[featureIndex] = ref)}
ref={(ref) => {
if (ref) {
slideRefs.current[featureIndex] = ref
}
}}
className="w-full flex-none snap-center px-4 sm:px-6"
>
<div className="relative transform overflow-hidden rounded-2xl bg-gray-800 px-5 py-6">

BIN
src/images/docs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
src/images/flow.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

BIN
src/images/interface.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB