update ai commerce section

This commit is contained in:
2026-07-23 10:26:49 +05:30
parent 4e0facc9af
commit a4328a791a
135 changed files with 4081 additions and 391 deletions

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "NODE_OPTIONS=--max-old-space-size=6144 next dev",
"build": "next build",
"start": "next start",
"lint": "eslint"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 431 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

View File

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

View File

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View File

Before

Width:  |  Height:  |  Size: 338 KiB

After

Width:  |  Height:  |  Size: 338 KiB

View File

Before

Width:  |  Height:  |  Size: 260 KiB

After

Width:  |  Height:  |  Size: 260 KiB

View File

Before

Width:  |  Height:  |  Size: 290 KiB

After

Width:  |  Height:  |  Size: 290 KiB

View File

@@ -0,0 +1,24 @@
<svg width="476" height="941" viewBox="0 0 476 941" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- Notch + status bar extracted verbatim from the provided iPhone SVG.
Rendered above the live app screen so the app sits under the notch,
exactly like real iOS. -->
<g clip-path="url(#clip0_312_252)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M388.5 25C387.119 25 386 26.1193 386 27.5V33C386 34.3807 387.119 35.5 388.5 35.5H404.469H405.5C406.881 35.5 408 34.3807 408 33V27.5C408 26.1193 406.881 25 405.5 25H388.5ZM389 26C387.895 26 387 26.8954 387 28V32.5C387 33.6046 387.895 34.5 389 34.5H403.469H405C406.105 34.5 407 33.6046 407 32.5V28C407 26.8954 406.105 26 405 26H389Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M409 32.374C409.863 32.152 410.5 31.3689 410.5 30.437C410.5 29.5051 409.863 28.722 409 28.5V32.374Z" fill="white"/>
<rect x="388" y="27" width="18" height="6.5" rx="1" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M373.33 26.6079C375.546 26.608 377.678 27.4594 379.283 28.9862C379.404 29.1041 379.598 29.1026 379.717 28.9829L380.873 27.8162C380.933 27.7555 380.967 27.6733 380.966 27.5877C380.966 27.5021 380.931 27.4202 380.87 27.3602C376.655 23.3207 370.005 23.3207 365.79 27.3602C365.729 27.4202 365.694 27.502 365.694 27.5876C365.693 27.6732 365.727 27.7555 365.787 27.8162L366.943 28.9829C367.062 29.1028 367.256 29.1043 367.377 28.9862C368.983 27.4593 371.114 26.6079 373.33 26.6079ZM373.33 30.4036C374.548 30.4035 375.722 30.856 376.624 31.6732C376.747 31.7892 376.939 31.7867 377.058 31.6676L378.212 30.5009C378.273 30.4397 378.307 30.3567 378.306 30.2704C378.305 30.1842 378.27 30.1018 378.208 30.0419C375.46 27.4855 371.204 27.4855 368.455 30.0419C368.393 30.1018 368.358 30.1842 368.357 30.2705C368.356 30.3568 368.39 30.4398 368.451 30.5009L369.605 31.6676C369.724 31.7867 369.917 31.7892 370.039 31.6732C370.941 30.8566 372.114 30.4041 373.33 30.4036ZM375.549 33.1879C375.611 33.1273 375.645 33.0439 375.643 32.9574C375.642 32.8709 375.604 32.7889 375.54 32.7309C374.265 31.652 372.396 31.652 371.121 32.7309C371.057 32.7889 371.019 32.8708 371.017 32.9573C371.015 33.0438 371.049 33.1272 371.111 33.1879L373.109 35.2036C373.167 35.2628 373.247 35.2961 373.33 35.2961C373.414 35.2961 373.494 35.2628 373.552 35.2036L375.549 33.1879Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M344.667 31.3334H345.667C346.219 31.3334 346.667 31.7811 346.667 32.3334V34.3334C346.667 34.8857 346.219 35.3334 345.667 35.3334H344.667C344.114 35.3334 343.667 34.8857 343.667 34.3334V32.3334C343.667 31.7811 344.114 31.3334 344.667 31.3334ZM349.333 29.3334H350.333C350.885 29.3334 351.333 29.7811 351.333 30.3334V34.3334C351.333 34.8857 350.885 35.3334 350.333 35.3334H349.333C348.781 35.3334 348.333 34.8857 348.333 34.3334V30.3334C348.333 29.7811 348.781 29.3334 349.333 29.3334ZM354 27.0001H355C355.552 27.0001 356 27.4478 356 28.0001V34.3334C356 34.8857 355.552 35.3334 355 35.3334H354C353.448 35.3334 353 34.8857 353 34.3334V28.0001C353 27.4478 353.448 27.0001 354 27.0001ZM358.667 24.6667H359.667C360.219 24.6667 360.667 25.1145 360.667 25.6667V34.3334C360.667 34.8857 360.219 35.3334 359.667 35.3334H358.667C358.114 35.3334 357.667 34.8857 357.667 34.3334V25.6667C357.667 25.1145 358.114 24.6667 358.667 24.6667Z" fill="white"/>
<g clip-path="url(#clip1_312_252)">
<path d="M85.1341 35.2563C87.8221 35.2563 89.4187 33.1543 89.4187 29.5874C89.4187 26.0864 87.7195 24.1675 85.1927 24.1675C82.8929 24.1675 81.2669 25.7129 81.2669 27.8735C81.2669 29.9023 82.7317 31.3818 84.7459 31.3818C85.9837 31.3818 86.9871 30.8105 87.4852 29.8071H87.6097C87.5877 32.29 86.7015 33.7109 85.1561 33.7109C84.2479 33.7109 83.5228 33.2129 83.2957 32.4072H81.4134C81.721 34.1284 83.2005 35.2563 85.1341 35.2563ZM85.2 29.9243C83.9695 29.9243 83.1199 29.0601 83.1199 27.8149C83.1199 26.6211 84.0135 25.7056 85.2073 25.7056C86.4012 25.7056 87.2947 26.6357 87.2947 27.8516C87.2947 29.0527 86.4231 29.9243 85.2 29.9243ZM92.4366 28.1592C93.1324 28.1592 93.6085 27.6758 93.6085 27.0239C93.6085 26.3721 93.1324 25.8887 92.4366 25.8887C91.7481 25.8887 91.2647 26.3721 91.2647 27.0239C91.2647 27.6758 91.7481 28.1592 92.4366 28.1592ZM92.4366 33.5352C93.1324 33.5352 93.6085 33.0444 93.6085 32.3999C93.6085 31.748 93.1324 31.2646 92.4366 31.2646C91.7481 31.2646 91.2647 31.748 91.2647 32.3999C91.2647 33.0444 91.7481 33.5352 92.4366 33.5352ZM100.611 35H102.42V32.9712H103.848V31.4111H102.42V24.4312H99.7538C98.3183 26.6138 96.8168 29.0454 95.4472 31.4258V32.9712H100.611V35ZM97.1977 31.3452C98.2304 29.5508 99.4535 27.5952 100.537 25.9399H100.64V31.4551H97.1977V31.3452ZM107.877 35H109.766V24.4312H107.884L105.123 26.3721V28.1519L107.752 26.2915H107.877V35Z" fill="white"/>
</g>
</g>
<path d="M138 5H338V23C338 31.2843 331.284 38 323 38H153C144.716 38 138 31.2843 138 23V5Z" fill="black"/>
<defs>
<clipPath id="clip0_312_252">
<rect width="375" height="44" fill="white" transform="translate(50 7)"/>
</clipPath>
<clipPath id="clip1_312_252">
<rect width="54" height="18" fill="white" transform="translate(71 21)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 5.0 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 463 KiB

View File

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 133 KiB

View File

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 135 KiB

View File

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

Before

Width:  |  Height:  |  Size: 431 KiB

After

Width:  |  Height:  |  Size: 431 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 MiB

After

Width:  |  Height:  |  Size: 2.0 MiB

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View File

Before

Width:  |  Height:  |  Size: 186 KiB

After

Width:  |  Height:  |  Size: 186 KiB

View File

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 203 KiB

View File

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

View File

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 109 KiB

View File

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 MiB

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

Before

Width:  |  Height:  |  Size: 188 KiB

After

Width:  |  Height:  |  Size: 188 KiB

View File

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 89 KiB

View File

Before

Width:  |  Height:  |  Size: 99 KiB

After

Width:  |  Height:  |  Size: 99 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 MiB

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 110 KiB

View File

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View File

Before

Width:  |  Height:  |  Size: 222 KiB

After

Width:  |  Height:  |  Size: 222 KiB

View File

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 101 KiB

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 MiB

After

Width:  |  Height:  |  Size: 2.2 MiB

View File

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View File

Before

Width:  |  Height:  |  Size: 2.5 MiB

After

Width:  |  Height:  |  Size: 2.5 MiB

View File

Before

Width:  |  Height:  |  Size: 186 KiB

After

Width:  |  Height:  |  Size: 186 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 MiB

