Every component, every state, on one page.
Built as the review surface for handoff: each row forces the states a spec sheet has to prove. Hover and active are simulated with classes so they can be inspected side by side; in production they come from real pointer state.
Buttons
Height 44px minimum, 36px for compact header actions, 52px for large, 68px for the hero primary. Focus ring is 2px at 3px offset on every variant. The loading state keeps the label box for width stability and swaps in a 18px spinner.
Chain selector
Radio group semantics, arrow keys move between the two chains, 44px targets. The selected pill takes the chain's own colour as border and tint, and always carries its logo, so the state is not colour-only. Two instances exist: the two-up selector (input card, final CTA, entry states) and the compact pill in the results header.
Address field
EVM addresses only. The chain logo sits inside the field so the address and the chain are read together. Paste control is 40px; the hint line below is the validation channel and reserves its height so nothing jumps.
Badges, chips and tags
Chain badges always pair the official logo with the chain name. Risk chips always pair colour, icon and the tier word. Tags are mono, lowercase and used for categories and formats.
Ethereum
BNB Smart Chain
DEMO
Neutral
sanctionsmixerbridge
PDFJSON
Risk markers
Gauge geometry is fixed: 270 degrees, 9px stroke, rounded caps, 11 ticks with a longer tick every fifth. The number and the tier word are the primary signal; the arc is confirmation.
Findings row
A summary row is 68px tall with a 44px severity tile. The expanded body indents to the text column, not the tile, so evidence keeps a single reading edge. Native details/summary gives keyboard and screen-reader behaviour for free.
Indirect match to a designated entity
Collapsed default. Click to open the evidence block below.
Mixer and tumbler exposure
Expanded state. Evidence rows use mono for values so addresses and dates line up across rows.
Alerts and states
Four tones, one geometry. Feedback colour never reuses the risk ladder: a rate limit is not a severe finding.
Controls
Data display
| Finding | Tier | Share |
|---|---|---|
| Sanctions · indirect | Severe | 4.8% |
| Mixer exposure | High | 12.4% |
| Darknet-adjacent | Moderate | 3.1% |
| Bridge hops | Low | 6 hops |
{
"tier": "high",
"score": 68,
"chain": "ethereum",
"audit_id": "TL-8F42-01C9"
}
Wallet connection
A scan cannot run before a wallet is connected: Check wallet opens the connection step instead of producing a report, and the report screen has its own locked state rather than reusing the input form. The sheet is one component, built in JS so every page shares it.
Every button that opens wallet connection carries the connect-btn class and is bound by the wallet script. The interface adds no handler of its own, so the script always receives the click.
Hidden once a wallet is connected; the chip takes its place in the header.
Component contract
| Component | Tokens used | States | Notes |
|---|---|---|---|
| Button | grad-cta, glow-cta, r-3/4, dur-2 | 6 + 4 sizes | Loading keeps width; label hidden, not removed |
| Chain pill | chain-eth, chain-bnb, chain-*-tint | 6 | Role radio; arrows move selection |
| Address field | surface, border-strong, focus cyan | 6 | Hint line reserves 18px to prevent layout shift |
| Risk chip | risk-*, risk-*-tint, risk-*-edge | 4 tiers × 3 sizes | Icon + word mandatory |
| Finding row | surface-2, risk-*, r-4 | collapsed, open, hover | Native details/summary, 68px summary |
| Gauge | risk ramp, dur-5 | 4 tiers, empty | Starts at 0 and sweeps once on mount |
| Alert | ok/warn/danger/info | 4 tones | Never encodes risk severity |
| Account chip | border-strong, mono 11.5 | connected only | Hidden on mobile address text, keeps the chain logo |