The Engine Design System.

Tokens, components and the landing page formula for every Engine surface, published as @engineio/ui. Everything on this page is the shipped component. The rules ship with it as AGENTS.md, so the tools that build Engine surfaces read the same ones.

  • Engine Studio
  • Engine Integration
  • engine.io
  • The approval queue
  • Insights
  • Provably fair
  • The operator portal
  • Studio docs

Brand.

The rules every Engine surface follows: architecture, marks, colour, type, shape, space, motion, imagery and voice.

Architecture.

Engine is a B2B iGaming platform. The promise is speed. The platform is the product, not the player experience. Nothing here uses the visual language of a casino: no coins, no jackpots, no gold, no celebration.

Master brand

Engine

engine.io owns everything above the two products: marketing, the corporate story, recruitment, stationery. Master-brand surfaces carry the wordmark, never a sub-brand lockup.

Engine Studio.

Build and publish. Creators build games on Engine; Engine publishes them on Stake. Addresses creators and studios.

Home
studio.engine.io
Subject
The machined and constructed. Rigs, keycaps, tooling.
Engine Integration.

Distribution. Casinos integrate against Engine's docs, pull down Engine Studio games and run them on a revenue share. Addresses operators.

Home
integration.engine.io
Subject
The connective. Pipework, manifolds, junctions.

Magenta is the accent on both. One accent per surface, never two.

Naming

Write sub-brands in full on first use. Engine Studio, Engine Integration. Never abbreviate to ES or EI. Once a lockup has established which product is speaking, later references on the same surface may shorten to Studio or Integration. The master brand is Engine, never the Engine platform. Audiences do not mix: a Studio surface does not sell catalogue size, an Integration surface does not sell build tooling, and neither speaks to players.

Marks.

Vector artwork from the brand team, in the only two colourways the brand sanctions. Pure White for dark surfaces, Off Black for print and inverted panels. The wordmark is a custom soft-rounded face, not DM Sans. It is artwork, never set in type and never approximated. The figure mark is the turbo — the wordmark's g is retired as a standalone mark and does not come back.

Wordmark, for master brand surfaces

Engine

Figure mark, the turbo

Engine

Secondary, on an inverted panel

Engine

Scale by height only, never both dimensions

Colour is a two-value variant and not currentColor. With currentColor, any ancestor's text colour silently becomes brand colour, and a magenta wordmark is one careless text-primary away. Size by height alone. The brand forbids distortion, and neither the turbo's 1001:1000 — square to the eye, not to the box — nor the wordmark's 2001:732.5 is a ratio anybody reproduces by hand.

Colour.

The brand is three colours. Everything else is a neutral step between the outer two. One accent per surface, never two. No gradients, no coloured borders, no light theme.

Brand

Off Black

#0E0E0E

--color-background

Pure White

#FFFFFF

--color-foreground

Magenta

#FF006A

--color-primary

Magenta Press

#D60059

--color-primary-press

Neutral ramp

grey-950

grey-900

grey-850

grey-800

grey-700

grey-600

grey-500

grey-400

grey-300

grey-200

grey-100

grey-050

Status, functional only

8.37:1

Success

#00C46A

--color-success

10.56:1

Warning

#FFB020

--color-warning

5.44:1

Danger

#FF3B30

--color-danger

Status is functional colour. It reports state and nothing else. It is never decoration, never a second accent, and never a stand-in for magenta. Ink on a status fill is always Off Black, because white fails AA on all three. There is no info colour. Use the neutral ramp for informational states.

Typography.

DM Sans only. Bold for display, Semibold for UI labels, Regular for body. Title Case for headlines, UPPERCASE only for small structural labels. No all-caps headlines, no italics, no other typefaces.

Display 1

Accelerate Growth.

Display 2

Accelerate Growth.

Headline

Accelerate Growth.

H1

Accelerate Growth.

H2

Accelerate Growth.

H3

Accelerate Growth.

Subtitle

Accelerate Growth.

Body

Accelerate Growth.

Caption

Accelerate Growth.

Mono

GAME_ID 7f3a91c2 · RTP 96.42% · 2300 live games

Condensed roles

