// home-extras.jsx — animated showcase sections that demonstrate agency craft // ===== CapVisual: mini-animation per capability ===== // kind: brand | realestate | political | performance | automation | content function useInView(threshold = 0) { const ref = React.useRef(null); const [seen, setSeen] = React.useState(false); React.useEffect(() => { if (!ref.current) return; // Fire as soon as any part of the element enters the viewport // (with a tiny negative margin so it triggers just before fully visible) const io = new IntersectionObserver((es) => { es.forEach(e => { if (e.isIntersecting) { setSeen(true); io.disconnect(); } }); }, { threshold, rootMargin: '0px 0px -8% 0px' }); io.observe(ref.current); // Safety net — if the element is already in view on mount (e.g. above the fold, // or a tall section the observer might not fire on), reveal after a short delay. const fallback = setTimeout(() => setSeen(true), 1200); return () => { io.disconnect(); clearTimeout(fallback); }; }, [threshold]); return [ref, seen]; } function BrandVisual() { const [ref, seen] = useInView(); const palette = ['#D4A24C', '#F39137', '#E63E1F', '#0a0a0a', '#fafafa']; return (
{palette.map((c, i) => ( ))}
System v1.45 weights
); } function RealEstateVisual() { const [ref, seen] = useInView(); return (
Site visit booked · Royal Greens
); } function PoliticalVisual() { const [ref, seen] = useInView(); const cells = 12 * 6; return (
{Array.from({ length: cells }).map((_, i) => ( ))}
Booth #424.2L touchpoints
); } function PerformanceVisual() { const [ref, seen] = useInView(); const bars = [40, 62, 35, 78, 55, 90, 70]; const [cpl, setCpl] = React.useState(62); React.useEffect(() => { if (!seen) return; let v = 62; const id = setInterval(() => { v = Math.max(24, v - 1); setCpl(v); if (v <= 24) clearInterval(id); }, 70); return () => clearInterval(id); }, [seen]); return (
{bars.map((h, i) => ( ))}
Cost per lead {cpl}↓ 62%
); } function AutomationVisual() { const [ref, seen] = useInView(); // Animated WhatsApp-style chat const msgs = [ { side: 'in', t: 'Interested in your 3BHK pricing for Royal Greens.' }, { side: 'out', t: 'Hi Rajan — sharing the floor plan + price sheet now.' }, { side: 'in', t: 'Can I visit on Saturday?' }, { side: 'out', t: '11:30 AM with our site team. Pin: maps.app/r-greens' }, ]; return (
WhatsApp · Royal Greens bot live
{msgs.map((m, i) => (
{m.t}
))}
); } function ContentVisual() { const [ref, seen] = useInView(); const [pct, setPct] = React.useState(0); React.useEffect(() => { if (!seen) return; let p = 0; const id = setInterval(() => { p = (p + 1) % 100; setPct(p); }, 80); return () => clearInterval(id); }, [seen]); return (
{[12, 25, 50, 75, 88].map(t => ( ))}
00:{String(Math.floor(pct * 0.12)).padStart(2,'0')} / 00:121080×1920
); } const CAP_VISUALS = { brand: BrandVisual, realestate: RealEstateVisual, political: PoliticalVisual, performance: PerformanceVisual, automation: AutomationVisual, content: ContentVisual, }; function AnimatedCapabilities({ setRoute }) { const caps = [ { num: '01', title: 'Brand Identity', slug: 'brand-identity' }, { num: '02', title: 'Real Estate Marketing', slug: 'real-estate' }, { num: '03', title: 'Political Campaigns', slug: 'political' }, { num: '04', title: 'Performance Marketing', slug: 'performance' }, { num: '05', title: 'Marketing Automation', slug: 'automation' }, { num: '06', title: 'Content & Production', slug: 'content-video' }, ]; return (

What we do
under one roof.

{caps.map((c, i) => ( setRoute('service/' + c.slug)}>

{c.title.split('').map((ch, j) => ( {ch === ' ' ? ' ' : ch} {ch === ' ' ? ' ' : ch} ))}

))}
); } // ===== Animated metrics ticker ===== function MetricsTicker() { const [ref, seen] = useInView(); const items = [ { v: 10, suffix: '+', k: 'Years in practice', sub: 'Since 2014' }, { v: 140, suffix: '+', k: 'Projects delivered', sub: 'Film · Social · Marketing' }, { v: 4.2, suffix: 'L', k: 'Voter touchpoints', sub: '2025 · verified', float: true }, { v: 6, suffix: '', k: 'Countries — social clients', sub: 'UK · AU · CA · USA · UAE · TH' }, ]; return (
{items.map((it, i) => (
it.float ? n.toFixed(1) : Math.round(n)} suffix={it.suffix} />
{it.k}
{it.sub}
))}
); } // Live activity feed — strip of "events" cycling through function ActivityFeed() { const events = [ { t: 'JUST NOW', e: 'Reel published', d: 'Royal Greens · 9:16 · 12s', kind: 'content' }, { t: '2 MIN', e: 'Lead routed', d: 'Sona Foods · WhatsApp · 47s response', kind: 'auto' }, { t: '14 MIN', e: 'CPL crossed target', d: 'Aman Buildwell · ₹38.4k', kind: 'perf' }, { t: '38 MIN', e: 'Hoarding installed', d: 'GT Road · 40×20 · install verified', kind: 'print' }, { t: '1 HR', e: 'IVR broadcast sent', d: 'MLA campaign · 84/84 booths · 412k calls', kind: 'pol' }, { t: '2 HR', e: 'Brand sprint v2', d: 'Punjab Khadi · identity v2 shipped', kind: 'brand' }, { t: '4 HR', e: 'Drone reel cut', d: 'Heritage Resorts · 90s master', kind: 'content' }, ]; const doubled = [...events, ...events]; return ( ); } // ===== Cursor spotlight on hero ===== function HeroSpotlight() { const ref = React.useRef(null); React.useEffect(() => { const el = ref.current; if (!el) return; const hero = el.closest('.hero'); if (!hero) return; const onMove = (e) => { const r = hero.getBoundingClientRect(); const x = ((e.clientX - r.left) / r.width) * 100; const y = ((e.clientY - r.top) / r.height) * 100; el.style.setProperty('--mx', x + '%'); el.style.setProperty('--my', y + '%'); el.classList.add('on'); }; const onLeave = () => el.classList.remove('on'); hero.addEventListener('mousemove', onMove); hero.addEventListener('mouseleave', onLeave); return () => { hero.removeEventListener('mousemove', onMove); hero.removeEventListener('mouseleave', onLeave); }; }, []); return