Item 6 — Desk showcase renders REAL data (or hides), kills the mocked ladder
The pricing Desk showcase hardcoded an alt-line ladder (1.5 A +7.1% / 2.5 A+ +11.4% / 4.5 C -3.8%), QUARTER-KELLY 2.4%, and PARLAY φ 0.34 — a mocked demo selling something we weren't proving. - deskShowcaseService reads the pre-graded snapshot for a real A/B prop's alt-line ladder (prefers the one with the most grade variation — the most compelling real example). Edge per rung shows only when it's a plausible market value; the inflated (model-line)/line artifact on small lines is guarded to "—" rather than shown as a fake +91%. - PARLAY φ is now REAL: the model's same-team correlation (0.34, mirroring the frontend parlayMath team constant) computed for TWO REAL same-team legs, named. No real same-team pair on the board → the tile hides, never an invented number. - QUARTER-KELLY tile is REMOVED: the snapshot has no odds, so a real quarter-Kelly % can't be computed here — a fabricated 2.4% is worse than nothing. Kelly stays a real in-app Desk feature; the showcase just doesn't fake it. - DeskShowcase is now a client component fetching /api/desk-showcase; when the board has no real ladder the whole visuals column hides (real-or-hidden, same law as the hero). The pitch copy is unchanged. 5 service tests. Change-affected suites green, web build exit 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -217,6 +217,7 @@ app.use('/api/internal', internalRoutes);
|
||||
app.use('/api/partners', require('./routes/partners'));
|
||||
app.use('/api/founders', require('./routes/founders'));
|
||||
app.use('/api/hero-prop', require('./routes/heroProp'));
|
||||
app.use('/api/desk-showcase', require('./routes/deskShowcase'));
|
||||
|
||||
// Session 10 — Sentry's Express error handler catches uncaught
|
||||
// errors from every route mounted above. Must come AFTER routes but
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* GET /api/desk-showcase (Truth-Everywhere Part 2, item 6) — REAL data for the
|
||||
* pricing Desk showcase (alt-line ladder + same-team correlation). Public,
|
||||
* cache-only. { available:false } when the board has nothing → the visuals hide.
|
||||
*/
|
||||
const express = require('express');
|
||||
const { createRateLimit } = require('../middleware/rateLimit');
|
||||
const deskShowcaseService = require('../services/deskShowcaseService');
|
||||
|
||||
const router = express.Router();
|
||||
router.use(createRateLimit({ windowMs: 60_000, max: 60 }));
|
||||
|
||||
router.get('/', async (req, res) => {
|
||||
try {
|
||||
const data = await deskShowcaseService.getDeskShowcase({});
|
||||
res.set('Cache-Control', 'public, max-age=300');
|
||||
return res.json(data);
|
||||
} catch (err) {
|
||||
console.error('[desk-showcase]', err.message);
|
||||
return res.status(200).json({ available: false });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
@@ -0,0 +1,98 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* deskShowcaseService (Truth-Everywhere Part 2, item 6) — REAL data for the
|
||||
* pricing-page Desk showcase. The ladder/Kelly/phi were hardcoded mocks; this
|
||||
* feeds the flagship demo from the pre-graded snapshot, or returns nothing so
|
||||
* the visuals HIDE (real-or-hidden, same law as the hero). No grading, no
|
||||
* credits — cache reads only.
|
||||
*
|
||||
* - ladder: a real A/B graded prop's alt-line ladder (line + grade; the edge
|
||||
* is shown only when it's a plausible market value, else omitted — the
|
||||
* (model-line)/line metric is huge on 0.5-lines and would look fake).
|
||||
* - parlay: the model's real same-team correlation (0.34, mirrors the frontend
|
||||
* parlayMath team constant) computed for TWO REAL same-team A/B legs. No
|
||||
* real pair on the board → null (hidden), never an invented number.
|
||||
* - kelly: null — the snapshot carries no odds, so a real quarter-Kelly % can't
|
||||
* be computed here. The tile hides rather than show a fabricated 2.4%.
|
||||
*/
|
||||
|
||||
const DEFAULT_SPORTS = ['nba', 'wnba', 'mlb', 'soccer'];
|
||||
const TEAM_CORRELATION = 0.34; // mirrors web parlayMath: same-team pairwise phi
|
||||
const SANE_EDGE_MAX = 40; // beyond this the (model-line)/line value isn't a market edge
|
||||
|
||||
const isAB = (g) => /^[AB]/.test(String(g || '').trim().toUpperCase());
|
||||
const distinctGrades = (ladder) => new Set((ladder || []).map((r) => r.grade)).size;
|
||||
|
||||
function rungsOf(alt) {
|
||||
return (alt || [])
|
||||
.filter((r) => r && Number.isFinite(Number(r.line)) && r.grade)
|
||||
.map((r) => {
|
||||
const edge = Number(r.edge_pct);
|
||||
return {
|
||||
line: Number(r.line),
|
||||
grade: r.grade,
|
||||
base: !!r.base,
|
||||
// guard the small-line artifact: show an edge only when it's plausible
|
||||
edge: Number.isFinite(edge) && Math.abs(edge) <= SANE_EDGE_MAX ? Math.round(edge * 10) / 10 : null,
|
||||
};
|
||||
})
|
||||
.sort((a, b) => a.line - b.line);
|
||||
}
|
||||
|
||||
async function getDeskShowcase(deps = {}) {
|
||||
const cacheGet = deps.cacheGet || require('../utils/redis').cacheGet;
|
||||
const sports = deps.sports || DEFAULT_SPORTS;
|
||||
|
||||
const ab = [];
|
||||
for (const sport of sports) {
|
||||
let grades = null;
|
||||
const snap = await cacheGet(`snapshot:${sport}:latest`);
|
||||
if (snap && Array.isArray(snap.grades)) grades = snap.grades;
|
||||
else {
|
||||
const env = await cacheGet(`grades:${sport}`);
|
||||
if (env && Array.isArray(env.grades)) grades = env.grades;
|
||||
}
|
||||
for (const g of grades || []) {
|
||||
if (!g || g.insufficient_data || !isAB(g.grade)) continue;
|
||||
ab.push({ g, sport });
|
||||
}
|
||||
}
|
||||
|
||||
// Ladder: prefer the prop whose ladder shows the MOST grade variation (the
|
||||
// most compelling REAL example — "A here, C there"), then longest ladder.
|
||||
let best = null, bestScore = -1;
|
||||
for (const { g, sport } of ab) {
|
||||
const rungs = rungsOf(g.alt_lines);
|
||||
if (rungs.length < 2) continue;
|
||||
const score = distinctGrades(rungs) * 100 + rungs.length;
|
||||
if (score > bestScore) { bestScore = score; best = { g, sport, rungs }; }
|
||||
}
|
||||
|
||||
if (!best) return { available: false };
|
||||
|
||||
const ladder = {
|
||||
player: best.g.player_name || best.g.player || null,
|
||||
stat_type: best.g.stat_type || best.g.stat || null,
|
||||
sport: best.sport,
|
||||
rungs: best.rungs,
|
||||
};
|
||||
|
||||
// Parlay phi: two REAL A/B legs on the same (non-null) team.
|
||||
let parlay = null;
|
||||
const byTeam = {};
|
||||
for (const { g } of ab) {
|
||||
const t = g.team ? String(g.team) : null;
|
||||
const name = g.player_name || g.player;
|
||||
if (!t || !name) continue;
|
||||
(byTeam[t] = byTeam[t] || []).push(name);
|
||||
}
|
||||
for (const [team, names] of Object.entries(byTeam)) {
|
||||
const uniq = [...new Set(names)];
|
||||
if (uniq.length >= 2) { parlay = { value: TEAM_CORRELATION, legs: [uniq[0], uniq[1]], team }; break; }
|
||||
}
|
||||
|
||||
return { available: true, ladder, parlay, kelly: null };
|
||||
}
|
||||
|
||||
module.exports = { getDeskShowcase, __internals: { rungsOf, isAB, SANE_EDGE_MAX, TEAM_CORRELATION } };
|
||||
@@ -0,0 +1,63 @@
|
||||
'use strict';
|
||||
|
||||
// Item 6 (Truth-Everywhere Part 2) — the Desk showcase renders REAL snapshot
|
||||
// data (alt-line ladder + same-team correlation) or hides. No mocked numbers.
|
||||
|
||||
const { getDeskShowcase, __internals } = require('../../src/services/deskShowcaseService');
|
||||
|
||||
const cacheFrom = (map) => async (k) => (k in map ? map[k] : null);
|
||||
const grade = (o) => ({
|
||||
player_name: o.player, stat_type: o.stat || 'hits', grade: o.grade,
|
||||
team: o.team || null, alt_lines: o.alt || [],
|
||||
});
|
||||
|
||||
describe('getDeskShowcase', () => {
|
||||
test('renders a real A/B ladder; inflated edges are guarded to null', async () => {
|
||||
const cacheGet = cacheFrom({ 'snapshot:mlb:latest': { grades: [
|
||||
grade({ player: 'Vary', stat: 'strikeouts', grade: 'A', alt: [
|
||||
{ line: 4.5, grade: 'A', edge_pct: 8.2 }, { line: 6.5, grade: 'B', edge_pct: 3.1, base: true }, { line: 8.5, grade: 'C', edge_pct: 91.3 },
|
||||
] }),
|
||||
] } });
|
||||
const out = await getDeskShowcase({ cacheGet, sports: ['mlb'] });
|
||||
expect(out.available).toBe(true);
|
||||
expect(out.ladder.player).toBe('Vary');
|
||||
expect(out.ladder.rungs.map((r) => r.grade)).toEqual(['A', 'B', 'C']); // sorted by line
|
||||
expect(out.ladder.rungs[0].edge).toBe(8.2); // sane edge kept
|
||||
expect(out.ladder.rungs[2].edge).toBeNull(); // 91.3% guarded (artifact, not a market edge)
|
||||
expect(out.kelly).toBeNull(); // no odds → never a fabricated %
|
||||
});
|
||||
|
||||
test('prefers the ladder with the MOST grade variation (best real example)', async () => {
|
||||
const cacheGet = cacheFrom({ 'snapshot:mlb:latest': { grades: [
|
||||
grade({ player: 'Flat', grade: 'B', alt: [{ line: 0.5, grade: 'B' }, { line: 1.5, grade: 'B' }] }),
|
||||
grade({ player: 'Varies', grade: 'A', alt: [{ line: 0.5, grade: 'A' }, { line: 1.5, grade: 'C' }] }),
|
||||
] } });
|
||||
const out = await getDeskShowcase({ cacheGet, sports: ['mlb'] });
|
||||
expect(out.ladder.player).toBe('Varies');
|
||||
});
|
||||
|
||||
test('parlay φ is REAL — the model correlation for two real same-team legs', async () => {
|
||||
const cacheGet = cacheFrom({ 'snapshot:mlb:latest': { grades: [
|
||||
grade({ player: 'Alice', grade: 'A', team: 'NYY', alt: [{ line: 0.5, grade: 'A' }, { line: 1.5, grade: 'B' }] }),
|
||||
grade({ player: 'Bob', grade: 'B', team: 'NYY', alt: [{ line: 0.5, grade: 'B' }, { line: 1.5, grade: 'C' }] }),
|
||||
] } });
|
||||
const out = await getDeskShowcase({ cacheGet, sports: ['mlb'] });
|
||||
expect(out.parlay).toEqual({ value: 0.34, legs: ['Alice', 'Bob'], team: 'NYY' });
|
||||
});
|
||||
|
||||
test('no same-team pair → parlay null (never an invented correlation)', async () => {
|
||||
const cacheGet = cacheFrom({ 'snapshot:mlb:latest': { grades: [
|
||||
grade({ player: 'Solo', grade: 'A', team: 'NYY', alt: [{ line: 0.5, grade: 'A' }, { line: 1.5, grade: 'C' }] }),
|
||||
] } });
|
||||
const out = await getDeskShowcase({ cacheGet, sports: ['mlb'] });
|
||||
expect(out.parlay).toBeNull();
|
||||
});
|
||||
|
||||
test('no A/B ladder anywhere → { available:false } (visuals hide)', async () => {
|
||||
const cacheGet = cacheFrom({ 'snapshot:mlb:latest': { grades: [
|
||||
grade({ player: 'Weak', grade: 'D', alt: [{ line: 0.5, grade: 'D' }] }),
|
||||
] } });
|
||||
const out = await getDeskShowcase({ cacheGet, sports: ['mlb'] });
|
||||
expect(out).toEqual({ available: false });
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:3000';
|
||||
|
||||
/**
|
||||
* Desk-showcase proxy (item 6) — real alt-line ladder + same-team correlation
|
||||
* from the snapshot. Any failure → { available:false } so the visuals hide.
|
||||
*/
|
||||
export async function GET() {
|
||||
try {
|
||||
const upstream = await fetch(`${BACKEND_URL}/api/desk-showcase`, {
|
||||
method: 'GET', headers: { Accept: 'application/json' }, cache: 'no-store',
|
||||
});
|
||||
const data = await upstream.json().catch(() => ({ available: false }));
|
||||
return NextResponse.json(data, { status: 200, headers: { 'Cache-Control': 'public, s-maxage=300, stale-while-revalidate=60' } });
|
||||
} catch {
|
||||
return NextResponse.json({ available: false }, { status: 200 });
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,64 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import SectionHead from '@/components/vyndr/SectionHead';
|
||||
|
||||
/**
|
||||
* DeskShowcase (DS5 · DESIGN-SPEC Part 6, #8) — the Desk-as-hero story that
|
||||
* sits ABOVE the pricing grid. Its job is the founder's one line: make $44.99
|
||||
* feel impossibly low for a professional terminal ("how is this only $44.99"
|
||||
* IS the conversion event). Balanced two-column layout — the pitch on the left,
|
||||
* REAL feature visuals on the right (kills the dead right-half, audit #8). The
|
||||
* single primary CTA scrolls to the grid where the real Stripe checkout lives
|
||||
* (checkout wiring untouched).
|
||||
*
|
||||
* Server component — no interactivity here; the CTA is an in-page anchor and the
|
||||
* feature visuals are static, tokenized, mono-for-data mock readouts.
|
||||
* DeskShowcase (DS5 · DESIGN-SPEC Part 6, #8) — the Desk-as-hero story above the
|
||||
* pricing grid. The pitch (left) is copy; the feature visuals (right) are now
|
||||
* REAL data (Truth-Everywhere Part 2, item 6), fetched from /api/desk-showcase:
|
||||
* - ALT LINE LADDER: a real graded prop's ladder (line + grade; edge only when
|
||||
* it's a plausible market value).
|
||||
* - PARLAY φ: the model's real same-team correlation, computed for two REAL
|
||||
* same-team legs (named).
|
||||
* The old hardcoded ladder / QUARTER-KELLY 2.4% / φ 0.34 mocks are gone. When
|
||||
* the board has no real ladder, the visuals HIDE (real-or-hidden) — the Kelly
|
||||
* tile is dropped entirely (the snapshot has no odds to size from honestly).
|
||||
*/
|
||||
|
||||
// A real alt-line-ladder rung (the Desk exclusive) — line + locked grade + edge.
|
||||
function Rung({ line, grade, edge, base }: { line: string; grade: string; edge: string; base?: boolean }) {
|
||||
const gradeCol = grade.startsWith('A') ? 'var(--g-a)' : grade.startsWith('B') ? 'var(--text-0)' : 'var(--amber)';
|
||||
const edgeCol = edge.startsWith('+') ? 'var(--g-a)' : edge.startsWith('-') ? 'var(--miss)' : 'var(--text-2)';
|
||||
interface Rung { line: number; grade: string; edge: number | null; base?: boolean }
|
||||
interface Showcase {
|
||||
available: boolean;
|
||||
ladder?: { player: string | null; stat_type: string | null; sport?: string; rungs: Rung[] } | null;
|
||||
parlay?: { value: number; legs: string[]; team?: string } | null;
|
||||
}
|
||||
|
||||
const STAT_LABEL: Record<string, string> = {
|
||||
total_bases: 'TB', home_runs: 'HR', hits: 'H', rbi: 'RBI', runs: 'R', doubles: '2B',
|
||||
strikeouts: 'K', points: 'PTS', rebounds: 'REB', assists: 'AST', threes: '3PT',
|
||||
};
|
||||
const statLabel = (s?: string | null) => (s ? (STAT_LABEL[s] || s.replace(/_/g, ' ').toUpperCase()) : '');
|
||||
|
||||
function RungCell({ line, grade, edge, base }: Rung) {
|
||||
const gradeCol = grade.startsWith('A') ? 'var(--g-a)' : grade.startsWith('B') ? 'var(--text-0)' : grade.startsWith('C') ? 'var(--text-1)' : 'var(--miss)';
|
||||
const edgeCol = edge == null ? 'var(--text-2)' : edge >= 0 ? 'var(--g-a)' : 'var(--miss)';
|
||||
return (
|
||||
<div style={{ flex: '1 1 0', minWidth: 58, textAlign: 'center', padding: '9px 6px', background: 'var(--bg-2)', border: `1px solid ${base ? 'var(--border-hi)' : 'var(--border)'}`, borderRadius: 6 }}>
|
||||
<div className="mono" style={{ fontSize: 11, color: base ? 'var(--text-0)' : 'var(--text-1)', marginBottom: 5 }}>{line}{base ? ' •' : ''}</div>
|
||||
<div className="mono" style={{ fontSize: 17, fontWeight: 800, color: gradeCol }}>{grade}</div>
|
||||
<div className="mono" style={{ fontSize: 10, color: edgeCol, marginTop: 3 }}>{edge}</div>
|
||||
<div className="mono" style={{ fontSize: 10, color: edgeCol, marginTop: 3 }}>
|
||||
{edge == null ? '—' : `${edge >= 0 ? '+' : ''}${edge}%`}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function DeskShowcase() {
|
||||
const [data, setData] = useState<Showcase | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
let alive = true;
|
||||
fetch('/api/desk-showcase', { cache: 'no-store' })
|
||||
.then((r) => r.json())
|
||||
.then((d) => { if (alive) setData(d); })
|
||||
.catch(() => { if (alive) setData({ available: false }); });
|
||||
return () => { alive = false; };
|
||||
}, []);
|
||||
|
||||
const ladder = data?.available ? data.ladder : null;
|
||||
const parlay = data?.available ? data.parlay : null;
|
||||
const showVisuals = !!ladder && ladder.rungs.length > 0;
|
||||
|
||||
return (
|
||||
<section style={{ padding: '72px 24px 8px', borderTop: '1px solid var(--border)' }}>
|
||||
<div className="desk-showcase" style={{ maxWidth: 1100, margin: '0 auto', display: 'grid', gap: 40, alignItems: 'center' }}>
|
||||
@@ -56,46 +88,41 @@ export default function DeskShowcase() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* RIGHT — real feature visuals (no dead half) */}
|
||||
<div style={{ display: 'grid', gap: 14 }}>
|
||||
<div style={{ background: 'var(--bg-1)', border: '1px solid var(--border-hi)', borderRadius: 12, padding: 18 }}>
|
||||
<SectionHead style={{ marginBottom: 12 }}>
|
||||
ALT LINE LADDER <span style={{ color: 'var(--amber)', fontSize: 9, border: '1px solid rgba(255,179,71,.4)', borderRadius: 3, padding: '1px 5px', marginLeft: 4 }}>DESK</span>
|
||||
</SectionHead>
|
||||
<div style={{ display: 'flex', gap: 7 }}>
|
||||
<Rung line="1.5" grade="A" edge="+7.1%" />
|
||||
<Rung line="2.5" grade="A+" edge="+11.4%" base />
|
||||
<Rung line="3.5" grade="B" edge="+2.0%" />
|
||||
<Rung line="4.5" grade="C" edge="-3.8%" />
|
||||
{/* RIGHT — REAL feature visuals (hidden when the board has none) */}
|
||||
{showVisuals && (
|
||||
<div style={{ display: 'grid', gap: 14 }}>
|
||||
<div style={{ background: 'var(--bg-1)', border: '1px solid var(--border-hi)', borderRadius: 12, padding: 18 }}>
|
||||
<SectionHead style={{ marginBottom: 4 }}>
|
||||
ALT LINE LADDER <span style={{ color: 'var(--amber)', fontSize: 9, border: '1px solid rgba(255,179,71,.4)', borderRadius: 3, padding: '1px 5px', marginLeft: 4 }}>DESK</span>
|
||||
</SectionHead>
|
||||
<div className="mono" style={{ fontSize: 10.5, color: 'var(--text-2)', marginBottom: 10, letterSpacing: '0.04em' }}>
|
||||
{ladder!.player} · {statLabel(ladder!.stat_type)}
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: 7, flexWrap: 'wrap' }}>
|
||||
{ladder!.rungs.map((r) => <RungCell key={r.line} {...r} />)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gap: 14, gridTemplateColumns: '1fr 1fr' }}>
|
||||
<div style={{ background: 'var(--bg-1)', border: '1px solid var(--border)', borderRadius: 12, padding: 16 }}>
|
||||
<SectionHead style={{ marginBottom: 10 }}>QUARTER-KELLY</SectionHead>
|
||||
<div className="mono" style={{ fontSize: 26, fontWeight: 800, color: 'var(--g-a)', fontVariantNumeric: 'tabular-nums' }}>2.4%</div>
|
||||
<div className="mono" style={{ fontSize: 11, color: 'var(--text-tertiary)', marginTop: 4 }}>of bankroll · at -110</div>
|
||||
</div>
|
||||
<div style={{ background: 'var(--bg-1)', border: '1px solid var(--border)', borderRadius: 12, padding: 16 }}>
|
||||
<SectionHead style={{ marginBottom: 10 }}>PARLAY φ</SectionHead>
|
||||
<div className="mono" style={{ fontSize: 26, fontWeight: 800, color: 'var(--text-0)', fontVariantNumeric: 'tabular-nums' }}>0.34</div>
|
||||
<div className="mono" style={{ fontSize: 11, color: 'var(--text-tertiary)', marginTop: 4 }}>correlation · same-team legs</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* PARLAY φ — real, only when two real same-team legs exist */}
|
||||
{parlay && (
|
||||
<div style={{ background: 'var(--bg-1)', border: '1px solid var(--border)', borderRadius: 12, padding: 16 }}>
|
||||
<SectionHead style={{ marginBottom: 10 }}>PARLAY φ</SectionHead>
|
||||
<div className="mono" style={{ fontSize: 26, fontWeight: 800, color: 'var(--text-0)', fontVariantNumeric: 'tabular-nums' }}>{parlay.value}</div>
|
||||
<div className="mono" style={{ fontSize: 11, color: 'var(--text-tertiary)', marginTop: 4 }}>
|
||||
correlation · {parlay.legs[0]} + {parlay.legs[1]}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Wave 4A (Step 4) — this claim is now BACKED by a real feature: the
|
||||
CONSENSUS vs MODEL strip (components/vyndr/MarketBreadth, fed by
|
||||
lib/marketBreadth.collectBreadth) ships on the live slate/dashboard,
|
||||
computing the median book line vs the model's projection. "live
|
||||
line moves" is the existing snapshot line-deltas / LineSparkline.
|
||||
No longer an empty promise — do not remove without removing those. */}
|
||||
<div style={{ background: 'var(--bg-1)', border: '1px solid var(--border)', borderRadius: 12, padding: '14px 16px', display: 'flex', alignItems: 'center', gap: 12 }}>
|
||||
<span className="live-dot" style={{ background: 'var(--g-a)' }} aria-hidden />
|
||||
<span className="mono" style={{ fontSize: 11.5, color: 'var(--text-1)', letterSpacing: '0.04em' }}>
|
||||
REAL-TIME FEED · <span style={{ color: 'var(--g-a)', fontWeight: 700 }}>consensus vs model</span>, live line moves
|
||||
</span>
|
||||
{/* Real-time feed — backed by the live MarketBreadth (consensus vs model). */}
|
||||
<div style={{ background: 'var(--bg-1)', border: '1px solid var(--border)', borderRadius: 12, padding: '14px 16px', display: 'flex', alignItems: 'center', gap: 12 }}>
|
||||
<span className="live-dot" style={{ background: 'var(--g-a)' }} aria-hidden />
|
||||
<span className="mono" style={{ fontSize: 11.5, color: 'var(--text-1)', letterSpacing: '0.04em' }}>
|
||||
REAL-TIME FEED · <span style={{ color: 'var(--g-a)', fontWeight: 700 }}>consensus vs model</span>, live line moves
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user