After

Width:  |  Height:  |  Size: 2.1 MiB

View File

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

View File

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

View File

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 203 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -2,10 +2,10 @@ import React from "react";
import Image from "next/image";
import Link from "next/link";
import { MaterialIcon } from "@/components/ui/MaterialIcon";
import { PremiumPageShell } from "@/components/layout/PremiumPageShell";
import { PremiumPageShell } from "@/components/common/PremiumPageShell";
import { AboutHero } from "@/components/heroes/AboutHero";
import { AnimatedSection } from "@/components/motion/AnimatedSection";
import { AnimatedGrid, AnimatedCard } from "@/components/motion/AnimatedGrid";
import { AnimatedSection } from "@/components/animations/AnimatedSection";
import { AnimatedGrid, AnimatedCard } from "@/components/animations/AnimatedGrid";
import { FloatingDelivery } from "@/components/about/FloatingDelivery";
import type { Metadata } from "next";
@@ -20,7 +20,7 @@ const STRATEGY_CARDS = [
descr: "To help average stores perform like the great ones, not just by selling products, but by building a strong brand identity and real relationships with customers through Nearle.",
icon: "target",
iconClass: "bg-[#6330D6]/[0.07] text-[#6330D6] border-[#6330D6]/10",
image: "/images/nearle-how/how-storefront.webp",
image: "/images/workflow/how-storefront.webp",
imageAlt: "3D local store storefront with purple awning",
imgFit: "object-contain object-bottom"
},
@@ -29,7 +29,7 @@ const STRATEGY_CARDS = [
descr: "Our vision is to make every neighbourhood more connected by helping people discover, support, and shop from the local businesses around them.",
icon: "visibility",
iconClass: "bg-secondary/[0.07] text-secondary border-secondary/10",
image: "/images/nearle-merchant/local-map.webp",
image: "/images/stores/local-map.webp",
imageAlt: "Nearle local neighbourhood map",
imgFit: "object-cover object-center"
},
@@ -38,7 +38,7 @@ const STRATEGY_CARDS = [
descr: "Nearle is essential for a business to grow by leveraging the full potential of its neighbourhood. It is an indispensable tool for consumers to take advantage of what their neighbourhood has to offer.",
icon: "help_outline",
iconClass: "bg-[#6330D6]/10 text-[#6330D6] border-[#6330D6]/20",
image: "/images/app-mockup.webp",
image: "/images/platform/app-mockup.webp",
imageAlt: "Nearle app on a smartphone",
imgFit: "object-contain object-bottom"
}

View File

