Colour

from _variables-custom.scss, published as custom properties
Paper
#F7F8FA · var(--paper)
page background
Ink
#0A0E27 · var(--ink)
text, headings, rules
Ink soft
#3C4252 · var(--ink-soft)
body copy
Ink muted
#6B7280 · var(--ink-muted)
secondary text
Ocean
#216B9F · var(--ocean)
accent, links, CTAs
Ocean light
#2B8AC9 · var(--ocean-light)
accent hover, the mark on ink
Rule
#D7DAE2 · var(--rule)
hairline dividers
Up
#0F766E · var(--up)
positive figures
Down
#B42318 · var(--down)
negative figures
Marker
#8A6A16 · var(--marker)
sourced events on a chart

Logo

one mark, three files
On paper: logos/logo.png

The topbar, the construction page, mail and every open-graph image. Never redrawn, never typed: the wordmark and the "DeFi Research Data Services" line are part of the file.

On ink: logo-all-white.png and logo-white-letters.png

All white on the sign-in cover; white letters with the blue mark in the footer.

Type

three families, self-hosted
Newsreader · headlines and leads
Every figure, read from the block.

A lead in the serif, one size down, for the sentence that explains the headline.

Hanken Grotesk · everything else people read
Hanken

Body copy, forms, navigation, buttons and labels in one voice. Labels are sentence case; there is no uppercase tracked label in version 3.

A label, as labels look now
IBM Plex Mono · data
0x9c1e4f0a7b3d2e8f6a5c4b3d2e1f0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f
23,088,584   1,204,118.42 USDC   4.38%
Every hash, address, block number and figure. Hashes are never truncated.
Measures

Prose sits inside a measure: 46rem for a lead or a paragraph beside a figure, 60rem for long-form. No inline max-width.

.measure-46 · .measure-60 · .measure-72 · .text-xs · .text-sm · .text-lg

How a page opens

Ui::PageHeaderComponent

A back link only where a parent exists; a meta line only when the title does not already say it. Nothing else sits above a title.

Buttons

Ui::ButtonComponent

Primary is ink; secondary is an ink outline; the accent is ocean and rare; ghost is the third action in a row. A button says what happens and keeps its name through the flow.

Cards, pills and metrics

Ui::CardComponent · Ui::PillComponent · Ui::MetricComponent
Swap Verified Drift Not yet checked Sourced event Alpha aave_v3

Statement of accounts

Ui::StatPanelComponent
Coverage
NetworksEthereum
Lending protocols5
Price venues611,095 pools
24h change-1.2%
MethodologyRead
Transaction
Hash0x9c1e4f0a7b3d2e8f6a5c4b3d2e1f0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f
Block23,088,591

Data table

Ui::DataTableComponent, rows tint only when they navigate
BlockEventEmitterValue
23,415,902 Swap USDC/WETH 0.05% 0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640 1,204,118.42
23,415,901 LiquidationCall Aave V3 Pool 0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2 -381.9021

Callouts, tabs, empty states

Ui::CalloutComponent · Ui::TabsComponent · Ui::EmptyStateComponent
Finding
Sixty-one accounts were liquidated at a realised bonus of 4.38% against the configured 5%.
Caveat
Prices before the depeg are thin; treat the first hour as indicative.
Seats nearly full
Two seats left on this plan.

No alerts yet

An alert watches a pool and tells you when a price crosses a line you set.

An empty state says what is missing and the next step. It never shows sample data.

Icons

ui_icon(name), inline SVG, config/icons.txt
search compass chart-line activity notes database-export key bolt shield-lock users copy check x