Living spec

Design system

The shared visual language behind trd.fun. Token-driven, theme-safe, and built to compose into the surfaces you see on /coach#signals, the research workspace, and the Cmd+K palette. Read the guide in docs/DESIGN.md.

Color Tokens

trd.fun ships two themes (dark default + warm-sandy light) over a single CSS-custom-property layer. Always reference tokens by name — never hard-coded hex — so theme switching is automatic.

Surface
--og-bg
page background
--og-surface
cards
--og-surface-2
inset panels
--og-elevated
modals
--bg-primary
app shell
--bg-surface
flat cards
--bg-hover
hover surface
--bg-active
pressed
Text
--text-primary
--text-secondary
--text-tertiary
--og-text
--og-text-muted
--og-text-faint
Semantic + soft fills
--green / --og-bull
positive · up
--red / --og-bear
negative · down
--blue / --og-neutral
informational
--og-accent
brand purple
--amber / --og-warn
caution
--og-bull-soft
--og-bear-soft
--og-neutral-soft
--og-accent-soft
--og-warn-soft
Glass + overlay
--glass-bg
overlay shell
--glass-border
--glass-highlight
inputs in glass
--overlay-bg
modal backdrop

Typography

Two stacks: IBM Plex Sans for UI copy, and the mono stack via var(--font-mono) for every numeric or symbol-anchored value (prices, P/E, change %). Numeric content always uses tabular-nums so columns line up.

36px / 600 / -0.025emPage title
24px / 600 / -0.02emSection heading
18px / 600 / -0.01em · mono$245.83
14px / 400 / 1.55Body copy and lede paragraphs sit at 14px with a relaxed line-height.
13px / 600 — UI copyUI text · button labels
12px / 400 — secondarySecondary descriptive text
10px / 600 / 0.2em up · monoEyebrow label
Numbers
$1,245.83+12.45%-3.18%P/E 28.4 · TTM 4.21

Motion

A small, consistent motion vocabulary. Everything respects prefers-reduced-motion: reduce via the global override in app/globals.css. Hit replay to re-trigger.

.og-anim-fade350ms ease-outHero blocks
.og-anim-slide420ms cubic-bezier(.22,1,.36,1)Card entry
.og-anim-scale320ms ease-outPop-in elements
.og-anim-pulse2.4s infiniteLive indicators
.og-anim-bob2.6s infiniteIdle visuals
Stagger

Wrap N children in .og-stagger to slide them in with escalating animation-delay (0ms → 420ms in 60ms steps).

Discover
Research
Track
Analyze
Decide

Components

Primitive components that compose into every screen. All tone-aware, all theme-safe, all importable from @/app/components/ui.

Buttons
Cards
Variant
flat
Default card padding sits at 16px on the M scale.
Variant
raised
Default card padding sits at 16px on the M scale.
Variant
elevated
Default card padding sits at 16px on the M scale.
Variant
glass
Default card padding sits at 16px on the M scale.
Hover-lift
Adds a small translateY + shadow swell on hover.
Accent stripe
accent prop draws a 3-px gradient bar on the left edge.
Chips
DefaultBullBearNeutralAccentWarnFilledWith iconMedium size
Inputs
⌘K
Keyboard hints
⌘KESC⇧⌘P
Tabs
Active tab: overview
Toggles
Stat tiles
NAV
$1.24M
+$12,540 today
vs $1.227M yesterday
Buying power
$248k
4× margin
Day P&L
-$3,142
-1.18%
Open positions
28
Icon tiles
Radio cards (selectable)

The same primitive used by the onboarding stock picker. Click to toggle selection — the whole card is the hit target.

Patterns

How the primitives compose into the recurring shapes you'll see across trd.fun. These are the canonical recipes — copy them, don't re-roll them.

Command palette · Cmd+K

Glass shell · commandk-enter motion · 2-px left-edge accent on the active row · group labels in tracked-out tertiary mono · to navigate · to select · ESC to close.

Nothing picked yet
Card head + body
Pricing & valuation
Chart, change %, and forward P/E
+12.45%
Latest news
Synthesised from 5 sources
SYNTHESIS
Empty state
No watchlist yet
Add up to twelve symbols to start tracking real-time pricing and signals across markets.
Eyebrow + value
Trail P/E
28.4
Fwd P/E
24.1
24mo Avg
26.8
Mkt Cap
$2.4T

Marketing surfaces

Two complementary treatments for entry-point screens. Rich (live at /login) is the design system at its most expressive. Flat (live at /onboarding) is the calm, in-product feel. The hand-off from rich → flat after sign-in is intentional — it signals “you're in the product now”.

