Merge DS3 (design): the color contract — one meaning, enforced by tests

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

# Conflicts:
#	web/src/components/vyndr/GradeResultCard.tsx
This commit is contained in:
Kev
2026-07-12 19:36:07 -04:00
6 changed files with 296 additions and 29 deletions
+4 -3
View File
@@ -66,7 +66,7 @@ const row: React.CSSProperties = {
borderBottom: '1px solid var(--border)',
};
function Stat({ label, value, tone }: { label: string; value: string; tone?: 'positive' }) {
function Stat({ label, value, tone }: { label: string; value: string; tone?: 'positive' | 'negative' }) {
return (
<div
style={{
@@ -83,7 +83,8 @@ function Stat({ label, value, tone }: { label: string; value: string; tone?: 'po
style={{
fontSize: 14,
fontWeight: 700,
color: tone === 'positive' ? 'var(--grade-a)' : 'var(--text-primary)',
// Color contract #2: edge/CLV colored by SIGN — positive green, negative muted red.
color: tone === 'positive' ? 'var(--grade-a)' : tone === 'negative' ? 'var(--miss)' : 'var(--text-primary)',
}}
>
{value}
@@ -258,7 +259,7 @@ export default function LiveHeroProp() {
{/* Projection + edge — visible, the proof. */}
<div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>
<Stat label="Projection" value={`${projection} ${statTypeLabel}`} />
<Stat label="Edge" value={edgeDisplay} tone={edge > 0 ? 'positive' : undefined} />
<Stat label="Edge" value={edgeDisplay} tone={edge > 0 ? 'positive' : edge < 0 ? 'negative' : undefined} />
</div>
{/* Reasoning — BLURRED, the paywall. */}
+15 -10
View File
@@ -7,6 +7,7 @@ import VBtn from '@/components/vyndr/VBtn';
import ArchetypeBlend from '@/components/vyndr/ArchetypeBlend';
import GradeBadge from '@/components/vyndr/GradeBadge';
import { gradeColor, gradeHex } from '@/lib/vyndrTokens';
import { edgeColor, gradeGlows } from '@/lib/colorContract';
import { playerHref } from '@/lib/playerHref';
export interface GradeResultData {
@@ -69,9 +70,9 @@ export default function GradeResultCard({
}, [replayKey]);
const sideColor = d.side === 'Over' ? 'var(--g-a)' : 'var(--miss)';
// COLOR CONTRACT (Part 1 #3): edge/CLV colored by SIGN. A negative edge must
// NEVER render green — negative = var(--miss), positive/zero = signal-green.
const edgeColor = d.edge != null && d.edge < 0 ? 'var(--miss)' : 'var(--g-a)';
// COLOR CONTRACT (Part 1 #3): edge/CLV colored by SIGN via the centralized
// colorContract.edgeColor helper (imported) — negative = var(--miss). DS4
// introduced a local const that DS3 superseded with the shared enforcer.
const hasKill = !!d.killConditions && d.killConditions.length > 0;
const hasBooks = Array.isArray(d.books) && d.books.length > 0;
const hasAlt = Array.isArray(d.altLadder) && d.altLadder.length > 0;
@@ -140,7 +141,8 @@ export default function GradeResultCard({
lineHeight: 0.95,
color: hex,
letterSpacing: '-0.04em',
textShadow: `0 0 28px ${hex}aa, 0 0 60px ${hex}55`,
// GLOW = A/A+ ONLY (color contract #4): a glowing C/D devalues the cue.
textShadow: gradeGlows(d.grade) ? `0 0 28px ${hex}aa, 0 0 60px ${hex}55` : 'none',
fontFamily: 'var(--sans)',
}}
>
@@ -153,7 +155,7 @@ export default function GradeResultCard({
{d.edge != null && (
<>
<span style={{ color: 'rgba(232,255,244,.4)', margin: '0 9px' }}>·</span>
<span style={{ color: edgeColor }}>{d.edge >= 0 ? '+' : ''}{d.edge}% edge</span>
<span style={{ color: edgeColor(d.edge) }}>{d.edge >= 0 ? '+' : ''}{d.edge}% edge</span>
</>
)}
<span style={{ color: 'rgba(232,255,244,.4)', margin: '0 9px' }}>·</span>
@@ -176,7 +178,7 @@ export default function GradeResultCard({
{[
{ l: 'MODEL', v: d.projection != null ? d.projection : '—', col: d.projection != null ? 'var(--g-a)' : 'var(--text-2)' },
{ l: 'LINE', v: d.line, col: 'var(--text-0)' },
{ l: 'EDGE', v: d.edge != null ? `${d.edge >= 0 ? '+' : ''}${d.edge}%` : '—', col: d.edge != null ? edgeColor : 'var(--text-2)' },
{ l: 'EDGE', v: d.edge != null ? `${d.edge >= 0 ? '+' : ''}${d.edge}%` : '—', col: d.edge != null ? edgeColor(d.edge) : 'var(--text-2)' },
].map((x, i) => (
<div key={i} style={{ padding: '14px 16px', textAlign: 'center', borderRight: i < 2 ? '1px solid var(--border)' : 'none' }}>
<div className="label" style={{ fontSize: 10, marginBottom: 5 }}>{x.l}</div>
@@ -219,15 +221,18 @@ export default function GradeResultCard({
</div>
)}
{/* 5c. VYNDR INTELLIGENCE (Session 42) */}
{/* 5c. VYNDR INTELLIGENCE (Session 42). Color contract #6: the panel is
MUTED (neutral border) with a single green label as its identity
accent. Form/Rest are CONTEXT data, not "edge" — neutral-bright,
never green. */}
{d.vyndrIntel && (
<div className="intel-surface" style={{ margin: '0 20px 16px', padding: '15px 16px', borderRadius: 12, border: '1px solid rgba(0,212,160,0.24)' }}>
<div className="intel-surface" style={{ margin: '0 20px 16px', padding: '15px 16px', borderRadius: 12, border: '1px solid var(--border)' }}>
<div className="mono" style={{ fontSize: 10, fontWeight: 600, letterSpacing: '0.1em', color: 'var(--g-a)', marginBottom: 12 }}>VYNDR INTELLIGENCE</div>
<div className="mono" style={{ display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'center', fontSize: 12 }}>
{d.vyndrIntel.form != null && (<><span style={{ color: 'var(--text-2)' }}>Form</span><span style={{ color: 'var(--g-ap)', fontWeight: 700 }}>{d.vyndrIntel.form}</span><span style={{ color: '#2A3531' }}>·</span></>)}
{d.vyndrIntel.form != null && (<><span style={{ color: 'var(--text-2)' }}>Form</span><span style={{ color: 'var(--text-0)', fontWeight: 700 }}>{d.vyndrIntel.form}</span><span style={{ color: '#2A3531' }}>·</span></>)}
{d.vyndrIntel.usage && (<><span style={{ color: 'var(--text-2)' }}>Usage</span><span style={{ color: 'var(--text-0)', fontWeight: 600 }}>{d.vyndrIntel.usage}</span><span style={{ color: '#2A3531' }}>·</span></>)}
{d.vyndrIntel.matchup && (<><span style={{ color: 'var(--text-2)' }}>Matchup</span><GradeBadge grade={d.vyndrIntel.matchup} size="sm" /><span style={{ color: '#2A3531' }}>·</span></>)}
{d.vyndrIntel.rest && (<><span style={{ color: 'var(--text-2)' }}>Rest</span><span style={{ color: 'var(--g-a)', fontWeight: 600 }}>{d.vyndrIntel.rest}</span></>)}
{d.vyndrIntel.rest && (<><span style={{ color: 'var(--text-2)' }}>Rest</span><span style={{ color: 'var(--text-0)', fontWeight: 600 }}>{d.vyndrIntel.rest}</span></>)}
</div>
</div>
)}