import type { StageTone } from "./stageStatus"; // The line invents no colours. Every value below is one of the semantic tokens // the repo already carries across the two bases, light and dark // (common/styles/tokens.css); a bespoke hue here would be wrong on every base // at once. export const STATION_DOT: Record = { // A station with nothing to say is an outline, not a filled dot: "○" in the // sketch. Notably this is also where a DISABLED lane lands — see the tone rule // in channelFlow.ts. neutral: "border border-border-strong bg-transparent", ok: "bg-success", attention: "bg-warning", danger: "bg-destructive", // The travelling pulse. The only animated thing on the page. running: "bg-info animate-pulse", }; export const STATION_TEXT: Record = { neutral: "text-muted-foreground", ok: "text-foreground", attention: "text-warning", danger: "text-destructive", running: "text-info", }; export function formatCount(n: number | null): string { // "—", never "0". A zero here would claim a measurement nobody took. return n == null ? "—" : n.toLocaleString(); } export function formatCoverage(coverage: number | null): string { if (coverage == null) return "—"; const pct = coverage * 100; // Whole percents once you are past 10% — the third significant figure on // "94.37%" is noise at this size. Below that, one decimal, because the // difference between 6.8% and 6% is the difference between a sweep that is // moving and one that is not. return `${pct >= 10 ? Math.round(pct) : Math.round(pct * 10) / 10}%`; }