When to use
Rich
First-impression surfaces
  • Public landing / login pages
  • Marketing announcements
  • Hero takeovers, full-bleed promos
glass · gradient · hover-lift · shadow
Flat
Guided / in-product flows
  • Onboarding, sign-up, account setup
  • Settings, preferences
  • Confirmation / success screens
solid · brand-as-accent · no shadow
Hero pattern · rich

Two-column hero: gradient headline + sub-line + chip strip on the left, glass sign-in (or primary CTA) card on the right. The card shares its shell with the Cmd+K palette and Modal so the motion + chrome read as one family across the app.

Live · v0.1

Your watchlist,
with a brain.

Real-time prices · multi-source synthesis · IBKR-aware research.

Live ticksAI synthesisSmart alerts
Sign in · OAuth · Google
Continue to trd.fun
One-click sign-in. No password to remember.
No passwordsOwner-only
View live page · app/login/page.tsx + app/login/styles.tsx
Animated KPI peek

The hero ships a faked-but-realistic KPI strip whose numbers jitter every 2.4s so the surface reads as “live” without becoming distracting. Use it on public surfaces where you want to hint at the real product's motion without exposing live user data.

Source: app/login/components/LiveDataPeek.tsx
Pillar grid

Six (or fewer) raised cards in a 3-col responsive grid. Each row opens with an IconTile, ends with a dotted-divider meta footer in mono. Wrap the grid in og-stagger to slide cards in with escalating delays on first paint.

Multi-source synthesis
One run pulls Reddit, X, news, fundamentals, and your portfolio context into one grounded answer.
5 sources · grounded
Real-time everywhere
Finnhub WebSocket ticks stream live across every watchlist row.
Live · SSE
Portfolio in context
IBKR positions and P&L sit alongside every research run.
IBKR Flex
How-it-works steps

Three solid-surface cards with floating gradient number pills. Use sparingly — the cards work best as the “and now what?” beat between the hero and the bottom CTA.

1
Pick stocks
Add 3–12 names through the guided tour or paste into Cmd+K.
2
Run research
One run pulls every source, returns one grounded answer.
3
Stay in flow
Live prices stream in. Alerts fire. Cmd+K jumps anywhere.
CTA banner · elevated

The closer for marketing pages. Gradient backdrop, large headline + sub-line, primary action paired with a ghost alternative. Stretches full-width inside the page shell.

Ready to take the watchlist for a spin?
Owner-only beta. Sign in with Google to get started.

Stock page

The public /stock/<symbol> page — cached and SEO-crawlable. An editorial, magazine-style layout: a big mono symbol, an at-a-glance stats band, an AI-research brief with four cache states, and a discovery rail. Blue accent throughout. Mocks below are flat re-renders using global tokens only.

Editorial hero

What it is: the page masthead — identity, live quote, actions, and a cached one-line TLDR. Used on: /stock/<symbol>.

NVDA
NVIDIA CorporationNASDAQ
Share Deep research
$182.41+2.14%live

Datacenter demand stays red-hot as Blackwell ramps; Street eyes margin durability and China headwinds into the next print.

— cached tldr
Stats band

What it is: a slim figure strip under the hero. Tiles are omitted (not dashed) when a value is missing. Momentum chips colour by sign.

Mkt Cap$4.48T
P/E (TTM)52.1
Fwd P/E38.4
EPS (TTM)$3.50
Next ERin 12d
30D+8.2%
90D-3.1%
AI research · four cache states

What it is: the cache-shared AI brief. Its header badge encodes one of four states. Stale shows the SAME content (never hidden) with an amber badge; only none swaps in a teaser / generating notice.

AI Researchcached · 8m ago
NewsSentimentReddit
Synthesis + sections shown. Approved viewers get a quiet ⟳ Refresh.
AI Researchlast generated 9h Refresh
NewsSentimentReddit
Same content, amber badge. Refresh becomes prominent for approved viewers.
AI ResearchNo brief yet
No AI research yet for NVDA
Sign in and we’ll generate the first brief — news, sentiment, and catalysts — then cache it here for everyone.
Sign in to generate
Guests see a sign-in teaser; the brief is generated + cached for everyone.
AI ResearchGenerating brief…
NewsSentimentReddit
Assembling the first AI brief — news, sentiment, and catalysts. Runs in the background; refresh in a moment.
Approved viewer — a background run was already kicked. Provider chips pulse.
Discovery rail