2300 Games.

DM Sans has no condensed cut. --font-condensed and --font-extra-condensed remain as roles and resolve to the brand face, so big numbers and poster-scale words are set in DM Sans Black until the brand team assigns a condensed face. Display type is large: 92 to 104px on a 1480px page. Scaling Display 1 down to 48px does not produce a smaller display size. It produces an H1.

DM Sans is a variable Google Font under the Open Font Licence: weight 100 to 1000, and an optical-size axis from 9 to 40, so body sizes get the looser cut and display sizes the tight one. There is no substitute face. A machine that cannot reach Google renders a size-adjusted Helvetica Neue or Arial matched to DM Sans's width, which the package ships as "DM Sans Fallback". --font-mono resolves to the brand face; JetBrains Mono is retired, and a product that needs character-cell alignment binds its own monospace.

Shape.

Radii by role, never mixed arbitrarily on one surface. The outer frame is always larger than the inner panel. Two border weights only: 1px hairline for structure, 1.5px for container rules.

Radii

Tag

6px

Field

10px

Media

14px

Card

18px

Frame

26px

Control

999px

Border weights

Hairline

1px · structure

Container rule

1.5px · cards and panels

Nesting, outer frame always larger

26 → 18 → 10

Depth comes from rules and nested panels, not shadow. The package holds two shadow tokens, --shadow-panel and --shadow-modal, and both are for product chrome and modals. Neither belongs on a brand surface. Neither is a substitute for the rule that should have been there.

Space.

1480px page, 40px gutters, and 920px for anything anyone has to read. Spacing is 4px-based, with large jumps at 56 / 72 / 96 / 128 for section rhythm and 12 to 20px within a group. Rhythm comes from the gap between groups being clearly larger than the gap inside one.

Widths

Page

1480px maximum, 40px gutters, 72px on large brand pages, for product surfaces. This page is not one: it sits on the 1180px marketing column described under Marketing.

Reading

920px, and this paragraph stops there. Body copy that runs the full 1480px is unreadable however correct the type scale is.

Brand page

1480 × 836. Slides and statement pages are drawn at that ratio.

Card

20px padding, 28px on the large variant.

Section rhythm, the large jumps

56px

72px

96px

128px

Within a group

2

4

6

8

12

16

20

24

32

40

Signature composition, big type flush to a bottom corner

Accelerate Growth.

The hairline sits 14px from the top, inset 24px each side, and the type is set flush to the bottom-left instead of centred. That is the deck's signature composition. Centring it is the most common way a page stops looking like Engine.

Motion.

Fast and mechanical, to match the promise of speed. 140ms for control states, 220ms for surfaces, 360 to 640ms for reveals. Entrances ease out, exits accelerate, presses scale to 0.98. Never bounce, never spring, never parallax, never a looping decorative animation.

Durations

Instant

80ms

Anything that should not be seen moving at all.

Fast

140ms

Control states: hover, press, focus, the switch knob.

Base

220ms

Surfaces: dialogs, popovers, the tab marker.

Slow

360ms

Reveals on a product surface.

Reveal

640ms

The longest move the brand allows.

Easings, run side by side

Same distance, same 640ms, three curves.

ease-brand

cubic-bezier(.2,0,.2,1)

Control states, in and out.

ease-brand-out

cubic-bezier(.16,1,.3,1)

Entrances on surfaces and reveals.

ease-brand-accelerate

cubic-bezier(.6,0,.3,1)

Exits, and nothing else.

Reveal, 8px up with a fade and never further

Make Ambition Move Faster.

Motion is fast, but it is never mandatory. prefers-reduced-motion drops everything to fades, and the package's base layer already does that globally. A product importing @engineio/ui/styles gets it without writing a line. Turn the setting on and press Run again. The blocks jump, and nothing on this page breaks.

Imagery.

Black-and-white photographs and renders of machined objects: turbines, rigs, pipework, schematics, keycaps. Cool, hard, high-contrast, slightly clinical. Some frames read as technical drawings with faint annotation type. Occasionally one tiny point of magenta light in an otherwise monochrome frame, and no more than one.

