updated mobile view

This commit is contained in:
R-Bharathraj
2026-07-15 13:16:11 +05:30
parent 89b0089457
commit 85e0f6eb63
25 changed files with 572 additions and 219 deletions

View File

@@ -29,22 +29,22 @@ const nextConfig: NextConfig = {
}, },
{ {
source: '/loyaly_php/use_cases.php', source: '/loyaly_php/use_cases.php',
destination: '/use_cases', destination: '/for_business',
permanent: true, permanent: true,
}, },
{ {
source: '/use_cases.php', source: '/use_cases.php',
destination: '/use_cases', destination: '/for_business',
permanent: true, permanent: true,
}, },
{ {
source: '/loyaly_php/solutions_page.php', source: '/loyaly_php/solutions_page.php',
destination: '/solutions_page', destination: '/meet_the_agents',
permanent: true, permanent: true,
}, },
{ {
source: '/solutions_page.php', source: '/solutions_page.php',
destination: '/solutions_page', destination: '/meet_the_agents',
permanent: true, permanent: true,
}, },
{ {

View File

@@ -1,6 +1,6 @@
'use client'; 'use client';
import React, { useState } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import Link from 'next/link'; import Link from 'next/link';
import Image from 'next/image'; import Image from 'next/image';
import { useReveal } from '@/hooks/useReveal'; import { useReveal } from '@/hooks/useReveal';
@@ -28,7 +28,7 @@ export default function AboutUsPage() {
minHeight: '100vh', background: 'radial-gradient(ellipse 120% 90% at 22% 0%, #3a2b5e 0%, #251c40 38%, #1a1530 100%)', minHeight: '100vh', background: 'radial-gradient(ellipse 120% 90% at 22% 0%, #3a2b5e 0%, #251c40 38%, #1a1530 100%)',
display: 'flex', alignItems: 'center', display: 'flex', alignItems: 'center',
padding: '120px 8% 80px', padding: '120px 8% 80px',
margin: '20px', borderRadius: '32px', margin: 'var(--hero-top) var(--sec-gutter) var(--sec-gap) var(--sec-gutter)', borderRadius: '32px',
position: 'relative', overflow: 'hidden', position: 'relative', overflow: 'hidden',
}}> }}>
{/* Background photo */} {/* Background photo */}
@@ -57,7 +57,7 @@ export default function AboutUsPage() {
</section> </section>
{/* ── OUR STORY ── */} {/* ── OUR STORY ── */}
<section style={{ padding: '140px 8%', background: '#fff', margin: '0 20px 20px', borderRadius: 24 }}> <section style={{ padding: '140px 8%', background: '#fff', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24 }}>
<div className="au-story-grid" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '8vw', alignItems: 'start' }}> <div className="au-story-grid" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '8vw', alignItems: 'start' }}>
<Reveal> <Reveal>
<SectionEyebrow variant="line" style={{ marginBottom: 24 }}>Our Story</SectionEyebrow> <SectionEyebrow variant="line" style={{ marginBottom: 24 }}>Our Story</SectionEyebrow>
@@ -77,7 +77,7 @@ export default function AboutUsPage() {
</section> </section>
{/* ── MISSION & VISION ── */} {/* ── MISSION & VISION ── */}
<section style={{ position: 'relative', overflow: 'hidden', padding: 'clamp(60px, 9vh, 104px) 8%', background: '#07070d', margin: '0 20px 20px', borderRadius: 28 }}> <section style={{ position: 'relative', overflow: 'hidden', padding: 'clamp(60px, 9vh, 104px) 8%', background: '#07070d', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 28 }}>
{/* Ambient top glow */} {/* Ambient top glow */}
<div aria-hidden style={{ position: 'absolute', top: '-24%', left: '50%', transform: 'translateX(-50%)', width: 680, height: 420, background: 'radial-gradient(ellipse, rgba(244,190,40,0.12) 0%, transparent 70%)', pointerEvents: 'none' }} /> <div aria-hidden style={{ position: 'absolute', top: '-24%', left: '50%', transform: 'translateX(-50%)', width: 680, height: 420, background: 'radial-gradient(ellipse, rgba(244,190,40,0.12) 0%, transparent 70%)', pointerEvents: 'none' }} />
@@ -209,7 +209,7 @@ export default function AboutUsPage() {
</section> </section>
{/* ── MARKET OPPORTUNITY ── */} {/* ── MARKET OPPORTUNITY ── */}
<section style={{ padding: '140px 8%', background: '#fff', margin: '0 20px 20px', borderRadius: 24 }}> <section style={{ padding: '140px 8%', background: '#fff', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24 }}>
<div className="au-market-grid" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '8vw', alignItems: 'start' }}> <div className="au-market-grid" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '8vw', alignItems: 'start' }}>
<Reveal> <Reveal>
<SectionEyebrow variant="pill" style={{ marginBottom: 24 }}>Market Opportunity</SectionEyebrow> <SectionEyebrow variant="pill" style={{ marginBottom: 24 }}>Market Opportunity</SectionEyebrow>
@@ -243,7 +243,7 @@ export default function AboutUsPage() {
{/* ── CLOSE: POINT TO THE CREW ── */} {/* ── CLOSE: POINT TO THE CREW ── */}
<section style={{ <section style={{
padding: '160px 8%', background: '#f4be28', padding: '160px 8%', background: '#f4be28',
margin: '0 20px 20px', borderRadius: 24, margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24,
display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center', display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center',
position: 'relative', overflow: 'hidden', position: 'relative', overflow: 'hidden',
}}> }}>
@@ -253,7 +253,7 @@ export default function AboutUsPage() {
"We're not just building a product. We're redefining retail." "We're not just building a product. We're redefining retail."
</p> </p>
<div style={{ display: 'flex', gap: 14, flexWrap: 'wrap', justifyContent: 'center', position: 'relative', zIndex: 2 }}> <div style={{ display: 'flex', gap: 14, flexWrap: 'wrap', justifyContent: 'center', position: 'relative', zIndex: 2 }}>
<Link href="/solutions_page" style={{ <Link href="/meet_the_agents" style={{
display: 'inline-flex', alignItems: 'center', gap: 10, display: 'inline-flex', alignItems: 'center', gap: 10,
padding: '18px 44px', background: '#111', color: '#f4be28', padding: '18px 44px', background: '#111', color: '#f4be28',
fontSize: 16, fontWeight: 800, borderRadius: 100, textDecoration: 'none', fontSize: 16, fontWeight: 800, borderRadius: 100, textDecoration: 'none',
@@ -374,7 +374,33 @@ function TeamCarousel() {
// Dimensions matching premium layout // Dimensions matching premium layout
const CARD_W = 320; const CARD_W = 320;
const CARD_GAP = 24; const CARD_GAP = 24;
const STEP = CARD_W + CARD_GAP;
// The card width (and gap) is responsive via CSS media queries, so the slide
// distance can't be a hard-coded constant. We measure the real pixel offset
// between the first two cards and recompute it on resize — this keeps the
// active card perfectly centered at every breakpoint.
const trackRef = useRef<HTMLDivElement>(null);
const [step, setStep] = useState(CARD_W + CARD_GAP);
useEffect(() => {
const measure = () => {
const track = trackRef.current;
if (!track) return;
const cards = track.querySelectorAll<HTMLElement>('.team-card');
if (cards.length >= 2) {
const delta = cards[1].offsetLeft - cards[0].offsetLeft;
if (delta > 0) setStep(delta);
}
};
measure();
// Re-measure once layout has settled (fonts, media queries, reveal) so the
// slide distance always matches the real rendered card width.
const raf = requestAnimationFrame(() => requestAnimationFrame(measure));
window.addEventListener('resize', measure);
return () => {
cancelAnimationFrame(raf);
window.removeEventListener('resize', measure);
};
}, [visible]);
const go = (dir: number) => setActive(a => Math.min(count - 1, Math.max(0, a + dir))); const go = (dir: number) => setActive(a => Math.min(count - 1, Math.max(0, a + dir)));
@@ -405,10 +431,10 @@ function TeamCarousel() {
const indexStr = String(active + 1).padStart(2, '0'); const indexStr = String(active + 1).padStart(2, '0');
return ( return (
<section ref={ref as React.RefObject<HTMLElement>} style={{ <section ref={ref as React.RefObject<HTMLElement>} className="team-section" style={{
padding: '110px 0 120px', padding: '110px 0 120px',
background: '#07070d', background: '#07070d',
margin: '0 20px 20px', margin: '0 var(--sec-gutter) var(--sec-gap)',
borderRadius: 24, borderRadius: 24,
overflow: 'hidden', overflow: 'hidden',
position: 'relative' position: 'relative'
@@ -602,8 +628,10 @@ function TeamCarousel() {
{/* Right Column: Carousel Stage */} {/* Right Column: Carousel Stage */}
<div className="team-stage" style={{ flex: 1, minWidth: 0, position: 'relative' }}> <div className="team-stage" style={{ flex: 1, minWidth: 0, position: 'relative' }}>
{/* Main viewport */} {/* Main viewport */}
<div style={{ position: 'relative', height: 510, padding: '20px 10px', margin: '-20px -10px', overflow: 'hidden' }}> <div className="team-viewport" style={{ position: 'relative', height: 510, padding: '20px 10px', margin: '-20px -10px', overflow: 'hidden' }}>
<div <div
ref={trackRef}
className="team-track"
onTouchStart={handleTouchStart} onTouchStart={handleTouchStart}
onTouchMove={handleTouchMove} onTouchMove={handleTouchMove}
onTouchEnd={handleTouchEnd} onTouchEnd={handleTouchEnd}
@@ -612,7 +640,7 @@ function TeamCarousel() {
gap: CARD_GAP, gap: CARD_GAP,
alignItems: 'center', alignItems: 'center',
height: '100%', height: '100%',
transform: `translateX(${-active * STEP}px)`, transform: `translateX(${-active * step}px)`,
transition: 'transform 0.7s cubic-bezier(0.2, 0.8, 0.2, 1)', transition: 'transform 0.7s cubic-bezier(0.2, 0.8, 0.2, 1)',
}} }}
> >
@@ -647,7 +675,7 @@ function TeamCarousel() {
}} }}
> >
{/* Top Left Number Tag */} {/* Top Left Number Tag */}
<div style={{ <div className="team-num-tag" style={{
position: 'absolute', position: 'absolute',
top: 20, top: 20,
left: 20, left: 20,
@@ -850,7 +878,7 @@ function TeamCarousel() {
)} )}
{/* Bottom controls: arrows and page counter */} {/* Bottom controls: arrows and page counter */}
<div style={{ display: 'flex', alignItems: 'center', gap: 16, marginTop: 40, ...enter(4) }}> <div className="team-controls" style={{ display: 'flex', alignItems: 'center', gap: 16, marginTop: 40, ...enter(4) }}>
{/* Prev button */} {/* Prev button */}
<button <button
onClick={() => go(-1)} onClick={() => go(-1)}
@@ -972,6 +1000,28 @@ function TeamCarousel() {
to { transform: translateX(120%); } to { transform: translateX(120%); }
} }
/* ── Premium active-card finish: a layered depth shadow, a faint gold
rim, and a soft light spilling from the top edge. ── */
.team-card.is-active {
box-shadow:
0 34px 70px -20px rgba(0,0,0,0.9),
0 0 0 1px rgba(244,190,40,0.35),
0 0 46px -6px rgba(244,190,40,0.28) !important;
}
.team-card.is-active::after {
content: '';
position: absolute;
inset: 0;
z-index: 3;
pointer-events: none;
border-radius: 18px;
background: radial-gradient(130% 55% at 50% -8%, rgba(244,190,40,0.16) 0%, transparent 55%);
}
/* Gold accent line under the active thumbnail number tag reads richer */
.team-card.is-active .team-num-tag {
box-shadow: 0 6px 16px -4px rgba(244,190,40,0.5);
}
@media (max-width: 1024px) { @media (max-width: 1024px) {
.team-wrap { .team-wrap {
padding: 0 40px !important; padding: 0 40px !important;
@@ -982,12 +1032,21 @@ function TeamCarousel() {
} }
} }
/* ────────────────────────────────────────────────────────────
MOBILE / TABLET — heading stacks above a centered card
carousel. The slide distance is measured in JS, so overriding
the card width here (with !important, to beat the inline style)
automatically keeps the active card centered.
──────────────────────────────────────────────────────────── */
@media (max-width: 900px) { @media (max-width: 900px) {
.team-section {
padding: 84px 0 92px !important;
}
.team-wrap { .team-wrap {
flex-direction: column !important; flex-direction: column !important;
gap: 48px !important; gap: 44px !important;
align-items: stretch !important; align-items: stretch !important;
padding: 0 32px !important; padding: 0 28px !important;
} }
.team-head { .team-head {
width: 100% !important; width: 100% !important;
@@ -996,10 +1055,10 @@ function TeamCarousel() {
} }
.team-purpose-badge { .team-purpose-badge {
align-self: center !important; align-self: center !important;
max-width: 320px; max-width: 340px;
} }
.team-top-dots { .team-top-dots {
display: none !important; /* Hide top-right dots on mobile, they overflow */ display: none !important; /* moved to the bottom counter row on mobile */
} }
.team-stage { .team-stage {
width: 100% !important; width: 100% !important;
@@ -1007,16 +1066,52 @@ function TeamCarousel() {
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
} }
/* Centre the card row in the stage with a symmetric peek of the
neighbouring card on both sides. */
.team-viewport {
height: 452px !important;
width: 100% !important;
padding: 20px calc((100% - min(300px, 80vw)) / 2) !important;
margin: -20px 0 !important;
}
.team-track {
gap: 18px !important;
}
.team-card {
width: min(300px, 80vw) !important;
height: 412px !important;
}
.team-card.is-active {
height: 452px !important;
}
.team-next-overlay { .team-next-overlay {
right: 0px !important; display: none !important; /* redundant with the bottom Next control */
}
/* Bottom controls: centre them under the carousel */
.team-controls {
justify-content: center !important;
margin-top: 28px !important;
} }
} }
@media (max-width: 480px) { @media (max-width: 480px) {
.team-wrap { .team-section {
padding: 0 20px !important; padding: 64px 0 72px !important;
} }
.team-next-overlay { .team-wrap {
display: none !important; /* Hide overlay button on very small screens */ padding: 0 16px !important;
gap: 36px !important;
}
.team-viewport {
height: 424px !important;
padding: 20px calc((100% - min(272px, 82vw)) / 2) !important;
}
.team-card {
width: min(272px, 82vw) !important;
height: 388px !important;
}
.team-card.is-active {
height: 424px !important;
} }
} }
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {

View File

@@ -101,7 +101,7 @@ export default function BlogMainPage() {
{/* ── HERO ── */} {/* ── HERO ── */}
<section style={{ <section style={{
padding: '120px 8% 90px', background: 'radial-gradient(ellipse 120% 90% at 50% 0%, #2c2350 0%, #211c3e 38%, #181429 100%)', padding: '120px 8% 90px', background: 'radial-gradient(ellipse 120% 90% at 50% 0%, #2c2350 0%, #211c3e 38%, #181429 100%)',
margin: '20px', borderRadius: '32px', margin: 'var(--hero-top) var(--sec-gutter) var(--sec-gap) var(--sec-gutter)', borderRadius: '32px',
position: 'relative', overflow: 'hidden', position: 'relative', overflow: 'hidden',
}}> }}>
{/* Background photo */} {/* Background photo */}
@@ -296,7 +296,7 @@ export default function BlogMainPage() {
</section> </section>
{/* ── NEWSLETTER CTA ── */} {/* ── NEWSLETTER CTA ── */}
<section style={{ padding: 0, background: '#07070d', margin: '0 20px 20px', borderRadius: 28, overflow: 'hidden', position: 'relative' }}> <section style={{ padding: 0, background: '#07070d', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 28, overflow: 'hidden', position: 'relative' }}>
<div style={{ position: 'absolute', top: '20%', left: '10%', width: 420, height: 420, borderRadius: '50%', background: 'radial-gradient(circle,rgba(244,190,40,0.1) 0%,transparent 70%)', pointerEvents: 'none' }} /> <div style={{ position: 'absolute', top: '20%', left: '10%', width: 420, height: 420, borderRadius: '50%', background: 'radial-gradient(circle,rgba(244,190,40,0.1) 0%,transparent 70%)', pointerEvents: 'none' }} />
<div style={{ position: 'absolute', bottom: '-10%', right: '5%', width: 380, height: 380, borderRadius: '50%', background: 'radial-gradient(circle,rgba(167,139,250,0.08) 0%,transparent 70%)', pointerEvents: 'none' }} /> <div style={{ position: 'absolute', bottom: '-10%', right: '5%', width: 380, height: 380, borderRadius: '50%', background: 'radial-gradient(circle,rgba(167,139,250,0.08) 0%,transparent 70%)', pointerEvents: 'none' }} />
<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: '56px 56px', pointerEvents: 'none' }} /> <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: '56px 56px', pointerEvents: 'none' }} />

View File

@@ -43,7 +43,7 @@ export default function BlogSinglePage() {
{/* Hero */} {/* Hero */}
<section style={{ <section style={{
padding: '140px 8% 100px', background: 'radial-gradient(ellipse 120% 90% at 50% 0%, #2c2350 0%, #211c3e 38%, #181429 100%)', padding: '140px 8% 100px', background: 'radial-gradient(ellipse 120% 90% at 50% 0%, #2c2350 0%, #211c3e 38%, #181429 100%)',
margin: '20px', borderRadius: '32px', margin: 'var(--hero-top) var(--sec-gutter) var(--sec-gap) var(--sec-gutter)', borderRadius: '32px',
position: 'relative', overflow: 'hidden', position: 'relative', overflow: 'hidden',
}}> }}>
{/* Background photo */} {/* Background photo */}
@@ -78,7 +78,7 @@ export default function BlogSinglePage() {
</section> </section>
{/* Article body */} {/* Article body */}
<section style={{ padding: '80px 8%', background: '#fff', margin: '0 20px 20px', borderRadius: 24 }}> <section style={{ padding: '80px 8%', background: '#fff', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24 }}>
<div style={{ maxWidth: 740, margin: '0 auto' }}> <div style={{ maxWidth: 740, margin: '0 auto' }}>
{ARTICLE.sections.map((s, i) => ( {ARTICLE.sections.map((s, i) => (
<div key={i} style={{ marginBottom: 56 }}> <div key={i} style={{ marginBottom: 56 }}>
@@ -109,7 +109,7 @@ export default function BlogSinglePage() {
</section> </section>
{/* CTA */} {/* CTA */}
<section style={{ padding: '80px 8%', background: '#07070d', margin: '0 20px 20px', borderRadius: 24, display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 32 }}> <section style={{ padding: '80px 8%', background: '#07070d', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24, display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 32 }}>
<div> <div>
<h2 style={{ fontSize: 'clamp(28px, 3.5vw, 52px)', fontWeight: 800, letterSpacing: '-0.04em', color: '#fff', margin: '0 0 12px', fontFamily: 'Sora, sans-serif' }}> <h2 style={{ fontSize: 'clamp(28px, 3.5vw, 52px)', fontWeight: 800, letterSpacing: '-0.04em', color: '#fff', margin: '0 0 12px', fontFamily: 'Sora, sans-serif' }}>
Ready to see your store&apos;s data? Ready to see your store&apos;s data?
@@ -122,7 +122,7 @@ export default function BlogSinglePage() {
</section> </section>
{/* Related articles */} {/* Related articles */}
<section style={{ padding: '80px 8%', background: '#fff', margin: '0 20px 20px', borderRadius: 24 }}> <section style={{ padding: '80px 8%', background: '#fff', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24 }}>
<div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.2em', textTransform: 'uppercase', color: '#f4be28', fontFamily: 'Sora, sans-serif', marginBottom: 32 }}>More from Market Insights</div> <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.2em', textTransform: 'uppercase', color: '#f4be28', fontFamily: 'Sora, sans-serif', marginBottom: 32 }}>More from Market Insights</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit,minmax(240px,1fr))', gap: 16 }}> <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit,minmax(240px,1fr))', gap: 16 }}>
{ARTICLE.relatedArticles.map((a) => ( {ARTICLE.relatedArticles.map((a) => (

View File

@@ -15,7 +15,7 @@ export default function ContactsPage() {
{/* ── HERO ── */} {/* ── HERO ── */}
<section style={{ <section style={{
padding: '120px 8% 100px', background: 'radial-gradient(ellipse 120% 90% at 78% 0%, #2e2350 0%, #221b3e 38%, #191529 100%)', padding: '120px 8% 100px', background: 'radial-gradient(ellipse 120% 90% at 78% 0%, #2e2350 0%, #221b3e 38%, #191529 100%)',
margin: '20px', borderRadius: '32px', margin: 'var(--hero-top) var(--sec-gutter) var(--sec-gap) var(--sec-gutter)', borderRadius: '32px',
position: 'relative', overflow: 'hidden', position: 'relative', overflow: 'hidden',
display: 'flex', alignItems: 'center', display: 'flex', alignItems: 'center',
}}> }}>

View File

@@ -51,7 +51,7 @@ export default function FAQPage() {
{/* Hero */} {/* Hero */}
<section style={{ <section style={{
padding: '140px 8% 100px', background: 'radial-gradient(ellipse 120% 90% at 50% 0%, #2c2350 0%, #211c3e 38%, #181429 100%)', padding: '140px 8% 100px', background: 'radial-gradient(ellipse 120% 90% at 50% 0%, #2c2350 0%, #211c3e 38%, #181429 100%)',
margin: '20px', borderRadius: '32px', margin: 'var(--hero-top) var(--sec-gutter) var(--sec-gap) var(--sec-gutter)', borderRadius: '32px',
position: 'relative', overflow: 'hidden', position: 'relative', overflow: 'hidden',
display: 'flex', alignItems: 'center', display: 'flex', alignItems: 'center',
}}> }}>
@@ -81,7 +81,7 @@ export default function FAQPage() {
{/* FAQ sections */} {/* FAQ sections */}
{FAQS.map((section) => ( {FAQS.map((section) => (
<section key={section.category} style={{ padding: '80px 8%', background: '#fff', margin: '0 20px 20px', borderRadius: 24 }}> <section key={section.category} style={{ padding: '80px 8%', background: '#fff', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24 }}>
{/* Category header */} {/* Category header */}
<div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 40 }}> <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 40 }}>
<div style={{ width: 10, height: 10, borderRadius: '50%', background: section.color, boxShadow: `0 0 14px ${section.color}` }} /> <div style={{ width: 10, height: 10, borderRadius: '50%', background: section.color, boxShadow: `0 0 14px ${section.color}` }} />
@@ -133,7 +133,7 @@ export default function FAQPage() {
))} ))}
{/* CTA */} {/* CTA */}
<section style={{ padding: '80px 8%', background: '#f4be28', margin: '0 20px 20px', borderRadius: 24, textAlign: 'center' }}> <section style={{ padding: '80px 8%', background: '#f4be28', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24, textAlign: 'center' }}>
<h2 style={{ fontSize: 'clamp(28px, 4vw, 56px)', fontWeight: 800, letterSpacing: '-0.04em', color: '#111', margin: '0 0 16px', fontFamily: 'Sora, sans-serif' }}>Still have questions?</h2> <h2 style={{ fontSize: 'clamp(28px, 4vw, 56px)', fontWeight: 800, letterSpacing: '-0.04em', color: '#111', margin: '0 0 16px', fontFamily: 'Sora, sans-serif' }}>Still have questions?</h2>
<p style={{ fontSize: 16, color: 'rgba(0,0,0,0.55)', fontFamily: 'Sora, sans-serif', margin: '0 0 36px' }}>Our team is happy to help get in touch and we&apos;ll respond within one business day.</p> <p style={{ fontSize: 16, color: 'rgba(0,0,0,0.55)', fontFamily: 'Sora, sans-serif', margin: '0 0 36px' }}>Our team is happy to help get in touch and we&apos;ll respond within one business day.</p>
<Link href="/contacts" style={{ display: 'inline-flex', alignItems: 'center', gap: 10, padding: '16px 40px', background: '#111', color: '#f4be28', fontSize: 15, fontWeight: 800, borderRadius: 100, textDecoration: 'none', fontFamily: 'Sora, sans-serif' }}> <Link href="/contacts" style={{ display: 'inline-flex', alignItems: 'center', gap: 10, padding: '16px 40px', background: '#111', color: '#f4be28', fontSize: 15, fontWeight: 800, borderRadius: 100, textDecoration: 'none', fontFamily: 'Sora, sans-serif' }}>

View File

@@ -134,7 +134,7 @@ export default function ForBusinessPage() {
minHeight: '100vh', background: 'radial-gradient(ellipse 120% 90% at 30% 0%, #2c2350 0%, #211c3e 38%, #181429 100%)', minHeight: '100vh', background: 'radial-gradient(ellipse 120% 90% at 30% 0%, #2c2350 0%, #211c3e 38%, #181429 100%)',
display: 'flex', alignItems: 'center', display: 'flex', alignItems: 'center',
padding: '120px 8% 100px', position: 'relative', overflow: 'hidden', padding: '120px 8% 100px', position: 'relative', overflow: 'hidden',
margin: '20px', borderRadius: '32px', margin: 'var(--hero-top) var(--sec-gutter) var(--sec-gap) var(--sec-gutter)', borderRadius: '32px',
}}> }}>
{/* Background photo */} {/* Background photo */}
<Image src="/assets/images/stock/use-cases.jpg" alt="" fill priority style={{ objectFit: 'cover', opacity: 0.9 }} /> <Image src="/assets/images/stock/use-cases.jpg" alt="" fill priority style={{ objectFit: 'cover', opacity: 0.9 }} />
@@ -199,7 +199,7 @@ export default function ForBusinessPage() {
</section> </section>
{/* ── CHALLENGE ── */} {/* ── CHALLENGE ── */}
<section style={{ padding: '140px 8%', background: '#fff', margin: '0 20px 20px', borderRadius: 24 }}> <section style={{ padding: '140px 8%', background: '#fff', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24 }}>
<RevealBlock> <RevealBlock>
<div style={{ maxWidth: 200, height: 2, background: '#f4be28', marginBottom: 48 }} /> <div style={{ maxWidth: 200, height: 2, background: '#f4be28', marginBottom: 48 }} />
</RevealBlock> </RevealBlock>
@@ -288,9 +288,9 @@ export default function ForBusinessPage() {
<ProductsScrollSection /> <ProductsScrollSection />
{/* ── CAPABILITIES ── */} {/* ── CAPABILITIES ── */}
<section style={{ padding: '140px 8%', background: '#fff', margin: '0 20px 20px', borderRadius: 24 }}> <section className="uc-cap-section" style={{ padding: '140px 8%', background: '#fff', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24 }}>
<RevealBlock> <RevealBlock>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', marginBottom: 80, flexWrap: 'wrap', gap: 24 }}> <div className="uc-cap-header" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', marginBottom: 80, flexWrap: 'wrap', gap: 24 }}>
<div> <div>
<SectionEyebrow variant="number" index="01" style={{ marginBottom: 16 }}>The AI Agents</SectionEyebrow> <SectionEyebrow variant="number" index="01" style={{ marginBottom: 16 }}>The AI Agents</SectionEyebrow>
<h2 style={{ fontSize: 'clamp(36px, 5vw, 72px)', fontWeight: 800, letterSpacing: '-0.04em', lineHeight: 0.95, color: '#0a0a0f', margin: 0, fontFamily: 'Sora, sans-serif' }}> <h2 style={{ fontSize: 'clamp(36px, 5vw, 72px)', fontWeight: 800, letterSpacing: '-0.04em', lineHeight: 0.95, color: '#0a0a0f', margin: 0, fontFamily: 'Sora, sans-serif' }}>
@@ -338,7 +338,7 @@ export default function ForBusinessPage() {
<p style={{ fontSize: 14.5, lineHeight: 1.7, color: 'rgba(255,255,255,0.72)', margin: '0 0 26px', fontFamily: 'Sora, sans-serif' }}>{cap.desc}</p> <p style={{ fontSize: 14.5, lineHeight: 1.7, color: 'rgba(255,255,255,0.72)', margin: '0 0 26px', fontFamily: 'Sora, sans-serif' }}>{cap.desc}</p>
{/* Metric chips with icon badges */} {/* Metric chips with icon badges */}
<div style={{ display: 'flex', flexWrap: 'nowrap', gap: 12 }}> <div className="uc-cap-metrics" style={{ display: 'flex', flexWrap: 'nowrap', gap: 12 }}>
{cap.metrics.map((m, j) => ( {cap.metrics.map((m, j) => (
<div key={j} style={{ flex: '1 1 0', minWidth: 0, display: 'flex', alignItems: 'center', gap: 11, padding: '12px 14px', borderRadius: 14, background: 'rgba(0,0,0,0.22)', border: `1px solid ${cap.accent}26` }}> <div key={j} style={{ flex: '1 1 0', minWidth: 0, display: 'flex', alignItems: 'center', gap: 11, padding: '12px 14px', borderRadius: 14, background: 'rgba(0,0,0,0.22)', border: `1px solid ${cap.accent}26` }}>
<span style={{ flexShrink: 0, width: 34, height: 34, borderRadius: '50%', background: `${cap.accent}30`, display: 'flex', alignItems: 'center', justifyContent: 'center', color: cap.accent }}> <span style={{ flexShrink: 0, width: 34, height: 34, borderRadius: '50%', background: `${cap.accent}30`, display: 'flex', alignItems: 'center', justifyContent: 'center', color: cap.accent }}>
@@ -359,7 +359,7 @@ export default function ForBusinessPage() {
</section> </section>
{/* ── HOW IT WORKS ── */} {/* ── HOW IT WORKS ── */}
<section style={{ padding: '140px 8%', background: '#07070d', margin: '0 20px 20px', borderRadius: 24, overflow: 'hidden', position: 'relative' }}> <section style={{ padding: '140px 8%', background: '#07070d', margin: '0 var(--sec-gutter) var(--sec-gap)', 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' }} /> <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> <RevealBlock>
<SectionEyebrow variant="dot" style={{ marginBottom: 20, position: 'relative' }}>How It Works</SectionEyebrow> <SectionEyebrow variant="dot" style={{ marginBottom: 20, position: 'relative' }}>How It Works</SectionEyebrow>
@@ -409,7 +409,7 @@ export default function ForBusinessPage() {
</section> </section>
{/* ── PROXIMITY MARKETING ── */} {/* ── PROXIMITY MARKETING ── */}
<section style={{ padding: '120px 8%', background: '#ffffff', margin: '0 20px 20px', borderRadius: 24, overflow: 'hidden', position: 'relative' }}> <section style={{ padding: '120px 8%', background: '#ffffff', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24, overflow: 'hidden', position: 'relative' }}>
<div style={{ position: 'absolute', inset: 0, backgroundImage: 'linear-gradient(rgba(23,21,18,0.035) 1px,transparent 1px),linear-gradient(90deg,rgba(23,21,18,0.035) 1px,transparent 1px)', backgroundSize: '56px 56px', pointerEvents: 'none' }} /> <div style={{ position: 'absolute', inset: 0, backgroundImage: 'linear-gradient(rgba(23,21,18,0.035) 1px,transparent 1px),linear-gradient(90deg,rgba(23,21,18,0.035) 1px,transparent 1px)', backgroundSize: '56px 56px', pointerEvents: 'none' }} />
<RevealBlock> <RevealBlock>
<div className="uc-proximity-grid" style={{ display: 'grid', gridTemplateColumns: '0.9fr 1.1fr', gap: '5vw', alignItems: 'center', position: 'relative' }}> <div className="uc-proximity-grid" style={{ display: 'grid', gridTemplateColumns: '0.9fr 1.1fr', gap: '5vw', alignItems: 'center', position: 'relative' }}>
@@ -542,7 +542,7 @@ export default function ForBusinessPage() {
</section> </section>
{/* ── OUTCOMES ── */} {/* ── OUTCOMES ── */}
<section ref={statsRef} style={{ padding: '140px 8%', background: '#fff', margin: '0 20px 20px', borderRadius: 24 }}> <section ref={statsRef} style={{ padding: '140px 8%', background: '#fff', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24 }}>
<RevealBlock> <RevealBlock>
<SectionEyebrow variant="line" style={{ marginBottom: 20 }}>Outcomes</SectionEyebrow> <SectionEyebrow variant="line" style={{ marginBottom: 20 }}>Outcomes</SectionEyebrow>
<h2 style={{ fontSize: 'clamp(36px, 5vw, 68px)', fontWeight: 800, letterSpacing: '-0.04em', lineHeight: 0.95, color: '#0a0a0f', margin: '0 0 80px', fontFamily: 'Sora, sans-serif' }}> <h2 style={{ fontSize: 'clamp(36px, 5vw, 68px)', fontWeight: 800, letterSpacing: '-0.04em', lineHeight: 0.95, color: '#0a0a0f', margin: '0 0 80px', fontFamily: 'Sora, sans-serif' }}>
@@ -566,7 +566,7 @@ export default function ForBusinessPage() {
</section> </section>
{/* ── WHO IT'S FOR ── */} {/* ── WHO IT'S FOR ── */}
<section style={{ padding: '140px 8%', background: '#1a1a24', margin: '0 20px 20px', borderRadius: 24, position: 'relative', overflow: 'hidden' }}> <section style={{ padding: '140px 8%', background: '#1a1a24', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24, position: 'relative', overflow: 'hidden' }}>
{/* Background photo */} {/* Background photo */}
<Image src="/assets/images/stock/physical retail.png" alt="" fill style={{ objectFit: 'cover', opacity: 0.72, filter: 'blur(7px)', transform: 'scale(1.06)' }} /> <Image src="/assets/images/stock/physical retail.png" alt="" fill style={{ objectFit: 'cover', opacity: 0.72, filter: 'blur(7px)', transform: 'scale(1.06)' }} />
{/* Minimal black vignette — keeps the center bright, softly shades only the edges */} {/* Minimal black vignette — keeps the center bright, softly shades only the edges */}
@@ -608,7 +608,7 @@ export default function ForBusinessPage() {
</section> </section>
{/* ── FINAL CTA ── */} {/* ── FINAL CTA ── */}
<section style={{ padding: '160px 8%', background: '#f4be28', margin: '0 20px 20px', borderRadius: 24, textAlign: 'center', position: 'relative', overflow: 'hidden' }}> <section style={{ padding: '160px 8%', background: '#f4be28', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24, textAlign: 'center', position: 'relative', overflow: 'hidden' }}>
<div style={{ position: 'absolute', top: '-20%', left: '50%', transform: 'translateX(-50%)', width: '120%', height: '140%', background: 'radial-gradient(ellipse,rgba(255,255,255,0.15) 0%,transparent 60%)', pointerEvents: 'none' }} /> <div style={{ position: 'absolute', top: '-20%', left: '50%', transform: 'translateX(-50%)', width: '120%', height: '140%', background: 'radial-gradient(ellipse,rgba(255,255,255,0.15) 0%,transparent 60%)', pointerEvents: 'none' }} />
<RevealBlock> <RevealBlock>
<h2 style={{ fontSize: 'clamp(44px, 7vw, 100px)', fontWeight: 800, letterSpacing: '-0.05em', lineHeight: 0.92, color: '#111', margin: '0 0 24px', fontFamily: 'Sora, sans-serif', position: 'relative', zIndex: 2 }}> <h2 style={{ fontSize: 'clamp(44px, 7vw, 100px)', fontWeight: 800, letterSpacing: '-0.05em', lineHeight: 0.92, color: '#111', margin: '0 0 24px', fontFamily: 'Sora, sans-serif', position: 'relative', zIndex: 2 }}>
@@ -653,9 +653,10 @@ export default function ForBusinessPage() {
.uc-outcomes-grid { grid-template-columns: repeat(2,1fr) !important; } .uc-outcomes-grid { grid-template-columns: repeat(2,1fr) !important; }
.uc-outcomes-grid > div > div { border-radius: 16px !important; } .uc-outcomes-grid > div > div { border-radius: 16px !important; }
.uc-who-grid { grid-template-columns: repeat(2,1fr) !important; } .uc-who-grid { grid-template-columns: repeat(2,1fr) !important; }
/* AI Agents — single column; keep the artwork on the right for tablets */
.uc-cap-grid { grid-template-columns: 1fr !important; } .uc-cap-grid { grid-template-columns: 1fr !important; }
.uc-cap-content { width: 62% !important; } .uc-cap-content { width: 60% !important; }
.uc-cap-art { width: 40% !important; } .uc-cap-art { width: 42% !important; }
.uc-pillar-grid { grid-template-columns: 1fr !important; } .uc-pillar-grid { grid-template-columns: 1fr !important; }
.uc-proximity-grid { grid-template-columns: 1fr !important; gap: 40px !important; } .uc-proximity-grid { grid-template-columns: 1fr !important; gap: 40px !important; }
.uc-prox-stats { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; } .uc-prox-stats { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
@@ -663,11 +664,24 @@ export default function ForBusinessPage() {
.uc-timeline-row > div:first-child { width: 44px !important; height: 44px !important; } .uc-timeline-row > div:first-child { width: 44px !important; height: 44px !important; }
.uc-timeline-line { left: 21px !important; } .uc-timeline-line { left: 21px !important; }
} }
/* AI Agents phone redesign: drop the artwork, let copy use the full
width, and give each card a compact, self-sizing height */
@media (max-width: 640px) {
.uc-cap-section { padding: 96px 6% !important; }
.uc-cap-header { margin-bottom: 44px !important; }
.uc-cap-grid { gap: 16px !important; }
.uc-cap-card { min-height: 0 !important; padding: 28px 24px !important; }
.uc-cap-content { width: 100% !important; }
.uc-cap-art { display: none !important; }
}
@media (max-width: 360px) {
/* Very narrow: stack the two metric chips instead of squeezing them */
.uc-cap-metrics { flex-direction: column !important; }
.uc-cap-metrics > div { width: 100% !important; }
}
@media (max-width: 520px) { @media (max-width: 520px) {
.uc-outcomes-grid { grid-template-columns: 1fr !important; } .uc-outcomes-grid { grid-template-columns: 1fr !important; }
.uc-who-grid { grid-template-columns: 1fr !important; } .uc-who-grid { grid-template-columns: 1fr !important; }
.uc-cap-content { width: 100% !important; }
.uc-cap-art { display: none !important; }
} }
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
.uc-radar-ring { animation: none !important; opacity: 0.4 !important; } .uc-radar-ring { animation: none !important; opacity: 0.4 !important; }

View File

@@ -8,6 +8,25 @@
--loyaly-carbon: #171512; --loyaly-carbon: #171512;
--loyaly-warm-text: #4f463a; --loyaly-warm-text: #4f463a;
--loyaly-copper: #bc7122; --loyaly-copper: #bc7122;
/* Section gutters. --sec-gutter = left/right side margin (+ width calc);
--sec-gap = vertical gap between stacked sections; --hdr-gutter = header side padding.
On phones the side gutter goes to 0 (full-bleed sections) while the vertical
gap is preserved. Laptop/desktop/tablet keep the original values. */
--sec-gutter: 20px;
--sec-gap: 20px;
--hero-top: 20px;
--hdr-gutter: 48px;
}
/* Phones only — sections span the full width (no left/right margin),
and hero sections sit flush to the top (top margin 0). */
@media (max-width: 600px) {
:root {
--sec-gutter: 0px;
--sec-gap: 12px;
--hero-top: 0px;
--hdr-gutter: 20px;
}
} }
/* Legacy styles are loaded dynamically in layout.tsx. This file is kept minimal. */ /* Legacy styles are loaded dynamically in layout.tsx. This file is kept minimal. */

View File

@@ -98,7 +98,7 @@ export default function MeetTheCrewPage() {
minHeight: '100vh', background: 'radial-gradient(ellipse 120% 90% at 22% 0%, #3a2b5e 0%, #251c40 38%, #1a1530 100%)', minHeight: '100vh', background: 'radial-gradient(ellipse 120% 90% at 22% 0%, #3a2b5e 0%, #251c40 38%, #1a1530 100%)',
display: 'flex', alignItems: 'center', display: 'flex', alignItems: 'center',
padding: '120px 8% 80px', padding: '120px 8% 80px',
margin: '20px', borderRadius: '32px', margin: 'var(--hero-top) var(--sec-gutter) var(--sec-gap) var(--sec-gutter)', borderRadius: '32px',
position: 'relative', overflow: 'hidden', position: 'relative', overflow: 'hidden',
}}> }}>
{/* Background photo */} {/* Background photo */}
@@ -127,7 +127,7 @@ export default function MeetTheCrewPage() {
</section> </section>
{/* ── VALUES ── */} {/* ── VALUES ── */}
<section style={{ padding: '140px 8%', background: '#fff', margin: '0 20px 20px', borderRadius: 24 }}> <section style={{ padding: '140px 8%', background: '#fff', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24 }}>
<Reveal> <Reveal>
<SectionEyebrow variant="bar" style={{ marginBottom: 20 }}>How We Work</SectionEyebrow> <SectionEyebrow variant="bar" style={{ marginBottom: 20 }}>How We Work</SectionEyebrow>
<h2 style={{ fontSize: 'clamp(36px, 5vw, 72px)', fontWeight: 800, letterSpacing: '-0.04em', lineHeight: 0.95, color: '#0a0a0f', margin: '0 0 80px', fontFamily: 'Sora, sans-serif' }}> <h2 style={{ fontSize: 'clamp(36px, 5vw, 72px)', fontWeight: 800, letterSpacing: '-0.04em', lineHeight: 0.95, color: '#0a0a0f', margin: '0 0 80px', fontFamily: 'Sora, sans-serif' }}>
@@ -185,7 +185,7 @@ export default function MeetTheCrewPage() {
</section> </section>
{/* ── OUR PRODUCTS ── */} {/* ── OUR PRODUCTS ── */}
<section style={{ padding: '140px 5%', background: '#07070d', margin: '0 20px 20px', borderRadius: 24, overflow: 'hidden', position: 'relative' }}> <section style={{ padding: '140px 5%', background: '#07070d', margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24, overflow: 'hidden', position: 'relative' }}>
{/* Background photo confined to the hero band at the top so it isn't {/* Background photo confined to the hero band at the top so it isn't
stretched/zoomed across the tall product-stack section below */} stretched/zoomed across the tall product-stack section below */}
<div style={{ position: 'absolute', top: 0, left: 0, right: 0, height: 760, pointerEvents: 'none' }}> <div style={{ position: 'absolute', top: 0, left: 0, right: 0, height: 760, pointerEvents: 'none' }}>
@@ -210,20 +210,37 @@ export default function MeetTheCrewPage() {
<ScrollStack useWindowScroll disabled={isMobile} stackPosition="14%" scaleEndPosition="8%" itemDistance={160} itemScale={0} itemStackDistance={40} baseScale={1} hideBehind> <ScrollStack useWindowScroll disabled={isMobile} stackPosition="14%" scaleEndPosition="8%" itemDistance={160} itemScale={0} itemStackDistance={40} baseScale={1} hideBehind>
{PRODUCTS.map((p, i) => ( {PRODUCTS.map((p, i) => (
<ScrollStackItem key={i}> <ScrollStackItem key={i}>
<div style={{ <div
className="mtc-product-card"
style={{
position: 'relative', overflow: 'hidden', position: 'relative', overflow: 'hidden',
background: `radial-gradient(130% 80% at 100% 0%, ${p.color}22 0%, transparent 46%), linear-gradient(155deg, #16161f 0%, #0a0a10 100%)`, background: `radial-gradient(130% 80% at 100% 0%, ${p.color}1a 0%, transparent 46%), linear-gradient(155deg, #16161f 0%, #0a0a10 100%)`,
border: `1px solid ${p.color}4d`, border: `1px solid ${p.color}1c`,
boxShadow: `inset 0 1px 0 rgba(255,255,255,0.06)`, boxShadow: `inset 0 1px 0 rgba(255,255,255,0.06)`,
borderRadius: 28, padding: 'clamp(26px, 3vw, 48px)', borderRadius: 28, padding: 'clamp(26px, 3vw, 48px)',
minHeight: 'clamp(320px, 42vh, 440px)', height: '100%', boxSizing: 'border-box', minHeight: 'clamp(320px, 42vh, 440px)', height: '100%', boxSizing: 'border-box',
}}> ['--card-color' as string]: p.color,
}}
>
{/* Background photo */} {/* Background photo */}
<Image src={p.image} alt="" fill sizes="(max-width: 900px) 100vw, 1100px" style={{ objectFit: 'cover', opacity: 0.55 }} /> <Image src={p.image} alt="" fill sizes="(max-width: 900px) 100vw, 1100px" style={{ objectFit: 'cover', opacity: 0.55 }} />
{/* Left-anchored scrim — copy sits on near-solid dark, photo breathes to the right */} {/* Left-anchored scrim — copy sits on near-solid dark, photo breathes to the right */}
<div aria-hidden style={{ position: 'absolute', inset: 0, background: `linear-gradient(100deg, rgba(8,8,12,0.94) 0%, rgba(8,8,12,0.82) 34%, rgba(8,8,12,0.5) 66%, rgba(8,8,12,0.32) 100%)`, pointerEvents: 'none' }} /> <div aria-hidden style={{ position: 'absolute', inset: 0, background: `linear-gradient(100deg, rgba(8,8,12,0.94) 0%, rgba(8,8,12,0.82) 34%, rgba(8,8,12,0.5) 66%, rgba(8,8,12,0.32) 100%)`, pointerEvents: 'none' }} />
{/* Ambient pulsing glow */}
<div className="mtc-card-glow" style={{
position: 'absolute',
top: 0, right: 0,
width: '60%', height: '60%',
background: `radial-gradient(circle, ${p.color}24 0%, transparent 70%)`,
pointerEvents: 'none',
zIndex: 1,
}} />
{/* Accent tint from the top-right + bottom vignette for depth */} {/* Accent tint from the top-right + bottom vignette for depth */}
<div aria-hidden style={{ position: 'absolute', inset: 0, background: `radial-gradient(120% 90% at 100% 0%, ${p.color}2e 0%, transparent 42%), linear-gradient(180deg, transparent 55%, rgba(6,6,10,0.7) 100%)`, pointerEvents: 'none' }} /> <div aria-hidden style={{ position: 'absolute', inset: 0, background: `radial-gradient(120% 90% at 100% 0%, ${p.color}2e 0%, transparent 42%), linear-gradient(180deg, transparent 55%, rgba(6,6,10,0.7) 100%)`, pointerEvents: 'none', zIndex: 1 }} />
{/* Border beam */}
<div className="mtc-border-beam-container" aria-hidden="true">
<div className="mtc-border-beam" style={{ ['--card-color' as string]: p.color } as React.CSSProperties} />
</div>
<div className="mtc-product-grid" style={{ position: 'relative', display: 'grid', gridTemplateColumns: '1.3fr 1fr', gap: 'clamp(32px, 4.5vw, 68px)', alignItems: 'center', height: '100%' }}> <div className="mtc-product-grid" style={{ position: 'relative', display: 'grid', gridTemplateColumns: '1.3fr 1fr', gap: 'clamp(32px, 4.5vw, 68px)', alignItems: 'center', height: '100%' }}>
@@ -289,7 +306,7 @@ export default function MeetTheCrewPage() {
{/* ── CULTURE CLOSE ── */} {/* ── CULTURE CLOSE ── */}
<section style={{ <section style={{
padding: '160px 8%', background: '#f4be28', padding: '160px 8%', background: '#f4be28',
margin: '0 20px 20px', borderRadius: 24, margin: '0 var(--sec-gutter) var(--sec-gap)', borderRadius: 24,
display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center', display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center',
position: 'relative', overflow: 'hidden', position: 'relative', overflow: 'hidden',
}}> }}>
@@ -315,8 +332,85 @@ export default function MeetTheCrewPage() {
.mtc-vc-shine { background: linear-gradient(115deg, transparent 32%, rgba(255,255,255,0.22) 48%, transparent 64%); transform: translateX(-130%); transition: transform 0.9s cubic-bezier(0.22,1,0.36,1); } .mtc-vc-shine { background: linear-gradient(115deg, transparent 32%, rgba(255,255,255,0.22) 48%, transparent 64%); transform: translateX(-130%); transition: transform 0.9s cubic-bezier(0.22,1,0.36,1); }
.mtc-value-card:hover { transform: translateY(-8px) scale(1.02); box-shadow: 0 34px 60px -22px var(--vc-glow); } .mtc-value-card:hover { transform: translateY(-8px) scale(1.02); box-shadow: 0 34px 60px -22px var(--vc-glow); }
.mtc-value-card:hover .mtc-vc-shine { transform: translateX(130%); } .mtc-value-card:hover .mtc-vc-shine { transform: translateX(130%); }
/* Premium Card Hover & Animation Styles */
.mtc-product-card {
transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}
.mtc-product-card:hover {
transform: translateY(-4px) scale(1.005);
box-shadow: 0 45px 95px -30px rgba(0, 0, 0, 0.9), inset 0 1px 0 rgba(255, 255, 255, 0.12);
}
.mtc-product-card:active {
transform: scale(0.995);
}
.mtc-card-glow {
opacity: 0.65;
mix-blend-mode: plus-lighter;
transition: transform 0.8s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.8s ease;
animation: mtcCardGlow 14s ease-in-out infinite alternate;
}
.mtc-product-card:hover .mtc-card-glow {
opacity: 1 !important;
transform: scale(1.2) translate(-5%, 5%);
}
@keyframes mtcCardGlow {
0% {
transform: translate(6%, -6%) scale(1);
}
50% {
transform: translate(-4%, 4%) scale(1.15);
}
100% {
transform: translate(4%, -2%) scale(0.95);
}
}
/* Premium Card Border Beam */
.mtc-border-beam-container {
position: absolute;
inset: 0;
border-radius: 28px;
padding: 1.5px;
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
overflow: hidden;
z-index: 10;
}
.mtc-border-beam {
position: absolute;
top: 50%;
left: 50%;
width: 250%;
height: 250%;
background: conic-gradient(from 0deg, transparent 35%, var(--card-color) 50%, transparent 65%);
transform: translate(-50%, -50%) rotate(0deg);
animation: mtcBorderRotate 9s linear infinite;
transform-origin: center;
opacity: 0.75;
transition: opacity 0.5s ease;
}
.mtc-product-card:hover .mtc-border-beam {
animation-duration: 5s;
opacity: 1;
}
@keyframes mtcBorderRotate {
0% {
transform: translate(-50%, -50%) rotate(0deg);
}
100% {
transform: translate(-50%, -50%) rotate(360deg);
}
}
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
.mtc-value-card, .mtc-vc-glow { animation: none !important; } .mtc-value-card, .mtc-vc-glow, .mtc-card-glow, .mtc-border-beam { animation: none !important; }
.mtc-border-beam { transform: translate(-50%, -50%) rotate(0deg) !important; }
} }
@media (max-width: 860px) { @media (max-width: 860px) {
.mtc-value-grid { grid-template-columns: 1fr !important; } .mtc-value-grid { grid-template-columns: 1fr !important; }

View File

@@ -9,16 +9,16 @@ const NAV = [
title: 'Product', title: 'Product',
links: [ links: [
{ label: 'For People', href: '/for_people' }, { label: 'For People', href: '/for_people' },
{ label: 'For Business', href: '/use_cases' }, { label: 'For Business', href: '/for_business' },
{ label: 'Meet the Agents', href: '/solutions_page' }, { label: 'Meet the Agents', href: '/meet_the_agents' },
], ],
}, },
{ {
title: 'Platform', title: 'Platform',
links: [ links: [
{ label: 'Behavision AI', href: '/use_cases' }, { label: 'Behavision AI', href: '/for_business' },
{ label: 'SpendSense AI', href: '/use_cases' }, { label: 'SpendSense AI', href: '/for_business' },
{ label: 'Dyscount AI', href: '/use_cases' }, { label: 'Dyscount AI', href: '/for_business' },
], ],
}, },
{ {
@@ -66,7 +66,7 @@ export default function Footer() {
color: '#ffffff', color: '#ffffff',
position: 'relative', position: 'relative',
overflow: 'hidden', overflow: 'hidden',
margin: '0 20px 20px', margin: '0 var(--sec-gutter) var(--sec-gap)',
borderRadius: '0 0 24px 24px', borderRadius: '0 0 24px 24px',
}}> }}>

View File

@@ -16,7 +16,7 @@ const DETAILS = [
}, },
{ {
label: 'Email us', label: 'Email us',
value: <a href="mailto:loyalydigital@gmail.com" style={{ color: '#fff', textDecoration: 'none', fontWeight: 600 }}>loyalydigital@gmail.com</a>, value: <a href="mailto:loyalydigital@gmail.com" className="git-email-link">loyalydigital@gmail.com</a>,
icon: ( icon: (
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
<rect x="2" y="4" width="20" height="16" rx="2" /><path d="m22 7-10 5L2 7" /> <rect x="2" y="4" width="20" height="16" rx="2" /><path d="m22 7-10 5L2 7" />
@@ -72,7 +72,7 @@ export default function GetInTouch() {
aria-label="Contact us" aria-label="Contact us"
style={{ style={{
position: 'relative', position: 'relative',
margin: '0 20px 0', margin: '0 var(--sec-gutter) 0',
borderRadius: '24px 24px 0 0', borderRadius: '24px 24px 0 0',
overflow: 'hidden', overflow: 'hidden',
background: '#07070d', background: '#07070d',
@@ -84,7 +84,7 @@ export default function GetInTouch() {
maxWidth: 1200, margin: '0 auto', maxWidth: 1200, margin: '0 auto',
padding: 'clamp(56px, 8vh, 100px) clamp(28px, 5vw, 72px)', padding: 'clamp(56px, 8vh, 100px) clamp(28px, 5vw, 72px)',
display: 'grid', display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(320px, 1fr))', gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 320px), 1fr))',
gap: 'clamp(40px, 5vw, 80px)', gap: 'clamp(40px, 5vw, 80px)',
alignItems: 'start', alignItems: 'start',
}}> }}>
@@ -117,20 +117,13 @@ export default function GetInTouch() {
{/* Detail cards */} {/* Detail cards */}
<div style={{ display: 'flex', flexDirection: 'column', gap: 14, marginBottom: 36 }}> <div style={{ display: 'flex', flexDirection: 'column', gap: 14, marginBottom: 36 }}>
{DETAILS.map((d) => ( {DETAILS.map((d) => (
<div key={d.label} style={{ <div key={d.label} className="git-detail">
display: 'flex', gap: 16, alignItems: 'flex-start', <div className="git-detail-icon">
padding: '18px 20px', borderRadius: 16, {d.icon}
background: 'rgba(255,255,255,0.03)', border: '1px solid rgba(255,255,255,0.07)', </div>
}}>
<div style={{
width: 40, height: 40, borderRadius: 11, flexShrink: 0,
display: 'flex', alignItems: 'center', justifyContent: 'center',
background: 'rgba(244,190,40,0.1)', border: '1px solid rgba(244,190,40,0.22)',
color: '#f4be28',
}}>{d.icon}</div>
<div> <div>
<div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.12em', textTransform: 'uppercase', color: 'rgba(255,255,255,0.4)', fontFamily: 'Sora, sans-serif', marginBottom: 6 }}>{d.label}</div> <div className="git-detail-label">{d.label}</div>
<div style={{ fontSize: 15, lineHeight: 1.6, color: 'rgba(255,255,255,0.7)', fontFamily: 'Sora, sans-serif' }}>{d.value}</div> <div className="git-detail-value">{d.value}</div>
</div> </div>
</div> </div>
))} ))}
@@ -147,16 +140,7 @@ export default function GetInTouch() {
</div> </div>
</div> </div>
{/* ── Right — form ── */} <div className="git-form-card">
<div style={{
background: 'rgba(255,255,255,0.03)',
border: '1px solid rgba(255,255,255,0.08)',
borderRadius: 24,
padding: 'clamp(28px, 3vw, 44px)',
backdropFilter: 'blur(20px)',
WebkitBackdropFilter: 'blur(20px)',
boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.05)',
}}>
{formState === 'success' ? ( {formState === 'success' ? (
<div role="status" aria-live="polite" style={{ textAlign: 'center', padding: '40px 0' }}> <div role="status" aria-live="polite" style={{ textAlign: 'center', padding: '40px 0' }}>
<div style={{ <div style={{
@@ -235,6 +219,95 @@ export default function GetInTouch() {
@keyframes gitspin { to { transform: rotate(360deg); } } @keyframes gitspin { to { transform: rotate(360deg); } }
.git-input::placeholder { color: rgba(255,255,255,0.3); } .git-input::placeholder { color: rgba(255,255,255,0.3); }
.git-input:focus { border-color: rgba(244,190,40,0.6) !important; box-shadow: 0 0 0 3px rgba(244,190,40,0.12) !important; } .git-input:focus { border-color: rgba(244,190,40,0.6) !important; box-shadow: 0 0 0 3px rgba(244,190,40,0.12) !important; }
.git-detail {
display: flex;
gap: 20px;
align-items: flex-start;
padding: 10px 0;
transition: transform 0.2s ease;
}
.git-detail-icon {
width: 42px;
height: 42px;
border-radius: 50%;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255,255,255,0.02);
border: 1px solid rgba(255,255,255,0.06);
color: rgba(255,255,255,0.5);
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
.git-detail:hover .git-detail-icon {
background: rgba(244,190,40,0.1);
border-color: rgba(244,190,40,0.3);
color: #f4be28;
transform: scale(1.05);
box-shadow: 0 0 15px rgba(244,190,40,0.1);
}
.git-detail-label {
font-size: 11px;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
color: rgba(255,255,255,0.4);
font-family: 'Sora', sans-serif;
margin-bottom: 6px;
transition: color 0.3s ease;
}
.git-detail:hover .git-detail-label {
color: #f4be28;
}
.git-detail-value {
font-size: 15px;
line-height: 1.6;
color: rgba(255,255,255,0.75);
font-family: 'Sora', sans-serif;
transition: color 0.3s ease;
}
.git-detail:hover .git-detail-value {
color: rgba(255,255,255,0.95);
}
.git-email-link {
color: #fff;
text-decoration: none;
font-weight: 600;
position: relative;
transition: color 0.3s ease;
}
.git-email-link::after {
content: '';
position: absolute;
width: 100%;
transform: scaleX(0);
height: 1px;
bottom: -2px;
left: 0;
background-color: #f4be28;
transform-origin: bottom right;
transition: transform 0.25s ease-out;
}
.git-email-link:hover {
color: #f4be28;
}
.git-email-link:hover::after {
transform: scaleX(1);
transform-origin: bottom left;
}
.git-form-card {
background: rgba(255,255,255,0.03);
border: 1px solid rgba(255,255,255,0.08);
border-radius: 24px;
padding: clamp(28px, 3vw, 44px);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: inset 0 1px 0 rgba(255,255,255,0.05);
}
.git-social { .git-social {
width: 38px; height: 38px; border-radius: 10px; width: 38px; height: 38px; border-radius: 10px;
display: flex; align-items: center; justify-content: center; display: flex; align-items: center; justify-content: center;
@@ -242,6 +315,17 @@ export default function GetInTouch() {
color: rgba(255,255,255,0.5); transition: all 0.2s ease; color: rgba(255,255,255,0.5); transition: all 0.2s ease;
} }
.git-social:hover { background: rgba(244,190,40,0.12); border-color: rgba(244,190,40,0.3); color: #f4be28; } .git-social:hover { background: rgba(244,190,40,0.12); border-color: rgba(244,190,40,0.3); color: #f4be28; }
@media (max-width: 768px) {
.git-form-card {
border: none;
background: transparent;
padding: 20px 0;
box-shadow: none;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
}
@media (max-width: 420px) { @media (max-width: 420px) {
.git-grid { grid-template-columns: 1fr !important; } .git-grid { grid-template-columns: 1fr !important; }
} }

View File

@@ -8,8 +8,8 @@ import Image from 'next/image';
const NAV_LINKS = [ const NAV_LINKS = [
{ label: 'Home', href: '/' }, { label: 'Home', href: '/' },
{ label: 'For People', href: '/for_people' }, { label: 'For People', href: '/for_people' },
{ label: 'For Business', href: '/use_cases' }, { label: 'For Business', href: '/for_business' },
{ label: 'Meet the Agents', href: '/solutions_page' }, { label: 'Meet the Agents', href: '/meet_the_agents' },
{ label: 'About us', href: '/about_us' }, { label: 'About us', href: '/about_us' },
{ label: 'Blogs', href: '/blog_main' }, { label: 'Blogs', href: '/blog_main' },
]; ];
@@ -232,7 +232,7 @@ export default function Header() {
className={transparentHeader ? 'header-transparent' : ''} className={transparentHeader ? 'header-transparent' : ''}
style={{ style={{
position: 'fixed', position: 'fixed',
top: isMobileViewport ? '14px' : 0, top: isMobileViewport ? '20px' : 0,
left: '20px', left: '20px',
right: '20px', right: '20px',
width: 'auto', width: 'auto',
@@ -247,18 +247,18 @@ export default function Header() {
transition: 'transform 0.35s cubic-bezier(0.4,0,0.2,1), background 0.3s ease, box-shadow 0.3s ease', transition: 'transform 0.35s cubic-bezier(0.4,0,0.2,1), background 0.3s ease, box-shadow 0.3s ease',
}} }}
> >
<div style={{ <div className="header-inner" style={{
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'space-between', justifyContent: 'space-between',
padding: '0 48px', padding: '0 var(--hdr-gutter)',
height: transparentHeader ? '150px' : '92px', height: transparentHeader ? '150px' : '92px',
width: '100%', width: '100%',
boxSizing: 'border-box', boxSizing: 'border-box',
transition: 'height 0.3s ease', transition: 'height 0.3s ease',
}}> }}>
{/* Logo */} {/* Logo */}
<div style={{ flexShrink: 0, flex: 1, minWidth: 120 }}> <div style={{ flexShrink: 0, flex: 1, minWidth: 120, display: 'flex', alignItems: 'center' }}>
<Link href="/" aria-label="Loyaly.AI home" style={{ display: 'inline-flex', alignItems: 'center', textDecoration: 'none' }}> <Link href="/" aria-label="Loyaly.AI home" style={{ display: 'inline-flex', alignItems: 'center', textDecoration: 'none' }}>
<Image <Image
src={transparentHeader ? '/assets/images/logo-dark.png' : '/assets/images/loyalyai.png'} src={transparentHeader ? '/assets/images/logo-dark.png' : '/assets/images/loyalyai.png'}
@@ -360,6 +360,8 @@ export default function Header() {
@media (max-width: 1023px) { @media (max-width: 1023px) {
.desktop-nav { display: none !important; } .desktop-nav { display: none !important; }
.menu-trigger { display: flex !important; } .menu-trigger { display: flex !important; }
.header-inner { height: 68px !important; }
.header-logo-img { height: 32px !important; }
} }
@media (min-width: 1024px) and (max-width: 1280px) { @media (min-width: 1024px) and (max-width: 1280px) {
.header-nav-pill { padding: 5px 6px !important; } .header-nav-pill { padding: 5px 6px !important; }

View File

@@ -9,7 +9,7 @@ export default function MapSection() {
return ( return (
<section style={{ <section style={{
margin: '0 20px 20px', margin: '0 var(--sec-gutter) var(--sec-gap)',
borderRadius: 24, borderRadius: 24,
overflow: 'hidden', overflow: 'hidden',
background: '#fff', background: '#fff',

View File

@@ -100,11 +100,14 @@ export default function EarnRewardsSection() {
}} /> }} />
{/* Safe area — reserves the notch strip above the app's top bar */} {/* Safe area — reserves the notch strip above the app's top bar */}
<div style={{ height: 32, flexShrink: 0, background: '#ffffff' }} /> <div style={{ height: 32, flexShrink: 0, background: '#ffffff' }} />
{/* The embed is a Flutter web app built for a real phone's logical {/* The embed is a responsive Flutter web app. We render it at a
width (390px). Rendering it at 390 and scaling to fit keeps the comfortable logical width (390px) and scale it down to fill the
UI proportioned as designed instead of cramped at ~280px. The screen exactly, so the UI stays proportioned as designed instead
iframe is overscanned ~16px past the right clip so Flutter's of cramped at ~260px. The iframe width is exactly the design
desktop-style list scrollbar falls outside the visible screen. */} width (no horizontal overscan) so the app lays out edge-to-edge
and stays centered — nothing on the right (e.g. the Profile tab)
gets clipped. Flutter's thin right-edge list scrollbar is hidden
by a slim mask strip rather than by cutting into the layout. */}
<div className="erm-phone-viewport" style={{ position: 'relative', flex: 1, minHeight: 0, overflow: 'hidden' }}> <div className="erm-phone-viewport" style={{ position: 'relative', flex: 1, minHeight: 0, overflow: 'hidden' }}>
<iframe <iframe
src="https://anbarasu22004.github.io/lytsup_view/" src="https://anbarasu22004.github.io/lytsup_view/"
@@ -118,6 +121,8 @@ export default function EarnRewardsSection() {
transformOrigin: 'top left', transformOrigin: 'top left',
}} }}
/> />
{/* Masks Flutter's canvas-painted scrollbar at the far right edge */}
<div className="erm-scrollbar-mask" aria-hidden />
</div> </div>
</div> </div>
<style>{` <style>{`
@@ -126,10 +131,15 @@ export default function EarnRewardsSection() {
/* --pm-scale = screen width (frame - 2*10px padding) ÷ 390px design width */ /* --pm-scale = screen width (frame - 2*10px padding) ÷ 390px design width */
.erm-phone-shell { --pm-scale: calc(280 / 390); } .erm-phone-shell { --pm-scale: calc(280 / 390); }
.erm-phone-iframe { .erm-phone-iframe {
width: calc(100% / var(--pm-scale) + 16px); width: calc(100% / var(--pm-scale));
height: calc(100% / var(--pm-scale)); height: calc(100% / var(--pm-scale));
transform: scale(var(--pm-scale)); transform: scale(var(--pm-scale));
} }
.erm-scrollbar-mask {
position: absolute; top: 0; right: 0; z-index: 2;
width: 7px; height: 100%; pointer-events: none;
background: linear-gradient(to right, rgba(255,255,255,0), #ffffff 75%);
}
@media (prefers-reduced-motion: reduce) { .erm-phone-shell { animation: none !important; } } @media (prefers-reduced-motion: reduce) { .erm-phone-shell { animation: none !important; } }
@media (max-width: 900px) { @media (max-width: 900px) {
.erm-phone-shell { width: 280px !important; --pm-scale: calc(260 / 390); } .erm-phone-shell { width: 280px !important; --pm-scale: calc(260 / 390); }

View File

@@ -10,22 +10,7 @@ if (typeof window !== 'undefined') gsap.registerPlugin(ScrollTrigger);
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect; const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
function useMagnetic() {
const ref = useRef<HTMLAnchorElement | null>(null);
useEffect(() => {
const el = ref.current;
if (!el) return;
const onMove = (e: MouseEvent) => {
const r = el.getBoundingClientRect();
el.style.transform = `translate(${((e.clientX - r.left) / r.width - 0.5) * 16}px,${((e.clientY - r.top) / r.height - 0.5) * 16}px) scale(1.04)`;
};
const onLeave = () => { el.style.transform = ''; };
el.addEventListener('mousemove', onMove);
el.addEventListener('mouseleave', onLeave);
return () => { el.removeEventListener('mousemove', onMove); el.removeEventListener('mouseleave', onLeave); };
}, []);
return ref;
}
const PROOF = [ const PROOF = [
{ val: '50K+', label: 'Active users', color: '#f4be28', icon: '👥', iconBg: '#fffbeb' }, { val: '50K+', label: 'Active users', color: '#f4be28', icon: '👥', iconBg: '#fffbeb' },
@@ -36,8 +21,6 @@ const PROOF = [
export default function FinalCTASection() { export default function FinalCTASection() {
const sectionRef = useRef<HTMLDivElement>(null); const sectionRef = useRef<HTMLDivElement>(null);
const mag1 = useMagnetic();
const mag2 = useMagnetic();
const coinLayerRef = useRef<HTMLDivElement>(null); const coinLayerRef = useRef<HTMLDivElement>(null);
const badgeMag1 = useMagneticShared<HTMLDivElement>(10); const badgeMag1 = useMagneticShared<HTMLDivElement>(10);
const badgeMag2 = useMagneticShared<HTMLDivElement>(10); const badgeMag2 = useMagneticShared<HTMLDivElement>(10);
@@ -106,10 +89,6 @@ export default function FinalCTASection() {
'-=0.35' '-=0.35'
) )
.call(burstCoins) .call(burstCoins)
.fromTo('.fcta-btns',
{ opacity: 0, y: 20 },
{ opacity: 1, y: 0, duration: 0.55, ease: 'power3.out' }, '-=0.45'
)
.fromTo('.fcta-stat', .fromTo('.fcta-stat',
{ opacity: 0, y: 28, scale: 0.88 }, { opacity: 0, y: 28, scale: 0.88 },
{ opacity: 1, y: 0, scale: 1, duration: 0.55, stagger: 0.1, ease: 'back.out(1.8)' }, '-=0.25' { opacity: 1, y: 0, scale: 1, duration: 0.55, stagger: 0.1, ease: 'back.out(1.8)' }, '-=0.25'
@@ -147,8 +126,8 @@ export default function FinalCTASection() {
ref={sectionRef} ref={sectionRef}
style={{ style={{
position: 'relative', position: 'relative',
width: 'calc(100% - 40px)', width: 'calc(100% - (var(--sec-gutter) * 2))',
margin: '0 20px 20px', margin: '0 var(--sec-gutter) var(--sec-gap)',
borderRadius: 32, borderRadius: 32,
overflow: 'hidden', overflow: 'hidden',
background: '#ffffff', background: '#ffffff',
@@ -176,7 +155,7 @@ export default function FinalCTASection() {
fontSize: 'clamp(52px,8vw,116px)', fontSize: 'clamp(52px,8vw,116px)',
fontWeight: 900, color: '#171512', fontWeight: 900, color: '#171512',
}}> }}>
Your lyts Your Lyts
</span> </span>
<span className="fcta-line-2" style={{ <span className="fcta-line-2" style={{
display: 'block', display: 'block',
@@ -263,41 +242,7 @@ export default function FinalCTASection() {
</div> </div>
</div> </div>
{/* CTAs */}
<div className="fcta-btns" style={{ display: 'flex', gap: 14, justifyContent: 'center', flexWrap: 'wrap', marginBottom: 64 }}>
<Link
href="/contacts"
ref={mag1}
style={{
display: 'inline-flex', alignItems: 'center', gap: 9,
padding: '16px 34px', borderRadius: 100,
background: 'linear-gradient(135deg,#f4be28,#ff9500)',
color: '#1a1200', fontWeight: 800, fontSize: '0.97rem',
fontFamily: 'Sora, sans-serif', textDecoration: 'none',
boxShadow: '0 8px 32px rgba(244,190,40,0.35)',
transition: 'box-shadow 0.3s ease, transform 0.3s ease',
}}
>
<svg width="17" height="17" viewBox="0 0 24 24" fill="currentColor"><path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.8-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z"/></svg>
Download for iOS
</Link>
<Link
href="/contacts"
ref={mag2}
style={{
display: 'inline-flex', alignItems: 'center', gap: 9,
padding: '16px 34px', borderRadius: 100,
background: 'transparent',
color: '#171512', fontWeight: 700, fontSize: '0.97rem',
fontFamily: 'Sora, sans-serif', textDecoration: 'none',
border: '1.5px solid rgba(23,21,18,0.2)',
transition: 'border-color 0.3s ease, background 0.3s ease',
}}
>
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"><rect x="2" y="8" width="20" height="10" rx="2"/><path d="M7.83 3l1.3 2.35M16.17 3l-1.3 2.35"/></svg>
Get on Android
</Link>
</div>
{/* Proof stats — individual sticker cards, matching the dark-border card system used across the page */} {/* Proof stats — individual sticker cards, matching the dark-border card system used across the page */}
<div className="fcta-proof-row" style={{ display: 'flex', justifyContent: 'center', gap: 18, flexWrap: 'wrap', width: '80%', maxWidth: 720, margin: '0 auto' }}> <div className="fcta-proof-row" style={{ display: 'flex', justifyContent: 'center', gap: 18, flexWrap: 'wrap', width: '80%', maxWidth: 720, margin: '0 auto' }}>
@@ -389,18 +334,10 @@ export default function FinalCTASection() {
.fcta-sweep { display: none; } .fcta-sweep { display: none; }
} }
@media (max-width: 1023px) { @media (max-width: 1023px) {
.fcta-store-badges {
display: none !important;
}
.fcta-sub { .fcta-sub {
margin-bottom: 40px !important; margin-bottom: 40px !important;
} }
} }
@media (min-width: 1024px) {
.fcta-btns {
display: none !important;
}
}
@media (max-width: 560px) { @media (max-width: 560px) {
.fcta-proof-row { .fcta-proof-row {
width: 100% !important; width: 100% !important;

View File

@@ -357,6 +357,10 @@ export default function VerticalScrollWrapper({ children, sections = [] }: Props
} }
@media (max-width: 600px) { @media (max-width: 600px) {
.fp-shell { padding: 0 22px; } .fp-shell { padding: 0 22px; }
/* Full-bleed panels on phones (no left/right margin), keep bottom gap */
.fp-panel { width: 100%; margin: 0 0 12px; }
/* Hero flush to the top on phones */
.fp-root { padding-top: 0; }
} }
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {

View File

@@ -178,6 +178,16 @@ export default function HeroCarousel({ onReady }: HeroCarouselProps) {
} }
} }
/* Phones — full-bleed hero, flush to top (top margin 0), keep bottom gap */
@media (max-width: 600px) {
.hero-carousel {
width: 100%;
height: calc(100vh - 12px);
height: calc(100svh - 12px);
margin: 0 0 12px;
}
}
.hero-carousel-slides { .hero-carousel-slides {
position: absolute; position: absolute;
inset: 0; inset: 0;

View File

@@ -156,8 +156,8 @@ export default function LytsUpSection({ isLoaded = true }: LytsUpSectionProps) {
id="lytsup" id="lytsup"
className="relative overflow-hidden" className="relative overflow-hidden"
style={{ style={{
width: 'calc(100% - 40px)', width: 'calc(100% - (var(--sec-gutter) * 2))',
margin: '0 20px 20px', margin: '0 var(--sec-gutter) var(--sec-gap)',
borderRadius: 32, borderRadius: 32,
padding: 'clamp(64px, 8vw, 110px) clamp(20px, 4vw, 64px) clamp(64px, 8vw, 96px)', padding: 'clamp(64px, 8vw, 110px) clamp(20px, 4vw, 64px) clamp(64px, 8vw, 96px)',
zIndex: 2, zIndex: 2,

View File

@@ -110,8 +110,8 @@ export default function ProblemSection({ isLoaded = true }: ProblemSectionProps)
className="relative overflow-hidden problem-section" className="relative overflow-hidden problem-section"
style={{ style={{
background: '#ffffff', background: '#ffffff',
width: 'calc(100% - 40px)', width: 'calc(100% - (var(--sec-gutter) * 2))',
margin: '0 20px 20px', margin: '0 var(--sec-gutter) var(--sec-gap)',
borderRadius: '32px', borderRadius: '32px',
padding: 'clamp(72px, 9vw, 130px) clamp(20px, 4vw, 64px) clamp(64px, 7vw, 96px)', padding: 'clamp(72px, 9vw, 130px) clamp(20px, 4vw, 64px) clamp(64px, 7vw, 96px)',
zIndex: 1, zIndex: 1,
@@ -526,8 +526,14 @@ export default function ProblemSection({ isLoaded = true }: ProblemSectionProps)
} }
@media (max-width: 900px) { @media (max-width: 900px) {
#problem .problem-header-grid { grid-template-columns: 1fr; } #problem .problem-header-grid { grid-template-columns: 1fr !important; }
#problem .problem-header-right { border-left: none; padding-left: 0; border-top: 2px solid rgba(23,21,18,0.1); padding-top: 20px; margin-top: 20px; } #problem .problem-header-right {
border-left: none !important;
padding-left: 0 !important;
border-top: 2px solid rgba(23,21,18,0.1) !important;
padding-top: 20px !important;
margin-top: 20px !important;
}
#problem .problem-stats-row { grid-template-columns: 1fr !important; } #problem .problem-stats-row { grid-template-columns: 1fr !important; }
#problem .dark-bento-grid { grid-template-columns: 1fr !important; } #problem .dark-bento-grid { grid-template-columns: 1fr !important; }
#problem .dark-bento-card-4 { grid-column: span 1; } #problem .dark-bento-card-4 { grid-column: span 1; }

View File

@@ -389,7 +389,7 @@ function ProductCard({ product, index }: { product: Product; index: number }) {
</div> </div>
<Link <Link
href="/solutions_page" href="/meet_the_agents"
style={{ style={{
display: 'inline-flex', alignItems: 'center', gap: '8px', width: 'max-content', display: 'inline-flex', alignItems: 'center', gap: '8px', width: 'max-content',
padding: '11px 22px', borderRadius: '99px', fontSize: '0.85rem', fontWeight: 800, padding: '11px 22px', borderRadius: '99px', fontSize: '0.85rem', fontWeight: 800,
@@ -694,7 +694,15 @@ export default function ProductsSection({ isLoaded = false }: ProductsSectionPro
flex-direction: column; align-items: flex-start; gap: 16px; flex-direction: column; align-items: flex-start; gap: 16px;
padding: clamp(40px, 8vw, 64px) 24px 24px; padding: clamp(40px, 8vw, 64px) 24px 24px;
} }
.products-heading-hint { text-align: left !important; } .products-heading-hint {
text-align: left !important;
border-right: none !important;
padding-right: 0 !important;
border-top: 2px solid rgba(244,190,40,0.3) !important;
padding-top: 16px !important;
margin-top: 8px !important;
max-width: 100% !important;
}
.products-track { .products-track {
position: relative; height: auto; position: relative; height: auto;
padding-top: 8px; padding-bottom: 8px; padding-top: 8px; padding-bottom: 8px;

View File

@@ -135,8 +135,8 @@ export default function ShiftSection({ isLoaded = true }: ShiftSectionProps) {
className="relative overflow-hidden shift-section" className="relative overflow-hidden shift-section"
style={{ style={{
background: 'linear-gradient(155deg, #fffdf6 0%, #fbf5e4 48%, #f6ecd2 100%)', background: 'linear-gradient(155deg, #fffdf6 0%, #fbf5e4 48%, #f6ecd2 100%)',
width: 'calc(100% - 40px)', width: 'calc(100% - (var(--sec-gutter) * 2))',
margin: '0 20px 20px', margin: '0 var(--sec-gutter) var(--sec-gap)',
borderRadius: '32px', borderRadius: '32px',
padding: 'clamp(72px, 9vw, 130px) clamp(20px, 4vw, 64px) clamp(56px, 7vw, 90px)', padding: 'clamp(72px, 9vw, 130px) clamp(20px, 4vw, 64px) clamp(56px, 7vw, 90px)',
zIndex: 1, zIndex: 1,
@@ -490,8 +490,14 @@ export default function ShiftSection({ isLoaded = true }: ShiftSectionProps) {
} }
@media (max-width: 900px) { @media (max-width: 900px) {
#shift .shift-header-grid { grid-template-columns: 1fr; } #shift .shift-header-grid { grid-template-columns: 1fr !important; }
#shift .shift-header-right { border-left: none; padding-left: 0; border-top: 2px solid rgba(244,190,40,0.3); padding-top: 20px; margin-top: 20px; } #shift .shift-header-right {
border-left: none !important;
padding-left: 0 !important;
border-top: 2px solid rgba(244,190,40,0.3) !important;
padding-top: 20px !important;
margin-top: 20px !important;
}
} }
`}</style> `}</style>
</section> </section>

View File

@@ -32,7 +32,7 @@ interface Step {
const STEPS: Step[] = [ const STEPS: Step[] = [
{ step: '01', id: 'earn', title: 'Earn Online', desc: 'Daily login, 5,000-step walking challenges, and interactive games like Maze and Spin Wheel earn LYTs and unlock surprise coupons.' }, { step: '01', id: 'earn', title: 'Earn Online', desc: 'Daily login, 5,000-step walking challenges, and interactive games like Maze and Spin Wheel earn LYTs and unlock surprise coupons.' },
{ step: '02', id: 'engage', title: 'Unlock Deals', desc: 'Merchants create game based discount campaigns: customers play once to reveal their exclusive reward on a specific product.' }, { step: '02', id: 'engage', title: 'Unlock Deals', desc: 'Merchants create LYTs-earning campaigns: customers play once to reveal their exclusive reward on a specific product.' },
{ step: '03', id: 'spend', title: 'Discover & Visit', desc: 'Browse participating stores nearby, view active game campaigns and LYTs-earning offers, then walk in and shop in person.' }, { step: '03', id: 'spend', title: 'Discover & Visit', desc: 'Browse participating stores nearby, view active game campaigns and LYTs-earning offers, then walk in and shop in person.' },
{ step: '04', id: 'repeat', title: 'Redeem & Repeat', desc: 'Use LYTs and coupons at checkout to save money, then come back tomorrow to earn more and keep the loop going.' }, { step: '04', id: 'repeat', title: 'Redeem & Repeat', desc: 'Use LYTs and coupons at checkout to save money, then come back tomorrow to earn more and keep the loop going.' },
]; ];
@@ -270,8 +270,8 @@ export default function TheLoop() {
id="the-loop" id="the-loop"
style={{ style={{
position: 'relative', position: 'relative',
width: 'calc(100% - 40px)', width: 'calc(100% - (var(--sec-gutter) * 2))',
margin: '0 20px 0', margin: '0 var(--sec-gutter) 0',
borderRadius: '32px 32px 0 0', borderRadius: '32px 32px 0 0',
overflow: 'hidden', overflow: 'hidden',
zIndex: 2, zIndex: 2,
@@ -316,7 +316,7 @@ export default function TheLoop() {
color: 'rgba(255,255,255,0.38)', lineHeight: 1.75, color: 'rgba(255,255,255,0.38)', lineHeight: 1.75,
fontFamily: 'Sora, sans-serif', fontFamily: 'Sora, sans-serif',
}}> }}>
Earn LYTs online, unlock game based deals, discover nearby stores, and redeem offline. Earn LYTs online, unlock LYTs-based deals, discover nearby stores, and redeem offline.
</p> </p>
</div> </div>
@@ -536,8 +536,8 @@ export default function TheLoop() {
id="the-loop-mobile" id="the-loop-mobile"
style={{ style={{
position: 'relative', position: 'relative',
width: 'calc(100% - 40px)', width: 'calc(100% - (var(--sec-gutter) * 2))',
margin: '0 20px 0', margin: '0 var(--sec-gutter) 0',
borderRadius: '32px 32px 0 0', borderRadius: '32px 32px 0 0',
overflow: 'hidden', overflow: 'hidden',
zIndex: 2, zIndex: 2,
@@ -581,7 +581,7 @@ export default function TheLoop() {
color: 'rgba(255,255,255,0.4)', lineHeight: 1.5, color: 'rgba(255,255,255,0.4)', lineHeight: 1.5,
fontFamily: 'Sora, sans-serif', fontFamily: 'Sora, sans-serif',
}}> }}>
Earn LYTs online, unlock game based deals, discover nearby stores, and redeem offline. Earn LYTs online, unlock LYTs-based deals, discover nearby stores, and redeem offline.
</p> </p>
</div> </div>
@@ -729,8 +729,8 @@ export default function TheLoop() {
{/* Impact metrics — outside section to avoid overflow:hidden clipping */} {/* Impact metrics — outside section to avoid overflow:hidden clipping */}
<div style={{ <div style={{
position: 'relative', zIndex: 2, position: 'relative', zIndex: 2,
width: 'calc(100% - 40px)', width: 'calc(100% - (var(--sec-gutter) * 2))',
margin: '0 20px 20px', margin: '0 var(--sec-gutter) var(--sec-gap)',
borderRadius: '0 0 32px 32px', borderRadius: '0 0 32px 32px',
background: '#0c0a07', background: '#0c0a07',
padding: 'clamp(32px,4vh,52px) clamp(28px,5vw,80px) clamp(28px,4vh,48px)', padding: 'clamp(32px,4vh,52px) clamp(28px,5vw,80px) clamp(28px,4vh,48px)',

View File

@@ -221,8 +221,8 @@ export default function WhatWeDo({ isLoaded = false }: WhatWeDoProps) {
id="what-we-do" id="what-we-do"
className="relative bg-[#0D0D0D] !pt-32 sm:!pt-40 md:!pt-44 pb-24 md:pb-32 px-6 md:px-12 xl:px-16 overflow-hidden select-none" className="relative bg-[#0D0D0D] !pt-32 sm:!pt-40 md:!pt-44 pb-24 md:pb-32 px-6 md:px-12 xl:px-16 overflow-hidden select-none"
style={{ style={{
width: 'calc(100% - 40px)', width: 'calc(100% - (var(--sec-gutter) * 2))',
margin: '0 20px 20px', margin: '0 var(--sec-gutter) var(--sec-gap)',
borderRadius: 32, borderRadius: 32,
zIndex: 2, zIndex: 2,
}} }}

View File

@@ -24,7 +24,7 @@ export const HERO_SLIDES: HeroSlideData[] = [
ctaLabel: 'Book a Demo', ctaLabel: 'Book a Demo',
ctaHref: '/contacts', ctaHref: '/contacts',
secondaryLabel: 'See How It Works', secondaryLabel: 'See How It Works',
secondaryHref: '/solutions_page', secondaryHref: '/meet_the_agents',
image: '/assets/home_hero/home_hero_01.png', image: '/assets/home_hero/home_hero_01.png',
imageAlt: 'Shoppers walking through a modern premium shopping mall', imageAlt: 'Shoppers walking through a modern premium shopping mall',
}, },
@@ -50,9 +50,9 @@ export const HERO_SLIDES: HeroSlideData[] = [
description: description:
'Behavision, SpendSense, Dyscount, Identiq, Flowmind, and the Loyaly App — a connected AI suite that knows your customers inside out.', 'Behavision, SpendSense, Dyscount, Identiq, Flowmind, and the Loyaly App — a connected AI suite that knows your customers inside out.',
ctaLabel: 'Explore Platform', ctaLabel: 'Explore Platform',
ctaHref: '/solutions_page', ctaHref: '/meet_the_agents',
secondaryLabel: 'Meet the Tools', secondaryLabel: 'Meet the Tools',
secondaryHref: '/solutions_page', secondaryHref: '/meet_the_agents',
image: '/assets/home_hero/home_hero_03.png', image: '/assets/home_hero/home_hero_03.png',
imageAlt: 'Aerial view of a large, crowded luxury shopping mall atrium', imageAlt: 'Aerial view of a large, crowded luxury shopping mall atrium',
}, },

View File

@@ -115,17 +115,17 @@ export default function ProductsScrollSection() {
return ( return (
<section <section
ref={sectionRef} ref={sectionRef}
className="products-scroll-section"
style={{ style={{
position: 'relative', position: 'relative',
height: `${(TOTAL - 1) * STEP_VH + 100}vh`, height: `${(TOTAL - 1) * STEP_VH + 100}vh`,
background: '#07070d', background: '#07070d',
margin: '0 20px 20px',
borderRadius: 24,
overflow: 'hidden', overflow: 'hidden',
}} }}
> >
<div <div
ref={pinRef} ref={pinRef}
className="uc-pp-pin"
style={{ style={{
height: '100vh', height: '100vh',
display: 'flex', display: 'flex',
@@ -144,7 +144,7 @@ export default function ProductsScrollSection() {
}} /> }} />
{/* Header */} {/* Header */}
<div style={{ position: 'relative', zIndex: 2, marginBottom: 'clamp(56px,8vh,96px)' }}> <div className="uc-pp-header" style={{ position: 'relative', zIndex: 2, marginBottom: 'clamp(56px,8vh,96px)' }}>
<SectionEyebrow variant="pill" style={{ marginBottom: 16 }}>Our Products</SectionEyebrow> <SectionEyebrow variant="pill" style={{ marginBottom: 16 }}>Our Products</SectionEyebrow>
<h2 style={{ fontSize: 'clamp(32px, 4.5vw, 64px)', fontWeight: 800, letterSpacing: '-0.05em', lineHeight: 0.92, color: '#fff', margin: 0, fontFamily: 'Sora, sans-serif', maxWidth: 640 }}> <h2 style={{ fontSize: 'clamp(32px, 4.5vw, 64px)', fontWeight: 800, letterSpacing: '-0.05em', lineHeight: 0.92, color: '#fff', margin: 0, fontFamily: 'Sora, sans-serif', maxWidth: 640 }}>
Offline Shopping. Online Intelligence. Offline Shopping. Online Intelligence.
@@ -152,7 +152,7 @@ export default function ProductsScrollSection() {
</div> </div>
{/* Horizontal progress track with 3 points */} {/* Horizontal progress track with 3 points */}
<div style={{ position: 'relative', zIndex: 2, margin: '0 0 clamp(72px,10vh,120px)', padding: '0 16px' }}> <div className="uc-pp-track" style={{ position: 'relative', zIndex: 2, margin: '0 0 clamp(72px,10vh,120px)', padding: '0 16px' }}>
<div style={{ position: 'relative', height: 2, background: 'rgba(255,255,255,0.08)', borderRadius: 2 }}> <div style={{ position: 'relative', height: 2, background: 'rgba(255,255,255,0.08)', borderRadius: 2 }}>
{/* Growing fill line */} {/* Growing fill line */}
<div <div
@@ -215,6 +215,7 @@ export default function ProductsScrollSection() {
<div <div
key={p.name} key={p.name}
ref={el => { visualRefs.current[i] = el; }} ref={el => { visualRefs.current[i] = el; }}
data-pp-panel
style={{ style={{
position: 'absolute', inset: 0, position: 'absolute', inset: 0,
opacity: i === 0 ? 1 : 0, opacity: i === 0 ? 1 : 0,
@@ -234,7 +235,7 @@ export default function ProductsScrollSection() {
<div style={{ position: 'absolute', bottom: '-25%', left: '-15%', width: '55%', aspectRatio: '1', borderRadius: '50%', background: 'rgba(0,0,0,0.08)', pointerEvents: 'none' }} /> <div style={{ position: 'absolute', bottom: '-25%', left: '-15%', width: '55%', aspectRatio: '1', borderRadius: '50%', background: 'rgba(0,0,0,0.08)', pointerEvents: 'none' }} />
{/* Ghost number */} {/* Ghost number */}
<span style={{ <span data-pp-ghost style={{
position: 'absolute', bottom: -30, right: 14, lineHeight: 1, position: 'absolute', bottom: -30, right: 14, lineHeight: 1,
fontSize: 'clamp(130px,13vw,200px)', fontWeight: 900, fontSize: 'clamp(130px,13vw,200px)', fontWeight: 900,
fontFamily: 'Sora, sans-serif', letterSpacing: '-0.06em', fontFamily: 'Sora, sans-serif', letterSpacing: '-0.06em',
@@ -257,7 +258,7 @@ export default function ProductsScrollSection() {
{/* Hero metric */} {/* Hero metric */}
<div style={{ position: 'relative' }}> <div style={{ position: 'relative' }}>
<div style={{ <div data-pp-metric style={{
fontSize: 'clamp(72px,8.5vw,130px)', fontWeight: 900, lineHeight: 0.9, fontSize: 'clamp(72px,8.5vw,130px)', fontWeight: 900, lineHeight: 0.9,
color: '#111', fontFamily: 'Sora, sans-serif', letterSpacing: '-0.05em', color: '#111', fontFamily: 'Sora, sans-serif', letterSpacing: '-0.05em',
}}>{p.metric}</div> }}>{p.metric}</div>
@@ -273,7 +274,7 @@ export default function ProductsScrollSection() {
</div> </div>
{/* Right — editorial text (stacked, cross-fading) */} {/* Right — editorial text (stacked, cross-fading) */}
<div style={{ position: 'relative', minHeight: 'clamp(300px, 38vh, 420px)' }}> <div className="uc-pp-text" style={{ position: 'relative', minHeight: 'clamp(300px, 38vh, 420px)' }}>
{PRODUCTS.map((p, i) => ( {PRODUCTS.map((p, i) => (
<div <div
key={p.name} key={p.name}
@@ -287,22 +288,22 @@ export default function ProductsScrollSection() {
display: 'flex', flexDirection: 'column', justifyContent: 'center', display: 'flex', flexDirection: 'column', justifyContent: 'center',
}} }}
> >
<div style={{ <div data-pp-tag style={{
display: 'inline-block', width: 'fit-content', fontSize: 11, fontWeight: 700, letterSpacing: '0.14em', display: 'inline-block', width: 'fit-content', fontSize: 11, fontWeight: 700, letterSpacing: '0.14em',
textTransform: 'uppercase', color: p.color, fontFamily: 'Sora, sans-serif', textTransform: 'uppercase', color: p.color, fontFamily: 'Sora, sans-serif',
marginBottom: 20, background: `${p.color}15`, padding: '6px 14px', borderRadius: 100, marginBottom: 20, background: `${p.color}15`, padding: '6px 14px', borderRadius: 100,
border: `1px solid ${p.color}30`, border: `1px solid ${p.color}30`,
}}>{p.tag}</div> }}>{p.tag}</div>
<h3 style={{ fontSize: 'clamp(34px, 4vw, 60px)', fontWeight: 800, letterSpacing: '-0.04em', lineHeight: 0.95, color: '#fff', margin: '0 0 22px', fontFamily: 'Sora, sans-serif' }}>{p.name}</h3> <h3 data-pp-title style={{ fontSize: 'clamp(34px, 4vw, 60px)', fontWeight: 800, letterSpacing: '-0.04em', lineHeight: 0.95, color: '#fff', margin: '0 0 22px', fontFamily: 'Sora, sans-serif' }}>{p.name}</h3>
<p style={{ <p data-pp-desc style={{
fontSize: 'clamp(15px,1.25vw,19px)', lineHeight: 1.7, color: 'rgba(255,255,255,0.45)', fontSize: 'clamp(15px,1.25vw,19px)', lineHeight: 1.7, color: 'rgba(255,255,255,0.45)',
fontFamily: 'Sora, sans-serif', margin: '0 0 36px', maxWidth: 460, fontFamily: 'Sora, sans-serif', margin: '0 0 36px', maxWidth: 460,
paddingLeft: 20, borderLeft: `2px solid ${p.color}55`, paddingLeft: 20, borderLeft: `2px solid ${p.color}55`,
}}>{p.desc}</p> }}>{p.desc}</p>
<Link href="/contacts" style={{ <Link href="/contacts" data-pp-cta style={{
display: 'inline-flex', alignItems: 'center', gap: 8, width: 'fit-content', display: 'inline-flex', alignItems: 'center', gap: 8, width: 'fit-content',
padding: '15px 32px', background: p.color, color: '#111', padding: '15px 32px', background: p.color, color: '#111',
fontSize: 14, fontWeight: 800, borderRadius: 100, textDecoration: 'none', fontSize: 14, fontWeight: 800, borderRadius: 100, textDecoration: 'none',
@@ -315,10 +316,73 @@ export default function ProductsScrollSection() {
</div> </div>
<style>{` <style>{`
.products-scroll-section {
margin: 0 20px 20px;
width: calc(100% - 40px);
border-radius: 24px;
}
@media (max-width: 768px) {
.products-scroll-section {
margin: 0 var(--sec-gutter) 20px !important;
width: calc(100% - (var(--sec-gutter) * 2)) !important;
}
}
/* ── Tablet / large phone: stack the two columns. The section is a fixed
100vh pin, so the stacked blocks are kept compact enough to fit the
viewport height across this whole range (incl. shorter tablets). ── */
@media (max-width: 860px) { @media (max-width: 860px) {
.uc-pp-grid { grid-template-columns: 1fr !important; gap: 24px !important; } .uc-pp-pin { padding: 0 4% !important; }
.uc-pp-visual { min-height: 260px !important; } .uc-pp-grid { grid-template-columns: 1fr !important; gap: 20px !important; }
.uc-pp-visual { min-height: 200px !important; }
/* Text panels are absolutely-positioned crossfaders, so the column
needs an explicit height to reserve space for them. */
.uc-pp-text { min-height: 260px !important; }
.uc-pp-label { display: none; } .uc-pp-label { display: none; }
.uc-pp-header { margin-bottom: 30px !important; }
.uc-pp-track { margin-bottom: 40px !important; }
}
/* ── Phone: compress further so the pinned frame never clips the header
or CTA, even on short viewports. ── */
@media (max-width: 600px) {
.uc-pp-pin { padding: 0 24px !important; }
.uc-pp-header { margin-bottom: 26px !important; }
.uc-pp-header h2 { font-size: clamp(26px, 7.5vw, 34px) !important; }
.uc-pp-track { margin-bottom: 34px !important; padding: 0 14px !important; }
.uc-pp-grid { gap: 18px !important; }
.uc-pp-visual { min-height: 190px !important; }
.uc-pp-text { min-height: 270px !important; }
/* Shrink the oversized hero metric + ghost number to fit the panel */
.uc-pp-visual [data-pp-metric] { font-size: clamp(52px, 15vw, 72px) !important; }
.uc-pp-visual [data-pp-ghost] { font-size: clamp(96px, 30vw, 130px) !important; bottom: -20px !important; }
.uc-pp-visual [data-pp-panel] { padding: 20px 22px !important; }
/* Tighten the editorial text stack */
.uc-pp-text [data-pp-title] { font-size: clamp(28px, 8vw, 38px) !important; margin-bottom: 14px !important; }
.uc-pp-text [data-pp-desc] { font-size: 14px !important; margin-bottom: 22px !important; line-height: 1.6 !important; }
.uc-pp-text [data-pp-tag] { margin-bottom: 14px !important; }
.uc-pp-text [data-pp-cta] { padding: 13px 26px !important; }
}
/* ── Short viewports (small phones like iPhone SE ~568px, landscape,
short windows). The pinned frame equals the viewport height, so on
these we compress aggressively so nothing spills out of view.
Scoped to the stacked range so desktop short windows are untouched. ── */
@media (max-width: 860px) and (max-height: 700px) {
.uc-pp-header { margin-bottom: 16px !important; }
.uc-pp-header h2 { font-size: clamp(20px, 6vw, 27px) !important; line-height: 1 !important; }
.uc-pp-track { margin-bottom: 22px !important; }
.uc-pp-grid { gap: 14px !important; }
.uc-pp-visual { min-height: 156px !important; }
.uc-pp-text { min-height: 230px !important; }
.uc-pp-visual [data-pp-metric] { font-size: 46px !important; }
.uc-pp-visual [data-pp-ghost] { font-size: 92px !important; bottom: -16px !important; }
.uc-pp-visual [data-pp-panel] { padding: 16px 18px !important; }
.uc-pp-text [data-pp-tag] { margin-bottom: 10px !important; }
.uc-pp-text [data-pp-title] { font-size: 25px !important; margin-bottom: 8px !important; }
.uc-pp-text [data-pp-desc] { font-size: 12.5px !important; margin-bottom: 14px !important; line-height: 1.5 !important; }
.uc-pp-text [data-pp-cta] { padding: 10px 20px !important; font-size: 12.5px !important; }
} }
`}</style> `}</style>
</section> </section>