What it is: the right-hand rail — valuation + momentum key/value cards and blue theme chips. Each card hides entirely when its data is empty.

Valuation
P/E (TTM)
52.1×
Fwd P/E
38.4×
EPS (TTM)
$3.50
Fwd EPS
$4.75
Momentum
1D
+2.14%
5D
+5.40%
30D
+8.20%
90D
-3.10%
In these themes3
AI InfrastructureSemiconductorsDatacenter

Theme deck

The condensed editorial one-pager at /theme/<slug>. A theme is a basket of tickers framed by a generated brief, laid out top→bottom as a big editorial header, a 7-stat bar, a "The take" lead block, a 3-card thesis row, and a dense roster of tradeable cards with private / pre-IPO names folded in as badged tiles. Below are flat re-renders of each pattern — global tokens only, no scoped theme-page CSS.

Editorial header + intro

Mono eyebrow (EyebrowLabel) → oversized title (clamp(40px,6vw,62px), weight 800, letter-spacing -.03em) → bold sub-headline (the AI headline) → an intro overview paragraph as prose (not bullets) → a N stocks · curated/AI theme meta line. Used on: /theme/<slug>.

⚛️Theme · Curated

Nuclear Renaissance

AI's power hunger is reviving an industry left for dead — and the re-rating has only just begun.

Hyperscaler datacenter demand is reopening shuttered plants and underwriting new small-modular-reactor builds, while uranium spot has tripled off its lows as utilities scramble to re-contract supply. Government de-risking — loan guarantees and streamlined licensing — has shortened the runway to revenue.

11 stocks · curated theme
Stat bar · 7 tiles

A full-width strip of seven KPI tiles: 1D basket move, real 1-yr growth, aggregate cap, company count, median P/E, and 30D / 90D basket moves. Momentum / valuation figures are computed client-side from the loaded fundamentals. Signed values colour via var(--green) / var(--red). Composes the shared StatTile primitive. Used on: /theme/<slug>.

1D basket
−0.84%
1-yr growth
+212.6%
Agg cap
$486.2B
Companies
11
Median P/E
29.4×
30D
+9.7%
90D
+34.1%
The take · lead block

A full-width synthesis of the brief's whyItMatters / overview: a mono section label, a bold lead line, and a bulleted body. The editorial anchor of the page. Used on: /theme/<slug>.

The take

Power — not chips — is now the binding constraint on AI scale, and the nuclear fuel cycle is structurally under-supplied through the decade.

  • Datacenter PPAs give the operators multi-decade demand visibility that the market is only starting to price.
  • Spot uranium has tripled, but long-term contract volumes still lag replacement needs.
The thesis · 3-card row

Three raised cards (Card variant="raised"): the bull case (green, TrendingUp), the catch (amber, AlertTriangle), and outlook · 12mo (blue, Compass). Each = a tinted IconTilewith a monochrome lucide line icon → heading → bullets → a dashed-divider mono keyword footer tinted to the card's tone. One tone per card (DS §5). Used on: /theme/<slug>.

The thesis

The bull case

  • Multi-decade demand visibility from datacenter PPAs.
  • Pure-play scarcity forces premium valuations.
secular demand · tight supply

The catch

  • SMR timelines slip; first revenue is years out.
  • Sentiment-driven names round-trip on headlines.
valuation · timeline risk

Outlook · 12mo

  • Watch utility re-contracting cadence and the first SMR design approvals.
  • Restart announcements re-rate the operators.
re-contracting · approvals
Roster cards · big player / rising star

Selectable cards (toggle into the watchlist). The big-player card is dense — symbol, live price, 1D chip, 1D/30D/90D momentum strip, market cap + sector role chip, and a USP tagline. The rising-star card is a compact two-momentum-cell variant. Selection affordance is BLUE (DS §5), never green. Used on: /theme/<slug>.

CEG
Constellation Energy
$284.50+2.34%
1D+2.3%
30D+14.8%
90D+41.2%
$89.4BUtilities
Largest US nuclear fleet — direct beneficiary of datacenter PPAs and the Three Mile Island restart.
OKLO
$22.18
1D-1.6%
30D+38.4%
$3.1B
Fast-reactor SMR developer with a build-own-operate model.
More in this theme · private folded in

The "More in this theme" roster folds two card kinds into one dense grid. Public names render as selectable, solid-border roster cards (left). Private / pre-IPO names are info-only — a gold status badge flags the stage and the figure is a last-round valuation (dotted underline), not a live price. Used on: /theme/<slug>.

