diff --git a/next.config.mjs b/next.config.mjs index 5fee4fa..b3d7116 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -6,6 +6,7 @@ const nextConfig = { }, trailingSlash: true, reactStrictMode: true, + allowedDevOrigins: ['127.0.0.1', 'localhost', '10.255.254.66'], }; export default nextConfig; diff --git a/public/images/robots/featured-bellabot-pro.png b/public/images/robots/featured-bellabot-pro.png new file mode 100644 index 0000000..295bece Binary files /dev/null and b/public/images/robots/featured-bellabot-pro.png differ diff --git a/public/images/robots/featured-g1.jpg b/public/images/robots/featured-g1.jpg new file mode 100644 index 0000000..a130df9 Binary files /dev/null and b/public/images/robots/featured-g1.jpg differ diff --git a/public/images/robots/featured-go2.png b/public/images/robots/featured-go2.png new file mode 100644 index 0000000..b5a5eb9 Binary files /dev/null and b/public/images/robots/featured-go2.png differ diff --git a/public/images/robots/featured-kettybot-black.webp b/public/images/robots/featured-kettybot-black.webp new file mode 100644 index 0000000..3cb40eb Binary files /dev/null and b/public/images/robots/featured-kettybot-black.webp differ diff --git a/public/images/robots/featured-kettybot-yellow.webp b/public/images/robots/featured-kettybot-yellow.webp new file mode 100644 index 0000000..6250a29 Binary files /dev/null and b/public/images/robots/featured-kettybot-yellow.webp differ diff --git a/public/images/robots/pudu-bellabot.png b/public/images/robots/pudu-bellabot.png new file mode 100644 index 0000000..4beb03c Binary files /dev/null and b/public/images/robots/pudu-bellabot.png differ diff --git a/public/images/robots/pudu-bellabot.svg b/public/images/robots/pudu-bellabot.svg deleted file mode 100644 index 9bc0eb2..0000000 --- a/public/images/robots/pudu-bellabot.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PUDU BELLABOT - diff --git a/public/images/robots/pudu-cc1.png b/public/images/robots/pudu-cc1.png new file mode 100644 index 0000000..a6e6c09 Binary files /dev/null and b/public/images/robots/pudu-cc1.png differ diff --git a/public/images/robots/pudu-cc1.svg b/public/images/robots/pudu-cc1.svg deleted file mode 100644 index ed4c0de..0000000 --- a/public/images/robots/pudu-cc1.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PUDU CC1 CLEANING ROBOT - diff --git a/public/images/robots/pudu-d7.png b/public/images/robots/pudu-d7.png new file mode 100644 index 0000000..6781874 Binary files /dev/null and b/public/images/robots/pudu-d7.png differ diff --git a/public/images/robots/pudu-d9.png b/public/images/robots/pudu-d9.png new file mode 100644 index 0000000..e4cdec7 Binary files /dev/null and b/public/images/robots/pudu-d9.png differ diff --git a/public/images/robots/pudu-holabot.png b/public/images/robots/pudu-holabot.png new file mode 100644 index 0000000..17b8ef6 Binary files /dev/null and b/public/images/robots/pudu-holabot.png differ diff --git a/public/images/robots/pudu-kettybot.png b/public/images/robots/pudu-kettybot.png new file mode 100644 index 0000000..17cacac Binary files /dev/null and b/public/images/robots/pudu-kettybot.png differ diff --git a/public/images/robots/pudu-kettybot.svg b/public/images/robots/pudu-kettybot.svg deleted file mode 100644 index 821b476..0000000 --- a/public/images/robots/pudu-kettybot.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PUDU KETTYBOT - diff --git a/public/images/robots/pudu-pudubot.svg b/public/images/robots/pudu-pudubot.svg deleted file mode 100644 index 3e363f0..0000000 --- a/public/images/robots/pudu-pudubot.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - PUDU D-SERIES - diff --git a/public/images/robots/pudu-pudubot2.png b/public/images/robots/pudu-pudubot2.png new file mode 100644 index 0000000..9d85e77 Binary files /dev/null and b/public/images/robots/pudu-pudubot2.png differ diff --git a/src/app/globals.css b/src/app/globals.css index 0fd8761..bc40ed9 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -266,53 +266,264 @@ html { ::-webkit-scrollbar-thumb { background: rgba(136, 145, 199, 0.28); border-radius: var(--radius-sm); } ::-webkit-scrollbar-thumb:hover { background: rgba(39, 63, 148, 0.7); } -/* === Buttons === */ -.btn { +/* === CTA Button System === */ +/* Reusable across all sections — primary | secondary | ghost | link, sizes sm | md | lg. + Arrow handled via .cta-arrow capsule; data-arrow="up-right" rotates on hover, "right" translates X. */ +.cta-btn { + position: relative; display: inline-flex; align-items: center; - gap: 0.625rem; - padding: 0.875rem 1.75rem; + gap: 0.65rem; border-radius: 999px; - font-size: 0.85rem; - font-weight: 600; - letter-spacing: 0.08em; + font-family: inherit; + font-weight: 800; + letter-spacing: 0.22em; text-transform: uppercase; text-decoration: none; cursor: pointer; - transition: transform 0.25s cubic-bezier(0.16,1,0.3,1), box-shadow 0.25s ease, background 0.25s ease, color 0.25s ease; - border: 1px solid transparent; white-space: nowrap; + isolation: isolate; + overflow: hidden; + border: 1px solid transparent; + transition: transform 0.3s cubic-bezier(0.16,1,0.3,1), box-shadow 0.3s, background 0.3s, border-color 0.3s, color 0.3s; + -webkit-user-select: none; + user-select: none; } -.btn:hover { transform: translateY(-1px); } - -.btn-primary { - background: linear-gradient(135deg, #3a55c4 0%, #273F94 55%, #1a2e6e 100%); - color: #FBFBFD; - box-shadow: 0 8px 28px rgba(39, 63, 148, 0.45), inset 0 1px 0 rgba(222, 224, 240, 0.25); +.cta-btn:focus-visible { + outline: 2px solid #DEE0F0; + outline-offset: 3px; } -.btn-primary:hover { - box-shadow: 0 12px 38px rgba(58, 85, 196, 0.6), inset 0 1px 0 rgba(222, 224, 240, 0.35); +.cta-btn:disabled, +.cta-btn[aria-disabled='true'] { + opacity: 0.5; + cursor: not-allowed; + transform: none !important; } -.btn-ghost { - background: rgba(222, 224, 240, 0.04); - color: #FBFBFD; - border-color: rgba(199, 207, 230, 0.28); - backdrop-filter: blur(12px); +/* sizes */ +.cta-sm { padding: 0.62rem 1.05rem; font-size: 0.64rem; letter-spacing: 0.22em; } +.cta-md { padding: 0.95rem 1.45rem; font-size: 0.74rem; } +.cta-lg { padding: 1.05rem 1.7rem; font-size: 0.8rem; letter-spacing: 0.24em; } + +/* shared arrow capsule */ +.cta-arrow { + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 999px; + background: rgba(222, 224, 240, 0.12); + border: 1px solid rgba(222, 224, 240, 0.22); + color: currentColor; + transition: transform 0.35s, background 0.35s, border-color 0.35s; + flex-shrink: 0; } -.btn-ghost:hover { - background: rgba(39, 63, 148, 0.16); - border-color: rgba(136, 145, 199, 0.6); - color: #DEE0F0; +.cta-sm .cta-arrow { width: 20px; height: 20px; } +.cta-md .cta-arrow { width: 24px; height: 24px; } +.cta-lg .cta-arrow { width: 26px; height: 26px; } + +/* PRIMARY — filled gradient, strongest emphasis */ +.cta-primary { + background: linear-gradient(135deg, #5a76e8 0%, #4a66d8 35%, #2f4cb4 70%, #273F94 100%); + color: #FFFFFF; + box-shadow: + 0 24px 56px rgba(39, 63, 148, 0.55), + 0 0 0 1px rgba(222, 224, 240, 0.22), + 0 0 32px rgba(74, 102, 216, 0.4), + inset 0 1px 0 rgba(255, 255, 255, 0.24); +} +.cta-primary::before { + content: ''; + position: absolute; + inset: 0; + border-radius: inherit; + background: linear-gradient(120deg, transparent 30%, rgba(255, 255, 255, 0.2) 50%, transparent 70%); + transform: translateX(-100%); + transition: transform 0.7s ease; + pointer-events: none; +} +.cta-primary:hover { + transform: translateY(-2px); + box-shadow: + 0 30px 66px rgba(39, 63, 148, 0.7), + 0 0 0 1px rgba(222, 224, 240, 0.32), + 0 0 44px rgba(74, 102, 216, 0.55), + inset 0 1px 0 rgba(255, 255, 255, 0.3); +} +.cta-primary:hover::before { transform: translateX(100%); } +.cta-primary .cta-arrow { + background: rgba(255, 255, 255, 0.18); + border-color: rgba(255, 255, 255, 0.24); +} +.cta-primary:hover .cta-arrow { + background: rgba(255, 255, 255, 0.32); + border-color: rgba(255, 255, 255, 0.4); } -.btn-outline { +/* SECONDARY — glassmorphism, supporting actions */ +.cta-secondary { + border-color: rgba(222, 224, 240, 0.55); + background: + linear-gradient(135deg, rgba(58, 85, 196, 0.16), rgba(14, 13, 18, 0.55) 60%), + rgba(14, 13, 18, 0.55); + color: #FFFFFF; + backdrop-filter: blur(14px); + -webkit-backdrop-filter: blur(14px); + box-shadow: + 0 14px 32px rgba(0, 0, 0, 0.55), + inset 0 1px 0 rgba(222, 224, 240, 0.22), + 0 0 0 1px rgba(58, 85, 196, 0.18); +} +.cta-secondary::before { + content: ''; + position: absolute; + inset: 0; + border-radius: inherit; + background: linear-gradient(120deg, transparent 30%, rgba(222, 224, 240, 0.16) 50%, transparent 70%); + transform: translateX(-100%); + transition: transform 0.7s ease; + pointer-events: none; +} +.cta-secondary:hover { + border-color: rgba(222, 224, 240, 0.82); + background: + linear-gradient(135deg, rgba(74, 102, 216, 0.3), rgba(20, 22, 38, 0.62) 60%), + rgba(20, 22, 38, 0.62); + transform: translateY(-2px); + box-shadow: + 0 22px 46px rgba(0, 0, 0, 0.62), + inset 0 1px 0 rgba(222, 224, 240, 0.3), + 0 0 0 1px rgba(58, 85, 196, 0.5), + 0 0 32px rgba(58, 85, 196, 0.4); +} +.cta-secondary:hover::before { transform: translateX(100%); } + +/* GHOST — outline, low-emphasis action */ +.cta-ghost { + border-color: rgba(222, 224, 240, 0.28); + background: transparent; + color: #ECEEF6; +} +.cta-ghost:hover { + border-color: rgba(222, 224, 240, 0.6); + background: rgba(58, 85, 196, 0.14); + color: #FFFFFF; + transform: translateY(-2px); +} +.cta-ghost .cta-arrow { + background: rgba(222, 224, 240, 0.08); + border-color: rgba(222, 224, 240, 0.2); +} +.cta-ghost:hover .cta-arrow { + background: rgba(58, 85, 196, 0.22); + border-color: rgba(222, 224, 240, 0.4); +} + +/* LINK — text-only for minor inline links */ +.cta-link { + padding: 0.45rem 0; + border: none; background: transparent; color: #DEE0F0; - border-color: rgba(136, 145, 199, 0.55); + font-size: 0.72rem; + letter-spacing: 0.2em; + border-bottom: 1px solid transparent; + border-radius: 0; + white-space: nowrap; + font-weight: 700; +} +.cta-link:hover { + color: #FFFFFF; + border-bottom-color: rgba(222, 224, 240, 0.55); + transform: translateX(2px); +} +.cta-link .cta-arrow { + width: auto; + height: auto; + padding: 0; + background: transparent; + border: none; +} +.cta-link:hover .cta-arrow { transform: translate(3px, -1px); } + +/* arrow motion per direction */ +.cta-btn[data-arrow='up-right']:hover .cta-arrow { transform: rotate(45deg); } +.cta-btn[data-arrow='right']:hover .cta-arrow { transform: translateX(3px); } +.cta-link[data-arrow='up-right']:hover .cta-arrow, +.cta-link[data-arrow='right']:hover .cta-arrow { transform: translate(3px, -1px); } + +/* full-width on small screens for primary CTA wrappers */ +.cta-btn.cta-full { + width: 100%; + justify-content: space-between; +} + +/* === Legacy .btn aliases — kept for backward compat, route to new system === */ +.btn { + display: inline-flex; + align-items: center; + gap: 0.65rem; + padding: 0.95rem 1.45rem; + border-radius: 999px; + font-size: 0.74rem; + font-weight: 800; + letter-spacing: 0.22em; + text-transform: uppercase; + text-decoration: none; + cursor: pointer; + border: 1px solid transparent; + white-space: nowrap; + transition: transform 0.3s cubic-bezier(0.16,1,0.3,1), box-shadow 0.3s, background 0.3s, color 0.3s, border-color 0.3s; +} +.btn:hover { transform: translateY(-2px); } +.btn-primary { + background: linear-gradient(135deg, #5a76e8 0%, #4a66d8 35%, #2f4cb4 70%, #273F94 100%); + color: #FFFFFF; + box-shadow: + 0 24px 56px rgba(39, 63, 148, 0.55), + 0 0 0 1px rgba(222, 224, 240, 0.22), + 0 0 32px rgba(74, 102, 216, 0.4), + inset 0 1px 0 rgba(255, 255, 255, 0.24); +} +.btn-primary:hover { + box-shadow: + 0 30px 66px rgba(39, 63, 148, 0.7), + 0 0 0 1px rgba(222, 224, 240, 0.32), + 0 0 44px rgba(74, 102, 216, 0.55), + inset 0 1px 0 rgba(255, 255, 255, 0.3); +} +.btn-ghost { + background: + linear-gradient(135deg, rgba(58, 85, 196, 0.16), rgba(14, 13, 18, 0.55) 60%), + rgba(14, 13, 18, 0.55); + color: #FFFFFF; + border-color: rgba(222, 224, 240, 0.55); + backdrop-filter: blur(14px); + box-shadow: + 0 14px 32px rgba(0, 0, 0, 0.55), + inset 0 1px 0 rgba(222, 224, 240, 0.22), + 0 0 0 1px rgba(58, 85, 196, 0.18); +} +.btn-ghost:hover { + border-color: rgba(222, 224, 240, 0.82); + background: + linear-gradient(135deg, rgba(74, 102, 216, 0.3), rgba(20, 22, 38, 0.62) 60%), + rgba(20, 22, 38, 0.62); + color: #FFFFFF; + box-shadow: + 0 22px 46px rgba(0, 0, 0, 0.62), + inset 0 1px 0 rgba(222, 224, 240, 0.3), + 0 0 0 1px rgba(58, 85, 196, 0.5), + 0 0 32px rgba(58, 85, 196, 0.4); +} +.btn-outline { + background: transparent; + color: #ECEEF6; + border-color: rgba(222, 224, 240, 0.28); } .btn-outline:hover { - background: rgba(39, 63, 148, 0.14); + background: rgba(58, 85, 196, 0.14); + border-color: rgba(222, 224, 240, 0.6); + color: #FFFFFF; } /* === Layout helpers === */ diff --git a/src/app/page.tsx b/src/app/page.tsx index f4ea789..410bcfe 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -4,7 +4,7 @@ import { FooterAndContact } from '@/components/FooterAndContact'; import { Hero3DRobotics } from '@/components/robotics/Hero3DRobotics'; import { BrandShowcase } from '@/components/robotics/BrandShowcase'; import { CategoryShowcaseScroll } from '@/components/robotics/CategoryShowcaseScroll'; -import { RobotProductCard } from '@/components/robotics/RobotProductCard'; +import { FeaturedRobotsShowcase } from '@/components/robotics/FeaturedRobotsShowcase'; import { IndustryUseCases } from '@/components/robotics/IndustryUseCases'; import { DemoCTA } from '@/components/robotics/DemoCTA'; import { ConfigureCTA } from '@/components/robotics/ConfigureCTA'; @@ -83,7 +83,7 @@ export default function HomePage() { - +
-
- {FEATURED_ROBOTS.map((r, idx) => ( - - ))} -
+
@@ -124,9 +114,9 @@ export default function HomePage() {
@@ -147,9 +137,9 @@ export default function HomePage() {
diff --git a/src/app/robots/[slug]/page.tsx b/src/app/robots/[slug]/page.tsx index b6efd75..ba91f40 100644 --- a/src/app/robots/[slug]/page.tsx +++ b/src/app/robots/[slug]/page.tsx @@ -177,10 +177,7 @@ export default async function RobotDetailPage({ params }: { params: Promise - + {related.length > 0 && ( diff --git a/src/components/robotics/BrandShowcase.tsx b/src/components/robotics/BrandShowcase.tsx index 1415141..c92e63b 100644 --- a/src/components/robotics/BrandShowcase.tsx +++ b/src/components/robotics/BrandShowcase.tsx @@ -24,8 +24,8 @@ const BRAND_VISUALS: Record = { description: 'Service, delivery, cleaning, and hospitality robotics available exclusively in the UAE through YS Lootah Robotics.', chips: ['Service', 'Delivery', 'Cleaning', 'Hospitality'], - primary: { src: '/images/robots/pudu-bellabot.svg', alt: 'Pudu BellaBot delivery robot' }, - secondary: { src: '/images/robots/pudu-kettybot.svg', alt: 'Pudu KettyBot service robot' }, + primary: { src: '/images/robots/pudu-bellabot.png', alt: 'Pudu BellaBot multi-tray delivery robot' }, + secondary: { src: '/images/robots/pudu-kettybot.png', alt: 'Pudu KettyBot Pro service robot with built-in advertising display' }, }, }; diff --git a/src/components/robotics/CategoryShowcaseScroll.tsx b/src/components/robotics/CategoryShowcaseScroll.tsx index 65bd2f3..b2fce17 100644 --- a/src/components/robotics/CategoryShowcaseScroll.tsx +++ b/src/components/robotics/CategoryShowcaseScroll.tsx @@ -1,22 +1,18 @@ 'use client'; -import { useRef, useEffect, useState, useCallback } from 'react'; -import Image from 'next/image'; -import Link from 'next/link'; -import { motion, useScroll, useTransform } from 'framer-motion'; -import { ArrowRight, Bot, Footprints, Coffee, Truck, Sparkles, Hotel, Search, Factory } from 'lucide-react'; +import { motion } from 'framer-motion'; +import { ArrowUpRight, Bot, Footprints, Coffee, Truck, Sparkles, Hotel, Search, Factory } from 'lucide-react'; import type { LucideIcon } from 'lucide-react'; +import Link from 'next/link'; + +const ease = [0.16, 1, 0.3, 1] as const; type Category = { id: string; + num: string; name: string; - brand: 'Unitree' | 'Pudu Robotics' | 'Unitree + Pudu'; - brandAccent: string; - models: string; description: string; - useCases: string[]; - image: string; - imageAlt: string; + chips: [string, string, string]; href: string; Icon: LucideIcon; }; @@ -24,649 +20,296 @@ type Category = { const CATEGORIES: Category[] = [ { id: 'humanoid', + num: '01', name: 'Humanoid Robots', - brand: 'Unitree', - brandAccent: '#DEE0F0', - models: 'G1 · H2 · R1', - description: - 'Bipedal humanoid platforms for events, education, research, and customer-facing experiences across the UAE.', - useCases: ['Events & activations', 'Education & STEM', 'Research labs', 'Concierge & reception'], - image: '/images/robots/unitree-g1.png', - imageAlt: 'Unitree G1 humanoid robot', + description: 'Bipedal humanoid platforms for concierge, events, and research.', + chips: ['Events', 'Concierge', 'Research'], href: '/robots/?category=humanoid', Icon: Bot, }, { id: 'quadruped', + num: '02', name: 'Quadruped Robots', - brand: 'Unitree', - brandAccent: '#DEE0F0', - models: 'Go2 · B2 · A2', - description: - 'Agile four-legged robots built for inspection, security patrol, and field mobility in any terrain.', - useCases: ['Facility inspection', 'Security patrol', 'Terrain mobility', 'Robotics research'], - image: '/images/robots/unitree-go2.png', - imageAlt: 'Unitree Go2 quadruped robot', + description: 'Four-legged mobility for inspection, security, and field robotics.', + chips: ['Inspection', 'Security', 'Outdoor'], href: '/robots/?category=quadruped', Icon: Footprints, }, { id: 'service', + num: '03', name: 'Service Robots', - brand: 'Pudu Robotics', - brandAccent: '#8891C7', - models: 'KettyBot · BellaBot', - description: - 'Greeting, guiding, and customer-interaction robots designed for restaurants, hotels, and retail venues.', - useCases: ['Restaurant greeting', 'Customer guidance', 'Retail activation', 'Hospitality service'], - image: '/images/robots/pudu-kettybot.svg', - imageAlt: 'Pudu KettyBot service robot', + description: 'Greeting, guidance, and customer interaction for restaurants and retail.', + chips: ['Restaurants', 'Retail', 'Reception'], href: '/robots/?category=service', Icon: Coffee, }, { id: 'delivery', + num: '04', name: 'Delivery Robots', - brand: 'Pudu Robotics', - brandAccent: '#8891C7', - models: 'BellaBot · D-Series', - description: - 'Multi-tray autonomous delivery robots for hotels, restaurants, hospitals, and back-of-house operations.', - useCases: ['Hotel room service', 'Restaurant delivery', 'Hospital logistics', 'Back-of-house transport'], - image: '/images/robots/pudu-bellabot.svg', - imageAlt: 'Pudu BellaBot delivery robot', + description: 'Multi-tray autonomous delivery for hotels, dining, and back-of-house.', + chips: ['Hotels', 'Dining', 'Logistics'], href: '/robots/?category=delivery', Icon: Truck, }, { id: 'cleaning', + num: '05', name: 'Cleaning Robots', - brand: 'Pudu Robotics', - brandAccent: '#8891C7', - models: 'CC1 · Commercial Cleaning', - description: - 'Autonomous commercial cleaning platforms that sweep, scrub, mop, and vacuum across large venues.', - useCases: ['Shopping malls', 'Airports & transit', 'Hotels & resorts', 'Corporate offices'], - image: '/images/robots/pudu-cc1.svg', - imageAlt: 'Pudu CC1 cleaning robot', + description: 'Sweep, scrub, mop, vacuum across malls, airports, and large venues.', + chips: ['Malls', 'Airports', 'Hotels'], href: '/robots/?category=cleaning', Icon: Sparkles, }, { id: 'hospitality', + num: '06', name: 'Hospitality Robots', - brand: 'Pudu Robotics', - brandAccent: '#8891C7', - models: 'BellaBot · KettyBot', - description: - 'Premium guest-facing robots for hotels, resorts, and events — designed to enhance every guest moment.', - useCases: ['Hotel concierge', 'Resort service', 'Event activations', 'Guest experience'], - image: '/images/robots/pudu-bellabot.svg', - imageAlt: 'Pudu BellaBot hospitality robot', + description: 'Premium guest-facing robotics for hotels, resorts, and events.', + chips: ['Hotels', 'Resorts', 'Events'], href: '/robots/?category=hospitality', Icon: Hotel, }, { id: 'inspection', + num: '07', name: 'Inspection Robots', - brand: 'Unitree', - brandAccent: '#DEE0F0', - models: 'Go2 · B2 · AS2', - description: - 'Quadruped inspection platforms for energy, utilities, and industrial sites — equipped with rich sensor payloads.', - useCases: ['Energy & utilities', 'Industrial sites', 'Infrastructure', 'Security patrols'], - image: '/images/robots/unitree-b2.png', - imageAlt: 'Unitree B2 industrial quadruped robot', + description: 'Industrial quadrupeds with sensor payloads for energy and utilities.', + chips: ['Energy', 'Utilities', 'Patrol'], href: '/robots/?category=inspection', Icon: Search, }, { id: 'commercial', + num: '08', name: 'Commercial Automation', - brand: 'Unitree + Pudu', - brandAccent: '#3a55c4', - models: 'Multi-brand portfolio', - description: - 'Mixed robotics fleets for warehouses, smart buildings, and enterprise operations across the UAE.', - useCases: ['Warehouses', 'Smart buildings', 'Enterprise venues', 'Mixed-fleet deployments'], - image: '/images/robots/unitree-as2.png', - imageAlt: 'Unitree AS2 autonomous system for commercial automation', + description: 'Mixed robotics fleets for warehouses, smart buildings, and enterprises.', + chips: ['Warehouses', 'Smart buildings', 'Fleets'], href: '/robots/?category=commercial', Icon: Factory, }, ]; export function CategoryShowcaseScroll() { - const [isMobile, setIsMobile] = useState(false); - - useEffect(() => { - const check = () => setIsMobile(window.innerWidth < 900); - check(); - window.addEventListener('resize', check); - return () => window.removeEventListener('resize', check); - }, []); - - if (isMobile) return ; - return ; -} - -function CategorySticky() { - const containerRef = useRef(null); - const { scrollYProgress } = useScroll({ - target: containerRef, - offset: ['start start', 'end end'], - }); - const [activeIdx, setActiveIdx] = useState(0); - const manualLockUntil = useRef(0); - - useEffect(() => { - return scrollYProgress.on('change', (v) => { - /* honor manual click for a short window so scroll doesn't override */ - if (Date.now() < manualLockUntil.current) return; - const idx = Math.min( - CATEGORIES.length - 1, - Math.max(0, Math.floor(v * CATEGORIES.length)) - ); - setActiveIdx(idx); - }); - }, [scrollYProgress]); - - const handlePick = useCallback((i: number) => { - /* swap in place, no scroll. Lock scroll listener for 1.2s. */ - manualLockUntil.current = Date.now() + 1200; - setActiveIdx(i); - }, []); - - /* progress bar height */ - const progressHeight = useTransform(scrollYProgress, [0, 1], ['0%', '100%']); - return ( -
-
- {/* LEFT — sticky text column with progress + active category */} -
- {/* progress rail */} -
- -
- - {/* category list */} -
- Robot categories · 8 - {CATEGORIES.map((c, i) => ( - - ))} -
- - {/* active category copy */} -
- - - {CATEGORIES[activeIdx].name} - - - - {CATEGORIES[activeIdx].description} - - - - - Explore robots - - - - Book demo - - - -
-
- - {/* RIGHT — visual stage */} -
- {/* metallic edge */} -
- {/* grid */} -
- {/* spotlight */} -
- - {/* top floating brand chip */} -
- - {CATEGORIES[activeIdx].brand} -
- - {/* top-right index */} -
- {String(activeIdx + 1).padStart(2, '0')} - - / {String(CATEGORIES.length).padStart(2, '0')} - -
- - {/* product stage — cross-fade per category */} -
- {CATEGORIES.map((c, i) => ( - -
- {c.imageAlt} -
-
- ))} -
- - {/* floor line */} -
- - {/* floor reflection */} - {CATEGORIES.map((c, i) => ( - - - - ))} - - {/* bottom info bar: models + use cases */} +
+
+ {CATEGORIES.map((c, i) => ( -
- - Featured models - - - {CATEGORIES[activeIdx].models} - -
-
- {CATEGORIES[activeIdx].useCases.map((u) => ( - - {u} + + {/* TOP: number left, icon right */} +
+ {c.num} + + - ))} -
- -
-
-
- ); -} +
-function CategoryStack() { - return ( -
- {CATEGORIES.map((c, i) => ( - -
- - {String(i + 1).padStart(2, '0')} · {c.brand} - -

- {c.name} -

-

- {c.description} -

- - Explore - - -
-
- {c.imageAlt} -
- - ))} -
+ {/* MIDDLE: title + description */} +
+

{c.name}

+

{c.description}

+
+ + {/* BOTTOM: chips + CTA */} +
+
    + {c.chips.map((chip) => ( +
  • {chip}
  • + ))} +
+ + Explore + + + + +
+ + + + + ))} +
+ + + ); } diff --git a/src/components/robotics/ConfigureCTA.tsx b/src/components/robotics/ConfigureCTA.tsx index d8c3fdd..c9d1c45 100644 --- a/src/components/robotics/ConfigureCTA.tsx +++ b/src/components/robotics/ConfigureCTA.tsx @@ -1,67 +1,196 @@ 'use client'; -import Link from 'next/link'; +import { motion } from 'framer-motion'; +import { Sparkles } from 'lucide-react'; +import { CTAButton } from '@/components/ui/CTAButton'; -type Props = { - title?: string; - description?: string; - href?: string; - ctaLabel?: string; -}; +const ease = [0.16, 1, 0.3, 1] as const; -export function ConfigureCTA({ - title = 'Configure a robotics solution for your business.', - description = 'Build a tailored robot choose persona, attire, color, accessories, and accessories. Visualize before you request a quote.', - href = '/configure/', - ctaLabel = 'Start configuration', -}: Props) { +export function ConfigureCTA() { return ( -
-
+
+ -
- 3D Configurator · Unitree G1 · Dubai -

- {title} -

-

{description}

-
-
- - {ctaLabel} - - - Book a demo -
-
+
+
+ + +
+ + + 3D Configurator · Dubai + +

+ Configure a robotics solution for your business. +

+

+ Build a tailored robot experience — choose persona, attire, color, accessories, language, and venue use case before requesting a quote. +

+

+ + Available for Unitree G1 and selected robotics solutions. +

+
+ +
+ + Start configuration + + + Book a demo + +
+
+ + + ); } diff --git a/src/components/robotics/DemoCTA.tsx b/src/components/robotics/DemoCTA.tsx index 4f9248b..6f58e81 100644 --- a/src/components/robotics/DemoCTA.tsx +++ b/src/components/robotics/DemoCTA.tsx @@ -1,6 +1,6 @@ 'use client'; -import { PremiumButton } from '@/components/ui/PremiumButton'; +import { CTAButton } from '@/components/ui/CTAButton'; type Props = { title?: string; @@ -62,8 +62,8 @@ export function DemoCTA({ {description}

- {primaryLabel} - {secondaryLabel} + {primaryLabel} + {secondaryLabel}
diff --git a/src/components/robotics/ExclusiveAccessSection.tsx b/src/components/robotics/ExclusiveAccessSection.tsx index 64de9d6..5151c00 100644 --- a/src/components/robotics/ExclusiveAccessSection.tsx +++ b/src/components/robotics/ExclusiveAccessSection.tsx @@ -113,8 +113,8 @@ export function ExclusiveAccessSection() { brand="Pudu Robotics" tag="Service · Delivery · Cleaning" accent="#8891C7" - primary={{ src: '/images/robots/pudu-bellabot.svg', alt: 'Pudu BellaBot delivery robot' }} - secondary={{ src: '/images/robots/pudu-kettybot.svg', alt: 'Pudu KettyBot service robot' }} + primary={{ src: '/images/robots/pudu-bellabot.png', alt: 'Pudu BellaBot multi-tray delivery robot' }} + secondary={{ src: '/images/robots/pudu-kettybot.png', alt: 'Pudu KettyBot Pro service robot with built-in advertising display' }} /> diff --git a/src/components/robotics/FeaturedRobotsShowcase.tsx b/src/components/robotics/FeaturedRobotsShowcase.tsx new file mode 100644 index 0000000..f5df9ba --- /dev/null +++ b/src/components/robotics/FeaturedRobotsShowcase.tsx @@ -0,0 +1,1147 @@ +'use client'; + +import { useState, useCallback, useRef, useEffect } from 'react'; +import Image from 'next/image'; +import { motion, AnimatePresence } from 'framer-motion'; +import { ArrowUpRight, Sparkles, Cpu, Globe2 } from 'lucide-react'; +import type { Robot } from '@/data/robots'; +import { CTAButton } from '@/components/ui/CTAButton'; + +const ease = [0.16, 1, 0.3, 1] as const; + +/* unique exhibit visuals per slug — transparent renders for clean dark integration */ +const FEATURED_IMG: Record = { + 'unitree-g1': '/images/robots/unitree-g1.png', + 'unitree-go2': '/images/robots/featured-go2.png', + 'pudu-bellabot': '/images/robots/featured-bellabot-pro.png', + 'pudu-kettybot': '/images/robots/pudu-kettybot.png', +}; +const exhibitImg = (slug: string, fallback: string) => FEATURED_IMG[slug] ?? fallback; + +type Props = { robots: Robot[] }; + +export function FeaturedRobotsShowcase({ robots }: Props) { + const [activeIdx, setActiveIdx] = useState(0); + const prevIdxRef = useRef(0); + const [pointer, setPointer] = useState<{ x: number; y: number } | null>(null); + const heroRef = useRef(null); + + const pick = useCallback((i: number) => { + if (i === activeIdx) return; + prevIdxRef.current = activeIdx; + setActiveIdx(i); + }, [activeIdx]); + + useEffect(() => { + const el = heroRef.current; + if (!el) return; + const onMove = (e: PointerEvent) => { + const r = el.getBoundingClientRect(); + setPointer({ x: (e.clientX - r.left) / r.width - 0.5, y: (e.clientY - r.top) / r.height - 0.5 }); + }; + const onLeave = () => setPointer(null); + el.addEventListener('pointermove', onMove); + el.addEventListener('pointerleave', onLeave); + return () => { + el.removeEventListener('pointermove', onMove); + el.removeEventListener('pointerleave', onLeave); + }; + }, []); + + if (!robots.length) return null; + + const active = robots[activeIdx]; + const dir = activeIdx >= prevIdxRef.current ? 1 : -1; + const px = pointer ? pointer.x * 22 : 0; + const py = pointer ? pointer.y * 14 : 0; + + return ( +
+ {/* HERO PANEL */} +
+ {/* atmospheric layers */} +
+ +
+ +
+ + {/* top meta */} +
+ + + Showroom spotlight · Dubai floor + + + + + {active.brandLabel} + + +
+ + {/* hero body */} +
+ {/* left: huge robot stage */} +
+ + +
+ + + + {active.name.replace(/\s+/g, ' ').toUpperCase()} + + + + + + + {active.name} + + + + +
+ + + + + + + + + +
+ + {/* right: copy */} +
+ + + + + Exhibit · {String(activeIdx + 1).padStart(2, '0')}/{String(robots.length).padStart(2, '0')} + + +

+ {active.name} +

+ +

{active.tagline}

+ +
    +
  • + + Available now +
  • +
  • + + Demo in Dubai +
  • +
  • + + Price on request +
  • +
+ +
    + {active.features.slice(0, 3).map((f) => ( +
  • + + {f} +
  • + ))} +
+ +
+ + View robot + + + Book demo + + + Request price + +
+
+
+
+
+
+ + {/* SECONDARY RAIL */} +
+ {robots.map((r, i) => { + const isOn = i === activeIdx; + return ( + + ); + })} +
+ + {/* utility band */} +
+
+ +
+ Sales · Demo · Deployment + End-to-end UAE support +
+
+
+ +
+ Coverage + Dubai showroom · UAE-wide +
+
+ + Browse full robotics portfolio + +
+ + +
+ ); +} diff --git a/src/components/robotics/HowItWorks.tsx b/src/components/robotics/HowItWorks.tsx index a906253..7734d5b 100644 --- a/src/components/robotics/HowItWorks.tsx +++ b/src/components/robotics/HowItWorks.tsx @@ -1,86 +1,250 @@ 'use client'; -const STEPS = [ +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: 'Discover', - body: 'Tell us about your venue and use case. We recommend a brand and model humanoid, quadruped, service, delivery, cleaning, or commercial.', + title: 'Procurement', + body: 'Exclusive UAE access to Unitree & Pudu lineups.', + Icon: Boxes, accent: '#DEE0F0', }, { n: '02', - title: 'Demo & configure', - body: 'Book a live demo at our Dubai showroom or your venue. Configure your robot’s persona, attire, and accessories in our 3D configurator.', - accent: '#273F94', + title: 'Configuration', + body: 'Persona, attire, routes, languages, and brand fit.', + Icon: Cog, + accent: '#A6B2D8', }, { n: '03', - title: 'Deploy & support', - body: 'We handle procurement, setup, training, and ongoing service across the UAE so your team can run, not maintain.', - accent: '#8891C7', + 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(null); + const { scrollYProgress } = useScroll({ + target: ref, + offset: ['start 85%', 'end 25%'], + }); + const lineHeight = useTransform(scrollYProgress, [0, 1], ['0%', '100%']); + return ( -
- {STEPS.map((s, i) => ( -
- +
+ +
+ +
    + {STEPS.map((s, i) => ( + - {s.n} - -
    - - Step {i + 1} -
    -

    {s.title}

    -

    {s.body}

    -
- ))} + + + + + +
+
+ {s.n} + + + + +
+ +

{s.title}

+

{s.body}

+
+ + ))} + + +
); } diff --git a/src/components/robotics/ServicesGrid.tsx b/src/components/robotics/ServicesGrid.tsx index f4a2572..5e1872d 100644 --- a/src/components/robotics/ServicesGrid.tsx +++ b/src/components/robotics/ServicesGrid.tsx @@ -1,101 +1,652 @@ 'use client'; -type Service = { title: string; body: string; icon: string }; +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 SERVICES: Service[] = [ - { - title: 'Autonomous Robotics & Intelligent Automation', - body: 'End-to-end deployment of autonomous robotic systems for industrial, commercial, and public sector operations.', - icon: 'M12 2a8 8 0 0 1 8 8v3l2 4-2 1v3a3 3 0 0 1-3 3h-2v-3h-2v3H9v-3H7v3H5a3 3 0 0 1-3-3v-3l-2-1 2-4v-3a8 8 0 0 1 8-8Z', - }, - { - title: 'Autonomous Site Inspection & Patrolling', - body: 'Quadruped patrol robots for facility, infrastructure, and security inspection across UAE sites.', - icon: 'M3 11l3-3h4l2-2 2 2h4l3 3v3l-2 1v3h-3v-3h-3l-1 2-1-2H8v3H5v-3l-2-1v-3Z', - }, - { - title: 'Smart Service & Delivery Robots', - body: 'Hospitality, retail, and back-of-house delivery robots configured for UAE venues.', - icon: 'M3 6h11v9H3V6Zm14 3h3l2 3v3h-2a2 2 0 1 1-4 0h-1V9h2ZM6 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4Z', - }, - { - title: 'Collaborative & Flexible Robotics Integration', - body: 'Integration of robotic systems into existing workflows collaborative, flexible, business-friendly.', - icon: 'M12 2v6m0 8v6M4.93 4.93l4.24 4.24m5.66 5.66 4.24 4.24M2 12h6m8 0h6M4.93 19.07l4.24-4.24m5.66-5.66 4.24-4.24', - }, - { - title: 'Custom Robot Motion Programming', - body: 'Tailored motion sequences and choreography for events, demos, and brand activations.', - icon: 'M3 12h4l3-7 4 14 3-7h4', - }, - { - title: 'Cloud-Based Robot Program Repository', - body: 'Centralized program repository for storing, versioning, and deploying robot behaviors.', - icon: 'M7 18a4 4 0 0 1-1.4-7.8 5 5 0 0 1 9.6-1.6A4.5 4.5 0 0 1 21 13.5 4.5 4.5 0 0 1 16.5 18H7Z', - }, - { - title: 'Algorithm Customization & Optimization', - body: 'Tuning of perception, planning, and control algorithms for venue-specific performance.', - icon: 'M4 6h16M4 12h10m-6 6h12', - }, - { - title: 'Remote System Monitoring & Diagnostics', - body: 'Live monitoring, alerts, and remote diagnostics keep your robot fleet running.', - icon: 'M2 12h4l3-9 4 18 3-9h6', - }, - { - title: 'Hardware-Software Co-Design Consultation', - body: 'Co-design across hardware, sensors, software, and integration for custom robotics programs.', - icon: 'M4 4h7v7H4Zm9 0h7v7h-7Zm-9 9h7v7H4Zm9 0h7v7h-7Z', - }, - { - title: 'Robotics Software Development Kit', - body: 'SDK access for partners and developers building on top of our deployed robots.', - icon: 'M8 3 3 8l5 5m8-10 5 5-5 5M14 3l-4 18', - }, - { - title: 'Data Analytics Dashboard', - body: 'Centralized dashboards turning robot telemetry into actionable business insight.', - icon: 'M3 21V8h4v13H3Zm7 0V3h4v18h-4Zm7 0v-9h4v9h-4Z', - }, +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 ACCENTS = ['#DEE0F0', '#273F94', '#8891C7']; +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 ( -
- {SERVICES.map((s, i) => { - const accent = ACCENTS[i % ACCENTS.length]; - return ( -
-
+
+ +
+ +
+ + + UAE Deployment + +

+ Robotics deployment across the UAE. +

+

+ From Dubai showroom demo to live venue deployment, our team handles procurement, configuration, installation, staff training, and ongoing support. +

+
+ +
+ {/* LEFT — network visual */} + + Dubai HQ · Coverage network + +
-

{s.title}

-

{s.body}

+ DUBAI · HQ + + + {/* 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 ( + + + + + + + + + {n.label.toUpperCase()} + + + ); + })} + + +
+ + + Dubai HQ · Showroom + + + + Active service regions +
- ); - })} -
+ + + {/* RIGHT — proof cards */} +
+ {PROOFS.map((p, i) => ( + + + + +
+ {p.value} + {p.label} + {p.detail} +
+
+ ))} +
+
+ + {/* TIMELINE */} +
+
+ {STEPS.map((s, i) => ( + + + + + {s.n} +
+ + + + {s.label} +
+
+ ))} +
+ +
+ + Book a deployment call + + + Browse robots + +
+ + + ); } diff --git a/src/components/sections/robotics-scroll-showcase.tsx b/src/components/sections/robotics-scroll-showcase.tsx index 4210149..07cdb82 100644 --- a/src/components/sections/robotics-scroll-showcase.tsx +++ b/src/components/sections/robotics-scroll-showcase.tsx @@ -23,7 +23,7 @@ const SHOWROOM_ROBOTS = [ { name: 'Pudu BellaBot', slug: 'pudu-bellabot', - image: '/images/robots/pudu-bellabot.svg', + image: '/images/robots/pudu-bellabot.png', category: 'Delivery', accent: '#8891C7', }, diff --git a/src/components/ui/CTAButton.tsx b/src/components/ui/CTAButton.tsx new file mode 100644 index 0000000..f1935dd --- /dev/null +++ b/src/components/ui/CTAButton.tsx @@ -0,0 +1,130 @@ +'use client'; + +import Link from 'next/link'; +import { forwardRef } from 'react'; +import type { ReactNode, MouseEventHandler } from 'react'; +import { ArrowRight, ArrowUpRight } from 'lucide-react'; + +export type CTAVariant = 'primary' | 'secondary' | 'ghost' | 'link'; +export type CTASize = 'sm' | 'md' | 'lg'; +export type CTAArrow = 'up-right' | 'right' | 'none'; + +type BaseProps = { + variant?: CTAVariant; + size?: CTASize; + arrow?: CTAArrow; + full?: boolean; + children: ReactNode; + className?: string; + ariaLabel?: string; +}; + +type AnchorProps = BaseProps & { + href: string; + external?: boolean; + download?: boolean | string; + type?: never; + onClick?: MouseEventHandler; + disabled?: never; +}; + +type ButtonProps = BaseProps & { + href?: undefined; + type?: 'button' | 'submit' | 'reset'; + onClick?: MouseEventHandler; + disabled?: boolean; +}; + +export type CTAButtonProps = AnchorProps | ButtonProps; + +const arrowIcon = (arrow: CTAArrow, size: CTASize) => { + if (arrow === 'none') return null; + const px = size === 'sm' ? 12 : size === 'lg' ? 15 : 13; + return ( + + ); +}; + +const classFor = (variant: CTAVariant, size: CTASize, full: boolean, extra?: string) => + [ + 'cta-btn', + `cta-${variant}`, + `cta-${size}`, + full ? 'cta-full' : '', + extra ?? '', + ] + .filter(Boolean) + .join(' '); + +export const CTAButton = forwardRef( + function CTAButton(props, ref) { + const { + variant = 'primary', + size = 'md', + arrow = 'up-right', + full = false, + children, + className, + ariaLabel, + } = props; + + const cls = classFor(variant, size, full, className); + const inner = ( + <> + {children} + {arrowIcon(arrow, size)} + + ); + + if ('href' in props && props.href) { + const isExternal = props.external || /^https?:\/\//.test(props.href); + if (isExternal) { + return ( + } + href={props.href} + target="_blank" + rel="noopener noreferrer" + className={cls} + data-arrow={arrow} + aria-label={ariaLabel} + onClick={props.onClick} + > + {inner} + + ); + } + return ( + } + href={props.href} + className={cls} + data-arrow={arrow} + aria-label={ariaLabel} + onClick={props.onClick} + > + {inner} + + ); + } + + const btnProps = props as ButtonProps; + return ( + + ); + }, +); + +CTAButton.displayName = 'CTAButton'; diff --git a/src/data/robots.ts b/src/data/robots.ts index 1adbfed..6bfc0f4 100644 --- a/src/data/robots.ts +++ b/src/data/robots.ts @@ -309,10 +309,10 @@ export const ROBOTS: Robot[] = [ SPEC_CONSULT, SPEC_PLACEHOLDER, ], - image: '/images/robots/pudu-bellabot.svg', - imageType: 'placeholder', + image: '/images/robots/pudu-bellabot.png', + imageType: 'photo', accent: GOLD_BRONZE, - officialUrl: 'https://www.pudurobotics.com/en', + officialUrl: 'https://www.pudurobotics.com/en/products/bellabot', }, { id: 'pudu-kettybot', @@ -339,10 +339,10 @@ export const ROBOTS: Robot[] = [ SPEC_CONSULT, SPEC_PLACEHOLDER, ], - image: '/images/robots/pudu-kettybot.svg', - imageType: 'placeholder', + image: '/images/robots/pudu-kettybot.png', + imageType: 'photo', accent: GOLD_BRAND, - officialUrl: 'https://www.pudurobotics.com/en', + officialUrl: 'https://www.pudurobotics.com/en/products/kettybot_pro', }, { id: 'pudu-cc1', @@ -369,10 +369,10 @@ export const ROBOTS: Robot[] = [ SPEC_CONSULT, SPEC_PLACEHOLDER, ], - image: '/images/robots/pudu-cc1.svg', - imageType: 'placeholder', + image: '/images/robots/pudu-cc1.png', + imageType: 'photo', accent: GOLD_BRONZE, - officialUrl: 'https://www.pudurobotics.com/en', + officialUrl: 'https://www.pudurobotics.com/en/products/puduCC1', }, { id: 'pudu-d-series', @@ -395,10 +395,10 @@ export const ROBOTS: Robot[] = [ ], useCases: ['Warehouses', 'Hospital logistics', 'Hotel back-of-house', 'Industrial kitchens'], specs: [SPEC_CONSULT, SPEC_PLACEHOLDER], - image: '/images/robots/pudu-pudubot.svg', - imageType: 'placeholder', + image: '/images/robots/pudu-pudubot2.png', + imageType: 'photo', accent: GOLD_CHAMPAGNE, - officialUrl: 'https://www.pudurobotics.com/en', + officialUrl: 'https://www.pudurobotics.com/en/products/pudubot2', }, ];