update home page

This commit is contained in:
2026-06-18 16:32:31 +05:30
parent d9cc83aa82
commit 8e0d704438
57 changed files with 2813 additions and 301 deletions

View File

@@ -1 +0,0 @@
demo.artureanec.com 2/

3
.gitignore vendored
View File

@@ -20,6 +20,9 @@
# production # production
/build /build
# copied reference-site dumps
demo.artureanec.com*/
# misc # misc
.DS_Store .DS_Store
*.pem *.pem

197
PIXEL_PERFECT_WORKFLOW.md Normal file
View File

@@ -0,0 +1,197 @@
# PIXEL PERFECT WORKFLOW
## PRIMARY OBJECTIVE
Recreate the reference website section with pixel-perfect visual accuracy.
The goal is NOT to recreate Elementor, WordPress, PHP, or original HTML structure.
The goal IS to recreate the final visual output exactly as shown in the reference screenshot.
---
## SOURCE PRIORITY
Always follow this order:
1. Reference Screenshot (Highest Priority)
2. Live Website Visual Output
3. User Instructions
4. HTML Inspect Data
5. Existing Codebase
If screenshot and HTML conflict, always follow the screenshot.
---
## CORE RULES
### Rule 1
Never redesign.
Do not improve the design.
Do not modernize the design.
Do not optimize spacing because it looks better.
Do not change typography because it feels cleaner.
Match the reference exactly.
---
### Rule 2
HTML is reference only.
Inspect code exists only for:
* Content identification
* Asset extraction
* Text extraction
* Image extraction
* Icon extraction
* Section identification
Do not recreate Elementor structure.
Do not copy Elementor wrappers.
Do not reproduce unnecessary nested divs.
---
### Rule 3
Build clean Next.js components.
Use:
* Next.js App Router
* TypeScript
* Tailwind CSS
Create reusable components only when visual accuracy is preserved.
---
### Rule 4
Never modify unrelated sections.
Only touch files required for the requested section.
Do not refactor the page.
Do not reorganize folders.
Do not rename components unless required.
---
### Rule 5
Before implementation, perform visual analysis.
Return:
* Container width
* Padding
* Margin
* Gap values
* Border radius
* Typography sizes
* Font weights
* Icon sizes
* Image dimensions
* Layout behavior
* Responsive behavior
---
### Rule 6
For screenshot recreation tasks:
1. Audit first
2. Create implementation plan
3. Wait for approval
4. Implement
Never skip the audit phase.
---
## SCREENSHOT COMPARISON WORKFLOW
When a reference screenshot and implementation screenshot are provided:
Step 1:
Compare both screenshots.
Step 2:
List every mismatch.
Step 3:
Categorize mismatches:
* Layout
* Padding
* Margin
* Radius
* Typography
* Icon sizing
* Image sizing
* Alignment
* Responsive issues
Step 4:
Create a fix plan.
Step 5:
Implement only the listed fixes.
---
## SUCCESS CRITERIA
Implementation is complete only when:
* Side-by-side comparison shows no obvious visual differences.
* Layout matches reference.
* Padding matches reference.
* Typography matches reference.
* Border radius matches reference.
* Image positioning matches reference.
* Mobile behavior matches reference.
---
## FAILURE CONDITIONS
Task is considered failed if:
* Design is improved instead of matched.
* Layout is approximated.
* Unrelated components are modified.
* Existing sections are unnecessarily refactored.
* HTML structure is copied without matching visual output.
* Visible differences remain.
---
## REQUIRED RESPONSE FORMAT
For every task:
1. Audit First
2. List Differences
3. Create Implementation Plan
4. Wait For Approval
5. Implement
6. Re-compare
7. Verify Pixel Accuracy
Never skip these steps.

29
app/about/page.tsx Normal file
View File

@@ -0,0 +1,29 @@
import { Navbar } from "@/components/aiero/Navbar";
import { PageTitleBanner } from "@/components/shared/PageTitleBanner";
import { MarqueeStrip } from "@/components/aiero/MarqueeStrip";
import { ContactFormSection } from "@/components/shared/ContactFormSection";
import { AboutIntroSection } from "@/components/aiero/about/AboutIntroSection";
import { MissionSection } from "@/components/aiero/about/MissionSection";
import { PartnerLogosSection } from "@/components/shared/PartnerLogosSection";
import { TeamSection } from "@/components/aiero/about/TeamSection";
export const metadata = {
title: "About us - Aiero",
};
export default function AboutPage() {
return (
<>
<Navbar />
<main className="min-h-screen bg-aiero-dark">
<PageTitleBanner title="About us" breadcrumbs={[{ label: "About us" }]} />
<AboutIntroSection />
<MarqueeStrip text="/ Neural Networks in shaping the future of technology." />
<MissionSection />
<PartnerLogosSection />
<TeamSection />
<ContactFormSection />
</main>
</>
);
}

21
app/contacts/page.tsx Normal file
View File

@@ -0,0 +1,21 @@
import { Navbar } from "@/components/aiero/Navbar";
import { PageTitleBanner } from "@/components/shared/PageTitleBanner";
import { ContactFormSection } from "@/components/shared/ContactFormSection";
import { MapSection } from "@/components/aiero/contacts/MapSection";
export const metadata = {
title: "Contacts - Aiero",
};
export default function ContactsPage() {
return (
<>
<Navbar />
<main className="min-h-screen bg-aiero-dark">
<PageTitleBanner title="Contacts" breadcrumbs={[{ label: "Contacts" }]} />
<ContactFormSection />
<MapSection />
</main>
</>
);
}

View File