SMR
NuScale Power
First NRC-certified small modular reactor design.
Pure-play$2.4B
TerraPowerPRE-IPO
Gates-backed sodium fast reactor with integrated molten-salt storage.
Disruptor$8.0B

Research view

The single shared, presentational research deck — <ResearchView> in app/components/research/ResearchView.tsx. One component composes the whole research library: header · provider chip strip · RUN/MODEL/SOURCES meta line · accent-left-border synthesis sections with type chips · sources drawer · follow-up chips · ask box. The public stock page renders the same component, so this is the look it must match. The accent is --rv-accent (default gold), overridable per variant. This block is a flat re-render using global tokens only.

Full anatomy · panel variant

Header (ticker + company + live price + refresh/expand/close icons) → provider chips → meta line → synthesis rows → sources drawer → follow-up chips → ask box. Live: ResearchView (variant="panel").

NVDANVIDIA Corporation$724.30+2.41%
NewsnowX12mReddit12mFund.emptyPortfolioempty
Run12m agoModelgemini-3-flashSources3/5

Overview

Synthesis

NVDA held above the 50-day after the earnings beat; bulls cite data-center demand, bears flag a stretched forward multiple.

Latest News

News

Two analyst upgrades and a supply-chain note dominate the last 24h of coverage.

X/Twitter Sentiment

X

Retail mood skews bullish into the print; a few high-follow accounts flagging valuation risk.

Reddit Sentiment

Reddit

r/stocks threads lean cautiously optimistic; recurring debate on whether the rally has run too far.

Sources 2
Why did it move?What changed since last run?Only sentiment
Ask a follow-up about NVDA…⏎ to send
Overridable accent · --rv-accent

