The whole brand sits on ~12 tokens. The terracotta accent is the only saturated color in the system — everything else is in the warm-stone neutral family. This is intentional: scarcity makes the accent meaningful.
Accent (the brand color)
accent
#C44536
Primary actions, links, focus rings, badges
accent-2
#8E2D24
Hover state, gradient pair, deeper emphasis
accent-ink
#6B1E18
Text/icon ON accent-soft surfaces
accent-soft
#F8DFD8
Icon chip background, tag background, progress track
Tertiary text, disabled, chevrons, dividers in dense lists
border
#E8DED3
Hairline borders on cards, list dividers
border-strong
#D6C9BB
Input default border, more present than hairline
surface-2
#FBF7F1
Subtle alt surface (filled inputs, zebra rows)
surface
#FFFFFF
All cards and panels
bg
#F5EFE8
App-level page background
Semantic
warn
#D9933A
Warning badges, "needs attention", soft alerts
warn-soft
#FBEFD9
Warning badge bg
success
#4F7A5C
Completed, delivered, "all good" states
success-soft
#DFEEE3
Success badge bg
Note: there is no separate "error" color. The accent is the error/destructive color. This is OK because: (1) the accent is reserved for emphasis, so seeing it on a destructive action reads correctly, and (2) it avoids a competing palette in a system that's already small.
Dark mode pair
bg
#1A1410
Warm-dark page bg
surface
#2A201A
Cards
surface-2
#352B24
Filled inputs, alt surface
ink
#F5EFE8
Primary text (was charcoal in light)
accent
#E55D4D
Brighter for dark-mode contrast
border
#3A2D24
Hairline
In dark mode the signature offset shadow flips: 4px 4px 0 var(--accent) instead of ink. Otherwise the signature would disappear into the bg.
02 · Type
Typography
Inter (or system: -apple-system, Roboto, system-ui). Weights 500 / 600 / 700 / 800. Tracking -0.01em on display sizes. Mono only for raw IDs (IDNO, phone, version numbers).
display
Bună dimineața, Andrei
28/32800 -0.02em
h1 / page title
Magazinul tău e aproape gata
22/28700 -0.01em
h2 / section
Echipa
18/24700
h3 / card title
Comanda #1248 e în drum
15/20700
body
Răsfoiește catalogul nostru exclusiv de vinuri moldovenești.
14/20400/500
label / button
Invită colegii în echipă
13/18600
caption / hint
2 din 4 pași completați
12/16500
eyebrow
Configurare
11/14700 +0.08em UPPER
mono / ID
IDNO 1003600012345
13/18500 mono
03 · Spacing
Spacing scale
Scale of 4. Pick from the scale — do not invent intermediate values. Common patterns: 18 (screen edge padding), 14-16 (card padding), 10-12 (card gap), 6-8 (icon-to-text gap).
space-1
4 px
space-2
8 px
space-3
12 px
space-4
16 px
space-5
18 px (screen padding)
space-6
24 px
space-7
32 px
space-8
48 px
04 · Radii
Border radius
Five values. The 14px hero-card radius is the most distinctive — pair it with the signature offset shadow for editorial moments.
radius-1
6 px
Brand mark · tag
radius-2
8 px
Small chip · cell
radius-3
10 px
Button · input · icon chip
radius-4
12 px
List card · standard
radius-5
14 px
Hero · signature card
pill
999 px
Badge · avatar · chip
05 · Elevation
Borders & shadows
Three elevation styles. The "signature" style is the brand's recognizable element — use sparingly for hero moments, not on every card.
Stroked icons from Lucide React Native (or Phosphor as a fallback). 1.5px stroke weight, 20-22px size. Always rendered in an "icon chip" container: 32×32 or 36×36 rounded square with accent-soft bg.
⌂
home
Acasă tab
▤
grid
Catalog/Produse
▦
clipboard-list
Comenzi
◑
users
Echipa
⌖
map-pin
Rute / Vizite
★
star
Loialitate
⚙
settings
Setări
◔
bell
Notificări
?
help-circle
Suport
⏻
log-out
Ieși din cont
The glyphs above (▤ ◑ ⌖ etc.) are placeholder geometry for these mockups only. Production uses the actual SVG icons from Lucide React Native.
10 · Chrome
Top bar & bottom tab bar
The two pieces of chrome that bracket every authenticated screen.
Top bar
S
Magazin Central
Proprietar
◔
AG
Brand mark + org/role chip on the left.
Bell (notifications) + avatar (tap → profile screen) on the right.
Avatar has a 2px ink border to signal it's tappable.
Bottom tab bar
⌂Acasă
▥Magazin
◑Echipa
▦Comenzi
Always 4 tabs. Active tab gets the accent color plus a small accent indicator at the top.
Inactive tabs are text-3. Background is pure white to maximize legibility against the warm bg.
10b · Chrome scale
Chrome reads ~15–25% bigger than the content type scale
The type scale in section 02 is correct for content — display headings, body
copy, captions inside cards. When the same tokens are applied verbatim to chrome (top bars,
tab bars, brand marks, input fields, role badges, sheet rows, CTA labels), the result reads too small
at native DPI. Chrome elements need an explicit bump.
Chrome overrides (use these in primitives, not the content tokens)
Element
Spec (was)
Chrome (use this)
Lives in
TopBar brand mark
28×28, font 12
36×36, font 15
TopBar.tsx
TopBar title
label · 13/18
h3 · 15/20
TopBar.tsx
TopBar subtitle
11/14
13/16
TopBar.tsx
TopBar bell
32×32
40×40
TopBar.tsx
Tab bar label
10/13
12/16
(tabs)/_layout.tsx
Tab bar icon
18
22
(tabs)/_layout.tsx
Tab bar height
64
76 + safe-area
(tabs)/_layout.tsx
Button label
label · 13/18
15/20 · weight 700
Button.tsx
Button height
~46 (s3+2 padding)
~52 (s4 padding)
Button.tsx
Input field height
~44 (s3 padding)
~52 (s4 padding)
Input.tsx
Input label
caption · 12/16
13/18 · weight 600
Input.tsx
Badge text
10.5
11.5
Badge.tsx
BottomSheet subtitle
14
15
BottomSheet.tsx
List-row label (member name, settings row, sheet row, role picker)
label · 13/18
17/22 · weight 600 (matches iOS Settings)
ListRow.tsx + per-screen overrides
List-row trailing meta (e.g. "v0.1.0")
caption · 12/16
15/18 · weight 500
per-screen
Screen-edge padding
s5 · 18px
s6 · 24px
every screen
Why this exists. Native rendering at high DPI makes the literal token values feel
smaller than they look in the static HTML mockup. The rule isn't that the type scale is wrong — it's
that chrome and content are different problems. Body type at 14 inside a card is readable; the same
14 in a tab bar disappears.
How to apply. Implement chrome elements as primitives (Button, Input, TopBar, Badge,
BottomSheet, the eventual ScreenHeader). Bake the bumped values into the primitive so every consumer
gets the right size by default. If you find yourself overriding a primitive's font/padding inline
because "it feels small", the bump belongs in the primitive instead.
What we did not do. Add a separate chrome namespace to
constants/tokens.ts. With ~6 primitives, inline overrides are easier to read than a
second indirection layer. Revisit if primitive count doubles.
CSS variables (ready to copy into constants/Colors.ts)