// 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 (
Harjog
Harjog
{palette.map((c, i) => (
))}
System v1.4 5 weights
);
}
function RealEstateVisual() {
const [ref, seen] = useInView();
return (
{[
{ x: 22, y: 30, d: 0 },
{ x: 65, y: 55, d: 600 },
{ x: 45, y: 72, d: 1100 },
{ x: 80, y: 22, d: 1500 },
].map((p, i) => (
))}
Site visit booked · Royal Greens
);
}
function PoliticalVisual() {
const [ref, seen] = useInView();
const cells = 12 * 6;
return (
{Array.from({ length: cells }).map((_, i) => (
))}
Booth #42 4.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:12 1080×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 (
{doubled.map((ev, i) => (
{ev.t}
{ev.e}
{ev.d}
))}
);
}
// ===== 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
;
}
Object.assign(window, {
AnimatedCapabilities, MetricsTicker, HeroSpotlight
});