All screens and questions

Live specimen, in the real fonts. The palettes below are shown as tables.

23 / 69

Seasons, not weeks

$0.000412 · 1,234,567.89 INDEX · 69 SOL

Body copy in Inter. A position is kept or lost for good.

Moodboard and token proposal

For dusty's review at gate G1, alongside the wireframes (F3). This document proposes the tokens packages/ui ships in F1: two real palettes (dark, light) and the reasoning behind them, the type system, motion/sound/cursor principles, how the legal and devnet notices look, and the four open questions this gate resolves.

Direction

The master plan's brief: "Bloomberg terminal possessed by SPX6900" — a real index's gravitas (dense data, monospace numerals, methodology language) delivered with meme-market energy (the 69 motif, celebratory burn animations). That still holds. Three things changed for v2:

Nothing here is copied from Stonk.fun's or pump.fun's branding, layout, or logos. The interaction model (a curve, a buy/sell panel, a bonding progress bar) is the same familiar shape traders already know; the visual language is INDEX's own.

Palettes

Both themes are shipped as CSS custom properties in packages/ui/src/tokens.css (dark is the default; a third, wire, greyscale theme exists only for the wireframes and isn't part of this proposal). Nothing below is a mockup color picked by eye — every value is what's actually checked into tokens.css today, and the contrast table further down is computed from that same file, not redrawn from memory.

Dark (default)

TokenValueRole
--color-ground#0A0B0EPage background — near-black, the terminal floor
--color-panel#12141ACard/panel surface, one step up from ground
--color-text#F5F6F8Primary text
--color-muted#8B93A3Secondary text, labels
--color-brand#FF7A00INDEX brand: burn accents, primary actions, large counters
--color-positive#00E17BUp-movement, the OPEN state
--color-alert#FF3B4EDown-movement, permanent removal
--status-pending#FFC24BAwaiting graduation / LP lock pending / season ended — never a survival verdict
--star#FFD166The ★ a survived season earns — deliberately a different gold from --status-pending, so a star never reads as a pending flag
--state-full#FFB020The 69 Grid at FULL
--focus#5AC8FAKeyboard focus ring
--banner-devnet / --banner-devnet-fg#8C74FF / #0A0B0EThe devnet/unaudited banner — its own hue, so "this is a test network" never reads as a warning about the protocol

Light

TokenValueRole
--color-ground#F4F5F7Page background
--color-panel#FFFFFFCard/panel surface
--color-text#12141APrimary text
--color-muted#5B6472Secondary text, labels
--color-brand#C75A00INDEX brand (darkened from dark-theme orange to hold contrast on a light ground)
--color-positive#048A54Up-movement, the OPEN state
--color-alert#B91C3CDown-movement, permanent removal
--status-pending#9C6500Awaiting graduation / LP lock pending / season ended
--star#9C7209The survivor ★
--state-full#AD6600The 69 Grid at FULL
--focus#0A63B5Keyboard focus ring
--banner-devnet / --banner-devnet-fg#5B34E6 / #FFFFFFThe devnet/unaudited banner

Every color that carries meaning in the dark theme keeps the same *role* in light — only the value moves, enough to hold WCAG contrast on the lighter ground. Nothing swaps roles between themes.

Contrast

Every pair above is checked against WCAG AA (4.5:1 for body text; 3:1 for large text and non-text UI, per WCAG 1.4.11) by packages/ui/test/contrast-helper.ts, which reads tokens.css directly rather than a copy of the palette — so this table can't quietly drift from what ships. packages/ui/test/contrast.test.ts asserts every row below passes; running it is part of pnpm --filter @index/ui test.

Reproduce this table: pnpm --filter @index/ui contrast-report

ThemePairForeground on backgroundRatioNeedsResult
darkbody text on the page--color-text on --color-ground18.20:14.5:1 (normal text)pass
darkbody text on a panel--color-text on --color-panel17.02:14.5:1 (normal text)pass
darkmuted text on the page--color-muted on --color-ground6.37:14.5:1 (normal text)pass
darkbrand counters / headlines--color-brand on --color-ground7.53:13:1 (large text / UI)pass
darkpositive indicator--color-positive on --color-ground11.30:13:1 (large text / UI)pass
darkalert indicator--color-alert on --color-ground5.61:13:1 (large text / UI)pass
darkpending status--status-pending on --color-ground12.25:13:1 (large text / UI)pass
darksurvivor star glyph--star on --color-ground13.65:13:1 (large text / UI)pass
darkFULL state indicator--state-full on --color-ground10.76:13:1 (large text / UI)pass
darkfocus ring (non-text, WCAG 1.4.11)--focus on --color-ground10.38:13:1 (large text / UI)pass
darkdevnet/unaudited banner text--banner-devnet-fg on --banner-devnet5.68:14.5:1 (normal text)pass
lightbody text on the page--color-text on --color-ground16.88:14.5:1 (normal text)pass
lightbody text on a panel--color-text on --color-panel18.41:14.5:1 (normal text)pass
lightmuted text on the page--color-muted on --color-ground5.48:14.5:1 (normal text)pass
lightbrand counters / headlines--color-brand on --color-ground3.94:13:1 (large text / UI)pass
lightpositive indicator--color-positive on --color-ground4.04:13:1 (large text / UI)pass
lightalert indicator--color-alert on --color-ground5.84:13:1 (large text / UI)pass
lightpending status--status-pending on --color-ground4.50:13:1 (large text / UI)pass
lightsurvivor star glyph--star on --color-ground3.99:13:1 (large text / UI)pass
lightFULL state indicator--state-full on --color-ground4.12:13:1 (large text / UI)pass
lightfocus ring (non-text, WCAG 1.4.11)--focus on --color-ground5.56:13:1 (large text / UI)pass
lightdevnet/unaudited banner text--banner-devnet-fg on --banner-devnet6.82:14.5:1 (normal text)pass

Every pair passes today, in both themes, with margin — the tightest is light's pending status at 4.50:1 against a 3:1 floor.

Type

Three families, all SIL OFL 1.1 and self-hosted rather than loaded from Google Fonts or any third-party CDN (OD4):

lightweight-charts' own TradingView attribution is kept as its license requires.

Specimen

RoleFamily1440px390px
Hero counter (NN / 69)Archivo Black96px / 1.048px / 1.0
Section headlineArchivo Black48px / 1.128px / 1.15
Table data, large (a token's price)JetBrains Mono20px / 1.3, tabular-nums16px / 1.3, tabular-nums
Table data, body (a trade row)JetBrains Mono16px / 1.4, tabular-nums14px / 1.4, tabular-nums
Body copyInter16px / 1.515px / 1.5
Muted labelInter13px / 1.4, uppercase12px / 1.4, uppercase

F3 renders this specimen live (/moodboard), against the real fonts.

Motion, sound, cursor

Motion — numbers tick, never fade. Counters count up or down (odometer-style), they don't cross-fade. Beyond that, one deliberate, celebratory moment per event class, and everything else instant:

Two motion tokens exist today (--motion-duration-fast, --motion-duration-celebratory, --motion-ease); the keyframes themselves are each surface's own job as they're built.

Sound — opt-in, off by default. If enabled, sound plays only on the same celebratory moments motion marks above — never as UI feedback (no click, hover or error sounds). A visitor who never opts in hears nothing, ever.

Cursor — a crosshair on data surfaces. The 69 Grid, charts, and trade/holder tables get a crosshair cursor, the one deliberately "terminal" affordance in an otherwise ordinary interface. Everywhere else, the ordinary pointer.

Legal and risk notice styles

Two components carry every legal/risk surface (packages/ui/src/primitives/Banner.tsx and the acknowledgment dialog, F10a):

Questions for G1

Three open decisions this gate is asked to resolve or confirm. Each has a safe default already built in, named below, that ships if nothing is said.

  1. OD11 — "no trading terminal." The token page is a chart plus one simple buy/sell panel, not a multi-pane trading terminal — confirming that's still the right call for launch, not a heavier interface. Default: chart + simple panel, as built.
  2. OD12 — themes, tagline, brand mark and colour, sound, crosshair, pair emphasis. Confirming seven small defaults together: dark and light both shipped (dark default); no tagline until you give one, so the wordmark stands alone; a wordmark rather than a pictorial logo; orange (#FF7A00 on dark, #C75A00 on light) as the v0 brand colour; sound off by default; the crosshair cursor on data surfaces; SOL shown first among trading pairs. Say now if any of these should change, and send the tagline if there is one. Default: all seven, as described above.
  3. OD15's placement (text itself is a separate, later decision with counsel). Where the legal and risk notices sit is fixed by this proposal — top-of-page banner, gated acknowledgment dialogs, a placeholder /risk page, footer links on every page. Confirming that placement now means counsel's later text drops into a structure you've already seen, rather than reopening layout once legal text exists.

Anything raised here that changes a page's composition can reopen F5, F6, F10 or F13 (recorded against whichever task it reopens, per the plan's G1 section) — this is expected, not a sign something was missed.