quotacap 0.0.28 → 0.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useRef, useState } from "react";
3
3
  const STATES = [
4
- { label: "On track", cls: "pace-ontrack", meaning: "Usage aligns with time (±20%)" },
4
+ { label: "On track", cls: "pace-ontrack", meaning: "Burning at a rate the window sustains" },
5
5
  { label: "Behind pace", cls: "pace-behind", meaning: "Burning slow; risk of unused quota waste" },
6
6
  { label: "Ahead of pace", cls: "pace-ahead", meaning: "Burning faster than time; monitor usage" },
7
7
  { label: "Cap risk", cls: "pace-cap", meaning: "Will hit cap before reset window closes" },
8
+ { label: "Measuring", cls: "pace-out", meaning: "Not enough data yet; pace appears after 6h" },
8
9
  { label: "Not reporting", cls: "pace-out", meaning: "No usable reading; excluded from ranking" },
9
10
  ];
10
11
  export function PacingLegend() {
@@ -28,7 +29,7 @@ export function PacingLegend() {
28
29
  document.removeEventListener("keydown", onKey);
29
30
  };
30
31
  }, [open]);
31
- return (_jsxs("div", { className: "legend-wrap", ref: rootRef, children: [_jsx("button", { type: "button", className: "legend-btn", "aria-expanded": open, "aria-controls": "pacing-legend", onClick: () => setOpen((v) => !v), children: "Pacing Legend \u25BE" }), open && (_jsxs("div", { id: "pacing-legend", className: "legend-popover", role: "dialog", "aria-label": "Pacing legend", children: [_jsxs("div", { className: "legend-head", children: [_jsx("b", { children: "Pacing Scale Legend" }), _jsx("button", { type: "button", className: "legend-close", "aria-label": "Close pacing legend", onClick: () => setOpen(false), children: "\u00D7" })] }), _jsx("p", { className: "legend-intro", children: "Pacing measures quota burn against elapsed window time:" }), _jsx("div", { className: "legend-rows", children: STATES.map((s) => (_jsxs("div", { className: "legend-row", children: [_jsx("span", { className: `pace ${s.cls}`, children: s.label }), _jsx("span", { children: s.meaning })] }, s.label))) }), _jsxs("div", { className: "legend-foot", children: [_jsx("code", { children: "\u2588" }), " allowance used \u00B7 ", _jsx("code", { children: "\u2502" }), " time elapsed \u00B7 ", _jsx("code", { children: "\u2591" }), " projected waste"] })] }))] }));
32
+ return (_jsxs("div", { className: "legend-wrap", ref: rootRef, children: [_jsx("button", { type: "button", className: "legend-btn", "aria-expanded": open, "aria-controls": "pacing-legend", onClick: () => setOpen((v) => !v), children: "Pacing Legend \u25BE" }), open && (_jsxs("div", { id: "pacing-legend", className: "legend-popover", role: "dialog", "aria-label": "Pacing legend", children: [_jsxs("div", { className: "legend-head", children: [_jsx("b", { children: "Pacing Scale Legend" }), _jsx("button", { type: "button", className: "legend-close", "aria-label": "Close pacing legend", onClick: () => setOpen(false), children: "\u00D7" })] }), _jsx("p", { className: "legend-intro", children: "Pacing measures quota burn against elapsed window time:" }), _jsx("div", { className: "legend-rows", children: STATES.map((s) => (_jsxs("div", { className: "legend-row", children: [_jsx("span", { className: `pace ${s.cls}`, children: s.label }), _jsx("span", { children: s.meaning })] }, s.label))) }), _jsxs("div", { className: "legend-foot", children: [_jsx("code", { children: "\u2588" }), " allowance used \u00B7 ", _jsx("code", { children: "\u2502" }), " time elapsed \u00B7 ", _jsx("code", { children: "\u2591" }), " projected waste"] }), _jsx("div", { className: "legend-foot", children: "Avg = used \u00F7 days elapsed \u00B7 24h = burn over the last day \u00B7 Ideal = remaining \u00F7 days left" })] }))] }));
32
33
  }