Treatment: 14px crop, badge top-right, scrim under type

Rigs · Keycaps · Tooling

Engine Studio
Build. Publish.

Pipework · Manifolds · Junctions

Engine Integration
Integrate Once.

Never people. Never warm tones. Never stock-office imagery. No handshakes, no laptops, no meeting rooms. Always cropped into a rounded rectangle at the media radius or bled to the page edge, with the sub-brand badge top-right. Type over photography gets the bottom-up black scrim, not a capsule and not a box. Subject leans by sub-brand and the grade never does. Studio takes the machined and constructed, Integration the connective, both monochrome.

The two frames hold no photography. None ships in this package, and filling them with a stand-in would put an image into the design system that the brand never approved. The scrim under the type is the only gradient the brand permits. Backgrounds are one of three things, and photography is the third: flat Off Black, flat white for print and letterhead, or full-bleed monochrome. No patterns, no textures, no illustration, no noise.

Voice.

Declarative, mechanical, confident. Short sentences that end in a full stop, headlines included. Second person for the customer, third person for Engine. Engine rarely says we. Register is plain and commercial: no showmanship, no exclamation marks.

Sentence shapes

Claim + mechanism

Accelerate Growth. The platform to build, publish and scale in the iGaming space.

Instruction + payoff

Integrate once with Engine to grow your casino catalogue with tested and proven games.

Question + answer

Thinking of growing your online casino offering? Engine Integration gives you access to over 2300 live games.

Numbers front-loaded

Over 2300 live games.

Engine writes, and does not

Written

Not written

Why

Accelerate Growth.

Accelerate growth!

Headlines end in a full stop. The stop lands the claim; an exclamation mark undoes it.

Build on Engine.

We will help you build.

Third person for Engine. Engine rarely says we.

Your catalogue, live on every operator.

The client catalogue, live on every operator.

Second person for the customer.

Colour, catalogue, favours, turbocharge.

Color, catalog, favors.

Spelling is British and Australian throughout.

Publish Game

PUBLISH GAME

Title Case for headlines and controls. Uppercase is for small structural labels only.

No emoji. Anywhere. Not in brand material, not in product UI, not in copy, and not in a commit message that ends up in release notes. The only non-alphanumeric glyphs the brand sanctions are the multiplication sign for a close control and the brand's asterisk for footnotes. This is the one voice rule with a grep behind it. CI scans the source and fails the build, because a design system that only asks nicely gets one eventually.

Components.

Twenty primitives from the package. Add a variant in your product by extending the exported variant map. Do not fork one.

Button.

Pill controls at 32 / 40 / 48px, Bold 15px labels, 140ms mechanical transitions, a 0.98 press and a 2px magenta focus ring. Tab through them. The ring is never removed.

Variants

Sizes

States

Badge.

One chip for every job, in the soft repository-label treatment: tinted fill, matching ink, 6px radius. Fills are translucent by design, so a chip reads the same on the page, on a card and on a table tile.

Brand and neutral

featured documentation archived

Status, functional only

certified needs review blocked

The same chips on a card surface

featured documentation archived certified blocked

There is no solid variant. An opaque fill can only be right on one surface, and these chips have to read on the page, on a card and in a table cell. The status variants are functional, not categorical. Reach for success when something has succeeded, never because green suited the row. The brand chip's ink is primary-300 and not pure magenta, because magenta on its own tint is 4.37:1 and the brand forbids magenta text below 15px bold.

Alert.

The panel is always neutral. A 3px bar down the left edge is the only thing that says good, bad or warning. The fill, the rule and the type never change. A column of alerts reads as one surface with state down its side, not as four different components.

The bar is aria-hidden, so the title has to carry the message with the colour ignored entirely. "Upload failed." beats "Error." The neutral variant takes a grey bar instead of none, so a mixed stack keeps its left edge. Pass onDismiss to get the close control, and omit it for a static alert.

Fields.

40px height, 10px radius, 1px hairline border on the grey ramp. Focus swaps the border to magenta and adds the ring. All three share the `field` utility, so the focus treatment is defined exactly once.

Controls.

