/** * DashboardCardSpotlight — the right-rail Card Spotlight panel from * the operator's redesign-v2 mockup (sub-convoy #8). * * Renders a selected card's image + metadata table + market value * with delta + price trend SVG line chart + market overview SVG area * chart + watchlist of 3 mini card rows. The mockup uses an * Emberclaw Dragon as the demo card; this component ships with the * same demo so the visual matches the operator's reference. * * Per umbrella convoy § 8: this is the sketch tier. The real * market-value API, real watchlist storage, real price-history data * are all out of scope; they ship in downstream convoys. * * Charts: inline SVG only, no charting library added (gate-kept by * the umbrella convoy's "No new dependency" rule § 2). * * Props: none today — fully self-contained demo. Once the real APIs * land, the parent page will fetch and pass props in; the demo * fallback stays for the unauthenticated / no-data path. * * Accessibility: * - Card image uses an alt with the card name. * - Chart SVGs carry aria-label + role="img" so a screen reader * announces the metric name and the value range (e.g. "Price * trend over 30 days, ranging from $108 to $148"). * - Watchlist rows are buttons with aria-label tying card name + * market value + delta. */ const SPOTLIGHT_CARD = { name: 'Emberclaw Dragon', rarity: 'Mythic', set: 'Ignis Reborn', collectorNumber: '07/120', condition: 'Near Mint', marketValue: 128.47, delta: '+18.6%', deltaPeriod: '30d', // Inline SVG art for the card thumbnail. Placeholder warmth and // type-line until real card images are wired. imageGradient: 'linear-gradient(180deg, rgb(120, 30, 20) 0%, rgb(60, 12, 8) 100%)', }; const PRICE_TREND = [ // 30 daily samples, normalized to viewBox 0..300 horizontally, // 60..10 vertically (low Y = high value in SVG coords). Hand- // shaped to roughly match the mockup's gentle climb + dip + peak. [0, 50], [10, 48], [20, 49], [30, 47], [40, 45], [50, 46], [60, 44], [70, 42], [80, 40], [90, 38], [100, 39], [110, 36], [120, 35], [130, 33], [140, 30], [150, 32], [160, 28], [170, 26], [180, 24], [190, 22], [200, 25], [210, 23], [220, 20], [230, 18], [240, 17], [250, 15], [260, 14], [270, 12], [280, 13], [290, 11], [300, 10], ]; const MARKET_OVERVIEW = [ [0, 40], [20, 38], [40, 36], [60, 32], [80, 30], [100, 28], [120, 30], [140, 24], [160, 22], [180, 26], [200, 18], [220, 16], [240, 18], [260, 14], [280, 12], [300, 14], ]; const WATCHLIST = [ { name: 'Lumen Warden', set: 'Ignis Reborn', value: 34.21, delta: '-2.1%' }, { name: 'Voidforge Titan', set: 'Ignis Reborn', value: 89.99, delta: '+6.7%' }, { name: 'Chaos Invasion', set: 'Ignis Reborn', value: 12.48, delta: '+8.3%' }, ]; function pointsToPath(points) { return points.map(([x, y], i) => `${i === 0 ? 'M' : 'L'} ${x} ${y}`).join(' '); } function pointsToAreaPath(points) { const top = pointsToPath(points); const last = points[points.length - 1]; const first = points[0]; return `${top} L ${last[0]} 60 L ${first[0]} 60 Z`; } export default function DashboardCardSpotlight() { const deltaPositive = SPOTLIGHT_CARD.delta.startsWith('+'); return ( ); }