DIXI · Design system
Design system
Foundations, tokens and components behind dixi.agency and this portal. Copy any value, switch the theme, try every state.
DIXI Design System · v1.2 · 5 Nov 2026
One system behind every DIXI screen.
The foundations, tokens and components that run dixi.agency and this portal. Three token tiers, light and dark themes checked for WCAG 2.2 AA, and every component documented the way we build it.
Start here
Principles
Four rules every screen is checked against.
Clear in five seconds
One idea per screen and one loud action per view. Hierarchy comes from size and weight before colour.
Proof over promise
Every number carries its period and its source. Data is tabular, aligned and never rounded into fiction.
Quiet surfaces, sharp details
Soft grey cards, hairline edges, generous radius. Colour is kept for action, status and data.
Accessible by default
AA contrast in light and dark, a visible focus ring, 36 px targets and respect for reduced motion.
How tokens work
Three tiers, so a brand change is one edit and dark mode is a second set of values, not a second stylesheet.
Primitives
Raw values with no meaning: a ramp step, a pixel size. Never used directly in components.
Semantic
A role, with a value per theme. This is the layer you build with and the one that flips for dark mode.
Component
Decisions owned by one component: its heights, paddings, its own aliases. Change one button, not every blue.
Files
The same tokens the portal runs on.
Tokens · CSS
dixi-tokens.css
Every token as a custom property. Light by default; .dk, data-theme="dark" or the system setting switch it.
Tokens · JSON
dixi-tokens.json · W3C DTCG
Design Tokens Community Group format, with light and dark modes. Reads into Tokens Studio and Style Dictionary.
Icons · SVG sprite
dixi-icons.svg · 90 symbols
One file, one <symbol> per icon. Use with <svg><use href="#i-search"/></svg>.
<link rel="stylesheet" href="/portal/ds/dixi-tokens.css">
<html class="dk"> <!-- dark theme: add .dk or data-theme="dark" -->:root {
/* load once, then theme with a class */
}
.card {
background: var(--dx-bg-surface);
border-radius: var(--dx-radius-card);
padding: var(--dx-space-inset-card);
color: var(--dx-text-primary);
}
.card:hover {
box-shadow: var(--dx-shadow-raised);
transition: box-shadow var(--dx-duration-fast) var(--dx-ease-standard);
}Changelog
- v1.2 · 5 Nov 2026Everything the site and the portal gained since v1.1: 11 components (Dropdown, Slider, Option card, Status, Breadcrumb, Mega menu, Drawer, Lightbox, Cookie consent, Contact dock, Accordion), the Effects page, and Patterns with the blocks of dixi.agency and of the portal. Every one in light and dark.
- v1.1 · 30 Oct 2026The site’s CTA buttons (graphite, pearl, glass and the circling beam) as a component; icons redrawn in the site’s two-tone style, with its 22 icons and the link arrow; Illustrations page.
- v1.0 · 30 Oct 2026First release: tokens in three tiers (224), light and dark themes checked for WCAG 2.2 AA, 26 components with playgrounds, 79 icons, CSS, DTCG JSON and an SVG sprite.
- Before v1Brand book v1.0 (27 Oct 2026): logo, colour, Geist, usage rules. Its eight brand colours are the anchors of the primitive ramps.
| Token | CSS variable | Light | Dark | Tier | Note |
|---|
Naming and rules
Naming
category · role · variant · state, written with dots in design tools and with dashes in CSS, behind the --dx- prefix.
color.bg.surface→--dx-bg-surfacecolor.action.primary.bg-hover→--dx-action-primary-bg-hovertype.title-2→--dx-font-title-2button.height.md→--dx-button-height-md
Rules
- Components read semantic or component tokens, never primitives.
- Add a primitive only when a semantic role needs a value that does not exist.
- A new theme is a new set of semantic values; primitives stay the same.
- Deprecate before deleting: keep the old name as an alias for one version.
Brand colours
The eight colours of the brand book. They anchor the ramps below, pinned to their exact values.
Brand gradient
135°, Sky to DIXI Blue. For marks, dots, bars and glows. Text never sits on its sky end (white on sky is 2.4:1).
Primitive palettes
Each ramp is generated in OKLCH, so steps look evenly spaced, and passes exactly through the brand anchors (dotted). Click a step to copy it.
Semantic colours
What components use. Each role has a light and a dark value; alpha values are shown over their own canvas. Click a name to copy its variable.
Background
| Token | Light | Dark | Use |
|---|
Border
| Token | Light | Dark | Use |
|---|
Text
| Token | Light | Dark | Use |
|---|
Accent and action
| Token | Light | Dark | Use |
|---|
Status
| Token | Light | Dark | Use |
|---|
Data
| Token | Light | Dark | Use |
|---|
Using colour
Neutrals do the work
About 80% of any screen is canvas and surface, 15% ink for text, and only the rest is colour.
Blue means action and data
Accent marks what you can click and the main data series. The gradient appears once per view, on decoration, never under text.
Status colours mean state
Green, amber and red only say good, needs work and failed, always next to a word or an icon.
Typefaces
Two families from one designer, so sans and mono share proportions.
Geist
Every word in the interface. Variable, 100–900; we use 400–700.
Aa
ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 — · → ±% $€₴
Geist Mono
Values people copy: hex, paths, code, token names.
#4461F0
--dx-accent-default · /client-portal · 0O 1lI
Type scale
14 styles. Type below to try your own words; click a style to copy its CSS.
Weights
Numbers
Tabular figures keep columns aligned and stop values from jumping when they change.
Proportional · default in text
- Visitors1,111
- Pageviews8,888
- Revenue$41,700
Tabular · font-variant-numeric: tabular-nums
- Visitors1,111
- Pageviews8,888
- Revenue$41,700
Rules
- Sentence case everywhere. Titles, buttons and labels: “Book a call”, not “Book A Call”.
- Tight tracking only when big. Negative letter-spacing from 18 px up; body text stays at 0.
- 60–75 characters per line. Paragraphs cap at about 680 px wide.
- Nothing below 11.5 px. Caption is the floor, and it is semibold to stay readable.
- Tabular figures for data. Tables, stat cards and anything that updates.
- One display style per screen. Display sizes are for the single most important line.
Spacing scale
4 px base with 2 px half-steps for tight UI. Names are the pixel value, so they never lie. Click a row to copy.
Semantic spacing
Use these names in layouts; they map to the scale and can change in one place.
| Token | Value | Use |
|---|---|---|
space.gutter | 12 px | Gap between cards and grid columns |
space.inset-card | 24 px | Padding inside a card (18 on phones) |
space.inset-tile | 16 px | Padding inside tiles and list rows |
space.stack-section | 40 px | Space above a new section |
space.stack-text | 8 px | Title to description |
space.page | 12 px | Outer page padding (8 on phones) |
App shell
- Sidebar 272 px, content takes the rest; 12 px gutter between them.
- Page padding 12 px (8 px on phones), so cards nearly touch the edge like an app.
- Cards snap to 2, 3, 4 or 5 equal columns with 12 px gaps.
- Below 1060 px the sidebar becomes a top bar with a scrolling nav.
Grid
12 columns, 12 px gutters. Stat rows use 4 spans of 3; project cards 3 spans of 4; brand colours 6 spans of 2.
Breakpoints
Width at which each layout change happens.
Layers
| Token | Value | Layer |
|---|---|---|
z.base | 0 | Content |
z.sticky | 5 | Sticky section bars |
z.toast | 50 | Toasts |
z.overlay | 60 | Menus, popovers, date picker |
z.modal | 70 | Dialogs and their backdrop |
Radius scale
Nine values, named by role. Click to copy the variable.
Nesting
The rule that keeps rounded UI calm.
Concentric: inner = outer − gap. Corners stay parallel.
Same radius inside: corners pinch and look off.
- Interactive pills (buttons, chips, badges, switches) are always radius.full.
- Cards are 24 px; compact cards 22; hero panels and dialogs 28.
- Media and tiles inside a card use the card radius minus the inset: 24 − 8 = 16.
- Fields are 14 px, not pills, so a form never looks like a row of buttons.
Levels
Most of the interface is flat on tint. Shadow means “this floats” or “this can be lifted”.
Values
In dark mode shadows barely show, so every level adds a light ring instead.
| Token | Light value | Use |
|---|---|---|
shadow.none | none | Cards sit on tint, not shadow |
shadow.ring | inset 0 0 0 1px #ECECEE | Raised items inside a surface |
shadow.raised | 0 1px 2px rgba(17, 17, 19, 0.05), 0 12px 32px -18px rgba(17, 17, 19, 0.22) | Sticky bars, hovered cards |
shadow.overlay | 0 0 0 1px #DCDCE0, 0 24px 60px -20px rgba(17, 17, 19, 0.35), 0 8px 20px -12px rgba(17, 17, 19, 0.2) | Menus, popovers, date picker |
shadow.modal | 0 0 0 1px rgba(17, 17, 19, 0.06), 0 40px 80px -24px rgba(17, 17, 19, 0.45) | Dialogs and toasts |
Durations
duration.fast200 msduration.base250 msduration.slow350 msduration.slower500 msduration.slowest600 msEasing
Press play to compare the curves over the same 900 ms.
ease.standard
Most UI motion: quick out, soft landing
cubic-bezier(0.2, 0.7, 0.2, 1)ease.spring
Toasts and confirmations: a small overshoot
cubic-bezier(0.2, 0.9, 0.3, 1.2)ease.in-out
Moves between two resting places
cubic-bezier(0.4, 0, 0.2, 1)ease.linear
Spinners, progress and the CTA beam
cubic-bezier(0, 0, 1, 1)ease.overshoot
CTA buttons and arrows: a quick, springy lift
cubic-bezier(0.3, 1.4, 0.5, 1)Rules
- Motion confirms, it doesn’t decorate. Every animation answers “did that work?” or “where did it go?”.
- Small and fast. Hover and focus: 200 ms. Most moves: 250–350 ms. Nothing over 600 ms.
- Ease out on entry. Things arrive fast and settle softly: ease.standard. Overshoot only for confirmations.
- Reduced motion means none. With prefers-reduced-motion every transition and animation is off.
Effects on dixi.agency and in the portal
Each card shows the effect in this page’s theme, where it is used and the code behind it. Press play to replay the ones that run once.
Reveal on scroll
Sections rise 24 px and fade in as they enter the screen. Scroll-driven CSS, no JavaScript; the first screen never hides.
.rv {
animation: rv linear both;
animation-timeline: view();
animation-range: entry 0% entry 60%;
}
@keyframes rv {
from { opacity: 0; transform: translateY(24px); }
}
.rv.rv-0 { animation: none; } /* first screen */Count-up numbers
Results count up once when they scroll in. A number already on screen at load keeps its real value, and the HTML always carries the final number.
const io = new IntersectionObserver((es) => es.forEach((e) => {
if (!e.isIntersecting) return;
io.unobserve(e.target);
const el = e.target, to = +el.dataset.to, t0 = performance.now();
const step = (t) => {
const k = Math.min(1, (t - t0) / 1200);
el.textContent = Math.round(to * (1 - (1 - k) ** 3)).toLocaleString('en-US');
if (k 1) requestAnimationFrame(step);
};
requestAnimationFrame(step);
}));Beam
A sky-to-white-to-blue arc circles the edge of the one main button on a page, every 3.4 s. The glow brightens on hover.
Hover lift
Cards and tiles lift 2–3 px with a soft blue glow, on a slight overshoot. Only things you can click lift.
.card {
transition: transform .35s var(--dx-ease-overshoot),
box-shadow var(--dx-duration-base);
}
.card:hover {
transform: translateY(-2px);
box-shadow: inset 0 0 0 1px var(--dx-border-default),
0 16px 30px -20px rgba(68, 97, 240, .6);
}Live pulse
A green dot with a ring that grows and fades every 1.8 s. Only for data that is live right now; one per view.
.dot {
width: 14px; height: 14px; border-radius: 50%;
background: var(--dx-success-solid);
animation: ring 1.8s infinite;
}
@keyframes ring {
0% { box-shadow: 0 0 0 0 rgb(47 180 90 / .5); }
80%, 100% { box-shadow: 0 0 0 14px rgb(47 180 90 / 0); }
}Poster, then video
Loops play only while on screen and pause off it. The poster stays until the video is really playing, then fades in 300 ms, so nothing flashes black.
video[data-auto] { opacity: 0; transition: opacity .3s; }
video[data-auto].is-pl { opacity: 1; }
/* the poster <img> sits underneath until .is-pl */Marquee
Rows of logos and work drift sideways with soft masked edges. Hover pauses; on the Work page you can drag them.
.mq {
overflow: hidden;
mask: linear-gradient(90deg, transparent 0, #000 6%, #000 94%, transparent 100%);
}
.mq-t { display: flex; width: max-content; animation: mq 40s linear infinite; }
.mq:hover .mq-t { animation-play-state: paused; }
@keyframes mq { to { transform: translateX(-50%); } }Glass
Menus, the cookie card and the contact pills float on a 16 px blur. Phones get a solid surface instead: blur costs frames there.
.glass {
background: color-mix(in srgb, var(--dx-bg-raised) 88%, transparent);
backdrop-filter: blur(16px) saturate(170%);
}
@media (max-width: 760px) {
.glass { backdrop-filter: none; background: var(--dx-bg-raised); }
}Reading progress
A 3 px bar across the top of long pages, sky to blue, with a soft glowing head. It appears after the first screen and fades out at the end.
.ar-prog i {
transform-origin: 0 50%;
transform: scaleX(var(--p, 0));
background: linear-gradient(90deg, #12B2FD 0%, #4461F0 70%, #7C90FF 100%);
box-shadow: 0 0 14px rgb(68 97 240 / .55);
}Rules
- One moving thing per view. The beam, a live dot or a playing loop: pick one. Everything else waits for a hover or a scroll.
- Motion follows the content. Reveals run once, counters once, loops only on screen. Nothing animates while it is out of view.
- Never hide content behind motion. The first screen is never hidden for a reveal; numbers are real in the HTML before they count.
- Reduced motion turns it all off. With prefers-reduced-motion, reveals, counters, loops, the beam and the pulses stop. The page is complete without them.
Library
Click an icon to inspect it; copy the SVG or the sprite snippet. Blue dots mark the icons drawn for dixi.agency.
on dixi.agency
Construction
The rules the site icons are drawn by. New icons follow them or they don’t ship.
24 px grid
2 px safe area on each side; shapes live in the 20 px keyline. Same grid as the site.
1.6 px stroke
One weight at every size. Round caps and joins, outlines only.
Two tones
The base takes currentColor; one detail takes the accent, --ia. Never more than one accent part.
Dashed accent
Secondary paths are dashed 2.1 / 2.5: the shackle, a meridian, the reply. It reads as motion or “in progress”.
Accent dots
Small filled dots mark the point that matters: today, the answer, the crumbs.
Mono in controls
Inside buttons, fields, chips, menus and badges the accent takes the text colour, so states stay readable.
Accent colour
One custom property, --ia, recolours the accent part. Set it on the icon or any parent.
--ia: var(--dx-accent-default)--ia: #12B2FD--ia: #E2795B--ia: currentColorLink arrow
The site’s own arrow: a dot, a dashed run-up and a head.
.mlar.mlar.is-hv.mlar<a class="mlar" href="/koyfincase">Read the case
<svg aria-hidden="true" width="22" height="16" viewBox="0 0 22 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
<circle cx="2.2" cy="8" r="1.3" fill="currentColor" stroke="none"/>
<path d="M5.5 8h7" stroke-dasharray="2 2.4"/>
<path d="M14 8h5.5M15.8 4.3 19.5 8l-3.7 3.7"/>
</svg>
</a>Problem cards
Home page, “The problem”. Each card draws one question a buyer leaves with, and the fix is written in the gradient.
Is this for me?
Visitors don't get what you do in 5 seconds.
+ One-line message
Can I trust this?
Not enough proof to book a demo or place an order.
+ Proof where doubt starts
Why now?
Nothing shows what changes for them after the call.
+ A reason to act now
What do I do next?
The next step is buried or unclear.
+ One obvious next step
Process steps
Home page, “Three steps”. The same rules at 112 px tall.
Discover & audit
A 25-minute call on your goals and traffic, then an audit of the journey, message and proof gaps, with a written plan of priorities.
Design
Key pages, flows and proof points, with weekly reviews directly with the founder. You see real progress every week.
Build & launch
We develop and launch what we designed, then track demos, orders and conversion and keep improving.
Palette
Illustrations always sit on the dark card, in both themes.
#17171AOuter card#121215Drawing area#0F1013Fills that hide lines behind#D1D2D8Main shapes, 1 px#6C6E78Secondary shapes, 0.75–1 px#8E9099Uppercase labels#12B2FD → #4461F0The one part that fails or fixes#7C90FFProcess cardsDrawing rules
One idea per drawing
Each drawing is a diagram of one sentence: the eye that can’t focus, the bridge with the missing beam.
Lines, not pictures
Strokes of 0.75, 1, 1.25 and 1.5 px on near-black. No fills except knock-outs that hide lines behind a shape.
One signal
Only the part that fails or fixes takes the sky-to-blue gradient. Everything else stays grey.
Labels are quiet
Uppercase Geist, 14–18 px, letter-spacing 1, in #8E9099. A label in the gradient is the answer.
Motion is slow and looping
Dashes flow, points breathe, nothing jumps. Loops of 1.6 to 5 s, off with reduced motion.
Always described
role="img" and an aria-label that says what the drawing means, not what it shows.
Motion
Animation classes from the site. Add one to a path or group; the drawing still reads with every class removed.
| Class | What moves | Change | Timing |
|---|---|---|---|
| .an-f8 | Dashes flow along the path | stroke-dashoffset 0 → −16 | 1.6 s linear, loop |
| .an-f7 | Same, for 3.5 / 3.5 dashes | 0 → −14 | 1.6 s linear, loop |
| .an-f12 | Same, for 6 / 6 dashes | 0 → −24 | 1.8 s linear, loop |
| .an-f135 | Same, for longer gaps | 0 → −27 | 1.9 s linear, loop |
| .an-p | The point that matters breathes | opacity 1 → .3 → 1 | 3 s ease-in-out, loop |
| .an-p2 | A softer pulse, for labels | opacity 1 → .6 → 1 | 3.2 s ease-in-out, loop |
| .an-r | Scattered rays fade | opacity 1 → .25 → 1 | 4 s ease-in-out, loop |
| .an-b | Arrows bob down | translateY 0 → 4 px | 3.4 s ease-in-out, loop |
| .an-s | The lens scans the line | translateX 0 → −8 px | 5 s ease-in-out, loop |
| .an-n | A nudge, kept off on the site | translate(7 px, −6 px) | 3.6 s, disabled |
.an-f8 { animation: af8 1.6s linear infinite; }
@keyframes af8 { to { stroke-dashoffset: -16; } }
.an-p { animation: ap 3s ease-in-out infinite; }
@keyframes ap { 50% { opacity: .3; } }
.an-s { animation: as 5s ease-in-out infinite; }
@keyframes as { 50% { transform: translateX(-8px); } }
@media (prefers-reduced-motion: reduce) {
[class*="an-"] { animation: none !important; }
}Contrast
Every text token on every surface, computed from the token values. AAA ≥ 7, AA ≥ 4.5, Large ≥ 3.
| Light | bg.canvas | bg.surface | bg.raised | bg.sunken |
|---|---|---|---|---|
| text.primary | 18.9AAA | 17.5AAA | 18.9AAA | 16.0AAA |
| text.secondary | 11.2AAA | 10.3AAA | 11.2AAA | 9.5AAA |
| text.tertiary | 5.9AA | 5.5AA | 5.9AA | 5.0AA |
| accent.default | 6.8AA | 6.3AA | 6.8AA | 5.8AA |
| success.fg | 5.4AA | 5.0AA | 5.4AA | 4.5AA |
| warning.fg | 7.5AAA | 6.9AA | 7.5AAA | 6.3AA |
| danger.fg | 6.6AA | 6.1AA | 6.6AA | 5.6AA |
| Dark | bg.canvas | bg.surface | bg.raised | bg.sunken |
|---|---|---|---|---|
| text.primary | 18.5AAA | 17.5AAA | 16.0AAA | 14.3AAA |
| text.secondary | 12.9AAA | 12.1AAA | 11.1AAA | 9.9AAA |
| text.tertiary | 7.5AAA | 7.1AAA | 6.5AA | 5.8AA |
| accent.default | 7.9AAA | 7.5AAA | 6.9AA | 6.1AA |
| success.fg | 10.6AAA | 9.9AAA | 9.1AAA | 8.1AAA |
| warning.fg | 11.8AAA | 11.1AAA | 10.2AAA | 9.1AAA |
| danger.fg | 8.8AAA | 8.3AAA | 7.6AAA | 6.8AA |
Check a pair
Clear in five seconds.
Body text at 15 px uses this pair.
Values follow the page theme: switch to dark to check the dark pair. AA needs 4.5:1 for text and 3:1 for large text and controls.
Focus
2 px Sky ring (#12B2FD) with a 2 px offset, on :focus-visible only, so mouse clicks stay clean. Sky has 3:1 or more against white and against Night.
Target size
DIXI controls start at 36 px; the 30 px inline button sits inside a larger field.
Keyboard
| Pattern | Keys | Used by |
|---|---|---|
| Activate | Enter Space | Buttons, chips, switches, checkboxes |
| Move within a group | ← → ↑ ↓ | Tabs, radio groups, menus |
| Close | Esc | Dialogs, menus, tooltips, the date picker |
| Jump | Home End | Tabs, menus, chart points |
Rules
- Colour is never alone. Status has a word, selection has a fill, links in text are underlined.
- Real elements. button, a, input, select, table, dialog. No clickable divs.
- Names for everything. Icon-only controls have aria-label; groups have legends; charts have a table view.
- Reduced motion. All transitions and animations stop when the system asks for less motion.
- Text can grow. Layouts hold at 200% zoom; nothing is fixed in height that holds text.
- Hover is never required. Anything shown on hover is also shown on focus and on tap.
Blocks on dixi.agency
The sections service, niche, case and article pages are built from, in this page’s theme. Each one names what it is made of.
From the first screen
to the App Store.
We design and build iOS and Android apps in React Native or in Swift and Kotlin.
KFCCHCTrusted by 40+ B2B tech companiesHero
Every service and niche page: breadcrumb, keyword line, a two-line headline with the gradient half, one line, the CTA pair and the trust row.
Proof numbers
Under the hero: four results with their source. Gradient numbers count up once.
Trust row
Client logos in grey, full colour on hover. Wraps under 420 px.
Built with
The tools behind a service, as logo chips. Two or three per row on phones.
Problem cards
Dark tiles with a line drawing each: the problem in the buyer’s words. Drawings on the Illustrations page.
Process
Five numbered steps, then the commitments. Three per row on tablets.
- Flows and UI
- Design system
- iOS + Android
- Released to the stores
- Swift + Kotlin
- Platform-specific UX
Formats and prices
Three formats, the recommended one ringed with “Start here”. Prices always say “from”.
“They turned a messy MVP into an app our users actually open every day.”
Founder, coaching appClient quote
One quote, a real face and role. Photo goes above the words under 560 px.
How much does a mobile app cost?
An app MVP starts at $28k and takes 10–16 weeks.
FAQ
Boxed accordion, questions as buyers ask them, mirrored in FAQPage JSON-LD.
- Web development
- SaaS product design
- Motion design for SaaS
Related
Three to five next pages, one list with dividers.
Calculator callout
Card that deep-links into the calculator with the right type preselected.
| Check | Target |
|---|---|
| Touch targets | 44 pt iOS · 48 dp Android |
| Contrast | WCAG 4.5:1 |
| Crash rate | under 1.09% |
Spec table
Numbers with their source: launch checks, vitals, store rules.
Have an app idea
or a stalled build?
Closing band
Dark band at the end of every page, in both themes, with the one beamed button.
Blocks in the portal
The pieces the portal pages are built from, in this page’s theme.
KPI tile
Analytics Summary: value, change against the previous period, sparkline, and a footer with the previous number and the baseline.
Funnel
Visit to revenue. Bars scaled by square root so small steps stay visible; the biggest drop is ringed.
Calls booked 4 of 7
Leads 16 of 11
Pace to target
Monthly and weekly targets scaled to the range. The tick is where you should be today.
Leela AIReplied: “Can you share examples?”
AnswerHoloSent 4 days ago, no reply
Follow upRevnuSeed $3M · fit 80
NewToday list
Top of Outreach: who to answer, who to follow up, who is new. Write opens the card with the right message type.
Backlog29
Sent3
Proposal sent1
Pipeline board
Columns per stage, cards with fit and days in stage. Drag to move; on phones one stage at a time.
- Cal.comBookings, every 5 minutesLive
- Search ConsoleDaily, lags about 2 daysDaily
- AttioAdd ATTIO_API_KEY to syncKey missing
Connected sources
Sources & reports: each source with what it brings and its state.
What’s new
Overview: the latest deliveries, newest first, each with a link.
Stage colours
The same eight colours on the board, in pickers, in Attio and in the weekly digest.
Read the ComboCurve case study for the numbers behind each module.
Selected: . Click a segment.
IG| Share |
|---|
Sort by
- Search Console
- +25B2B software / AI
- +15Raised 17 days ago
- +20Founder is the contact
- Proposal sent3 Nov · $18,000
- Call booked30 Oct
- Replied28 Oct
We count visits without cookies. With your OK we also record sessions to fix confusing pages. Cookie policy
Cookie settings
Pick what we may use. You can change it any time in the footer.
- NecessarySign-in, the theme you picked, this choice. Always on.Necessary
- AnalyticsMicrosoft Clarity recordings and heatmaps.Analytics
- MarketingApollo.io company lookup.Marketing
Hi! Ask me anything about working with DIXI.
How much is a mobile app?
An app MVP for iOS and Android in React Native starts at $28k and takes 10–16 weeks.
On dixi.agency
The buttons as they ship on the site, with the place each one lives. The site is light by default; its dark band is the teardown block.
.bd.bw.cta-lg.bl.cta-nav.bl + .bd.bl.cta-sm.bd.cta-sm.hx .bl.bw.bs.dk .bd.bw.bd.cta-lgStyles and themes
Graphite is the primary action and pearl the secondary. In dark theme they swap materials, so the primary is always the brightest thing on the page.
Dark · .bd
Primary. Graphite with a bevelled rim on light pages; pearl with a blue glow in dark theme.
Light · .bl
Secondary. Pearl on light pages, graphite in dark theme. Inside the dark band it stays pearl.
Glass · .bs
Frosted, 14 px blur, over dark bands and images only. Phones drop the blur for speed.
Beam
A 130° arc of light runs around the edge once every 3.4 s. It marks the one action we want clicked on the page.
How it is built
A registered angle, @property --a, turns from 0 to 360° on a linear curve, animated on the two pseudo-elements so it stays on the compositor. They paint a 1.5 px ring masked to the border and a 12 px glow blurred by 10 px behind the button.
Spec
- Lap
- 3.4 s, linear, infinite
- Arc
- 230° → 360° (130°)
- Colours
- #12B2FD → #FFFFFF → #4461F0
- Ring
- 1.5 px, masked to the edge
- Glow
- 12 px, blur 10 px, 55% → 100% on hover
- Hover
- lift 1 px, ease.overshoot, 250 ms
- Press
- down 1 px, scale .985
- Reduced motion
- the beam stops; the ring stays
Sizes
The site sets these inline; the system names them. 54 for heroes, 48 by default, 42 in menus, cards and lists, 36 in dense rows.
.cta-lg.cta-md.cta-sm.cta-xs.cta-navStates
Hover, pressed and focus are forced so you can compare them. Hover brightens graphite and glass, deepens the pearl shadow and wakes the glow.
Anatomy
- FillGraphite #3B3C42 → #1D1E21 → #111113, top to bottom, in the padding box.
- Bevel edgeA 1.5 px transparent border painted with a 165° light-dark-light gradient. Reads as a machined rim.
- Inner lightTwo inset shadows: a 1 px top highlight and a soft glow along the bottom.
- Beam ringConic arc, sky → white → blue, masked to the edge. One lap every 3.4 s.
- GlowThe same arc, 12 px wide and blurred, behind the button. 55% at rest, full on hover.
- Label and iconGeist 500 with a 1 px text shadow. Optional 16 px arrow, 2 px stroke, slides 3 px on hover.
Variants
Pick by weight, not by colour. One primary per view; everything else steps down.
.bt-p.bt-s.bt-g.bt-a.bt-d.bt-w.bt-glSizes
36, 42 and 50 px tall. Medium is the default; Large is for sign-in and checkout forms.
.bt-sm.bt.bt-lgStates
Hover, pressed and focus are forced here so you can compare them side by side.
Anatomy
- ContainerPill, 36 / 42 / 50 px. Padding 14 / 18 / 24 px.
button.height.* - Leading icon16 px, names the object: calendar, download, mail.
- LabelLabel type, 13.5 to 15.5 px, medium. A verb first, three words at most.
- Trailing iconAn arrow for navigation. Moves 2 px on hover.
Variants and sizes
.ib.ib-g.ib-p.ib-xs .ib-sm .ib-lgStates
Kinds
.lk.lk.lk-x.lk.lk-bSee the pricing page for formats.
.tl.lkIn use
.seg.seg.seg-sm.seg.seg-ioExamples
.fldfld-l em.is-err.fld-pill.fld-md.fld-x.is-disAnatomy
- LabelSubhead, 13.5 px, medium, text.secondary. Always visible.
- Container50 px (42 px medium), radius.field, 1 px border that becomes a 2 px accent ring on focus.
- Leading iconOptional, 16 px, text.tertiary.
- Value16 px, so iOS never zooms the page.
- Helper or errorFootnote, 12.5 px. Becomes the error message and is linked with aria-describedby.
Compact pill in a table
Change a status in place. The tone follows the value.
.sp.tn-*States
In a group
A fieldset with a legend names the group.
fieldset.rgWith descriptions
fieldset.rg.rg-h.rdoSettings list
Switches take effect at once. In a form with a Save button, use checkboxes instead.
.swt-r.swt-sm.is-hv .is-fc .is-disStates
.is-ok.is-errTones
Soft fills keep a page calm; the solid badge is for one “new” at a time.
.st .st-acc .st-ok .st-wn .st-bad.st-ol.st-solid.st .i.st-smFilter group
One group, one selection; “All” resets.
.chips.chip-sm.chip-xSizes and groups

.av-24 … .av-56.av · .av-ic.avg.av-sqIn a row
Four across on desktop, two on phones. Bounce rate going down is good, so it is green.
Anatomy
- LabelWhat is counted, in plain words.
- Value34 px semibold, tabular figures.
stat.value.size - ChangeGreen when good, red when bad, whatever the sign.
- ComparisonThe period it is compared with. Never omitted.
- SparklineOptional trend over the period, data.1 with a soft fill.
Rich cells
Badges, pill selects and links live inside cells; numbers stay right-aligned.
| Date | Who | Type | Source | Stage | Value |
|---|---|---|---|---|---|
| 27 Oct | Fintech SaaS · Series A | Call booked | $12,000 | ||
| 26 Oct | DTC skincare brand | Teardown | — | ||
| 21 Oct | Energy software | Brief | $24,000 |
Sample rows.
In use
.pb.mtr.spn.ringPlacements
Top is the default. Flip to stay inside the screen.
.tip-t.tip-r.tip-b.tip-lTones
.al.al-ok.al-wn.al-bad.al-bnTones
.tst.tst.tn-n.tst.tn-bad.tst buttonPatterns
.sk.kpi + .sk.sk-pContexts
No files match “logo dark”
Try a shorter word or clear the filters.
.empNo visitors yet
Numbers appear with the first visit. Check back in an hour.
.empCould not load this report
We retry every minute.
.emp.tn-badStyles
.tabs.tabs-uSidebar
The full portal nav: five destinations, one current.
Anatomy of a menu
.miVariants
What’s new
Latest deliveries from your team.
.crdYour numbers, explained
30 minutes with Ignat.
.crd-vQuarterly growth review
Three changes worth making next.
.crd-brThree triggers
The menu is the same; the trigger fits where it sits.
.ddn-fld.ddn-bare.ddn-pill.ddn-b:disabledOn phones
Under 760 px the button hands over to the native select it sits on, so people get the system wheel or sheet.
Desktop
DIXI menu: 16 px radius, raised surface, overlay shadow, check on the selected option, opens up when there is no room below.
Phones
The hidden select.ddn-n takes the tap. Same value, same change event, no second code path.
Anatomy
Track 8 px with the brand gradient up to the thumb; a 30 px pearl thumb that grows on drag; the value sits above, in the heading row.
input.sld.sld.is-fcinput.sld:disabledStates
Selected adds a 1.5 px accent ring and a 4 px halo; hover lifts 2 px with a blue glow.
.opc.opc.is-on.opc.is-disIndicators
Seven states, each with its own word. The live dot breathes; syncing turns; nothing else moves.
.sts-live .sts-ok.sts-sync .sts-wait.sts-warn .sts-err.sts-offIn context
How the portal uses them.
- Cal.comBookings, every 5 minutesLive
- Search ConsoleDaily, lags about 2 daysDaily
- ChatGPTNo API key: switched offOff
- AttioAdd ATTIO_API_KEY to syncKey missing
.sts-row.sts-st.sts-sy.sts-fr.sts-blWhere each style lives
.bcr-sl.bcr-c.bcr-dt.bcr-ellFull panel
Glass panel under the header: 16 px blur on desktop, a solid surface on phones, where the menu becomes a full-screen sheet with the same groups.
.mgmBoth steps
The banner sits bottom-left and never blocks the page; settings open as a dialog over a blurred scrim.
We count visits without cookies. With your OK we also record sessions to fix confusing pages. Cookie policy
.ckx-bCookie settings
Pick what we may use. You can change it any time in the footer.
- NecessarySign-in, the theme you picked, this choice. Always on.Necessary
- AnalyticsMicrosoft Clarity recordings and heatmaps.Analytics
- MarketingApollo.io company lookup.Marketing
.ckx-mParts
.asx-mHi! Ask me anything about working with DIXI.
How much is a mobile app?
An app MVP for iOS and Android in React Native starts at $28k and takes 10–16 weeks.
.asx-p.asx-fabStyles
Boxed cards on service pages; a divided list in articles and the portal.
How much does a mobile app cost with DIXI?
An app MVP for iOS and Android in React Native starts at $28k and takes 10–16 weeks. Design for your engineers starts at $12k.
Do you write the copy?
On request, as a paid add-on: messaging and copy add $2k–4k to a website.
.acd-boxWill we lose SEO when we move?
No: every old URL gets a 301 and the pages keep their titles, headings and structured data.
Do you write the copy?
On request, as a paid add-on: messaging and copy add $2k–4k to a website.
.acd-listUsage
Do
Don’t
Accessibility
Keyboard
Notes
API
Props for the React component and the CSS that implements each one.
| Prop | Type | Default | Description | HTML / CSS |
|---|
Tokens used
Click to copy the variable.