docs/DITHER.md
Market value research
The Exchange's Where the GP is panel ranks actual, filtered, loaded market items by buy-order GP, sell-order GP, or executed trade value in the selected period. Three leaders are shown by default; expand to five or collapse the panel. This replaces the decorative Market Pulse ribbon.
Click a bar to open the item's Charts dossier, star an item to toggle the shared persistent watchlist, or use Compare with AI to prepare a research prompt with the metric, exact leader values, window, timestamps and coverage. The user still sends the prompt. The chart follows the existing exchange feed and filters; no extra collector or artificial values are introduced. Changing the metric ranks the loaded subset, not the entire economy. Unknown values are excluded and counted; observed zero is distinct from unknown. Open-order value is aggregated across prices and does not establish executable depth or profitability.
Frosted owns the Card, Heading, Text, Select and Button components, spacing, colors and interaction states. The dither is a static two-pixel dot fill inside data bars, built using dithercn fillStyle. Bar widths share a linear zero-based GP scale; actual values remain readable HTML. No WebGL or animation runs for the panel, including under reduced motion. Blue denotes turnover, green buy commitments, amber sell listings; labels carry the meaning independently of color.
Implementation: src/blackrock/MarketPulse.tsx, market-pulse.css, market-pulse-model.ts. Tests protect ranking, scale and unknown handling. Engine: src/lib/dither; agent skills: .agents/skills/dithercn and .claude/skills/dithercn. Tailwind v4 provides engine utilities without Preflight; Frosted remains the application design system. components.json points at src/dither-theme.css.
Engine compatibility: two toSorted calls in shader.tsx and export.ts use sort on freshly allocated arrays, preserving the app's ES2022 target without mutating inputs.
For visual QA, run pnpm exec vite --config vite.dither.config.ts and open /dither-preview.html. The fixture uses clearly labeled recorded samples and local-only actions, with light/dark Frosted controls. It is not in the production build. Validate the actual exchange at http://127.0.0.1:5197/#market as well. Production remains dark; the component supports both themes.
Chart rollout · October 26
blackrock/DitherChart.tsx owns static SVG patterns, solid-cap bars with a tiny-bar fallback, and the shared Frosted tooltip. React instance IDs isolate patterns across charts and dossiers. MarketCharts uses this for order totals, trade volume and sparse VWAP fill; bid/ask remain solid/dashed step lines with exact samples available. The Units/GP readout uses the same series as the bars.
Economy contributions use signed patterned bars and keyboard-accessible item inspection, with a zero reference; the index keeps a clear line and reference at 100. Assistant evidence charts share the Frosted tooltip. Existing date gaps and calculation semantics remain intact.
SwarmCharts.tsx adds activity filtering and a history slider with exact interval evidence. The upper timeline is normalized activity share; the lower strip is observed / known expected member-seconds from retained summaries. Unknown expected coverage stays unknown. Patterned Unknown activity is different from an empty collection interval. The range slider provides one keyboard stop instead of hundreds of column stops. Explicit grid alignment isolates these bars from the world shell's generic button centering styles.
The expanded development fixture reads market/economy data through a loopback proxy to 5197, alongside labeled example swarms and recorded leaders. Start the normal local app first. It supports light/dark component QA; production retains its current dark theme. No chart shader, animation loop or added collection cadence is used.
Shared server population · October 27
src/LivePopulation.tsx is mounted once in the shared mode dock across Palantir and Blackrock. It displays the global online-player roster count, independent of map filters, teams, player selection and bank previews. Palantir reuses its existing /api/state poll; Blackrock polls the small /api/population projection once per second without retrieving player/NPC arrays or opening another upstream connection. The projection exposes status, readiness, count, last roster receipt and server time only.
Freshness uses roster age (10-second cutoff), server time plus elapsed browser time, connection status and request errors. The last count remains labeled Last known if data becomes stale; unknown never becomes zero. The two-pixel dither mark has a slow 3.8-second breathing layer and a 3.2-second upward dot sweep while the roster is fresh. Both stop when data is stale, the tab is hidden, or reduced motion is enabled. It is not a fabricated activity graph, capacity gauge or population history. Reduced motion removes the transition; readable numbers/status remain HTML. Frosted owns the badge and semantic colors. Mobile places the count in a centered second header row.
shared/population.ts and scripts/population.test.ts protect global-count freshness, zero vs unknown, disconnection and stale browser responses. The existing /dither-preview.html includes this component for light/dark theme checks against the local service. Production remains dark themed.