Checkbox at 18px with a 6px radius, radio as an 18px circle, switch as a 44 × 24 track. Magenta fill when on, knob travels in 140ms.

Switch

Enabled

Checkbox

Radio

Progress

64%

Card.

Off-black panel, 1.5px rule, 18px radius, with an inner panel at 10px holding artwork. Hover lifts the rule. Not a shadow, not a transform.

Turbine.

Monochrome machined objects. Never people, never warm tones.

Inner panel · 10px
Engine Studio
Manifold.

Monochrome machined objects. Never people, never warm tones.

Inner panel · 10px
Engine Studio
Keycap.

Monochrome machined objects. Never people, never warm tones.

Inner panel · 10px
Engine Studio

Tabs.

Two flavours. Pill is the default. Underline is the section-level treatment: a hairline rule with a 2px magenta marker under the active tab. No pill-background tabs at section level.

Pill tabs, for switching a panel's contents.
Underline tabs, for navigating a page's sections.

Overlays.

Dialog scrim is rgba(10,10,10,.72) with an 18px blur. This and the sticky header are the only sanctioned uses of blur. Panels enter over 220ms and exit over 140ms.

Dialog, Popover, Tooltip

Responsive dialog

Table.

Ruled, not tiled. No frame, no fills, no gaps. The surface behind shows through, and a hairline under each row does all the structural work. Headings are Bold 13px in Pure White, Title Case, separated from the body by a rule one step stronger than the dividers.

Game Studio RTP Status
Turbine Rush Northwind 96.42% live
Manifold Grayscale 95.18% draft
Keycap Klondike Northwind 96.01% live
Pipework Grayscale 94.87% draft
4 games 2 studios 95.87%

Hover a row for the 6% white wash. The second row is data-state="selected", which takes the magenta tint. Never a coloured border or an edge accent, both of which the brand rules out. Because the cells carry no fill there are no fill collisions. A Badge, a Separator or an unchecked Switch reads correctly in any column, which the gapped-tile treatment could not promise.

Skeleton and Separator.

Loading states stay on the grey ramp. A divider is a 1px hairline, never a coloured rule.

Below the rule.

Marketing.

The landing page formula: an 1180px column, four text sizes, a glass header, and motion that plays once and lands on its end state. This page uses it.

Page.

A logged-out landing is read once, top to bottom, by a stranger. It is narrower than a product page, breathes more and says less per screen. The two Engine landings settled this formula in September 2026 and calibrated it against stripe.com: an 1180px column, fluid gutters and rhythm, a glass header with no rules, a left-aligned hero with the art to its right, and a logo marquee before the first section.

Column and rhythm

--container-marketing

1180px

max-w-marketing — the column. Content starts at x=194 on 1440.

--spacing-gutter

clamp(20px, 5vw, 64px)

px-gutter — the side padding, fluid.

--spacing-section

clamp(88px, 12vw, 160px)

mt-section, pb-section — the gap before every h2.

--spacing-header / -sm

72px / 64px

h-header, -top-header — the glass bar, and where hero art starts.

--spacing-anchor / -sm

120px / 96px

scroll-mt-anchor — header plus breathing room for #links.

--blur-glass

20px

glass — 65% page colour over the blur, always on.

Banner, header, hero and marquee, as shipped

Are you a creator? Games are built and published on Engine Studio. Go to Engine Studio Opens in a new tab.

A Modern Take on the Traditional Aggregator.

Thousands of publishers, one contract, one invoice, completely standardised behind one integration. Forget the negotiations and focus on what actually matters. Apply and go live today.

  • Northwind
  • Bolt & Bracket
  • Millwright
  • Anvil Works
  • Cold Forge
  • Keycap
  • Manifold
  • Turbine

The header is `static` here only so the gallery can scroll past it. On a page it is sticky and the hero's art layer starts at its top edge, so the render shows through the glass at rest. The marquee takes real logos as images — white on transparent, fitted to one box — and this one renders text tiles through the `item` snippet.

Type.

Four sizes and a standfirst, each a whole spec on one utility: size, leading, tracking and weight together, so text-hero is the h1 and not a font size. Headings are capped in ch and balanced. Base text is white; grey is reserved for meaning.