33
34
  function servingHost() {
34
35
  try {
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ageDuration } from "../state.js";
3
- import { Badge, PaceBar, isEstimated, resetClock, resetCountdown, timeLeft, } from "./PaceBar.js";
3
+ import { Badge, PACE_TIPS, PaceBar, isEstimated, paceCells, resetClock, resetCountdown, timeLeft, } from "./PaceBar.js";
4
4
  import { ProviderIcon, providerTint } from "./ProviderIcon.js";
5
5
  function resetsDate(provider) {
6
6
  if (!provider.quota)
@@ -13,6 +13,7 @@ function resetsDate(provider) {
13
13
  export function ProviderCard({ provider, recommended, asOf, onSelect, }) {
14
14
  const quota = provider.quota;
15
15
  const advisory = provider.advisory;
16
+ const pace = paceCells(advisory);
16
17
  const asOfMs = Date.parse(asOf);
17
18
  const updated = ageDuration(provider.ageMs);
18
19
  const resetsIn = quota ? timeLeft(quota.resetsAt, asOfMs) : null;
@@ -22,5 +23,5 @@ export function ProviderCard({ provider, recommended, asOf, onSelect, }) {
22
23
  e.preventDefault();
23
24
  onSelect(provider.id);
24
25
  }
25
- }, className: `pcard ${recommended ? "is-recommended is-top-pick" : ""}`, children: [_jsxs("div", { className: "pcard-head", children: [_jsx("span", { className: "picon", style: providerTint(provider.id), "aria-hidden": "true", children: _jsx(ProviderIcon, { id: provider.id, title: name }) }), _jsxs("div", { className: "who", children: [_jsxs("b", { children: [name, recommended && (_jsx("span", { className: "rec-icon", title: "Recommended for next session", role: "img", "aria-label": "recommended", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.3", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "m12 3-1.9 5.8a2 2 0 0 1-1.3 1.3L3 12l5.8 1.9a2 2 0 0 1 1.3 1.3L12 21l1.9-5.8a2 2 0 0 1 1.3-1.3L21 12l-5.8-1.9a2 2 0 0 1-1.3-1.3z" }) }) }))] }), quota && quota.plan && _jsx("span", { className: "pl", children: quota.plan }), updated && _jsxs("span", { className: "src", children: ["Updated ", updated, " ago"] })] }), _jsx(Badge, { provider: provider })] }), _jsxs("div", { className: "pcard-body", children: [_jsx(PaceBar, { provider: provider, asOf: asOf }), _jsxs("div", { className: "pstats", children: [_jsxs("div", { children: [_jsx("span", { className: "l", children: "Pace" }), _jsx("span", { className: "v", children: advisory && advisory.burnRate !== null ? `${advisory.burnRate.toFixed(1)}%/d` : "—" })] }), _jsxs("div", { children: [_jsx("span", { className: "l", children: "Needed" }), _jsx("span", { className: "v", children: advisory ? `${advisory.idealRate.toFixed(1)}%/d` : "—" })] }), _jsxs("div", { children: [_jsx("span", { className: "l", children: "Resets in" }), _jsx("span", { className: "v", children: resetsIn ? `${resetsIn}${isEstimated(provider) ? " (est.)" : ""}` : resetCountdown(provider, asOfMs) })] })] })] }), _jsxs("div", { className: "pcard-foot", children: [_jsx("span", { children: resetsDate(provider) ?? resetCountdown(provider, asOfMs) }), _jsx("span", { className: "rowbtn", "aria-hidden": "true", children: "Inspect" })] })] }));
26
+ }, className: `pcard ${recommended ? "is-recommended is-top-pick" : ""}`, children: [_jsxs("div", { className: "pcard-head", children: [_jsx("span", { className: "picon", style: providerTint(provider.id), "aria-hidden": "true", children: _jsx(ProviderIcon, { id: provider.id, title: name }) }), _jsxs("div", { className: "who", children: [_jsxs("b", { children: [name, recommended && (_jsx("span", { className: "rec-icon", title: "Recommended for next session", role: "img", "aria-label": "recommended", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.3", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "m12 3-1.9 5.8a2 2 0 0 1-1.3 1.3L3 12l5.8 1.9a2 2 0 0 1 1.3 1.3L12 21l1.9-5.8a2 2 0 0 1 1.3-1.3L21 12l-5.8-1.9a2 2 0 0 1-1.3-1.3z" }) }) }))] }), quota && quota.plan && _jsx("span", { className: "pl", children: quota.plan }), updated && _jsxs("span", { className: "src", children: ["Updated ", updated, " ago"] })] }), _jsx(Badge, { provider: provider })] }), _jsxs("div", { className: "pcard-body", children: [_jsx(PaceBar, { provider: provider, asOf: asOf }), _jsxs("div", { className: "pstats", children: [_jsxs("div", { title: PACE_TIPS.avg, children: [_jsx("span", { className: "l", children: "Avg pace" }), _jsx("span", { className: "v", children: pace.avg })] }), _jsxs("div", { title: PACE_TIPS.recent, children: [_jsx("span", { className: "l", children: "24h pace" }), _jsx("span", { className: "v", children: pace.recent })] }), _jsxs("div", { title: PACE_TIPS.ideal, children: [_jsx("span", { className: "l", children: "Ideal pace" }), _jsx("span", { className: "v", children: advisory ? `${advisory.idealRate.toFixed(1)}%/day` : "—" })] }), _jsxs("div", { children: [_jsx("span", { className: "l", children: "Resets in" }), _jsx("span", { className: "v", children: resetsIn ? `${resetsIn}${isEstimated(provider) ? " (est.)" : ""}` : resetCountdown(provider, asOfMs) })] })] })] }), _jsxs("div", { className: "pcard-foot", children: [_jsx("span", { children: resetsDate(provider) ?? resetCountdown(provider, asOfMs) }), _jsx("span", { className: "rowbtn", "aria-hidden": "true", children: "Inspect" })] })] }));
26
27
  }
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useRef, useState } from "react";
3
3
  import { ageDuration, providerSubtitle } from "../state.js";
4
- import { Badge, PaceBar, barGeometry, isEstimated, paceBadge, resetClock, timeLeft, } from "./PaceBar.js";
4
+ import { Badge, PaceBar, barGeometry, isEstimated, paceBadge, paceFigures, resetClock, timeLeft, } from "./PaceBar.js";
5
5
  import { ProviderIcon, providerTint } from "./ProviderIcon.js";
6
6
  import { renameProvider } from "../api.js";
7
7
  export function exclusionWords(reason) {
@@ -122,6 +122,8 @@ export function pacingStatusToken(provider) {
122
122
  return "ahead";
123
123
  case "Cap risk":
124
124
  return "cap";
125
+ case "Measuring":
126
+ return "measuring";
125
127
  case "Not reporting":
126
128
  return "out";
127
129
  }
@@ -153,11 +155,21 @@ export function rankingCopy(provider, recommendation) {
153
155
  if (!advisory || advisory.paceSource === "unknown" || advisory.burnRate === null) {
154
156
  pace = modelFailure(provider) ?? "No current pace.";
155
157
  }
156
- else if (advisory.status === "at risk") {
157
- pace = `${advisory.burnRate.toFixed(1)}%/day so far this window, against a ${advisory.idealRate.toFixed(1)}%/day target.`;
158
+ else if (advisory.remaining <= 0) {
159
+ pace = `Exhausted at ${quota?.usedPct ?? 100}% used.${stamp ? ` Resets ${stamp}.` : ""}`;
158
160
  }
159
161
  else {
160
- pace = `${advisory.burnRate.toFixed(1)}%/day so far this window. Finishing it needs ${advisory.idealRate.toFixed(1)}%/day.`;
162
+ const { avg, recent } = paceFigures(advisory);
163
+ const figures = avg !== null && recent !== null && avg.toFixed(1) !== recent.toFixed(1)
164
+ ? `${avg.toFixed(1)}%/day window average and ${recent.toFixed(1)}%/day over the last 24h`
165
+ : avg !== null
166
+ ? `${avg.toFixed(1)}%/day window average`
167
+ : `${recent.toFixed(1)}%/day over the last 24h`;
168
+ const ideal = `${advisory.idealRate.toFixed(1)}%/day`;
169
+ pace =
170
+ advisory.status === "at risk"
171
+ ? `${figures}, against an ideal pace of ${ideal}.`
172
+ : `${figures}. The ideal pace to finish is ${ideal}.`;
161
173
  }
162
174
  let decision;
163
175
  if (provider.exclusionReason) {
@@ -1,12 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Badge, PaceBar, evidenceLabels, forecastLine, resetCountdown, } from "./PaceBar.js";
2
+ import { Badge, PaceBar, forecastLine, paceLines, resetCell, } from "./PaceBar.js";
3
3
  export function ProviderRow({ provider, recommended, asOf, onSelect, }) {
4
4
  const quota = provider.quota;
5
5
  const advisory = provider.advisory;
6
6
  const asOfMs = Date.parse(asOf);
7
- const evidence = evidenceLabels(provider.evidence);
7
+ const lines = paceLines(advisory);
8
8
  const name = provider.displayName;
9
- return (_jsxs("div", { "data-testid": `provider-row-${provider.id}`, className: `lrow ${recommended ? "is-recommended is-top-pick" : ""}`, onClick: () => onSelect(provider.id), children: [_jsxs("div", { className: "prov", "data-label": "Provider", children: [_jsx("span", { className: "dot", style: { background: `var(--p-${provider.id.split(":")[0]}, var(--surface-raised))` }, "aria-hidden": "true" }), _jsxs("span", { children: [_jsxs("span", { className: "nm", children: [name, recommended && (_jsx("span", { className: "rec-icon", title: "Recommended for next session", role: "img", "aria-label": "recommended", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.3", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "m12 3-1.9 5.8a2 2 0 0 1-1.3 1.3L3 12l5.8 1.9a2 2 0 0 1 1.3 1.3L12 21l1.9-5.8a2 2 0 0 1 1.3-1.3L21 12l-5.8-1.9a2 2 0 0 1-1.3-1.3z" }) }) }))] }), quota?.plan && _jsx("span", { className: "pl", children: quota.plan }), quota?.sessionPct !== undefined && quota.sessionPct !== null && (_jsxs("span", { className: "src", children: ["Session use ", quota.sessionPct, "%"] }))] })] }), _jsx("div", { "data-label": "Used vs elapsed", children: quota ? _jsx(PaceBar, { provider: provider, asOf: asOf }) : "—" }), _jsx("div", { "data-label": "Resets in", children: _jsx("span", { className: "cell-b", children: resetCountdown(provider, asOfMs) }) }), _jsxs("div", { "data-label": "Pace", children: [_jsx(Badge, { provider: provider }), advisory && advisory.burnRate !== null && (_jsxs("div", { className: "cell-s", style: { marginTop: 2 }, children: ["Pace ", advisory.burnRate.toFixed(1), "%/d \u00B7 needed ", advisory.idealRate.toFixed(1), "%/d"] })), evidence.length > 0 && _jsx("div", { className: "cell-s", style: { marginTop: 2 }, children: evidence.join(" · ") })] }), _jsx("button", { type: "button", className: "rowbtn", onClick: (e) => {
9
+ return (_jsxs("div", { "data-testid": `provider-row-${provider.id}`, className: `lrow ${recommended ? "is-recommended is-top-pick" : ""}`, onClick: () => onSelect(provider.id), children: [_jsxs("div", { className: "prov", "data-label": "Provider", children: [_jsx("span", { className: "dot", style: { background: `var(--p-${provider.id.split(":")[0]}, var(--surface-raised))` }, "aria-hidden": "true" }), _jsxs("span", { children: [_jsxs("span", { className: "nm", children: [name, recommended && (_jsx("span", { className: "rec-icon", title: "Recommended for next session", role: "img", "aria-label": "recommended", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.3", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "m12 3-1.9 5.8a2 2 0 0 1-1.3 1.3L3 12l5.8 1.9a2 2 0 0 1 1.3 1.3L12 21l1.9-5.8a2 2 0 0 1 1.3-1.3L21 12l-5.8-1.9a2 2 0 0 1-1.3-1.3z" }) }) }))] }), quota?.plan && _jsx("span", { className: "pl", children: quota.plan }), quota?.sessionPct !== undefined && quota.sessionPct !== null && (_jsxs("span", { className: "src", children: ["Session use ", quota.sessionPct, "%"] }))] })] }), _jsx("div", { "data-label": "Used vs elapsed", children: quota ? _jsx(PaceBar, { provider: provider, asOf: asOf }) : "—" }), _jsx("div", { "data-label": "Reset", children: _jsx("span", { className: "cell-b", children: resetCell(provider, asOfMs) }) }), _jsxs("div", { "data-label": "Pace", children: [_jsx(Badge, { provider: provider }), lines.length > 0 && (_jsx("div", { style: { marginTop: 2 }, children: lines.map((l) => (_jsxs("div", { className: "cell-s paceline", title: l.tip, children: [_jsx("span", { children: l.label }), _jsx("span", { className: "cell-b", children: l.value })] }, l.label))) }))] }), _jsx("button", { type: "button", className: "rowbtn", onClick: (e) => {
10
10
  e.stopPropagation();
11
11
  onSelect(provider.id);
12
12
  }, children: "Inspect" }), _jsx("span", { className: "sr-only", children: forecastLine(provider) })] }));
@@ -6,7 +6,7 @@ const RAIL_MS = RAIL_DAYS * 24 * 60 * 60 * 1000;
6
6
  /** Pins within this span of rail group into one collision window. */
7
7
  const COLLISION_PCT = 3;
8
8
  /** Pins per window before they group into a cluster pin. */
9
- const WINDOW_CAPACITY = 2;
9
+ const WINDOW_CAPACITY = 3;
10
10
  /**
11
11
  * Place reset pins proportionally over the next 7 days from `asOf`.
12
12
  * Crowded windows past tier capacity group into clusters; resets beyond the
@@ -102,5 +102,5 @@ export function SubscriptionList({ providers, recommendation, asOf, lastComplete
102
102
  const asOfMs = Date.parse(asOf);
103
103
  const ranked = enabled.filter((p) => p.exclusionReason === null);
104
104
  const excluded = enabled.filter((p) => p.exclusionReason !== null);
105
- return (_jsxs("section", { "aria-label": "Subscriptions", children: [_jsxs("div", { className: "section-head", children: [_jsx("h2", { children: "All subscriptions" }), _jsxs("div", { className: "section-head-controls", children: [_jsx(SortDropdown, { value: sortKey, onChange: setSortKey }), _jsxs("div", { role: "group", "aria-label": "Display density", className: "seg", children: [_jsxs("button", { type: "button", "aria-pressed": effective === "cards", onClick: () => setDensity("cards"), children: [_jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: [_jsx("rect", { x: "3", y: "3", width: "8", height: "8", rx: "2" }), _jsx("rect", { x: "13", y: "3", width: "8", height: "8", rx: "2" }), _jsx("rect", { x: "3", y: "13", width: "8", height: "8", rx: "2" }), _jsx("rect", { x: "13", y: "13", width: "8", height: "8", rx: "2" })] }), "Cards"] }), _jsxs("button", { type: "button", "aria-pressed": effective === "table", onClick: () => setDensity("table"), children: [_jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: [_jsx("rect", { x: "3", y: "5", width: "18", height: "2.6", rx: "1.3" }), _jsx("rect", { x: "3", y: "11", width: "18", height: "2.6", rx: "1.3" }), _jsx("rect", { x: "3", y: "17", width: "18", height: "2.6", rx: "1.3" })] }), "Table"] })] })] })] }), effective === "cards" ? (_jsx("div", { "data-testid": "cards-grid", className: "cards cards-grid", children: enabled.map((p) => (_jsx(ProviderCard, { provider: p, recommended: p.id === recommendation.use, asOf: asOf, onSelect: onSelectProvider }, p.id))) })) : (_jsx("div", { className: "table-scroll", children: _jsxs("div", { "data-testid": "ledger-table", className: "ledger", role: "table", children: [_jsxs("div", { className: "lrow lhead", role: "row", children: [_jsx("span", { role: "columnheader", children: "Provider" }), _jsx("span", { role: "columnheader", children: "Used vs elapsed" }), _jsx("span", { role: "columnheader", children: "Resets in" }), _jsx("span", { role: "columnheader", children: "Pace" }), _jsx("span", { role: "columnheader" })] }), enabled.map((p) => (_jsx(ProviderRow, { provider: p, recommended: p.id === recommendation.use, asOf: asOf, onSelect: onSelectProvider }, p.id)))] }) })), _jsxs("footer", { className: "health", children: [_jsxs("ul", { children: [_jsxs("li", { className: "legend-rec", children: [_jsx("svg", { className: "legend-star", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.3", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "m12 3-1.9 5.8a2 2 0 0 1-1.3 1.3L3 12l5.8 1.9a2 2 0 0 1 1.3 1.3L12 21l1.9-5.8a2 2 0 0 1 1.3-1.3L21 12l-5.8-1.9a2 2 0 0 1-1.3-1.3z" }) }), _jsx("span", { children: "Recommended to use next" })] }), _jsxs("li", { children: [_jsx("span", { className: "dot", style: { background: "var(--good)" } }), _jsxs("span", { children: [ranked.length, " used in ranking"] })] }), excluded.length > 0 && (_jsxs("li", { children: [_jsx("span", { className: "dot", style: { background: "var(--fill-out)" } }), _jsxs("span", { children: [excluded.length, " not reporting", excluded.length <= 2 ? ` · ${excluded.map((p) => p.displayName).join(", ")}` : ""] })] }))] }), _jsx("span", { children: nextRefreshLabel(lastCompletedPollAt, polling) })] }), disabled.length > 0 && (_jsxs("section", { "aria-label": "Disabled providers", children: [_jsxs("h3", { children: ["Disabled (", disabled.length, ")"] }), _jsx("ul", { children: disabled.map((p) => (_jsxs("li", { style: { fontSize: "var(--t-2)" }, children: [p.displayName, " \u00B7 disabled \u00B7 ", resetCountdown(p, asOfMs)] }, p.id))) })] }))] }));
105
+ return (_jsxs("section", { "aria-label": "Subscriptions", children: [_jsxs("div", { className: "section-head", children: [_jsx("h2", { children: "All subscriptions" }), _jsxs("div", { className: "section-head-controls", children: [_jsx(SortDropdown, { value: sortKey, onChange: setSortKey }), _jsxs("div", { role: "group", "aria-label": "Display density", className: "seg", children: [_jsxs("button", { type: "button", "aria-pressed": effective === "cards", onClick: () => setDensity("cards"), children: [_jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: [_jsx("rect", { x: "3", y: "3", width: "8", height: "8", rx: "2" }), _jsx("rect", { x: "13", y: "3", width: "8", height: "8", rx: "2" }), _jsx("rect", { x: "3", y: "13", width: "8", height: "8", rx: "2" }), _jsx("rect", { x: "13", y: "13", width: "8", height: "8", rx: "2" })] }), "Cards"] }), _jsxs("button", { type: "button", "aria-pressed": effective === "table", onClick: () => setDensity("table"), children: [_jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: [_jsx("rect", { x: "3", y: "5", width: "18", height: "2.6", rx: "1.3" }), _jsx("rect", { x: "3", y: "11", width: "18", height: "2.6", rx: "1.3" }), _jsx("rect", { x: "3", y: "17", width: "18", height: "2.6", rx: "1.3" })] }), "Table"] })] })] })] }), effective === "cards" ? (_jsx("div", { "data-testid": "cards-grid", className: "cards cards-grid", children: enabled.map((p) => (_jsx(ProviderCard, { provider: p, recommended: p.id === recommendation.use, asOf: asOf, onSelect: onSelectProvider }, p.id))) })) : (_jsx("div", { className: "table-scroll", children: _jsxs("div", { "data-testid": "ledger-table", className: "ledger", role: "table", children: [_jsxs("div", { className: "lrow lhead", role: "row", children: [_jsx("span", { role: "columnheader", children: "Provider" }), _jsx("span", { role: "columnheader", children: "Used vs elapsed" }), _jsx("span", { role: "columnheader", children: "Reset" }), _jsx("span", { role: "columnheader", children: "Pace" }), _jsx("span", { role: "columnheader" })] }), enabled.map((p) => (_jsx(ProviderRow, { provider: p, recommended: p.id === recommendation.use, asOf: asOf, onSelect: onSelectProvider }, p.id)))] }) })), _jsxs("footer", { className: "health", children: [_jsxs("ul", { children: [_jsxs("li", { className: "legend-rec", children: [_jsx("svg", { className: "legend-star", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.3", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "m12 3-1.9 5.8a2 2 0 0 1-1.3 1.3L3 12l5.8 1.9a2 2 0 0 1 1.3 1.3L12 21l1.9-5.8a2 2 0 0 1 1.3-1.3L21 12l-5.8-1.9a2 2 0 0 1-1.3-1.3z" }) }), _jsx("span", { children: "Recommended to use next" })] }), _jsxs("li", { children: [_jsx("span", { className: "dot", style: { background: "var(--good)" } }), _jsxs("span", { children: [ranked.length, " used in ranking"] })] }), excluded.length > 0 && (_jsxs("li", { children: [_jsx("span", { className: "dot", style: { background: "var(--fill-out)" } }), _jsxs("span", { children: [excluded.length, " not reporting", excluded.length <= 2 ? ` · ${excluded.map((p) => p.displayName).join(", ")}` : ""] })] }))] }), _jsx("span", { children: nextRefreshLabel(lastCompletedPollAt, polling) })] }), disabled.length > 0 && (_jsxs("section", { "aria-label": "Disabled providers", children: [_jsxs("h3", { children: ["Disabled (", disabled.length, ")"] }), _jsx("ul", { children: disabled.map((p) => (_jsxs("li", { style: { fontSize: "var(--t-2)" }, children: [p.displayName, " \u00B7 disabled \u00B7 ", resetCountdown(p, asOfMs)] }, p.id))) })] }))] }));
106
106
  }
@@ -9,6 +9,8 @@ export interface AdvisoryView {
9
9
  remaining: number;
10
10
  idealRate: number;
11
11
  burnRate: number | null;
12
+ /** Window-average pace (used % ÷ days elapsed); null before the window start is known. */
13
+ avgPace: number | null;
12
14
  burnMeasured: boolean;
13
15
  paceSource: PaceSource;
14
16
  daysToExhaust: number | null;