refactor: remove ServicesGrid component and its associated styles

This commit is contained in:
Najjar\NajjarV02 2026-05-21 13:28:38 +04:00
parent 7458818c62
commit de9f358582
9 changed files with 1483 additions and 1261 deletions

View File

@ -7,7 +7,6 @@ import { WhyUs } from '@/components/robotics/WhyUs';
import { FloatingTechPanel } from '@/components/robotics/FloatingTechPanel';
import { CompanyStory } from '@/components/robotics/CompanyStory';
import { FounderSection } from '@/components/robotics/FounderSection';
import { ServicesGrid } from '@/components/robotics/ServicesGrid';
export const metadata: Metadata = {
title: 'About YS Lootah Robotics Exclusive UAE Access to Unitree & Pudu',
@ -44,18 +43,6 @@ export default function AboutPage() {
<FounderSection />
</MotionSection>
<MotionSection>
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
<h2 style={{ margin: 0, fontSize: 'clamp(1.5rem, 3vw, 2.2rem)', fontWeight: 400, letterSpacing: '-0.02em' }}>
<span className="text-gradient" style={{ fontWeight: 500 }}>Our solutions</span>
</h2>
<p style={{ margin: 0, color: '#DEE0F0', lineHeight: 1.7, maxWidth: 760 }}>
Eleven robotics services covering autonomous deployment, integration, motion programming, cloud, analytics, and live diagnostics.
</p>
<ServicesGrid />
</div>
</MotionSection>
<MotionSection>
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
<h2 style={{ margin: 0, fontSize: 'clamp(1.5rem, 3vw, 2.2rem)', fontWeight: 400, letterSpacing: '-0.02em' }}>

View File

@ -11,9 +11,7 @@ import { ConfigureCTA } from '@/components/robotics/ConfigureCTA';
import { ExclusiveAccessSection } from '@/components/robotics/ExclusiveAccessSection';
import { MarqueeStrip } from '@/components/robotics/MarqueeStrip';
import { BentoGrid } from '@/components/robotics/BentoGrid';
import { HowItWorks } from '@/components/robotics/HowItWorks';
import { CompanyStory } from '@/components/robotics/CompanyStory';
import { ServicesGrid } from '@/components/robotics/ServicesGrid';
import { FounderSection } from '@/components/robotics/FounderSection';
import { BuSunaidahSection } from '@/components/robotics/BuSunaidahSection';
import { MotionSection } from '@/components/ui/MotionSection';
@ -111,17 +109,6 @@ export default function HomePage() {
</div>
</MotionSection>
<MotionSection style={{ padding: 'clamp(3rem, 6vw, 5rem) 0' }} id="services">
<div className="container-wide" style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
<SectionHeading
eyebrow="UAE deployment"
title="Real robots, deployed and supported across the UAE."
description="From Dubai showroom demo to live venue deployment — procurement, configuration, installation, training, and ongoing support, handled by one local team."
/>
<ServicesGrid />
</div>
</MotionSection>
<MotionSection style={{ padding: 'clamp(3rem, 6vw, 5rem) 0' }} id="leadership">
<div className="container-wide">
<FounderSection />
@ -134,18 +121,10 @@ export default function HomePage() {
</div>
</MotionSection>
<MotionSection style={{ padding: 'clamp(3rem, 6vw, 5rem) 0' }} id="how-it-works">
<div className="container-wide" style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
<SectionHeading
eyebrow="Deployment timeline"
title="Five steps from procurement to support."
description="The robotics implementation journey — what changes at every stage, in order."
/>
<HowItWorks />
</div>
</MotionSection>
<MotionSection style={{ padding: 'clamp(3rem, 6vw, 5rem) 0' }} id="industries">
<MotionSection
style={{ padding: 'clamp(3rem, 6vw, 5rem) 0', scrollMarginTop: 'clamp(80px, 12vh, 120px)' }}
id="industries"
>
<div className="container-wide" style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
<SectionHeading
eyebrow="Industries served"
@ -156,13 +135,13 @@ export default function HomePage() {
</div>
</MotionSection>
<MotionSection style={{ padding: 'clamp(3rem, 6vw, 5rem) 0 clamp(4rem, 8vw, 7rem)' }}>
<MotionSection style={{ padding: 'clamp(2.5rem, 5vw, 4rem) 0 clamp(1.5rem, 3vw, 2.5rem)' }}>
<div className="container-wide">
<DemoCTA
title="Talk to our robotics team."
description="Book a live demo at our Dubai showroom or request a UAE quotation. Our local team responds within one business day."
primaryLabel="Book a live demo"
secondaryLabel="Talk to our team"
description="See the robots in action at our Dubai showroom or request a UAE-ready quotation. Our team responds within one business day."
primaryLabel="Book a Live Demo"
secondaryLabel="Talk to Our Team"
/>
</div>
</MotionSection>

View File

@ -2,7 +2,9 @@
import Link from 'next/link';
import Image from 'next/image';
import { Phone, Mail, MapPin, MessageCircle, ArrowUpRight } from 'lucide-react';
import { BRANDS } from '@/data/robots';
import { CTAButton } from '@/components/ui/CTAButton';
const CONTACT = {
phonePrimary: '+971 55 948 2728',
@ -18,40 +20,37 @@ const CONTACT = {
export function FooterAndContact() {
return (
<footer
style={{
position: 'relative',
zIndex: 10,
marginTop: 'clamp(4rem, 8vw, 6rem)',
borderTop: '1px solid rgba(39, 63, 148,0.12)',
background:
'radial-gradient(ellipse 80% 60% at 50% 0%, rgba(39, 63, 148,0.05), transparent 60%), linear-gradient(180deg, #030303, #02040a)',
color: '#DEE0F0',
}}
>
<div className="container-wide" style={{ paddingTop: 'clamp(3rem, 6vw, 5rem)', paddingBottom: '2rem' }}>
<div
style={{
display: 'grid',
gap: 'clamp(2rem, 4vw, 3.5rem)',
gridTemplateColumns: 'repeat(auto-fit, minmax(min(220px, 100%), 1fr))',
paddingBottom: '2.5rem',
}}
>
<div style={{ minWidth: 0 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.7rem', marginBottom: '1.25rem' }}>
<span
style={{
position: 'relative',
width: 46,
height: 46,
borderRadius: '50%',
overflow: 'hidden',
flex: 'none',
boxShadow: '0 0 18px rgba(39, 63, 148, 0.35)',
border: '1px solid rgba(39, 63, 148,0.4)',
}}
>
<footer className="ft">
<div className="ft-top-line" aria-hidden />
<div className="ft-bg" aria-hidden />
<div className="ft-grid-tex" aria-hidden />
<div className="container-wide ft-inner">
{/* CTA STRIP */}
<div className="ft-cta">
<div className="ft-cta-copy">
<span className="ft-cta-eyebrow">Talk to a robotics advisor</span>
<h3 className="ft-cta-title">Need help choosing a robot?</h3>
<p className="ft-cta-desc">
Our Dubai team will match the right Unitree or Pudu solution to your venue service, delivery, security, or humanoid.
</p>
</div>
<div className="ft-cta-actions">
<CTAButton href="/book-demo/" variant="primary" size="md" arrow="up-right">
Talk to our Dubai team
</CTAButton>
<CTAButton href="/robots/" variant="link" size="sm" arrow="right">
Browse robots
</CTAButton>
</div>
</div>
{/* MAIN GRID */}
<div className="ft-main">
{/* BRAND */}
<div className="ft-brand">
<div className="ft-logo-row">
<span className="ft-logo">
<Image
src="/images/brands/ys-lootah-robotics-logo.png"
alt="YS Lootah Robotics logo"
@ -60,128 +59,496 @@ export function FooterAndContact() {
style={{ objectFit: 'cover' }}
/>
</span>
<span style={{ display: 'flex', flexDirection: 'column', lineHeight: 1 }}>
<span style={{ fontSize: '1rem', fontWeight: 700, letterSpacing: '0.16em', color: '#ffffff', textTransform: 'uppercase' }}>
YS Lootah
</span>
<span style={{ fontSize: '0.7rem', fontWeight: 500, letterSpacing: '0.32em', color: '#DEE0F0', textTransform: 'uppercase', marginTop: 4 }}>
Robotics
</span>
<span className="ft-name-stack">
<span className="ft-name">YS Lootah</span>
<span className="ft-name-sub">Robotics</span>
</span>
</div>
<p style={{ margin: '0 0 0.75rem', color: '#DEE0F0', fontSize: '0.78rem', letterSpacing: '0.22em', textTransform: 'uppercase', fontWeight: 600 }}>
In Tech We Innovate · In Trust We Lead
<p className="ft-tag">In Tech We Innovate · In Trust We Lead</p>
<p className="ft-desc">
UAE&apos;s dedicated destination for selected Unitree and Pudu Robotics solutions.
</p>
<p style={{ margin: 0, color: '#8891C7', lineHeight: 1.7, fontSize: '0.95rem' }}>
Innovating today for a smarter tomorrow. YS Lootah Robotics the UAE&apos;s dedicated destination for selected Unitree and Pudu Robotics solutions.
</p>
<div style={{ display: 'flex', gap: '0.625rem', marginTop: '1.5rem' }}>
<SocialLink href={CONTACT.instagram} label="Instagram" path="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z" />
<SocialLink href={CONTACT.linkedin} label="LinkedIn" path="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.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 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" />
<SocialLink href={CONTACT.facebook} label="Facebook" path="M9.101 24v-11.01h-3.427v-3.929h3.427v-2.897c0-3.411 2.083-5.268 5.123-5.268 1.455 0 2.707.108 3.07.157v3.56h-2.107c-1.654 0-1.974.786-1.974 1.938v2.51h3.942l-.513 3.929h-3.429V24H9.101z" />
<div className="ft-social">
<SocialLink
href={CONTACT.instagram}
label="Instagram"
path="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"
/>
<SocialLink
href={CONTACT.linkedin}
label="LinkedIn"
path="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.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 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"
/>
<SocialLink
href={CONTACT.facebook}
label="Facebook"
path="M9.101 24v-11.01h-3.427v-3.929h3.427v-2.897c0-3.411 2.083-5.268 5.123-5.268 1.455 0 2.707.108 3.07.157v3.56h-2.107c-1.654 0-1.974.786-1.974 1.938v2.51h3.942l-.513 3.929h-3.429V24H9.101z"
/>
</div>
</div>
<ColumnLinks
title="Explore"
items={[
{ label: 'Robots', href: '/robots/' },
{ label: 'Brands', href: '/brands/' },
{ label: 'Industries', href: '/industries/' },
{ label: 'About', href: '/about/' },
{ label: 'Configure your robot', href: '/configure/' },
]}
/>
{/* EXPLORE + BRANDS */}
<div className="ft-col">
<ColumnGroup
title="Explore"
items={[
{ label: 'Robots', href: '/robots/' },
{ label: 'Industries', href: '/industries/' },
{ label: 'About', href: '/about/' },
{ label: 'Configure your robot', href: '/configure/' },
{ label: 'Book a demo', href: '/book-demo/' },
]}
/>
<ColumnGroup
title="Brands"
items={[
{ label: BRANDS.unitree.name, href: '/brands/#unitree' },
{ label: BRANDS.pudu.name, href: '/brands/#pudu' },
]}
/>
</div>
<ColumnLinks
title="Robot categories"
items={[
{ label: 'Humanoid', href: '/robots/?category=humanoid' },
{ label: 'Quadruped', href: '/robots/?category=quadruped' },
{ label: 'Service', href: '/robots/?category=service' },
{ label: 'Delivery', href: '/robots/?category=delivery' },
{ label: 'Hospitality', href: '/robots/?category=hospitality' },
{ label: 'Cleaning', href: '/robots/?category=cleaning' },
]}
/>
{/* CATEGORIES */}
<div className="ft-col">
<ColumnGroup
title="Robot categories"
items={[
{ label: 'Humanoid', href: '/robots/?category=humanoid' },
{ label: 'Quadruped', href: '/robots/?category=quadruped' },
{ label: 'Service', href: '/robots/?category=service' },
{ label: 'Delivery', href: '/robots/?category=delivery' },
{ label: 'Hospitality', href: '/robots/?category=hospitality' },
{ label: 'Cleaning', href: '/robots/?category=cleaning' },
]}
/>
</div>
<ColumnLinks
title="Brands"
items={[
{ label: BRANDS.unitree.name, href: '/brands/#unitree' },
{ label: BRANDS.pudu.name, href: '/brands/#pudu' },
]}
/>
<div style={{ minWidth: 0 }}>
<h4 style={{ margin: '0 0 1.25rem', fontSize: '0.72rem', letterSpacing: '0.22em', textTransform: 'uppercase', color: '#8891C7', fontWeight: 700 }}>
Contact
</h4>
<ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
{/* CONTACT CARD */}
<div className="ft-contact">
<h4 className="ft-col-title">Contact</h4>
<ul className="ft-contact-list">
<li>
<a href={`tel:${CONTACT.phonePrimary.replace(/\s/g, '')}`} style={footerLink}>{CONTACT.phonePrimary}</a>
</li>
<li>
<a href={`tel:${CONTACT.phoneSecondary.replace(/\s/g, '')}`} style={footerLink}>{CONTACT.phoneSecondary}</a>
</li>
<li>
<a href={`mailto:${CONTACT.email}`} style={footerLink}>{CONTACT.email}</a>
</li>
<li>
<a href={CONTACT.maps} target="_blank" rel="noopener noreferrer" style={{ ...footerLink, color: '#8891C7' }}>
{CONTACT.address}
<a className="ft-contact-row" href={`tel:${CONTACT.phonePrimary.replace(/\s/g, '')}`}>
<span className="ft-contact-ico" aria-hidden><Phone size={13} strokeWidth={2} /></span>
<span className="ft-contact-text">{CONTACT.phonePrimary}</span>
</a>
</li>
<li>
<a href={CONTACT.whatsapp} target="_blank" rel="noopener noreferrer" style={{ ...footerLink, color: '#DEE0F0' }}>
WhatsApp us
<a className="ft-contact-row" href={`tel:${CONTACT.phoneSecondary.replace(/\s/g, '')}`}>
<span className="ft-contact-ico" aria-hidden><Phone size={13} strokeWidth={2} /></span>
<span className="ft-contact-text">{CONTACT.phoneSecondary}</span>
</a>
</li>
<li>
<a className="ft-contact-row" href={`mailto:${CONTACT.email}`}>
<span className="ft-contact-ico" aria-hidden><Mail size={13} strokeWidth={2} /></span>
<span className="ft-contact-text">{CONTACT.email}</span>
</a>
</li>
<li>
<a className="ft-contact-row" href={CONTACT.maps} target="_blank" rel="noopener noreferrer">
<span className="ft-contact-ico" aria-hidden><MapPin size={13} strokeWidth={2} /></span>
<span className="ft-contact-text ft-contact-text-soft">{CONTACT.address}</span>
</a>
</li>
</ul>
<a
className="ft-wa"
href={CONTACT.whatsapp}
target="_blank"
rel="noopener noreferrer"
aria-label="Message us on WhatsApp"
>
<span className="ft-wa-ico" aria-hidden><MessageCircle size={14} strokeWidth={2} /></span>
<span>WhatsApp us</span>
<span className="ft-wa-arrow" aria-hidden><ArrowUpRight size={12} /></span>
</a>
</div>
</div>
<div style={{ borderTop: '1px solid rgba(39, 63, 148,0.1)', paddingTop: '1.75rem', display: 'flex', flexWrap: 'wrap', justifyContent: 'space-between', alignItems: 'center', gap: '1rem' }}>
<p style={{ margin: 0, fontSize: '0.82rem', color: '#6a73a5' }}>
{/* BOTTOM ROW */}
<div className="ft-bot">
<p className="ft-bot-copy">
© {new Date().getFullYear()} YS Lootah Robotics. All rights reserved.
</p>
<p style={{ margin: 0, fontSize: '0.78rem', color: '#6a73a5' }}>
Website designed &amp; developed by{' '}
<a href="https://yslootahtech.com" target="_blank" rel="noopener noreferrer" style={{ color: '#8891C7', textDecoration: 'none' }}>
<p className="ft-bot-credit">
Designed &amp; built by{' '}
<a href="https://yslootahtech.com" target="_blank" rel="noopener noreferrer" className="ft-bot-link">
YS Lootah Tech
</a>
</p>
<div style={{ display: 'flex', gap: '1.5rem' }}>
<Link href="/privacy-policy/" style={{ fontSize: '0.82rem', color: '#6a73a5', textDecoration: 'none' }}>Privacy</Link>
<Link href="/terms-of-service/" style={{ fontSize: '0.82rem', color: '#6a73a5', textDecoration: 'none' }}>Terms</Link>
<div className="ft-bot-legal">
<Link href="/privacy-policy/" className="ft-bot-link">Privacy</Link>
<span className="ft-bot-dot" aria-hidden />
<Link href="/terms-of-service/" className="ft-bot-link">Terms</Link>
</div>
</div>
</div>
<style jsx>{`
.ft {
position: relative;
isolation: isolate;
z-index: 10;
margin-top: clamp(3rem, 6vw, 5rem);
background: linear-gradient(180deg, #030307 0%, #020409 100%);
color: #DEE0F0;
overflow: hidden;
}
.ft-top-line {
position: absolute;
top: 0;
left: 12%;
right: 12%;
height: 1px;
background: linear-gradient(90deg, transparent, rgba(74, 102, 216, 0.6), transparent);
box-shadow: 0 0 24px rgba(74, 102, 216, 0.35);
z-index: 1;
}
.ft-bg {
position: absolute;
inset: 0;
background:
radial-gradient(ellipse 50% 60% at 20% 0%, rgba(58, 85, 196, 0.16), transparent 60%),
radial-gradient(ellipse 60% 70% at 90% 100%, rgba(136, 145, 199, 0.08), transparent 60%);
pointer-events: none;
z-index: 0;
}
.ft-grid-tex {
position: absolute;
inset: 0;
background-image:
linear-gradient(rgba(199, 207, 230, 0.035) 1px, transparent 1px),
linear-gradient(90deg, rgba(199, 207, 230, 0.035) 1px, transparent 1px);
background-size: 56px 56px;
mask-image: radial-gradient(ellipse 80% 80% at 50% 30%, #000 30%, transparent 85%);
-webkit-mask-image: radial-gradient(ellipse 80% 80% at 50% 30%, #000 30%, transparent 85%);
pointer-events: none;
z-index: 0;
}
.ft-inner {
position: relative;
z-index: 2;
padding-top: clamp(2.5rem, 5vw, 3.5rem);
padding-bottom: clamp(5rem, 7vw, 6rem);
}
/* CTA STRIP */
.ft-cta {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 1.25rem;
padding: 1.4rem 1.5rem;
border-radius: 18px;
border: 1px solid rgba(222, 224, 240, 0.12);
background:
radial-gradient(ellipse 60% 80% at 0% 50%, rgba(58, 85, 196, 0.18), transparent 60%),
radial-gradient(ellipse 50% 80% at 100% 50%, rgba(136, 145, 199, 0.1), transparent 60%),
linear-gradient(180deg, rgba(22, 21, 30, 0.7), rgba(10, 10, 14, 0.9));
margin-bottom: clamp(2rem, 4vw, 3rem);
backdrop-filter: blur(14px);
}
.ft-cta-copy { display: flex; flex-direction: column; gap: 0.4rem; min-width: 0; }
.ft-cta-eyebrow {
font-size: 0.6rem;
letter-spacing: 0.3em;
text-transform: uppercase;
font-weight: 800;
color: #8891C7;
}
.ft-cta-title {
margin: 0;
font-size: clamp(1.3rem, 2.5vw, 1.7rem);
font-weight: 300;
letter-spacing: -0.02em;
color: #FFFFFF;
line-height: 1.15;
}
.ft-cta-desc {
margin: 0;
color: #B5BDDB;
font-size: 0.92rem;
line-height: 1.55;
max-width: 520px;
}
.ft-cta-actions {
display: flex;
flex-wrap: wrap;
gap: 0.65rem;
align-items: center;
}
/* MAIN GRID */
.ft-main {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: clamp(2rem, 3.5vw, 2.75rem);
padding-bottom: clamp(1.5rem, 3vw, 2.25rem);
}
.ft-col { display: flex; flex-direction: column; gap: 1.5rem; min-width: 0; }
.ft-col-title {
margin: 0 0 1rem;
font-size: 0.66rem;
letter-spacing: 0.26em;
text-transform: uppercase;
color: #8891C7;
font-weight: 800;
}
/* BRAND */
.ft-brand { min-width: 0; }
.ft-logo-row {
display: flex;
align-items: center;
gap: 0.7rem;
margin-bottom: 1.1rem;
}
.ft-logo {
position: relative;
width: 46px;
height: 46px;
border-radius: 50%;
overflow: hidden;
flex: none;
box-shadow: 0 0 18px rgba(39, 63, 148, 0.4);
border: 1px solid rgba(74, 102, 216, 0.5);
}
.ft-name-stack { display: flex; flex-direction: column; line-height: 1; }
.ft-name {
font-size: 1rem;
font-weight: 700;
letter-spacing: 0.16em;
color: #FFFFFF;
text-transform: uppercase;
}
.ft-name-sub {
font-size: 0.7rem;
font-weight: 500;
letter-spacing: 0.32em;
color: #DEE0F0;
text-transform: uppercase;
margin-top: 4px;
}
.ft-tag {
margin: 0 0 0.7rem;
color: #DEE0F0;
font-size: 0.7rem;
letter-spacing: 0.22em;
text-transform: uppercase;
font-weight: 600;
}
.ft-desc {
margin: 0;
color: #8891C7;
line-height: 1.65;
font-size: 0.9rem;
max-width: 340px;
}
.ft-social {
display: flex;
gap: 0.55rem;
margin-top: 1.25rem;
}
/* CONTACT CARD */
.ft-contact {
position: relative;
padding: 1.1rem 1.15rem 1.15rem;
border-radius: 14px;
border: 1px solid rgba(222, 224, 240, 0.1);
background:
radial-gradient(ellipse 70% 50% at 100% 0%, rgba(58, 85, 196, 0.12), transparent 65%),
linear-gradient(180deg, rgba(20, 19, 26, 0.5), rgba(10, 10, 14, 0.78));
backdrop-filter: blur(10px);
min-width: 0;
}
.ft-contact-list {
list-style: none;
padding: 0;
margin: 0 0 1rem;
display: flex;
flex-direction: column;
gap: 0.6rem;
}
.ft-contact-row {
display: grid;
grid-template-columns: 22px minmax(0, 1fr);
align-items: start;
gap: 0.65rem;
color: #DEE0F0;
text-decoration: none;
font-size: 0.85rem;
line-height: 1.45;
transition: color 0.25s, transform 0.25s;
}
.ft-contact-row:hover { color: #FFFFFF; transform: translateX(2px); }
.ft-contact-ico {
display: inline-flex;
align-items: center;
justify-content: center;
width: 22px;
height: 22px;
border-radius: 7px;
background: rgba(74, 102, 216, 0.12);
border: 1px solid rgba(74, 102, 216, 0.28);
color: #DEE0F0;
margin-top: 1px;
transition: background 0.25s, border-color 0.25s;
}
.ft-contact-row:hover .ft-contact-ico {
background: rgba(74, 102, 216, 0.22);
border-color: rgba(74, 102, 216, 0.5);
}
.ft-contact-text { min-width: 0; word-break: break-word; }
.ft-contact-text-soft { color: #8891C7; }
.ft-wa {
display: inline-flex;
align-items: center;
gap: 0.55rem;
padding: 0.55rem 0.85rem 0.55rem 0.7rem;
border-radius: 999px;
background:
linear-gradient(135deg, rgba(37, 211, 102, 0.16), rgba(18, 140, 126, 0.16)),
rgba(14, 13, 18, 0.7);
border: 1px solid rgba(37, 211, 102, 0.35);
color: #DCFBE8;
font-size: 0.72rem;
letter-spacing: 0.16em;
text-transform: uppercase;
font-weight: 700;
text-decoration: none;
transition: border-color 0.25s, background 0.25s, transform 0.25s;
}
.ft-wa:hover {
border-color: rgba(37, 211, 102, 0.65);
background:
linear-gradient(135deg, rgba(37, 211, 102, 0.28), rgba(18, 140, 126, 0.28)),
rgba(14, 13, 18, 0.75);
transform: translateY(-1px);
}
.ft-wa-ico {
display: inline-flex;
align-items: center;
justify-content: center;
width: 22px;
height: 22px;
border-radius: 999px;
background: rgba(37, 211, 102, 0.22);
color: #DCFBE8;
}
.ft-wa-arrow { color: #DCFBE8; display: inline-flex; }
/* BOTTOM */
.ft-bot {
display: flex;
flex-wrap: wrap;
gap: 0.85rem 1.5rem;
padding-top: 1.5rem;
border-top: 1px solid rgba(222, 224, 240, 0.08);
align-items: center;
justify-content: space-between;
}
.ft-bot-copy { margin: 0; font-size: 0.78rem; color: #6a73a5; }
.ft-bot-credit { margin: 0; font-size: 0.74rem; color: #6a73a5; }
.ft-bot-legal { display: flex; gap: 0.85rem; align-items: center; }
.ft-bot-dot {
width: 3px;
height: 3px;
border-radius: 999px;
background: rgba(106, 115, 165, 0.6);
}
.ft-bot-link {
font-size: 0.78rem;
color: #8891C7;
text-decoration: none;
transition: color 0.25s;
}
.ft-bot-link:hover { color: #DEE0F0; }
/* RESPONSIVE */
@media (min-width: 760px) {
.ft-cta {
grid-template-columns: minmax(0, 1.4fr) auto;
align-items: center;
gap: 1.5rem;
padding: 1.5rem 1.75rem;
}
.ft-cta-actions { justify-content: flex-end; }
.ft-main {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (min-width: 1024px) {
.ft-main {
grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.1fr);
}
}
@media (max-width: 600px) {
.ft-bot {
flex-direction: column;
align-items: flex-start;
text-align: left;
}
.ft-cta-actions :global(.cta-btn) { width: 100%; justify-content: space-between; }
}
`}</style>
</footer>
);
}
const footerLink: React.CSSProperties = {
fontSize: '0.9rem',
color: '#DEE0F0',
textDecoration: 'none',
transition: 'color 0.2s',
};
function ColumnLinks({ title, items }: { title: string; items: { label: string; href: string }[] }) {
function ColumnGroup({ title, items }: { title: string; items: { label: string; href: string }[] }) {
return (
<div style={{ minWidth: 0 }}>
<h4 style={{ margin: '0 0 1.25rem', fontSize: '0.72rem', letterSpacing: '0.22em', textTransform: 'uppercase', color: '#8891C7', fontWeight: 700 }}>
{title}
</h4>
<ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
<div className="cg">
<h4 className="cg-title">{title}</h4>
<ul className="cg-list">
{items.map((it) => (
<li key={it.label}>
<Link href={it.href} style={footerLink}>{it.label}</Link>
<Link href={it.href} className="cg-link">
<span className="cg-link-text">{it.label}</span>
<span className="cg-link-bar" aria-hidden />
</Link>
</li>
))}
</ul>
<style jsx>{`
.cg { min-width: 0; }
.cg-title {
margin: 0 0 0.95rem;
font-size: 0.66rem;
letter-spacing: 0.26em;
text-transform: uppercase;
color: #8891C7;
font-weight: 800;
}
.cg-list {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: 0.55rem;
}
.cg-link {
position: relative;
display: inline-flex;
align-items: center;
gap: 0.5rem;
font-size: 0.88rem;
color: #DEE0F0;
text-decoration: none;
padding: 1px 0;
transition: color 0.25s, transform 0.25s;
}
.cg-link-bar {
width: 0;
height: 1px;
background: linear-gradient(90deg, #4a66d8, #8891C7);
transition: width 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
.cg-link:hover { color: #FFFFFF; transform: translateX(3px); }
.cg-link:hover .cg-link-bar { width: 18px; }
`}</style>
</div>
);
}
@ -193,22 +560,33 @@ function SocialLink({ href, label, path }: { href: string; label: string; path:
target="_blank"
rel="noopener noreferrer"
aria-label={label}
style={{
width: 38,
height: 38,
borderRadius: 10,
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
background: 'rgba(15, 12, 8,0.6)',
border: '1px solid rgba(39, 63, 148,0.18)',
color: '#8891C7',
transition: 'all 0.25s ease',
}}
className="sl"
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d={path} />
</svg>
<style jsx>{`
.sl {
width: 36px;
height: 36px;
border-radius: 10px;
display: inline-flex;
align-items: center;
justify-content: center;
background: rgba(14, 13, 18, 0.7);
border: 1px solid rgba(222, 224, 240, 0.12);
color: #8891C7;
transition: color 0.25s, border-color 0.25s, background 0.25s, transform 0.25s, box-shadow 0.25s;
}
.sl:hover {
color: #FFFFFF;
border-color: rgba(74, 102, 216, 0.55);
background: rgba(58, 85, 196, 0.16);
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(58, 85, 196, 0.25);
}
`}</style>
</a>
);
}

View File

@ -149,7 +149,7 @@ export function CategoryShowcaseScroll() {
.cats-grid {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 0.85rem;
gap: 1rem;
}
.cat-wrap { display: flex; }
@ -159,24 +159,41 @@ export function CategoryShowcaseScroll() {
isolation: isolate;
display: grid;
grid-template-rows: auto 1fr auto;
gap: 1rem;
gap: 0.75rem;
width: 100%;
padding: 1.25rem 1.25rem 1.1rem;
border-radius: 18px;
border: 1px solid rgba(222, 224, 240, 0.1);
background: linear-gradient(180deg, rgba(20, 19, 26, 0.7), rgba(8, 8, 12, 0.92));
padding: 1.1rem 1.15rem 1rem;
border-radius: 16px;
border: 1px solid rgba(222, 224, 240, 0.16);
background:
radial-gradient(ellipse 80% 60% at 100% 0%, rgba(74, 102, 216, 0.12), transparent 60%),
linear-gradient(180deg, rgba(28, 27, 38, 0.85), rgba(12, 12, 18, 0.96));
color: #FFFFFF;
text-decoration: none;
overflow: hidden;
box-shadow:
0 1px 0 rgba(222, 224, 240, 0.05) inset,
0 14px 30px rgba(0, 0, 0, 0.4);
transition: border-color 0.35s, transform 0.35s, box-shadow 0.35s, background 0.35s;
}
.cat::before {
content: '';
position: absolute;
top: 0;
left: 14px;
right: 14px;
height: 1px;
background: linear-gradient(90deg, transparent, rgba(74, 102, 216, 0.45), transparent);
pointer-events: none;
z-index: 1;
}
.cat:hover {
border-color: rgba(74, 102, 216, 0.45);
border-color: rgba(74, 102, 216, 0.55);
transform: translateY(-3px);
box-shadow:
0 22px 50px rgba(0, 0, 0, 0.55),
0 0 0 1px rgba(74, 102, 216, 0.28),
0 0 32px rgba(58, 85, 196, 0.22);
0 22px 50px rgba(0, 0, 0, 0.6),
0 0 0 1px rgba(74, 102, 216, 0.32),
0 0 32px rgba(58, 85, 196, 0.26),
0 1px 0 rgba(222, 224, 240, 0.08) inset;
}
.cat-hover-glow {
@ -231,11 +248,11 @@ export function CategoryShowcaseScroll() {
.cat-mid {
display: flex;
flex-direction: column;
gap: 0.4rem;
gap: 0.3rem;
}
.cat-title {
margin: 0;
font-size: 1.05rem;
font-size: 1.02rem;
font-weight: 700;
line-height: 1.2;
letter-spacing: -0.005em;
@ -244,15 +261,18 @@ export function CategoryShowcaseScroll() {
.cat-desc {
margin: 0;
color: #B5BDDB;
font-size: 0.84rem;
line-height: 1.55;
font-size: 0.82rem;
line-height: 1.5;
}
/* BOTTOM */
.cat-bot {
display: flex;
flex-direction: column;
gap: 0.85rem;
gap: 0.7rem;
margin-top: 0.15rem;
padding-top: 0.7rem;
border-top: 1px solid rgba(222, 224, 240, 0.07);
}
.cat-chips {
list-style: none;
@ -268,9 +288,10 @@ export function CategoryShowcaseScroll() {
padding: 0.28rem 0.6rem;
border-radius: 999px;
border: 1px solid rgba(222, 224, 240, 0.14);
background: rgba(14, 13, 18, 0.45);
background: rgba(14, 13, 18, 0.55);
color: #B5BDDB;
font-weight: 600;
white-space: nowrap;
}
.cat-cta {
display: inline-flex;
@ -304,10 +325,10 @@ export function CategoryShowcaseScroll() {
/* RESPONSIVE GRID */
@media (min-width: 640px) {
.cats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.95rem; }
.cats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.1rem; }
}
@media (min-width: 1024px) {
.cats-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1.05rem; }
.cats-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1.25rem; }
}
`}</style>
</section>

View File

@ -1,7 +1,11 @@
'use client';
import { motion } from 'framer-motion';
import { MapPin, FileText, Clock, Sparkles } from 'lucide-react';
import { CTAButton } from '@/components/ui/CTAButton';
const ease = [0.16, 1, 0.3, 1] as const;
type Props = {
title?: string;
description?: string;
@ -11,61 +15,475 @@ type Props = {
secondaryLabel?: string;
};
const CHIPS = [
{ Icon: MapPin, label: 'Dubai showroom' },
{ Icon: Sparkles, label: 'Live demo' },
{ Icon: FileText, label: 'UAE quotation' },
{ Icon: Clock, label: 'Fast response' },
];
export function DemoCTA({
title = 'Bring premium robotics to your team.',
description = 'Book a live demo at our Dubai showroom or talk to a robotics advisor about your project. We respond fast.',
title = 'Talk to our robotics team.',
description = 'See the robots in action at our Dubai showroom or request a UAE-ready quotation. Our team responds within one business day.',
primaryHref = '/book-demo/',
primaryLabel = 'Book a live demo',
secondaryHref = '/contact/',
secondaryLabel = 'Talk to an advisor',
secondaryLabel = 'Talk to our team',
}: Props) {
return (
<div
style={{
position: 'relative',
borderRadius: '2rem',
padding: 'clamp(2rem, 5vw, 4rem)',
overflow: 'hidden',
background:
'radial-gradient(ellipse 60% 80% at 20% 20%, rgba(39, 63, 148,0.18), transparent 60%), radial-gradient(ellipse 70% 80% at 80% 100%, rgba(136, 145, 199,0.18), transparent 60%), linear-gradient(135deg, rgba(15, 12, 8,0.9), rgba(5, 5, 5,0.95))',
border: '1px solid rgba(39, 63, 148,0.18)',
boxShadow: '0 30px 100px rgba(0, 0, 0,0.6), inset 0 1px 0 rgba(255,255,255,0.04)',
}}
<motion.section
className="dcta"
aria-label="Book a demo or contact the robotics team"
initial={{ opacity: 0, y: 24 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-10%' }}
transition={{ duration: 0.7, ease }}
>
<div
style={{
position: 'absolute',
inset: 0,
background:
'linear-gradient(rgba(39, 63, 148,0.05) 1px, transparent 1px), linear-gradient(90deg, rgba(39, 63, 148,0.05) 1px, transparent 1px)',
backgroundSize: '48px 48px',
maskImage: 'radial-gradient(ellipse 60% 80% at 50% 30%, #000 30%, transparent 80%)',
WebkitMaskImage: 'radial-gradient(ellipse 60% 80% at 50% 30%, #000 30%, transparent 80%)',
pointerEvents: 'none',
}}
/>
<div style={{ position: 'relative', display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center', gap: '1.25rem' }}>
<span className="eyebrow">Book a demo · Dubai showroom</span>
<h2
style={{
margin: 0,
fontSize: 'clamp(1.8rem, 4.5vw, 3rem)',
lineHeight: 1.1,
fontWeight: 300,
letterSpacing: '-0.03em',
maxWidth: 760,
}}
>
<span className="text-gradient" style={{ fontWeight: 500 }}>{title}</span>
</h2>
<p style={{ margin: 0, color: '#DEE0F0', maxWidth: 620, lineHeight: 1.7, fontSize: 'clamp(0.95rem, 2vw, 1.05rem)' }}>
{description}
</p>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.75rem', justifyContent: 'center', marginTop: '0.5rem' }}>
<CTAButton href={primaryHref} variant="primary" size="lg" arrow="up-right">{primaryLabel}</CTAButton>
<CTAButton href={secondaryHref} variant="secondary" size="lg" arrow="right">{secondaryLabel}</CTAButton>
<div className="dcta-glow dcta-glow-a" aria-hidden />
<div className="dcta-glow dcta-glow-b" aria-hidden />
<div className="dcta-grid" aria-hidden />
<div className="dcta-scan" aria-hidden />
<div className="dcta-inner">
{/* LEFT — copy + actions */}
<div className="dcta-text">
<span className="dcta-eyebrow">
<span className="dcta-eyebrow-dot" />
Book a demo · Dubai showroom
</span>
<h2 className="dcta-title">
<span className="text-gradient">{title}</span>
</h2>
<p className="dcta-desc">{description}</p>
<ul className="dcta-chips" role="list">
{CHIPS.map((c) => (
<li key={c.label} className="dcta-chip">
<span className="dcta-chip-icon" aria-hidden>
<c.Icon size={12} />
</span>
<span>{c.label}</span>
</li>
))}
</ul>
<div className="dcta-actions">
<CTAButton
href={primaryHref}
variant="primary"
size="lg"
arrow="up-right"
ariaLabel={`${primaryLabel} at the Dubai showroom`}
>
{primaryLabel}
</CTAButton>
<CTAButton
href={secondaryHref}
variant="secondary"
size="lg"
arrow="right"
ariaLabel={`${secondaryLabel} via contact form`}
>
{secondaryLabel}
</CTAButton>
</div>
<div className="dcta-meta" aria-hidden>
<span className="dcta-meta-dot" />
<span>UAE-based robotics team · Replies within 1 business day</span>
</div>
</div>
{/* RIGHT — status module (desktop only) */}
<aside className="dcta-panel" aria-hidden>
<div className="dcta-panel-head">
<span className="dcta-panel-tag">YSL · LIVE</span>
<span className="dcta-panel-live">
<span className="dcta-panel-live-dot" />
Online
</span>
</div>
<div className="dcta-orbit">
<svg viewBox="0 0 220 220" role="img" aria-hidden="true" className="dcta-orbit-svg">
<defs>
<radialGradient id="dcta-core" cx="50%" cy="50%" r="50%">
<stop offset="0%" stopColor="#FFFFFF" />
<stop offset="55%" stopColor="#DEE0F0" />
<stop offset="100%" stopColor="#4a66d8" />
</radialGradient>
<linearGradient id="dcta-route" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stopColor="rgba(222, 224, 240, 0.0)" />
<stop offset="50%" stopColor="rgba(222, 224, 240, 0.55)" />
<stop offset="100%" stopColor="rgba(74, 102, 216, 0.0)" />
</linearGradient>
</defs>
<circle cx="110" cy="110" r="42" fill="none" stroke="rgba(74,102,216,0.45)" strokeWidth="1" strokeDasharray="3 4" />
<circle cx="110" cy="110" r="70" fill="none" stroke="rgba(222,224,240,0.18)" strokeWidth="1" strokeDasharray="2 6" />
<circle cx="110" cy="110" r="96" fill="none" stroke="rgba(74,102,216,0.22)" strokeWidth="1" />
<circle cx="110" cy="110" r="42" fill="none" stroke="rgba(74,102,216,0.7)" strokeWidth="1.2">
<animate attributeName="r" values="42;96;42" dur="4.8s" repeatCount="indefinite" />
<animate attributeName="opacity" values="0.7;0;0.7" dur="4.8s" repeatCount="indefinite" />
</circle>
<g>
<circle cx="110" cy="110" r="14" fill="url(#dcta-core)" />
<circle cx="110" cy="110" r="18" fill="none" stroke="rgba(222,224,240,0.55)" strokeWidth="1" />
</g>
<g transform="translate(110 110)">
<g>
<circle r="3" cx="70" cy="0" fill="#DEE0F0">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="9s" repeatCount="indefinite" />
</circle>
</g>
<g>
<circle r="2.5" cx="-96" cy="0" fill="#A6B2D8">
<animateTransform attributeName="transform" type="rotate" from="0" to="-360" dur="14s" repeatCount="indefinite" />
</circle>
</g>
</g>
</svg>
<span className="dcta-orbit-label">Dubai · 25.20°N</span>
</div>
<div className="dcta-panel-rows">
<div className="dcta-row">
<span className="dcta-row-k">Showroom</span>
<span className="dcta-row-v">Dubai · By appointment</span>
</div>
<div className="dcta-row">
<span className="dcta-row-k">Coverage</span>
<span className="dcta-row-v">UAE-wide</span>
</div>
<div className="dcta-row">
<span className="dcta-row-k">Response</span>
<span className="dcta-row-v"> 1 business day</span>
</div>
</div>
</aside>
</div>
</div>
<style jsx>{`
.dcta {
position: relative;
isolation: isolate;
overflow: hidden;
border-radius: 24px;
border: 1px solid rgba(74, 102, 216, 0.18);
background:
radial-gradient(ellipse 60% 100% at 0% 0%, rgba(58, 85, 196, 0.16), transparent 55%),
radial-gradient(ellipse 60% 100% at 100% 100%, rgba(136, 145, 199, 0.14), transparent 55%),
linear-gradient(135deg, rgba(14, 13, 22, 0.92), rgba(6, 6, 10, 0.97));
box-shadow:
0 30px 90px rgba(0, 0, 0, 0.55),
inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
.dcta-glow {
position: absolute;
border-radius: 999px;
filter: blur(110px);
pointer-events: none;
}
.dcta-glow-a {
width: 520px;
height: 520px;
top: -180px;
left: -160px;
background: rgba(58, 85, 196, 0.42);
opacity: 0.55;
animation: dcta-drift 16s ease-in-out infinite alternate;
}
.dcta-glow-b {
width: 480px;
height: 480px;
bottom: -200px;
right: -160px;
background: rgba(136, 145, 199, 0.32);
opacity: 0.45;
animation: dcta-drift 22s ease-in-out infinite alternate-reverse;
}
@keyframes dcta-drift {
0% { transform: translate(0, 0); }
100% { transform: translate(24px, -16px); }
}
.dcta-grid {
position: absolute;
inset: 0;
background:
linear-gradient(rgba(74, 102, 216, 0.06) 1px, transparent 1px),
linear-gradient(90deg, rgba(74, 102, 216, 0.06) 1px, transparent 1px);
background-size: 48px 48px;
mask-image: radial-gradient(ellipse 70% 90% at 30% 40%, #000 25%, transparent 80%);
-webkit-mask-image: radial-gradient(ellipse 70% 90% at 30% 40%, #000 25%, transparent 80%);
pointer-events: none;
}
.dcta-scan {
position: absolute;
inset: 0;
background: repeating-linear-gradient(
180deg,
transparent 0,
transparent 3px,
rgba(222, 224, 240, 0.018) 3px,
rgba(222, 224, 240, 0.018) 4px
);
mix-blend-mode: overlay;
opacity: 0.6;
pointer-events: none;
}
.dcta-inner {
position: relative;
z-index: 1;
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: clamp(1.5rem, 3vw, 2.5rem);
padding: clamp(1.6rem, 3.8vw, 2.8rem);
align-items: center;
}
.dcta-text {
display: flex;
flex-direction: column;
gap: 1rem;
max-width: 640px;
}
.dcta-eyebrow {
display: inline-flex;
align-items: center;
gap: 0.6rem;
font-size: 0.6rem;
letter-spacing: 0.32em;
text-transform: uppercase;
font-weight: 800;
color: #8891C7;
width: fit-content;
}
.dcta-eyebrow-dot {
width: 8px;
height: 8px;
border-radius: 999px;
background: #DEE0F0;
box-shadow: 0 0 14px rgba(222, 224, 240, 0.85);
animation: dcta-pulse 2.2s ease-in-out infinite;
}
@keyframes dcta-pulse {
0%, 100% { opacity: 0.45; transform: scale(0.85); }
50% { opacity: 1; transform: scale(1.12); }
}
.dcta-title {
margin: 0;
font-size: clamp(1.8rem, 4.2vw, 2.8rem);
line-height: 1.05;
font-weight: 300;
letter-spacing: -0.03em;
color: #FFFFFF;
}
.dcta-title :global(.text-gradient) { font-weight: 500; }
.dcta-desc {
margin: 0;
color: #DEE0F0;
font-size: clamp(0.95rem, 1.8vw, 1.05rem);
line-height: 1.65;
max-width: 540px;
}
.dcta-chips {
list-style: none;
margin: 0.25rem 0 0;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 0.4rem;
}
.dcta-chip {
display: inline-flex;
align-items: center;
gap: 0.45rem;
padding: 0.4rem 0.7rem;
border-radius: 999px;
border: 1px solid rgba(222, 224, 240, 0.12);
background: rgba(20, 19, 26, 0.55);
color: #DEE0F0;
font-size: 0.78rem;
font-weight: 600;
letter-spacing: 0.01em;
transition: border-color 0.3s, background 0.3s, color 0.3s;
}
.dcta-chip:hover {
border-color: rgba(74, 102, 216, 0.45);
background: rgba(58, 85, 196, 0.14);
color: #FFFFFF;
}
.dcta-chip-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
border-radius: 999px;
color: #DEE0F0;
background: rgba(74, 102, 216, 0.22);
border: 1px solid rgba(74, 102, 216, 0.45);
}
.dcta-actions {
display: flex;
flex-wrap: wrap;
gap: 0.6rem;
margin-top: 0.35rem;
}
.dcta-meta {
display: inline-flex;
align-items: center;
gap: 0.55rem;
margin-top: 0.4rem;
color: #8891C7;
font-size: 0.78rem;
letter-spacing: 0.01em;
}
.dcta-meta-dot {
width: 7px;
height: 7px;
border-radius: 999px;
background: #7FD6D0;
box-shadow: 0 0 10px rgba(127, 214, 208, 0.7);
animation: dcta-pulse 2.4s ease-in-out infinite;
}
/* RIGHT PANEL */
.dcta-panel {
display: none;
position: relative;
border-radius: 18px;
border: 1px solid rgba(74, 102, 216, 0.22);
background:
radial-gradient(ellipse 80% 80% at 50% 30%, rgba(58, 85, 196, 0.18), transparent 65%),
linear-gradient(180deg, rgba(14, 13, 22, 0.75), rgba(6, 6, 10, 0.92));
padding: 1rem 1.1rem 1.1rem;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
overflow: hidden;
}
.dcta-panel-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.5rem;
margin-bottom: 0.5rem;
}
.dcta-panel-tag {
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 0.62rem;
letter-spacing: 0.32em;
color: #DEE0F0;
font-weight: 800;
}
.dcta-panel-live {
display: inline-flex;
align-items: center;
gap: 0.4rem;
font-size: 0.62rem;
letter-spacing: 0.22em;
font-weight: 700;
color: #7FD6D0;
text-transform: uppercase;
}
.dcta-panel-live-dot {
width: 7px;
height: 7px;
border-radius: 999px;
background: #7FD6D0;
box-shadow: 0 0 10px rgba(127, 214, 208, 0.75);
animation: dcta-pulse 1.8s ease-in-out infinite;
}
.dcta-orbit {
position: relative;
aspect-ratio: 1 / 1;
border-radius: 14px;
border: 1px solid rgba(222, 224, 240, 0.06);
background:
radial-gradient(ellipse 80% 80% at 50% 50%, rgba(58, 85, 196, 0.18), transparent 70%),
linear-gradient(180deg, rgba(10, 10, 14, 0.6), rgba(6, 6, 10, 0.9));
overflow: hidden;
}
.dcta-orbit-svg {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.dcta-orbit-label {
position: absolute;
left: 12px;
bottom: 10px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 0.62rem;
letter-spacing: 0.18em;
color: #8891C7;
}
.dcta-panel-rows {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-top: 0.85rem;
}
.dcta-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.5rem;
padding: 0.55rem 0.7rem;
border-radius: 10px;
border: 1px solid rgba(222, 224, 240, 0.06);
background: rgba(10, 10, 14, 0.55);
}
.dcta-row-k {
font-size: 0.6rem;
letter-spacing: 0.26em;
font-weight: 800;
color: #8891C7;
text-transform: uppercase;
}
.dcta-row-v {
font-size: 0.82rem;
font-weight: 600;
color: #FFFFFF;
}
/* DESKTOP */
@media (min-width: 980px) {
.dcta-inner {
grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
gap: clamp(1.8rem, 3vw, 3rem);
padding: clamp(2rem, 3.6vw, 3rem);
}
.dcta-panel { display: block; }
}
@media (max-width: 520px) {
.dcta-actions :global(.cta-btn) {
width: 100%;
justify-content: space-between;
}
}
@media (prefers-reduced-motion: reduce) {
.dcta-glow-a, .dcta-glow-b, .dcta-eyebrow-dot, .dcta-meta-dot, .dcta-panel-live-dot {
animation: none !important;
}
}
`}</style>
</motion.section>
);
}

View File

@ -237,13 +237,15 @@ export function FeaturedRobotsShowcase({ robots }: Props) {
))}
</ul>
<div className="frs-cta-row">
<CTAButton href={`/robots/${active.slug}/`} variant="primary" size="lg" arrow="up-right">
View robot
</CTAButton>
<CTAButton href="/book-demo/" variant="secondary" size="lg" arrow="right">
Book demo
</CTAButton>
<div className="frs-cta-block">
<div className="frs-cta-row">
<CTAButton href={`/robots/${active.slug}/`} variant="primary" size="lg" arrow="up-right">
View robot
</CTAButton>
<CTAButton href="/book-demo/" variant="secondary" size="lg" arrow="right">
Book demo
</CTAButton>
</div>
<CTAButton href="/contact/" variant="link" size="md" arrow="right">
Request price
</CTAButton>
@ -287,7 +289,7 @@ export function FeaturedRobotsShowcase({ robots }: Props) {
<span className="frs-tile-name">{r.name}</span>
<span className="frs-tile-avail" aria-label="Available in UAE">
<span className="frs-tile-avail-dot" aria-hidden />
Available in UAE
UAE available
</span>
</div>
{isOn && (
@ -420,9 +422,10 @@ export function FeaturedRobotsShowcase({ robots }: Props) {
color: #ECEEF6;
font-size: 0.6rem;
font-weight: 800;
letter-spacing: 0.28em;
letter-spacing: 0.26em;
text-transform: uppercase;
backdrop-filter: blur(10px);
white-space: nowrap;
}
.frs-feat-tag-dot {
width: 6px;
@ -446,9 +449,10 @@ export function FeaturedRobotsShowcase({ robots }: Props) {
border: 1px solid;
font-size: 0.6rem;
font-weight: 800;
letter-spacing: 0.28em;
letter-spacing: 0.26em;
text-transform: uppercase;
backdrop-filter: blur(10px);
white-space: nowrap;
}
.frs-brand-dot {
width: 6px;
@ -620,23 +624,31 @@ export function FeaturedRobotsShowcase({ robots }: Props) {
.frs-hero-copy-stack {
display: flex;
flex-direction: column;
gap: 1rem;
gap: 0;
max-width: 600px;
}
.frs-hero-copy-stack > .frs-kicker { margin-top: 0 !important; }
.frs-hero-copy-stack > .frs-name { margin-top: 1.5rem !important; }
.frs-hero-copy-stack > .frs-tagline { margin-top: 1.75rem !important; }
.frs-hero-copy-stack > .frs-chips { margin-top: 3rem !important; margin-bottom: 10px !important; }
.frs-hero-copy-stack > .frs-features { margin-top: 3rem !important; }
.frs-hero-copy-stack > .frs-cta-block { margin-top: 2.85rem !important; }
.frs-kicker {
display: inline-flex;
align-items: center;
gap: 0.5rem;
font-size: 0.62rem;
font-weight: 800;
letter-spacing: 0.32em;
letter-spacing: 0.3em;
text-transform: uppercase;
color: #DEE0F0;
white-space: nowrap;
}
.frs-name {
margin: 0;
font-size: clamp(2.1rem, 5.2vw, 3.6rem);
font-weight: 300;
line-height: 1.02;
line-height: 1.18;
letter-spacing: -0.045em;
color: #FFFFFF;
filter: drop-shadow(0 6px 24px rgba(0, 0, 0, 0.6));
@ -646,31 +658,38 @@ export function FeaturedRobotsShowcase({ robots }: Props) {
margin: 0;
color: #F2F4FA;
font-size: clamp(1rem, 1.7vw, 1.12rem);
line-height: 1.6;
max-width: 540px;
line-height: 1.9;
max-width: 620px;
text-shadow: 0 2px 16px rgba(0, 0, 0, 0.55);
hyphens: none;
-webkit-hyphens: none;
word-break: normal;
overflow-wrap: normal;
text-wrap: pretty;
}
.frs-chips {
list-style: none;
margin: 0;
margin: 0 0 10px 0;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 0.4rem;
gap: 0.55rem;
}
.frs-chip {
display: inline-flex;
align-items: center;
gap: 0.42rem;
padding: 0.35rem 0.75rem;
gap: 0.45rem;
height: 30px;
padding: 0 0.85rem;
border-radius: 999px;
border: 1px solid rgba(222, 224, 240, 0.22);
background: rgba(14, 13, 18, 0.55);
font-size: 0.6rem;
letter-spacing: 0.22em;
letter-spacing: 0.2em;
text-transform: uppercase;
font-weight: 700;
color: #DEE0F0;
white-space: nowrap;
backdrop-filter: blur(10px);
}
.frs-chip-dot {
@ -717,31 +736,39 @@ export function FeaturedRobotsShowcase({ robots }: Props) {
padding: 0;
display: flex;
flex-direction: column;
gap: 0.5rem;
gap: 1.35rem;
}
.frs-feature {
display: grid;
grid-template-columns: 14px 1fr;
align-items: start;
gap: 0.7rem;
gap: 0.85rem;
color: #F0F2F8;
font-size: 0.96rem;
line-height: 1.55;
font-size: 0.97rem;
line-height: 1.85;
}
.frs-feature-bullet {
margin-top: 0.55rem;
margin-top: 0.75rem;
width: 6px;
height: 6px;
border-radius: 999px;
background: linear-gradient(135deg, #DEE0F0, #3a55c4);
box-shadow: 0 0 12px rgba(58, 85, 196, 0.55);
}
.frs-cta-block {
display: flex;
flex-direction: column;
gap: 1rem;
align-items: flex-start;
}
.frs-cta-row {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-top: 0.4rem;
gap: 0.7rem;
align-items: center;
margin-top: 10px;
}
.frs-cta-block :global(.cta-link) { padding-left: 0.25rem; }
.frs-cta-primary {
position: relative;
display: inline-flex;
@ -863,10 +890,11 @@ export function FeaturedRobotsShowcase({ robots }: Props) {
.frs-tile {
position: relative;
display: grid;
grid-template-columns: 132px minmax(0, 1fr);
grid-template-columns: 116px minmax(0, 1fr);
align-items: center;
gap: 0.95rem;
padding: 0.85rem 1rem;
gap: 0.9rem;
padding: 0.85rem 1rem 0.85rem 0.85rem;
min-height: 132px;
border-radius: 20px;
border: 1px solid rgba(222, 224, 240, 0.14);
background:
@ -907,8 +935,8 @@ export function FeaturedRobotsShowcase({ robots }: Props) {
}
.frs-tile-img-wrap {
position: relative;
width: 132px;
height: 116px;
width: 116px;
height: 108px;
border-radius: 14px;
overflow: hidden;
background:
@ -916,6 +944,7 @@ export function FeaturedRobotsShowcase({ robots }: Props) {
radial-gradient(ellipse 60% 40% at 50% 25%, rgba(255, 255, 255, 0.06), transparent 70%),
linear-gradient(180deg, rgba(28, 27, 33, 0.7), rgba(10, 10, 12, 0.95));
border: 1px solid rgba(222, 224, 240, 0.12);
flex-shrink: 0;
}
.frs-tile-img-wrap :global(img) {
transition: transform 0.4s ease, filter 0.4s ease;
@ -937,33 +966,42 @@ export function FeaturedRobotsShowcase({ robots }: Props) {
.frs-tile-meta {
display: flex;
flex-direction: column;
gap: 0.25rem;
justify-content: center;
gap: 0.3rem;
min-width: 0;
padding-right: 28px;
}
.frs-tile-brand {
font-size: 0.6rem;
letter-spacing: 0.22em;
font-size: 0.58rem;
letter-spacing: 0.2em;
text-transform: uppercase;
color: color-mix(in srgb, var(--frs-acc) 80%, white);
font-weight: 700;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.frs-tile-name {
font-size: 1.02rem;
font-size: 1rem;
font-weight: 700;
color: #FFFFFF;
letter-spacing: -0.01em;
line-height: 1.15;
line-height: 1.2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.frs-tile-avail {
display: inline-flex;
align-items: center;
gap: 0.38rem;
margin-top: 0.25rem;
gap: 0.4rem;
margin-top: 0.15rem;
font-size: 0.56rem;
letter-spacing: 0.26em;
letter-spacing: 0.18em;
text-transform: uppercase;
font-weight: 700;
color: #B5BDDB;
white-space: nowrap;
}
.frs-tile-avail-dot {
width: 5px;
@ -1002,8 +1040,8 @@ export function FeaturedRobotsShowcase({ robots }: Props) {
.frs-utility {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 0.75rem;
padding: 1rem 1.15rem;
gap: 0.85rem;
padding: 1rem 1.25rem;
border-radius: 18px;
border: 1px solid rgba(222, 224, 240, 0.12);
background:
@ -1013,24 +1051,40 @@ export function FeaturedRobotsShowcase({ robots }: Props) {
}
.frs-utility-block {
display: grid;
grid-template-columns: 28px minmax(0, 1fr);
gap: 0.65rem;
align-items: start;
grid-template-columns: 32px minmax(0, 1fr);
gap: 0.75rem;
align-items: center;
color: #ECEEF6;
}
.frs-utility-block :global(svg) {
margin-top: 4px;
width: 16px;
height: 16px;
color: #DEE0F0;
margin: 0;
justify-self: center;
}
.frs-utility-block > div {
display: flex;
flex-direction: column;
gap: 0.2rem;
min-width: 0;
}
.frs-utility-block > div { display: flex; flex-direction: column; gap: 0.15rem; }
.frs-utility-label {
font-size: 0.58rem;
letter-spacing: 0.28em;
letter-spacing: 0.24em;
text-transform: uppercase;
color: #8891C7;
font-weight: 700;
white-space: nowrap;
}
.frs-utility-value {
color: #FFFFFF;
font-size: 0.9rem;
font-weight: 600;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.frs-utility-value { color: #FFFFFF; font-size: 0.9rem; font-weight: 600; }
.frs-utility-link {
position: relative;
display: inline-flex;
@ -1102,15 +1156,15 @@ export function FeaturedRobotsShowcase({ robots }: Props) {
/* DESKTOP */
@media (min-width: 900px) {
.frs-hero {
padding: clamp(1.5rem, 2.8vw, 2.25rem) clamp(1.75rem, 3vw, 2.5rem);
padding: clamp(1.75rem, 3vw, 2.5rem) clamp(1.75rem, 3vw, 2.5rem);
}
.frs-hero-body {
grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
gap: clamp(0.75rem, 1.6vw, 1.25rem);
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: clamp(1.5rem, 2.5vw, 2.25rem);
align-items: center;
}
.frs-hero-stage { min-height: clamp(420px, 56vh, 560px); }
.frs-hero-copy { padding-left: 0; }
.frs-hero-copy { padding-left: 0.5rem; }
.frs-utility {
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
align-items: center;
@ -1120,10 +1174,11 @@ export function FeaturedRobotsShowcase({ robots }: Props) {
}
@media (min-width: 1280px) {
.frs-hero-body {
grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
gap: clamp(1rem, 1.8vw, 1.5rem);
grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
gap: clamp(2rem, 3vw, 3rem);
}
.frs-hero-stage { min-height: clamp(460px, 58vh, 600px); }
.frs-hero-copy { padding-left: 1rem; }
}
@media (min-width: 1200px) {
.frs-rail {
@ -1133,8 +1188,28 @@ export function FeaturedRobotsShowcase({ robots }: Props) {
@media (max-width: 600px) {
.frs-hero { border-radius: 22px; padding: 1.1rem 1rem; }
.frs-name { font-size: clamp(1.7rem, 8vw, 2.4rem); }
.frs-tile { grid-template-columns: 84px minmax(0, 1fr); }
.frs-tile-img-wrap { width: 84px; height: 80px; }
.frs-rail {
display: flex;
grid-template-columns: none;
overflow-x: auto;
scroll-snap-type: x mandatory;
scrollbar-width: none;
-webkit-overflow-scrolling: touch;
padding-bottom: 0.5rem;
margin: 0 calc(-1 * var(--page-pad, 1rem));
padding-left: var(--page-pad, 1rem);
padding-right: var(--page-pad, 1rem);
}
.frs-rail::-webkit-scrollbar { display: none; }
.frs-tile {
flex: 0 0 82%;
scroll-snap-align: start;
grid-template-columns: 88px minmax(0, 1fr);
min-height: 116px;
}
.frs-tile-img-wrap { width: 88px; height: 92px; }
.frs-cta-row :global(.cta-btn) { width: 100%; justify-content: space-between; }
.frs-utility { padding: 0.85rem 1rem; }
}
@media (prefers-reduced-motion: reduce) {
.frs-hero-aurora, .frs-hero-sweep, .frs-hero-halo,

View File

@ -1,250 +0,0 @@
'use client';
import { useRef } from 'react';
import { motion, useScroll, useTransform } from 'framer-motion';
import { Boxes, Cog, ClipboardCheck, GraduationCap, Wrench } from 'lucide-react';
import type { LucideIcon } from 'lucide-react';
const ease = [0.16, 1, 0.3, 1] as const;
type Step = { n: string; title: string; body: string; Icon: LucideIcon; accent: string };
const STEPS: Step[] = [
{
n: '01',
title: 'Procurement',
body: 'Exclusive UAE access to Unitree & Pudu lineups.',
Icon: Boxes,
accent: '#DEE0F0',
},
{
n: '02',
title: 'Configuration',
body: 'Persona, attire, routes, languages, and brand fit.',
Icon: Cog,
accent: '#A6B2D8',
},
{
n: '03',
title: 'Deployment',
body: 'Venue mapping, installation, and live commissioning.',
Icon: ClipboardCheck,
accent: '#7FD6D0',
},
{
n: '04',
title: 'Training',
body: 'Staff onboarding and operations handover.',
Icon: GraduationCap,
accent: '#F5C089',
},
{
n: '05',
title: 'Support',
body: 'Remote diagnostics and on-site service in the UAE.',
Icon: Wrench,
accent: '#C9B7E0',
},
];
export function HowItWorks() {
const ref = useRef<HTMLDivElement | null>(null);
const { scrollYProgress } = useScroll({
target: ref,
offset: ['start 85%', 'end 25%'],
});
const lineHeight = useTransform(scrollYProgress, [0, 1], ['0%', '100%']);
return (
<div className="tl" ref={ref}>
<div className="tl-track" aria-hidden>
<motion.span className="tl-track-fill" style={{ height: lineHeight }} />
</div>
<ol className="tl-list" role="list">
{STEPS.map((s, i) => (
<motion.li
key={s.n}
className="tl-step"
style={{ ['--tl-acc' as string]: s.accent }}
initial={{ opacity: 0, x: -24 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true, margin: '-15%' }}
transition={{ duration: 0.6, ease, delay: 0.08 * i }}
>
<span className="tl-dot" aria-hidden>
<span className="tl-dot-pulse" />
<span className="tl-dot-core" />
</span>
<div className="tl-card">
<div className="tl-head">
<span className="tl-num">{s.n}</span>
<span className="tl-bar" aria-hidden />
<span className="tl-icon" aria-hidden>
<s.Icon size={14} />
</span>
</div>
<h3 className="tl-title">{s.title}</h3>
<p className="tl-body">{s.body}</p>
</div>
</motion.li>
))}
</ol>
<style jsx>{`
.tl {
position: relative;
padding: 0.5rem 0;
}
.tl-track {
position: absolute;
left: 24px;
top: 16px;
bottom: 16px;
width: 2px;
border-radius: 2px;
background: linear-gradient(180deg,
rgba(222, 224, 240, 0.08) 0%,
rgba(58, 85, 196, 0.12) 50%,
rgba(222, 224, 240, 0.08) 100%);
overflow: hidden;
pointer-events: none;
}
.tl-track-fill {
display: block;
width: 100%;
background: linear-gradient(180deg,
#DEE0F0 0%,
#4a66d8 50%,
#273F94 100%);
box-shadow:
0 0 12px rgba(74, 102, 216, 0.7),
0 0 28px rgba(58, 85, 196, 0.4);
}
.tl-list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: clamp(1rem, 1.6vw, 1.4rem);
}
.tl-step {
position: relative;
display: grid;
grid-template-columns: 50px minmax(0, 1fr);
gap: 1rem;
align-items: start;
}
.tl-dot {
position: relative;
width: 50px;
height: 50px;
display: inline-flex;
align-items: center;
justify-content: center;
}
.tl-dot-pulse {
position: absolute;
width: 36px;
height: 36px;
border-radius: 999px;
background: var(--tl-acc);
opacity: 0.18;
filter: blur(10px);
animation: tl-pulse 2.4s ease-in-out infinite;
}
.tl-dot-core {
position: relative;
width: 16px;
height: 16px;
border-radius: 999px;
background: radial-gradient(circle at 30% 30%, #FFFFFF, var(--tl-acc) 65%);
box-shadow:
0 0 0 4px rgba(10, 10, 14, 0.95),
0 0 0 5px color-mix(in srgb, var(--tl-acc) 55%, transparent),
0 0 18px color-mix(in srgb, var(--tl-acc) 65%, transparent);
}
@keyframes tl-pulse {
0%, 100% { transform: scale(0.85); opacity: 0.18; }
50% { transform: scale(1.15); opacity: 0.42; }
}
.tl-card {
position: relative;
padding: clamp(1rem, 1.8vw, 1.35rem) clamp(1.1rem, 2vw, 1.5rem);
border-radius: 18px;
border: 1px solid rgba(222, 224, 240, 0.12);
background:
radial-gradient(ellipse 60% 80% at 100% 0%, color-mix(in srgb, var(--tl-acc) 14%, transparent), transparent 60%),
linear-gradient(135deg, rgba(20, 19, 26, 0.7), rgba(8, 8, 12, 0.92));
overflow: hidden;
transition: border-color 0.35s, transform 0.35s, box-shadow 0.35s;
}
.tl-step:hover .tl-card {
border-color: color-mix(in srgb, var(--tl-acc) 45%, transparent);
transform: translateX(2px);
box-shadow:
0 20px 48px rgba(0, 0, 0, 0.55),
0 0 0 1px color-mix(in srgb, var(--tl-acc) 32%, transparent),
0 0 32px color-mix(in srgb, var(--tl-acc) 22%, transparent);
}
.tl-head {
display: flex;
align-items: center;
gap: 0.65rem;
margin-bottom: 0.55rem;
}
.tl-num {
font-size: 0.6rem;
letter-spacing: 0.32em;
color: color-mix(in srgb, var(--tl-acc) 78%, white);
font-weight: 800;
text-transform: uppercase;
}
.tl-bar {
flex: 1;
height: 1px;
background: linear-gradient(90deg, color-mix(in srgb, var(--tl-acc) 50%, transparent), transparent);
}
.tl-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 26px;
height: 26px;
border-radius: 8px;
color: color-mix(in srgb, var(--tl-acc) 90%, white);
border: 1px solid color-mix(in srgb, var(--tl-acc) 35%, transparent);
background: color-mix(in srgb, var(--tl-acc) 12%, rgba(14, 13, 18, 0.55));
}
.tl-title {
margin: 0 0 0.35rem;
font-size: 1.18rem;
font-weight: 700;
color: #FFFFFF;
letter-spacing: -0.01em;
}
.tl-body {
margin: 0;
color: #DEE0F0;
font-size: 0.92rem;
line-height: 1.55;
}
@media (min-width: 900px) {
.tl { padding: 0.5rem 0; }
.tl-track { left: 32px; }
.tl-step { grid-template-columns: 64px minmax(0, 1fr); gap: 1.25rem; }
.tl-dot { width: 64px; height: 64px; }
}
@media (prefers-reduced-motion: reduce) {
.tl-dot-pulse { animation: none !important; }
}
`}</style>
</div>
);
}

View File

@ -1,73 +1,339 @@
'use client';
import { motion } from 'framer-motion';
import Link from 'next/link';
import {
Building2,
Utensils,
Hotel,
ShoppingBag,
HeartPulse,
GraduationCap,
Shield,
Warehouse,
Sparkles,
Landmark,
ArrowRight,
} from 'lucide-react';
import type { LucideIcon } from 'lucide-react';
import { INDUSTRIES, type Industry } from '@/data/industries';
const ICONS: Record<Industry['icon'], string> = {
building: 'M3 21V8l9-5 9 5v13h-6v-6h-6v6H3Z',
utensils: 'M4 2h2v9a2 2 0 1 1-4 0V2h2Zm9 0h2v7l2 2v11h-2v-9h-2Zm-3 0h2v9a2 2 0 1 1-4 0V2h2Z',
hotel: 'M2 21V7h20v14h-2v-3H4v3H2Zm5-7a3 3 0 1 1 0-6 3 3 0 0 1 0 6Zm5 0V8h8v6h-8Z',
'shopping-bag': 'M6 6V5a6 6 0 0 1 12 0v1h3v15H3V6h3Zm2 0h8V5a4 4 0 0 0-8 0v1Z',
'heart-pulse': 'M12 21s-7-4.5-9-9a5 5 0 0 1 9-3 5 5 0 0 1 9 3c-2 4.5-9 9-9 9Zm-2-8 2-3 2 5 2-3h3',
'graduation-cap': 'M12 3 2 8l10 5 10-5-10-5Zm-7 7v4l7 3 7-3v-4l-7 3-7-3Z',
shield: 'M12 2 4 5v6c0 5 3.5 9 8 11 4.5-2 8-6 8-11V5l-8-3Z',
warehouse: 'M3 21V9l9-5 9 5v12H3Zm5-9h8v8H8v-8Z',
sparkles: 'M12 2l2 6 6 2-6 2-2 6-2-6-6-2 6-2 2-6Zm7 12l1 3 3 1-3 1-1 3-1-3-3-1 3-1 1-3Z',
landmark: 'M2 21v-2h20v2H2Zm2-4v-8h2v8H4Zm4 0v-8h2v8H8Zm4 0v-8h2v8h-2Zm4 0v-8h2v8h-2ZM12 2l10 5H2l10-5Z',
const ease = [0.16, 1, 0.3, 1] as const;
const ICON_MAP: Record<Industry['icon'], LucideIcon> = {
building: Building2,
utensils: Utensils,
hotel: Hotel,
'shopping-bag': ShoppingBag,
'heart-pulse': HeartPulse,
'graduation-cap': GraduationCap,
shield: Shield,
warehouse: Warehouse,
sparkles: Sparkles,
landmark: Landmark,
};
const SHORT_COPY: Record<string, string> = {
hospitality: 'Service and delivery robots that help hotels, lounges, and guest venues operate smoothly.',
restaurants: 'Delivery robots that support faster table service and reduce staff walking time.',
hotels: 'Autonomous delivery and concierge-style robotics for premium guest experiences.',
malls: 'Cleaning, service, and activation robots for high-traffic retail environments.',
healthcare: 'Autonomous transport robots for supplies, meals, and routine internal deliveries.',
education: 'Humanoid and quadruped robotics for STEM labs and innovation programs.',
security: 'Quadruped robots for patrol, inspection, and perimeter monitoring.',
warehousing: 'Inspection and delivery robots for repetitive facility operations.',
events: 'Humanoid and service robots that elevate brand activations and live events.',
government: 'Smart-city robotics for public spaces, civic programs, and innovation hubs.',
};
const STATS = [
{ value: '8+', label: 'Sectors served' },
{ value: '4', label: 'Robot families' },
{ value: 'UAE-wide', label: 'Deployment' },
{ value: 'Dubai', label: 'Local support' },
] as const;
export function IndustryUseCases({ limit }: { limit?: number }) {
const list = limit ? INDUSTRIES.slice(0, limit) : INDUSTRIES;
return (
<div
style={{
display: 'grid',
gap: '1rem',
gridTemplateColumns: 'repeat(auto-fit, minmax(min(280px, 100%), 1fr))',
}}
>
{list.map((i) => (
<div key={i.id} className="card" style={{ padding: '1.5rem', display: 'flex', flexDirection: 'column', gap: '1rem' }}>
<div
style={{
display: 'flex',
alignItems: 'center',
gap: '0.875rem',
}}
>
<div
style={{
width: 44,
height: 44,
borderRadius: 12,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: `${i.accent}1A`,
border: `1px solid ${i.accent}55`,
}}
>
<svg width="20" height="20" viewBox="0 0 24 24" fill={i.accent} aria-hidden="true">
<path d={ICONS[i.icon]} />
</svg>
</div>
<h3 style={{ margin: 0, fontSize: '1.1rem', fontWeight: 600 }}>{i.name}</h3>
</div>
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
<div>
<div style={{ fontSize: '0.68rem', letterSpacing: '0.22em', textTransform: 'uppercase', color: '#6a73a5', marginBottom: 4 }}>Problem</div>
<p style={{ margin: 0, color: '#DEE0F0', fontSize: '0.92rem', lineHeight: 1.55 }}>{i.problem}</p>
</div>
<div>
<div style={{ fontSize: '0.68rem', letterSpacing: '0.22em', textTransform: 'uppercase', color: '#6a73a5', marginBottom: 4 }}>Solution</div>
<p style={{ margin: 0, color: '#e8e0cf', fontSize: '0.92rem', lineHeight: 1.55 }}>{i.solution}</p>
</div>
<div>
<div style={{ fontSize: '0.68rem', letterSpacing: '0.22em', textTransform: 'uppercase', color: i.accent, marginBottom: 4 }}>Benefit</div>
<p style={{ margin: 0, color: '#ffffff', fontSize: '0.92rem', lineHeight: 1.55 }}>{i.benefit}</p>
</div>
</div>
</div>
))}
</div>
<section className="iu" aria-label="Industries served">
{/* STATS ROW */}
<motion.ul
className="iu-stats"
role="list"
initial={{ opacity: 0, y: 12 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-10%' }}
transition={{ duration: 0.6, ease }}
>
{STATS.map((s) => (
<li key={s.label} className="iu-stat">
<span className="iu-stat-value">{s.value}</span>
<span className="iu-stat-label">{s.label}</span>
</li>
))}
</motion.ul>
{/* GRID */}
<div className="iu-grid">
{list.map((industry, i) => (
<IndustryCard key={industry.id} industry={industry} delay={0.04 * i} />
))}
</div>
<style jsx>{`
.iu {
position: relative;
display: flex;
flex-direction: column;
gap: clamp(1.75rem, 3.5vw, 2.75rem);
padding: clamp(1.5rem, 3vw, 2.5rem) clamp(1.25rem, 2.5vw, 2rem);
border-radius: 24px;
background: #F6F7F9;
color: #0F1116;
}
/* STATS */
.iu-stats {
list-style: none;
margin: 0;
padding: 0.4rem 0;
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 1rem 1.5rem;
border-top: 1px solid rgba(16, 22, 46, 0.08);
border-bottom: 1px solid rgba(16, 22, 46, 0.08);
}
.iu-stat {
display: flex;
flex-direction: column;
gap: 0.2rem;
padding: 0.85rem 0.25rem;
}
.iu-stat-value {
font-size: clamp(1.65rem, 3vw, 2.2rem);
font-weight: 600;
letter-spacing: -0.025em;
line-height: 1;
color: #0F1116;
}
.iu-stat-label {
font-size: 0.7rem;
letter-spacing: 0.18em;
text-transform: uppercase;
font-weight: 600;
color: #5b6076;
}
/* GRID */
.iu-grid {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 1rem;
}
@media (min-width: 600px) {
.iu-stats { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.iu-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.1rem; }
}
@media (min-width: 980px) {
.iu-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.25rem; }
}
@media (min-width: 1400px) {
.iu-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
`}</style>
</section>
);
}
function IndustryCard({ industry, delay }: { industry: Industry; delay: number }) {
const Icon = ICON_MAP[industry.icon];
const blurb = SHORT_COPY[industry.id] ?? industry.solution;
return (
<motion.div
initial={{ opacity: 0, y: 16 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-8%' }}
transition={{ duration: 0.55, ease, delay }}
>
<Link
href={`/industries/${industry.slug}/`}
className="ic"
style={{ ['--accent' as string]: industry.accent }}
aria-label={`Learn more about robotics for ${industry.name}`}
>
<div className="ic-media" aria-hidden>
<span className="ic-media-glow" />
<span className="ic-media-grid" />
<span className="ic-media-icon">
<Icon size={42} strokeWidth={1.4} />
</span>
<span className="ic-media-tag">{industry.name}</span>
</div>
<div className="ic-body">
<h3 className="ic-title">{industry.name}</h3>
<p className="ic-desc">{blurb}</p>
<span className="ic-cta">
<span>Learn more</span>
<span className="ic-cta-arrow" aria-hidden>
<ArrowRight size={14} strokeWidth={2} />
</span>
</span>
</div>
</Link>
<style jsx>{`
.ic {
position: relative;
display: flex;
flex-direction: column;
height: 100%;
background: #FFFFFF;
border: 1px solid rgba(16, 22, 46, 0.06);
border-radius: 18px;
overflow: hidden;
text-decoration: none;
color: inherit;
box-shadow: 0 4px 14px rgba(8, 12, 28, 0.04);
transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1),
box-shadow 0.4s, border-color 0.4s;
}
.ic:hover,
.ic:focus-visible {
transform: translateY(-3px);
border-color: rgba(74, 102, 216, 0.28);
box-shadow: 0 18px 36px rgba(8, 12, 28, 0.10), 0 2px 6px rgba(8, 12, 28, 0.04);
}
.ic:focus-visible {
outline: 2px solid #4a66d8;
outline-offset: 3px;
}
/* MEDIA AREA */
.ic-media {
position: relative;
aspect-ratio: 16 / 10;
background:
radial-gradient(ellipse 70% 80% at 30% 20%, color-mix(in srgb, var(--accent) 35%, white) 0%, transparent 60%),
linear-gradient(135deg, #EEF1F6 0%, #DDE3EE 100%);
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
.ic-media-glow {
position: absolute;
width: 60%;
height: 80%;
left: 20%;
top: 10%;
border-radius: 999px;
background: radial-gradient(circle at 50% 50%, rgba(74, 102, 216, 0.16), transparent 65%);
filter: blur(20px);
pointer-events: none;
}
.ic-media-grid {
position: absolute;
inset: 0;
background-image:
linear-gradient(rgba(16, 22, 46, 0.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(16, 22, 46, 0.05) 1px, transparent 1px);
background-size: 32px 32px;
mask-image: radial-gradient(ellipse 70% 80% at 50% 50%, #000 30%, transparent 80%);
-webkit-mask-image: radial-gradient(ellipse 70% 80% at 50% 50%, #000 30%, transparent 80%);
pointer-events: none;
}
.ic-media-icon {
position: relative;
z-index: 2;
display: inline-flex;
align-items: center;
justify-content: center;
width: 88px;
height: 88px;
border-radius: 22px;
color: #273F94;
background: rgba(255, 255, 255, 0.85);
border: 1px solid rgba(16, 22, 46, 0.06);
box-shadow: 0 8px 22px rgba(8, 12, 28, 0.08);
transition: transform 0.45s cubic-bezier(0.16, 1, 0.3, 1);
}
.ic:hover .ic-media-icon,
.ic:focus-visible .ic-media-icon {
transform: scale(1.06);
}
.ic-media-tag {
position: absolute;
left: 14px;
bottom: 12px;
z-index: 2;
padding: 0.32rem 0.65rem;
border-radius: 999px;
font-size: 0.62rem;
letter-spacing: 0.2em;
text-transform: uppercase;
font-weight: 700;
color: #273F94;
background: rgba(255, 255, 255, 0.85);
border: 1px solid rgba(39, 63, 148, 0.18);
}
/* BODY */
.ic-body {
display: flex;
flex-direction: column;
gap: 0.55rem;
padding: 1.1rem 1.15rem 1.15rem;
flex: 1;
}
.ic-title {
margin: 0;
font-size: 1.1rem;
font-weight: 600;
letter-spacing: -0.01em;
color: #0F1116;
}
.ic-desc {
margin: 0;
color: #4a4f63;
font-size: 0.9rem;
line-height: 1.55;
flex: 1;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.ic-cta {
display: inline-flex;
align-items: center;
gap: 0.45rem;
margin-top: 0.4rem;
font-size: 0.82rem;
font-weight: 600;
color: #273F94;
}
.ic-cta-arrow {
display: inline-flex;
align-items: center;
justify-content: center;
transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}
.ic:hover .ic-cta-arrow,
.ic:focus-visible .ic-cta-arrow {
transform: translateX(4px);
}
@media (prefers-reduced-motion: reduce) {
.ic, .ic-media-icon, .ic-cta-arrow { transition: none !important; }
.ic:hover, .ic:focus-visible { transform: none; }
.ic:hover .ic-media-icon, .ic:focus-visible .ic-media-icon { transform: none; }
}
`}</style>
</motion.div>
);
}

View File

@ -1,652 +0,0 @@
'use client';
import { motion } from 'framer-motion';
import { Boxes, Cog, ClipboardCheck, GraduationCap, Wrench, ShieldCheck, Activity, Layers } from 'lucide-react';
import type { LucideIcon } from 'lucide-react';
import { CTAButton } from '@/components/ui/CTAButton';
const ease = [0.16, 1, 0.3, 1] as const;
/* Abstract Dubai-centered coverage network */
type Node = { id: string; label: string; angle: number; radius: number };
const HQ = { x: 50, y: 50 };
const NODES: Node[] = [
{ id: 'abu-dhabi', label: 'Abu Dhabi', angle: 210, radius: 36 },
{ id: 'sharjah', label: 'Sharjah', angle: 30, radius: 24 },
{ id: 'ajman', label: 'Ajman', angle: 350, radius: 30 },
{ id: 'rak', label: 'Ras Al Khaimah', angle: 320, radius: 40 },
{ id: 'fujairah', label: 'Fujairah', angle: 80, radius: 38 },
];
const nodePos = (n: Node) => {
const rad = (n.angle * Math.PI) / 180;
return { x: HQ.x + Math.cos(rad) * n.radius, y: HQ.y + Math.sin(rad) * n.radius };
};
type Proof = { value: string; label: string; detail: string; Icon: LucideIcon };
const PROOFS: Proof[] = [
{ value: '11+', label: 'Robot models', detail: 'Unitree + Pudu portfolio', Icon: Layers },
{ value: 'UAE-wide', label: 'Coverage', detail: 'Deployment from Dubai HQ', Icon: ShieldCheck },
{ value: '1 day', label: 'Response SLA', detail: 'Sales & demo · 7 days a week', Icon: Activity },
];
type Step = { n: string; label: string; Icon: LucideIcon };
const STEPS: Step[] = [
{ n: '01', label: 'Procure', Icon: Boxes },
{ n: '02', label: 'Configure', Icon: Cog },
{ n: '03', label: 'Deploy', Icon: ClipboardCheck },
{ n: '04', label: 'Train', Icon: GraduationCap },
{ n: '05', label: 'Support', Icon: Wrench },
];
export function ServicesGrid() {
return (
<section className="net" aria-label="UAE robotics deployment network">
<div className="net-bg" aria-hidden />
<motion.div
className="net-glow"
aria-hidden
animate={{ opacity: [0.45, 0.75, 0.45], scale: [1, 1.04, 1] }}
transition={{ duration: 10, repeat: Infinity, ease: 'easeInOut' }}
/>
<div className="net-vignette" aria-hidden />
<header className="net-intro">
<span className="net-eyebrow">
<span className="net-eyebrow-dot" />
UAE Deployment
</span>
<h3 className="net-title">
<span className="text-gradient">Robotics deployment across the UAE.</span>
</h3>
<p className="net-desc">
From Dubai showroom demo to live venue deployment, our team handles procurement, configuration, installation, staff training, and ongoing support.
</p>
</header>
<div className="net-body">
{/* LEFT — network visual */}
<motion.figure
className="net-vis"
initial={{ opacity: 0, y: 18 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-12%' }}
transition={{ duration: 0.75, ease }}
aria-label="Dubai HQ deployment network reaching every emirate"
>
<span className="net-vis-tag">Dubai HQ · Coverage network</span>
<svg
className="net-vis-svg"
viewBox="0 0 400 400"
role="img"
aria-hidden="true"
preserveAspectRatio="xMidYMid meet"
>
<defs>
<radialGradient id="net-haze" cx="50%" cy="50%" r="50%">
<stop offset="0%" stopColor="rgba(74, 102, 216, 0.55)" />
<stop offset="65%" stopColor="rgba(58, 85, 196, 0.16)" />
<stop offset="100%" stopColor="rgba(58, 85, 196, 0)" />
</radialGradient>
<radialGradient id="net-hq" cx="50%" cy="50%" r="50%">
<stop offset="0%" stopColor="#FFFFFF" />
<stop offset="55%" stopColor="#DEE0F0" />
<stop offset="100%" stopColor="#4a66d8" />
</radialGradient>
<linearGradient id="net-route" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stopColor="rgba(222, 224, 240, 0.85)" />
<stop offset="100%" stopColor="rgba(74, 102, 216, 0.55)" />
</linearGradient>
<filter id="net-blur" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="2" />
</filter>
</defs>
{/* central haze */}
<circle cx="200" cy="200" r="170" fill="url(#net-haze)" />
{/* coverage rings */}
{[60, 100, 140, 175].map((r, i) => (
<circle
key={`ring-${r}`}
cx="200"
cy="200"
r={r}
fill="none"
stroke="rgba(222, 224, 240, 0.12)"
strokeWidth="1"
strokeDasharray={i === 3 ? '4 6' : '2 5'}
opacity={1 - i * 0.12}
/>
))}
{/* animated pulse ring */}
<circle cx="200" cy="200" r="40" fill="none" stroke="rgba(74, 102, 216, 0.7)" strokeWidth="1.4">
<animate attributeName="r" values="40;160;40" dur="4s" repeatCount="indefinite" />
<animate attributeName="opacity" values="0.65;0;0.65" dur="4s" repeatCount="indefinite" />
</circle>
<circle cx="200" cy="200" r="40" fill="none" stroke="rgba(222, 224, 240, 0.45)" strokeWidth="1">
<animate attributeName="r" values="40;130;40" dur="4s" begin="1.2s" repeatCount="indefinite" />
<animate attributeName="opacity" values="0.5;0;0.5" dur="4s" begin="1.2s" repeatCount="indefinite" />
</circle>
{/* axis cross */}
<line x1="40" y1="200" x2="360" y2="200" stroke="rgba(222,224,240,0.08)" strokeDasharray="1 6" />
<line x1="200" y1="40" x2="200" y2="360" stroke="rgba(222,224,240,0.08)" strokeDasharray="1 6" />
{/* routes */}
{NODES.map((n) => {
const p = nodePos(n);
const x2 = (p.x / 100) * 400;
const y2 = (p.y / 100) * 400;
return (
<g key={`route-${n.id}`}>
<line
x1="200"
y1="200"
x2={x2}
y2={y2}
stroke="url(#net-route)"
strokeWidth="1.2"
strokeDasharray="3 5"
opacity="0.7"
/>
<circle r="3" fill="#DEE0F0" opacity="0.95">
<animateMotion
dur="3.2s"
repeatCount="indefinite"
path={`M200,200 L${x2},${y2}`}
/>
<animate attributeName="opacity" values="0;1;0" dur="3.2s" repeatCount="indefinite" />
</circle>
</g>
);
})}
{/* HQ glow */}
<circle cx="200" cy="200" r="28" fill="rgba(74, 102, 216, 0.32)" filter="url(#net-blur)" />
{/* HQ core */}
<circle cx="200" cy="200" r="11" fill="url(#net-hq)" />
<circle cx="200" cy="200" r="14" fill="none" stroke="rgba(222, 224, 240, 0.55)" strokeWidth="1" />
<text
x="200"
y="235"
textAnchor="middle"
fill="#FFFFFF"
fontFamily="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
fontSize="9.5"
fontWeight="800"
letterSpacing="0.22em"
>
DUBAI · HQ
</text>
{/* peripheral nodes */}
{NODES.map((n) => {
const p = nodePos(n);
const x = (p.x / 100) * 400;
const y = (p.y / 100) * 400;
const leftSide = p.x < 50;
return (
<g key={n.id} transform={`translate(${x} ${y})`}>
<circle r="9" fill="rgba(74, 102, 216, 0.18)" />
<circle r="4" fill="#DEE0F0" />
<circle r="4" fill="none" stroke="rgba(222, 224, 240, 0.5)" strokeWidth="1">
<animate attributeName="r" values="4;12;4" dur="3.6s" repeatCount="indefinite" />
<animate attributeName="opacity" values="0.9;0;0.9" dur="3.6s" repeatCount="indefinite" />
</circle>
<text
x={leftSide ? -12 : 12}
y="3"
textAnchor={leftSide ? 'end' : 'start'}
fill="#B5BDDB"
fontFamily="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
fontSize="8.5"
fontWeight="700"
letterSpacing="0.18em"
>
{n.label.toUpperCase()}
</text>
</g>
);
})}
</svg>
<div className="net-vis-legend">
<span className="net-legend-item">
<span className="net-legend-dot net-legend-hq" />
Dubai HQ · Showroom
</span>
<span className="net-legend-item">
<span className="net-legend-dot" />
Active service regions
</span>
</div>
</motion.figure>
{/* RIGHT — proof cards */}
<div className="net-proofs">
{PROOFS.map((p, i) => (
<motion.article
key={p.label}
className="net-proof"
initial={{ opacity: 0, x: 18 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true, margin: '-10%' }}
transition={{ duration: 0.55, ease, delay: 0.08 * i }}
>
<span className="net-proof-icon" aria-hidden>
<p.Icon size={16} />
</span>
<div className="net-proof-stack">
<span className="net-proof-value">{p.value}</span>
<span className="net-proof-label">{p.label}</span>
<span className="net-proof-detail">{p.detail}</span>
</div>
</motion.article>
))}
</div>
</div>
{/* TIMELINE */}
<div className="net-timeline" aria-label="Deployment steps">
<div className="net-timeline-line" aria-hidden />
{STEPS.map((s, i) => (
<motion.div
key={s.n}
className="net-step"
initial={{ opacity: 0, y: 14 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-5%' }}
transition={{ duration: 0.5, ease, delay: 0.08 * i }}
>
<span className="net-step-dot" aria-hidden>
<span className="net-step-dot-core" />
</span>
<span className="net-step-num">{s.n}</span>
<div className="net-step-text">
<span className="net-step-icon" aria-hidden>
<s.Icon size={13} />
</span>
<span className="net-step-label">{s.label}</span>
</div>
</motion.div>
))}
</div>
<div className="net-cta-row">
<CTAButton href="/book-demo/" variant="primary" size="lg" arrow="up-right">
Book a deployment call
</CTAButton>
<CTAButton href="/robots/" variant="secondary" size="lg" arrow="right">
Browse robots
</CTAButton>
</div>
<style jsx>{`
.net {
position: relative;
isolation: isolate;
overflow: hidden;
border-radius: 26px;
border: 1px solid rgba(222, 224, 240, 0.12);
background:
radial-gradient(circle at 88% 4%, rgba(58, 85, 196, 0.16), transparent 55%),
linear-gradient(180deg, #0a0a0d 0%, #050507 100%);
padding: clamp(1.4rem, 3vw, 2.25rem) clamp(1.25rem, 3vw, 2.25rem);
display: grid;
gap: clamp(1.1rem, 2.2vw, 1.6rem);
box-shadow: 0 30px 90px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(222, 224, 240, 0.05);
}
.net-bg {
position: absolute;
inset: 0;
background:
radial-gradient(circle at 18% 22%, rgba(58, 85, 196, 0.18), transparent 55%),
radial-gradient(circle at 82% 80%, rgba(136, 145, 199, 0.1), transparent 55%);
background-image:
linear-gradient(rgba(199, 207, 230, 0.035) 1px, transparent 1px),
linear-gradient(90deg, rgba(199, 207, 230, 0.035) 1px, transparent 1px);
background-size: 100% 100%, 100% 100%, 48px 48px, 48px 48px;
z-index: 0;
pointer-events: none;
}
.net-glow {
position: absolute;
top: -10%;
left: -10%;
width: 55%;
height: 65%;
background: radial-gradient(ellipse 60% 60% at 50% 50%, rgba(58, 85, 196, 0.42), transparent 70%);
filter: blur(55px);
z-index: 0;
pointer-events: none;
}
.net-vignette {
position: absolute;
inset: 0;
background: radial-gradient(ellipse 100% 70% at 50% 115%, rgba(0, 0, 0, 0.4), transparent 55%);
z-index: 0;
pointer-events: none;
}
/* INTRO */
.net-intro {
position: relative;
z-index: 2;
display: flex;
flex-direction: column;
gap: 0.7rem;
max-width: 760px;
}
.net-eyebrow {
display: inline-flex;
align-items: center;
gap: 0.55rem;
font-size: 0.6rem;
letter-spacing: 0.32em;
text-transform: uppercase;
font-weight: 800;
color: #8891C7;
}
.net-eyebrow-dot {
width: 8px;
height: 8px;
border-radius: 999px;
background: #DEE0F0;
box-shadow: 0 0 14px rgba(222, 224, 240, 0.85);
animation: net-pulse 2.2s ease-in-out infinite;
}
@keyframes net-pulse {
0%, 100% { opacity: 0.45; transform: scale(0.85); }
50% { opacity: 1; transform: scale(1.12); }
}
.net-title {
margin: 0;
font-size: clamp(1.7rem, 4.2vw, 2.6rem);
font-weight: 300;
line-height: 1.05;
letter-spacing: -0.04em;
color: #FFFFFF;
}
.net-title :global(.text-gradient) { font-weight: 600; }
.net-desc {
margin: 0;
color: #DEE0F0;
font-size: clamp(0.95rem, 1.55vw, 1.05rem);
line-height: 1.6;
}
/* BODY */
.net-body {
position: relative;
z-index: 2;
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: clamp(1rem, 1.8vw, 1.5rem);
}
/* NETWORK VISUAL */
.net-vis {
position: relative;
margin: 0;
border-radius: 22px;
border: 1px solid rgba(222, 224, 240, 0.1);
background:
radial-gradient(ellipse 80% 80% at 50% 50%, rgba(58, 85, 196, 0.12), transparent 70%),
linear-gradient(180deg, rgba(14, 13, 18, 0.7), rgba(6, 6, 10, 0.95));
padding: 1.1rem;
overflow: hidden;
aspect-ratio: 1 / 1;
max-height: 480px;
}
.net-vis-tag {
position: absolute;
top: 1rem;
left: 1.1rem;
z-index: 2;
font-size: 0.56rem;
letter-spacing: 0.3em;
text-transform: uppercase;
color: #8891C7;
font-weight: 800;
}
.net-vis-svg {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.net-vis-legend {
position: absolute;
left: 1rem;
right: 1rem;
bottom: 0.9rem;
z-index: 2;
display: flex;
gap: 1rem;
flex-wrap: wrap;
font-size: 0.58rem;
letter-spacing: 0.22em;
text-transform: uppercase;
color: #8891C7;
font-weight: 700;
}
.net-legend-item { display: inline-flex; align-items: center; gap: 0.4rem; }
.net-legend-dot {
width: 8px;
height: 8px;
border-radius: 999px;
background: #A6B2D8;
box-shadow: 0 0 8px rgba(166, 178, 216, 0.55);
}
.net-legend-hq {
background: #DEE0F0;
box-shadow: 0 0 12px rgba(222, 224, 240, 0.9), 0 0 0 3px rgba(74, 102, 216, 0.32);
}
/* PROOF CARDS */
.net-proofs {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 0.75rem;
align-content: start;
}
.net-proof {
display: grid;
grid-template-columns: 44px minmax(0, 1fr);
gap: 1rem;
padding: 1.1rem 1.2rem;
border-radius: 16px;
border: 1px solid rgba(222, 224, 240, 0.12);
background:
radial-gradient(ellipse 80% 100% at 0% 50%, rgba(58, 85, 196, 0.14), transparent 60%),
linear-gradient(135deg, rgba(20, 19, 26, 0.65), rgba(8, 8, 12, 0.9));
transition: border-color 0.35s, transform 0.35s, box-shadow 0.35s;
}
.net-proof:hover {
border-color: rgba(74, 102, 216, 0.45);
transform: translateY(-2px);
box-shadow: 0 18px 42px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(74, 102, 216, 0.28), 0 0 28px rgba(58, 85, 196, 0.22);
}
.net-proof-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 44px;
height: 44px;
border-radius: 12px;
border: 1px solid rgba(74, 102, 216, 0.42);
background: rgba(58, 85, 196, 0.16);
color: #DEE0F0;
}
.net-proof-stack {
display: flex;
flex-direction: column;
gap: 0.15rem;
min-width: 0;
}
.net-proof-value {
font-size: 1.55rem;
font-weight: 700;
color: #FFFFFF;
letter-spacing: -0.02em;
line-height: 1.05;
}
.net-proof-label {
font-size: 0.62rem;
letter-spacing: 0.26em;
text-transform: uppercase;
color: #DEE0F0;
font-weight: 700;
}
.net-proof-detail {
font-size: 0.78rem;
color: #8891C7;
line-height: 1.45;
margin-top: 0.18rem;
}
/* TIMELINE */
.net-timeline {
position: relative;
z-index: 2;
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 0.75rem;
padding: 1.2rem 1.1rem 1.1rem;
border-radius: 20px;
border: 1px solid rgba(222, 224, 240, 0.1);
background: linear-gradient(135deg, rgba(20, 19, 26, 0.55), rgba(8, 8, 12, 0.78));
backdrop-filter: blur(10px);
}
.net-timeline-line { display: none; }
.net-step {
position: relative;
display: grid;
grid-template-columns: 22px 32px minmax(0, 1fr);
align-items: center;
gap: 0.8rem;
padding: 0.55rem 0.6rem;
border-radius: 12px;
transition: background 0.3s;
}
.net-step:hover { background: rgba(74, 102, 216, 0.08); }
.net-step-dot {
position: relative;
width: 22px;
height: 22px;
display: inline-flex;
align-items: center;
justify-content: center;
}
.net-step-dot-core {
width: 10px;
height: 10px;
border-radius: 999px;
background: radial-gradient(circle at 30% 30%, #FFFFFF, #4a66d8 65%);
box-shadow:
0 0 0 3px rgba(10, 10, 14, 0.95),
0 0 0 4px rgba(74, 102, 216, 0.45),
0 0 14px rgba(74, 102, 216, 0.6);
}
.net-step-num {
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 0.62rem;
letter-spacing: 0.26em;
color: #6f78a2;
font-weight: 800;
}
.net-step-text {
display: flex;
align-items: center;
gap: 0.55rem;
min-width: 0;
}
.net-step-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 26px;
height: 26px;
border-radius: 8px;
border: 1px solid rgba(74, 102, 216, 0.4);
background: rgba(58, 85, 196, 0.14);
color: #DEE0F0;
}
.net-step-label {
font-size: 1rem;
font-weight: 700;
color: #FFFFFF;
letter-spacing: -0.005em;
}
/* CTAs */
.net-cta-row {
position: relative;
z-index: 2;
display: flex;
flex-wrap: wrap;
gap: 0.6rem;
}
/* DESKTOP */
@media (min-width: 900px) {
.net { padding: clamp(1.8rem, 3vw, 2.5rem); gap: clamp(1.25rem, 2.2vw, 1.8rem); }
.net-body {
grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
gap: clamp(1.25rem, 2.4vw, 1.85rem);
align-items: stretch;
}
.net-vis { max-height: 520px; }
.net-timeline {
grid-template-columns: repeat(5, minmax(0, 1fr));
gap: 0;
padding: 1.1rem 0.5rem;
position: relative;
}
.net-timeline-line {
display: block;
position: absolute;
left: 6%;
right: 6%;
top: 50%;
height: 1px;
background: linear-gradient(90deg, transparent, rgba(74, 102, 216, 0.45), rgba(222, 224, 240, 0.35), rgba(74, 102, 216, 0.45), transparent);
z-index: 0;
}
.net-step {
grid-template-columns: 22px minmax(0, 1fr);
grid-template-rows: auto auto;
align-items: center;
column-gap: 0.55rem;
row-gap: 0.3rem;
padding: 0.55rem 1rem;
background: transparent !important;
z-index: 1;
}
.net-step::before {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(180deg, rgba(20, 19, 26, 0.55), rgba(8, 8, 12, 0.78));
border-radius: 12px;
z-index: -1;
}
.net-step-num { grid-column: 2; grid-row: 1; }
.net-step-dot { grid-column: 1; grid-row: 1 / span 2; }
.net-step-text { grid-column: 2; grid-row: 2; }
}
@media (max-width: 520px) {
.net-cta-row :global(.cta-btn) { width: 100%; justify-content: space-between; }
}
@media (prefers-reduced-motion: reduce) {
.net-glow { animation: none !important; }
.net-eyebrow-dot { animation: none !important; }
}
`}</style>
</section>
);
}