text-hero

clamp(38px, 5vw, 64px) · 1.02 · −0.02em · 700

max-w-[18ch]

A Modern Take on the Traditional Aggregator.

text-section

clamp(28px, 3.2vw, 44px) · 1.06 · −0.02em · 700

max-w-[26ch]

Every operator and every creator is on the same simplified contract.

text-standfirst

clamp(18px, 1.5vw, 22px) · 1.5

max-w-[54ch]

One contract, one invoice, completely standardised behind one integration. Forget the negotiations and focus on what actually matters. Apply and go live today.

text-lead

clamp(17px, 1.4vw, 20px) · 1.5

max-w-[52ch]

You just need to pay the invoice, and we will settle with the creators.

text-card-title

17px · 1.35 · 600

max-w-[40ch]

Near real-time analytics, see exactly how the integration is performing.

text-stat

42px · 0.94 · 900 · tabular

9.7B+

text-small

13px · 1.5

Platform-wide totals, live from engine.io.

No uppercase, no mono and no eyebrows on a landing. The page has four sizes of type; a tracked label is a fifth. Inside a mock screen the scale drops again — 15px bold titles, 11 to 13px text, 10px tags — because a mock is a picture of a product, not the page.

Motion grammar.

A mock screen is a scene. Its elements rise in 140ms apart, fills sweep from the left, bars climb from the bottom, and three seconds in — once the reader has taken it in — the confirmation settles and a pending tag swaps to done. Every utility is global, honours prefers-reduced-motion by landing on its end state, and can be held paused by a motion-gate until the block is on screen.

Timings

--motion-reveal

700ms

rise — an element arriving on a scene.

--motion-stagger

140ms

Between siblings, multiplied by --i.

--motion-fill

1400ms

sweep — a gauge or split bar filling.

--motion-settle

3000ms

settle, swap — the confirmation, once the screen has been read.

--motion-swap

300ms

The outgoing half of a swap, and every fade-out.

--motion-pulse

2400ms

live-dot — one breath.

--motion-step

8000ms

One Tour step.

--motion-beat

3000ms

The bento metronome. One card moves per beat.

The scene, replayed

Fields rise, the gauge sweeps, the tag swaps at three seconds.

Exposure limits.

Unsaved Saved
Maximum exposure

100,000.00 USD

Maximum bet cost

500.00 USD

Save exposure limits Saved. Live

Rules learned the expensive way. Nothing plays until it is on screen. Rotating rows never use rise — the stagger leaves a hole — they use Svelte fly, flip and fade. A reveal is opacity only, because a translate on it makes every anchor scroll land short. And when several things on a page rotate they share one beat and take turns, so only one thing is ever moving.

Tour.

The Stripe-style product walkthrough. A numbered step list beside a browser-frame mock, one screen per step, one callout hanging off the frame's corner, advancing on the progress bar's own animationend every eight seconds and paused while off screen. The shell is the component; the screens are yours, built from the motion grammar.

Choose a step

Application.

Your name, your website and a few lines on what you do.

Sign in / Apply for access

Clicking a step is the only control — no hover pause, no pause button, both tried and removed. The mock is decorative; the step list and the callout carry everything it shows. Under reduced motion the timer is off, not fast: a 0.01ms fill would advance every step in one frame.

Bento.

Six columns from lg: a wide card spans three, a narrow one two. Each card is a cropped product mock over one sentence. The grid holds every scene paused until a quarter of it is on screen, then starts them together, and ticks one shared 3s beat so rotating cards take turns.

You keep

93%

Creators

5%

Engine

2%

One agreement for every operator and every creator.

Top games, past 30 days
  • Turbine Rush by Northwind $575M
  • Keycap Clash by Bolt & Bracket $298M
  • Pipework by Millwright $273M
  • Cold Forge by Anvil Works $112M

Near real-time analytics, see exactly how the integration is performing.

INV-2026-07

Due in 20 days Paid
Total due, 7% of GGR 28,845.60 USD
Pay invoice Creators settled.

Simplified billing. One invoice a month, then Engine settles with the creators.

GGR per day Live

