';
})
@@ -1531,7 +1541,7 @@ function render(d) {
'
' + fmt(targetBy[pos.symbol]) + '
' +
'
' + rBar(entry, cur, stop) + '
' +
'
' + unrealCell(upnl, pct) + '
' +
- (canCommand ? '
' : '') +
+ (canCommand ? '
' : '') +
'');
}));
$("pos-count").textContent = posRows.length;
diff --git a/docs/UI-REVIEW.md b/docs/UI-REVIEW.md
new file mode 100644
index 0000000..9e05979
--- /dev/null
+++ b/docs/UI-REVIEW.md
@@ -0,0 +1,106 @@
+# UI Review β Momentum Dashboard (`api/static/dashboard.html`)
+
+**Audited**: 2026-07-20 Β· retroactive 6-pillar visual audit (no UI-SPEC exists β
+audited against abstract standards). Adversarial stance: assume failure until
+the code proves otherwise. Scores are 1β4, not averaged upward.
+
+**Scope**: the primary operator dashboard (`dashboard.html`, ~1600 lines,
+single-file inline CSS/JS) plus its siblings `backtest.html` / `admin.html`.
+Method: static analysis of color/spacing/typography tokens, structure, and
+interaction states (the auditor's grep-based method; a headless render pass is
+the standing follow-up).
+
+## Scorecard
+
+| Pillar | Score | One-line verdict |
+|---|---|---|
+| 1. Copywriting | **4** | Domain-precise, explains *why* β not generic |
+| 2. Visuals / hierarchy | **3** | Clear stripβpanel structure; dense but legible |
+| 3. Color | **3** | Real token system, undermined by duplicate semantic colors + 90 hardcoded values |
+| 4. Typography | **3** | Sensible mono scale; 9px floor is too small |
+| 5. Spacing | **2** | No systematic scale β 20 distinct px values incl. arbitrary 7/9/11/13 |
+| 6. Experience design | **4** | Standout β confirm-to-destruct, full empty/loading/error/connection states |
+
+**Overall**: a genuinely competent, purpose-built operator UI. The failures are
+consistency-and-accessibility drift, not structural β this is a good dashboard
+with three fixable rough edges, not a rebuild.
+
+## Findings
+
+### Pillar 1 β Copywriting Β· 4
+Labels state intent, not just nouns: "closest to fire on top", "why each entry
+was taken or refused Β· value β threshold per gate", "held long with no / short
+protective stop". Empty states teach ("No armed gappers β waiting for the open").
+No lorem, no vague "Loadingβ¦" without context. **No fix needed.**
+
+### Pillar 2 β Visuals / hierarchy Β· 3
+Strong top-down hierarchy: risk-strip β P&L-strip β collapsible ``
+panels, colour-coded side pills, sparklines, R-bars. Weakness: extreme density
+(10β11px body across 51 elements) with little whitespace β correct for a trading
+terminal, but the eye has few rest points. **WARNING** β acceptable for the
+audience; revisit if non-expert users are ever a target.
+
+### Pillar 3 β Color Β· 3
+Real foundation: 17 CSS custom properties, 149 `var(--β¦)` uses, coherent dark
+theme, defensible 60/30/10 (bg dominant / panels secondary / `#5ba3ff` accent on
+interactive). **But** two concrete defects:
+- **Duplicate semantic colors** β THREE greens (`#2fbf71`, `#2ecc71`, `#34d17e`)
+ and FOUR reds (`#e5484d`, `#ff4d4f`, `#ff5a60`, `#ff8589`) all meaning
+ "up/good" and "down/bad". These should be one `--green` / `--red` (+ one
+ intentional bright variant), not near-identical one-offs.
+- **90 hardcoded hex values** bypass the token system that already exists.
+**WARNING** β the system is right; application drifted.
+
+### Pillar 4 β Typography Β· 3
+One monospace family (correct for aligned numeric data), a real size ladder
+(9β27px), weight used for hierarchy. Defect: the **9px floor** (4 elements) is
+below comfortable-read and fails WCAG minimums; 10β11px carries most of the UI,
+which is tight. **WARNING** β raise the 9px labels to β₯11px.
+
+### Pillar 5 β Spacing Β· 2 (lowest)
+**20 distinct padding/margin values** including arbitrary `7px`, `9px`, `11px`,
+`13px` with no discernible 4/8 rhythm. Dense layout justifies *tightness*, not
+*arbitrariness* β the values look hand-tuned per element rather than drawn from a
+scale. **WARNING** β adopt a spacing scale (e.g. 2/4/8/12/16/24) and snap values
+to it; the visual result changes little but future edits stay consistent.
+
+### Pillar 6 β Experience design Β· 4 (standout)
+This is where the dashboard earns its keep:
+- **Confirm-to-destruct**: EXIT/FLATTEN/PAUSE use an arm-then-confirm pattern
+ (`armButton`, 8 sites) β no accidental market flatten.
+- **Full state coverage**: 38 loading/loader refs, 20 explicit empty states, 7
+ error/connection-lost handlers ("stream lost β polling", "render error").
+- **Resilience**: SSE with polling fallback, degrade-gracefully panels.
+- **3 `@media` breakpoints** β responsive to phone/tablet.
+**No fix needed** β this pillar is a model for the rest.
+
+### Cross-cutting β Accessibility (drags 2 & 6)
+**0 ARIA roles/labels, only 2 `:focus` styles** on a dashboard whose buttons
+submit real orders (Approve / Reject / EXIT / FLATTEN). Keyboard and
+screen-reader users cannot see focus or understand controls. Not a visual defect
+but a real usability gap for the money-path controls. **WARNING (borderline
+BLOCKER for keyboard operators).**
+
+## Top 3 priority fixes
+
+1. **Collapse duplicate semantic colors + migrate hardcoded values** (Pillar 3).
+ Define `--green`/`--red` (+ one bright variant each), replace the 3 greens / 4
+ reds and the 90 hardcoded hex. Highest consistency-per-effort. *WARNING.*
+2. **Add focus + ARIA to money-path controls** (Accessibility). `:focus-visible`
+ outlines and `aria-label` on Approve/Reject/EXIT/FLATTEN. A keyboard operator
+ currently flies blind on the destructive buttons. *WARNING β BLOCKER for
+ keyboard use.*
+3. **Adopt a spacing scale** (Pillar 5). Snap the 20 ad-hoc px values to a
+ 2/4/8/12/16/24 ladder; raise the 9px type floor to β₯11px. *WARNING.*
+
+## What NOT to touch
+Experience design (Pillar 6) and copywriting (Pillar 1) are strengths β don't
+regress the confirm-to-destruct flow or the explanatory empty states while
+refactoring color/spacing. The density is a deliberate, correct choice for the
+trading-terminal audience; do not "add whitespace" reflexively.
+
+---
+*No UI-SPEC exists for this project. If the dashboard becomes a maintained
+surface, the highest-leverage next step is extracting the existing `:root` tokens
+into a small declared design contract so future changes have a baseline to audit
+against β the token system is 80% there already.*
diff --git a/storage/projections.py b/storage/projections.py
index 1769d19..59a05cb 100644
--- a/storage/projections.py
+++ b/storage/projections.py
@@ -668,6 +668,8 @@ def query_session_pnl(store, session_id: str | None = None,
trades.append(
{
"symbol": payload.get("symbol"),
+ "entry_price": payload.get("entry_price"),
+ "exit_price": payload.get("exit_price"),
"realized_pnl": round(pnl, 2),
"r_multiple": r,
"exit_reason": payload.get("exit_reason"),