"use client"; import { motion, useReducedMotion } from "motion/react"; const EASE_OUT: [number, number, number, number] = [0.16, 1, 0.3, 1]; const VIEWPORT = { once: true, amount: 0.4 } as const; export type UseCaseArtVariant = "price" | "brand" | "leads" | "serp" | "chat" | "api"; /** Soft infinite pulse ring marking the "live" signal in each artifact. */ function Pulse({ cx, cy, reduce, delay = 0, }: { cx: number; cy: number; reduce: boolean; delay?: number; }) { if (reduce) return null; return ( ); } /** Competitor price monitoring: a price line steps up; the change point alerts. */ function PriceArt({ reduce }: { reduce: boolean }) { return ( {/* Grid */} {[24, 48, 72].map((y) => ( ))} {/* Price line with a step change at x=132 */} {/* Alert at the step */} {/* Price-change tag */} +$10/mo ); } /** Brand monitoring: a listening radar; mentions blip in around the brand. */ function BrandArt({ reduce }: { reduce: boolean }) { const blips = [ { cx: 84, cy: 30, delay: 0.5 }, { cx: 168, cy: 38, delay: 0.7 }, { cx: 100, cy: 70, delay: 0.9 }, ]; return ( {/* Radar rings */} {[16, 30, 44].map((r, i) => ( ))} {/* Brand at the center */} {/* Mention blips */} {blips.map((blip) => ( ))} ); } /** B2B lead generation: a lead list fills in row by row, each verified. */ function LeadsArt({ reduce }: { reduce: boolean }) { const rows = [22, 48, 74]; return ( {rows.map((y, i) => ( {/* Avatar */} {/* Name + contact lines */} {/* Verified check */} ))} ); } /** Market research: SERP rows; your result climbs from #3 to #1. */ function SerpArt({ reduce }: { reduce: boolean }) { const swapDelay = 0.8; const swapY = { duration: 0.5, ease: EASE_OUT, delay: swapDelay, times: [0, 0.6, 1] }; return ( {/* Competitor rows: start at ranks 1 and 2, shift down one slot */} {[ { startY: 14, width: 148 }, { startY: 40, width: 120 }, ].map((row, i) => ( ))} {/* Your row: starts at rank 3, climbs to rank 1 */} ); } /** Founders & marketers: a plain-English ask streams back an agent brief with cited sources. */ function ChatArt({ reduce }: { reduce: boolean }) { const briefLines = [ { y: 38, width: 150, delay: 0.55 }, { y: 52, width: 180, delay: 0.7 }, { y: 66, width: 120, delay: 0.85 }, ]; return ( {/* User ask: right-aligned bubble */} {/* Agent avatar */} {/* Brief streams in line by line */} {briefLines.map((line) => ( ))} {/* Citation chip */} 3 sources ); } /** Developers & agents: a typed request gets a 200 and JSON streams back. */ function ApiArt({ reduce }: { reduce: boolean }) { const jsonLines = [ { y: 50, text: '{ "items": [', delay: 0.6 }, { y: 66, text: ' { "title": "...", "score": 812 },', delay: 0.75 }, { y: 82, text: "] }", delay: 0.9 }, ]; return ( {/* Request line */} POST /scrapers/reddit/scrape {/* 200 OK badge */} 200 OK {/* JSON response streams in */} {jsonLines.map((line) => ( {line.text} ))} {/* Blinking cursor after the closing brace */} ); } const ART: Record React.ReactNode> = { price: PriceArt, brand: BrandArt, leads: LeadsArt, serp: SerpArt, chat: ChatArt, api: ApiArt, }; /** Small animated artifact rendered at the top of each use-case card. */ export function UseCaseArt({ variant }: { variant: UseCaseArtVariant }) { const reduce = useReducedMotion() ?? false; const Art = ART[variant]; return (
); }