Landing

IQUIT.GG design system

Every colour, size, and timing value below is read from the tokens in @iquit/ui. Contrast ratios are measured against the ground at render time, not quoted from memory. The same token values drive the React Native app, so the two platforms differ in rendering, never in specification.

Light

One rule governs every surface: light comes from directly above the screen. Raised elements catch a 1px specular line on their top edge and cast a shadow below; recessed elements take the shadow on their top inner edge and catch light on their bottom. Surfaces are the same cool light at increasing intensity over the ground, so they stack: a surface on a surface is automatically brighter, which opaque greys cannot do.

Surface intensities reproduce the brand-locked greys almost exactly (5.0% lands on #1A1C25 against the locked #1A1C26; 12.5% is #262936 exactly), so this is a change of mechanism, not a repalette.

TH
14Days clean

A card inside a card. Because surfaces are light rather than opaque greys, the inner one is automatically a second level.

The rule, per element

RaisedCards, buttons, chips, rows, switch thumbsHighlight on the top edge, shadow below
RecessedInputs, tracks, wells, segmented backgroundsShadow on the top inner edge, light on the bottom
PressedAny raised element under the pointerDrops 1px and loses its shadow
MetallicWordmark and the single primary CTA onlyGradient fill plus a specular top edge

Colour ramps

Generated in OKLCH from each brand-locked base, which is pinned unchanged at step 500. Lightness is perceptually even and monotonic, so a step number means the same thing in every ramp. The number under each swatch is its measured WCAG contrast against the ground.

50100200300400500600700800900
gold
50#3627001.3:1
100#5741021.9:1
200#7B5C043.0:1
300#A27A024.7:1
400#C8991B7.1:1
500#EBBB4A10.4:1
600#F0C66811.5:1
700#F4D28812.7:1
800#F6DDA914.0:1
900#F8E9C915.4:1
blue
50#0F23371.2:1
100#1736541.5:1
200#1E4B732.0:1
300#2F608E2.8:1
400#4576A63.9:1
500#5B8DBE5.3:1
600#76A3CF7.0:1
700#94B8DD9.0:1
800#B4CEE911.4:1
900#D4E4F514.3:1
red
50#470B041.2:1
100#6B11061.5:1
200#9317082.1:1
300#B81E092.8:1
400#DC33164.0:1
500#FF4D245.6:1
600#FF6E476.7:1
700#FF9C7A9.1:1
800#FFB89E11.1:1
900#FFDACB14.2:1
green
50#0330171.3:1
100#0248231.7:1
200#06793A3.4:1
300#06893F4.1:1
400#1FAD586.3:1
500#25C8628.4:1
600#4FD68310.0:1
700#86DFA511.6:1
800#B0E8C213.4:1
900#D4F2DC15.5:1
violet
50#271A3F1.2:1
100#3D2A611.5:1
200#5539862.0:1
300#6C4EA42.9:1
400#8366BE4.1:1
500#9B7ED95.6:1
600#AD95E67.3:1
700#C0ADF09.2:1
800#D3C5F711.6:1
900#E6DEFD14.3:1
orchid
50#3216361.2:1
100#4D23531.5:1
200#6A30732.0:1
300#85448E2.8:1
400#9E5CA84.0:1
500#B874C25.6:1
600#C88CD17.2:1
700#D7A5DE9.1:1
800#E5BFEA11.5:1
900#F2DBF414.3:1
orange
50#3A1C001.2:1
100#592F011.6:1
200#7B43052.3:1
300#9F57023.4:1
400#C06F1B4.9:1
500#DE8A3E6.9:1
600#E99E5F8.4:1
700#F2B48110.3:1
800#F8CAA612.3:1
900#FCDFC914.6:1
bronze
50#331E061.2:1
100#5030091.6:1
200#6E430C2.2:1
300#8B591E3.1:1
400#A571394.4:1
500#C08A526.2:1
600#CF9F6E7.8:1
700#DDB48C9.7:1
800#E8CAAD11.9:1
900#F3E0CF14.5:1
steel
50#2222251.2:1
100#35363A1.5:1
200#494B502.1:1
300#5F61673.0:1
400#75777E4.1:1
500#8D8F965.7:1
600#A1A3AA7.4:1
700#B6B8BD9.3:1
800#CCCDD111.7:1
900#E2E3E514.4:1
teal
50#002D261.2:1
100#00463D1.7:1
200#0061562.5:1
300#007E703.7:1
400#109C8B5.4:1
500#3FB8A67.6:1
600#64C7B69.2:1
700#88D4C610.8:1
800#ACE1D612.8:1
900#CDEEE715.0:1
rose
50#410A181.1:1
100#620F241.4:1
200#8615311.9:1
300#A8193D2.5:1
400#CA28503.5:1
500#EB38654.7:1
600#EE587D5.6:1
700#F386A17.7:1
800#F6A7BB9.9:1
900#FAD0DA13.3:1

Neutrals

Steps 0–3, 8 and 11 are the brand-locked greys; the rest are interpolated between them in Oklab. Step −1 sits below the ground for wells and inset tracks.

0#1213191.0:1
1#1A1C261.1:1
2#2225331.2:1
3#2629361.3:1
4#3B3F4C1.8:1
5#5155632.5:1
6#696D7A3.6:1
7#8186935.1:1
8#9AA0AC7.1:1
9#B7BBC29.6:1
10#D4D6D812.7:1
11#F2F2EE16.5:1
-1#09090E1.1:1

Tones

A component asks for a tone, never a hue. Each tone resolves to nine roles, and every toned component uses those nine and nothing else, which is why a danger card and a success card are structurally identical. Note the split between solid and fill: solid is the saturated mark used at chip scale under dark ink, fill is the deep one used at button scale under light text. onSolid and onFill name the text colour each fill carries, so the pairing is a token rather than something each component has to remember.

brandgold
surface#362700
surfaceHover#574102
border#7B5C04
solid#EBBB4A
solidHover#F0C668
fill#7B5C04
text#F4D288
infoblue
surface#0F2337
surfaceHover#173654
border#1E4B73
solid#5B8DBE
solidHover#76A3CF
fill#2F608E
text#94B8DD
dangerred
surface#470B04
surfaceHover#6B1106
border#931708
solid#FF4D24
solidHover#FF6E47
fill#B81E09
text#FF4D24
successgreen
surface#033017
surfaceHover#024823
border#06793A
solid#25C862
solidHover#4FD683
fill#06793A
text#25C862
focusviolet
surface#271A3F
surfaceHover#3D2A61
border#553986
solid#9B7ED9
solidHover#AD95E6
fill#6C4EA4
text#C0ADF0
warnorange
surface#3A1C00
surfaceHover#592F01
border#7B4305
solid#DE8A3E
solidHover#E99E5F
fill#9F5702
text#F2B481

The grammar, applied

One card, six tones, one attribute changed. This is the multi-colour panel test: every tone has to hold on the same ground.

brand

You quit today

The brand tone carries IQUIT.GG itself and the one primary action.

info

Your week in numbers

Calm, factual, asks nothing of you.

danger

You played 6 hours last night

Harm, relapse, and destructive actions.

success

14 day streak

Recovery and progress you earned.

focus

What pulls you back in?

Questionnaires and prompts that ask something of you.

warn

Two hours until your cutoff

Caution and time pressure, short of harm.

Type scale

Inter throughout. Sizes and line heights are in px so web and native resolve to the same number; tracking is in em.

display56/56 · 900 · -0.03em

Conquer gaming. Conquer the world.

title32/38 · 800 · -0.02em

Conquer gaming. Conquer the world.

heading22/28 · 700 · -0.015em

Conquer gaming. Conquer the world.

metric30/32 · 800 · -0.02em

Conquer gaming. Conquer the world.

subheading18/24 · 600 · -0.01em

Conquer gaming. Conquer the world.

body16/24 · 400 · 0em

Conquer gaming. Conquer the world.

bodyStrong16/24 · 600 · 0em

Conquer gaming. Conquer the world.

label14/20 · 600 · 0em

Conquer gaming. Conquer the world.

caption13/18 · 400 · 0em

Conquer gaming. Conquer the world.

micro11/14 · 600 · 0.04em

Conquer gaming. Conquer the world.

Text colours

Default 16.5:1

Muted 7.1:1

Disabled 3.6:1

Gold gradient

Space & shape

A 4px base step. Control heights exist so a button, a field, and a select always line up; md is 44px, the iOS minimum touch target.

spacing
xs4px
sm8px
md16px
lg24px
xl40px
xxl64px
radii
sm8px
md14px
lg18px
xl34px
full999px
control heights
36px
44px
52px
shadow
none0 layers
low2 layers
high3 layers
well1 layer
overlay3 layers

Web renders the whole stack. React Native renders only the first layer (iOS allows one shadow and Android only an elevation number), so a shadow may never carry meaning the layer and highlight do not already carry.

Motion

The opener's staggered entrance uses stagger + rise + riseDistance. Every transition on this page uses one of these durations and the shared easing curve.

fast120ms
base200ms
slow320ms
stagger90ms
rise500ms
riseDistance16px
glassArrive50ms
spin700ms
pulse1400ms
toast3200ms
easingcubic-bezier(0.2, 0, 0, 1)

Primitives

26 primitives. The inventory is exported from @iquit/ui, so a component the mobile app has not implemented yet is a visible gap rather than an assumption.

Button
primary
secondary
ghost
danger
IconButton
Chip
solidbrandinfodangersuccessfocuswarn
softbrandinfodangersuccessfocuswarn
outlinebrandinfodangersuccessfocuswarn
selectable
Badge
1233333
Card

Plain

The default surface for content.

Toned

Tinted surface and border from one tone.

Outline

Border only, no fill.

Callout

Your data stays on device

Nothing syncs until you create an account.

You're in a relapse window

Last three sessions all started after 11pm.

Longest streak yet

You passed your previous best of 11 days.

A day is still open

Yesterday has no answer yet. It closes at midnight.

Field / TextArea
We only use this to sync across devices.
That address doesn't look right.
24
160
Checkbox / Radio / Switch
OptionRow
SegmentedControl
Slider

62 hours

ProgressBar
ProgressRing
72%12d
Stat
14Days clean
212Hours reclaimed
2Relapses
ListRow
Longest streak14 daysNew
Check-in reminderScore a day the sweep could not verify
Avatar
THTHTHIQIQIQIQIQ
Spinner / Skeleton
Divider

Icon
check
close
chevronRight
chevronLeft
chevronDown
more
plus
minus
arrowRight
arrowUp
alert
info
shield
clock
home
flame
trophy
moon
power
bell
bellOff
calendar
heart
mail
message
link
trash
chart
book
user
users
star
settings
copy
share
lock
pin
camera
image
fingerprint
dumbbell
bed
briefcase
hammer
face
react
keyboard
backspace
drop
sun
leaf
coffee
music
pen
compose
phone
run
bike
search
car
bulb
flag
apple

Overlays

The only elements that read off the page rather than off a surface. They take the one shadow stack reserved for them and sit above a scrim, which is the light being blocked, so it deepens the ground rather than tinting it. Three, deliberately: a tooltip needs hover, which mobile does not have.

Modal
Sheet
Toast
SavedNot sentCopiedNot posted