@@ -200,25 +200,6 @@ button {
background-clip: text; background-clip: text;
} }
/* ── Icon decoration (curved corners) ── */
.icon-decoration {
position: relative;
}
.icon-decoration .icon-inner {
position: relative;
z-index: 1;
}
.icon-decoration::before,
.icon-decoration::after {
content: "";
position: absolute;
width: 20px;
height: 20px;
background: transparent;
}
/* ── Marquee animation ── */ /* ── Marquee animation ── */
@keyframes marquee { @keyframes marquee {
0% { 0% {
@@ -229,8 +210,17 @@ button {
} }
} }
.animate-marquee { .marquee-track {
animation: marquee 15s linear infinite; animation: marquee 15s linear infinite;
will-change: transform;
}
.marquee-text {
display: inline-block;
font-size: clamp(50px, 8.4vw, 120px);
font-weight: 400;
letter-spacing: -0.03em;
line-height: 1;
} }
/* ── Counter animation ── */ /* ── Counter animation ── */
@@ -261,6 +251,153 @@ button {
animation: headingReveal 0.8s ease-out forwards; animation: headingReveal 0.8s ease-out forwards;
} }
/* ── Shared reveal and hover motion ── */
@keyframes premiumRevealDown {
from {
opacity: 0;
transform: translateY(-12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes premiumRevealUp {
from {
opacity: 0;
transform: translateY(18px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes heroBgFloat {
0%,
100% {
transform: translate3d(var(--hero-parallax-x, 0), var(--hero-parallax-y, 0), 0) scale(1.02);
}
50% {
transform: translate3d(
calc(var(--hero-parallax-x, 0px) + 2px),
calc(var(--hero-parallax-y, 0px) - 3px),
0
) scale(1.025);
}
}
@keyframes scrollFloat {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-4px);
}
}
@keyframes scrollWidgetEntrance {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.navbar-reveal {
opacity: 0;
animation: premiumRevealDown 0.7s cubic-bezier(0.22, 1, 0.36, 1) forwards;
animation-delay: 80ms;
}
.nav-link-swap {
position: relative;
overflow: hidden;
}
.nav-link-swap > .text-active {
display: inline-block;
transition: opacity 0.3s ease, transform 0.3s ease;
}
.nav-link-swap > span:not(.text-active) {
position: absolute;
left: 21px;
top: 14px;
opacity: 0;
transform: translateY(150%);
transition: opacity 0.3s ease, transform 0.3s ease;
}
.nav-link-swap:hover > .text-active {
opacity: 0;
transform: translateY(-150%);
}
.nav-link-swap:hover > span:not(.text-active) {
opacity: 1;
transform: translateY(0);
}
.dropdown-reveal {
opacity: 0;
transform: translateY(5px);
animation: premiumRevealUp 0.28s cubic-bezier(0.4, 0.28, 0.31, 1.28) forwards;
}
.hero-bg-motion {
animation: heroBgFloat 8s ease-in-out infinite;
transition: transform 0.35s ease-out;
will-change: transform;
}
.hero-reveal {
opacity: 0;
animation: premiumRevealUp 0.78s cubic-bezier(0.22, 1, 0.36, 1) forwards;
animation-delay: 580ms;
}
.scroll-widget {
opacity: 0;
animation: scrollWidgetEntrance 0.7s ease 1.05s forwards;
transform: rotate(-90deg) translateX(-50%) translateY(100%);
transform-origin: left bottom;
}
.scroll-widget .scroll-btn-decoration {
display: inline-block;
animation: scrollFloat 3.4s ease-in-out 1.7s infinite;
}
.reveal-on-view {
opacity: 0;
transform: translateY(22px);
transition:
opacity 0.72s cubic-bezier(0.22, 1, 0.36, 1),
transform 0.72s cubic-bezier(0.22, 1, 0.36, 1);
transition-delay: var(--reveal-delay, 0ms);
}
.reveal-on-view.is-visible {
opacity: 1;
transform: translateY(0);
}
.aiero-card {
transition:
transform 0.32s ease,
box-shadow 0.32s ease,
border-color 0.32s ease;
}
.aiero-card:hover {
transform: translateY(-4px);
box-shadow: 0 22px 55px rgba(31, 31, 31, 0.16), 0 0 0 1px rgba(69, 208, 189, 0.22);
}
/* ── Scroll down button decoration ── */ /* ── Scroll down button decoration ── */
.scroll-btn-decoration { .scroll-btn-decoration {
position: relative; position: relative;
@@ -309,3 +446,22 @@ button {
height: 1px; height: 1px;
background: currentColor; background: currentColor;
} }
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
scroll-behavior: auto !important;
transition-duration: 0.01ms !important;
}
.navbar-reveal,
.hero-reveal,
.scroll-widget,
.reveal-on-view {
opacity: 1;
transform: none;
}
}

View File

@@ -1,5 +1,6 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
import { Manrope, Sora, DM_Sans } from "next/font/google"; import { Manrope, Sora, DM_Sans } from "next/font/google";
import { Footer } from "@/components/shared/Footer";
import "./globals.css"; import "./globals.css";
const manrope = Manrope({ const manrope = Manrope({
@@ -36,7 +37,10 @@ export default function RootLayout({
lang="en" lang="en"
className={`${manrope.variable} ${sora.variable} ${dmSans.variable}`} className={`${manrope.variable} ${sora.variable} ${dmSans.variable}`}
> >
<body suppressHydrationWarning>{children}</body> <body suppressHydrationWarning>
{children}
<Footer />
</body>
</html> </html>
); );
} }

View File

@@ -2,18 +2,20 @@ import { Navbar } from "@/components/aiero/Navbar";
import { HeroSection } from "@/components/aiero/HeroSection"; import { HeroSection } from "@/components/aiero/HeroSection";
import { CardsGrid } from "@/components/aiero/CardsGrid"; import { CardsGrid } from "@/components/aiero/CardsGrid";
import { PossibilitiesSection } from "@/components/aiero/PossibilitiesSection"; import { PossibilitiesSection } from "@/components/aiero/PossibilitiesSection";
import { TinkerSection } from "@/components/aiero/TinkerSection";
import { MarqueeStrip } from "@/components/aiero/MarqueeStrip"; import { MarqueeStrip } from "@/components/aiero/MarqueeStrip";
import { FeaturesSection } from "@/components/aiero/FeaturesSection"; import { FeaturesSection } from "@/components/aiero/FeaturesSection";
export default function Home() { export default function Home() {
return ( return (
<main className="bg-white"> <main className="bg-white">
<div className="absolute inset-x-0 top-0 z-50"> <div className="absolute left-5 right-5 top-0 z-50">
<Navbar /> <Navbar />
</div> </div>
<HeroSection /> <HeroSection />
<CardsGrid /> <CardsGrid />
<PossibilitiesSection /> <PossibilitiesSection />
<TinkerSection />
<MarqueeStrip /> <MarqueeStrip />
<FeaturesSection /> <FeaturesSection />
</main> </main>

32
app/services/page.tsx Normal file
View File

@@ -0,0 +1,32 @@
import { Navbar } from "@/components/aiero/Navbar";
import { PageTitleBanner } from "@/components/shared/PageTitleBanner";
import { MarqueeStrip } from "@/components/aiero/MarqueeStrip";
import { ContactFormSection } from "@/components/shared/ContactFormSection";
import { PartnerLogosSection } from "@/components/shared/PartnerLogosSection";
import { ServiceCardsGrid } from "@/components/aiero/services/ServiceCardsGrid";
import { ServiceFeaturesSection } from "@/components/aiero/services/ServiceFeaturesSection";
import { TestimonialsSection } from "@/components/aiero/services/TestimonialsSection";
import { PricingSection } from "@/components/aiero/services/PricingSection";
export const metadata = {
title: "Services - Aiero",
};
export default function ServicesPage() {
return (
<>
<Navbar />
<main className="min-h-screen bg-aiero-dark">
<PageTitleBanner title="Services Page" breadcrumbs={[{ label: "Services Page" }]} />
<ServiceCardsGrid />
<MarqueeStrip text="/ Neural Networks in shaping the future of technology." />
<ServiceFeaturesSection />
<TestimonialsSection />
<PricingSection />
<PartnerLogosSection />
<ContactFormSection />
</main>
</>
);
}

View File

@@ -1,123 +1,169 @@
import Image from "next/image";
import { CardHeading, IconButton } from "@/components/shared/CardShared"; import { CardHeading, IconButton } from "@/components/shared/CardShared";
import { ChartIcon } from "@/components/shared/icons/ChartIcon"; import { ChartIcon } from "@/components/shared/icons/ChartIcon";
import { Counter } from "@/components/shared/Counter"; import { Counter } from "@/components/shared/Counter";
import { RevealOnView } from "@/components/shared/RevealOnView";
const socialIcons = [
{
src: "/images/aiero/messenger-logo-1.png",
alt: "Messenger",
width: 57,
height: 59,
},
{
src: "/images/aiero/skype-logo.png",
alt: "Skype",
width: 56,
height: 57,
},
{
src: "/images/aiero/telegram-symbol-1.png",
alt: "Telegram",
width: 59,
height: 58,
},
{
src: "/images/aiero/discord-1.png",
alt: "Discord",
width: 54,
height: 54,
},
];
export function CardsGrid() { export function CardsGrid() {
return ( return (
<section className="px-[20px] pb-[20px]"> <section className="px-[20px] pb-[20px]">
<div className="grid grid-cols-1 gap-[20px] md:grid-cols-2 xl:grid-cols-4"> <div className="grid grid-cols-1 gap-[20px] md:grid-cols-2 xl:grid-cols-[1fr_1fr_0.73fr]">
{/* Card 1 */} {/* Card 1 */}
<div className="relative flex flex-col justify-between overflow-hidden rounded-[25px] bg-[#343F78] p-[40px_35px_45px_35px] lg:p-[55px_45px_60px_45px] xl:col-span-1"> <RevealOnView delay={0}>
<div <div className="aiero-card group relative flex h-full flex-col justify-between overflow-hidden rounded-[25px] bg-aiero-card-purple p-[40px_35px_45px_35px] lg:p-[50px_45px_50px_45px]">
className="absolute inset-0 bg-[url('/images/aiero/assistant-artificial-intelligence-min.png')] bg-right-top bg-no-repeat opacity-100 transition-all duration-300 hover:scale-105" <Image
src="/images/aiero/assistant-artificial-intelligence-min.png"
alt=""
className="pointer-events-none absolute right-[-10px] top-[-10px] h-auto w-[150px] object-contain object-right-top transition-transform duration-500 group-hover:scale-105 lg:w-[190px]"
width={220}
height={274}
/> />
<div className="relative z-10 flex gap-[6px]"> <div className="relative z-10 flex gap-[6px]">
<span className="rounded-[15px] border border-white px-[20px] py-[5px] text-[12px] text-white transition-colors hover:border-[#45D0BD] hover:text-[#45D0BD]"> <span className="rounded-[15px] border border-white px-[20px] py-[5px] text-[12px] text-white transition-colors hover:border-aiero-teal hover:text-aiero-teal">
Solutions Solutions
</span> </span>
<span className="rounded-[15px] border border-white px-[20px] py-[5px] text-[12px] text-white transition-colors hover:border-[#45D0BD] hover:text-[#45D0BD]"> <span className="rounded-[15px] border border-white px-[20px] py-[5px] text-[12px] text-white transition-colors hover:border-aiero-teal hover:text-aiero-teal">
Plugins Plugins
</span> </span>
</div> </div>
<div className="relative z-10 mt-[60px] lg:mt-[100px]"> <div className="relative z-10 mt-[66px] max-w-[460px] lg:mt-[110px]">
<CardHeading <CardHeading
title="Enhance operational efficiency" title="Transform customer support with intelligent AI chatbots for seamless and effortless service"
titleClassName="text-white" titleClassName="text-white"
wrapperClassName="mb-0"
/> />
<div className="mt-[44px] flex -space-x-[15px]"> <div className="mt-[36px] flex items-center gap-[20px]">
<div className="flex h-[52px] w-[52px] items-center justify-center rounded-full bg-[#E8F3FF] shadow-sm"> {socialIcons.map((icon) => (
<svg className="h-[24px] w-[24px]" viewBox="0 0 24 24" fill="#0084FF"><path d="M12 2C6.477 2 2 6.145 2 11.258C2 14.156 3.52 16.735 5.868 18.361V22L9.208 20.151C10.096 20.395 11.033 20.516 12 20.516C17.523 20.516 22 16.371 22 11.258C22 6.145 17.523 2 12 2Z"/></svg> <Image
</div> key={icon.alt}
<div className="flex h-[52px] w-[52px] items-center justify-center rounded-full bg-[#E5F5FF] shadow-sm"> src={icon.src}
<svg className="h-[24px] w-[24px]" viewBox="0 0 24 24" fill="#00AFF0"><path d="M11.996 22C17.519 22 22 17.523 22 12C22 6.477 17.519 2 11.996 2C6.473 2 2 6.477 2 12C2 17.523 6.473 22 11.996 22Z"/></svg> alt={icon.alt}
</div> width={icon.width}
<div className="flex h-[52px] w-[52px] items-center justify-center rounded-full bg-[#E5FAFF] shadow-sm"> height={icon.height}
<svg className="h-[24px] w-[24px]" viewBox="0 0 24 24" fill="#229ED9"><path d="M12 2C6.477 2 2 6.477 2 12C2 17.523 6.477 22 12 22C17.523 22 22 17.523 22 12C2 6.477 17.523 2 12 2Z"/></svg> className="h-auto w-auto"
</div> />
<div className="flex h-[52px] w-[52px] items-center justify-center rounded-full bg-[#EAE8FF] shadow-sm"> ))}
<svg className="h-[24px] w-[24px]" viewBox="0 0 24 24" fill="#5865F2"><path d="M12 2C6.477 2 2 6.477 2 12C2 17.523 6.477 22 12 22C17.523 22 22 17.523 22 12C2 6.477 17.523 2 12 2Z"/></svg>
</div>
</div> </div>
</div> </div>
<IconButton /> <IconButton />
</div> </div>
</RevealOnView>
{/* Card 2 */} {/* Card 2 */}
<div className="relative flex flex-col justify-between overflow-hidden rounded-[25px] bg-[#56619E] p-[40px_35px_45px_35px] lg:p-[45px_45px_50px_45px] xl:col-span-1"> <RevealOnView delay={110}>
<div <div className="aiero-card group relative flex h-full flex-col justify-between overflow-hidden rounded-[25px] bg-aiero-card-purple-2 p-[40px_35px_45px_35px] lg:p-[50px_45px_50px_45px]">
className="absolute inset-0 bg-[url('/images/aiero/c0eb2845-min.png')] bg-bottom bg-no-repeat transition-all duration-300 hover:scale-105" <div className="absolute inset-0 bg-aiero-card-purple-2" />
/> <div className="absolute inset-0 bg-[url('/images/aiero/c0eb2845-min.png')] bg-[length:60%] bg-right-bottom bg-no-repeat transition-transform duration-500 group-hover:scale-105" />
<div className="absolute inset-0 bg-gradient-to-b from-[#3F497F00] to-[#333D74] from-[75%] to-[100%]" /> <div className="absolute inset-0 bg-gradient-to-b from-transparent via-transparent to-[#454f88]/16" />
<div className="relative z-10 mb-[50px]"> <div className="relative z-10 mb-[54px] max-w-[515px]">
<div className="mb-[24px] inline-flex h-[38px] w-[38px] items-center justify-center"> <div className="mb-[24px] inline-flex h-[38px] w-[38px] items-center justify-center">
<ChartIcon className="h-full w-full text-white" /> <ChartIcon className="h-full w-full text-white" />
</div> </div>
<CardHeading <CardHeading
title="Tailor algorithms to adapt and optimize processes" title="All-in-One AI solutions dashboard for smarter business insights & innovation."
titleClassName="text-white" titleClassName="text-white"
wrapperClassName="mb-[18px]"
/> />
<p className="text-[16px] text-white"> <p className="max-w-[448px] text-[16px] leading-[1.85] text-white">
Cobra opaleye gray reef shark bluntnose minnow. Explore our comprehensive AI solutions dashboard designed to
provide actionable business insights and drive innovation
</p> </p>
</div> </div>
<IconButton /> <IconButton />
</div> </div>
</RevealOnView>
{/* Card 3 (spans 2 columns) */} {/* Card 3 (spans 2 columns) */}
<div className="flex flex-col gap-[20px] md:col-span-2 xl:col-span-2"> <RevealOnView className="md:col-span-2 xl:col-span-1" delay={220}>
<div className="flex h-full flex-col gap-[20px]">
{/* Card 3 - Top half */} {/* Card 3 - Top half */}
<div className="relative flex flex-col justify-center overflow-hidden rounded-[25px] bg-[#AC8DE0] p-[40px] lg:p-[45px_50px]"> <div className="aiero-card relative flex min-h-[176px] flex-col justify-center overflow-hidden rounded-[25px] bg-aiero-card-lavender p-[40px] lg:p-[45px_50px]">
<a href="#" className="absolute inset-0 z-20" aria-label="Happy clients" /> <a href="#" className="absolute inset-0 z-20" aria-label="Happy clients" />
<div className="relative z-10 flex flex-col md:flex-row md:items-center md:justify-between"> <div className="relative z-10 flex flex-col items-start">
<div> <div>
<Counter <Counter
target={500} target={500}
suffix="K+" suffix="K+"
numberClassName="text-[80px] font-bold leading-none font-[var(--font-manrope)] gradient-text-counter" numberClassName="font-[var(--font-manrope)] text-[82px] font-extrabold leading-none tracking-[-0.04em] text-transparent"
style={{ backgroundImage: "linear-gradient(0deg, rgba(255,255,255,0) 15%, #FFFFFF 100%)" }} style={{
WebkitTextStroke: "1px rgba(255,255,255,0.16)",
backgroundImage:
"linear-gradient(180deg, rgba(255,255,255,0.44) 0%, rgba(255,255,255,0.06) 90%)",
}}
/> />
</div> </div>
<div className="mt-4 md:mt-0"> <div className="mt-[4px]">
<h4 className="font-[var(--font-manrope)] text-[16px] font-medium leading-[20px] text-[#F8E1E1]"> <h4 className="font-[var(--font-manrope)] text-[16px] font-medium leading-[20px] text-white">
Happy Happy clients
<br />
clients
</h4> </h4>
</div> </div>
</div> </div>
</div> </div>
{/* Card 3 - Bottom half */} {/* Card 3 - Bottom half */}
<div className="relative flex flex-col justify-between overflow-hidden rounded-[25px] bg-[#282828] p-[40px_35px_45px_35px] lg:p-[50px_45px_45px_45px]"> <div className="aiero-card group relative flex flex-col justify-between overflow-hidden rounded-[25px] bg-aiero-card-dark p-[40px_35px_45px_35px] lg:p-[50px_45px_45px_45px]">
<div <div
className="absolute inset-0 bg-[url('/images/aiero/Layer_2-min.jpg')] bg-cover bg-center transition-all duration-300 hover:scale-105" className="absolute inset-0 bg-[url('/images/aiero/Layer_2-min.jpg')] bg-cover bg-center transition-all duration-500 group-hover:scale-105"
/> />
<div className="relative z-10 mb-[26px]"> <div className="relative z-10 mb-[26px]">
<CardHeading <CardHeading
title="Unlock your full potential today with the power of Aiero AI" title="Unlock your full potential with effortless OpenAI integration solutions"
titleClassName="text-white max-w-[80%]" titleClassName="text-white max-w-[80%]"
wrapperClassName="mb-0"
/> />
</div> </div>
<div className="relative z-10"> <div className="relative z-10">
<svg width="136" viewBox="0 0 100 28" fill="none" xmlns="http://www.w3.org/2000/svg"> <Image
<path d="M26.4 13.9C26.4 11.2 25.4 9 23.5 7.4C21.6 5.8 19 5 15.7 5C12.4 5 9.8 5.8 7.9 7.4C6 9 5 11.2 5 13.9C5 16.6 6 18.8 7.9 20.4C9.8 22 12.4 22.8 15.7 22.8C19 22.8 21.6 22 23.5 20.4C25.4 18.8 26.4 16.6 26.4 13.9ZM30.7 13.9C30.7 18 29.3 21.2 26.5 23.7C23.7 26.2 19.9 27.5 15.1 27.5C10.3 27.5 6.5 26.2 3.7 23.7C0.9 21.2 -0.5 18 -0.5 13.9C-0.5 9.8 0.9 6.6 3.7 4.1C6.5 1.6 10.3 0.3 15.1 0.3C19.9 0.3 23.7 1.6 26.5 4.1C29.3 6.6 30.7 9.8 30.7 13.9ZM37.7 27V0.8H42V4.5C43.5 2 46.1 0.8 49.8 0.8C52.9 0.8 55.4 1.8 57.3 3.8C59.2 5.8 60.1 8.5 60.1 11.9V27H55.8V12.4C55.8 9.9 55.1 8.1 53.7 6.9C52.3 5.7 50.4 5.1 48 5.1C45.3 5.1 43.1 5.9 41.4 7.5C39.7 9.1 38.8 11.4 38.8 14.4V27H37.7ZM71.1 27.5C67.5 27.5 64.6 26.4 62.4 24.2C60.2 22 59.1 18.9 59.1 14.9V14.2C59.1 10.1 60.3 6.9 62.7 4.5C65.1 2.1 68.3 0.9 72.3 0.9C75.8 0.9 78.6 1.9 80.7 3.9C82.8 5.9 83.8 8.8 83.8 12.6V15.7H63.4C63.6 18.4 64.5 20.4 66.1 21.6C67.7 22.8 69.8 23.4 72.4 23.4C74.6 23.4 76.5 23 78.1 22.2C79.7 21.4 81.1 20.2 82.2 18.6L84.8 21.8C83.2 23.6 81.2 25 78.8 26C76.4 27 73.8 27.5 71.1 27.5ZM80.6 10.6C80.6 8.3 79.9 6.6 78.5 5.5C77.1 4.4 75 3.8 72.2 3.8C69.3 3.8 67 4.6 65.3 6.2C63.6 7.8 62.7 10 62.7 12.8H80.6V10.6ZM90.2 0H94.4V27H90.2V0Z" fill="white"/> src="/images/aiero/openai-logo-1.png"
</svg> alt="OpenAI"
width={272}
height={71}
className="h-auto w-[138px] lg:w-[152px]"
/>
</div> </div>
</div> </div>
</div> </div>
</RevealOnView>
</div> </div>
</section> </section>

View File

@@ -7,7 +7,7 @@ export function FeaturesSection() {
<div className="mx-auto max-w-[1260px]"> <div className="mx-auto max-w-[1260px]">
{/* Top text and separator */} {/* Top text and separator */}
<div className="mb-[70px] pr-[10%]"> <div className="mb-[70px] pr-[10%]">
<div className="mb-[20px] h-px w-[130px] bg-[#3F3F3F]" /> <div className="mb-[20px] h-px w-[130px] bg-aiero-card-border" />
<h2 <h2
className="max-w-[700px] tracking-[-0.03em] text-white" className="max-w-[700px] tracking-[-0.03em] text-white"
style={{ style={{
@@ -25,7 +25,7 @@ export function FeaturesSection() {
<div className="grid grid-cols-1 gap-[20px] lg:grid-cols-2"> <div className="grid grid-cols-1 gap-[20px] lg:grid-cols-2">
{/* Card 1 - Left */} {/* Card 1 - Left */}
<div className="relative flex flex-col justify-between overflow-hidden rounded-[25px] border border-[#3F3F3F] bg-[#282828] p-[40px_35px_45px_35px] lg:p-[22%_9%_20%_9%]"> <div className="relative flex flex-col justify-between overflow-hidden rounded-[25px] border border-aiero-card-border bg-aiero-card-dark p-[40px_35px_45px_35px] lg:p-[22%_9%_20%_9%]">
<div <div
className="absolute inset-0 bg-[url('/images/aiero/home-9-img.png')] bg-bottom bg-no-repeat transition-all duration-300 hover:scale-105" className="absolute inset-0 bg-[url('/images/aiero/home-9-img.png')] bg-bottom bg-no-repeat transition-all duration-300 hover:scale-105"
style={{ backgroundSize: "100% auto" }} style={{ backgroundSize: "100% auto" }}
@@ -39,16 +39,16 @@ export function FeaturesSection() {
/> />
<ul className="mt-[20px] flex flex-col gap-3"> <ul className="mt-[20px] flex flex-col gap-3">
<li className="flex items-center gap-3 text-[#87899B]"> <li className="flex items-center gap-3 text-aiero-text-muted">
<span className="flex h-1 w-1 rounded-full bg-[#87899B]" /> <span className="flex h-1 w-1 rounded-full bg-aiero-text-muted" />
Advanced analytics processing Advanced analytics processing
</li> </li>
<li className="flex items-center gap-3 text-[#87899B]"> <li className="flex items-center gap-3 text-aiero-text-muted">
<span className="flex h-1 w-1 rounded-full bg-[#87899B]" /> <span className="flex h-1 w-1 rounded-full bg-aiero-text-muted" />
Real-time data synchronization Real-time data synchronization
</li> </li>
<li className="flex items-center gap-3 text-[#87899B]"> <li className="flex items-center gap-3 text-aiero-text-muted">
<span className="flex h-1 w-1 rounded-full bg-[#87899B]" /> <span className="flex h-1 w-1 rounded-full bg-aiero-text-muted" />
Secure API endpoints Secure API endpoints
</li> </li>
</ul> </ul>
@@ -58,7 +58,7 @@ export function FeaturesSection() {
</div> </div>
{/* Card 2 - Right */} {/* Card 2 - Right */}
<div className="relative flex flex-col justify-between overflow-hidden rounded-[25px] border border-[#3F3F3F] bg-[#282828] p-[40px_35px_45px_35px] lg:p-[10%_9%_11%_9%]"> <div className="relative flex flex-col justify-between overflow-hidden rounded-[25px] border border-aiero-card-border bg-aiero-card-dark p-[40px_35px_45px_35px] lg:p-[10%_9%_11%_9%]">
<div <div
className="absolute inset-0 bg-[url('/images/aiero/Dots.png')] bg-[length:auto] bg-[50%_20px] bg-no-repeat opacity-20" className="absolute inset-0 bg-[url('/images/aiero/Dots.png')] bg-[length:auto] bg-[50%_20px] bg-no-repeat opacity-20"
/> />
@@ -74,7 +74,7 @@ export function FeaturesSection() {
title="Data privacy and security with robust measures" title="Data privacy and security with robust measures"
titleClassName="text-white" titleClassName="text-white"
/> />
<p className="text-[16px] text-[#87899B]"> <p className="text-[16px] text-aiero-text-muted">
Cobra opaleye gray reef shark bluntnose minnow. Triggerfish bango guppy opah sunfish bluntnose knifefish upside-down catfish. Cobra opaleye gray reef shark bluntnose minnow. Triggerfish bango guppy opah sunfish bluntnose knifefish upside-down catfish.
</p> </p>
</div> </div>
@@ -83,7 +83,7 @@ export function FeaturesSection() {
</div> </div>
{/* Card 3 - Bottom Full Width */} {/* Card 3 - Bottom Full Width */}
<div className="relative col-span-1 overflow-hidden rounded-[25px] border border-[#3F3F3F] bg-[#282828] lg:col-span-2"> <div className="relative col-span-1 overflow-hidden rounded-[25px] border border-aiero-card-border bg-aiero-card-dark lg:col-span-2">
<div <div
className="absolute inset-0 bg-[url('/images/aiero/3d-woman-shape-glowing-with-bright-holographic-colors-1-min.png')] bg-right-bottom bg-no-repeat transition-all duration-300 hover:scale-105" className="absolute inset-0 bg-[url('/images/aiero/3d-woman-shape-glowing-with-bright-holographic-colors-1-min.png')] bg-right-bottom bg-no-repeat transition-all duration-300 hover:scale-105"
style={{ backgroundSize: "83% auto" }} style={{ backgroundSize: "83% auto" }}
@@ -95,24 +95,24 @@ export function FeaturesSection() {
subtitle="Technology" subtitle="Technology"
title="Tailored solutions specifically to your needs" title="Tailored solutions specifically to your needs"
titleClassName="text-white" titleClassName="text-white"
subtitleClassName="text-[#45D0BD]" subtitleClassName="text-aiero-teal"
/> />
</div> </div>
<div className="flex flex-col gap-[40px] sm:flex-row sm:gap-[60px] lg:pl-[15%]"> <div className="flex flex-col gap-[40px] sm:flex-row sm:gap-[60px] lg:pl-[15%]">
<Counter <Counter
target={99} target={98}
suffix="%" suffix="%"
numberClassName="text-[60px] font-bold leading-none font-[var(--font-manrope)] text-white" numberClassName="text-[60px] font-bold leading-none font-[var(--font-manrope)] text-white"
title="Accuracy rate" title="Accuracy rate"
titleClassName="font-[var(--font-sora)] text-[11px] font-semibold tracking-[0.18em] uppercase text-[#87899B] mt-2" titleClassName="font-[var(--font-sora)] text-[11px] font-semibold tracking-[0.18em] uppercase text-aiero-text-muted mt-2"
/> />
<Counter <Counter
target={24} target={24}
suffix="/7" suffix="/7"
numberClassName="text-[60px] font-bold leading-none font-[var(--font-manrope)] text-white" numberClassName="text-[60px] font-bold leading-none font-[var(--font-manrope)] text-white"
title="Customer support" title="Customer support"
titleClassName="font-[var(--font-sora)] text-[11px] font-semibold tracking-[0.18em] uppercase text-[#87899B] mt-2" titleClassName="font-[var(--font-sora)] text-[11px] font-semibold tracking-[0.18em] uppercase text-aiero-text-muted mt-2"
/> />
</div> </div>
</div> </div>

View File

@@ -0,0 +1,214 @@
"use client";
import { useEffect, useRef } from "react";
import { Mesh, Plane, Program, Renderer, Texture } from "ogl";
const vertex = `
attribute vec2 uv;
attribute vec2 position;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4(position, 0.0, 1.0);
}
`;
const fragment = `
precision highp float;
uniform sampler2D tMap;
uniform vec2 uResolution;
uniform vec2 uImageResolution;
uniform vec2 uPointer;
uniform vec2 uVelocity;
uniform float uStrength;
varying vec2 vUv;
vec2 coverUv(vec2 uv, vec2 screen, vec2 image) {
float screenRatio = screen.x / screen.y;
float imageRatio = image.x / image.y;
vec2 scale = vec2(1.0);
if (screenRatio > imageRatio) {
scale.y = imageRatio / screenRatio;
} else {
scale.x = screenRatio / imageRatio;
}
return (uv - 0.5) * scale + 0.5;
}
void main() {
vec2 uv = coverUv(vUv, uResolution, uImageResolution);
vec2 pointerDelta = uv - uPointer;
float distanceFromPointer = length(pointerDelta);
float cursorMask = smoothstep(0.36, 0.0, distanceFromPointer);
float innerMask = smoothstep(0.16, 0.0, distanceFromPointer);
vec2 pull = normalize(pointerDelta + 0.0001) * innerMask * 0.0035;
vec2 distortion = ((uVelocity * 0.075) - pull) * cursorMask * uStrength;
uv += distortion;
float red = texture2D(tMap, uv + distortion * 0.12).r;
float green = texture2D(tMap, uv).g;
float blue = texture2D(tMap, uv - distortion * 0.1).b;
gl_FragColor = vec4(red, green, blue, 1.0);
}
`;
interface HeroImageSceneProps {
imageSrc: string;
}
export function HeroImageScene({ imageSrc }: HeroImageSceneProps) {
const rootRef = useRef<HTMLDivElement>(null);
const pointerRef = useRef({ x: 0.5, y: 0.5 });
const velocityRef = useRef({ x: 0, y: 0 });
const strengthRef = useRef(0);
const lastMoveTimeRef = useRef(0);
useEffect(() => {
const root = rootRef.current;
if (!root) return;
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
if (reduceMotion.matches) return;
const renderer = new Renderer({
alpha: true,
antialias: true,
dpr: Math.min(window.devicePixelRatio, 2),
});
const gl = renderer.gl;
root.appendChild(gl.canvas);
gl.canvas.className = "absolute inset-0 h-full w-full";
gl.clearColor(0, 0, 0, 0);
const texture = new Texture(gl, {
generateMipmaps: false,
minFilter: gl.LINEAR,
magFilter: gl.LINEAR,
});
const image = new Image();
image.src = imageSrc;
image.onload = () => {
texture.image = image;
texture.needsUpdate = true;
};
const program = new Program(gl, {
vertex,
fragment,
uniforms: {
tMap: { value: texture },
uResolution: { value: [1, 1] },
uImageResolution: { value: [1883, 855] },
uPointer: { value: [0.5, 0.5] },
uVelocity: { value: [0, 0] },
uStrength: { value: 0 },
},
transparent: true,
});
const mesh = new Mesh(gl, {
geometry: new Plane(gl, { width: 2, height: 2 }),
program,
});
let animationFrame = 0;
let width = 1;
let height = 1;
const resize = () => {
const rect = root.getBoundingClientRect();
width = Math.max(1, rect.width);
height = Math.max(1, rect.height);
renderer.setSize(width, height);
program.uniforms.uResolution.value = [width, height];
};
const onPointerMove = (event: PointerEvent) => {
const rect = root.getBoundingClientRect();
const isInside =
event.clientX >= rect.left &&
event.clientX <= rect.right &&
event.clientY >= rect.top &&
event.clientY <= rect.bottom;
if (!isInside) {
velocityRef.current = { x: 0, y: 0 };
return;
}
const nextPointer = {
x: (event.clientX - rect.left) / rect.width,
y: 1 - (event.clientY - rect.top) / rect.height,
};
const now = performance.now();
const elapsed = Math.max(16, now - lastMoveTimeRef.current);
lastMoveTimeRef.current = now;
velocityRef.current = {
x: ((nextPointer.x - pointerRef.current.x) / elapsed) * 16.67,
y: ((nextPointer.y - pointerRef.current.y) / elapsed) * 16.67,
};
pointerRef.current = nextPointer;
strengthRef.current = Math.min(1, strengthRef.current + 0.72);
};
const onPointerLeave = () => {
velocityRef.current = { x: 0, y: 0 };
};
const render = () => {
strengthRef.current *= 0.86;
velocityRef.current = {
x: velocityRef.current.x * 0.74,
y: velocityRef.current.y * 0.74,
};
program.uniforms.uPointer.value = [
pointerRef.current.x,
pointerRef.current.y,
];
program.uniforms.uVelocity.value = [
velocityRef.current.x,
velocityRef.current.y,
];
program.uniforms.uStrength.value = strengthRef.current;
renderer.render({ scene: mesh });
animationFrame = requestAnimationFrame(render);
};
const observer = new ResizeObserver(resize);
observer.observe(root);
window.addEventListener("pointermove", onPointerMove);
root.addEventListener("pointerleave", onPointerLeave);
resize();
animationFrame = requestAnimationFrame(render);
return () => {
cancelAnimationFrame(animationFrame);
observer.disconnect();
window.removeEventListener("pointermove", onPointerMove);
root.removeEventListener("pointerleave", onPointerLeave);
gl.canvas.remove();
};
}, [imageSrc]);
return (
<div
ref={rootRef}
aria-hidden="true"
className="hero-ogl-scene absolute inset-[-18px]"
>
<div
className="absolute inset-0 bg-cover bg-center"
style={{ backgroundImage: `url(${imageSrc})` }}
/>
</div>
);
}

View File

@@ -1,49 +1,35 @@
import { HeroImageScene } from "@/components/aiero/HeroImageScene";
import { ScrollDown } from "@/components/shared/ScrollDown";
export function HeroSection() { export function HeroSection() {
return ( return (
<section className="relative px-5 pt-5"> <section className="relative px-5 py-5">
{/* Scroll Down button — vertical, left side */} {/* Scroll Down button — vertical, left side */}
<div <div className="scroll-widget absolute left-0 top-[40%] z-20 hidden xl:block">
className="absolute left-0 top-1/2 z-20 hidden xl:block" <ScrollDown />
style={{
transform: "rotate(-90deg) translateX(-50%) translateY(100%)",
transformOrigin: "left bottom",
}}
>
<span className="scroll-btn-decoration">
<a
href="#scroll-down"
className="inline-flex items-center gap-2 rounded-b-[25px] bg-white px-[56px] py-[16px] text-[13px] font-semibold text-[#0b0e17] no-underline transition-colors hover:text-[#45d0bd]"
style={{ fontFamily: "var(--font-sora)" }}
>
Scroll down
<svg width="10" height="10" viewBox="0 0 12 12" fill="none">
<path d="M1 11L11 1M11 1H3M11 1V9" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</a>
</span>
</div> </div>
{/* Hero container with background */} {/* Hero container with background */}
<div <div
className="relative overflow-hidden rounded-[25px] bg-[#1f1f1f] bg-cover bg-center" className="relative overflow-hidden rounded-[25px] bg-aiero-dark"
style={{ style={{
backgroundImage: "url(/images/aiero/home-9-top-bg-min.jpg)", minHeight: "min(858px, calc(100vw * 0.447))",
padding: "13.5% 0 8.333% 0", padding: "14.3% 0 8.1% 0",
}} }}
> >
<HeroImageScene imageSrc="/images/aiero/home-9-top-bg-min.jpg" />
{/* Hero content */} {/* Hero content */}
<div className="relative z-10 mx-auto max-w-[1140px] px-[15px]" style={{ marginLeft: "-35px", paddingLeft: "calc(50% - 570px + 15px)" }}> <div className="relative z-10 w-full px-[12.7vw]">
<div className="flex flex-col items-start"> <div className="flex flex-col items-start">
{/* Heading */} {/* Heading */}
<h1 <h1
className="mb-5 max-w-[1100px] text-left tracking-[-0.03em] text-white" className="hero-reveal mb-[24px] max-w-[1280px] text-left tracking-[-0.03em] text-white"
style={{ style={{
fontFamily: "var(--font-manrope)", fontFamily: "var(--font-manrope)",
fontSize: "clamp(32px, 5.2vw, 80px)", fontSize: "clamp(42px, 4.43vw, 85px)",
fontWeight: 700, fontWeight: 400,
lineHeight: 1.1, lineHeight: 1.06,
}} }}
> >
Revolutionizing businesses with cutting-edge AI solutions and Revolutionizing businesses with cutting-edge AI solutions and
@@ -51,8 +37,8 @@ export function HeroSection() {
</h1> </h1>
{/* Subtitle */} {/* Subtitle */}
<div style={{ marginRight: "53%" }}> <div className="hero-reveal max-w-[660px]" style={{ animationDelay: "760ms" }}>
<p className="text-[16px] leading-[1.6] text-white"> <p className="text-[16px] font-semibold leading-[1.9] text-white">
Mummichog paradise fish! Triggerfish bango guppy opah sunfish Mummichog paradise fish! Triggerfish bango guppy opah sunfish
bluntnose knifefish upside-down catfish cobia spookfish convict bluntnose knifefish upside-down catfish cobia spookfish convict
cichlid. cichlid.
@@ -60,12 +46,12 @@ export function HeroSection() {
</div> </div>
{/* CTA Button */} {/* CTA Button */}
<div className="mt-10"> <div className="hero-reveal mt-[42px]" style={{ animationDelay: "940ms" }}>
<a <a
href="#" href="#"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="aiero-button aiero-button-solid inline-flex items-center gap-2 rounded-[25px] border border-[#EF6464] bg-[#EF6464] px-[30px] py-[14px] text-[16px] text-white transition-all hover:border-[#F57E7E] hover:bg-[#F57E7E]" className="aiero-button aiero-button-solid inline-flex items-center gap-2 rounded-[25px] border border-aiero-red bg-aiero-red px-[30px] py-[14px] text-[16px] text-white transition-all hover:-translate-y-0.5 hover:border-aiero-red-hover hover:bg-aiero-red-hover hover:shadow-[0_15px_30px_rgba(239,100,100,0.28)]"
style={{ minWidth: "216px", fontFamily: "var(--font-sora)" }} style={{ minWidth: "216px", fontFamily: "var(--font-sora)" }}
> >
Discover Discover

View File

@@ -1,29 +1,29 @@
export function MarqueeStrip() { interface MarqueeStripProps {
text?: string;
className?: string;
}
export function MarqueeStrip({
text = "Artificial Intelligence",
className = ""
}: MarqueeStripProps) {
const marqueeItems = Array.from({ length: 6 });
return ( return (
<div className="relative z-10 mx-[-5px] mb-[-90px] mt-[20px] overflow-hidden bg-gradient-to-r from-[#45D0BD] to-[#44B6E9] py-[42px]" style={{ transform: "rotate(-2.07deg)" }}> <div className={`relative z-10 mx-[-5px] mb-[-90px] mt-[20px] overflow-hidden bg-gradient-to-r from-aiero-teal to-aiero-blue py-[42px] ${className}`} style={{ transform: "rotate(-2.07deg)" }}>
<div className="flex w-[200%] whitespace-nowrap"> <div className="marquee-track flex w-max whitespace-nowrap">
{/* Marquee track 1 */} {[0, 1].map((track) => (
<div className="animate-marquee flex gap-8"> <div key={track} className="flex shrink-0 items-center">
{[...Array(6)].map((_, i) => ( {marqueeItems.map((_, i) => (
<div key={i} className="flex items-center gap-8"> <div key={`${track}-${i}`} className="flex items-center gap-8 pr-8">
<span className="text-[60px] font-bold leading-none text-white" style={{ fontFamily: "var(--font-sora)" }}> <span className="marquee-text text-white" style={{ fontFamily: "var(--font-sora)" }}>
Artificial Intelligence {text}
</span> </span>
<span className="flex h-3 w-3 rounded-full bg-white opacity-50" /> <span className="flex h-3 w-3 rounded-full bg-white opacity-50" />
</div> </div>
))} ))}
</div> </div>
{/* Marquee track 2 (seamless loop) */} ))}
<div className="animate-marquee flex gap-8">
{[...Array(6)].map((_, i) => (
<div key={`dup-${i}`} className="flex items-center gap-8">
<span className="text-[60px] font-bold leading-none text-white" style={{ fontFamily: "var(--font-sora)" }}>
Artificial Intelligence
</span>
<span className="flex h-3 w-3 rounded-full bg-white opacity-50" />
</div>
))}
</div>
</div> </div>
</div> </div>
); );

View File

@@ -1,58 +1,92 @@
"use client"; "use client";
import { useState } from "react"; import { useEffect, useState } from "react";
import Image from "next/image"; import Image from "next/image";
import { navigationData } from "@/data/navigation"; import { navigationData } from "@/data/navigation";
import { SearchIcon } from "@/components/shared/icons/SearchIcon"; import { SearchIcon } from "@/components/shared/icons/SearchIcon";
export function Navbar() { export function Navbar() {
const [isSticky, setIsSticky] = useState(false);
const [openDropdown, setOpenDropdown] = useState<string | null>(null); const [openDropdown, setOpenDropdown] = useState<string | null>(null);
useEffect(() => {
const onScroll = () => setIsSticky(window.scrollY > 120);
onScroll();
window.addEventListener("scroll", onScroll, { passive: true });
return () => window.removeEventListener("scroll", onScroll);
}, []);
return ( return (
<header className="relative z-30 mx-auto flex h-[76px] max-w-[2520px] items-center justify-between px-2"> <header
{/* Logo */} className={`aiero-navbar z-30 mx-auto grid h-[100px] max-w-[2520px] grid-cols-[280px_1fr_360px] items-center px-[34px] transition-[background-color,border-radius,box-shadow,transform] duration-500 ${
<a href="#" className="flex items-center"> isSticky
<Image ? "fixed left-5 right-5 top-0 rounded-b-[25px] bg-[#111111] shadow-[0_12px_35px_rgba(0,0,0,0.18)]"
src="/images/aiero/logo-dark.png" : "relative bg-transparent"
alt="Aiero" }`}
width={109.5} >
height={19.5} <div className="flex items-center gap-[64px]">
className="h-auto w-auto" <button
priority className="navbar-reveal grid h-6 w-6 grid-cols-2 gap-[5px] text-white transition-colors hover:text-aiero-teal"
/> aria-label="Open menu"
</a> >
<span className="h-[7px] w-[7px] rounded-[2px] border-2 border-current" />
<span className="h-[7px] w-[7px] rounded-[2px] border-2 border-current" />
<span className="h-[7px] w-[7px] rounded-[2px] border-2 border-current" />
<span className="h-[7px] w-[7px] rounded-[2px] border-2 border-current" />
</button>
{/* Logo */}
<a href="#" className="navbar-reveal flex items-center" style={{ animationDelay: "120ms" }}>
<Image
src="/images/aiero/logo-dark.png"
alt="Aiero"
width={109.5}
height={19.5}
className="h-auto w-auto"
priority
/>
</a>
</div>
{/* Navigation */} {/* Navigation */}
<nav className="hidden items-center gap-0 lg:flex" aria-label="Primary navigation"> <nav className="hidden items-center justify-center gap-[11px] lg:flex" aria-label="Primary navigation">
{navigationData.map((item) => ( {navigationData.map((item, index) => (
<div <div
key={item.label} key={item.label}
className="relative" className="navbar-reveal relative"
style={{ animationDelay: `${140 + index * 70}ms` }}
onMouseEnter={() => setOpenDropdown(item.label)} onMouseEnter={() => setOpenDropdown(item.label)}
onMouseLeave={() => setOpenDropdown(null)} onMouseLeave={() => setOpenDropdown(null)}
> >
<a <a
href={item.href} href={item.href}
className="flex items-center gap-1 rounded-[20px] px-[18px] py-[10px] text-[11px] font-semibold uppercase tracking-[0.18em] text-white transition-colors hover:bg-[#1f1f1f]" className={`nav-link-swap flex h-10 items-center rounded-[10px] px-[21px] text-[13px] font-bold uppercase leading-none text-white transition-colors hover:bg-aiero-dark ${
item.label === "Home" ? "bg-aiero-dark" : ""
}`}
style={{ fontFamily: "var(--font-sora)" }} style={{ fontFamily: "var(--font-sora)" }}
> >
{item.label} <span className="text-active">{item.label}</span>
<span aria-hidden>{item.label}</span>
{item.children && ( {item.children && (
<svg className="ml-0.5 h-2 w-2 opacity-60" viewBox="0 0 8 5" fill="none"> <svg className="ml-[12px] h-[5px] w-[5px] opacity-90" viewBox="0 0 5 5" fill="none">
<path d="M1 1L4 4L7 1" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round"/> <path d="M4.35 0.9L3.75 4.05L0.65 3.45" stroke="currentColor" strokeWidth="1.1" strokeLinecap="round" strokeLinejoin="round"/>
</svg> </svg>
)} )}
</a> </a>
{/* Dropdown */} {/* Dropdown */}
{item.children && openDropdown === item.label && ( {item.children && openDropdown === item.label && (
<div className="absolute left-0 top-full z-50 min-w-[200px] rounded-[15px] border border-[#2a2a2a] bg-[#111111] py-3 shadow-2xl"> <div className="absolute left-0 top-full z-50 min-w-[286px] origin-top rounded-[20px] border border-aiero-card-border bg-[#111111] px-[45px] py-[30px] shadow-2xl">
{item.children.map((child) => ( {item.children.map((child, childIndex) => (
<a <a
key={child.label} key={child.label}
href={child.href} href={child.href}
className="block px-5 py-2.5 text-[12px] font-medium text-white/80 transition-colors hover:text-[#45d0bd]" className="dropdown-reveal block py-[10px] pr-5 text-[14px] font-medium text-white/80 transition-all hover:pl-5 hover:text-aiero-teal"
style={{ fontFamily: "var(--font-sora)" }} style={{
animationDelay: `${childIndex * 45}ms`,
fontFamily: "var(--font-sora)",
}}
> >
{child.label} {child.label}
</a> </a>
@@ -64,14 +98,14 @@ export function Navbar() {
</nav> </nav>
{/* Right Icons */} {/* Right Icons */}
<div className="flex items-center gap-5"> <div className="navbar-reveal flex items-center justify-end gap-[10px]" style={{ animationDelay: "620ms" }}>
<button className="hidden text-white transition-colors hover:text-[#45d0bd] md:block" aria-label="Search"> <button className="hidden p-[8px] text-white transition-colors hover:text-aiero-teal md:block" aria-label="Search">
<SearchIcon className="h-[18px] w-[18px]" /> <SearchIcon className="h-[18px] w-[18px]" />
</button> </button>
<a <a
href="#" href="#"
className="hidden items-center gap-2 text-[11px] font-semibold uppercase tracking-[0.18em] text-white transition-colors hover:text-[#45d0bd] md:flex" className="hidden items-center gap-[8px] p-[8px] text-[13px] font-bold uppercase leading-none text-white transition-colors hover:text-aiero-teal md:flex"
style={{ fontFamily: "var(--font-sora)" }} style={{ fontFamily: "var(--font-sora)" }}
> >
<svg className="h-4 w-4" viewBox="0 0 16 16" fill="none"> <svg className="h-4 w-4" viewBox="0 0 16 16" fill="none">
@@ -83,7 +117,7 @@ export function Navbar() {
<a <a
href="#" href="#"
className="aiero-button aiero-button-gradient-border rounded-full px-[22px] py-[10px] text-[11px] font-semibold uppercase tracking-[0.18em] text-white" className="aiero-button aiero-button-gradient-border min-w-[188px] justify-center rounded-full px-[24px] py-[21px] text-[16px] font-semibold leading-none text-white"
style={{ fontFamily: "var(--font-sora)" }} style={{ fontFamily: "var(--font-sora)" }}
> >
Get in Touch Get in Touch

View File

@@ -11,14 +11,14 @@ export function PossibilitiesSection() {
{/* Left Column */} {/* Left Column */}
<div className="flex flex-col items-start pr-[10%] pt-[20px]"> <div className="flex flex-col items-start pr-[10%] pt-[20px]">
<span <span
className="aiero-subheading mb-[16px] text-white" className="aiero-subheading mb-[16px] text-aiero-dark uppercase tracking-[0.1em]"
style={{ fontFamily: "var(--font-sora)" }} style={{ fontFamily: "var(--font-sora)" }}
> >
Possibilities [ possibilities ]
</span> </span>
<h2 <h2
className="mb-[24px] max-w-[500px] tracking-[-0.03em] text-white" className="mb-[24px] max-w-[500px] tracking-[-0.03em] text-aiero-dark"
style={{ style={{
fontFamily: "var(--font-dm-sans)", fontFamily: "var(--font-dm-sans)",
fontSize: "clamp(32px, 4vw, 56px)", fontSize: "clamp(32px, 4vw, 56px)",
@@ -26,17 +26,17 @@ export function PossibilitiesSection() {
lineHeight: 1.1, lineHeight: 1.1,
}} }}
> >
Explore limitless possibilities with Aiero AI Explore limitless possibilities with our intelligent solutions
</h2> </h2>
<p className="mb-[40px] max-w-[480px] text-[16px] text-[#87899B]"> <p className="mb-[40px] max-w-[480px] text-[16px] leading-[1.8] text-aiero-text-muted">
Guppy siamese fighting fish, round stingray roach, sand tiger yellow weaver fish. Longnose lancetfish mooneye opah ghost fish. AIERO is a leading AI agency committed to transforming businesses through cutting-edge artificial intelligence solutions. We specialize in delivering tailored AI strategies that drive innovation, optimize processes, and unlock new opportunities for growth.
</p> </p>
<AieroButton <AieroButton
variant="gradient-fill" variant="gradient-border"
className="rounded-[25px] px-[35px] py-[15px] text-[15px] font-medium" className="rounded-[25px] px-[35px] py-[15px] text-[15px] font-medium"
showArrow={false} showArrow={true}
> >
Explore more Explore more
</AieroButton> </AieroButton>
@@ -45,9 +45,15 @@ export function PossibilitiesSection() {
<Counter <Counter
target={270} target={270}
suffix="k" suffix="k"
numberClassName="text-[60px] md:text-[80px] font-bold leading-none font-[var(--font-manrope)] gradient-text-purple" numberClassName="text-[60px] md:text-[100px] font-extrabold leading-none font-[var(--font-manrope)] text-transparent"
title="Global satisfied customers" style={{
titleClassName="font-[var(--font-manrope)] text-[16px] font-medium leading-[1.4] text-[#87899B] max-w-[120px]" WebkitTextStroke: "1px #E2D7F8",
backgroundImage: "linear-gradient(180deg, rgba(226, 215, 248, 0.44) 0%, rgba(226, 215, 248, 0.06) 90%)",
backgroundClip: "text",
WebkitBackgroundClip: "text",
}}
title="AI Solutions for our clients"
titleClassName="font-[var(--font-manrope)] text-[16px] font-bold leading-[1.4] text-aiero-dark max-w-[120px]"
layout="row-reverse" layout="row-reverse"
gap="30px" gap="30px"
/> />
@@ -59,26 +65,30 @@ export function PossibilitiesSection() {
<IconBox <IconBox
icon={<OrbitIcon className="h-full w-full" />} icon={<OrbitIcon className="h-full w-full" />}
title="Cutting-edge technology" title="Cutting-edge technology"
description="Integration of state-of-the-art AI algorithms, including deep learning, natural language processing." description="Integrating neural network models into existing systems or software applications, enabling businesses to leverage AI capabilities seamlessly."
hasBorder={true} hasBorder={true}
theme="light"
/> />
<IconBox <IconBox
icon={<FanIcon className="h-full w-full" />} icon={<FanIcon className="h-full w-full" />}
title="Tailored solutions" title="Tailored solutions"
description="Custom design and development of neural network architectures tailored to specific business needs." description="Integrating neural network models into existing systems or software applications, enabling businesses to leverage AI capabilities seamlessly."
hasBorder={true} hasBorder={true}
theme="light"
/> />
<IconBox <IconBox
icon={<CirclesIcon className="h-full w-full" />} icon={<CirclesIcon className="h-full w-full" />}
title="Training and workshops" title="Training and workshops"
description="Custom design and development of neural network architectures tailored to specific business needs and objectives." description="Custom design and development of neural network architectures tailored to specific business needs and objectives."
hasBorder={true} hasBorder={true}
theme="light"
/> />
<IconBox <IconBox
icon={<ExpandIcon className="h-full w-full" />} icon={<ExpandIcon className="h-full w-full" />}
title="AI-powered design" title="Modern development"
description="Integration of state-of-the-art AI algorithms, including deep learning, natural language processing." description="Building and training deep neural networks for tasks such as image recognition, natural language processing, speech recognition, and anomaly detection."
hasBorder={false} hasBorder={true}
theme="light"
/> />
</div> </div>

View File

@@ -0,0 +1,68 @@
export function TinkerSection() {
return (
<section className="relative px-[20px] py-[60px] md:py-[100px] overflow-hidden">
<div className="mx-auto flex max-w-[1260px] flex-col gap-[50px] lg:flex-row lg:items-center">
{/* Left Column - Images */}
<div className="relative flex w-full flex-col items-center justify-center lg:w-1/2">
{/* Background Glow */}
<div className="absolute inset-0 z-0 flex items-center justify-center pointer-events-none">
<img
src="https://8ded8880.delivery.rocketcdn.me/themes/aiero/wp-content/uploads/2025/02/Group-18433.svg"
alt=""
className="w-[120%] max-w-[800px] h-auto object-contain opacity-80"
aria-hidden="true"
/>
</div>
{/* Big X Image */}
<div className="relative z-10 w-full max-w-[450px]">
<img
src="https://8ded8880.delivery.rocketcdn.me/themes/aiero/wp-content/uploads/2025/01/Vector-13.png"
alt="Neural Network Visualization"
className="w-full h-auto"
/>
</div>
</div>
{/* Right Column - Text & Partners */}
<div className="relative z-10 flex w-full flex-col lg:w-1/2 lg:pl-[5%]">
<h2
className="mb-[60px] text-aiero-dark tracking-[-0.03em]"
style={{
fontFamily: "var(--font-dm-sans)",
fontSize: "clamp(36px, 4.5vw, 65px)",
fontWeight: 500,
lineHeight: 1.1,
}}
>
Tinker with a <span className="gradient-text-purple">Neural Network right here</span> in your browser. Dont worry, you cant break it. We Promise.
</h2>
{/* Partners row */}
<div className="flex flex-wrap items-center justify-start gap-x-[40px] gap-y-[30px]">
<img
src="https://8ded8880.delivery.rocketcdn.me/themes/aiero/wp-content/uploads/2024/12/partners-1.png"
alt="Partner 1"
className="h-auto w-[140px] object-contain"
/>
<img
src="https://8ded8880.delivery.rocketcdn.me/themes/aiero/wp-content/uploads/2024/12/partners-2.png"
alt="Partner 2"
className="h-auto w-[130px] object-contain"
/>
<img
src="https://8ded8880.delivery.rocketcdn.me/themes/aiero/wp-content/uploads/2024/12/partners-3.png"
alt="Partner 3"
className="h-auto w-[100px] object-contain"
/>
<img
src="https://8ded8880.delivery.rocketcdn.me/themes/aiero/wp-content/uploads/2024/12/partners-4.png"
alt="Partner 4"
className="h-auto w-[140px] object-contain"
/>
</div>
</div>
</div>
</section>
);
}

View File

@@ -0,0 +1,55 @@
import { PageContainer } from "@/components/shared/PageContainer";
import { SectionContainer } from "@/components/shared/SectionContainer";
export function AboutIntroSection() {
return (
<SectionContainer paddingY="lg">
<PageContainer className="grid grid-cols-1 gap-12 lg:grid-cols-[1fr_1fr] lg:gap-[60px] xl:gap-[100px]">
{/* Left: Text Content */}
<div className="flex flex-col items-start justify-center pt-5">
<span
className="aiero-subheading mb-4 text-aiero-teal"
style={{ fontFamily: "var(--font-sora)" }}
>
about
</span>
<h2
className="mb-6 tracking-[-0.03em] text-white"
style={{
fontFamily: "var(--font-dm-sans)",
fontSize: "clamp(32px, 4vw, 56px)",
fontWeight: 500,
lineHeight: 1.1,
}}
>
Awesome things in working with Aiero WordPress theme
</h2>
<p className="mb-8 text-base leading-relaxed text-aiero-text-muted">
At XXLando, we are a leading AI services provider dedicated to
delivering innovative solutions that leverage artificial
intelligence to transform businesses.
</p>
<p className="text-base leading-relaxed text-aiero-text-muted">
Our team of experts specializes in developing cutting-edge AI
technologies, such as machine learning, natural language
processing, and computer vision, to help our clients streamline
operations, enhance decision-making.
</p>
</div>
{/* Right: Images */}
<div className="relative">
<div className="relative aspect-[4/5] w-full overflow-hidden rounded-[25px] bg-aiero-card-dark">
<div
className="absolute inset-0 bg-cover bg-center"
style={{
backgroundImage: "url(/images/aiero/home-9-img.png)",
}}
/>
</div>
</div>
</PageContainer>
</SectionContainer>
);
}

View File

@@ -0,0 +1,68 @@
import { PageContainer } from "@/components/shared/PageContainer";
import { SectionContainer } from "@/components/shared/SectionContainer";
import { Counter } from "@/components/shared/Counter";
export function MissionSection() {
return (
<SectionContainer paddingY="lg">
<PageContainer className="grid grid-cols-1 gap-12 lg:grid-cols-[1fr_1.2fr] lg:gap-[60px] xl:gap-[100px]">
{/* Left: Images */}
<div className="relative aspect-square w-full md:aspect-[4/3] lg:aspect-square">
<div className="absolute bottom-0 left-0 h-[85%] w-[85%] overflow-hidden rounded-[25px] bg-aiero-card-dark">
<div
className="absolute inset-0 bg-cover bg-center"
style={{
backgroundImage: "url(/images/aiero/home-9-img.png)",
}}
/>
</div>
<div className="absolute right-0 top-0 h-[50%] w-[50%] overflow-hidden rounded-[25px] border-[8px] border-aiero-dark bg-aiero-card-purple">
<div
className="absolute inset-0 bg-cover bg-center"
style={{
backgroundImage: "url(/images/aiero/home-9-img.png)",
}}
/>
</div>
</div>
{/* Right: Text and Stats */}
<div className="flex flex-col items-start justify-center pt-5">
<span
className="aiero-subheading mb-4 text-aiero-teal"
style={{ fontFamily: "var(--font-sora)" }}
>
Mission
</span>
<h2
className="mb-6 tracking-[-0.03em] text-white"
style={{
fontFamily: "var(--font-dm-sans)",
fontSize: "clamp(32px, 4vw, 56px)",
fontWeight: 500,
lineHeight: 1.1,
}}
>
we create a professional product using artificial intelligence
</h2>
<p className="mb-10 text-base leading-relaxed text-aiero-text-muted">
Certainly, crafting a clear and inspiring mission statement is
essential for a development company. It should reflect your
company&apos;s values, purpose, and commitment to innovation.
</p>
<div className="w-full rounded-[25px] border border-aiero-card-border bg-aiero-card-dark p-8 md:p-10">
<Counter
target={1250}
suffix="+"
numberClassName="text-[60px] md:text-[80px] font-bold leading-none font-[var(--font-manrope)] gradient-text-purple"
title="Created projects"
titleClassName="font-[var(--font-sora)] text-[11px] font-semibold tracking-[0.18em] uppercase text-aiero-text-muted mt-2"
/>
</div>
</div>
</PageContainer>
</SectionContainer>
);
}

View File

@@ -0,0 +1,80 @@
"use client";
import { PageContainer } from "@/components/shared/PageContainer";
import { SectionContainer } from "@/components/shared/SectionContainer";
import { SectionHeading } from "@/components/shared/SectionHeading";
const teamMembers = [
{
name: "Dan Smith",
role: "Manager",
image: "/images/aiero/portrait-confident-man.jpg",
},
{
name: "Alan Begham",
role: "CEO",
image: "/images/aiero/waist-up-shot-handsome-calm.jpg",
},
{
name: "Brandon Adams",
role: "HR",
image: "/images/aiero/confident-ginger-man-with-trendy.jpg",
},
{
name: "Arthur Dowson",
role: "AI Programmer",
image: "/images/aiero/funny-curious-man-makes.jpg",
},
];
export function TeamSection() {
return (
<SectionContainer paddingY="lg">
<PageContainer>
<div className="mb-12 flex flex-col items-center justify-between gap-6 md:flex-row md:items-end">
<SectionHeading
tag="team"
title="The Neural Network experts: uniting talent for intelligent solutions"
titleClassName="text-white max-w-[600px]"
/>
<div className="flex flex-col items-start gap-4 md:items-end">
<p className="max-w-[200px] text-[16px] text-aiero-text-muted md:text-right">
Awesome team members + 0 Explore more
</p>
</div>
</div>
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4">
{teamMembers.map((member, i) => (
<div
key={i}
className="group relative overflow-hidden rounded-[25px] bg-aiero-card-dark"
>
<div className="relative aspect-[3/4] w-full">
<img
src={member.image}
alt={member.name}
className="h-full w-full object-cover transition-transform duration-500 group-hover:scale-105"
onError={(e) => {
(e.target as HTMLImageElement).src =
"/images/aiero/home-9-img.png"; // Fallback image
}}
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/80 via-transparent to-transparent opacity-80" />
</div>
<div className="absolute bottom-0 left-0 w-full p-6 text-white transition-transform duration-300 group-hover:-translate-y-2">
<h4
className="text-[20px] font-bold"
style={{ fontFamily: "var(--font-dm-sans)" }}
>
{member.name}
</h4>
<p className="text-[14px] text-aiero-teal">{member.role}</p>
</div>
</div>
))}
</div>
</PageContainer>
</SectionContainer>
);
}

View File

@@ -0,0 +1,18 @@
import { SectionContainer } from "@/components/shared/SectionContainer";
export function MapSection() {
return (
<SectionContainer paddingY="none" className="h-[500px] w-full">
<iframe
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d193595.15830869428!2d-74.11976397304603!3d40.69766374874431!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x89c24fa5d33f083b%3A0xc80b8f06e177fe62!2sNew%20York%2C%20NY%2C%20USA!5e0!3m2!1sen!2s!4v1716301234567!5m2!1sen!2s"
width="100%"
height="100%"
style={{ border: 0 }}
allowFullScreen={false}
loading="lazy"
referrerPolicy="no-referrer-when-downgrade"
title="Google Map"
/>
</SectionContainer>
);
}

View File

@@ -0,0 +1,92 @@
import { PageContainer } from "@/components/shared/PageContainer";
import { SectionContainer } from "@/components/shared/SectionContainer";
import { SectionHeading } from "@/components/shared/SectionHeading";
export function PricingSection() {
const plans = [
{
name: "Basic",
target: "Great for private individuals",
features: ["1 User", "Unlimited Projects", "Download prototypes", "1 Gb workspace"],
price: "Free",
isPopular: false,
},
{
name: "Premium",
target: "14 days free period",
features: ["15 Users", "Unlimited Projects", "Download prototypes", "15 Gb workspace"],
price: "$ 59 /mo",
isPopular: true,
},
{
name: "Unlimited",
target: "Great for private individuals",
features: ["100 Users", "Unlimited Projects", "Download prototypes", "100 Gb workspace"],
price: "$ 199 /mo",
isPopular: false,
},
];
return (
<SectionContainer paddingY="lg">
<PageContainer>
<div className="mb-16 flex flex-col items-center justify-center text-center">
<SectionHeading
tag="pricing"
title="Choose the plan that fits your needs"
titleClassName="text-white max-w-[500px] text-center"
/>
</div>
<div className="grid grid-cols-1 gap-6 md:grid-cols-3">
{plans.map((plan, i) => (
<div
key={i}
className={`relative flex flex-col overflow-hidden rounded-[25px] border ${
plan.isPopular ? "border-aiero-teal bg-aiero-card-dark" : "border-aiero-card-border bg-aiero-dark"
} p-10`}
>
{plan.isPopular && (
<div className="absolute right-6 top-6 rounded-full bg-aiero-teal px-4 py-1 text-[12px] font-bold uppercase text-aiero-dark" style={{ fontFamily: "var(--font-sora)" }}>
Popular
</div>
)}
<h3 className="mb-2 text-[24px] font-bold text-white" style={{ fontFamily: "var(--font-dm-sans)" }}>
{plan.name}
</h3>
<p className="mb-8 text-[14px] text-aiero-text-muted">{plan.target}</p>
<ul className="mb-10 flex flex-col gap-4">
{plan.features.map((feat, j) => (
<li key={j} className="flex items-center gap-3 text-white">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" className="text-aiero-teal">
<path d="M20 6L9 17l-5-5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
{feat}
</li>
))}
</ul>
<div className="mt-auto">
<div className="mb-6 text-[36px] font-bold text-white" style={{ fontFamily: "var(--font-dm-sans)" }}>
{plan.price}
</div>
<a
href="#"
className={`flex w-full items-center justify-center rounded-[12px] py-4 text-[16px] font-bold transition-all ${
plan.isPopular
? "bg-aiero-teal text-aiero-dark hover:bg-white"
: "border border-aiero-card-border text-white hover:border-aiero-teal hover:text-aiero-teal"
}`}
style={{ fontFamily: "var(--font-sora)" }}
>
Get started
</a>
</div>
</div>
))}
</div>
</PageContainer>
</SectionContainer>
);
}

View File

@@ -0,0 +1,63 @@
"use client";
import { PageContainer } from "@/components/shared/PageContainer";
import { SectionContainer } from "@/components/shared/SectionContainer";
import { ArrowIcon } from "@/components/shared/icons/ArrowIcon";
const services = [
{
title: "Neural Network Development",
desc: "Custom design and development of neural network architectures tailored to your specific business needs",
},
{
title: "Training & Optimization",
desc: "Fine-tuning and optimizing neural network models to improve accuracy, speed, and efficiency",
},
{
title: "Neural Network Integration",
desc: "Expert guidance and strategic advice on integrating neural networks into your existing systems",
},
];
export function ServiceCardsGrid() {
return (
<SectionContainer paddingY="lg">
<PageContainer>
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
{services.map((svc, i) => (
<div
key={i}
className="group relative flex h-full min-h-[340px] flex-col justify-between overflow-hidden rounded-[25px] border border-aiero-card-border bg-aiero-card-dark p-10 transition-all hover:bg-aiero-card-purple"
>
<div className="mb-6 h-[60px] w-[60px] rounded-full bg-aiero-card-purple2 p-4">
<img
src="/images/aiero/3x.png"
alt="Icon"
className="h-full w-full object-contain"
onError={(e) => {
(e.target as HTMLImageElement).src =
"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23fff'><path d='M12 2L2 22h20L12 2z'/></svg>";
}}
/>
</div>
<div>
<h4
className="mb-4 text-[22px] font-bold text-white transition-colors group-hover:text-aiero-teal"
style={{ fontFamily: "var(--font-dm-sans)" }}
>
{svc.title}
</h4>
<p className="text-[16px] text-aiero-text-muted">{svc.desc}</p>
</div>
<div className="absolute bottom-0 right-0 flex h-[60px] w-[60px] items-center justify-center rounded-tl-[25px] bg-white text-aiero-dark transition-all duration-300 group-hover:bg-aiero-teal group-hover:text-white">
<ArrowIcon className="h-4 w-4" />
</div>
</div>
))}
</div>
</PageContainer>
</SectionContainer>
);
}

View File

@@ -0,0 +1,67 @@
import { PageContainer } from "@/components/shared/PageContainer";
import { SectionContainer } from "@/components/shared/SectionContainer";
import { SectionHeading } from "@/components/shared/SectionHeading";
import { IconBox } from "@/components/shared/IconBox";
export function ServiceFeaturesSection() {
const features = [
{
title: "AI Technology",
desc: "Emphasize the expertise and knowledge of your team in developing and implementing neural networks.",
},
{
title: "Tailored solutions",
desc: "Mention your ability to create customized neural network solutions that specifically address your clients.",
},
{
title: "Cutting-edge technology",
desc: "Highlight that you use the latest and most advanced neural network frameworks and technologies.",
},
{
title: "AI consultancy & strategy",
desc: "Emphasize the expertise and knowledge of your team in developing and implementing neural networks.",
},
{
title: "Computer vision",
desc: "Mention your ability to create customized neural network solutions that specifically address your clients.",
},
{
title: "Deployment & Integration",
desc: "Highlight that you use the latest and most advanced neural network frameworks and technologies.",
},
];
const DefaultIcon = () => (
<div className="flex h-full w-full items-center justify-center rounded-[18px] bg-aiero-card-purple">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" className="text-white">
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</div>
);
return (
<SectionContainer paddingY="lg">
<PageContainer>
<div className="mb-16">
<SectionHeading
tag="features"
title="The unique selling points & advantages of our service"
titleClassName="text-white max-w-[700px]"
/>
</div>
<div className="grid grid-cols-1 gap-x-12 gap-y-12 md:grid-cols-2 lg:grid-cols-3">
{features.map((feat, i) => (
<IconBox
key={i}
icon={<DefaultIcon />}
title={feat.title}
description={feat.desc}
hasBorder={i < 3} // The original has a border for the first row
/>
))}
</div>
</PageContainer>
</SectionContainer>
);
}

View File

@@ -0,0 +1,72 @@
"use client";
import { PageContainer } from "@/components/shared/PageContainer";
import { SectionContainer } from "@/components/shared/SectionContainer";
import { SectionHeading } from "@/components/shared/SectionHeading";
export function TestimonialsSection() {
const testimonials = [
{
text: "Working with Aiero has been a game-changer for our business. Their AI solutions have revolutionized our operations, enabling us to automate repetitive tasks and make data-driven decisions. The level of efficiency we've achieved is unprecedented.",
author: "David Smith",
role: "CEO Company",
},
{
text: "Aiero has been a game-changer for our business. Their AI solutions have revolutionized our operations, enabling us to automate repetitive tasks and make data-driven decisions. The level of efficiency we've achieved is unprecedented.",
author: "Mark Dowson",
role: "Manager",
},
];
return (
<SectionContainer paddingY="lg" className="bg-aiero-card-dark">
<PageContainer>
<div className="mb-16">
<SectionHeading
tag="testimonials"
title="Discover what our clients have to say about our AI solutions"
titleClassName="text-white max-w-[650px]"
/>
</div>
<div className="grid grid-cols-1 gap-8 md:grid-cols-2">
{testimonials.map((t, i) => (
<div
key={i}
className="flex flex-col justify-between rounded-[25px] border border-aiero-card-border bg-[#1A1A1A] p-10 lg:p-12"
>
<div className="mb-8">
<div className="mb-6 flex gap-1 text-aiero-teal">
{[...Array(5)].map((_, index) => (
<svg key={index} width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
</svg>
))}
</div>
<p className="text-[18px] leading-[1.8] text-white">&quot;{t.text}&quot;</p>
</div>
<div className="flex items-center gap-4">
<div className="h-[60px] w-[60px] overflow-hidden rounded-full bg-aiero-dark">
<img
src={`/images/aiero/client-${i + 1}.jpg`}
alt={t.author}
className="h-full w-full object-cover"
onError={(e) => {
(e.target as HTMLImageElement).src = "/images/aiero/home-9-img.png";
}}
/>
</div>
<div>
<h5 className="text-[18px] font-bold text-white" style={{ fontFamily: "var(--font-dm-sans)" }}>
{t.author}
</h5>
<p className="text-[14px] text-aiero-teal">{t.role}</p>
</div>
</div>
</div>
))}
</div>
</PageContainer>
</SectionContainer>
);
}

View File

@@ -0,0 +1,51 @@
.iconWrapper {
position: absolute;
bottom: 0;
right: 0;
background-color: #FFFFFF;
border-top-left-radius: 30px;
border-bottom-right-radius: 25px;
padding: 10px 10px 0 10px;
z-index: 20;
}
.iconWrapper::before {
content: "";
position: absolute;
top: -20px;
right: 0;
width: 20px;
height: 20px;
background: radial-gradient(circle at 0 0, transparent 20px, #ffffff 20.5px);
}
.iconWrapper::after {
content: "";
position: absolute;
bottom: 0;
left: -20px;
width: 20px;
height: 20px;
background: radial-gradient(circle at 0 0, transparent 20px, #ffffff 20.5px);
}
.iconSlideAslant {
overflow: hidden;
}
.iconSlideAslantInner {
display: inline-flex;
transform: translate3d(-12px, 12px, 0);
transition: transform 0.34s cubic-bezier(0.22, 1, 0.36, 1);
will-change: transform;
}
.iconSlideAslantInner svg {
flex: 0 0 auto;
margin: 0 12px;
}
.iconSlideAslant:hover .iconSlideAslantInner,
:global(.aiero-card:hover) .iconSlideAslantInner {
transform: translate3d(12px, -12px, 0);
}

View File

@@ -1,4 +1,5 @@
import { ArrowIcon } from "@/components/shared/icons/ArrowIcon"; import { ArrowIcon } from "@/components/shared/icons/ArrowIcon";
import styles from "./CardShared.module.css";
interface CardHeadingProps { interface CardHeadingProps {
title: string; title: string;
@@ -19,20 +20,13 @@ export function CardHeading({
<div className={`mb-5 ${wrapperClassName}`}> <div className={`mb-5 ${wrapperClassName}`}>
{subtitle && ( {subtitle && (
<div <div
className={`aiero-subheading ${subtitleClassName}`} className={`aiero-subheading font-sora ${subtitleClassName}`}
style={{ fontFamily: "var(--font-sora)" }}
> >
{subtitle} {subtitle}
</div> </div>
)} )}
<h4 <h4
className={`tracking-[-0.03em] ${titleClassName}`} className={`font-dm-sans text-[30px] font-medium leading-[1.16666em] tracking-[-0.03em] ${titleClassName}`}
style={{
fontFamily: "var(--font-dm-sans)",
fontSize: "30px",
fontWeight: 500,
lineHeight: "1.16666em",
}}
> >
{title} {title}
</h4> </h4>
@@ -42,10 +36,17 @@ export function CardHeading({
export function IconButton({ className = "" }: { className?: string }) { export function IconButton({ className = "" }: { className?: string }) {
return ( return (
<div className={`absolute bottom-0 right-0 icon-decoration ${className}`}> <div className={`${styles.iconWrapper} ${className}`}>
<div className="icon-inner flex h-[52px] w-[52px] items-center justify-center rounded-tl-[30px] bg-white text-[#333333] transition-colors hover:bg-[#333333] hover:text-white"> <a
<ArrowIcon className="h-3 w-3" /> href="#"
</div> className={`${styles.iconSlideAslant} flex h-[52px] w-[52px] items-center justify-center rounded-[15px] bg-aiero-card-dark text-white transition-all duration-300 hover:bg-aiero-teal hover:text-aiero-dark`}
aria-label="Open details"
>
<span className={styles.iconSlideAslantInner} aria-hidden="true">
<ArrowIcon className="h-3 w-3" />
<ArrowIcon className="h-3 w-3" />
</span>
</a>
</div> </div>
); );
} }

View File

@@ -0,0 +1,171 @@
"use client";
import { type FormEvent, useState } from "react";
import { siteConfig } from "@/data/site-config";
import { SectionHeading } from "@/components/shared/SectionHeading";
import { SocialIcons } from "@/components/shared/SocialIcons";
import { PageContainer } from "@/components/shared/PageContainer";
import { SectionContainer } from "@/components/shared/SectionContainer";
import { ArrowIcon } from "@/components/shared/icons/ArrowIcon";
/**
* ContactFormSection — dark card with contact info + form.
*
* Shared by: About page (section 8) and Contacts page (section 2).
* Single implementation — avoids duplicated markup.
*
* Data sourced from `data/site-config.ts`.
*/
export function ContactFormSection() {
const [formState, setFormState] = useState({
fullName: "",
email: "",
subject: "",
message: "",
});
function handleSubmit(e: FormEvent) {
e.preventDefault();
// Form submission logic will be implemented later
}
function handleChange(
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) {
setFormState((prev) => ({ ...prev, [e.target.name]: e.target.value }));
}
return (
<SectionContainer paddingY="lg" className="bg-aiero-dark px-5">
<div className="overflow-hidden rounded-[25px] bg-aiero-card-dark">
<PageContainer className="grid grid-cols-1 gap-12 py-16 md:py-20 lg:grid-cols-2 lg:gap-16 lg:py-24">
{/* ── Left: Info column ── */}
<div className="flex flex-col">
<SectionHeading
tag="get in touch"
title="We are always ready to help you and answer your questions"
titleClassName="text-white"
description="Pacific hake false trevally queen parrotfish black prickleback mosshead warbonnet sweeper! Greenling sleeper."
/>
{/* Contact details grid */}
<div className="mt-10 grid grid-cols-1 gap-8 sm:grid-cols-2">
{/* Call Center */}
<div>
<h6 className="mb-3 font-sora text-sm font-semibold text-white">
Call Center
</h6>
<div className="flex flex-col gap-1">
<a
href={`tel:${siteConfig.phoneRaw}`}
className="text-[15px] text-aiero-text-muted transition-colors hover:text-aiero-teal"
>
{siteConfig.phone}
</a>
<a
href="tel:+11800234567"
className="text-[15px] text-aiero-text-muted transition-colors hover:text-aiero-teal"
>
+ (123) 1800-234-5678
</a>
</div>
</div>
{/* Our Location */}
<div>
<h6 className="mb-3 font-sora text-sm font-semibold text-white">
Our Location
</h6>
<p className="text-[15px] leading-relaxed text-aiero-text-muted">
{siteConfig.address.line1}
<br />
{siteConfig.address.line2}
</p>
</div>
{/* Email */}
<div>
<h6 className="mb-3 font-sora text-sm font-semibold text-white">
Email
</h6>
<a
href={`mailto:${siteConfig.email}`}
className="text-[15px] text-aiero-text-muted underline transition-colors hover:text-aiero-teal"
>
{siteConfig.email}
</a>
</div>
{/* Social */}
<div>
<h6 className="mb-3 font-sora text-sm font-semibold text-white">
Social network
</h6>
<SocialIcons links={siteConfig.socials} />
</div>
</div>
</div>
{/* ── Right: Form column ── */}
<div className="rounded-[25px] bg-white p-8 md:p-10">
<h4
className="mb-8 text-aiero-dark"
style={{
fontFamily: "var(--font-sora)",
fontSize: "28px",
fontWeight: 700,
lineHeight: 1.2,
}}
>
Get in Touch
</h4>
<form onSubmit={handleSubmit} className="flex flex-col gap-5">
<input
type="text"
name="fullName"
placeholder="Full name"
value={formState.fullName}
onChange={handleChange}
className="rounded-xl border border-gray-200 bg-gray-50 px-5 py-3.5 text-[15px] text-aiero-dark outline-none transition-colors focus:border-aiero-teal"
/>
<input
type="email"
name="email"
placeholder="Email"
required
value={formState.email}
onChange={handleChange}
className="rounded-xl border border-gray-200 bg-gray-50 px-5 py-3.5 text-[15px] text-aiero-dark outline-none transition-colors focus:border-aiero-teal"
/>
<input
type="text"
name="subject"
placeholder="Subject"
value={formState.subject}
onChange={handleChange}
className="rounded-xl border border-gray-200 bg-gray-50 px-5 py-3.5 text-[15px] text-aiero-dark outline-none transition-colors focus:border-aiero-teal"
/>
<textarea
name="message"
placeholder="Message"
rows={4}
value={formState.message}
onChange={handleChange}
className="resize-none rounded-xl border border-gray-200 bg-gray-50 px-5 py-3.5 text-[15px] text-aiero-dark outline-none transition-colors focus:border-aiero-teal"
/>
<button
type="submit"
className="aiero-button aiero-button-gradient-border mt-2 self-start rounded-full px-8 py-4 font-sora text-base font-semibold text-aiero-dark"
>
Send message
<ArrowIcon className="h-3 w-3" />
<span className="button-inner" />
</button>
</form>
</div>
</PageContainer>
</div>
</SectionContainer>
);
}

View File

@@ -53,7 +53,7 @@ export function Counter({
requestAnimationFrame(animate); requestAnimationFrame(animate);
} }
}, },
{ threshold: 0.3 } { rootMargin: "0px 0px 20% 0px", threshold: 0.01 }
); );
observer.observe(el); observer.observe(el);

View File

@@ -0,0 +1,109 @@
import Image from "next/image";
import Link from "next/link";
import { siteConfig } from "@/data/site-config";
import { SocialIcons } from "@/components/shared/SocialIcons";
import { PageContainer } from "@/components/shared/PageContainer";
/**
* Footer — shared site-wide footer.
*
* Renders on every page via layout.tsx.
* Data sourced from `data/site-config.ts` — no hardcoded links.
*
* Structure (from reference):
* Left: Logo · social icons · outline "since 2024" text
* Right: Company links column · Services links column
* Bottom: Copyright · Terms/Privacy
*/
export function Footer() {
return (
<footer className="bg-aiero-dark px-5 pb-10 pt-16 md:pt-20">
<PageContainer>
{/* ── Top row: Logo + link columns ── */}
<div className="grid grid-cols-1 gap-12 md:grid-cols-2 lg:grid-cols-[1.5fr_1fr_1fr]">
{/* Brand column */}
<div className="flex flex-col items-start gap-8">
<Link href="/" aria-label="Home">
<Image
src="/images/aiero/logo-dark.png"
alt={siteConfig.name}
width={146}
height={26}
className="h-auto w-auto brightness-0 invert"
/>
</Link>
<SocialIcons links={siteConfig.socials} />
{/* Outline "since 2024" decorative text */}
<span
className="mt-4 select-none font-sora text-[clamp(48px,6vw,80px)] font-bold leading-none tracking-tight"
style={{
WebkitTextStroke: "1px rgba(255,255,255,0.12)",
WebkitTextFillColor: "transparent",
}}
>
since 2024
</span>
</div>
{/* Company links */}
<div>
<h4 className="mb-6 font-sora text-sm font-semibold uppercase tracking-widest text-white">
Company
</h4>
<ul className="flex flex-col gap-3">
{siteConfig.footerLinks.company.map((link) => (
<li key={link.label}>
<a
href={link.href}
className="text-[15px] text-aiero-text-muted transition-colors duration-300 hover:text-aiero-teal"
>
{link.label}
</a>
</li>
))}
</ul>
</div>
{/* Services links */}
<div>
<h4 className="mb-6 font-sora text-sm font-semibold uppercase tracking-widest text-white">
Services
</h4>
<ul className="flex flex-col gap-3">
{siteConfig.footerLinks.services.map((link) => (
<li key={link.label}>
<a
href={link.href}
className="text-[15px] text-aiero-text-muted transition-colors duration-300 hover:text-aiero-teal"
>
{link.label}
</a>
</li>
))}
</ul>
</div>
</div>
{/* ── Bottom bar ── */}
<div className="mt-14 flex flex-col items-center justify-between gap-4 border-t border-aiero-card-border pt-8 md:flex-row">
<p className="text-sm text-aiero-text-muted">
{siteConfig.copyright}
</p>
<div className="flex gap-6">
{siteConfig.legalLinks.map((link) => (
<a
key={link.label}
href={link.href}
className="text-sm text-aiero-text-muted transition-colors duration-300 hover:text-aiero-teal"
>
{link.label}
</a>
))}
</div>
</div>
</PageContainer>
</footer>
);
}

View File

@@ -1,38 +1,53 @@
import { ReactNode } from "react"; import { ReactNode } from "react";
interface IconBoxProps { interface IconBoxProps {
icon: ReactNode; icon?: ReactNode;
title: string; title: string;
description: string; description: string;
hasBorder?: boolean; hasBorder?: boolean;
theme?: "dark" | "light";
} }
export function IconBox({ icon, title, description, hasBorder = true }: IconBoxProps) { export function IconBox({ icon, title, description, hasBorder = true, theme = "dark" }: IconBoxProps) {
const isLight = theme === "light";
return ( return (
<div className="flex flex-col items-start gap-[20px] sm:flex-row sm:gap-[40px]"> <div className="aiero-icon-box-widget w-full">
<div className="flex h-[88px] w-[88px] shrink-0 items-center justify-center"> <div className="icon-box-item flex flex-col items-start gap-[20px] sm:flex-row sm:gap-[40px]">
{icon} {icon && (
</div> <div className="icon-container background-type-none flex h-[88px] w-[88px] shrink-0 items-center justify-center">
<span className="icon block h-full w-full">
<div {icon}
className={`flex-1 pb-[30px] pt-[5px] ${ </span>
hasBorder ? "border-b border-[#3F3F3F]" : "" </div>
}`} )}
>
<h5 <div
className="mb-[15px] text-white" className={`content-container flex-1 pb-[30px] pt-[5px] ${
style={{ hasBorder
fontFamily: "var(--font-manrope)", ? isLight
fontSize: "25px", ? "border-b border-gray-200"
lineHeight: 1.4, : "border-b border-aiero-card-border"
fontWeight: 500, : ""
}} }`}
> >
{title} <h5
</h5> className={`icon-box-title mb-[15px] ${isLight ? "text-aiero-dark" : "text-white"}`}
<p className="text-[16px] leading-[1.6] text-[#87899B]"> style={{
{description} fontFamily: "var(--font-manrope)",
</p> fontSize: "25px",
lineHeight: 1.4,
fontWeight: 500,
}}
>
{title}
</h5>
<div className="icon-box-info">
<p className="text-[16px] leading-[1.6] text-aiero-text-muted">
{description}
</p>
</div>
</div>
</div> </div>
</div> </div>
); );

View File

@@ -0,0 +1,22 @@
import { type ReactNode } from "react";
interface PageContainerProps {
children: ReactNode;
className?: string;
}
/**
* PageContainer — global max-width + horizontal padding wrapper.
*
* Every section's inner content should be wrapped in this to ensure
* consistent container width across all pages.
*
* Default: max-w-[1260px], px-[15px], mx-auto
*/
export function PageContainer({ children, className = "" }: PageContainerProps) {
return (
<div className={`mx-auto w-full max-w-[1260px] px-[15px] ${className}`}>
{children}
</div>
);
}

View File

@@ -0,0 +1,126 @@
interface BreadcrumbItem {
label: string;
href?: string;
}
interface PageTitleBannerProps {
/** Page title — "About us", "Services", "Contacts" */
title: string;
/** Breadcrumb trail */
breadcrumbs: BreadcrumbItem[];
}
/**
* PageTitleBanner — shared inner-page hero banner.
*
* Used by: About, Services, Contacts pages.
*
* Structure (from reference):
* - Full-width rounded card with gradient background
* - Centered "/ Title /" text
* - Breadcrumbs bottom-left
* - Decorative "Aiero" outline text right side
* - Top-left and bottom-right rounded corner decorations
*/
export function PageTitleBanner({ title, breadcrumbs }: PageTitleBannerProps) {
return (
<div className="relative mx-5 overflow-hidden rounded-[25px] bg-aiero-dark">
{/* Background image */}
<div
className="absolute inset-0 bg-cover bg-center opacity-80"
style={{
backgroundImage: "url(/images/aiero/page-top-bg-min.png)",
}}
/>
{/* Gradient overlay */}
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-transparent to-aiero-dark/60" />
{/* Top-left corner decoration */}
<div className="absolute left-0 top-0 h-20 w-20">
<div className="absolute left-0 top-0 h-full w-full rounded-br-[25px] bg-white" />
<div className="absolute left-0 top-0 h-full w-full rounded-tl-[25px] bg-aiero-dark">
<div
className="absolute inset-0 bg-cover bg-center opacity-80"
style={{
backgroundImage: "url(/images/aiero/page-top-bg-min.png)",
}}
/>
</div>
</div>
{/* Bottom-right corner decoration */}
<div className="absolute bottom-0 right-0 h-20 w-20">
<div className="absolute bottom-0 right-0 h-full w-full rounded-tl-[25px] bg-white" />
<div className="absolute bottom-0 right-0 h-full w-full rounded-br-[25px] bg-aiero-dark">
<div
className="absolute inset-0 bg-cover bg-center opacity-80"
style={{
backgroundImage: "url(/images/aiero/page-top-bg-min.png)",
}}
/>
</div>
</div>
{/* Content */}
<div className="relative z-10 flex min-h-[320px] flex-col items-center justify-center px-8 py-16 md:min-h-[400px] lg:min-h-[460px]">
{/* Title */}
<h1
className="text-center text-white"
style={{
fontFamily: "var(--font-sora)",
fontSize: "clamp(36px, 5vw, 72px)",
fontWeight: 700,
lineHeight: 1.1,
}}
>
<span className="mr-3 text-aiero-text-muted">/</span>
{title}
<span className="ml-3 text-aiero-text-muted">/</span>
</h1>
{/* Breadcrumbs */}
<nav className="absolute bottom-8 left-8 md:bottom-10 md:left-12" aria-label="Breadcrumb">
<ol className="flex items-center gap-2 text-sm text-white/70">
{breadcrumbs.map((crumb, index) => (
<li key={crumb.label} className="flex items-center gap-2">
{index > 0 && (
<span className="mx-1 inline-block h-1 w-1 rounded-full bg-aiero-teal" />
)}
{index < breadcrumbs.length - 1 && crumb.href ? (
<a
href={crumb.href}
className="transition-colors hover:text-aiero-teal"
>
{crumb.label}
</a>
) : (
<span className="text-white">{crumb.label}</span>
)}
</li>
))}
</ol>
</nav>
{/* Decorative vertical "Aiero" text */}
<div
className="absolute bottom-8 right-8 hidden select-none lg:block"
style={{
writingMode: "vertical-rl",
textOrientation: "mixed",
}}
>
<span
className="font-sora text-[clamp(48px,5vw,72px)] font-bold leading-none tracking-tight"
style={{
WebkitTextStroke: "1px rgba(255,255,255,0.1)",
WebkitTextFillColor: "transparent",
}}
>
Aiero
</span>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,48 @@
"use client";
import { PageContainer } from "@/components/shared/PageContainer";
import { SectionContainer } from "@/components/shared/SectionContainer";
export function PartnerLogosSection() {
const logos = [
"/images/aiero/partners-1.png",
"/images/aiero/partners-2.png",
"/images/aiero/partners-1.png",
"/images/aiero/partners-2.png",
"/images/aiero/partners-1.png",
"/images/aiero/partners-2.png",
];
return (
<SectionContainer paddingY="lg" className="border-t border-aiero-card-border bg-aiero-dark">
<PageContainer className="flex flex-col items-center">
<h3
className="mb-16 max-w-[800px] text-center text-white"
style={{
fontFamily: "var(--font-dm-sans)",
fontSize: "clamp(24px, 3vw, 36px)",
fontWeight: 500,
lineHeight: 1.2,
}}
>
Tinker with a Neural Network right here in your browser. Dont worry, you cant break it. We Promise.
</h3>
<div className="flex flex-wrap justify-center gap-8 md:gap-16 lg:gap-24 opacity-60">
{logos.map((src, index) => (
<div key={index} className="flex h-12 items-center justify-center grayscale transition-all hover:grayscale-0">
<img
src={src}
alt={`Partner ${index + 1}`}
className="h-full w-auto object-contain"
onError={(e) => {
(e.target as HTMLImageElement).src = "/images/aiero/logo-dark.png";
}}
/>
</div>
))}
</div>
</PageContainer>
</SectionContainer>
);
}

View File

@@ -0,0 +1,45 @@
import { AieroButton } from "@/components/shared/AieroButton";
import { PageContainer } from "@/components/shared/PageContainer";
/**
* PreFooterCTA — "It's blow your mind! Meet Neural Networks" banner.
*
* Shared across: Home, About, Services, Contacts.
*
* Structure (from reference):
* - Dark grey rounded card
* - Large teal gradient heading
* - "Get a Quote" button with arrow
*/
export function PreFooterCTA() {
return (
<section className="px-5 pb-5">
<div className="overflow-hidden rounded-[25px] bg-aiero-card-dark">
<PageContainer className="flex flex-col items-center gap-8 py-16 text-center md:flex-row md:justify-between md:py-20 md:text-left lg:py-24">
{/* Heading */}
<h2
className="max-w-[700px]"
style={{
fontFamily: "var(--font-sora)",
fontSize: "clamp(28px, 3.5vw, 48px)",
fontWeight: 700,
lineHeight: 1.15,
}}
>
<span className="text-white">{"It's blow your mind! "}</span>
<span className="gradient-text-purple">Meet Neural Networks</span>
</h2>
{/* CTA */}
<AieroButton
href="/contacts"
variant="gradient-border"
className="shrink-0 rounded-full px-8 py-4 text-base font-semibold text-white"
>
Get a Quote
</AieroButton>
</PageContainer>
</div>
</section>
);
}

View File

@@ -0,0 +1,46 @@
"use client";
import { type CSSProperties, type ReactNode, useEffect, useRef, useState } from "react";
interface RevealOnViewProps {
children: ReactNode;
className?: string;
delay?: number;
}
export function RevealOnView({
children,
className = "",
delay = 0,
}: RevealOnViewProps) {
const ref = useRef<HTMLDivElement>(null);
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
const element = ref.current;
if (!element) return;
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true);
observer.unobserve(element);
}
},
{ rootMargin: "0px 0px 18% 0px", threshold: 0.01 }
);
observer.observe(element);
return () => observer.disconnect();
}, []);
return (
<div
ref={ref}
className={`reveal-on-view ${isVisible ? "is-visible" : ""} ${className}`}
style={{ "--reveal-delay": `${delay}ms` } as CSSProperties}
>
{children}
</div>
);
}

View File

@@ -0,0 +1,35 @@
import { ArrowIcon } from "./icons/ArrowIcon";
interface ScrollDownProps {
href?: string;
className?: string;
text?: string;
light?: boolean;
}
/**
* ScrollDown — interactive scroll indicator.
* Matches original Aiero reference animation and styling.
*/
export function ScrollDown({
href = "#scroll-down",
className = "",
text = "Scroll down",
light = true,
}: ScrollDownProps) {
return (
<span className={`scroll-btn-decoration ${className}`}>
<a
href={href}
className={`inline-flex h-[78px] w-[190px] items-center justify-center gap-2 rounded-b-[25px] ${
light ? "bg-white text-aiero-dark" : "bg-aiero-dark text-white"
} text-[14px] font-semibold no-underline transition-all hover:text-aiero-teal hover:shadow-scroll-btn`}
style={{ fontFamily: "var(--font-sora)" }}
>
{text}
<ArrowIcon className="h-3 w-3" />
</a>
</span>
);
}

View File

@@ -0,0 +1,54 @@
import { type ReactNode } from "react";
type PaddingSize = "none" | "sm" | "md" | "lg" | "xl";
interface SectionContainerProps {
children: ReactNode;
className?: string;
/** Vertical padding preset — maps to spacing tokens */
paddingY?: PaddingSize;
/** HTML element to render */
as?: "section" | "div";
/** Section id for anchor links */
id?: string;
}
/**
* Tailwind class map for vertical section padding.
*
* Values use the spacing tokens from design-tokens.ts:
* sm = 60px
* md = 60px → 80px
* lg = 60px → 80px → 100px
* xl = 60px → 80px → 100px → 120px
*/
const paddingYClasses: Record<PaddingSize, string> = {
none: "",
sm: "py-[60px]",
md: "py-[60px] md:py-[80px]",
lg: "py-[60px] md:py-[80px] lg:py-[100px]",
xl: "py-[60px] md:py-[80px] lg:py-[100px] xl:py-[120px]",
};
/**
* SectionContainer — consistent vertical spacing for page sections.
*
* Use this to wrap every major page section. The `paddingY` prop
* selects from predefined responsive spacing tokens.
*
* Does NOT include horizontal constraints — nest a `PageContainer`
* inside for boxed content.
*/
export function SectionContainer({
children,
className = "",
paddingY = "lg",
as: Tag = "section",
id,
}: SectionContainerProps) {
return (
<Tag id={id} className={`${paddingYClasses[paddingY]} ${className}`}>
{children}
</Tag>
);
}

View File

@@ -0,0 +1,72 @@
import { type ReactNode } from "react";
interface SectionHeadingProps {
/** Small tag label — e.g. "team", "get in touch" */
tag?: string;
/** Main heading text */
title: string | ReactNode;
/** Optional description paragraph below the heading */
description?: string;
/** HTML heading level */
titleAs?: "h1" | "h2" | "h3" | "h4";
/** Wrapper className */
className?: string;
/** Title className override */
titleClassName?: string;
/** Description className override */
descriptionClassName?: string;
/** Tag className override */
tagClassName?: string;
}
/**
* SectionHeading — page-level section header.
*
* Pattern: [tag] + heading + optional description.
* Used for top-level section titles across all pages.
*
* For card-internal headings, use `CardHeading` instead.
*/
export function SectionHeading({
tag,
title,
description,
titleAs: Tag = "h2",
className = "",
titleClassName = "",
descriptionClassName = "",
tagClassName = "",
}: SectionHeadingProps) {
return (
<div className={className}>
{tag && (
<span
className={`aiero-subheading mb-4 text-aiero-teal ${tagClassName}`}
style={{ fontFamily: "var(--font-sora)" }}
>
{tag}
</span>
)}
<Tag
className={`tracking-[-0.03em] ${titleClassName}`}
style={{
fontFamily: "var(--font-dm-sans)",
fontSize: "clamp(32px, 4vw, 56px)",
fontWeight: 500,
lineHeight: 1.1,
}}
>
{title}
</Tag>
{description && (
<p
className={`mt-6 text-base leading-relaxed text-aiero-text-muted ${descriptionClassName}`}
>
{description}
</p>
)}
</div>
);
}

View File

@@ -0,0 +1,67 @@
import { type SocialLink } from "@/data/site-config";
interface SocialIconsProps {
links: readonly SocialLink[] | SocialLink[];
className?: string;
iconClassName?: string;
}
/**
* Reusable social icon list.
* Used in: Footer, ContactFormSection.
*/
export function SocialIcons({
links,
className = "",
iconClassName = "",
}: SocialIconsProps) {
return (
<div className={`flex items-center gap-4 ${className}`} role="list">
{links.map((link) => (
<a
key={link.platform}
href={link.url}
target="_blank"
rel="noopener noreferrer"
role="listitem"
aria-label={link.platform}
className={`flex h-10 w-10 items-center justify-center rounded-full border border-aiero-card-border text-aiero-text-muted transition-all duration-300 hover:border-aiero-teal hover:text-aiero-teal ${iconClassName}`}
>
<SocialSvg icon={link.icon} />
</a>
))}
</div>
);
}
/** Inline SVG icons for each social platform */
function SocialSvg({ icon }: { icon: SocialLink["icon"] }) {
const size = "h-4 w-4";
switch (icon) {
case "facebook":
return (
<svg className={size} viewBox="0 0 24 24" fill="currentColor">
<path d="M9.198 21.5h4v-8.01h3.604l.396-3.98h-4V7.5a1 1 0 0 1 1-1h3v-4h-3a5 5 0 0 0-5 5v2.01h-2l-.396 3.98h2.396v8.01Z" />
</svg>
);
case "x-twitter":
return (
<svg className={size} viewBox="0 0 24 24" fill="currentColor">
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231 5.45-6.231Zm-1.161 17.52h1.833L7.084 4.126H5.117L17.083 19.77Z" />
</svg>
);
case "linkedin":
return (
<svg className={size} viewBox="0 0 24 24" fill="currentColor">
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286ZM5.337 7.433a2.062 2.062 0 0 1-2.063-2.065 2.064 2.064 0 1 1 2.063 2.065Zm1.782 13.019H3.555V9h3.564v11.452ZM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003Z" />
</svg>
);
case "youtube":
return (
<svg className={size} viewBox="0 0 24 24" fill="currentColor">
<path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814ZM9.545 15.568V8.432L15.818 12l-6.273 3.568Z" />
</svg>
);
}
}

View File

@@ -1,19 +1,90 @@
export function OrbitIcon({ className = "" }: { className?: string }) { export function OrbitIcon({ className = "" }: { className?: string }) {
return ( return (
<svg className={className} viewBox="0 0 78 88" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg className={className} viewBox="0 0 86 88" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M45.74 40.8109C51.6726 37.3857 53.7055 29.8003 50.2807 23.8683C46.8559 17.9363 39.2702 15.9042 33.3376 19.3294C27.405 22.7546 25.3721 30.3401 28.7969 36.2721C32.2217 42.2041 39.8074 44.2361 45.74 40.8109Z" stroke="url(#paint0_linear)" strokeWidth="0.6"/> <g opacity="0.9">
<path d="M47.1284 43.216C53.426 39.58 55.5842 31.528 51.9488 25.2313C48.3134 18.9346 40.2611 16.7777 33.9634 20.4136C27.6658 24.0496 25.5076 32.1016 29.143 38.3982C32.7784 44.6949 40.8307 46.8518 47.1284 43.216Z" stroke="url(#paint1_linear)" strokeWidth="0.6"/> <path d="M72.9676 74.6603C80.1714 67.289 72.5959 47.586 56.0472 30.6525C39.4986 13.719 20.2435 5.96732 13.0397 13.3386C5.83591 20.7099 13.4114 40.4129 29.9601 57.3464C46.5087 74.2799 65.7639 82.0316 72.9676 74.6603Z" stroke="url(#paint0_linear)" strokeWidth="2" strokeMiterlimit="10"></path>
<path d="M48.5691 45.7111C55.2842 41.8341 57.5856 33.2485 53.7094 26.5346C49.8331 19.8208 41.2471 17.521 34.5319 21.398C27.8168 25.275 25.5154 33.8606 29.3916 40.5745C33.2679 47.2883 41.8539 49.5881 48.5691 45.7111Z" stroke="url(#paint2_linear)" strokeWidth="0.6"/> <path d="M69.1024 78.6075C76.3062 71.2362 68.7307 51.5333 52.182 34.5998C35.6334 17.6663 16.3782 9.91459 9.17444 17.2859C1.97067 24.6572 9.54619 44.3601 26.0948 61.2936C42.6435 78.2271 61.8986 85.9788 69.1024 78.6075Z" stroke="url(#paint0_linear)" strokeWidth="2" strokeMiterlimit="10"></path>
<path d="M50.0791 48.2764C57.2512 44.1205 59.6971 34.9389 55.5422 27.7685C51.3874 20.5981 42.205 18.1543 35.0329 22.3102C27.8609 26.466 25.415 35.6477 29.5698 42.8181C33.7247 49.9885 42.9071 52.4322 50.0791 48.2764Z" stroke="url(#paint3_linear)" strokeWidth="0.6"/> <path d="M74.8934 72.6837C82.0972 65.3124 74.5217 45.6095 57.973 28.676C41.4244 11.7425 22.1692 3.99076 14.9655 11.3621C7.76168 18.7334 15.3372 38.4363 31.8859 55.3698C48.4345 72.3033 67.6896 80.055 74.8934 72.6837Z" stroke="url(#paint0_linear)" strokeWidth="2" strokeMiterlimit="10"></path>
<path d="M51.5834 50.9308C59.2604 46.4985 61.8917 36.6837 57.4607 29.0089C53.0296 21.334 43.2141 18.7054 35.5371 23.1377C27.8601 27.57 25.2288 37.3848 29.6599 45.0596C34.091 52.7345 43.9065 55.3631 51.5834 50.9308Z" stroke="url(#paint4_linear)" strokeWidth="0.6"/> <path d="M78.7587 68.7345C85.9624 61.3632 78.3869 41.6602 61.8383 24.7267C45.2896 7.79324 26.0345 0.0415411 18.8307 7.41284C11.6269 14.7841 19.2024 34.4871 35.7511 51.4206C52.2997 68.3541 71.5549 76.1058 78.7587 68.7345Z" stroke="url(#paint0_linear)" strokeWidth="2" strokeMiterlimit="10"></path>
<path d="M53.1404 53.6281C61.3442 48.8916 64.1552 38.4018 59.419 30.1984C54.6827 21.995 44.1928 19.1845 35.989 23.921C27.7852 28.6574 24.9742 39.1472 29.7105 47.3506C34.4467 55.554 44.9366 58.3645 53.1404 53.6281Z" stroke="url(#paint5_linear)" strokeWidth="0.6"/> <path d="M80.6844 66.7579C87.8882 59.3866 80.3127 39.6837 63.764 22.7502C47.2154 5.81667 27.9602 -1.93502 20.7565 5.43628C13.5527 12.8076 21.1282 32.5105 37.6769 49.444C54.2255 66.3775 73.4807 74.1292 80.6844 66.7579Z" stroke="url(#paint0_linear)" strokeWidth="2" strokeMiterlimit="10"></path>
<path d="M54.7248 56.3733C63.4817 51.3175 66.4824 40.1209 61.4271 31.3649C56.3718 22.609 45.1749 19.6093 36.4181 24.6651C27.6613 29.7208 24.6606 40.9175 29.7159 49.6734C34.7711 58.4294 45.968 61.429 54.7248 56.3733Z" stroke="url(#paint6_linear)" strokeWidth="0.6"/> <path d="M76.827 70.7091C84.0308 63.3378 76.4553 43.6349 59.9066 26.7013C43.358 9.76785 24.1028 2.01615 16.8991 9.38745C9.69528 16.7588 17.2708 36.4617 33.8194 53.3952C50.3681 70.3287 69.6232 78.0804 76.827 70.7091Z" stroke="url(#paint0_linear)" strokeWidth="2" strokeMiterlimit="10"></path>
<path d="M56.3293 59.1495C65.6588 53.7631 68.856 41.8346 63.4704 32.5064C58.0847 23.1782 46.1557 19.9827 36.8262 25.3691C27.4967 30.7555 24.2995 42.6841 29.6852 52.0123C35.0708 61.3405 47.0001 64.5359 56.3293 59.1495Z" stroke="url(#paint7_linear)" strokeWidth="0.6"/> <path d="M71.034 76.6349C78.2378 69.2636 70.6623 49.5606 54.1136 32.6271C37.565 15.6936 18.3099 7.94193 11.1061 15.3132C3.90231 22.6845 11.4778 42.3875 28.0265 59.321C44.5751 76.2545 63.8303 84.0062 71.034 76.6349Z" stroke="url(#paint0_linear)" strokeWidth="2" strokeMiterlimit="10"></path>
<path d="M57.9492 61.9564C67.8667 56.2305 71.2646 43.5487 65.5385 33.6308C59.8124 23.7129 47.1307 20.3147 37.2132 26.0406C27.2956 31.7664 23.8978 44.4482 29.6239 54.3661C35.35 64.284 48.0317 67.6823 57.9492 61.9564Z" stroke="url(#paint8_linear)" strokeWidth="0.6"/> <path d="M63.3055 84.5392C70.5093 77.1679 62.9338 57.4649 46.3851 40.5314C29.8365 23.5979 10.5813 15.8462 3.37757 23.2175C-3.8262 30.5888 3.74932 50.2918 20.298 67.2253C36.8466 84.1588 56.1018 91.9105 63.3055 84.5392Z" stroke="url(#paint0_linear)" strokeWidth="2" strokeMiterlimit="10"></path>
<path d="M59.5832 64.788C70.104 58.7138 73.7088 45.2609 67.6347 34.7402C61.5606 24.2195 48.1077 20.6149 37.5868 26.6892C27.0659 32.7634 23.4612 46.2162 29.5353 56.7369C35.6094 67.2576 49.0623 70.8623 59.5832 64.788Z" stroke="url(#paint9_linear)" strokeWidth="0.6"/> <path d="M67.1747 80.586C74.3784 73.2147 66.8029 53.5118 50.2543 36.5783C33.7056 19.6448 14.4505 11.8931 7.24671 19.2644C0.0429349 26.6357 7.61846 46.3386 24.1671 63.2721C40.7158 80.2056 59.9709 87.9573 67.1747 80.586Z" stroke="url(#paint0_linear)" strokeWidth="2" strokeMiterlimit="10"></path>
<path d="M77.3353 53.9649C75.6778 68.1777 62.8087 78.3548 48.5983 76.6937C34.3841 75.0349 24.2075 62.1707 25.8712 47.9595C27.5286 33.7467 40.3978 23.5695 54.6081 25.2307C68.8224 26.8895 78.999 39.7537 77.3353 53.9649Z" stroke="url(#paint10_linear)" strokeWidth="0.6"/> <path d="M65.243 82.5606C72.4468 75.1893 64.8713 55.4864 48.3226 38.5529C31.774 21.6194 12.5188 13.8677 5.31507 21.239C-1.88871 28.6103 5.68682 48.3133 22.2355 65.2468C38.7841 82.1803 58.0393 89.932 65.243 82.5606Z" stroke="url(#paint0_linear)" strokeWidth="2" strokeMiterlimit="10"></path>
<path d="M79.5896 56.4701C77.5065 71.3716 63.7371 81.7627 48.8364 79.6828C33.9358 77.603 23.5412 63.8311 25.6244 48.9296C27.7075 34.0281 41.4769 23.637 56.3776 25.7169C71.2805 27.8007 81.6728 41.5686 79.5896 56.4701Z" stroke="url(#paint11_linear)" strokeWidth="0.6"/> <path d="M82.6141 64.7794C89.8179 57.4081 82.2424 37.7052 65.6937 20.7717C49.1451 3.83816 29.8899 -3.91354 22.6862 3.45777C15.4824 10.8291 23.0579 30.532 39.6066 47.4655C56.1552 64.399 75.4103 72.1507 82.6141 64.7794Z" stroke="url(#paint0_linear)" strokeWidth="2" strokeMiterlimit="10"></path>
<path d="M81.8459 58.9799C79.3371 74.5701 64.6657 85.1813 49.0742 82.6726C33.4849 80.1677 22.873 65.4985 25.3795 49.9043C27.8882 34.3142 42.5596 23.7029 58.1512 26.2116C73.7428 28.7204 84.3524 43.3857 81.8459 58.9799Z" stroke="url(#paint12_linear)" strokeWidth="0.6"/> </g>
<defs>
<linearGradient id="paint0_linear" x1="0" y1="26" x2="35" y2="-2" gradientUnits="userSpaceOnUse">
<stop stopColor="#8258C8"></stop>
<stop offset="0.315" stopColor="#6766C8"></stop>
<stop offset="1" stopColor="#2C84C8"></stop>
</linearGradient>
</defs>
</svg>
);
}
export function FanIcon({ className = "" }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 88 80" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.9">
<path d="M87.7358 51.8843C88.5393 40.4428 69.6078 29.7137 45.4514 27.92C21.2949 26.1264 1.06085 33.9474 0.257442 45.3889C-0.545971 56.8303 18.3854 67.5595 42.5419 69.3532C66.6984 71.1468 86.9324 63.3257 87.7358 51.8843Z" stroke="url(#paint0_linear)" strokeWidth="0.8" strokeMiterlimit="10"></path>
<path d="M86.1273 49.4961C86.4426 38.3099 67.5487 28.671 43.9267 27.9671C20.3047 27.2631 0.899755 35.7606 0.584497 46.9468C0.269239 58.133 19.1631 67.7718 42.7851 68.4758C66.4071 69.1798 85.8121 60.6822 86.1273 49.4961Z" stroke="url(#paint0_linear)" strokeWidth="0.8" strokeMiterlimit="10"></path>
<path d="M43.0465 67.609C66.1301 67.2237 84.7032 58.0488 84.5306 47.1164C84.358 36.1839 65.5051 27.6338 42.4216 28.0191C19.338 28.4044 0.764905 37.5793 0.937486 48.5117C1.11007 59.4442 19.9629 67.9943 43.0465 67.609Z" stroke="url(#paint0_linear)" strokeWidth="0.8" strokeMiterlimit="10"></path>
<path d="M43.2948 66.7346C65.8425 65.2596 83.5855 55.4071 82.9249 44.7284C82.2642 34.0497 63.4501 26.5887 40.9024 28.0637C18.3547 29.5387 0.611718 39.3911 1.27235 50.0698C1.93298 60.7485 20.7471 68.2095 43.2948 66.7346Z" stroke="url(#paint0_linear)" strokeWidth="0.8" strokeMiterlimit="10"></path>
<path d="M43.5405 65.8641C65.5549 63.3009 82.4707 52.7731 81.323 42.3497C80.1753 31.9264 61.3986 25.5544 39.3841 28.1177C17.3697 30.6809 0.453861 41.2086 1.6016 51.632C2.74933 62.0554 21.526 68.4273 43.5405 65.8641Z" stroke="url(#paint0_linear)" strokeWidth="0.8" strokeMiterlimit="10"></path>
<path d="M43.7803 65.0011C65.2575 61.3489 81.3422 50.1424 79.7064 39.9708C78.0706 29.7992 59.3338 24.5142 37.8567 28.1664C16.3795 31.8186 0.294806 43.025 1.93058 53.1966C3.56635 63.3683 22.3031 68.6533 43.7803 65.0011Z" stroke="url(#paint0_linear)" strokeWidth="0.8" strokeMiterlimit="10"></path>
<path d="M44.0316 64.1276C64.974 59.3849 80.2298 47.5022 78.1062 37.5869C75.9827 27.6716 57.284 23.4784 36.3416 28.2211C15.3991 32.9639 0.143341 44.8465 2.26688 54.7618C4.39041 64.6771 23.0891 68.8703 44.0316 64.1276Z" stroke="url(#paint0_linear)" strokeWidth="0.8" strokeMiterlimit="10"></path>
</g>
<defs>
<linearGradient id="paint0_linear" x1="0" y1="26" x2="35" y2="-2" gradientUnits="userSpaceOnUse">
<stop stopColor="#8258C8"></stop>
<stop offset="0.315" stopColor="#6766C8"></stop>
<stop offset="1" stopColor="#2C84C8"></stop>
</linearGradient>
</defs>
</svg>
);
}
export function CirclesIcon({ className = "" }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 84 84" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.9">
<path d="M41.9976 83C64.64 83 82.9952 64.6437 82.9952 42C82.9952 19.3563 64.64 1 41.9976 1C19.3553 1 1 19.3563 1 42C1 64.6437 19.3553 83 41.9976 83Z" stroke="url(#paint0_linear)" strokeMiterlimit="10"></path>
<path d="M82.0594 41.1137C82.0909 43.1738 82.0144 45.1755 81.7758 47.1501C81.1772 52.0351 79.611 56.722 77.2346 60.8963C75.6728 63.6356 73.8365 66.15 71.8381 68.4845C69.8173 70.8505 67.5579 72.9646 64.9789 74.7998C61.9679 76.9409 58.6013 78.6412 54.9872 79.7702C52.5298 80.5439 49.9823 81.0567 47.3764 81.3131C45.7156 81.475 44.0368 81.5245 42.322 81.4885C39.9996 81.439 37.7132 81.2186 35.4763 80.8408C34.1846 80.6203 32.9109 80.355 31.6642 80.0266C25.6781 78.4568 20.1557 75.6365 15.6864 71.5432C14.2776 70.2523 12.9589 68.8669 11.7212 67.4005C10.2449 65.6552 8.8857 63.8155 7.68849 61.8768C6.49578 59.9517 5.46961 57.932 4.60546 55.8179C3.88533 54.0592 3.30023 52.233 2.87266 50.3483C2.23354 47.555 1.94099 44.6357 1.9995 41.6445C2.04001 39.2875 2.28755 36.98 2.68812 34.7219C3.79982 28.4651 6.07271 22.7121 9.64633 17.7507C12.1263 14.3187 15.2003 11.3319 18.6659 8.91196C22.1045 6.50998 25.9347 4.65228 30.0394 3.39731C33.8875 2.21881 37.9878 1.5576 42.205 1.49013C49.1632 1.38217 55.7118 3.10943 61.4548 6.21311C67.2653 9.35727 72.2072 13.9318 75.7628 19.4779C79.7685 25.7258 81.9424 33.1611 82.0639 41.1137H82.0594Z" stroke="url(#paint0_linear)" strokeMiterlimit="10"></path>
<path d="M81.1161 40.2325C81.1791 42.2566 81.1881 44.2133 81.0081 46.1475C80.5625 50.9424 79.0773 55.6294 76.6963 59.7542C75.1211 62.471 73.3072 64.936 71.4394 67.2975C69.5581 69.6679 67.4697 71.7955 64.9673 73.6622C62.0418 75.8393 58.7157 77.5441 55.1151 78.6101C52.6757 79.3388 50.1507 79.7796 47.5988 79.9595C45.9695 80.0675 44.3267 80.0585 42.6479 79.9865C40.3885 79.8876 38.1472 79.6492 35.9553 79.2803C34.6861 79.0689 33.4393 78.8215 32.2151 78.5202C26.3596 77.0628 20.8597 74.4809 16.5389 70.3786C15.1842 69.0922 13.9195 67.7158 12.7087 66.2764C11.2685 64.5626 9.90476 62.7814 8.69855 60.9237C7.49684 59.0795 6.46166 57.1498 5.566 55.1212C4.81887 53.4254 4.21127 51.6576 3.78369 49.8224C3.14008 47.0966 2.88804 44.2313 3.00056 41.2941C3.08607 38.991 3.36512 36.733 3.77019 34.5154C4.89089 28.3621 6.86223 22.7125 10.3323 17.7871C12.7357 14.391 15.7963 11.4718 19.2259 9.14628C22.633 6.83427 26.4136 5.08451 30.4508 3.89252C34.245 2.7725 38.2822 2.11128 42.4004 1.98534C49.1336 1.77393 55.4842 3.37974 61.1011 6.33948C66.7721 9.3397 71.6105 13.7658 75.0536 19.1725C78.9332 25.2719 80.8776 32.5138 81.1206 40.228L81.1161 40.2325Z" stroke="url(#paint0_linear)" strokeMiterlimit="10"></path>
</g>
<defs>
<linearGradient id="paint0_linear" x1="0" y1="26" x2="35" y2="-2" gradientUnits="userSpaceOnUse">
<stop stopColor="#8258C8"></stop>
<stop offset="0.315" stopColor="#6766C8"></stop>
<stop offset="1" stopColor="#2C84C8"></stop>
</linearGradient>
</defs>
</svg>
);
}
export function ExpandIcon({ className = "" }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 86 88" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.9">
<path d="M45.74 40.8109C51.6726 37.3857 53.7055 29.8003 50.2807 23.8683C46.8559 17.9363 39.2702 15.9042 33.3376 19.3294C27.405 22.7546 25.3721 30.3401 28.7969 36.2721C32.2217 42.2041 39.8074 44.2361 45.74 40.8109Z" stroke="url(#paint0_linear)" strokeWidth="0.6"/>
<path d="M47.1284 43.216C53.426 39.58 55.5842 31.528 51.9488 25.2313C48.3134 18.9346 40.2611 16.7777 33.9634 20.4136C27.6658 24.0496 25.5076 32.1016 29.143 38.3982C32.7784 44.6949 40.8307 46.8518 47.1284 43.216Z" stroke="url(#paint1_linear)" strokeWidth="0.6"/>
<path d="M48.5691 45.7111C55.2842 41.8341 57.5856 33.2485 53.7094 26.5346C49.8331 19.8208 41.2471 17.521 34.5319 21.398C27.8168 25.275 25.5154 33.8606 29.3916 40.5745C33.2679 47.2883 41.8539 49.5881 48.5691 45.7111Z" stroke="url(#paint2_linear)" strokeWidth="0.6"/>
<path d="M50.0791 48.2764C57.2512 44.1205 59.6971 34.9389 55.5422 27.7685C51.3874 20.5981 42.205 18.1543 35.0329 22.3102C27.8609 26.466 25.415 35.6477 29.5698 42.8181C33.7247 49.9885 42.9071 52.4322 50.0791 48.2764Z" stroke="url(#paint3_linear)" strokeWidth="0.6"/>
<path d="M51.5834 50.9308C59.2604 46.4985 61.8917 36.6837 57.4607 29.0089C53.0296 21.334 43.2141 18.7054 35.5371 23.1377C27.8601 27.57 25.2288 37.3848 29.6599 45.0596C34.091 52.7345 43.9065 55.3631 51.5834 50.9308Z" stroke="url(#paint4_linear)" strokeWidth="0.6"/>
<path d="M53.1404 53.6281C61.3442 48.8916 64.1552 38.4018 59.419 30.1984C54.6827 21.995 44.1928 19.1845 35.989 23.921C27.7852 28.6574 24.9742 39.1472 29.7105 47.3506C34.4467 55.554 44.9366 58.3645 53.1404 53.6281Z" stroke="url(#paint5_linear)" strokeWidth="0.6"/>
<path d="M54.7248 56.3733C63.4817 51.3175 66.4824 40.1209 61.4271 31.3649C56.3718 22.609 45.1749 19.6093 36.4181 24.6651C27.6613 29.7208 24.6606 40.9175 29.7159 49.6734C34.7711 58.4294 45.968 61.429 54.7248 56.3733Z" stroke="url(#paint6_linear)" strokeWidth="0.6"/>
<path d="M56.3293 59.1495C65.6588 53.7631 68.856 41.8346 63.4704 32.5064C58.0847 23.1782 46.1557 19.9827 36.8262 25.3691C27.4967 30.7555 24.2995 42.6841 29.6852 52.0123C35.0708 61.3405 47.0001 64.5359 56.3293 59.1495Z" stroke="url(#paint7_linear)" strokeWidth="0.6"/>
<path d="M57.9492 61.9564C67.8667 56.2305 71.2646 43.5487 65.5385 33.6308C59.8124 23.7129 47.1307 20.3147 37.2132 26.0406C27.2956 31.7664 23.8978 44.4482 29.6239 54.3661C35.35 64.284 48.0317 67.6823 57.9492 61.9564Z" stroke="url(#paint8_linear)" strokeWidth="0.6"/>
<path d="M59.5832 64.788C70.104 58.7138 73.7088 45.2609 67.6347 34.7402C61.5606 24.2195 48.1077 20.6149 37.5868 26.6892C27.0659 32.7634 23.4612 46.2162 29.5353 56.7369C35.6094 67.2576 49.0623 70.8623 59.5832 64.788Z" stroke="url(#paint9_linear)" strokeWidth="0.6"/>
<path d="M77.3353 53.9649C75.6778 68.1777 62.8087 78.3548 48.5983 76.6937C34.3841 75.0349 24.2075 62.1707 25.8712 47.9595C27.5286 33.7467 40.3978 23.5695 54.6081 25.2307C68.8224 26.8895 78.999 39.7537 77.3353 53.9649Z" stroke="url(#paint10_linear)" strokeWidth="0.6"/>
<path d="M79.5896 56.4701C77.5065 71.3716 63.7371 81.7627 48.8364 79.6828C33.9358 77.603 23.5412 63.8311 25.6244 48.9296C27.7075 34.0281 41.4769 23.637 56.3776 25.7169C71.2805 27.8007 81.6728 41.5686 79.5896 56.4701Z" stroke="url(#paint11_linear)" strokeWidth="0.6"/>
<path d="M81.8459 58.9799C79.3371 74.5701 64.6657 85.1813 49.0742 82.6726C33.4849 80.1677 22.873 65.4985 25.3795 49.9043C27.8882 34.3142 42.5596 23.7029 58.1512 26.2116C73.7428 28.7204 84.3524 43.3857 81.8459 58.9799Z" stroke="url(#paint12_linear)" strokeWidth="0.6"/>
</g>
<defs> <defs>
<linearGradient id="paint0_linear" x1="1.76204" y1="0.999985" x2="96.3599" y2="20.9846" gradientUnits="userSpaceOnUse"><stop stopColor="#8258C8"/><stop offset="0.315" stopColor="#6766C8"/><stop offset="1" stopColor="#2C84C8"/></linearGradient> <linearGradient id="paint0_linear" x1="1.76204" y1="0.999985" x2="96.3599" y2="20.9846" gradientUnits="userSpaceOnUse"><stop stopColor="#8258C8"/><stop offset="0.315" stopColor="#6766C8"/><stop offset="1" stopColor="#2C84C8"/></linearGradient>
<linearGradient id="paint1_linear" x1="2.73637" y1="1.48534" x2="95.1113" y2="21.0161" gradientUnits="userSpaceOnUse"><stop stopColor="#8258C8"/><stop offset="0.315" stopColor="#6766C8"/><stop offset="1" stopColor="#2C84C8"/></linearGradient> <linearGradient id="paint1_linear" x1="2.73637" y1="1.48534" x2="95.1113" y2="21.0161" gradientUnits="userSpaceOnUse"><stop stopColor="#8258C8"/><stop offset="0.315" stopColor="#6766C8"/><stop offset="1" stopColor="#2C84C8"/></linearGradient>
@@ -32,50 +103,3 @@ export function OrbitIcon({ className = "" }: { className?: string }) {
</svg> </svg>
); );
} }
export function FanIcon({ className = "" }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 78 88" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M48.5691 45.7111C55.2842 41.8341 57.5856 33.2485 53.7094 26.5346C49.8331 19.8208 41.2471 17.521 34.5319 21.398C27.8168 25.275 25.5154 33.8606 29.3916 40.5745C33.2679 47.2883 41.8539 49.5881 48.5691 45.7111Z" stroke="url(#paint0_linear)" strokeWidth="0.6"/>
<path d="M50.0791 48.2764C57.2512 44.1205 59.6971 34.9389 55.5422 27.7685C51.3874 20.5981 42.205 18.1543 35.0329 22.3102C27.8609 26.466 25.415 35.6477 29.5698 42.8181C33.7247 49.9885 42.9071 52.4322 50.0791 48.2764Z" stroke="url(#paint1_linear)" strokeWidth="0.6"/>
<path d="M51.5834 50.9308C59.2604 46.4985 61.8917 36.6837 57.4607 29.0089C53.0296 21.334 43.2141 18.7054 35.5371 23.1377C27.8601 27.57 25.2288 37.3848 29.6599 45.0596C34.091 52.7345 43.9065 55.3631 51.5834 50.9308Z" stroke="url(#paint2_linear)" strokeWidth="0.6"/>
<defs>
<linearGradient id="paint0_linear" x1="1.76204" y1="0.999985" x2="96.3599" y2="20.9846" gradientUnits="userSpaceOnUse"><stop stopColor="#8258C8"/><stop offset="0.315" stopColor="#6766C8"/><stop offset="1" stopColor="#2C84C8"/></linearGradient>
<linearGradient id="paint1_linear" x1="2.73637" y1="1.48534" x2="95.1113" y2="21.0161" gradientUnits="userSpaceOnUse"><stop stopColor="#8258C8"/><stop offset="0.315" stopColor="#6766C8"/><stop offset="1" stopColor="#2C84C8"/></linearGradient>
<linearGradient id="paint2_linear" x1="3.70122" y1="1.96678" x2="93.8892" y2="21.0474" gradientUnits="userSpaceOnUse"><stop stopColor="#8258C8"/><stop offset="0.315" stopColor="#6766C8"/><stop offset="1" stopColor="#2C84C8"/></linearGradient>
</defs>
</svg>
);
}
export function CirclesIcon({ className = "" }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 78 88" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="39" cy="44" r="30" stroke="url(#paint0_linear)" strokeWidth="0.6"/>
<circle cx="39" cy="44" r="25" stroke="url(#paint1_linear)" strokeWidth="0.6"/>
<circle cx="39" cy="44" r="20" stroke="url(#paint2_linear)" strokeWidth="0.6"/>
<circle cx="39" cy="44" r="15" stroke="url(#paint3_linear)" strokeWidth="0.6"/>
<circle cx="39" cy="44" r="10" stroke="url(#paint4_linear)" strokeWidth="0.6"/>
<defs>
<linearGradient id="paint0_linear" x1="9" y1="14" x2="69" y2="74" gradientUnits="userSpaceOnUse"><stop stopColor="#8258C8"/><stop offset="0.315" stopColor="#6766C8"/><stop offset="1" stopColor="#2C84C8"/></linearGradient>
<linearGradient id="paint1_linear" x1="14" y1="19" x2="64" y2="69" gradientUnits="userSpaceOnUse"><stop stopColor="#8258C8"/><stop offset="0.315" stopColor="#6766C8"/><stop offset="1" stopColor="#2C84C8"/></linearGradient>
<linearGradient id="paint2_linear" x1="19" y1="24" x2="59" y2="64" gradientUnits="userSpaceOnUse"><stop stopColor="#8258C8"/><stop offset="0.315" stopColor="#6766C8"/><stop offset="1" stopColor="#2C84C8"/></linearGradient>
<linearGradient id="paint3_linear" x1="24" y1="29" x2="54" y2="59" gradientUnits="userSpaceOnUse"><stop stopColor="#8258C8"/><stop offset="0.315" stopColor="#6766C8"/><stop offset="1" stopColor="#2C84C8"/></linearGradient>
<linearGradient id="paint4_linear" x1="29" y1="34" x2="49" y2="54" gradientUnits="userSpaceOnUse"><stop stopColor="#8258C8"/><stop offset="0.315" stopColor="#6766C8"/><stop offset="1" stopColor="#2C84C8"/></linearGradient>
</defs>
</svg>
);
}
export function ExpandIcon({ className = "" }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 78 88" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M45.74 40.8109C51.6726 37.3857 53.7055 29.8003 50.2807 23.8683C46.8559 17.9363 39.2702 15.9042 33.3376 19.3294C27.405 22.7546 25.3721 30.3401 28.7969 36.2721C32.2217 42.2041 39.8074 44.2361 45.74 40.8109Z" stroke="url(#paint0_linear)" strokeWidth="0.6"/>
<path d="M48.5691 45.7111C55.2842 41.8341 57.5856 33.2485 53.7094 26.5346C49.8331 19.8208 41.2471 17.521 34.5319 21.398C27.8168 25.275 25.5154 33.8606 29.3916 40.5745C33.2679 47.2883 41.8539 49.5881 48.5691 45.7111Z" stroke="url(#paint1_linear)" strokeWidth="0.6"/>
<defs>
<linearGradient id="paint0_linear" x1="1.76204" y1="0.999985" x2="96.3599" y2="20.9846" gradientUnits="userSpaceOnUse"><stop stopColor="#8258C8"/><stop offset="0.315" stopColor="#6766C8"/><stop offset="1" stopColor="#2C84C8"/></linearGradient>
<linearGradient id="paint1_linear" x1="3.70122" y1="1.96678" x2="93.8892" y2="21.0474" gradientUnits="userSpaceOnUse"><stop stopColor="#8258C8"/><stop offset="0.315" stopColor="#6766C8"/><stop offset="1" stopColor="#2C84C8"/></linearGradient>
</defs>
</svg>
);
}

126
data/design-tokens.ts Normal file
View File

@@ -0,0 +1,126 @@
// ─── Design Tokens ───────────────────────────────────────────────────
// Single source of truth for all design values.
// Changing a value here should update the entire site.
// CSS custom properties in globals.css mirror these for Tailwind usage.
// ─────────────────────────────────────────────────────────────────────
/** Color palette — use Tailwind classes (e.g. `bg-aiero-dark`) when possible */
export const colors = {
// Backgrounds
bgDark: "#1F1F1F",
bgCardDark: "#282828",
bgCardBorder: "#3F3F3F",
bgWhite: "#FFFFFF",
// Accent
accentTeal: "#45D0BD",
accentBlue: "#44B6E9",
accentRed: "#EF6464",
accentRedHover: "#F57E7E",
// Purple palette
purpleStart: "#8258C8",
purpleMid: "#6766C8",
purpleEnd: "#2C84C8",
cardPurple: "#343F78",
cardPurple2: "#56619E",
cardLavender: "#AC8DE0",
// Text
textMuted: "#87899B",
textWhite: "#FFFFFF",
textDark: "#1F1F1F",
} as const;
/** Spacing tokens — predefined values only, no arbitrary px */
export const spacing = {
/** Vertical padding for page sections */
sectionPaddingY: {
sm: "60px",
md: "80px",
lg: "100px",
xl: "120px",
},
/** Horizontal page gutter */
pageGutter: "20px",
/** Max width for boxed containers */
containerMaxWidth: "1260px",
/** Container inner padding */
containerPaddingX: "15px",
/** Gap between cards in grids */
cardGap: "20px",
/** Gap between components within a section */
componentGap: {
sm: "30px",
md: "40px",
lg: "50px",
},
} as const;
/** Border radius tokens */
export const borderRadius = {
card: "25px",
button: "25px",
buttonPill: "9999px",
tag: "15px",
navbar: "10px",
section: "25px",
} as const;
/** Typography scale */
export const typography = {
hero: {
size: "clamp(38px, 5.9vw, 100px)",
weight: 700,
lineHeight: 1.1,
letterSpacing: "-0.03em",
},
sectionTitle: {
size: "clamp(32px, 4vw, 56px)",
weight: 500,
lineHeight: 1.1,
letterSpacing: "-0.03em",
},
cardTitle: {
size: "30px",
weight: 500,
lineHeight: "1.16666em",
letterSpacing: "-0.03em",
},
body: {
size: "16px",
weight: 400,
lineHeight: 1.6,
},
small: {
size: "14px",
weight: 500,
lineHeight: 1,
},
tag: {
size: "12px",
weight: 600,
lineHeight: 1,
letterSpacing: "0.1em",
textTransform: "uppercase" as const,
},
} as const;
/** Shadow tokens */
export const shadows = {
cardHover:
"0 22px 55px rgba(31, 31, 31, 0.16), 0 0 0 1px rgba(69, 208, 189, 0.22)",
buttonHover: "0 15px 30px rgba(239, 100, 100, 0.28)",
scrollBtn: "0 12px 30px rgba(0, 0, 0, 0.14)",
} as const;
/** Animation presets */
export const animations = {
/** Reveal-on-scroll */
revealDuration: "0.72s",
revealEase: "cubic-bezier(0.22, 1, 0.36, 1)",
/** Card / button hover */
hoverDuration: "0.32s",
hoverEase: "ease",
hoverLift: "-4px",
} as const;

View File

@@ -24,7 +24,7 @@ export const navigationData: NavItem[] = [
label: "Pages", label: "Pages",
href: "#", href: "#",
children: [ children: [
{ label: "About Us", href: "#" }, { label: "About Us", href: "/about" },
{ label: "About Us 2", href: "#" }, { label: "About Us 2", href: "#" },
{ label: "Team", href: "#" }, { label: "Team", href: "#" },
{ label: "Gallery Grid", href: "#" }, { label: "Gallery Grid", href: "#" },
@@ -39,7 +39,7 @@ export const navigationData: NavItem[] = [
label: "Services", label: "Services",
href: "#", href: "#",
children: [ children: [
{ label: "Services Page", href: "#" }, { label: "Services Page", href: "/services" },
{ label: "Service Single", href: "#" }, { label: "Service Single", href: "#" },
], ],
}, },
@@ -65,6 +65,6 @@ export const navigationData: NavItem[] = [
}, },
{ {
label: "Contacts", label: "Contacts",
href: "#", href: "/contacts",
}, },
]; ];

60
data/site-config.ts Normal file
View File

@@ -0,0 +1,60 @@
// ─── Site Configuration ──────────────────────────────────────────────
// Single source for branding, contact info, social links, and footer data.
// Shared by: Footer, ContactFormSection, Navbar (mobile), TopBar.
// ─────────────────────────────────────────────────────────────────────
export interface SocialLink {
platform: string;
url: string;
icon: "facebook" | "x-twitter" | "linkedin" | "youtube";
}
export interface FooterLink {
label: string;
href: string;
}
export const siteConfig = {
name: "Aiero",
tagline: "AI Agency",
// Contact
phone: "+1 800 529 10 37",
phoneRaw: "+18005291037",
email: "aiero@mail.co",
address: {
line1: "USA, New York 1060",
line2: "Str. First Avenue 1",
},
// Social
socials: [
{ platform: "Facebook", url: "https://www.facebook.com/", icon: "facebook" },
{ platform: "X", url: "https://twitter.com/", icon: "x-twitter" },
{ platform: "LinkedIn", url: "https://www.linkedin.com/", icon: "linkedin" },
{ platform: "Youtube", url: "https://www.youtube.com/", icon: "youtube" },
] as SocialLink[],
// Footer link columns
footerLinks: {
company: [
{ label: "About Us", href: "/about" },
{ label: "Creative Team", href: "#" },
{ label: "Pricing Plans", href: "#" },
{ label: "FAQ", href: "#" },
] as FooterLink[],
services: [
{ label: "Services Page", href: "/services" },
{ label: "AI Systems", href: "#" },
{ label: "Deep Learning", href: "#" },
{ label: "Neural Networks", href: "#" },
] as FooterLink[],
},
// Legal
copyright: "©Aiero 2025. All rights reserved.",
legalLinks: [
{ label: "Terms of use", href: "#" },
{ label: "Privacy Policy", href: "#" },
] as FooterLink[],
} as const;

View File

@@ -1,18 +1,17 @@
import { FlatCompat } from "@eslint/eslintrc"; import nextCoreWebVitals from "eslint-config-next/core-web-vitals";
import { dirname } from "path"; import nextTypescript from "eslint-config-next/typescript";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
});
const eslintConfig = [ const eslintConfig = [
...compat.extends("next/core-web-vitals", "next/typescript"), ...nextCoreWebVitals,
...nextTypescript,
{ {
ignores: [".next/**", "out/**", "build/**", "next-env.d.ts"], ignores: [
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
"demo.artureanec.com*/**",
],
}, },
]; ];

7
package-lock.json generated
View File

@@ -9,6 +9,7 @@
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"next": "16.2.9", "next": "16.2.9",
"ogl": "^1.0.11",
"react": "19.2.4", "react": "19.2.4",
"react-dom": "19.2.4" "react-dom": "19.2.4"
}, },
@@ -5317,6 +5318,12 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/ogl": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ogl/-/ogl-1.0.11.tgz",
"integrity": "sha512-kUpC154AFfxi16pmZUK4jk3J+8zxwTWGPo03EoYA8QPbzikHoaC82n6pNTbd+oEaJonaE8aPWBlX7ad9zrqLsA==",
"license": "Unlicense"
},
"node_modules/optionator": { "node_modules/optionator": {
"version": "0.9.4", "version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",

View File

@@ -10,6 +10,7 @@
}, },
"dependencies": { "dependencies": {
"next": "16.2.9", "next": "16.2.9",
"ogl": "^1.0.11",
"react": "19.2.4", "react": "19.2.4",
"react-dom": "19.2.4" "react-dom": "19.2.4"
}, },

40
parse_css.js Normal file
View File

@@ -0,0 +1,40 @@
const fs = require('fs');
const html = fs.readFileSync('/Users/apple/.gemini/antigravity-ide/brain/ea503590-6ba8-4b57-9e9c-c9c8fe9a2395/about_reference.html', 'utf8');
// Match all <style> blocks
const styleRegex = /<style[^>]*>([\s\S]*?)<\/style>/gi;
let styles = '';
let match;
while ((match = styleRegex.exec(html)) !== null) {
styles += match[1] + '\n';
}
function extractCSS(selector) {
// Very simple regex to find the block for a selector
const regex = new RegExp(selector.replace(/\./g, '\\.') + '\\s*\\{([^}]+)\\}', 'gi');
let results = [];
let m;
while ((m = regex.exec(styles)) !== null) {
results.push(m[1].trim());
}
return results.length > 0 ? results.join('\n') : 'NOT FOUND';
}
console.log("=== .top-bar ===");
console.log(extractCSS('.top-bar'));
console.log("\n=== .header ===");
console.log(extractCSS('.header'));
console.log("\n=== .page-title-container ===");
console.log(extractCSS('.page-title-container'));
console.log("\n=== .page-title ===");
console.log(extractCSS('.page-title'));
console.log("\n=== .breadcrumbs ===");
console.log(extractCSS('.breadcrumbs'));
console.log("\n=== .page-title-additional ===");
console.log(extractCSS('.page-title-additional'));

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

7
test-anti-alias.html Normal file
View File

@@ -0,0 +1,7 @@
<!DOCTYPE html>
<html>
<body style="background: #333; padding: 50px;">
<div style="width: 100px; height: 100px; background: radial-gradient(circle at 0 0, transparent 40px, #ffffff 40px); display: inline-block; margin-right: 20px;"></div>
<div style="width: 100px; height: 100px; background: radial-gradient(circle at 0 0, transparent 40px, #ffffff 40.5px); display: inline-block;"></div>
</body>
</html>

59
test-cutout.html Normal file
View File

@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<style>
body { background: #ccc; padding: 50px; }
.card {
position: relative;
width: 300px;
height: 200px;
background: #333;
border-radius: 25px;
overflow: hidden;
}
.iconWrapper {
position: absolute;
bottom: 0;
right: 0;
background-color: #FFFFFF;
border-top-left-radius: 30px;
padding: 10px 10px 0 10px;
z-index: 20;
display: flex;
align-items: center;
justify-content: center;
}
.iconWrapper::before {
content: "";
position: absolute;
top: -20px;
right: 0;
width: 20px;
height: 20px;
background: radial-gradient(circle at 0 0, transparent 20px, #ffffff 20px);
}
.iconWrapper::after {
content: "";
position: absolute;
bottom: 0;
left: -20px;
width: 20px;
height: 20px;
background: radial-gradient(circle at 0 0, transparent 20px, #ffffff 20px);
}
.button {
width: 52px;
height: 52px;
border-radius: 50%;
background: #111;
}
</style>
</head>
<body>
<div class="card">
<div class="iconWrapper">
<div class="button"></div>
</div>
</div>
</body>
</html>

11
test-svg.html Normal file
View File

@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<body>
<svg width="100" height="100" viewBox="0 0 20 20" style="border: 1px solid red;">
<path fill="black" d="M20,20 L20,0 A20,20 0 0,0 0,20 Z" />
</svg>
<svg width="100" height="100" viewBox="0 0 20 20" style="border: 1px solid blue;">
<path fill="black" d="M20,20 L20,0 A20,20 0 0,1 0,20 Z" />
</svg>
</body>
</html>

View File

@@ -15,7 +15,7 @@
"moduleResolution": "bundler", "moduleResolution": "bundler",
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"jsx": "preserve", "jsx": "react-jsx",
"incremental": true, "incremental": true,
"plugins": [ "plugins": [
{ {