GGR per day, for every game you run.

  • Turbine Rush
  • Keycap Clash
  • Pipework
  • Cold Forge
  • Manifold
  • Gantry

A catalogue of network games as soon as you integrate.

The screen runs off the card's bottom edge on purpose — design the mock to be cut. Two surfaces and no borders: card over page, page colour inside. One sentence per card, as an h3, with a full stop; the mock shows the thing and the sentence names it.

Proof.

Four figures that count up on sight, each with a magenta plus. The plus is a promise — it says at least this — so floor the figures before passing them, never round up. The caption says where the numbers come from and when.

The infrastructure behind Engine is already powering serious volume.

Proven and reliable at scale. Engine already powers Stake, the largest casino in the world.

3,800+ Games built on Engine
1,100+ Creators on Engine
9.7B+ Bets processed
$23B+ Turnover processed

Platform-wide totals as of September 2026. Games are released per operator.

SectionHead above it is the h2 and lead every section opens with, and mt-section is the rhythm between blocks — here overridden to zero because the gallery section already spaced it. Sentence case, a full stop, 26ch, balanced. No eyebrow above it; the landings removed every one.

For agents.

The rules ship inside the package as AGENTS.md. Point your tools at it. This exists to help automation converge on one system, not to enforce a style.

3 Brand colours
20 Primitives
10 Marketing components
4 Checks in CI

Counted from the package this page imports.

AGENTS.md.

Every rule on this page is in AGENTS.md. It ships inside the package at node_modules/@engineio/ui/AGENTS.md and versions with the components. The same file is served here at /AGENTS.md for a tool with nothing installed.

In a consumer's CLAUDE.md or AGENTS.md, one line does it

UI is built on `@engineio/ui`. Read `node_modules/@engineio/ui/AGENTS.md`
before writing or reviewing any UI.

Point at the path. Do not copy the rules into a repo; the copy goes stale on the next version. The repo also carries a Claude Code skill that is only that pointer.

Setup.

Tailwind 4 does not scan node_modules, so the @source line is required; without it the page half-styles with no error. The brand face is DM Sans from Google Fonts: the package names it and ships the fallback behind it, and you add the link to app.html. Skip that and the page renders in the fallback, also with no error.

app.css

@import "tailwindcss";
@import "@engineio/ui/styles";
@source "../node_modules/@engineio/ui/dist";

app.html

<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&display=swap" rel="stylesheet" />

CI checks.

Four greps fail the build. All four happened in the products first.

Raw hex literals

Every colour is a token. A literal is a colour nobody can find or change.

ci

Tailwind's stock palette

The brand has three colours and a grey ramp. A stock green is a status colour someone invented.

ci

Retired sub-brand colours

Originals Orange and Sportsbook Blue have no owner, so they are not available.

ci

Emoji

None, anywhere. The only sanctioned glyphs beyond letters and numbers are the close sign and the footnote mark.

ci

Purpose.

Engine surfaces are built by people and by agents. A rule written here once does not have to be rediscovered, and a component shipped here once does not have to be rebuilt. Where this page does not cover a case, choose the quieter option and flag the gap. Where it disagrees with the brand documents, the documents win.

Do not.

The prohibitions in one list. Four are grep checks in CI and fail the build.

No gradients, glows or coloured shadows. The scrim over photography is the one exception.

No two accents on one surface.

No colour outside the three brand colours, the neutral ramp and the three status colours.

ci

No info colour. Use the neutral ramp for informational states.

ci

No raw hex literals in component source. Use a token.

ci

No body copy in magenta, and no magenta text below 15px bold.

No drop shadows on cards or brand surfaces.

No coloured left border to indicate category or ownership.

No setting the wordmark in a typeface, and no approximating it in a lookalike.

No all-caps headlines. No italics. No other typefaces.

No emoji, illustration, textures, patterns or noise.

ci

No photography of people, no warm tones, no stock office scenes.

No light-mode variant.

No casino iconography. No coins, chips, jackpots, gold or celebration.

No scaling display type down to 48px and calling it display.

When something is not covered here, choose the option that is quieter and more mechanical. That resolves most of what this list does not.