Match Horizon mockup structure; restore qualified-first radar
Deploy / lint (push) Successful in 7s
Deploy / test (push) Successful in 1m8s
Deploy / deploy (push) Successful in 35s

Fixes from first prod review of the redesign:

- Top navigation bar (TopBar) replaces the sidebar, like the mockup:
  wordmark + sections + ticker search + jobs/status/logout; content in
  a centered max-width column. MobileNav unchanged.
- Radar panel: qualified setups lead again (the actionable list, as
  the old Top Setups did); non-qualified sit behind an "N below the
  gate" toggle with per-rule reasons, auto-open only when nothing
  qualifies. Adds mini radar fingerprints for the top 3 qualified
  (dimension scores from the rankings endpoint, fixed axis order).
- Dashboard layout: open positions and radar side by side (xl), as in
  the mockup.
- ScoreCard: the radar fingerprint was inside the showComposite block,
  which the ticker page disables - it never rendered. Now it shows
  whenever >= 3 dimensions exist.
- TradeChart: fresh positions with < 2 bars since entry rendered no
  chart; now pads with ~10 pre-entry context bars (gray) and marks the
  entry point. First open position auto-expands so the chart is
  visible without a click.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-10 07:44:55 +02:00
co-authored by Claude Fable 5
parent 20f6981712
commit 02cf9d1cba
8 changed files with 321 additions and 214 deletions
+9 -4
View File
@@ -64,13 +64,14 @@ export function ScoreCard({ compositeScore, dimensions, compositeBreakdown, show
return (
<div className="glass p-5">
{showComposite && (
{(showComposite || dimensions.length >= 3) && (
<div className="flex flex-wrap items-center gap-4">
{compositeScore !== null ? (
{showComposite && (compositeScore !== null ? (
<ScoreRing score={compositeScore} />
) : (
<div className="flex h-[88px] w-[88px] items-center justify-center text-sm text-gray-500">N/A</div>
)}
))}
{showComposite && (
<div>
<p className="text-xs text-gray-500 uppercase tracking-wider">Composite Score</p>
<p className={`text-2xl font-bold ${compositeScore !== null ? scoreColor(compositeScore) : 'text-gray-500'}`}>
@@ -88,8 +89,12 @@ export function ScoreCard({ compositeScore, dimensions, compositeBreakdown, show
</p>
)}
</div>
)}
{dimensions.length >= 3 && (
<div className="ml-auto" title="Score fingerprint — hover a corner for the exact value">
<div
className={showComposite ? 'ml-auto' : 'mx-auto sm:mx-0'}
title="Score fingerprint — hover a corner for the exact value"
>
<RadarChart
axes={dimensions.map((d) => ({
label: d.dimension.length > 9 ? `${d.dimension.slice(0, 8)}.` : d.dimension,