feat: add robotics showcase components and UI enhancements
CI/CD / test-and-build (push) Waiting to run
CI/CD / deploy (push) Blocked by required conditions

- Introduced FounderSection component to highlight leadership and vision.
- Created ServicesGrid component to display various robotics services offered.
- Developed RoboticsScrollShowcase for showcasing robots with interactive elements.
- Implemented RoboticsSplineShowcase featuring a 3D Spline scene for enhanced user experience.
- Added reusable Card component for consistent styling across sections.
- Integrated ContainerScroll for animated scrolling effects in the showcase.
- Built SplineScene component for lazy loading Spline 3D scenes.
- Added Spotlight component for interactive hover effects.
- Created utility function for class name merging to streamline styling.
This commit is contained in:
Najjar\NajjarV02
2026-05-20 17:46:36 +04:00
parent 92cf4aba3b
commit 461a00384c
73 changed files with 2041 additions and 582 deletions
+29 -9
View File
@@ -5,11 +5,14 @@ import { MotionSection } from '@/components/ui/MotionSection';
import { DemoCTA } from '@/components/robotics/DemoCTA';
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',
description:
'YS Lootah Robotics holds exclusive UAE sales rights for selected Unitree and Pudu Robotics solutions — with a Dubai-based team managing sales, demo, configuration, and deployment.',
'YS Lootah Robotics is part of the Yousuf Saeed Lootah Investment Group — a trusted UAE robotics partner delivering AI, automation, and intelligent robotics across Dubai and the UAE.',
};
export default function AboutPage() {
@@ -20,26 +23,43 @@ export default function AboutPage() {
<main style={{ paddingTop: 'clamp(6rem, 10vw, 8rem)', paddingBottom: 'clamp(4rem, 8vw, 6rem)' }}>
<div className="container-wide" style={{ display: 'flex', flexDirection: 'column', gap: 'clamp(3rem, 6vw, 5rem)' }}>
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.25rem', maxWidth: 820 }}>
<span className="eyebrow">About · Exclusive UAE Access</span>
<span className="eyebrow">About · YS Lootah Robotics</span>
<h1 style={{ margin: 0, fontSize: 'clamp(2rem, 5vw, 3.4rem)', fontWeight: 300, lineHeight: 1.05, letterSpacing: '-0.03em' }}>
<span className="text-gradient" style={{ fontWeight: 500 }}>The UAE&apos;s dedicated destination for Unitree and Pudu Robotics.</span>
<span className="text-gradient" style={{ fontWeight: 500 }}>In Tech We Innovate. In Trust We Lead.</span>
</h1>
<p style={{ margin: 0, color: '#cbc4b3', fontSize: 'clamp(0.95rem, 2vw, 1.05rem)', lineHeight: 1.7 }}>
YS Lootah Robotics is the robotics arm of the YS Lootah group — a UAE-based technology partner that holds exclusive sales rights in the UAE for selected Unitree and Pudu Robotics solutions. Our Dubai team manages sales, live demos, configuration, deployment, and ongoing service across the UAE.
</p>
<p style={{ margin: 0, color: '#94908a', fontSize: '0.92rem', lineHeight: 1.7 }}>
Brand names and product trademarks are property of their respective owners. Available exclusively in the UAE through YS Lootah Robotics.
<p style={{ margin: 0, color: '#DEE0F0', fontSize: 'clamp(0.95rem, 2vw, 1.05rem)', lineHeight: 1.7 }}>
YS Lootah Robotics is part of the Yousuf Saeed Lootah Investment Group — a trusted UAE technology and robotics partner helping businesses innovate, automate, and deploy intelligent robotic solutions. The UAE&apos;s dedicated destination for selected Unitree and Pudu Robotics solutions.
</p>
</div>
<MotionSection>
<CompanyStory />
</MotionSection>
<MotionSection>
<FloatingTechPanel />
</MotionSection>
<MotionSection>
<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 }}>Why work with us</span>
<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' }}>
<span className="text-gradient" style={{ fontWeight: 500 }}>Why businesses choose us</span>
</h2>
<WhyUs />
</div>
+5 -5
View File
@@ -52,10 +52,10 @@ export default function AdminLoginPage() {
}}>
🔐
</div>
<h1 style={{ fontSize: '1.25rem', fontWeight: 700, color: '#0a0907', margin: 0, marginBottom: '0.25rem' }}>
<h1 style={{ fontSize: '1.25rem', fontWeight: 700, color: '#0a0a0c', margin: 0, marginBottom: '0.25rem' }}>
Admin Login
</h1>
<p style={{ fontSize: '0.8rem', color: '#94908a', margin: 0 }}>
<p style={{ fontSize: '0.8rem', color: '#8891C7', margin: 0 }}>
Lootah Robotics — G1 Configurator
</p>
</div>
@@ -112,8 +112,8 @@ export default function AdminLoginPage() {
padding: '0.7rem',
borderRadius: '0.5rem',
border: '1px solid rgba(59, 130, 246, 0.3)',
background: loading ? 'rgba(196, 162, 101, 0.1)' : 'rgba(59, 130, 246, 0.08)',
color: loading ? '#94908a' : '#2563eb',
background: loading ? 'rgba(39, 63, 148, 0.1)' : 'rgba(59, 130, 246, 0.08)',
color: loading ? '#8891C7' : '#2563eb',
fontSize: '0.875rem',
fontWeight: 600,
cursor: loading ? 'not-allowed' : 'pointer',
@@ -164,7 +164,7 @@ const inputStyle: React.CSSProperties = {
borderRadius: '0.5rem',
border: '1px solid rgba(0, 0, 0, 0.1)',
background: '#ffffff',
color: '#0a0907',
color: '#0a0a0c',
fontSize: '0.875rem',
outline: 'none',
transition: 'border-color 0.2s ease',
+47 -47
View File
@@ -488,7 +488,7 @@ export default function AdminPage() {
new Date(ts * 1000).toLocaleDateString('en-AE', { day: 'numeric', month: 'short', year: 'numeric' });
if (!isPricingHydrated) {
return <div style={pageStyle}><p style={{ color: '#6b6862' }}>Loading…</p></div>;
return <div style={pageStyle}><p style={{ color: '#6a73a5' }}>Loading…</p></div>;
}
return (
@@ -497,10 +497,10 @@ export default function AdminPage() {
{/* HEADER */}
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '1.5rem' }}>
<div>
<h1 style={{ fontSize: '1.25rem', fontWeight: 700, color: '#0a0907', margin: 0, marginBottom: '0.2rem' }}>
<h1 style={{ fontSize: '1.25rem', fontWeight: 700, color: '#0a0a0c', margin: 0, marginBottom: '0.2rem' }}>
Admin Dashboard
</h1>
<p style={{ fontSize: '0.75rem', color: '#94908a', margin: 0 }}>Lootah Robotics G1 Configurator</p>
<p style={{ fontSize: '0.75rem', color: '#8891C7', margin: 0 }}>Lootah Robotics G1 Configurator</p>
</div>
<div style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>
<button onClick={() => setShowPwModal(true)} style={ghostBtnStyle}>Change Password</button>
@@ -527,7 +527,7 @@ export default function AdminPage() {
borderRadius: '0.375rem',
border: 'none',
background: activeTab === t ? 'rgba(59,130,246,0.08)' : 'transparent',
color: activeTab === t ? '#2563eb' : '#6b6862',
color: activeTab === t ? '#2563eb' : '#6a73a5',
fontSize: '0.8rem',
fontWeight: activeTab === t ? 600 : 400,
cursor: 'pointer',
@@ -558,9 +558,9 @@ export default function AdminPage() {
aria-label={`Label for ${item.label}`}
/>
</div>
<div style={{ fontSize: '0.7rem', color: '#94908a', fontFamily: 'monospace', paddingLeft: '0.25rem' }}>{item.id}</div>
<div style={{ fontSize: '0.7rem', color: '#8891C7', fontFamily: 'monospace', paddingLeft: '0.25rem' }}>{item.id}</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.375rem' }}>
<span style={{ fontSize: '0.7rem', color: '#94908a' }}>AED</span>
<span style={{ fontSize: '0.7rem', color: '#8891C7' }}>AED</span>
<input
type="text"
value={formatPrice(editedPrices[item.id] ?? item.price)}
@@ -584,7 +584,7 @@ export default function AdminPage() {
) : null}
<label
title="Upload / replace .glb"
style={{ display: 'inline-flex', alignItems: 'center', gap: '0.25rem', cursor: rowGlbUploading[item.id] ? 'wait' : 'pointer', fontSize: '0.7rem', color: rowGlbUploading[item.id] ? '#2563eb' : '#94908a', background: rowGlbUploading[item.id] ? 'rgba(59,130,246,0.06)' : 'transparent', border: `1px dashed ${rowGlbUploading[item.id] ? 'rgba(59,130,246,0.3)' : 'rgba(0,0,0,0.12)'}`, borderRadius: '0.375rem', padding: '0.2rem 0.45rem', whiteSpace: 'nowrap' }}
style={{ display: 'inline-flex', alignItems: 'center', gap: '0.25rem', cursor: rowGlbUploading[item.id] ? 'wait' : 'pointer', fontSize: '0.7rem', color: rowGlbUploading[item.id] ? '#2563eb' : '#8891C7', background: rowGlbUploading[item.id] ? 'rgba(59,130,246,0.06)' : 'transparent', border: `1px dashed ${rowGlbUploading[item.id] ? 'rgba(59,130,246,0.3)' : 'rgba(0,0,0,0.12)'}`, borderRadius: '0.375rem', padding: '0.2rem 0.45rem', whiteSpace: 'nowrap' }}
>
<input type="file" accept=".glb" style={{ display: 'none' }} onChange={(e) => {
const f = e.target.files?.[0] ?? null;
@@ -642,7 +642,7 @@ export default function AdminPage() {
background: addItemGlb ? 'rgba(59,130,246,0.04)' : '#fff',
cursor: 'pointer',
fontSize: '0.8rem',
color: addItemGlb ? '#2563eb' : '#94908a',
color: addItemGlb ? '#2563eb' : '#8891C7',
transition: 'all 0.2s',
}}>
<input
@@ -658,7 +658,7 @@ export default function AdminPage() {
{addItemGlb && (
<button
onClick={(e) => { e.preventDefault(); setAddItemGlb(null); }}
style={{ marginLeft: 'auto', background: 'none', border: 'none', cursor: 'pointer', color: '#94908a', fontSize: '0.75rem', padding: '0 2px' }}
style={{ marginLeft: 'auto', background: 'none', border: 'none', cursor: 'pointer', color: '#8891C7', fontSize: '0.75rem', padding: '0 2px' }}
>✕</button>
)}
</label>
@@ -686,7 +686,7 @@ export default function AdminPage() {
{activeTab === 'personas' && (
<div>
{!isPersonaHydrated ? (
<p style={{ color: '#6b6862', fontSize: '0.85rem' }}>Loading personas…</p>
<p style={{ color: '#6a73a5', fontSize: '0.85rem' }}>Loading personas…</p>
) : (
<TableCard>
<TableHeader cols="1fr 80px 80px 56px" labels={['Persona', 'Torso', 'Legs', '']} />
@@ -694,15 +694,15 @@ export default function AdminPage() {
<div key={p.id} style={{ display: 'grid', gridTemplateColumns: '1fr 80px 80px 56px', padding: '0.875rem 1.25rem', alignItems: 'center', borderBottom: i < personas.length - 1 ? '1px solid rgba(0,0,0,0.04)' : 'none' }}>
<div>
<div style={{ fontSize: '0.85rem', color: '#374151', fontWeight: 500 }}>{p.label}</div>
<div style={{ fontSize: '0.7rem', color: '#94908a' }}>{p.description}</div>
<div style={{ fontSize: '0.7rem', color: '#8891C7' }}>{p.description}</div>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.375rem' }}>
<div style={{ width: 20, height: 20, borderRadius: 4, backgroundColor: p.colors.torso, border: '1px solid rgba(0,0,0,0.1)', flexShrink: 0 }} />
<span style={{ fontSize: '0.7rem', color: '#94908a', fontFamily: 'monospace' }}>{p.colors.torso}</span>
<span style={{ fontSize: '0.7rem', color: '#8891C7', fontFamily: 'monospace' }}>{p.colors.torso}</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.375rem' }}>
<div style={{ width: 20, height: 20, borderRadius: 4, backgroundColor: p.colors.legs, border: '1px solid rgba(0,0,0,0.1)', flexShrink: 0 }} />
<span style={{ fontSize: '0.7rem', color: '#94908a', fontFamily: 'monospace' }}>{p.colors.legs}</span>
<span style={{ fontSize: '0.7rem', color: '#8891C7', fontFamily: 'monospace' }}>{p.colors.legs}</span>
</div>
<div style={{ display: 'flex', justifyContent: 'center' }}>
{p.id !== 'none' && (
@@ -762,7 +762,7 @@ export default function AdminPage() {
</div>
{ordersError && <p style={errorTextStyle}>{ordersError}</p>}
{!ordersLoading && orders.length === 0 && !ordersError && (
<p style={{ color: '#94908a', fontSize: '0.85rem', textAlign: 'center', padding: '2rem' }}>No orders found.</p>
<p style={{ color: '#8891C7', fontSize: '0.85rem', textAlign: 'center', padding: '2rem' }}>No orders found.</p>
)}
{orders.length > 0 && (
<TableCard>
@@ -791,7 +791,7 @@ export default function AdminPage() {
</div>
{contactsError && <p style={errorTextStyle}>{contactsError}</p>}
{!contactsLoading && contacts.length === 0 && !contactsError && (
<p style={{ color: '#94908a', fontSize: '0.85rem', textAlign: 'center', padding: '2rem' }}>No contact inquiries yet.</p>
<p style={{ color: '#8891C7', fontSize: '0.85rem', textAlign: 'center', padding: '2rem' }}>No contact inquiries yet.</p>
)}
{contacts.length > 0 && (
<TableCard>
@@ -799,10 +799,10 @@ export default function AdminPage() {
{contacts.map((c, i) => (
<div key={c.id} style={{ display: 'grid', gridTemplateColumns: '1.5fr 1fr 1fr 2.5fr 1fr', padding: '1rem 1.25rem', alignItems: 'flex-start', borderBottom: i < contacts.length - 1 ? '1px solid rgba(0,0,0,0.04)' : 'none', gap: '1rem' }}>
<div style={{ fontSize: '0.85rem', fontWeight: 500, color: '#1e293b' }}>{c.name}</div>
<div style={{ fontSize: '0.8rem', color: '#6b6862' }}><a href={`mailto:${c.email}`} style={{ color: '#3b82f6', textDecoration: 'none' }}>{c.email}</a></div>
<div style={{ fontSize: '0.8rem', color: '#6b6862' }}>{c.phone ? <a href={`tel:${c.phone}`} style={{ color: '#6b6862', textDecoration: 'none' }}>{c.phone}</a> : '-'}</div>
<div style={{ fontSize: '0.8rem', color: '#6a73a5' }}><a href={`mailto:${c.email}`} style={{ color: '#3b82f6', textDecoration: 'none' }}>{c.email}</a></div>
<div style={{ fontSize: '0.8rem', color: '#6a73a5' }}>{c.phone ? <a href={`tel:${c.phone}`} style={{ color: '#6a73a5', textDecoration: 'none' }}>{c.phone}</a> : '-'}</div>
<div style={{ fontSize: '0.8rem', color: '#475569', whiteSpace: 'pre-wrap', lineHeight: 1.5 }}>{c.message}</div>
<div style={{ fontSize: '0.75rem', color: '#94908a' }}>{new Date(c.createdAt).toLocaleDateString('en-AE')}</div>
<div style={{ fontSize: '0.75rem', color: '#8891C7' }}>{new Date(c.createdAt).toLocaleDateString('en-AE')}</div>
</div>
))}
</TableCard>
@@ -813,15 +813,15 @@ export default function AdminPage() {
{/* SETTINGS TAB */}
{activeTab === 'settings' && (
<div>
<h2 style={{ fontSize: '1rem', fontWeight: 700, color: '#0a0907', margin: '0 0 1rem' }}>App Settings</h2>
<h2 style={{ fontSize: '1rem', fontWeight: 700, color: '#0a0a0c', margin: '0 0 1rem' }}>App Settings</h2>
{settingError && <p style={{ color: '#dc2626', fontSize: '0.8rem', marginBottom: '0.75rem' }}>{settingError}</p>}
{settingsLoading ? (
<p style={{ color: '#6b6862', fontSize: '0.875rem' }}>Loading…</p>
<p style={{ color: '#6a73a5', fontSize: '0.875rem' }}>Loading…</p>
) : (
<TableCard>
<TableHeader cols="1fr 1.5fr 110px 50px" labels={['Key', 'Value', '', '']} />
{settings.length === 0 && (
<p style={{ padding: '1rem', color: '#94908a', fontSize: '0.8rem' }}>No settings yet.</p>
<p style={{ padding: '1rem', color: '#8891C7', fontSize: '0.8rem' }}>No settings yet.</p>
)}
{settings.map((s, i) => (
<SettingRow
@@ -837,8 +837,8 @@ export default function AdminPage() {
)}
{/* Add new setting */}
<div style={{ marginTop: '1.25rem', padding: '1rem', background: '#f5f1e8', borderRadius: '0.75rem', border: '1px solid rgba(0,0,0,0.06)' }}>
<h3 style={{ fontSize: '0.875rem', fontWeight: 600, color: '#0a0907', margin: '0 0 0.75rem' }}>Add Setting</h3>
<div style={{ marginTop: '1.25rem', padding: '1rem', background: '#FBFBFD', borderRadius: '0.75rem', border: '1px solid rgba(0,0,0,0.06)' }}>
<h3 style={{ fontSize: '0.875rem', fontWeight: 600, color: '#0a0a0c', margin: '0 0 0.75rem' }}>Add Setting</h3>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1.5fr auto', gap: '0.5rem', alignItems: 'flex-end' }}>
<div>
<label style={labelStyle}>Key</label>
@@ -869,7 +869,7 @@ export default function AdminPage() {
{showPwModal && (
<div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.3)', backdropFilter: 'blur(4px)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 50 }}>
<div style={{ background: '#fff', borderRadius: '1rem', padding: '1.5rem', width: '100%', maxWidth: '380px', boxShadow: '0 20px 60px rgba(0,0,0,0.15)' }}>
<h2 style={{ fontSize: '1rem', fontWeight: 700, color: '#0a0907', margin: '0 0 1.25rem' }}>Change Password</h2>
<h2 style={{ fontSize: '1rem', fontWeight: 700, color: '#0a0a0c', margin: '0 0 1.25rem' }}>Change Password</h2>
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
{(['current', 'next', 'confirm'] as const).map((field) => (
<div key={field}>
@@ -918,7 +918,7 @@ function SettingRow({
useEffect(() => { setEditVal(setting.value); }, [setting.value]);
return (
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1.5fr 110px 50px', gap: '0.75rem', padding: '0.625rem 1rem', alignItems: 'center', background: index % 2 === 0 ? '#fff' : '#f5f1e8', borderTop: index > 0 ? '1px solid rgba(0,0,0,0.04)' : 'none' }}>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1.5fr 110px 50px', gap: '0.75rem', padding: '0.625rem 1rem', alignItems: 'center', background: index % 2 === 0 ? '#fff' : '#FBFBFD', borderTop: index > 0 ? '1px solid rgba(0,0,0,0.04)' : 'none' }}>
<span style={{ fontSize: '0.8rem', fontFamily: 'monospace', color: '#334155' }}>{setting.key}</span>
<input
value={editVal}
@@ -979,7 +979,7 @@ function OrderRow({
const fieldStyle: React.CSSProperties = {
fontSize: '0.63rem',
fontWeight: 600,
color: '#94908a',
color: '#8891C7',
textTransform: 'uppercase',
letterSpacing: '0.04em',
};
@@ -996,8 +996,8 @@ function OrderRow({
<div style={{ display: 'grid', gridTemplateColumns: '1fr 130px 90px 100px 28px', padding: '0.75rem 1.25rem', alignItems: 'center' }}>
<div>
<div style={{ fontSize: '0.85rem', color: '#374151', fontWeight: 500 }}>{name}</div>
{email && <div style={{ fontSize: '0.7rem', color: '#94908a' }}>{email}</div>}
<div style={{ fontSize: '0.65rem', color: '#cbc4b3', fontFamily: 'monospace', marginTop: '0.1rem' }}>{order.id}</div>
{email && <div style={{ fontSize: '0.7rem', color: '#8891C7' }}>{email}</div>}
<div style={{ fontSize: '0.65rem', color: '#DEE0F0', fontFamily: 'monospace', marginTop: '0.1rem' }}>{order.id}</div>
</div>
<div style={{ fontSize: '0.85rem', color: '#374151', fontWeight: 500 }}>{formatAmount(order.amount, order.currency)}</div>
<div>
@@ -1008,17 +1008,17 @@ function OrderRow({
fontSize: '0.65rem',
fontWeight: 600,
textTransform: 'uppercase',
background: order.status === 'succeeded' ? 'rgba(34,197,94,0.1)' : order.status === 'canceled' ? 'rgba(239,68,68,0.08)' : 'rgba(196, 162, 101,0.15)',
color: order.status === 'succeeded' ? '#16a34a' : order.status === 'canceled' ? '#dc2626' : '#6b6862',
background: order.status === 'succeeded' ? 'rgba(34,197,94,0.1)' : order.status === 'canceled' ? 'rgba(239,68,68,0.08)' : 'rgba(39, 63, 148,0.15)',
color: order.status === 'succeeded' ? '#16a34a' : order.status === 'canceled' ? '#dc2626' : '#6a73a5',
}}>
{order.status}
</span>
</div>
<div style={{ fontSize: '0.75rem', color: '#94908a' }}>{formatDate(order.created)}</div>
<div style={{ fontSize: '0.75rem', color: '#8891C7' }}>{formatDate(order.created)}</div>
<button
onClick={handleExpand}
title={expanded ? 'Collapse' : 'Show details'}
style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#94908a', fontSize: '0.7rem', padding: '2px 4px', borderRadius: 4 }}
style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#8891C7', fontSize: '0.7rem', padding: '2px 4px', borderRadius: 4 }}
>
{expanded ? '▲' : '▼'}
</button>
@@ -1073,16 +1073,16 @@ function OrderRow({
</div>
))}
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', paddingTop: '0.4rem', marginTop: '0.1rem', borderTop: '1px solid rgba(0,0,0,0.07)' }}>
<span style={{ fontSize: '0.82rem', fontWeight: 700, color: '#0a0907' }}>Total</span>
<span style={{ fontSize: '0.88rem', fontWeight: 700, color: '#0a0907', fontFamily: 'monospace' }}>
<span style={{ fontSize: '0.82rem', fontWeight: 700, color: '#0a0a0c' }}>Total</span>
<span style={{ fontSize: '0.88rem', fontWeight: 700, color: '#0a0a0c', fontFamily: 'monospace' }}>
{formatAmount(order.amount, order.currency)}
</span>
</div>
</div>
) : (
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span style={{ fontSize: '0.78rem', color: '#6b6862' }}>Total (legacy order)</span>
<span style={{ fontSize: '0.88rem', fontWeight: 700, color: '#0a0907', fontFamily: 'monospace' }}>
<span style={{ fontSize: '0.78rem', color: '#6a73a5' }}>Total (legacy order)</span>
<span style={{ fontSize: '0.88rem', fontWeight: 700, color: '#0a0a0c', fontFamily: 'monospace' }}>
{formatAmount(order.amount, order.currency)}
</span>
</div>
@@ -1090,16 +1090,16 @@ function OrderRow({
</SectionBox>
{/* Payment ID */}
<div style={{ fontSize: '0.65rem', color: '#cbc4b3', fontFamily: 'monospace' }}>
<div style={{ fontSize: '0.65rem', color: '#DEE0F0', fontFamily: 'monospace' }}>
Payment ID: {order.id}
</div>
</div>
{/* Right: snapshot */}
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.375rem' }}>
<div style={{ fontSize: '0.63rem', fontWeight: 600, color: '#94908a', textTransform: 'uppercase', letterSpacing: '0.04em' }}>Robot Snapshot</div>
<div style={{ fontSize: '0.63rem', fontWeight: 600, color: '#8891C7', textTransform: 'uppercase', letterSpacing: '0.04em' }}>Robot Snapshot</div>
{snapshot === 'loading' && (
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'rgba(248,248,246,0.8)', borderRadius: '0.5rem', minHeight: 120, fontSize: '0.75rem', color: '#94908a' }}>Loading…</div>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'rgba(248,248,246,0.8)', borderRadius: '0.5rem', minHeight: 120, fontSize: '0.75rem', color: '#8891C7' }}>Loading…</div>
)}
{snapshot && snapshot !== 'loading' && snapshot !== 'none' && (
/* eslint-disable-next-line @next/next/no-img-element */
@@ -1110,7 +1110,7 @@ function OrderRow({
/>
)}
{snapshot === 'none' && (
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'rgba(248,248,246,0.8)', borderRadius: '0.5rem', minHeight: 80, fontSize: '0.72rem', color: '#cbc4b3' }}>No snapshot</div>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'rgba(248,248,246,0.8)', borderRadius: '0.5rem', minHeight: 80, fontSize: '0.72rem', color: '#DEE0F0' }}>No snapshot</div>
)}
</div>
</div>
@@ -1122,7 +1122,7 @@ function OrderRow({
function SectionBox({ title, children }: { title: string; children: React.ReactNode }) {
return (
<div style={{ background: 'rgba(248,248,246,0.8)', borderRadius: '0.5rem', padding: '0.75rem 1rem' }}>
<div style={{ fontSize: '0.6rem', fontWeight: 700, color: '#94908a', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: '0.5rem' }}>{title}</div>
<div style={{ fontSize: '0.6rem', fontWeight: 700, color: '#8891C7', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: '0.5rem' }}>{title}</div>
{children}
</div>
);
@@ -1138,7 +1138,7 @@ function InfoField({ label, value }: { label: string; value?: string | null }) {
if (!value) return null;
return (
<div>
<div style={{ fontSize: '0.63rem', fontWeight: 600, color: '#94908a', textTransform: 'uppercase', letterSpacing: '0.04em' }}>{label}</div>
<div style={{ fontSize: '0.63rem', fontWeight: 600, color: '#8891C7', textTransform: 'uppercase', letterSpacing: '0.04em' }}>{label}</div>
<div style={{ fontSize: '0.8rem', color: '#374151', marginTop: '0.1rem', wordBreak: 'break-word' }}>{value}</div>
</div>
);
@@ -1147,8 +1147,8 @@ function InfoField({ label, value }: { label: string; value?: string | null }) {
function StatCard({ label, value }: { label: string; value: string }) {
return (
<div style={{ background: 'rgba(255,255,255,0.95)', border: '1px solid rgba(0,0,0,0.06)', borderRadius: '0.75rem', padding: '1rem 1.25rem' }}>
<div style={{ fontSize: '0.7rem', fontWeight: 600, color: '#94908a', textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: '0.25rem' }}>{label}</div>
<div style={{ fontSize: '1.25rem', fontWeight: 700, color: '#0a0907' }}>{value}</div>
<div style={{ fontSize: '0.7rem', fontWeight: 600, color: '#8891C7', textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: '0.25rem' }}>{label}</div>
<div style={{ fontSize: '1.25rem', fontWeight: 700, color: '#0a0a0c' }}>{value}</div>
</div>
);
}
@@ -1165,7 +1165,7 @@ function TableHeader({ cols, labels }: { cols: string; labels: string[] }) {
return (
<div style={{ display: 'grid', gridTemplateColumns: cols, padding: '0.6rem 1.25rem', borderBottom: '1px solid rgba(0,0,0,0.04)', background: 'rgba(248,248,246,0.5)' }}>
{labels.map((l) => (
<span key={l} style={{ fontSize: '0.65rem', fontWeight: 600, color: '#6b6862', textTransform: 'uppercase', letterSpacing: '0.05em' }}>{l}</span>
<span key={l} style={{ fontSize: '0.65rem', fontWeight: 600, color: '#6a73a5', textTransform: 'uppercase', letterSpacing: '0.05em' }}>{l}</span>
))}
</div>
);
@@ -1204,7 +1204,7 @@ const formInputStyle: React.CSSProperties = {
borderRadius: '0.375rem',
border: '1px solid rgba(0,0,0,0.1)',
background: '#ffffff',
color: '#0a0907',
color: '#0a0a0c',
fontSize: '0.8rem',
outline: 'none',
boxSizing: 'border-box',
@@ -1216,7 +1216,7 @@ const tableInputStyle: React.CSSProperties = {
borderRadius: '0.375rem',
border: '1px solid rgba(0,0,0,0.1)',
background: '#ffffff',
color: '#0a0907',
color: '#0a0a0c',
fontSize: '0.8rem',
fontFamily: 'monospace',
textAlign: 'right' as const,
+3 -3
View File
@@ -21,7 +21,7 @@ export default function BookDemoPage() {
<h1 style={{ margin: 0, fontSize: 'clamp(2rem, 5vw, 3.2rem)', fontWeight: 300, lineHeight: 1.05, letterSpacing: '-0.03em' }}>
<span className="text-gradient" style={{ fontWeight: 500 }}>See the future in person.</span>
</h1>
<p style={{ margin: 0, color: '#cbc4b3', fontSize: 'clamp(0.95rem, 2vw, 1.05rem)', lineHeight: 1.7 }}>
<p style={{ margin: 0, color: '#DEE0F0', fontSize: 'clamp(0.95rem, 2vw, 1.05rem)', lineHeight: 1.7 }}>
Book a live robot demo at our Dubai showroom or schedule an on-site demo at your venue. Our team will tailor the demo to your use case before you arrive.
</p>
@@ -32,8 +32,8 @@ export default function BookDemoPage() {
'Walk through configuration and deployment options',
'Get UAE-specific pricing and availability',
].map((b) => (
<li key={b} style={{ display: 'flex', alignItems: 'flex-start', gap: '0.625rem', color: '#cbc4b3', lineHeight: 1.55 }}>
<span style={{ width: 8, height: 8, marginTop: 8, borderRadius: 999, background: '#e0c896', flex: 'none' }} />
<li key={b} style={{ display: 'flex', alignItems: 'flex-start', gap: '0.625rem', color: '#DEE0F0', lineHeight: 1.55 }}>
<span style={{ width: 8, height: 8, marginTop: 8, borderRadius: 999, background: '#DEE0F0', flex: 'none' }} />
{b}
</li>
))}
+3 -3
View File
@@ -28,10 +28,10 @@ export default function BrandsPage() {
Selected Unitree and Pudu solutions — exclusively in the UAE.
</span>
</h1>
<p style={{ margin: 0, color: '#cbc4b3', fontSize: 'clamp(0.95rem, 2vw, 1.05rem)', lineHeight: 1.7 }}>
<p style={{ margin: 0, color: '#DEE0F0', fontSize: 'clamp(0.95rem, 2vw, 1.05rem)', lineHeight: 1.7 }}>
YS Lootah Robotics holds exclusive UAE sales rights for selected Unitree and Pudu Robotics solutions — with on-the-ground sales, demo, and deployment support across Dubai and the UAE.
</p>
<p style={{ margin: 0, color: '#6b6862', fontSize: '0.82rem', lineHeight: 1.6 }}>
<p style={{ margin: 0, color: '#6a73a5', fontSize: '0.82rem', lineHeight: 1.6 }}>
Brand names and product trademarks are property of their respective owners. Available exclusively in the UAE through YS Lootah Robotics.
</p>
</div>
@@ -57,7 +57,7 @@ export default function BrandsPage() {
{robots.length} model{robots.length === 1 ? '' : 's'}
</span>
</div>
<p style={{ margin: 0, color: '#cbc4b3', lineHeight: 1.7, maxWidth: 800, marginBottom: '1.5rem' }}>
<p style={{ margin: 0, color: '#DEE0F0', lineHeight: 1.7, maxWidth: 800, marginBottom: '1.5rem' }}>
{brand.description}
</p>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.625rem', marginBottom: '2rem' }}>
+3 -3
View File
@@ -17,8 +17,8 @@ export default function ConfigurePage() {
paddingLeft: 'clamp(1rem, 4vw, 2rem)',
paddingRight: 'clamp(1rem, 4vw, 2rem)',
background:
'radial-gradient(ellipse 60% 80% at 50% 0%, rgba(196, 162, 101,0.12), transparent 60%), linear-gradient(180deg, #050505 0%, #030303 100%)',
borderBottom: '1px solid rgba(196, 162, 101,0.12)',
'radial-gradient(ellipse 60% 80% at 50% 0%, rgba(39, 63, 148,0.12), transparent 60%), linear-gradient(180deg, #050505 0%, #030303 100%)',
borderBottom: '1px solid rgba(39, 63, 148,0.12)',
}}
>
<div style={{ maxWidth: 1320, margin: '0 auto', display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
@@ -34,7 +34,7 @@ export default function ConfigurePage() {
>
<span className="text-gradient" style={{ fontWeight: 500 }}>Configure your robot.</span>
</h1>
<p style={{ margin: 0, color: '#94908a', fontSize: 'clamp(0.85rem, 1.6vw, 0.95rem)', lineHeight: 1.6, maxWidth: 720 }}>
<p style={{ margin: 0, color: '#8891C7', fontSize: 'clamp(0.85rem, 1.6vw, 0.95rem)', lineHeight: 1.6, maxWidth: 720 }}>
Choose persona, attire, colors, and accessories — visualize your Unitree G1 humanoid before you request a quotation from YS Lootah Robotics.
</p>
</div>
+6 -6
View File
@@ -21,14 +21,14 @@ export default function ContactPage() {
<h1 style={{ margin: 0, fontSize: 'clamp(2rem, 5vw, 3.2rem)', fontWeight: 300, lineHeight: 1.05, letterSpacing: '-0.03em' }}>
<span className="text-gradient" style={{ fontWeight: 500 }}>Talk to our Dubai robotics team.</span>
</h1>
<p style={{ margin: 0, color: '#cbc4b3', fontSize: 'clamp(0.95rem, 2vw, 1.05rem)', lineHeight: 1.7 }}>
<p style={{ margin: 0, color: '#DEE0F0', fontSize: 'clamp(0.95rem, 2vw, 1.05rem)', lineHeight: 1.7 }}>
Tell us about your venue, timeline, and use case. We will recommend a robot, share availability, and book a live demo at our Dubai showroom.
</p>
<div className="card" style={{ padding: 'clamp(1.5rem, 4vw, 2rem)', display: 'flex', flexDirection: 'column', gap: '1rem' }}>
<ContactRow label="Phone" value="+971 55 948 2728" href="tel:+971559482728" />
<ContactRow label="Office" value="+971 4 349 9319" href="tel:+97143499319" />
<ContactRow label="Email" value="info@yslootahtech.com" href="mailto:info@yslootahtech.com" />
<ContactRow label="Email" value="info@yslootahrobotics.com" href="mailto:info@yslootahrobotics.com" />
<ContactRow label="WhatsApp" value="+971 55 948 2728" href="https://wa.me/971559482728" external />
<ContactRow label="Address" value="Office 408, City Bay Business Center, Dubai, UAE" href="https://maps.google.com/?q=Office+408+City+Bay+Business+Center+Dubai" external />
</div>
@@ -60,13 +60,13 @@ function ContactRow({ label, value, href, external = false }: { label: string; v
alignItems: 'center',
gap: '1rem',
padding: '0.75rem 0',
borderBottom: '1px solid rgba(196, 162, 101,0.1)',
borderBottom: '1px solid rgba(39, 63, 148,0.1)',
textDecoration: 'none',
color: '#f5f1e8',
color: '#FBFBFD',
}}
>
<span style={{ fontSize: '0.7rem', letterSpacing: '0.22em', textTransform: 'uppercase', color: '#94908a' }}>{label}</span>
<span style={{ fontSize: '0.95rem', color: '#f5f1e8', textAlign: 'right' }}>{value}</span>
<span style={{ fontSize: '0.7rem', letterSpacing: '0.22em', textTransform: 'uppercase', color: '#8891C7' }}>{label}</span>
<span style={{ fontSize: '0.95rem', color: '#FBFBFD', textAlign: 'right' }}>{value}</span>
</a>
);
}
+97 -76
View File
@@ -1,44 +1,48 @@
@import "tailwindcss";
@theme {
/* === Luxury robotics — Black + Gold === */
--color-bg: #050505;
--color-bg-2: #0a0a0c;
--color-bg-3: #111114;
--color-bg-4: #18181c;
--color-surface: rgba(20, 18, 14, 0.7);
--color-primary: #050505;
--color-secondary: #0a0a0c;
/* === Luxury robotics — Graphite + Royal Blue + Silver === */
--color-bg: #0a0a0c;
--color-bg-2: #16151a;
--color-bg-3: #1c1b21;
--color-bg-4: #221f20;
--color-surface: rgba(34, 31, 32, 0.7);
--color-primary: #0a0a0c;
--color-secondary: #16151a;
/* Gold spectrum (matches YS Lootah brand) */
--color-gold: #c4a265;
--color-gold-light: #e0c896;
--color-gold-rich: #d4af6a;
--color-gold-bronze: #8b6f47;
--color-gold-deep: #6b5436;
/* Logo palette */
--color-blue: #273F94;
--color-blue-deep: #1a2e6e;
--color-blue-bright: #3a55c4;
--color-silver: #DEE0F0;
--color-silver-soft: #BFC3E2;
--color-steel: #8891C7;
--color-graphite: #221F20;
--color-white: #FBFBFD;
/* Accent aliases */
--color-accent: #c4a265;
--color-accent-2: #d4af6a;
--color-accent-3: #8b6f47;
--color-accent-hover: #d4af6a;
/* Accent aliases (kept for legacy class names) */
--color-gold: #DEE0F0;
--color-accent: #273F94;
--color-accent-2: #BFC3E2;
--color-accent-3: #8891C7;
--color-accent-hover: #3a55c4;
/* Text */
--color-text-primary: #f5f1e8;
--color-text-secondary: #cbc4b3;
--color-text-muted: #94908a;
--color-text-dim: #6b6862;
--color-text-primary: #FBFBFD;
--color-text-secondary: #DEE0F0;
--color-text-muted: #8891C7;
--color-text-dim: #6a73a5;
/* Borders */
--color-border: rgba(196, 162, 101, 0.18);
--color-border-strong: rgba(196, 162, 101, 0.36);
--color-border-light: rgba(196, 162, 101, 0.08);
--color-border-neutral: rgba(245, 241, 232, 0.08);
--color-border: rgba(191, 195, 226, 0.18);
--color-border-strong: rgba(191, 195, 226, 0.36);
--color-border-light: rgba(191, 195, 226, 0.08);
--color-border-neutral: rgba(255, 255, 255, 0.08);
/* Glass */
--color-glass-bg: rgba(20, 18, 14, 0.55);
--color-glass-border: rgba(196, 162, 101, 0.22);
--color-glass-highlight: rgba(245, 241, 232, 0.05);
--color-glass-bg: rgba(28, 27, 33, 0.6);
--color-glass-border: rgba(191, 195, 226, 0.22);
--color-glass-highlight: rgba(222, 224, 240, 0.06);
/* Spacing */
--spacing-xs: 0.25rem;
@@ -56,9 +60,9 @@
--radius-2xl: 1.5rem;
/* Shadows */
--shadow-glow: 0 0 30px rgba(196, 162, 101, 0.22);
--shadow-glow-lg: 0 0 60px rgba(196, 162, 101, 0.28);
--shadow-card: 0 14px 50px rgba(0, 0, 0, 0.55);
--shadow-glow: 0 0 30px rgba(39, 63, 148, 0.32);
--shadow-glow-lg: 0 0 60px rgba(39, 63, 148, 0.4);
--shadow-card: 0 14px 50px rgba(0, 0, 0, 0.6);
/* Transitions */
--transition-fast: 150ms ease;
@@ -81,10 +85,10 @@ body {
body {
background:
radial-gradient(1200px 700px at 80% -10%, rgba(196, 162, 101, 0.10), transparent 60%),
radial-gradient(900px 500px at -10% 30%, rgba(196, 162, 101, 0.06), transparent 60%),
radial-gradient(800px 500px at 50% 110%, rgba(139, 111, 71, 0.10), transparent 60%),
linear-gradient(180deg, #030303 0%, #050505 50%, #030303 100%);
radial-gradient(1200px 700px at 80% -10%, rgba(39, 63, 148, 0.18), transparent 60%),
radial-gradient(900px 500px at -10% 30%, rgba(58, 85, 196, 0.10), transparent 60%),
radial-gradient(800px 500px at 50% 110%, rgba(136, 145, 199, 0.10), transparent 60%),
linear-gradient(180deg, #050507 0%, #0a0a0c 50%, #050507 100%);
background-attachment: fixed;
}
@@ -93,12 +97,12 @@ html {
}
:focus-visible {
outline: 2px solid var(--color-gold);
outline: 2px solid var(--color-blue);
outline-offset: 2px;
}
::selection {
background-color: rgba(196, 162, 101, 0.4);
background-color: rgba(39, 63, 148, 0.55);
color: #ffffff;
}
@@ -123,9 +127,9 @@ html {
background: linear-gradient(135deg, var(--color-glass-highlight) 0%, transparent 60%);
}
/* === Typography gradients === */
/* === Typography gradients (metallic silver-blue) === */
.text-gradient {
background: linear-gradient(135deg, #ffffff 0%, #f5e9c8 40%, #d4af6a 100%);
background: linear-gradient(135deg, #FBFBFD 0%, #DEE0F0 45%, #8891C7 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
@@ -133,18 +137,17 @@ html {
}
.text-gradient-accent {
background: linear-gradient(135deg, #e0c896 0%, #c4a265 50%, #8b6f47 100%);
background: linear-gradient(135deg, #FBFBFD 0%, #DEE0F0 35%, #BFC3E2 65%, #273F94 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
}
.text-gold {
color: var(--color-gold);
}
.text-blue { color: var(--color-blue); }
.text-silver { color: var(--color-silver); }
/* Metallic gold border */
/* Metallic silver-blue border */
.metallic-border {
position: relative;
}
@@ -154,7 +157,7 @@ html {
inset: 0;
border-radius: inherit;
padding: 1px;
background: linear-gradient(135deg, rgba(224, 200, 150, 0.6), rgba(196, 162, 101, 0.25) 45%, rgba(139, 111, 71, 0.0) 100%);
background: linear-gradient(135deg, rgba(222, 224, 240, 0.55), rgba(136, 145, 199, 0.3) 45%, rgba(39, 63, 148, 0.0) 100%);
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
@@ -166,10 +169,10 @@ html {
position: absolute;
inset: 0;
background:
radial-gradient(ellipse 70% 60% at 60% 40%, rgba(196, 162, 101, 0.20) 0%, transparent 60%),
radial-gradient(ellipse 60% 50% at 20% 70%, rgba(139, 111, 71, 0.18) 0%, transparent 55%),
radial-gradient(ellipse 80% 70% at 80% 100%, rgba(224, 200, 150, 0.14) 0%, transparent 60%),
linear-gradient(180deg, #050505 0%, #070605 50%, #030303 100%);
radial-gradient(ellipse 70% 60% at 60% 40%, rgba(39, 63, 148, 0.32) 0%, transparent 60%),
radial-gradient(ellipse 60% 50% at 20% 70%, rgba(58, 85, 196, 0.22) 0%, transparent 55%),
radial-gradient(ellipse 80% 70% at 80% 100%, rgba(136, 145, 199, 0.18) 0%, transparent 60%),
linear-gradient(180deg, #07080c 0%, #0a0a10 50%, #050507 100%);
animation: heroShift 16s ease-in-out infinite alternate;
}
@@ -183,8 +186,8 @@ html {
position: absolute;
inset: 0;
background-image:
linear-gradient(rgba(196, 162, 101, 0.04) 1px, transparent 1px),
linear-gradient(90deg, rgba(196, 162, 101, 0.04) 1px, transparent 1px);
linear-gradient(rgba(191, 195, 226, 0.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(191, 195, 226, 0.05) 1px, transparent 1px);
background-size: 48px 48px;
mask-image: radial-gradient(ellipse 60% 50% at 50% 40%, #000 30%, transparent 80%);
-webkit-mask-image: radial-gradient(ellipse 60% 50% at 50% 40%, #000 30%, transparent 80%);
@@ -199,12 +202,29 @@ html {
}
.shimmer {
background: linear-gradient(110deg, transparent 35%, rgba(224, 200, 150, 0.12) 50%, transparent 65%);
background: linear-gradient(110deg, transparent 35%, rgba(222, 224, 240, 0.14) 50%, transparent 65%);
background-size: 200% 100%;
animation: shimmer 3.5s linear infinite;
}
@keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
/* Cinematic light sweep across hero */
.light-sweep {
position: absolute;
inset: 0;
pointer-events: none;
background: linear-gradient(110deg, transparent 30%, rgba(191, 195, 226, 0.07) 50%, transparent 70%);
background-size: 250% 100%;
animation: lightSweep 9s ease-in-out infinite;
mix-blend-mode: screen;
}
@keyframes lightSweep {
0% { background-position: 200% 0; opacity: 0; }
25% { opacity: 1; }
75% { opacity: 1; }
100% { background-position: -200% 0; opacity: 0; }
}
.float-y { animation: floatY 6s ease-in-out infinite; }
@keyframes floatY {
0%, 100% { transform: translateY(0); }
@@ -214,8 +234,8 @@ html {
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes pulseGlow {
0%, 100% { box-shadow: 0 0 0 0 rgba(196, 162, 101, 0.55), 0 0 40px rgba(196, 162, 101, 0.25); }
50% { box-shadow: 0 0 0 12px rgba(196, 162, 101, 0), 0 0 60px rgba(196, 162, 101, 0.45); }
0%, 100% { box-shadow: 0 0 0 0 rgba(39, 63, 148, 0.55), 0 0 40px rgba(39, 63, 148, 0.32); }
50% { box-shadow: 0 0 0 12px rgba(39, 63, 148, 0), 0 0 60px rgba(39, 63, 148, 0.55); }
}
/* Scroll indicator */
@@ -232,7 +252,7 @@ html {
left: 0;
width: 1px;
height: 100%;
background: linear-gradient(180deg, var(--color-gold), transparent);
background: linear-gradient(180deg, var(--color-blue), transparent);
animation: scrollPulse 2s ease-in-out infinite;
}
@keyframes scrollPulse {
@@ -243,8 +263,8 @@ html {
/* === Scrollbar === */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: var(--color-bg-2); }
::-webkit-scrollbar-thumb { background: rgba(196, 162, 101, 0.25); border-radius: var(--radius-sm); }
::-webkit-scrollbar-thumb:hover { background: rgba(196, 162, 101, 0.55); }
::-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 {
@@ -266,33 +286,33 @@ html {
.btn:hover { transform: translateY(-1px); }
.btn-primary {
background: linear-gradient(135deg, #e0c896 0%, #c4a265 55%, #8b6f47 100%);
color: #0b0905;
box-shadow: 0 8px 28px rgba(196, 162, 101, 0.35), inset 0 1px 0 rgba(255, 244, 220, 0.4);
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);
}
.btn-primary:hover {
box-shadow: 0 12px 38px rgba(224, 200, 150, 0.55), inset 0 1px 0 rgba(255, 244, 220, 0.5);
box-shadow: 0 12px 38px rgba(58, 85, 196, 0.6), inset 0 1px 0 rgba(222, 224, 240, 0.35);
}
.btn-ghost {
background: rgba(245, 241, 232, 0.04);
color: #f5f1e8;
border-color: rgba(196, 162, 101, 0.28);
background: rgba(222, 224, 240, 0.04);
color: #FBFBFD;
border-color: rgba(191, 195, 226, 0.28);
backdrop-filter: blur(12px);
}
.btn-ghost:hover {
background: rgba(196, 162, 101, 0.10);
border-color: rgba(196, 162, 101, 0.55);
color: #e0c896;
background: rgba(39, 63, 148, 0.16);
border-color: rgba(136, 145, 199, 0.6);
color: #DEE0F0;
}
.btn-outline {
background: transparent;
color: #e0c896;
border-color: rgba(196, 162, 101, 0.55);
color: #DEE0F0;
border-color: rgba(136, 145, 199, 0.55);
}
.btn-outline:hover {
background: rgba(196, 162, 101, 0.10);
background: rgba(39, 63, 148, 0.14);
}
/* === Layout helpers === */
@@ -312,13 +332,13 @@ html {
content: '';
width: 28px;
height: 1px;
background: linear-gradient(90deg, transparent, var(--color-gold));
background: linear-gradient(90deg, transparent, var(--color-silver));
}
/* === Cards === */
.card {
position: relative;
background: rgba(10, 9, 7, 0.72);
background: rgba(22, 21, 26, 0.72);
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
border: 1px solid var(--color-border);
@@ -328,8 +348,8 @@ html {
}
.card:hover {
transform: translateY(-6px);
border-color: rgba(196, 162, 101, 0.55);
box-shadow: 0 20px 60px rgba(0,0,0,0.7), 0 0 40px rgba(196, 162, 101, 0.15);
border-color: rgba(136, 145, 199, 0.55);
box-shadow: 0 20px 60px rgba(0,0,0,0.7), 0 0 40px rgba(39, 63, 148, 0.22);
}
/* === Configurator (preserve previous theme rules) === */
@@ -461,6 +481,7 @@ html {
scroll-behavior: auto !important;
}
.hero-gradient { animation: none !important; }
.light-sweep { animation: none !important; opacity: 0 !important; }
}
html, body { overflow-x: hidden; max-width: 100vw; }
+1 -1
View File
@@ -25,7 +25,7 @@ export default function IndustriesPage() {
Robotics solutions for UAE businesses.
</span>
</h1>
<p style={{ margin: 0, color: '#cbc4b3', fontSize: 'clamp(0.95rem, 2vw, 1.05rem)', lineHeight: 1.7 }}>
<p style={{ margin: 0, color: '#DEE0F0', fontSize: 'clamp(0.95rem, 2vw, 1.05rem)', lineHeight: 1.7 }}>
We deploy humanoid, quadruped, and service robots across industries that are reshaping how the UAE operates — every venue is matched to the right robot.
</p>
</div>
+1 -1
View File
@@ -45,7 +45,7 @@ export const metadata: Metadata = {
export const viewport: Viewport = {
width: 'device-width',
initialScale: 1,
themeColor: '#050505',
themeColor: '#0a0a0c',
};
export default function RootLayout({
+34 -1
View File
@@ -12,6 +12,10 @@ import { ExclusiveAccessSection } from '@/components/robotics/ExclusiveAccessSec
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';
import { FEATURED_ROBOTS } from '@/data/robots';
@@ -51,6 +55,12 @@ export default function HomePage() {
</div>
</MotionSection>
<MotionSection style={{ padding: 'clamp(3rem, 6vw, 5rem) 0' }} id="about">
<div className="container-wide">
<CompanyStory />
</div>
</MotionSection>
<MotionSection style={{ padding: 'clamp(3rem, 6vw, 5rem) 0' }} id="brands">
<div className="container-wide" style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
<SectionHeading
@@ -111,6 +121,29 @@ 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="Our solutions"
title="Intelligent robotics across the full lifecycle."
description="From autonomous robotics and intelligent automation to motion programming, SDKs, and remote diagnostics — a complete robotics partner for UAE businesses."
/>
<ServicesGrid />
</div>
</MotionSection>
<MotionSection style={{ padding: 'clamp(3rem, 6vw, 5rem) 0' }} id="leadership">
<div className="container-wide">
<FounderSection />
</div>
</MotionSection>
<MotionSection style={{ padding: 'clamp(3rem, 6vw, 5rem) 0' }} id="bu-sunaidah">
<div className="container-wide">
<BuSunaidahSection />
</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
@@ -158,7 +191,7 @@ function SectionHeading({ eyebrow, title, description }: { eyebrow: string; titl
<span className="text-gradient" style={{ fontWeight: 500 }}>{title}</span>
</h2>
{description && (
<p style={{ margin: 0, color: '#cbc4b3', fontSize: 'clamp(0.95rem, 2vw, 1.05rem)', lineHeight: 1.7 }}>
<p style={{ margin: 0, color: '#DEE0F0', fontSize: 'clamp(0.95rem, 2vw, 1.05rem)', lineHeight: 1.7 }}>
{description}
</p>
)}
+6 -6
View File
@@ -9,38 +9,38 @@ export default function PrivacyPolicyPage() {
<div style={{ background: '#050508', minHeight: '100vh', color: '#ffffff', fontFamily: 'Inter, sans-serif' }}>
<main style={{ maxWidth: '800px', margin: '0 auto', padding: '12rem 1.5rem 6rem', lineHeight: 1.8 }}>
<h1 style={{ fontSize: '3rem', fontWeight: 200, marginBottom: '1rem', letterSpacing: '-0.03em' }}>Privacy <span style={{ color: 'var(--color-gold)', fontWeight: 500 }}>Policy</span></h1>
<p style={{ color: '#94908a', fontSize: '1rem', marginBottom: '4rem' }}>Effective Date: {new Date().toLocaleDateString('en-AE')}</p>
<p style={{ color: '#8891C7', fontSize: '1rem', marginBottom: '4rem' }}>Effective Date: {new Date().toLocaleDateString('en-AE')}</p>
<section style={{ marginBottom: '3rem' }}>
<h2 style={{ fontSize: '1.5rem', fontWeight: 500, color: '#e8e0cf', marginBottom: '1rem' }}>1. Information We Collect</h2>
<p style={{ color: '#cbc4b3', marginBottom: '1rem' }}>
<p style={{ color: '#DEE0F0', marginBottom: '1rem' }}>
At YS Lootah Robotics, we collect information you provide directly to us when you request information, use the G1 Customizer, or contact us. This includes your name, email address, phone number, and any other information you choose to provide in your message.
</p>
</section>
<section style={{ marginBottom: '3rem' }}>
<h2 style={{ fontSize: '1.5rem', fontWeight: 500, color: '#e8e0cf', marginBottom: '1rem' }}>2. How We Use Your Information</h2>
<p style={{ color: '#cbc4b3', marginBottom: '1rem' }}>
<p style={{ color: '#DEE0F0', marginBottom: '1rem' }}>
We use the information we collect to respond to your inquiries, deliver our robotics enterprise solutions, maintain our dashboard, and communicate with you about your custom humanoid configurations.
</p>
</section>
<section style={{ marginBottom: '3rem' }}>
<h2 style={{ fontSize: '1.5rem', fontWeight: 500, color: '#e8e0cf', marginBottom: '1rem' }}>3. Data Security</h2>
<p style={{ color: '#cbc4b3', marginBottom: '1rem' }}>
<p style={{ color: '#DEE0F0', marginBottom: '1rem' }}>
We implement robust security measures designed to protect your personal information. Your contact data is stored securely in our private databases strictly for administrative and operational purposes.
</p>
</section>
<section style={{ marginBottom: '3rem' }}>
<h2 style={{ fontSize: '1.5rem', fontWeight: 500, color: '#e8e0cf', marginBottom: '1rem' }}>4. Contact Us</h2>
<p style={{ color: '#cbc4b3', marginBottom: '1rem' }}>
<p style={{ color: '#DEE0F0', marginBottom: '1rem' }}>
If you have questions or concerns about this Privacy Policy, please reach out to us at:
<br/><br/>
<strong>YS Lootah Robotics</strong><br/>
Office 408, City Bay Business Center<br/>
Dubai, United Arab Emirates<br/>
Email: info@yslootahtech.com
Email: info@yslootahrobotics.com
</p>
</section>
</main>
+5 -5
View File
@@ -71,7 +71,7 @@ function CatalogInner() {
</div>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexWrap: 'wrap', gap: '0.5rem' }}>
<span style={{ color: '#94908a', fontSize: '0.85rem' }}>
<span style={{ color: '#8891C7', fontSize: '0.85rem' }}>
{filtered.length} robot{filtered.length === 1 ? '' : 's'} found
</span>
{(filter.brand !== 'all' || filter.category !== 'all') && (
@@ -81,7 +81,7 @@ function CatalogInner() {
style={{
background: 'transparent',
border: 'none',
color: '#e0c896',
color: '#DEE0F0',
fontSize: '0.78rem',
letterSpacing: '0.14em',
textTransform: 'uppercase',
@@ -95,9 +95,9 @@ function CatalogInner() {
</div>
{filtered.length === 0 ? (
<div className="card" style={{ padding: '2rem', textAlign: 'center', color: '#cbc4b3' }}>
<div className="card" style={{ padding: '2rem', textAlign: 'center', color: '#DEE0F0' }}>
No robots match these filters yet. Try a different brand or category, or{' '}
<a href="/contact/" style={{ color: '#e0c896', textDecoration: 'none' }}>contact us</a> for tailored options.
<a href="/contact/" style={{ color: '#DEE0F0', textDecoration: 'none' }}>contact us</a> for tailored options.
</div>
) : (
<div
@@ -118,7 +118,7 @@ function CatalogInner() {
export function CatalogClient() {
return (
<Suspense fallback={<div className="card" style={{ padding: '2rem', color: '#cbc4b3' }}>Loading catalog…</div>}>
<Suspense fallback={<div className="card" style={{ padding: '2rem', color: '#DEE0F0' }}>Loading catalog…</div>}>
<CatalogInner />
</Suspense>
);
+13 -13
View File
@@ -43,12 +43,12 @@ export default async function RobotDetailPage({ params }: { params: Promise<Para
<main style={{ paddingTop: 'clamp(6rem, 10vw, 8rem)', paddingBottom: 'clamp(4rem, 8vw, 6rem)' }}>
<div className="container-wide" style={{ display: 'flex', flexDirection: 'column', gap: 'clamp(3rem, 6vw, 5rem)' }}>
<nav style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem', fontSize: '0.78rem', letterSpacing: '0.14em', textTransform: 'uppercase', color: '#94908a' }}>
<Link href="/" style={{ color: '#94908a', textDecoration: 'none' }}>Home</Link>
<nav style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem', fontSize: '0.78rem', letterSpacing: '0.14em', textTransform: 'uppercase', color: '#8891C7' }}>
<Link href="/" style={{ color: '#8891C7', textDecoration: 'none' }}>Home</Link>
<span>/</span>
<Link href="/robots/" style={{ color: '#94908a', textDecoration: 'none' }}>Robots</Link>
<Link href="/robots/" style={{ color: '#8891C7', textDecoration: 'none' }}>Robots</Link>
<span>/</span>
<span style={{ color: '#cbc4b3' }}>{robot.name}</span>
<span style={{ color: '#DEE0F0' }}>{robot.name}</span>
</nav>
<section
@@ -73,8 +73,8 @@ export default async function RobotDetailPage({ params }: { params: Promise<Para
padding: '0.3rem 0.55rem',
borderRadius: 999,
background: 'rgba(5, 5, 5,0.6)',
border: '1px solid rgba(196, 162, 101,0.2)',
color: '#94908a',
border: '1px solid rgba(39, 63, 148,0.2)',
color: '#8891C7',
fontSize: '0.62rem',
letterSpacing: '0.2em',
textTransform: 'uppercase',
@@ -94,8 +94,8 @@ export default async function RobotDetailPage({ params }: { params: Promise<Para
{robot.name}
</span>
</h1>
<p style={{ margin: 0, color: '#e0c896', fontSize: '1.05rem', lineHeight: 1.5 }}>{robot.tagline}</p>
<p style={{ margin: 0, color: '#cbc4b3', fontSize: '1rem', lineHeight: 1.7 }}>{robot.longDescription}</p>
<p style={{ margin: 0, color: '#DEE0F0', fontSize: '1.05rem', lineHeight: 1.5 }}>{robot.tagline}</p>
<p style={{ margin: 0, color: '#DEE0F0', fontSize: '1rem', lineHeight: 1.7 }}>{robot.longDescription}</p>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.625rem' }}>
<a className="btn btn-primary" href="#inquire">Request quotation</a>
@@ -123,14 +123,14 @@ export default async function RobotDetailPage({ params }: { params: Promise<Para
<Block title="Key features">
<ul style={{ margin: 0, paddingLeft: '1.1rem', display: 'flex', flexDirection: 'column', gap: '0.6rem' }}>
{robot.features.map((f) => (
<li key={f} style={{ color: '#cbc4b3', lineHeight: 1.6 }}>{f}</li>
<li key={f} style={{ color: '#DEE0F0', lineHeight: 1.6 }}>{f}</li>
))}
</ul>
</Block>
<Block title="Use cases">
<ul style={{ margin: 0, paddingLeft: '1.1rem', display: 'flex', flexDirection: 'column', gap: '0.6rem' }}>
{robot.useCases.map((u) => (
<li key={u} style={{ color: '#cbc4b3', lineHeight: 1.6 }}>{u}</li>
<li key={u} style={{ color: '#DEE0F0', lineHeight: 1.6 }}>{u}</li>
))}
</ul>
</Block>
@@ -156,7 +156,7 @@ export default async function RobotDetailPage({ params }: { params: Promise<Para
Request a quotation for {robot.name}.
</span>
</h2>
<p style={{ margin: 0, color: '#cbc4b3', lineHeight: 1.7 }}>
<p style={{ margin: 0, color: '#DEE0F0', lineHeight: 1.7 }}>
Tell us about your venue, timeline, and use case. We will respond with availability, configuration options, and pricing for the UAE.
</p>
</div>
@@ -166,12 +166,12 @@ export default async function RobotDetailPage({ params }: { params: Promise<Para
<div className="card" style={{ padding: 'clamp(1.5rem, 4vw, 2.25rem)', display: 'flex', flexDirection: 'column', gap: '1rem' }}>
<span className="eyebrow">Talk to an advisor</span>
<h3 style={{ margin: 0, fontSize: '1.25rem', fontWeight: 600 }}>Prefer a quick conversation?</h3>
<p style={{ margin: 0, color: '#cbc4b3', lineHeight: 1.7 }}>
<p style={{ margin: 0, color: '#DEE0F0', lineHeight: 1.7 }}>
Call our Dubai team or message us on WhatsApp — we will share availability and demo slots for {robot.name}.
</p>
<a className="btn btn-ghost" href="tel:+971559482728">Call +971 55 948 2728</a>
<a className="btn btn-outline" href="https://wa.me/971559482728" target="_blank" rel="noopener noreferrer">WhatsApp us</a>
<a className="btn btn-ghost" href="mailto:info@yslootahtech.com">Email info@yslootahtech.com</a>
<a className="btn btn-ghost" href="mailto:info@yslootahrobotics.com">Email info@yslootahrobotics.com</a>
</div>
</div>
</MotionSection>
+1 -1
View File
@@ -23,7 +23,7 @@ export default function RobotsPage() {
Robots ready to deploy across the UAE.
</span>
</h1>
<p style={{ margin: 0, color: '#cbc4b3', fontSize: 'clamp(0.95rem, 2vw, 1.05rem)', lineHeight: 1.7 }}>
<p style={{ margin: 0, color: '#DEE0F0', fontSize: 'clamp(0.95rem, 2vw, 1.05rem)', lineHeight: 1.7 }}>
Browse {ROBOTS.length}+ models across our portfolio. Filter by brand or category, then request a price or book a live demo at our Dubai showroom.
</p>
</div>
+5 -5
View File
@@ -9,32 +9,32 @@ export default function TermsOfServicePage() {
<div style={{ background: '#050508', minHeight: '100vh', color: '#ffffff', fontFamily: 'Inter, sans-serif' }}>
<main style={{ maxWidth: '800px', margin: '0 auto', padding: '12rem 1.5rem 6rem', lineHeight: 1.8 }}>
<h1 style={{ fontSize: '3rem', fontWeight: 200, marginBottom: '1rem', letterSpacing: '-0.03em' }}>Terms of <span style={{ color: 'var(--color-gold)', fontWeight: 500 }}>Service</span></h1>
<p style={{ color: '#94908a', fontSize: '1rem', marginBottom: '4rem' }}>Effective Date: {new Date().toLocaleDateString('en-AE')}</p>
<p style={{ color: '#8891C7', fontSize: '1rem', marginBottom: '4rem' }}>Effective Date: {new Date().toLocaleDateString('en-AE')}</p>
<section style={{ marginBottom: '3rem' }}>
<h2 style={{ fontSize: '1.5rem', fontWeight: 500, color: '#e8e0cf', marginBottom: '1rem' }}>1. Acceptance of Terms</h2>
<p style={{ color: '#cbc4b3', marginBottom: '1rem' }}>
<p style={{ color: '#DEE0F0', marginBottom: '1rem' }}>
By accessing and utilizing the YS Lootah Robotics web platform and the G1 Configurator, you accept and agree to be bound by the terms and provisions of this agreement.
</p>
</section>
<section style={{ marginBottom: '3rem' }}>
<h2 style={{ fontSize: '1.5rem', fontWeight: 500, color: '#e8e0cf', marginBottom: '1rem' }}>2. Use of the Site & Configurator</h2>
<p style={{ color: '#cbc4b3', marginBottom: '1rem' }}>
<p style={{ color: '#DEE0F0', marginBottom: '1rem' }}>
The 3D G1 Configurator is provided for informational and demonstrative purposes to showcase the capabilities of YS Lootah technologies. You agree to use this site strictly for lawful purposes resulting in enterprise robotics inquiries and configurations.
</p>
</section>
<section style={{ marginBottom: '3rem' }}>
<h2 style={{ fontSize: '1.5rem', fontWeight: 500, color: '#e8e0cf', marginBottom: '1rem' }}>3. Intellectual Property Rights</h2>
<p style={{ color: '#cbc4b3', marginBottom: '1rem' }}>
<p style={{ color: '#DEE0F0', marginBottom: '1rem' }}>
All original content on this website, including but not limited to text, graphics, 3D models (GLB files), logos, and software, is the exclusive property of YS Lootah Robotics and is protected by United Arab Emirates and international copyright laws.
</p>
</section>
<section style={{ marginBottom: '3rem' }}>
<h2 style={{ fontSize: '1.5rem', fontWeight: 500, color: '#e8e0cf', marginBottom: '1rem' }}>4. Disclaimer of Warranties</h2>
<p style={{ color: '#cbc4b3', marginBottom: '1rem' }}>
<p style={{ color: '#DEE0F0', marginBottom: '1rem' }}>
The materials on our platform are provided "as is". We make no warranties, expressed or implied, and hereby disclaim to the fullest extent permitted by law all warranties regarding the immediate enterprise availability of the rendered concepts displayed in the Configurator.
</p>
</section>