feat: implement solutions page, use cases, and update landing page sections including MagicBento, ScrollStack, and interactive components
This commit is contained in:
@@ -5,6 +5,7 @@ import Link from 'next/link';
|
||||
import Image from 'next/image';
|
||||
import GSAPAnimator from '@/components/GSAPAnimator';
|
||||
import { useReveal } from '@/hooks/useReveal';
|
||||
import ScrollStack, { ScrollStackItem } from '@/components/ScrollStack';
|
||||
|
||||
function RevealBlock({ children, delay = 0 }: { children: React.ReactNode; delay?: number }) {
|
||||
const { ref, visible } = useReveal();
|
||||
@@ -17,6 +18,53 @@ function RevealBlock({ children, delay = 0 }: { children: React.ReactNode; delay
|
||||
);
|
||||
}
|
||||
|
||||
const PRODUCTS = [
|
||||
{
|
||||
n: '01', title: 'Behavision', subtitle: 'AI Powered Footfall Analytics', color: '#f4be28',
|
||||
desc: 'AI powered footfall analytics and behavioral intelligence for physical retail. Behavision turns every camera and sensor you already have into a live map of how customers move, where they linger, and what makes them walk away, so store layout and staffing decisions are based on evidence, not guesswork.',
|
||||
capabilities: [
|
||||
'Real-time footfall counting, accurate to 98% across every entry point',
|
||||
'Dwell-time and zone heatmaps that show exactly where attention concentrates',
|
||||
'Entry-to-purchase funnel tracking that flags where shoppers drop off',
|
||||
],
|
||||
metric: { val: '3.2×', lbl: 'conversion uplift' },
|
||||
tags: ['Footfall Tracking', 'Heatmaps', 'Behavior Analysis'],
|
||||
},
|
||||
{
|
||||
n: '02', title: 'SpendSense', subtitle: 'Customer Spending Intelligence', color: '#10B981',
|
||||
desc: 'Deep, continuously updating intelligence on how your customers spend. SpendSense studies basket size, purchase frequency, and category preferences across every visit, surfacing the high-value segments and the early warning signs of churn well before a customer stops coming back.',
|
||||
capabilities: [
|
||||
'Automatic customer segmentation by spend, frequency, and loyalty tier',
|
||||
'Predictive churn scoring that flags at-risk high-value shoppers early',
|
||||
'Revenue opportunity alerts triggered by shifting basket-size trends',
|
||||
],
|
||||
metric: { val: '68%', lbl: 'retention improvement' },
|
||||
tags: ['Spending Trends', 'Revenue Analytics', 'Customer Value'],
|
||||
},
|
||||
{
|
||||
n: '03', title: 'Dyscount', subtitle: 'Smart Discount Engine', color: '#EF4444',
|
||||
desc: 'A discount engine that treats margin as a budget, not an afterthought. Dyscount decides who gets an offer, how deep it goes, and when it fires, targeting the customers most likely to convert while capping every discount so promotions never quietly eat into profit.',
|
||||
capabilities: [
|
||||
'Dynamic offer targeting based on real-time purchase intent signals',
|
||||
'Margin-safe discount caps enforced per product, category, or campaign',
|
||||
'A/B tested offer formats that keep conversion up without overspending',
|
||||
],
|
||||
metric: { val: '41%', lbl: 'discount waste reduced' },
|
||||
tags: ['Smart Discounts', 'Offer Automation', 'Margin Protection'],
|
||||
},
|
||||
{
|
||||
n: '04', title: 'Identiq', subtitle: 'Consumer Loyalty Platform', color: '#f4be28',
|
||||
desc: 'The consumer-facing app that closes the loop. Identiq turns daily logins, walking challenges, and quick mini-games into LYT, Loyaly’s reward token, redeemable instantly at any partner store, so every idle moment on a phone becomes a reason to walk into a real one.',
|
||||
capabilities: [
|
||||
'Daily login and step-challenge rewards that build a lasting habit loop',
|
||||
'Game based offers like Spin Wheel, Scratch Card, and Maze Challenge',
|
||||
'Instant offline redemption at any partner store, no card required',
|
||||
],
|
||||
metric: { val: '50K+', lbl: 'active shoppers' },
|
||||
tags: ['Daily Rewards', 'Game Based Offers', 'Offline Redemption'],
|
||||
},
|
||||
];
|
||||
|
||||
const CAPS = [
|
||||
{
|
||||
n: '01', title: 'Merchant Campaign Platform', color: '#f4be28',
|
||||
@@ -139,6 +187,83 @@ export default function SolutionsPage() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── OUR PRODUCTS ── */}
|
||||
<section style={{ padding: '140px 8%', background: '#07070d', margin: '0 20px 20px', borderRadius: 24, overflow: 'hidden', position: 'relative' }}>
|
||||
<div style={{ position: 'absolute', inset: 0, backgroundImage: 'linear-gradient(rgba(244,190,40,0.025) 1px,transparent 1px),linear-gradient(90deg,rgba(244,190,40,0.025) 1px,transparent 1px)', backgroundSize: '64px 64px', pointerEvents: 'none' }} />
|
||||
<RevealBlock>
|
||||
<div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.2em', textTransform: 'uppercase', color: '#f4be28', fontFamily: 'Sora, sans-serif', marginBottom: 20, position: 'relative' }}>Our Products</div>
|
||||
<h2 style={{ fontSize: 'clamp(36px, 5vw, 72px)', fontWeight: 800, letterSpacing: '-0.04em', lineHeight: 0.95, color: '#fff', margin: '0 0 20px', fontFamily: 'Sora, sans-serif', position: 'relative', maxWidth: 700 }}>
|
||||
Four products.<br />One ecosystem.
|
||||
</h2>
|
||||
<p style={{ fontSize: 16, color: 'rgba(255,255,255,0.45)', fontFamily: 'Sora, sans-serif', maxWidth: 460, lineHeight: 1.7, marginBottom: 80, position: 'relative' }}>
|
||||
Each product solves a distinct part of the retail journey, and together they form one connected platform, from footfall to spend to loyalty.
|
||||
</p>
|
||||
</RevealBlock>
|
||||
|
||||
<div style={{ position: 'relative' }}>
|
||||
<ScrollStack useWindowScroll itemDistance={160} itemScale={0.035} itemStackDistance={40} baseScale={0.86} blurAmount={1.2}>
|
||||
{PRODUCTS.map((p, i) => (
|
||||
<ScrollStackItem key={i}>
|
||||
<div style={{
|
||||
background: `linear-gradient(155deg, #14141c 0%, #0c0c12 100%)`,
|
||||
border: `1px solid ${p.color}40`,
|
||||
borderRadius: 28, padding: 'clamp(28px, 3.2vw, 48px)', height: '100%', boxSizing: 'border-box',
|
||||
}}>
|
||||
<div className="sp-product-grid" style={{ display: 'grid', gridTemplateColumns: '1.35fr 1fr', gap: 'clamp(28px, 4vw, 56px)', alignItems: 'start' }}>
|
||||
|
||||
{/* Left — identity + description */}
|
||||
<div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 20 }}>
|
||||
<span style={{ fontSize: 13, fontWeight: 800, color: p.color, fontFamily: 'Sora, sans-serif', letterSpacing: '0.05em' }}>{p.n}</span>
|
||||
<span style={{ width: 24, height: 1, background: `${p.color}66`, display: 'block' }} />
|
||||
<span style={{ fontSize: '0.7rem', fontWeight: 700, letterSpacing: '0.1em', textTransform: 'uppercase', color: p.color, fontFamily: 'Sora, sans-serif' }}>{p.subtitle}</span>
|
||||
</div>
|
||||
<h3 style={{ fontSize: 'clamp(1.8rem, 2.8vw, 2.8rem)', fontWeight: 800, letterSpacing: '-0.03em', color: '#fff', margin: '0 0 16px', fontFamily: 'Sora, sans-serif' }}>{p.title}</h3>
|
||||
<p style={{ fontSize: 15, lineHeight: 1.75, color: 'rgba(255,255,255,0.5)', fontFamily: 'Sora, sans-serif', margin: '0 0 24px', maxWidth: 480 }}>{p.desc}</p>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
|
||||
{p.tags.map((tag) => (
|
||||
<span key={tag} style={{
|
||||
padding: '6px 14px', borderRadius: 100, fontSize: '0.72rem', fontWeight: 600,
|
||||
color: 'rgba(255,255,255,0.7)', background: 'rgba(255,255,255,0.05)',
|
||||
border: '1px solid rgba(255,255,255,0.1)', fontFamily: 'Sora, sans-serif',
|
||||
}}>{tag}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right — metric + capabilities */}
|
||||
<div>
|
||||
<div style={{
|
||||
padding: 'clamp(18px, 2vw, 24px)', borderRadius: 18, marginBottom: 18,
|
||||
background: `${p.color}12`, border: `1px solid ${p.color}35`,
|
||||
}}>
|
||||
<div style={{ fontSize: 'clamp(1.8rem, 2.6vw, 2.4rem)', fontWeight: 900, color: p.color, fontFamily: 'Sora, sans-serif', letterSpacing: '-0.03em', lineHeight: 1 }}>{p.metric.val}</div>
|
||||
<div style={{ fontSize: 12, color: 'rgba(255,255,255,0.45)', fontFamily: 'Sora, sans-serif', marginTop: 6, textTransform: 'uppercase', letterSpacing: '0.06em' }}>{p.metric.lbl}</div>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
||||
{p.capabilities.map((cap) => (
|
||||
<div key={cap} style={{ display: 'flex', alignItems: 'flex-start', gap: 10 }}>
|
||||
<span style={{
|
||||
width: 18, height: 18, borderRadius: '50%', flexShrink: 0, marginTop: 2,
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
background: `${p.color}18`, border: `1px solid ${p.color}45`,
|
||||
}}>
|
||||
<svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke={p.color} strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><path d="M20 6L9 17l-5-5" /></svg>
|
||||
</span>
|
||||
<span style={{ fontSize: 13.5, lineHeight: 1.55, color: 'rgba(255,255,255,0.65)', fontFamily: 'Sora, sans-serif' }}>{cap}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ScrollStackItem>
|
||||
))}
|
||||
</ScrollStack>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── WHY IT MATTERS ── */}
|
||||
<section style={{ padding: '140px 8%', background: '#07070d', margin: '0 20px 20px', borderRadius: 24, overflow: 'hidden', position: 'relative' }}>
|
||||
<div style={{ position: 'absolute', inset: 0, backgroundImage: 'linear-gradient(rgba(244,190,40,0.025) 1px,transparent 1px),linear-gradient(90deg,rgba(244,190,40,0.025) 1px,transparent 1px)', backgroundSize: '64px 64px', pointerEvents: 'none' }} />
|
||||
@@ -192,6 +317,7 @@ export default function SolutionsPage() {
|
||||
.sp-cap-row { grid-template-columns: 1fr !important; gap: 14px !important; padding: 28px 0 !important; }
|
||||
.sp-cap-row > div:last-child { justify-content: flex-start !important; }
|
||||
.sp-cta-grid { grid-template-columns: 1fr !important; gap: 40px !important; }
|
||||
.sp-product-grid { grid-template-columns: 1fr !important; }
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.sp-cta-grid > div > div { grid-template-columns: 1fr !important; }
|
||||
|
||||
Reference in New Issue
Block a user