1import Link from 'next/link';2import type { IndexRow } from '@/lib/queries/indices';3import { fmtNum, cn, fmtPct, deltaClass } from '@/lib/format';45/**6 * Live tape (§163): a terminal-style ticker of the indices. Published indices show value + daily change;7 * indices still building show their constituent progress. Pauses on hover/focus; static under reduced motion.8 */9export function IndexTape({ indices, className }: { indices: IndexRow[]; className?: string }) {10 if (!indices.length) return null;11 const ordered = [...indices].sort((a, b) => Number(Boolean(b.latest)) - Number(Boolean(a.latest)) || (a.isFlagship ? -1 : 0) - (b.isFlagship ? -1 : 0));12 const items = ordered.map((i) => {13 const up = (i.change1d ?? 0) > 0;14 const down = (i.change1d ?? 0) < 0;15 return (16 <Link key={i.ticker} href={`/rareindex/${i.ticker}`} className="mono-num flex h-9 shrink-0 items-center gap-2.5 border-r border-border px-4 text-[12px] hover:bg-inset" aria-label={`${i.ticker}${i.latest ? ` ${fmtNum(i.latest.value, { digits: 2 })} ${fmtPct(i.change1d)}` : ' building'}`}>17 <span className="inline-block h-2 w-2 rounded-[2px]" style={{ background: i.color ?? 'var(--ri-index)' }} aria-hidden />18 <span className="font-semibold tracking-wide text-fg">{i.ticker}</span>19 {i.latest ? (20 <>21 <span className="text-muted">{fmtNum(i.latest.value, { digits: 2 })}</span>22 <span className={cn('font-medium', deltaClass(i.change1d))}>23 {up ? '▲' : down ? '▼' : '■'} {fmtPct(i.change1d)}24 </span>25 </>26 ) : (27 <span className="text-subtle">28 building {i.pricedAssets}/{i.minConstituents}29 </span>30 )}31 </Link>32 );33 });34 return (35 <div className={cn('relative overflow-hidden border-y border-border bg-elevated', className)} aria-label="Index tape" role="marquee">36 <div className="pointer-events-none absolute inset-y-0 left-0 z-10 w-8 bg-gradient-to-r from-elevated to-transparent" aria-hidden />37 <div className="pointer-events-none absolute inset-y-0 right-0 z-10 w-8 bg-gradient-to-l from-elevated to-transparent" aria-hidden />38 <div className="tape-track flex w-max">39 {items}40 {items.map((it, k) => (41 <span key={`dup-${k}`} aria-hidden className="contents">42 {it}43 </span>44 ))}45 </div>46 </div>47 );48}49