Product UI for business accounts. Quiet surfaces, exact numbers, one accent. Desktop browser first, phone second. Black and white come from holders.io; type is Mona Sans (extended for display) with Geist Mono for figures and addresses; petrol blue is the one accent.
Neutrals do the work. Black is for primary actions and finished states. Petrol blue marks what is selected, focused or in progress. Status colours appear only where they carry meaning, always with a label or shape.
Neutrals
19.2:1
Ink--ink #0e0f11Text, primary button, done
11.0:1
Ink 2--ink-2 #3a3c41Body copy, secondary text
5.8:1
Muted--muted #62656dLabels, captions, placeholder
3.2:1
Faint--faint #8e9097Disabled, decimals in display only
Line strong--line-strong #d2d1ccInput borders, empty track
Accent soft--accent-softSelection, info banner, focus halo
Aa
Positive soft--pos-soft
Aa
Warning soft--warn-soft
Aa
Negative soft--neg-soft
DoPrimary action in black. Accent for the one thing that is current: the selected nav item, the active step, the focused field.
Don'tAccent-coloured buttons next to black ones, coloured page headers, gradients, glass, or the Solana green and purple outside asset logos.
Type
Mona Sans, one variable family: extended (width 125, weight 700) for the balance and display, width 118 / 650 for headings, normal width for everything people read. Geist Mono for standalone figures, addresses, hashes and references. In tables one face per row: amounts stay in Mona Sans, mono only for the shortened address. Chosen 2026-11-10 (B2 in type.html).
balance 54/1 · 700 · wdth 125 · -0.025em
display 44/1 · 700 · wdth 125Held by you.
h1 34/1.1 · 650 · wdth 118Open a business account
h2 22/1.2 · 650 · wdth 118Deposits
h3 18/1.3 · 650 · wdth 118Company details
body-lg 16/1.55 · 400Start with your work email. You will use it to sign in.
body 14/1.5 · 400Default for tables, forms and panels. Desktop data UI reads at 14.
label 13/1.4 · 500Registration number
caption 12/1.4 · 400Use your company address. We send a confirmation link to it.
A 4px base. Tight inside a group, wide between groups: 6px label to input, 20px between fields, 32 to 40px between field groups, 48px between page sections.
s1 · 4
s2 · 8
s3 · 12
s4 · 16
s5 · 20
s6 · 24
s8 · 32
s10 · 40
s12 · 48
s14 · 56
s20 · 80
r-xs 4 · track, kbd
r-sm 6 · chips, copy
r-md 8 · inputs, banners, nav
r-lg 12 · panels, dialogs
pill · buttons only
Flat · panels sit on a border, never a shadow
--e-pop · menus, popovers
--e-dialog · dialogs, side sheets
Density
controls 36 (forms in app: 40) · table row 48, compact 40 · nav item 34 · sidebar 240 · page max 1120 · panel padding 16/20 · touch targets on phone ≥ 44
Motion
Motion only explains a change of state. 120ms for colour and hover, 180ms ease-out for dialogs and sheets entering. No entrance animations on page content, no shimmer skeletons. The in-progress segment of a settlement track breathes slowly; everything stops under reduced motion.
--ease cubic-bezier(.22,1,.36,1) · --d-fast 120ms · --d-base 180ms · prefers-reduced-motion: all off
Buttons
Pill shape carried from holders.io. One primary per view. Labels name the action: "Add funds with USDT", not "Submit".
primaryhoverfocusloadingdisabled
secondaryhoverghostdangericon
lg 40 · auth, final actionsmd 36 · defaultsm 28 · inside banners, rowstext action
Fields and validation
Label above, help below, error replaces help in place so the layout does not jump. Validate on blur, re-validate on input once an error shows. Errors say what is wrong and how to fix it.
Long forms are field groups, not one centred column. Each group: fields on the left in a two-column grid, a context rail on the right that says why we ask and what counts. Short fields share a row; addresses take the full width. On phone the rail folds under the heading.
Company
From Companies House
We filled these from the public register. Change anything that is out of date; we check it against the register again.
Where you operate
Where the team works day to day.
Why we ask
A different operating address needs one proof document later: a utility bill or bank statement from the last 3 months.
Saved 11:06
Steppers
Vertical stepper sits in the left column of a wizard and doubles as navigation back to finished steps. The compact bar is for headers and phone. Numbers only, no "Step 3 of 5" heading above the page title.
Company detailsDone
2Business profileIn progress
3Controlling persons
4Documents
5Review and sign
2 of 5 · Business profile
5 of 5 · Review and sign
Status and progress
A chip names the state in words and shape. The settlement track is the product's signature: four segments for received, checked, converted, credited. It sits in every deposit row, so a table answers "where is my money" without opening anything.
CheckingConvertedCreditedOn holdReturnedDraftLink sent
progress · done · hold · fail · neutral. Square and triangle marks keep hold and fail readable without colour.
Checking
Converted, crediting
Held at conversion
Credited
Money
Tabular figures, right-aligned in columns, two decimals always. Every sum is drawn by the <hb-amount> component (amount.js, ported from Postcash): separators at 50%, cents at 75%, code after the figure, never wrapped, "—" when missing. Estimates carry ≈ and muted ink until final.
Display · balance
Row · crypto amount
Estimate · pending
≈
You sent
Rate
1 USDT = 1.00 USD
Conversion fee 0.50%
Credited
Addresses and hashes
Full string in Geist Mono, never truncated where someone will send money to it. The first and last four characters are boxed, because that is what people check. In tables, truncate in the middle. Copy confirms in place for 1.4s.
Every table is hb-table: one text face per row, mono only for the shortened address, 44px single-line rows, headers 12/500 muted and never wrapped. Dates and amounts sort (real buttons, ↕ on hover, ▲/▼ when active). Columns menu hides and reorders, the layout is saved per table, the first column stays pinned when the table scrolls inside its box. Middle-drag pans. Row tones are opaque.
Date
From
Status
Progress
Amount
Credited
Today, 14:32
TXd4…6Uty
Checking
Nov 5, 09:21
TXd4…6Uty
On hold· Below minimum
Nov 8, 10:14
TXd4…6Uty
Credited
Nov 3, 12:10
TZp1…k9Qa
Returned· Wrong network
Loading and empty rows span the visible columns by themselves
Date
From
Status
Amount
Date
From
Status
Amount
Timeline
For one object's history: a deposit, an application. Done steps are filled ink, the current step is a petrol dot, held is an amber square. Time sits right-aligned in tabular figures; the detail line says what happened in numbers.
Received10:14 on TRON
Checked10:1519 confirmations, risk check passed
ConvertingnowAt 1 USDT = 1.00 USD
Credited≈ after 0.50% fee
ReceivedNov 4, 13:05
Checked13:06
On hold13:06Conversions are paused. It converts by itself when they resume; nothing to do.
Credited
Banners
Full-width at the top of the area they concern. Bold lead sentence states the fact; the rest says what happens next. One action at most. No side stripes.
Your file is with our banking partner. Nothing to do. We expect an answer in 2 to 3 working days.
One more document is needed. Proof of operating address for 18 Deansgate, Manchester.
We could not load your deposits. Check your connection and try again.
Your account is active. Add funds with USDT or receive USD to your account details.
Empty and error states
An empty state is the first-run screen: say what will appear here and give the one action that fills it. Left-aligned inside the area, dashed outline, no illustration.
No deposits yet
Send USDT on TRON to your deposit address. It shows here within about a minute and is credited as USD.
No deposits match "On hold"
Every deposit is either in progress or credited.
Email card
Transactional email from Holders Business: one subject, one fact, one button. The same card is the mock inbox in prototypes. Amounts inside sentences use <hb-amount inline>.
Holders Business <no-reply@business.holders.io>To anna.marsh@northwindtrading.co.uk · 09:40
Holders Business
One more document for Northwind Trading Ltd
Hi Anna, we checked your file and need one more item before we can continue: proof of operating address for 18 Deansgate, Manchester M3 2BW. A utility bill or bank statement from the last 3 months works.
If you did not expect this email, you can ignore it.
Holders Business · business.holders.io
Dialogs, sheets, menus
A dialog only to confirm something irreversible or to sign. Details open in a side sheet so the list stays in view. On phone both become a bottom sheet. Esc closes; focus returns to the trigger.
Sign and submit your file
Your signature confirms the information is true and complete. You cannot edit the file after this.
Company
Northwind Trading Ltd
Reference
HB-2026-04817
Side sheet: 420px, slides from the right edge over the table, --e-dialog, same header and footer anatomy as the dialog.
App shell
Sidebar on the canvas tone; the work area is one white surface inset by 8px with a hairline and 12px radius. Company switcher at the top, Anna's identity at the bottom, the current item gets a white chip with a petrol icon. Below 860px the sidebar becomes a top bar with a menu.
Two columns, 7 to 5. Left: brand, the task, one form, left-aligned at a reading measure of 440px. Right, on canvas: what happens next and what to have ready, in the product's own facts. No centred card, no marketing panel, no stock imagery. On phone the context follows the form.
Brand · sign-in link
Context rail: steps with time, documents to prepare, what the account does