@@ -2,11 +2,11 @@ import React from "react";
import Image from "next/image";
import Link from "next/link";
import { MaterialIcon } from "@/components/ui/MaterialIcon";
import { PremiumPageShell } from "@/components/layout/PremiumPageShell";
import { PremiumPageShell } from "@/components/common/PremiumPageShell";
import { BrandsHero } from "@/components/heroes/BrandsHero";
import { FAQAccordion } from "@/components/ui/FAQAccordion";
import { AnimatedSection } from "@/components/motion/AnimatedSection";
import { AnimatedGrid, AnimatedCard } from "@/components/motion/AnimatedGrid";
import { AnimatedSection } from "@/components/animations/AnimatedSection";
import { AnimatedGrid, AnimatedCard } from "@/components/animations/AnimatedGrid";
import { CTABanner } from "@/components/ui/CTABanner";
import { NetworkBackground } from "@/components/brands/NetworkBackground";
import { PartnershipConnector } from "@/components/brands/PartnershipConnector";
@@ -199,7 +199,7 @@ export default function BrandsPage() {
{/* ─── Industries ─── */}
<section className="relative overflow-hidden py-10 md:py-14 xl:py-12 bg-[#FAF7FD] border-b border-[#6330D6]/10">
<Image
src="/d2c bg1.png"
src="/images/illustrations/d2c-bg1.png"
alt=""
fill
priority={false}
@@ -215,7 +215,7 @@ export default function BrandsPage() {
<div className="relative mx-auto h-[280px] w-full max-w-[420px] sm:h-[360px] lg:mx-0 lg:h-[440px]">
<div className="absolute left-0 top-0 h-[62%] w-[72%] overflow-hidden rounded-[28px] border-4 border-white shadow-[0_20px_50px_rgba(22,0,29,0.16)]">
<Image
src="/images/cat-daily-essentials.webp"
src="/images/stores/cat-daily-essentials.webp"
alt="Daily essentials like milk, bread, and fresh produce stocked on Nearle stores"
fill
sizes="(max-width: 1023px) 300px, 22vw"
@@ -224,7 +224,7 @@ export default function BrandsPage() {
</div>
<div className="absolute right-0 top-[6%] h-[42%] w-[52%] overflow-hidden rounded-[22px] border-4 border-white shadow-[0_16px_40px_rgba(22,0,29,0.14)]">
<Image
src="/images/cat-health-wellness.webp"
src="/images/stores/cat-health-wellness.webp"
alt="Health and personal care products stocked on Nearle stores"
fill
sizes="(max-width: 1023px) 220px, 16vw"
@@ -233,7 +233,7 @@ export default function BrandsPage() {
</div>
<div className="absolute bottom-0 left-[10%] h-[38%] w-[54%] overflow-hidden rounded-[22px] border-4 border-white shadow-[0_16px_40px_rgba(22,0,29,0.14)]">
<Image
src="/images/cat-pet-essentials.webp"
src="/images/stores/cat-pet-essentials.webp"
alt="Pet essentials brand stocked on Nearle stores"
fill
sizes="(max-width: 1023px) 220px, 16vw"
@@ -329,7 +329,7 @@ export default function BrandsPage() {
<div className="absolute -right-4 -bottom-4 h-24 w-24 rounded-full bg-secondary/20 blur-3xl -z-10" />
<div className="relative h-[220px] sm:h-[260px] rounded-[28px] overflow-hidden shadow-[0_20px_50px_rgba(22,0,29,0.16)]">
<Image
src="/images/nearle-merchant/success-owner.webp"
src="/images/stores/success-owner.webp"
alt="Neighbourhood store owner reviewing brand orders on his phone"
fill
sizes="(max-width: 1023px) 90vw, 360px"
@@ -373,7 +373,7 @@ export default function BrandsPage() {
"circle at 70% 30%, rgba(99,48,214,0.2), transparent 50%",
"circle at 20% 70%, rgba(0,109,55,0.12), transparent 45%",
]}
backgroundImage="/brand part.png"
backgroundImage="/images/illustrations/brand-part.png"
/>
</PremiumPageShell>
);

View File

@@ -2,11 +2,11 @@ import React from "react";
import Image from "next/image";
import Link from "next/link";
import { MaterialIcon } from "@/components/ui/MaterialIcon";
import { PremiumPageShell } from "@/components/layout/PremiumPageShell";
import { PremiumPageShell } from "@/components/common/PremiumPageShell";
import { BusinessFeaturesGrid } from "@/components/businesses/BusinessFeaturesGrid";
import { BusinessHero } from "@/components/heroes/BusinessHero";
import { AnimatedSection } from "@/components/motion/AnimatedSection";
import { AnimatedGrid, AnimatedCard } from "@/components/motion/AnimatedGrid";
import { AnimatedSection } from "@/components/animations/AnimatedSection";
import { AnimatedGrid, AnimatedCard } from "@/components/animations/AnimatedGrid";
import { CTABanner } from "@/components/ui/CTABanner";
import type { Metadata } from "next";
@@ -177,7 +177,7 @@ export default function BusinessesPage() {
<div className="relative z-0 mt-auto pt-5 h-[170px] lg:h-[185px] flex items-end justify-center">
<div className="relative h-[150px] w-[220px] lg:h-[175px] lg:w-[255px]">
<Image
src="/images/nearle-how/how-storefront.webp"
src="/images/workflow/how-storefront.webp"
alt="Local shop storefront with purple awning and now online board"
fill
sizes="(max-width: 768px) 50vw, 25vw"
@@ -234,7 +234,7 @@ export default function BusinessesPage() {
</div>
<div className="relative h-[150px] w-[190px] lg:h-[175px] lg:w-[215px] shrink-0">
<Image
src="/images/nearle-how/how-grocery-bag.webp"
src="/images/workflow/how-grocery-bag.webp"
alt="Nearle grocery bag filled with vegetables and packaged products"
fill
sizes="(max-width: 768px) 50vw, 25vw"

View File

@@ -1,8 +1,8 @@
import React from "react";
import { MaterialIcon } from "@/components/ui/MaterialIcon";
import { PremiumPageShell } from "@/components/layout/PremiumPageShell";
import { PremiumPageShell } from "@/components/common/PremiumPageShell";
import { ContactHero } from "@/components/heroes/ContactHero";
import { AnimatedSection } from "@/components/motion/AnimatedSection";
import { AnimatedSection } from "@/components/animations/AnimatedSection";
import type { Metadata } from "next";
export const metadata: Metadata = {

View File

@@ -1,7 +1,7 @@
import React from "react";
import Link from "next/link";
import { MaterialIcon } from "@/components/ui/MaterialIcon";
import { PremiumPageShell } from "@/components/layout/PremiumPageShell";
import { PremiumPageShell } from "@/components/common/PremiumPageShell";
import type { Metadata } from "next";
export const metadata: Metadata = {

View File

@@ -1,11 +1,11 @@
import React from "react";
import Link from "next/link";
import { MaterialIcon } from "@/components/ui/MaterialIcon";
import { PremiumPageShell } from "@/components/layout/PremiumPageShell";
import { PremiumPageShell } from "@/components/common/PremiumPageShell";
import { DeliveryHero } from "@/components/heroes/DeliveryHero";
import { FAQAccordion } from "@/components/ui/FAQAccordion";
import { AnimatedSection } from "@/components/motion/AnimatedSection";
import { AnimatedGrid, AnimatedCard } from "@/components/motion/AnimatedGrid";
import { AnimatedSection } from "@/components/animations/AnimatedSection";
import { AnimatedGrid, AnimatedCard } from "@/components/animations/AnimatedGrid";
import { AnimatedTimeline } from "@/components/delivery/AnimatedTimeline";
import { CTABanner } from "@/components/ui/CTABanner";
import type { Metadata } from "next";

View File

@@ -1040,3 +1040,18 @@ main {
border-radius: 1.25rem;
background-color: var(--brand-accent-light);
}
/* Reduced motion: Framer components are handled by <MotionConfig reducedMotion="user">.
This covers CSS-only motion it can't reach — Tailwind transitions/hover transforms
and the infinite keyframe loops (float, pulse-subtle, hero-bike-float, stroke-dash,
hero-map-drift). Near-instant rather than removed, so final states stay intact. */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}

View File

@@ -1,9 +1,9 @@
import type { Metadata, Viewport } from "next";
import { Lato } from "next/font/google";
import "./globals.css";
import { MotionProvider } from "@/components/layout/MotionProvider";
import { PremiumNavbar } from "@/components/layout/PremiumNavbar";
import { PremiumFooter } from "@/components/layout/PremiumFooter";
import { MotionProvider } from "@/components/common/MotionProvider";
import { PremiumNavbar } from "@/components/navbar/PremiumNavbar";
import { PremiumFooter } from "@/components/footer/PremiumFooter";
const lato = Lato({
subsets: ["latin"],
@@ -41,7 +41,7 @@ export const metadata: Metadata = {
type: "website",
images: [
{
url: "/logo.png",
url: "/logos/logo.png",
width: 512,
height: 512,
alt: "Nearle logo",
@@ -53,13 +53,13 @@ export const metadata: Metadata = {
title: "Nearle: Your Neighborhood, Delivered",
description:
"India's hyperlocal neighborhood commerce platform",
images: ["/logo.png"],
images: ["/logos/logo.png"],
},
alternates: { canonical: "/" },
icons: {
icon: "/favicon.ico",
shortcut: "/favicon.ico",
apple: "/apple-icon.png",
apple: "/icons/apple-icon.png",
},
robots: { index: true, follow: true },
};
@@ -78,7 +78,7 @@ const jsonLd = {
"@id": "https://nearle.in/#organization",
name: "Nearle",
url: "https://nearle.in",
logo: "https://nearle.in/logo.png",
logo: "https://nearle.in/logos/logo.png",
description:
"Nearle is an AI Commerce platform that digitizes neighbourhood stores — with AI catalogs by ProductLLM, QR ordering, and local discovery — instead of replacing them.",
sameAs: [
@@ -119,7 +119,7 @@ export default function RootLayout({
<MotionProvider>
<div className="min-h-screen bg-white font-body text-[#16001D] antialiased flex flex-col">
<PremiumNavbar />
<main className="w-full overflow-x-hidden bg-white">
<main className="w-full overflow-x-clip bg-white">
{children}
</main>
<PremiumFooter />

View File

@@ -1,11 +1,11 @@
import React from "react";
import Link from "next/link";
import { MaterialIcon } from "@/components/ui/MaterialIcon";
import { PremiumPageShell } from "@/components/layout/PremiumPageShell";
import { PremiumPageShell } from "@/components/common/PremiumPageShell";
import { MerchantsHero } from "@/components/heroes/MerchantsHero";
import { FAQAccordion } from "@/components/ui/FAQAccordion";
import { AnimatedSection } from "@/components/motion/AnimatedSection";
import { AnimatedGrid, AnimatedCard } from "@/components/motion/AnimatedGrid";
import { AnimatedSection } from "@/components/animations/AnimatedSection";
import { AnimatedGrid, AnimatedCard } from "@/components/animations/AnimatedGrid";
import { CTABanner } from "@/components/ui/CTABanner";
import type { Metadata } from "next";

View File

@@ -1,18 +1,21 @@
import type { Metadata } from "next";
import { PremiumPageShell } from "@/components/layout/PremiumPageShell";
import { PremiumPageShell } from "@/components/common/PremiumPageShell";
import { Hero } from "@/components/home/Hero";
import { VoiceCommerceExperience } from "@/components/home/VoiceCommerceExperience";
import { StoreJourney } from "@/components/home/experience/StoreJourney";
import { ServiceCategories } from "@/components/home/ServiceCategories";
import { WhyNearle } from "@/components/home/WhyNearle";
import { HowItWorks } from "@/components/home/HowItWorks";
import { HyperlocalFeatures } from "@/components/home/HyperlocalFeatures";
import { BusinessSection } from "@/components/home/BusinessSection";
import { WhyAICommerceWins } from "@/components/home/WhyAICommerceWins";
import { AICommerceTeaser } from "@/components/home/AICommerceTeaser";
import { StoreQRSection } from "@/components/home/StoreQRSection";
export const metadata: Metadata = {
title: "AI Commerce Platform for Neighbourhood Stores",
description:
"Nearle is the AI Commerce platform that digitizes neighbourhood stores instead of replacing them. AI catalogs by ProductLLM, QR ordering, and local discovery — commerce that runs on your neighbourhood.",
"Nearle digitizes the neighbourhood stores you already trust. Shop from nearby merchants, let Nearle AI find products by natural language, and get orders packed by the shopkeeper and delivered by a Nearle rider.",
openGraph: {
title: "Nearle — AI Commerce Platform for Neighbourhood Stores",
description:
@@ -26,12 +29,15 @@ export default function HomePage() {
return (
<PremiumPageShell>
<Hero />
<VoiceCommerceExperience />
<StoreJourney />
<ServiceCategories />
<WhyNearle />
<HowItWorks />
<HyperlocalFeatures />
<BusinessSection />
<WhyAICommerceWins />
<AICommerceTeaser />
<StoreQRSection />
</PremiumPageShell>
);

View File

@@ -1,12 +1,12 @@
import React from "react";
import Image from "next/image";
import { MaterialIcon } from "@/components/ui/MaterialIcon";
import { PremiumPageShell } from "@/components/layout/PremiumPageShell";
import { PremiumPageShell } from "@/components/common/PremiumPageShell";
import { PeopleHero } from "@/components/heroes/PeopleHero";
import { AnimatedSection } from "@/components/motion/AnimatedSection";
import { AnimatedGrid, AnimatedCard } from "@/components/motion/AnimatedGrid";
import { AnimatedSection } from "@/components/animations/AnimatedSection";
import { AnimatedGrid, AnimatedCard } from "@/components/animations/AnimatedGrid";
import { AnimatedTimeline } from "@/components/delivery/AnimatedTimeline";
import { siteContent } from "@/config/site-content";
import { siteContent } from "@/constants/site-content";
import type { Metadata } from "next";
export const metadata: Metadata = {
@@ -79,7 +79,7 @@ const OFFERINGS = [
descr: "Enjoy the comfort of elegant living. Nearle is India's first hyper-local managed platform bringing all amenities and requirements directly to your fingertips.",
icon: "local_florist",
color: "from-purple-500/10 to-indigo-500/10 text-primary border-purple-100",
image: "/nearle-people.webp",
image: "/images/hero/nearle-people.webp",
isWide: false
},
{
@@ -88,7 +88,7 @@ const OFFERINGS = [
descr: "Pick hot deals within your neighbourhood. Stay updated on localized sales, discounts, and flash promotions happening today.",
icon: "local_activity",
color: "from-amber-500/10 to-orange-500/10 text-amber-700 border-amber-100",
image: "/images/app-mockup.webp",
image: "/images/platform/app-mockup.webp",
isWide: false
},
{
@@ -97,7 +97,7 @@ const OFFERINGS = [
descr: "Enjoy the ease of the World Wide Web, fulfilled entirely by trusted local businesses. Avoid traffic lights, parking hassles, and pollution.",
icon: "travel_explore",
color: "from-green-500/10 to-emerald-500/10 text-secondary border-green-100",
image: "/super.png",
image: "/images/illustrations/super.png",
isWide: false
},
{
@@ -106,7 +106,7 @@ const OFFERINGS = [
descr: "Enjoy safe, convenient shopping with custom pricing, resident promotions, and bulk order discounts negotiated for your community.",
icon: "shopping_bag",
color: "from-rose-500/10 to-pink-500/10 text-rose-700 border-rose-100",
image: "/images/cat-pet-essentials.webp",
image: "/images/stores/cat-pet-essentials.webp",
isWide: false
},
{
@@ -115,7 +115,7 @@ const OFFERINGS = [
descr: "Order everything you need in your neighborhood with a single tap. A fast, organized last-mile delivery network ensures prompt fulfillment.",
icon: "touch_app",
color: "from-sky-500/10 to-blue-500/10 text-sky-700 border-sky-100",
image: "/about.webp",
image: "/images/hero/about.webp",
isWide: true
},
{
@@ -124,7 +124,7 @@ const OFFERINGS = [
descr: "Get your fresh fruits, farm-fresh vegetables, dairy, and grocery items delivered instantly from verified local green grocers.",
icon: "eco",
color: "from-emerald-500/10 to-teal-500/10 text-emerald-700 border-emerald-100",
image: "/images/cat-daily-essentials.webp",
image: "/images/stores/cat-daily-essentials.webp",
isWide: false
},
{
@@ -133,7 +133,7 @@ const OFFERINGS = [
descr: "Choose from the best local restaurants and neighborhood eateries close to your home. Hot food delivered with relevance and speed.",
icon: "restaurant",
color: "from-orange-500/10 to-red-500/10 text-orange-700 border-orange-100",
image: "/images/cat-hot-food.webp",
image: "/images/stores/cat-hot-food.webp",
isWide: false
},
{
@@ -142,7 +142,7 @@ const OFFERINGS = [
descr: "Access custom-tailored local neighborhood services designed to integrate convenience directly into residential society living.",
icon: "stars",
color: "from-violet-500/10 to-purple-500/10 text-violet-700 border-violet-100",
image: "/images/cat-health-wellness.webp",
image: "/images/stores/cat-health-wellness.webp",
isWide: false
},
{
@@ -151,7 +151,7 @@ const OFFERINGS = [
descr: "Book certified local service providers at your convenience. From handymen to laundry, pet care to pharmacy delivery, all in one place.",
icon: "construction",
color: "from-cyan-500/10 to-blue-500/10 text-cyan-700 border-cyan-100",
image: "/images/cat-home-services.webp",
image: "/images/stores/cat-home-services.webp",
isWide: false
}
];

View File

@@ -1,5 +1,5 @@
import type { Metadata } from "next";
import { PremiumPageShell } from "@/components/layout/PremiumPageShell";
import { PremiumPageShell } from "@/components/common/PremiumPageShell";
import { PlatformHero } from "@/components/platform/PlatformHero";
import { PlatformArchitecture } from "@/components/platform/PlatformArchitecture";
import { ProductFeatureGrid } from "@/components/platform/ProductFeatureGrid";

View File

@@ -1,7 +1,7 @@
import React from "react";
import Link from "next/link";
import { MaterialIcon } from "@/components/ui/MaterialIcon";
import { PremiumPageShell } from "@/components/layout/PremiumPageShell";
import { PremiumPageShell } from "@/components/common/PremiumPageShell";
import type { Metadata } from "next";
export const metadata: Metadata = {

View File

@@ -1,7 +1,7 @@
import React from "react";
import Link from "next/link";
import { MaterialIcon } from "@/components/ui/MaterialIcon";
import { PremiumPageShell } from "@/components/layout/PremiumPageShell";
import { PremiumPageShell } from "@/components/common/PremiumPageShell";
import type { Metadata } from "next";
export const metadata: Metadata = {

View File

@@ -1,5 +1,5 @@
import type { Metadata } from "next";
import { PremiumPageShell } from "@/components/layout/PremiumPageShell";
import { PremiumPageShell } from "@/components/common/PremiumPageShell";
import { WhyNearleHero } from "@/components/why-nearle/WhyNearleHero";
import { CommerceEvolution } from "@/components/why-nearle/CommerceEvolution";
import { AICommerceExplainer } from "@/components/why-nearle/AICommerceExplainer";

View File

@@ -13,7 +13,7 @@ export function FloatingDelivery() {
transition={{ duration: 6, ease: "easeInOut", repeat: Infinity }}
>
<Image
src="/images/nearle-redesign/delivery-doorstep.webp"
src="/images/illustrations/delivery-doorstep.webp"
alt=""
width={220}
height={220}

View File

@@ -427,7 +427,7 @@ export function BusinessFeaturesGrid() {
>
<div className="relative h-[88%] w-full -translate-x-[2%]">
<Image
src="/superhero.png"
src="/images/illustrations/superhero.png"
alt=""
fill
sizes="600px"

View File

@@ -125,7 +125,7 @@ export function PremiumFooter() {
<motion.div variants={fadeUp} className="flex flex-col gap-5">
<Link href="/" className="inline-block w-fit">
<Image
src="/logo-light.png"
src="/logos/logo-light.png"
alt="Nearle"
width={240}
height={60}

View File

@@ -40,7 +40,7 @@ export function AboutHero() {
{/* Background image — scooter anchored to the right */}
<Image
src="/about.webp"
src="/images/hero/about.webp"
alt=""
fill
sizes="100vw"

View File

@@ -40,7 +40,7 @@ export function BrandsHero() {
transition={{ duration: 3, ease: "easeOut" }}
>
<Image
src="/Gemini_Generated_Image_lxh416lxh416lxh4.png"
src="/images/illustrations/gemini-generated-image.png"
alt=""
fill
sizes="100vw"

View File

@@ -34,7 +34,7 @@ export function BusinessHero() {
<section className="w-full flex flex-col select-none bg-white">
<div className="relative overflow-hidden border-b border-[#6330D6]/10 bg-[#FAF8FC]">
<Image
src="/images/business1.webp"
src="/images/hero/business1.webp"
alt=""
fill
sizes="100vw"

View File

@@ -55,7 +55,7 @@ export function ContactHero() {
return (
<section className="relative overflow-hidden border-b border-[#6330D6]/10 bg-[#FAF8FC] min-h-[560px] md:min-h-[85vh] px-4 py-10 md:px-6 md:py-12 lg:px-8 lg:py-14 xl:px-10 xl:py-16 2xl:px-12 2xl:py-20">
<Image
src="/contact-page1.webp"
src="/images/hero/contact-page1.webp"
alt=""
fill
sizes="100vw"

View File

@@ -39,7 +39,7 @@ export function DeliveryHero() {
<section className="w-full flex flex-col select-none bg-white">
<div className="relative overflow-hidden border-b border-[#6330D6]/10 bg-[#FAF8FC]">
<Image
src="/delivery.png"
src="/images/workflow/delivery.png"
alt=""
fill
sizes="100vw"

View File

@@ -51,7 +51,7 @@ export function HeroLogo({ align = "center", spacing = "default" }: HeroLogoProp
transition={{ duration: 1, delay: 0.2, ease: EASE_LOGO }}
>
<Image
src="/nerale (1).png"
src="/images/illustrations/nerale.png"
alt="Nearle"
width={465}
height={384}

View File

@@ -39,7 +39,7 @@ export function MerchantsHero() {
<section className="w-full flex flex-col select-none bg-white">
<div className="relative overflow-hidden border-b border-[#6330D6]/10 bg-[#FAF8FC]">
<Image
src="/merchant.png"
src="/images/stores/merchant.png"
alt=""
fill
sizes="100vw"

View File

@@ -34,7 +34,7 @@ export function PeopleHero() {
<section className="w-full flex flex-col select-none bg-white">
<div className="relative overflow-hidden border-b border-[#6330D6]/10 bg-[#FAF8FC]">
<Image
src="/images/people1.webp"
src="/images/hero/people1.webp"
alt=""
fill
sizes="100vw"

View File

@@ -0,0 +1,126 @@
"use client";
import Link from "next/link";
import { motion, useReducedMotion } from "framer-motion";
import { MaterialIcon } from "@/components/ui/MaterialIcon";
import { fadeUp, staggerContainer, staggerCards, viewport, viewport20 } from "@/lib/animations";
const EASE = [0.22, 1, 0.36, 1] as [number, number, number, number];
const ROWS = [
{ traditional: "Manual discovery", nearle: "AI discovery" },
{ traditional: "Walk into stores", nearle: "Search nearby instantly" },
{ traditional: "Limited visibility", nearle: "Every local merchant discoverable" },
{ traditional: "Static catalogue", nearle: "AI-organized catalogue" },
];
const rowVariant = {
hidden: { opacity: 0, y: 14 },
visible: { opacity: 1, y: 0, transition: { duration: 0.45, ease: EASE } },
};
// Priority 4: a compact teaser contrasting traditional commerce with Nearle's
// AI commerce. The full seven-row comparison lives on /why-nearle.
export function AICommerceTeaser() {
const reduce = useReducedMotion();
return (
<section className="section section-soft w-full overflow-hidden border-y border-[#6330D6]/10">
<div className="page-container">
<motion.div
variants={staggerContainer}
initial="hidden"
whileInView="visible"
viewport={viewport}
className="mx-auto max-w-[680px] text-center"
>
<motion.span
variants={fadeUp}
className="inline-flex items-center rounded-full bg-[#6330D6]/[0.08] px-3.5 py-1 text-xs font-black uppercase tracking-widest text-[#6330D6]"
>
The Shift
</motion.span>
<motion.h2
variants={fadeUp}
className="mt-4 font-display font-black tracking-tight text-[#16001D]"
style={{ fontSize: "clamp(28px, 3vw, 44px)", lineHeight: 1.1 }}
>
Traditional commerce, reimagined by AI
</motion.h2>
</motion.div>
<div className="mx-auto mt-10 max-w-[860px]">
{/* Column headers */}
<div className="grid grid-cols-2 gap-3 px-1 sm:gap-4">
<span className="text-[11px] font-black uppercase tracking-widest text-[#6D6172] sm:text-xs">
Traditional Commerce
</span>
<span className="pl-2 text-[11px] font-black uppercase tracking-widest text-[#6330D6] sm:text-xs">
Nearle AI Commerce
</span>
</div>
<motion.div
variants={staggerCards}
initial="hidden"
whileInView="visible"
viewport={viewport20}
className="mt-3 flex flex-col gap-3"
>
{ROWS.map((row) => (
<motion.div
key={row.nearle}
variants={rowVariant}
className="grid grid-cols-2 gap-3 sm:gap-4"
>
{/* Traditional side */}
<div className="flex items-center gap-2.5 rounded-2xl border border-[#6330D6]/8 bg-white px-4 py-3.5 shadow-[0_4px_16px_rgba(22,0,29,0.03)]">
<span className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-[#F3F3F6] text-[#6D6172]">
<MaterialIcon icon="remove" size={14} />
</span>
<span className="text-[13px] font-semibold text-[#5E5866] sm:text-[15px]">
{row.traditional}
</span>
</div>
{/* Nearle side */}
<div className="flex items-center gap-2.5 rounded-2xl border border-[#6330D6]/20 bg-[linear-gradient(135deg,#ffffff_0%,#fbf7ff_55%,#f1e8fb_100%)] px-4 py-3.5 shadow-[0_4px_20px_rgba(99,48,214,0.08)]">
<motion.span
className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-[#DCFCE7] text-[#16A34A]"
animate={reduce ? {} : { scale: [1, 1.12, 1] }}
transition={{ repeat: Infinity, duration: 2.4, ease: "easeInOut" }}
>
<MaterialIcon icon="check" size={13} />
</motion.span>
<span className="text-[13px] font-bold text-[#16001D] sm:text-[15px]">
{row.nearle}
</span>
</div>
</motion.div>
))}
</motion.div>
<motion.div
variants={fadeUp}
initial="hidden"
whileInView="visible"
viewport={viewport}
className="mt-8 flex justify-center"
>
<Link
href="/why-nearle"
className="group inline-flex items-center gap-2 text-base font-black text-[#6330D6] transition-colors hover:text-[#4C1D95]"
>
Learn More
<MaterialIcon
icon="arrow_forward"
size={20}
className="transition-transform duration-200 group-hover:translate-x-1"
/>
</Link>
</motion.div>
</div>
</div>
</section>
);
}

View File

@@ -11,7 +11,7 @@ const FEATURES = [
title: "AI Catalogue",
desc: "Turn your shelf into a live online catalogue with ProductLLM — no manual data entry.",
icon: "menu_book",
visual: "/images/nearle-merchant/catalogue-ui.webp",
visual: "/images/stores/catalogue-ui.webp",
alt: "Clean grocery catalogue interface preview",
tone: "bg-primary/8 text-primary",
},
@@ -19,7 +19,7 @@ const FEATURES = [
title: "QR Ordering",
desc: "Let customers scan, browse, and place orders directly from your store.",
icon: "qr_code",
visual: "/images/nearle-merchant/qr-stand.webp",
visual: "/images/stores/qr-stand.webp",
alt: "QR ordering stand on a local grocery store counter",
tone: "bg-secondary/8 text-secondary",
},
@@ -27,7 +27,7 @@ const FEATURES = [
title: "Local Discovery",
desc: "Get discovered by nearby customers searching for products you sell.",
icon: "location_on",
visual: "/images/nearle-merchant/local-map.webp",
visual: "/images/stores/local-map.webp",
alt: "Local discovery map with purple pins and a store listing",
tone: "bg-[#de96f9]/10 text-primary",
},
@@ -35,7 +35,7 @@ const FEATURES = [
title: "Delivery Support",
desc: "Deliver orders easily with your own staff or trusted local delivery partners.",
icon: "local_shipping",
visual: "/images/nearle-merchant/delivery-support.webp",
visual: "/images/stores/delivery-support.webp",
alt: "Local delivery partner handing a grocery bag to a customer",
tone: "bg-rose-500/5 text-rose-600",
},
@@ -105,7 +105,7 @@ function LocalDiscoveryVisual() {
{/* Store Card (Right Side) */}
<div className="absolute bottom-4 right-4 z-30 w-[200px] overflow-hidden rounded-[1.25rem] bg-white shadow-[0_12px_32px_rgba(22,0,29,0.12)] border border-primary/10 sm:bottom-6 sm:right-6 sm:w-[240px]">
<div className="relative h-[90px] w-full bg-brand-accent-light sm:h-[110px]">
<Image src="/images/nearle-merchant/success-owner.webp" alt="Owner" fill className="object-cover" />
<Image src="/images/stores/success-owner.webp" alt="Owner" fill className="object-cover" />
</div>
<div className="p-3.5 sm:p-4">
<p className="truncate text-[13px] font-black text-brand-dark sm:text-[15px]">Kumar Provision Store</p>
@@ -279,7 +279,7 @@ export function BusinessSection() {
>
<div className="relative min-h-[128px] overflow-hidden bg-brand-accent-light">
<Image
src="/images/nearle-merchant/success-owner.webp"
src="/images/stores/success-owner.webp"
alt="Indian grocery shop owner using a smartphone inside a kirana store"
fill
sizes="100px"

View File

@@ -89,7 +89,7 @@ export function Hero() {
transition={{ duration: 3, ease: "easeOut" }}
>
<Image
src="/images/home1.webp"
src="/images/hero/home1.webp"
alt=""
fill
sizes="100vw"

View File

@@ -3,37 +3,8 @@
import Image from "next/image";
import { motion } from "framer-motion";
import { MaterialIcon } from "@/components/ui/MaterialIcon";
import {
fadeUp,
scaleIn,
staggerContainer,
slideInLeft,
viewport,
} from "@/lib/animations";
const STEPS = [
{
num: "01",
icon: "storefront",
title: "Get Online",
desc: "Introduce your business to your Neighbourhood. Compete with online businesses through your offline store.",
visual: "store",
},
{
num: "02",
icon: "campaign",
title: "Get Noticed",
desc: "Your products get published to Nearle customers in your neighbourhood through the app. Customers search based on location, products, discounts, and promos.",
visual: "phone",
},
{
num: "03",
icon: "auto_awesome",
title: "Get Simplified",
desc: "Delight the community with a personalized online experience. Unlock revenue opportunities and marketing strategies that help your business grow further.",
visual: "bag",
},
];
import { fadeUp, scaleIn, slideInLeft, viewport } from "@/lib/animations";
import { MerchantJourney } from "@/components/home/merchant/MerchantJourney";
function OrdersCard() {
return (
@@ -109,169 +80,9 @@ function GrowthPill() {
);
}
function PhoneMapVisual() {
return (
<div className="relative flex h-full w-full items-center justify-center">
<div className="absolute bottom-1 h-6 w-32 rounded-full bg-brand-dark/20 blur-xl" />
{/* REALISTIC MOBILE DEVICE FRAME */}
<div className="relative aspect-[140/280] h-[95%] min-h-[240px] max-h-[280px] rounded-[24px] bg-[linear-gradient(145deg,#d1d5db_0%,#4b5563_15%,#111827_85%,#4b5563_100%)] p-[2px] shadow-[0_20px_50px_rgba(22,0,29,0.25),0_0_0_1px_rgba(0,0,0,0.1),inset_0_0_2px_rgba(255,255,255,0.4)]">
{/* Hardware Buttons */}
<div className="absolute -left-[2px] top-[18%] h-4 w-[2px] rounded-l bg-gradient-to-r from-[#9ca3af] to-[#374151] shadow-sm" />
<div className="absolute -left-[2px] top-[26%] h-7 w-[2px] rounded-l bg-gradient-to-r from-[#9ca3af] to-[#374151] shadow-sm" />
<div className="absolute -left-[2px] top-[34%] h-7 w-[2px] rounded-l bg-gradient-to-r from-[#9ca3af] to-[#374151] shadow-sm" />
<div className="absolute -right-[2px] top-[28%] h-9 w-[2px] rounded-r bg-gradient-to-l from-[#9ca3af] to-[#374151] shadow-sm" />
{/* Inner Black Bezel */}
<div className="relative h-full w-full overflow-hidden rounded-[22px] bg-black p-[4px] shadow-[inset_0_0_4px_rgba(255,255,255,0.1)]">
{/* Inner Screen */}
<div className="relative h-full w-full overflow-hidden rounded-[18px] bg-[#FAF8FC] shadow-[inset_0_0_8px_rgba(0,0,0,0.05)]">
{/* Dynamic Island */}
<div className="absolute left-1/2 top-1.5 z-50 flex h-[12px] w-[38px] -translate-x-1/2 items-center justify-end rounded-full bg-black px-1 shadow-[inset_0_-1px_1px_rgba(255,255,255,0.1)] ring-[0.5px] ring-white/10">
<div className="relative h-[6px] w-[6px] overflow-hidden rounded-full bg-[#050515] shadow-[inset_0_0_1px_rgba(255,255,255,0.2)]">
<div className="absolute right-0 top-0 h-[3px] w-[3px] rounded-full bg-blue-400/30 blur-[0.5px]" />
</div>
</div>
{/* Status Bar */}
<div className="absolute inset-x-0 top-0 z-40 flex items-center justify-between px-3 pt-2 text-[5px] font-black text-brand-dark">
<span className="tracking-tighter">9:41</span>
<div className="flex items-center gap-[2px] opacity-80">
{/* Signal */}
<div className="flex items-end gap-[0.5px]">
<div className="h-[3px] w-[1px] rounded-full bg-brand-dark" />
<div className="h-[4px] w-[1px] rounded-full bg-brand-dark" />
<div className="h-[5px] w-[1px] rounded-full bg-brand-dark" />
<div className="h-[6px] w-[1px] rounded-full bg-brand-dark/30" />
</div>
{/* Wifi */}
<svg width="6" height="6" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 21C11.5 21 11.1 20.9 10.7 20.6C8 18.2 4.4 17.5 1.4 18.3C0.8 18.5 0.2 18.1 0 17.5C-0.2 16.9 0.2 16.3 0.8 16.1C4.8 15 9.4 15.9 12.8 18.9C13.2 19.3 13.3 19.9 12.9 20.3C12.7 20.8 12.3 21 12 21Z" />
<path d="M12 16C11.6 16 11.2 15.9 10.9 15.7C5.3 12.2 0.4 14 0.3 14C-0.3 14.2 -0.8 13.9 -0.9 13.3C-1.1 12.7 -0.8 12.2 -0.2 12.1C0.2 11.9 5.9 9.8 12 13.7C12.5 14 12.6 14.6 12.3 15.1C12.2 15.7 12 16 12 16Z" opacity="0.7"/>
</svg>
{/* Battery */}
<div className="relative flex h-[5px] w-[10px] items-center rounded-[1.5px] border-[1px] border-brand-dark/80 p-[0.5px]">
<div className="h-full w-[80%] rounded-[0.5px] bg-brand-dark" />
<div className="absolute -right-[1.5px] top-1/2 h-[2px] w-[1px] -translate-y-1/2 rounded-r-[0.5px] bg-brand-dark/80" />
</div>
</div>
</div>
{/* Map Visual Content */}
<div className="absolute inset-0 top-3 bg-[linear-gradient(145deg,#FAF8FC,#F1E7F8)]">
<svg className="absolute inset-0 h-full w-full" viewBox="0 0 140 255" fill="none" aria-hidden="true" preserveAspectRatio="xMidYMid slice">
<rect width="140" height="255" fill="#FAF8FC" />
<path d="M-20 50C12 40 41 42 64 54C91 68 112 64 158 48" stroke="#E3D9EA" strokeWidth="8" strokeLinecap="round" />
<path d="M-18 178C24 158 51 164 78 179C102 192 124 192 158 174" stroke="#DDF0E3" strokeWidth="14" strokeLinecap="round" opacity="0.75" />
<path d="M24 -20L35 282" stroke="#E9E2F0" strokeWidth="5" strokeLinecap="round" />
<path d="M83 -24L73 280" stroke="#DED4E8" strokeWidth="5" strokeLinecap="round" />
<path d="M126 -16L112 268" stroke="#E9E2F0" strokeWidth="5" strokeLinecap="round" />
<path d="M-18 72H158" stroke="#E7DFEE" strokeWidth="5" strokeLinecap="round" />
<path d="M-18 122H158" stroke="#DED5E8" strokeWidth="5" strokeLinecap="round" />
<path d="M-18 212H158" stroke="#E9E2F0" strokeWidth="5" strokeLinecap="round" />
<path d="M-12 244L150 28" stroke="#E6DEED" strokeWidth="5" strokeLinecap="round" />
<path d="M6 180C35 155 48 130 70 117C92 104 108 91 125 70" stroke="#7C3AED" strokeWidth="1.8" strokeDasharray="3 5" strokeLinecap="round" opacity="0.55" />
<path d="M70 117C47 103 30 92 14 73" stroke="#006D37" strokeWidth="1.6" strokeDasharray="3 5" strokeLinecap="round" opacity="0.38" />
</svg>
{[
["left-[17%] top-[30%]", "bg-primary"],
["right-[16%] top-[28%]", "bg-[#006D37]"],
["left-[20%] bottom-[33%]", "bg-[#006D37]"],
["right-[18%] bottom-[32%]", "bg-primary"],
["right-[35%] top-[20%]", "bg-primary"],
].map(([position, color]) => (
<div key={position} className={`absolute ${position} z-10`}>
<div className={`relative h-4 w-4 -rotate-45 rounded-[50%_50%_50%_10%] ${color} shadow-[0_4px_8px_rgba(22,0,29,0.12)]`}>
<div className="absolute left-1/2 top-1/2 h-1.5 w-1.5 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white" />
</div>
</div>
))}
<div className="absolute left-1/2 top-[38%] z-20 -translate-x-1/2 -translate-y-1/2">
<div className="absolute left-1/2 top-[82%] h-8 w-14 -translate-x-1/2 rounded-full bg-primary/18 blur-sm" />
<div className="relative h-12 w-12 -rotate-45 rounded-[50%_50%_50%_12%] bg-[linear-gradient(135deg,#8B5CF6,#65149A)] shadow-[0_10px_20px_rgba(101,20,154,0.30)]">
<div className="absolute left-1/2 top-1/2 h-5 w-5 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white" />
</div>
</div>
<div className="absolute bottom-2 left-2 right-2 z-30 rounded-xl bg-white/94 p-2 shadow-[0_8px_20px_rgba(22,0,29,0.12)] backdrop-blur">
<p className="truncate text-[8.5px] font-black leading-none text-brand-dark">Your Store</p>
<div className="mt-1 flex flex-wrap items-center gap-x-1 gap-y-0.5 text-[6.5px] font-bold text-on-surface-variant">
<span className="inline-flex items-center gap-[1.5px]">
<MaterialIcon icon="star" size={8} fill className="text-amber-500" />
4.8
</span>
<span className="font-black text-[#006D37]">Open</span>
<span>0.8 km</span>
</div>
</div>
</div>
</div>
</div>
<div className="absolute -left-7 top-[29%] z-40 rounded-full bg-white px-2.5 py-1 text-[8px] font-black text-[#006D37] shadow-[0_8px_16px_rgba(22,0,29,0.12)] ring-1 ring-[#006D37]/10">
Offers
</div>
<div className="absolute -right-6 top-[43%] z-40 rounded-full bg-primary px-2.5 py-1 text-[8px] font-black text-white shadow-[0_8px_16px_rgba(101,20,154,0.20)]">
Shop
</div>
</div>
</div>
);
}
function StepVisual({ type }: { type: string }) {
if (type === "store") {
return (
<div className="absolute inset-x-4 bottom-0 top-2">
<div className="relative h-full w-full">
<Image
src="/images/nearle-how/how-storefront.webp"
alt="3D local shop storefront with purple awning and now online board"
fill
sizes="(max-width: 768px) 80vw, 28vw"
className="object-contain object-bottom"
/>
</div>
</div>
);
}
if (type === "phone") {
return (
<div className="flex h-full items-center justify-center">
<PhoneMapVisual />
</div>
);
}
return (
<div className="flex h-full items-end justify-end gap-2 px-2">
<div className="mb-4 hidden shrink-0 space-y-2 sm:block">
{["Offers & Discounts", "Loyal Customers", "Repeat Orders"].map((chip) => (
<div key={chip} className="rounded-full border border-primary/10 bg-white px-3 py-2 text-[11px] font-black text-brand-dark shadow-sm">
{chip}
</div>
))}
</div>
<div className="relative h-40 w-36 shrink-0">
<Image
src="/images/nearle-how/how-grocery-bag.webp"
alt="Nearle grocery bag filled with vegetables and packaged products"
fill
sizes="(max-width: 768px) 60vw, 18vw"
className="object-contain object-bottom"
/>
</div>
</div>
);
}
export function HowItWorks() {
return (
<>
<section className="section bg-white w-full overflow-hidden">
{/* HERO AREA */}
<div className="mx-auto w-[calc(100%-96px)] max-w-[1720px]">
@@ -316,7 +127,7 @@ export function HowItWorks() {
<div className="relative w-full max-w-[680px]">
<div className="relative h-[280px] overflow-hidden rounded-[2rem] bg-brand-accent-light shadow-[0_26px_70px_rgba(22,0,29,0.16)] md:h-[440px] xl:h-[400px]">
<Image
src="/images/nearle-merchant/merchant-hero.webp"
src="/images/stores/merchant-hero.webp"
alt="Indian kirana-store owner using a laptop inside a grocery shop"
fill
sizes="(max-width: 1024px) 100vw, 50vw"
@@ -336,62 +147,32 @@ export function HowItWorks() {
<div className="mx-auto mt-10 w-[calc(100%-96px)] max-w-[1720px] md:mt-14 xl:mt-10">
<div className="h-px w-full bg-gradient-to-r from-transparent via-primary/10 to-transparent" />
</div>
</section>
{/* CARDS SECTION */}
<div className="mx-auto w-full max-w-[2200px] px-6 lg:px-10 xl:px-12">
{/* MERCHANT JOURNEY — self-contained cinematic showcase (auto-plays in
place; no sticky pin, so no empty scroll-track). */}
<section className="bg-white pb-20 pt-12 md:pb-28 md:pt-16">
<motion.div
className="mt-10 text-center md:mt-14 xl:mt-10"
className="mx-auto max-w-3xl px-6 text-center"
variants={fadeUp}
initial="hidden"
whileInView="visible"
viewport={viewport}
>
<span className="inline-flex rounded-full bg-primary/8 px-4 py-2 text-xs font-black uppercase tracking-widest text-primary">
How It Works
Merchant Journey
</span>
<h2 className="mt-5 font-display text-4xl font-black leading-tight tracking-tight text-brand-dark md:text-5xl lg:text-[54px]">
Build Your Neighbourhood Brand
From your shelf to a growing business
</h2>
<p className="mx-auto mt-4 max-w-2xl text-base leading-relaxed text-on-surface-variant md:text-lg">
Three simple milestones to scale your retail reach from offline streets straight into neighbourhood homes.
Eight steps, powered by AI. Join once, and Nearle turns your shelf into a
discoverable storefront while you stay at the centre of every order.
</p>
</motion.div>
<motion.div
className="mt-10 grid min-w-0 grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3"
variants={staggerContainer}
initial="hidden"
whileInView="visible"
viewport={viewport}
>
{STEPS.map((step) => (
<motion.article
key={step.num}
variants={fadeUp}
whileHover={{ y: -6, transition: { duration: 0.22, ease: [0.22, 1, 0.36, 1] } }}
className="relative flex min-h-[380px] min-w-0 flex-col overflow-hidden rounded-3xl border border-primary/10 bg-white p-7 shadow-[0_18px_45px_rgba(22,0,29,0.08)] hover:shadow-[0_24px_60px_rgba(22,0,29,0.14)] hover:border-primary/20 transition-[box-shadow,border-color] duration-[250ms] md:min-h-[420px] lg:min-h-[460px] xl:min-h-[420px] lg:p-8"
>
<span className="absolute right-5 top-4 font-display text-6xl font-black leading-none text-primary/[0.07]">
{step.num}
</span>
<div className="relative z-10 flex h-13 w-13 items-center justify-center rounded-2xl bg-primary/7 text-primary">
<MaterialIcon icon={step.icon} size={28} />
</div>
<div className="relative z-10 mt-7 max-w-[22rem] lg:mt-8">
<p className="font-display text-2xl font-black text-brand-dark md:text-[28px]">
{step.title}
</p>
<p className="mt-3 text-sm leading-relaxed text-on-surface-variant md:text-base">
{step.desc}
</p>
</div>
<div className={`relative z-0 mt-auto w-full overflow-hidden rounded-[1.5rem] bg-brand-accent-light/60 ${step.visual === "phone" ? "h-64 lg:h-72" : "h-48 lg:h-52"}`}>
<StepVisual type={step.visual} />
</div>
</motion.article>
))}
</motion.div>
</div>
</section>
<MerchantJourney />
</section>
</>
);
}

View File

@@ -49,7 +49,7 @@ export function HyperlocalFeatures() {
viewport={viewport}
>
<Image
src="/map1.webp"
src="/images/workflow/map1.webp"
alt="Map Background"
fill
className="object-cover"

View File

@@ -11,7 +11,7 @@ const MotionLink = motion.create(Link);
const CATEGORIES = [
{
name: "Groceries & Daily Essentials",
image: "/images/cat-daily-essentials.webp",
image: "/images/stores/cat-daily-essentials.webp",
tag: "Local Store",
tagStyle: "bg-secondary text-white",
desc: "Fresh groceries, dairy, and household essentials from nearby shops.",
@@ -19,7 +19,7 @@ const CATEGORIES = [
},
{
name: "Wellness",
image: "/images/cat-health-wellness.webp",
image: "/images/stores/cat-health-wellness.webp",
tag: "Available Near You",
tagStyle: "bg-primary text-white",
desc: "Prescription medicines and wellness supplies from verified pharmacies.",
@@ -27,7 +27,7 @@ const CATEGORIES = [
},
{
name: "Food & Snacks",
image: "/images/cat-hot-food.webp",
image: "/images/stores/cat-hot-food.webp",
tag: "Nearby",
tagStyle: "bg-brand-accent text-brand-dark",
desc: "Fresh meals, bakes, and local snacks from neighbourhood kitchens.",
@@ -35,7 +35,7 @@ const CATEGORIES = [
},
{
name: "Fresh Fruits & Vegetables",
image: "/vegetable.png",
image: "/images/illustrations/vegetable.png",
tag: "Local Store",
tagStyle: "bg-secondary text-white",
desc: "Farm-fresh fruits and vegetables from trusted local vendors.",
@@ -43,7 +43,7 @@ const CATEGORIES = [
},
{
name: "Home Needs",
image: "/images/cat-pet-essentials.webp",
image: "/images/stores/cat-pet-essentials.webp",
tag: "Available Near You",
tagStyle: "bg-orange-500 text-white",
desc: "Kitchen supplies, household cleaners, and daily utilities.",
@@ -51,7 +51,7 @@ const CATEGORIES = [
},
{
name: "Local Services",
image: "/images/cat-home-services.webp",
image: "/images/stores/cat-home-services.webp",
tag: "Nearby",
tagStyle: "bg-blue-600 text-white",
desc: "Verified local handymen, laundry, tailors, and household help.",

View File

@@ -3,7 +3,7 @@
import Image from "next/image";
import { motion } from "framer-motion";
import { MaterialIcon } from "@/components/ui/MaterialIcon";
import { siteContent } from "@/config/site-content";
import { siteContent } from "@/constants/site-content";
import { fadeUp, scaleIn, slideInRight, staggerContainer, viewport } from "@/lib/animations";
const FLOW_STEPS = [
@@ -85,7 +85,7 @@ export function StoreQRSection() {
className="h-[60px] flex items-center shrink-0 cursor-pointer select-none transition-all duration-300 hover:scale-[1.03] active:scale-[0.98]"
>
<Image
src="/apple-download.svg"
src="/icons/apple-download.svg"
alt="Download Nearle on the App Store"
width={144}
height={60}
@@ -102,7 +102,7 @@ export function StoreQRSection() {
className="h-[60px] flex items-center shrink-0 cursor-pointer select-none transition-all duration-300 hover:scale-[1.03] active:scale-[0.98]"
>
<Image
src="/play-download.svg"
src="/icons/play-download.svg"
alt="Download Nearle on Google Play"
width={155}
height={60}
@@ -132,7 +132,7 @@ export function StoreQRSection() {
<div className="relative w-32 h-32 bg-white flex items-center justify-center">
<Image
src="/nearle-qr-code.png"
src="/images/stores/nearle-qr-code.png"
alt="Nearle Store QR Code"
width={132}
height={132}
@@ -153,7 +153,7 @@ export function StoreQRSection() {
className="relative w-[290px] shrink-0 aspect-[9/18.5] bg-[#120217] rounded-[2.75rem] border-[7px] border-brand-dark-surface shadow-2xl overflow-hidden ring-4 ring-outline-variant/10"
>
<Image
src="/mobile-image.webp"
src="/images/platform/mobile-image.webp"
alt="Nearle mobile app interface"
width={360}
height={760}
@@ -199,7 +199,7 @@ export function StoreQRSection() {
<div className="relative w-36 h-36 bg-white flex items-center justify-center">
<Image
src="/nearle-qr-code.png"
src="/images/stores/nearle-qr-code.png"
alt="Nearle Store QR Code"
width={144}
height={144}
@@ -242,7 +242,7 @@ export function StoreQRSection() {
viewport={viewport}
>
<Image
src="/mobile-image.webp"
src="/images/platform/mobile-image.webp"
alt="Nearle mobile app interface"
width={360}
height={760}
@@ -260,7 +260,7 @@ export function StoreQRSection() {
className="h-14 flex items-center shrink-0 cursor-pointer select-none transition-all duration-300 hover:scale-[1.03] active:scale-[0.98]"
>
<Image
src="/apple-download.svg"
src="/icons/apple-download.svg"
alt="Download Nearle on the App Store"
width={134}
height={56}
@@ -276,7 +276,7 @@ export function StoreQRSection() {
className="h-14 flex items-center shrink-0 cursor-pointer select-none transition-all duration-300 hover:scale-[1.03] active:scale-[0.98]"
>
<Image
src="/play-download.svg"
src="/icons/play-download.svg"
alt="Download Nearle on Google Play"
width={145}
height={56}

View File

@@ -0,0 +1,182 @@
"use client";
import Link from "next/link";
import { motion } from "framer-motion";
import { MaterialIcon } from "@/components/ui/MaterialIcon";
import { PhoneStage } from "@/components/home/voice/PhoneStage";
import { FloatingRequestCards } from "@/components/home/voice/FloatingRequestCards";
import { VoiceWaves } from "@/components/home/voice/VoiceWaves";
import { viewport } from "@/lib/animations";
const EASE = [0.22, 1, 0.36, 1] as [number, number, number, number];
const EASE_OUT = [0.16, 1, 0.3, 1] as [number, number, number, number];
const FEATURE_CHIPS = [
{ emoji: "🎤", label: "Voice Shopping" },
{ emoji: "🧠", label: "Natural Language AI" },
{ emoji: "🏪", label: "Local Merchant Discovery" },
{ emoji: "⚡", label: "Real-Time Availability" },
];
const badgeVariant = {
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0, transition: { duration: 0.6, ease: EASE } },
};
const lineStagger = {
hidden: {},
visible: { transition: { staggerChildren: 0.14, delayChildren: 0.12 } },
};
const lineReveal = {
hidden: { y: 48, opacity: 0, filter: "blur(8px)" },
visible: { y: 0, opacity: 1, filter: "blur(0px)", transition: { duration: 0.85, ease: EASE_OUT } },
};
const descVariant = {
hidden: { opacity: 0, y: 22 },
visible: { opacity: 1, y: 0, transition: { duration: 0.6, delay: 0.42, ease: EASE } },
};
const chipStagger = {
hidden: {},
visible: { transition: { staggerChildren: 0.07, delayChildren: 0.56 } },
};
const chipItem = {
hidden: { opacity: 0, y: 12 },
visible: { opacity: 1, y: 0, transition: { duration: 0.45, ease: EASE } },
};
const ctaVariant = {
hidden: { opacity: 0, y: 16 },
visible: { opacity: 1, y: 0, transition: { duration: 0.6, delay: 0.86, ease: EASE } },
};
const phoneVariant = {
hidden: { opacity: 0, y: 40, scale: 0.96 },
visible: { opacity: 1, y: 0, scale: 1, transition: { duration: 1.05, delay: 0.15, ease: EASE_OUT } },
};
// The homepage's product showcase: a live Nearle app running inside the phone,
// so a visitor can watch a spoken request turn into a delivered order without
// installing anything. The Hero above introduces Nearle — this shows the work.
export function VoiceCommerceExperience() {
return (
// Explicit padding rather than the shared .section rhythm: the cards that
// float above and below the phone need more room than 88px to breathe.
<section
className="relative w-full overflow-hidden py-24 lg:py-32"
style={{
background:
"radial-gradient(60% 50% at 78% 32%, rgba(124,58,237,0.13), transparent 70%)," +
"radial-gradient(45% 42% at 12% 22%, rgba(168,85,247,0.10), transparent 70%)," +
"linear-gradient(180deg, #FDFBFF 0%, #F7F3FF 55%, #FAF7FF 100%)",
}}
>
{/* Voice waves sit behind everything, centred on the phone side */}
<VoiceWaves className="left-auto right-0 z-0 hidden w-[62%] lg:block" />
<VoiceWaves className="z-0 lg:hidden" />
<div className="page-container relative z-10">
<div className="grid items-center gap-16 lg:grid-cols-[minmax(0,1.1fr)_minmax(0,0.9fr)] lg:gap-8 xl:gap-12">
{/* ─── LEFT: what it does ─── */}
<motion.div
initial="hidden"
whileInView="visible"
viewport={viewport}
className="order-1 flex flex-col items-center text-center lg:items-start lg:text-left"
>
<motion.span
variants={badgeVariant}
className="inline-flex w-fit items-center gap-1.5 rounded-full border border-[#7C3AED]/15 bg-white px-4 py-1.5 text-xs font-black uppercase tracking-widest text-[#6D28D9] shadow-[0_4px_18px_-6px_rgba(124,58,237,0.35)]"
>
<MaterialIcon icon="graphic_eq" size={14} />
AI Voice Commerce
</motion.span>
<motion.h2
variants={lineStagger}
className="mt-6 font-display text-[32px] font-extrabold tracking-[-0.05em] text-[#16001D] sm:text-[42px] lg:text-[42px] xl:text-[52px]"
>
<div className="overflow-hidden pb-1">
<motion.div variants={lineReveal} className="leading-[0.98]">
Just speak.
</motion.div>
</div>
<div className="overflow-hidden pb-1">
{/* text-balance keeps the mobile wrap as "Nearle handles /
the rest." instead of orphaning "rest." on its own line */}
<motion.div variants={lineReveal} className="text-balance leading-[0.98]">
Nearle handles <span className="text-[#7C3AED]">the rest.</span>
</motion.div>
</div>
</motion.h2>
<motion.p
variants={descVariant}
className="mt-5 max-w-[520px] text-base font-medium leading-[1.6] text-[#4A3F52] md:text-lg"
>
Order products, discover nearby stores, and book trusted local services using
natural conversation.
</motion.p>
<motion.ul
variants={chipStagger}
className="mt-7 flex flex-wrap justify-center gap-2.5 lg:justify-start"
>
{FEATURE_CHIPS.map((chip) => (
<motion.li
key={chip.label}
variants={chipItem}
className="flex items-center gap-2 rounded-full border border-[#7C3AED]/12 bg-white/70 py-2 pl-2.5 pr-4 shadow-[0_6px_20px_-10px_rgba(76,20,140,0.35)] backdrop-blur-md"
>
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-[#7C3AED]/[0.08] text-[13px]">
{chip.emoji}
</span>
<span className="text-[13px] font-bold text-[#2C1A38]">{chip.label}</span>
</motion.li>
))}
</motion.ul>
<motion.div variants={ctaVariant} className="mt-8">
<Link
href="/platform"
className="group inline-flex items-center gap-2.5 rounded-full bg-[#6330D6] px-8 py-4 text-sm font-black uppercase tracking-wider text-white shadow-[0_14px_38px_-12px_rgba(99,48,214,0.75)] transition-all duration-200 hover:-translate-y-0.5 hover:bg-[#5225b8] hover:shadow-[0_18px_44px_-12px_rgba(99,48,214,0.85)] active:translate-y-0 active:scale-[0.98]"
>
<MaterialIcon icon="mic" size={18} />
Try Voice Commerce
<MaterialIcon
icon="arrow_forward"
size={17}
className="transition-transform duration-200 group-hover:translate-x-1"
/>
</Link>
</motion.div>
</motion.div>
{/* ─── RIGHT: the live phone ─── */}
<motion.div
variants={phoneVariant}
initial="hidden"
whileInView="visible"
viewport={viewport}
className="relative order-2 flex justify-center lg:justify-end"
>
{/* Width-driven at every breakpoint — the 476/941 aspect ratio
derives the height, so the phone never collapses. */}
<div className="relative w-[min(72vw,300px)] lg:w-[min(38vh,400px)]">
{/* soft purple glow anchoring the device */}
<div
aria-hidden="true"
className="pointer-events-none absolute left-1/2 top-1/2 -z-10 h-[86%] w-[150%] -translate-x-1/2 -translate-y-1/2 rounded-full bg-[#A855F7]/16 blur-[80px]"
/>
<PhoneStage className="w-full" />
<FloatingRequestCards />
</div>
</motion.div>
</div>
</div>
</section>
);
}

Some files were not shown because too many files have changed in this diff Show More