soldi design system — "closer v2"

Authoritative design language for the app, derived from the closer — v2 prototype at reference/closer/public/v2/index.html. This replaces the current Robinhood-green theme. Migration is breaking for every themed element; do it as one foundation slice, then build new pages on top of it.

Prototype tagline (the product thesis): "The trading floor for real estate leads. Auction-priced exclusivity. AI-powered comps in under three seconds. One tab replaces PropStream, REsimpli, and Follow Up Boss."


1. Color palette

Editorial / metallic dark. Map into the Tailwind v4 @theme block in src/index.css as the single source of truth, then mirror into :root for raw var() consumers.

Neutrals |-|-|-| | token | hex | use | | --bg | #0B0D0E | page background | | --bg-elev | #0F1214 | elevated surfaces, drawer, insets | | --surface | #161A1D | cards | | --surface-2 | #1E2327 | pills, buttons, inset rows | | --surface-3 | #262C31 | active tab, hover surface | | --border | #22272B | default border | | --border-bright | #333A40 | hover / focus border | | --border-hot | #504437 | alert border |

Text tiers |-|-|-| | --text | #F1EDE8 | primary (warm off-white) | | --text-dim | #A7ADB3 | secondary | | --text-mute | #6B7278 | labels | | --text-faint | #4A5056 | disabled / faint |

Semantic (the metallic palette — locked 2026-04-22) |-|-|-| | --bull | #4FBA8B | positive / primary action / up (replaces old green accent) | | --bull-dim | #2F7D5E | tinted bull | | --bear | #E6675A | loss / danger / down | | --warn | #E8A94A | caution / time pressure | | --hot | #D97738 | urgency / alert / under-contract | | --accent | #A392E8 | AI / special / third-party (lavender) | | --accent-dim | #574A88 | tinted accent | | --gold | #C9A878 | premium / assigned / closed | | --gold-dim | #8E7650 | tinted gold |

Tinted variants use color-mix(in srgb, var(--x) 15%, transparent).

Semantic remap from the old theme

The old theme overloaded one green --accent for everything. Split it by meaning: |-|-| | old | new | | --accent #00D4AA (primary/positive) | --bull #4FBA8B | | --danger #FF4757 | --bear #E6675A | | --warning #FFA502 | --warn #E8A94A | | --success #2ED573 | --bull | | --gold #FFD700 | --gold #C9A878 | | (new) AI / special | --accent #A392E8 | | (new) urgency | --hot #D97738 |

First pass: find-replace #00D4AA → #4FBA8B. Second pass: re-classify each use — some greens are really --warn (time pressure) or --hot (urgency).

2. Typography

Load via Google Fonts (already in the prototype <link>): Fraunces (opsz 9..144 + SOFT axis), Instrument Serif, Hanken Grotesk, JetBrains Mono.

|-|-|-| | token | family | use | | --font-wordmark | Instrument Serif (italic) | the "closer" wordmark, 30px | | --font-display | Fraunces (optical sizing) | section headings (h2 30px italic), KPI numbers (26px) | | --font-body | Hanken Grotesk | body, nav, labels (13–14px) | | --font-mono | JetBrains Mono | currency, timestamps, counts (tabular-nums) |

  • Card / lead addresses: Instrument Serif 19px (hero 32px).
  • Micro labels (.lbl, .k, .micro): JetBrains Mono, 11px, uppercase, letter-spacing: .08em.
  • .tnum utility → font-feature-settings: "tnum" for aligned numerics.
  • Keep --font-body mapped to Hanken Grotesk; retire Inter/Plus Jakarta.

3. Radius, spacing, shadow, grid

  • Radius: --radius 10px (cards/pills), --radius-sm 6px (badges), --radius-lg 16px (hero, drawer, filters).
  • Gaps: 20px page grid · 14px card grid · 10px hero grid · 6px pill rows.
  • --shadow-lift: 0 1px 0 rgba(255,255,255,.02) inset, 0 16px 40px -24px rgba(0,0,0,.8).
  • Card hover glow: 0 0 0 1px <bull-tint>, 0 12px 32px -20px rgba(79,186,139,.35).
  • Decorative grid wash (net-new, global, zero JS): body::before, 56×56px repeating-linear-gradient at opacity .35 with a radial mask-image that fades top→bottom. Adds the "terminal" texture.

4. Signature components

  • Buttons: .btn (surface-2 + border-bright, secondary) · .btn.primary (bull bg, dark text #062315) · .btn.ghost (transparent + outline) · .btn.danger (bear text). Refactor today's single .btn-* set into this variant system.
  • Quality circle (.qscore): 90px conic-gradient(var(--bull) 0 calc(var(--score)*1%), …) with an inner surface ring; number in Fraunces 28px. Drives the lead quality badge.
  • Pills / chips: distress, hot, equity, age — surface-2, mono 11.5px, 999px radius.
  • Sparkline: SVG path from the bids[] series (bull line + gradient fill + last-point dot). Compute from real bid history, not random jitter.
  • Ticker (LiveTicker): 28px strip, marquee 72s, mono, --bull/--bear/--warn. Already exists — restyle only.
  • Lead drawer: 560px right slide-in (translateX(100%)→0, cubic-bezier .32s), dark gradient bid-console, order-book table (4-col grid, per-row --w gradient fill, .live highlight), tabs (Bid / Comps / Seller / Activity).
  • Animations: pulse (ticker dot), price-flash (bid update), urgent-pulse (countdown < 600s), revealUp (staggered page-load, use sparingly on hero + top grids).

5. Migration checklist (foundation slice)

  1. Rewrite @theme + :root in src/index.css with the tokens above; add font <link> to index.html.
  2. Add the grid-wash body::before, --shadow-lift, radius/spacing tokens, and the keyframes.
  3. Re-baseline component classes (.btn*, .card, pills, .qscore, headings) to the new variant system.
  4. Sweep pages (Marketplace, LeadDetail, Portfolio, TopNav, LiveTicker) replacing accent→bull and re-classifying semantic colors.
  5. Restyle TopNav brand to Instrument Serif "closer" wordmark + bull .dot; keep router intact.
  6. Visual-regression by screenshot against the prototype panel-by-panel.

Keep auth/session, routing, and the working marketplace+bidding logic intact — this slice is paint, not plumbing.