DS5 — Pricing (Desk-as-hero) + Motion + Empty/Error + archetype glyphs

Part 6 #8 — Desk $44.99 is the hero tier. New DeskShowcase leads the
pricing page with the "$1M terminal · $44.99" story + real feature
visuals (alt-line ladder, quarter-Kelly, parlay φ, real-time feed) in a
balanced two-column layout (kills the dead right-half). Desk is the sole
highlighted tier / single primary CTA (color contract #9); Analyst is
secondary. Real prices: Free 5 scans, Analyst $14.99/$19.99, Desk
$34.99/$44.99. ClaimMeter + Stripe checkout wiring untouched.

Part 4 #7 — Ticker → punctuated stillness. The continuous marquee is
retired; the ticker now RESTS ≥4s on each ranked item and pulses only on
change. The EKG heartbeat is a static readout — the header's ONE idle
proof-of-life is the single SIGNAL-LIVE live-dot (the ticker dropped its
competing pulse). All durations tokenized (--motion-*, --ticker-hold);
prefers-reduced-motion kills the motion entirely.

Part 8 #20 — new EmptyState component modeled on the north-star 404
(scanlines + glitch wordmark + amber system voice + CTA hierarchy),
reused at the bare-red "Team not found", "Game not found", and the
ledger empties — one unified voice.

Part 5 — archetype glyph+chip propagated to STREAKS rows + ledger rows
(optional + self-hiding; absent beats fabricated); grade reveal already
carries ArchetypeBlend.

Tests: new tests/unit/ds5PricingStates.test.js (22) locks all four
workstreams; updated teamHubUI + vyndrDesignSystem for the new surfaces.
237 suites / 2864 tests green; next build exit 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kev
2026-07-13 00:31:35 -04:00
parent cf91c04e90
commit a18a3f33fc
14 changed files with 620 additions and 86 deletions
+11
View File
@@ -3,6 +3,7 @@
import { useEffect, useState } from 'react';
import PlayerAvatar from '@/components/vyndr/PlayerAvatar';
import GradeBadge from '@/components/vyndr/GradeBadge';
import ArchetypeBadge from '@/components/vyndr/ArchetypeBadge';
import { type Tier } from '@/lib/tierGate';
/**
@@ -31,6 +32,9 @@ interface Streak {
// Session 60 (night2/C) — THE LENS + optional snapshot grade letter.
lens?: { builtVs?: string[] | null; matchup?: string | null; difficulty?: string | null; read?: string | null };
grade?: string | null;
// DS5 (Part 5) — the player's locked archetype from the snapshot join, when
// present. Optional + self-hiding: absent beats fabricated.
archetype?: string | null;
}
export interface StreaksPanelProps {
@@ -102,6 +106,13 @@ export default function StreaksPanel({ sport, tier = 'free', stat = 'all', limit
<div style={playerName}>
{s.player}{s.team ? <span style={teamTag}> · {s.team}</span> : null}
</div>
{/* Part 5 — the archetype glyph+chip (the Rosetta stone),
propagated here; self-hides when the join has no archetype. */}
{s.archetype && (
<div style={{ margin: '3px 0' }}>
<ArchetypeBadge archetype={s.archetype} sport={sport} size="sm" showDesc />
</div>
)}
<div className="mono" style={categoryLine}>{s.description}</div>
<div style={lensLine}>{builtVs}</div>
</div>