From c3f19f79f66054dc3b3a98999ea38b0f05248e06 Mon Sep 17 00:00:00 2001
From: Tyler Hoang <tyler@tylerhoang.xyz>
Date: Sun, 17 May 2026 13:36:57 -0700
Subject: Refine overview ratios and shell

---
 frontend/app/page.tsx | 48 ++++++++++++++++++++++++++++++++++--------------
 1 file changed, 34 insertions(+), 14 deletions(-)

(limited to 'frontend/app/page.tsx')

diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx
index 02bd706..41408b0 100644
--- a/frontend/app/page.tsx
+++ b/frontend/app/page.tsx
@@ -377,12 +377,12 @@ function SignalCard({ overview }: { overview: TickerOverview }) {
           <h2 className="psm-card-title">Readthrough</h2>
         </div>
       </div>
-      <div className="psm-signal-grid">
+      <div className="psm-signal-list">
         {overview.signals.map((signal) => (
-          <article key={signal.key} className={`psm-signal ${signalTone(signal.state)}`}>
+          <article key={signal.key} className={`psm-signal-row ${signalTone(signal.state)}`}>
             <span className="psm-signal-key">{signal.key}</span>
-            <span className="psm-signal-value">{signal.value}</span>
             <span className="psm-signal-copy">{signal.description}</span>
+            <span className="psm-signal-value">{signal.value}</span>
           </article>
         ))}
       </div>
@@ -392,12 +392,14 @@ function SignalCard({ overview }: { overview: TickerOverview }) {
 
 function DataStatusCard({ overview, missingFields }: { overview: TickerOverview; missingFields: string[] }) {
   const entries = Object.entries(overview.meta.sources).slice(0, 6);
+  const visibleMissing = missingFields.slice(0, 4);
+  const hiddenMissingCount = Math.max(0, missingFields.length - visibleMissing.length);
 
   return (
     <section className="psm-card">
       <div className="psm-card-head">
         <div>
-          <div className="psm-eyebrow">Data Quality</div>
+          <div className="psm-eyebrow">Coverage</div>
           <h2 className="psm-card-title">Coverage</h2>
         </div>
         <span className={`psm-status-chip${overview.meta.is_partial ? " partial" : ""}`}>{overview.meta.status}</span>
@@ -405,7 +407,8 @@ function DataStatusCard({ overview, missingFields }: { overview: TickerOverview;
       <p className="psm-quality-copy">{availableFieldSummary(overview)}</p>
       {overview.meta.is_partial ? (
         <div className="psm-stack">
-          {missingFields.length ? missingFields.slice(0, 8).map((field) => <span key={field} className="psm-field-tag missing">{field}</span>) : null}
+          {missingFields.length ? visibleMissing.map((field) => <span key={field} className="psm-field-tag missing">{field}</span>) : null}
+          {hiddenMissingCount ? <span className="psm-field-tag missing">+{hiddenMissingCount} more</span> : null}
         </div>
       ) : null}
       <div className="psm-source-list">
@@ -433,7 +436,7 @@ function ProfileCard({ overview }: { overview: TickerOverview }) {
       <div className="psm-card-head">
         <div>
           <div className="psm-eyebrow">Company Profile</div>
-          <h2 className="psm-card-title">Context</h2>
+          <h2 className="psm-card-title">Company Profile</h2>
         </div>
       </div>
       <div className="psm-profile-list">
@@ -474,7 +477,7 @@ function ShortInterestCard({ overview }: { overview: TickerOverview }) {
       <div className="psm-card-head">
         <div>
           <div className="psm-eyebrow">Short Interest</div>
-          <h2 className="psm-card-title">Pressure</h2>
+          <h2 className="psm-card-title">Short Interest</h2>
         </div>
       </div>
       <div className="psm-detail-grid">
@@ -488,21 +491,38 @@ function ShortInterestCard({ overview }: { overview: TickerOverview }) {
 }
 
 function StatsCard({ overview }: { overview: TickerOverview }) {
+  const referenceRows = [
+    { label: "Market Cap", value: fmtLarge(overview.stats.market_cap), missing: overview.stats.market_cap == null },
+    { label: "P/E TTM", value: overview.stats.trailing_pe == null ? "-" : `${fmtNumber(overview.stats.trailing_pe)}x`, missing: overview.stats.trailing_pe == null },
+    { label: "EPS TTM", value: fmtCurrency(overview.stats.trailing_eps), missing: overview.stats.trailing_eps == null },
+    { label: "P/B", value: overview.ratios.price_to_book == null ? "-" : `${fmtNumber(overview.ratios.price_to_book)}x`, missing: overview.ratios.price_to_book == null },
+    { label: "P/S", value: overview.ratios.price_to_sales == null ? "-" : `${fmtNumber(overview.ratios.price_to_sales)}x`, missing: overview.ratios.price_to_sales == null },
+    { label: "EV/Sales", value: overview.ratios.ev_to_sales == null ? "-" : `${fmtNumber(overview.ratios.ev_to_sales)}x`, missing: overview.ratios.ev_to_sales == null },
+    { label: "EV/EBITDA", value: overview.ratios.ev_to_ebitda == null ? "-" : `${fmtNumber(overview.ratios.ev_to_ebitda)}x`, missing: overview.ratios.ev_to_ebitda == null },
+    { label: "Gross Margin", value: fmtPct(overview.ratios.gross_margin_ttm), missing: overview.ratios.gross_margin_ttm == null },
+    { label: "Op Margin", value: fmtPct(overview.ratios.operating_margin_ttm), missing: overview.ratios.operating_margin_ttm == null },
+    { label: "Net Margin", value: fmtPct(overview.ratios.net_margin_ttm), missing: overview.ratios.net_margin_ttm == null },
+    { label: "ROE", value: fmtPct(overview.ratios.roe_ttm), missing: overview.ratios.roe_ttm == null },
+    { label: "ROA", value: fmtPct(overview.ratios.roa_ttm), missing: overview.ratios.roa_ttm == null },
+    { label: "ROIC", value: fmtPct(overview.ratios.roic_ttm), missing: overview.ratios.roic_ttm == null },
+    { label: "D/E", value: overview.ratios.debt_to_equity == null ? "-" : `${fmtNumber(overview.ratios.debt_to_equity)}x`, missing: overview.ratios.debt_to_equity == null },
+    { label: "Current Ratio", value: overview.ratios.current_ratio == null ? "-" : `${fmtNumber(overview.ratios.current_ratio)}x`, missing: overview.ratios.current_ratio == null },
+    { label: "Dividend Yield", value: fmtPct(overview.ratios.dividend_yield_ttm), missing: overview.ratios.dividend_yield_ttm == null },
+    { label: "Payout Ratio", value: fmtPct(overview.ratios.dividend_payout_ratio_ttm), missing: overview.ratios.dividend_payout_ratio_ttm == null }
+  ];
+
   return (
     <section className="psm-card">
       <div className="psm-card-head">
         <div>
-          <div className="psm-eyebrow">Overview Stats</div>
+          <div className="psm-eyebrow">Reference</div>
           <h2 className="psm-card-title">Reference</h2>
         </div>
       </div>
       <div className="psm-stat-list">
-        <StatRow label="Market Cap" value={fmtLarge(overview.stats.market_cap)} missing={overview.stats.market_cap == null} />
-        <StatRow label="P/E TTM" value={fmtNumber(overview.stats.trailing_pe)} missing={overview.stats.trailing_pe == null} />
-        <StatRow label="EPS TTM" value={fmtCurrency(overview.stats.trailing_eps)} missing={overview.stats.trailing_eps == null} />
-        <StatRow label="Volume" value={fmtNumber(overview.stats.volume, 0)} missing={overview.stats.volume == null} />
-        <StatRow label="Avg Volume" value={fmtNumber(overview.stats.average_volume, 0)} missing={overview.stats.average_volume == null} />
-        <StatRow label="Beta" value={fmtNumber(overview.stats.beta)} missing={overview.stats.beta == null} />
+        {referenceRows.map((row) => (
+          <StatRow key={row.label} label={row.label} value={row.value} missing={row.missing} />
+        ))}
       </div>
     </section>
   );
-- 
cgit v1.3-2-g0d8e