The synthesis bar, type chip, send button, and follow-up borders all read from --rv-accent, which defaults to the gold --rp-accent (#d8b765). A call site can re-tint an entire instance — e.g. an embedded variant — by setting --rv-accent once on the wrapper, with no component fork.

--rv-accent#d8b765 (default gold)
embedded ex.var(--blue) override

Signals board

The whole-universe Live Signals board — <SignalsBoard> in app/components/signals/board/, the canonical /signals. Composites: BoardHero (live status + verdict tallies) · FilterBar (scope toggle + theme menu) · SignalTape / SignalRow (the tape) · SignalRowDetail (the expanded drill-down) · ThemesStrip (heating-up momentum chips). Every selector is namespaced under .sb-board via <SignalsBoardStyles/>, so these are the LIVE components rendered on deterministic fixture data (SAMPLE_BOARD_ROWS).

Board hero · live status + verdict tallies

The pulsing market pill (phase-aware), the recompute / updated / universe meta line, the H1 headline, the AI subhead, and the four verdict tally tiles (Long / Exit / Short / Wait).

LIVE · MARKET OPENverdicts recomputed ~30s · poll · updated 4s ago · 428 symbols flashing now

What's flashing right now

A realtime green / amber / red verdict computed live on our own engine — then the AI reads Reddit, X and the news to tell you whether the crowd buys it. Live, not delayed.

6
Long
2
Exit
1
Short
14
Wait
Filter bar + tape · interactive

The “Ready to buy” title + “N firing now” bull chip, the [Watched | All universe] segmented control with the theme dropdown, and the tape itself. Click a row to expand its drill-down; the theme menu and scope toggle are live.

Ready to buy 4 firing now

SYMPRICECALLCONFBBRSISTOCHQUADRANTAGE · SRC
142.18LONG88Oversold + Bullish3s ago · worker
LONGconf 88/100
Bullish
RSI ↑
Bearish
RSI ↓
Oversold
+ Bullish
Overbought
+ Bullish
Oversold
+ Bearish
Overbought
+ Bearish
OversoldOverbought
Oversold + Bullish — highest-conviction long. Cheap on the band, regime still bullish. Buy shares, a bull call spread, or sell a CSP at the lower-band strike.
Why — engine verdict
  • Price pierced the lower Bollinger Band — statistically stretched cheap.
  • Stoch RSI K crossed above D from the oversold zone (K=14.2).
  • RSI 48.6 sits above 45 — clears the bullish-regime filter.
  • Bullish RSI divergence — price lower low while RSI made a higher low.
28.74LONG81Oversold + Bullish2s ago · worker
911.40LONG74Oversold + Bullish5s ago · worker
118.05LONG66Oversold + Bullish8s ago · worker
41.92EXIT71Overbought + Bullish4s ago · worker
241.30EXIT63Overbought + Bullish11s ago · worker
187.62SHORT69Overbought + Bearish6s ago · worker
213.55WAIT22Neutral19s ago · yahoo
428.90WAIT18Neutral7s ago · worker
Row detail · expanded drill-down

The expanded accordion: large VerdictPill + confidence, the three traffic lights, the LABELED 2×2 quadrant matrix with its guidance line, the two link-out buttons, and the left-aligned “Why — engine verdict” reasons list (leading marker).

LONGconf 88/100
Bullish
RSI ↑
Bearish
RSI ↓
Oversold
+ Bullish
Overbought
+ Bullish
Oversold
+ Bearish
Overbought
+ Bearish
OversoldOverbought
Oversold + Bullish — highest-conviction long. Cheap on the band, regime still bullish. Buy shares, a bull call spread, or sell a CSP at the lower-band strike.
Why — engine verdict
  • Price pierced the lower Bollinger Band — statistically stretched cheap.
  • Stoch RSI K crossed above D from the oversold zone (K=14.2).
  • RSI 48.6 sits above 45 — clears the bullish-regime filter.
  • Bullish RSI divergence — price lower low while RSI made a higher low.
Leaves · verdict pill · lights · quadrant matrix

The reusable atoms the row and drill-down compose from. The quadrant matrix labels its axes (Oversold→Overbought, Bullish→Bearish) and fills the active named cell in its tone color.

LONG· 88VerdictPill · lg
SignalLights · BB / RSI / Stoch
Bullish
RSI ↑
Bearish
RSI ↓
Oversold
+ Bullish
Overbought
+ Bullish
Oversold
+ Bearish
Overbought
+ Bearish
OversoldOverbought
GO · Oversold + Bullish
QuadrantMatrix · labeled 2×2
Themes strip · heating-up momentum chips

“Heating up · 30D momentum” — ranked theme chips (name + signed % + arrow), each a link to its /theme/<slug> AI deck.

Each opens an AI deck: bull case · the catch · 12-mo outlook · catalysts.

Research workspace

The multi-source AI research deck. Used on /research/<symbol> (owner only) — a three-column cockpit: session rail · synthesis · pricing rail, with a sticky chat dock at the bottom. The live surface is scoped behind .research-root with --rp-* tokens; these blocks are flat re-renders using global tokens only.

Provider chip strip

The five research sources — news · x · reddit · fundamentals · portfolio — in canonical order. Each chip carries a colored provider icon, an uppercase label, an age figure (tabular-nums), and a status dot: fresh · stale · tertiary empty · failed · pulsing gold loading. Live: ProviderChipStrip.

NewsnowX5hReddit···Fund.emptyPortfoliofailed
Synthesis block

One row per provider section: a 2-px left-edge gradient bar in that provider's accent fades from solid to transparent, a heading + a tinted tag, and a body paragraph (sans prose, not mono). The first row is always the cross-source Synthesis · Overview, tagged gold. Live: SynthesisBlock.

Overview

Synthesis

NVDA held above the 50-day after the earnings beat; bulls cite data-center demand, bears flag a stretched forward multiple.

Latest News

News

Two analyst upgrades and a supply-chain note dominate the last 24h of coverage.

Position Context

Portfolio

You hold 40 shares at $612 avg — current spot is +6.4% on cost.

Session rail · run cards

Left rail of past runs grouped by recency (Today / Yesterday / This week). Each card: a status dot (complete / partial / failed), a when · cost meta row (mono figures), a 2-line query, and a sources count. The active card gets a gold-tinted fill + ring. Live: SessionRail.

Click a run card
Bundle meta strip + input dock

A compact run-metadata strip — run age · model · sources loaded · cost · tokens as label/value cells (mono) — with export actions pushed right. Below it, the sticky input dock: a row of quick-prompt pills over a composer with a gold send button. Live: BundleMetaStrip + QuickPrompts.

RunnowModelgemini-2.5-flashSources5/5Cost$0.041Tokens18.4k in · 2.1k out Export · Markdown
Why did it move?What changed since last run?Portfolio impactSet an alert at $720
Ask a follow-up about NVDA…⏎ to send
Scoped exception · gold accent

The flat system reserves var(--blue) for primary accents. The research workspace is the one documented exception: it scopes a warm gold accent (--rp-accent: #d8b765) behind .research-root for the active session ring, synthesis tag, send button, and quick-prompt borders. It never leaks out of the route. Light-theme darkens it to #806000 for WCAG AA.

--rp-accent#d8b765
--blueflat default
Gold = “this is the owner's private AI deck.” Use the flat blue everywhere else.