Design system v0.2.2

Nadi Design System

Quicksand for warmth and brand voice, Inter for working UI, JetBrains Mono for anything measured; cool Mist neutrals over Nadi Ink with a single Pulse accent; dark mode only where the PT is mid-session.

Prinsip

Aturan dari SKILL.md yang tidak boleh dilanggar, dikutip apa adanya.

Brand

  • The logo is locked. Use brand/*.svg or the Logo component in one of its six official forms. Never redraw it, never stretch it, never recolor it, never add a second green, never append .fit. Clear space is 14 units on every side.
  • One Pulse accent per screen region, and the logo counts as that region's accent.

Color

  • --accent (Deep Pulse #087858) writes text, icons, links, and fills the primary button (--button-fill) with a white label (--button-label). --accent-fill (Pulse #10C98F) fills progress bars, check dots, and the mark only; it reaches 2.2:1 on white, so it is never a button fill and never small text on a light ground.
  • Check dots on a Pulse fill carry an Ink ✓ (--accent-contrast).
  • Clay only for pain and risk. Amber only for "Perlu Perhatian". Ember #FF6A4D is marketing-only and never enters product UI. Warning surfaces read --warn-bg / --warn-border / --warn-text; never raw amber.
  • No shadows. Hairline borders, 1.5px only for the active or next element.
  • Dark mode only for in-session PT surfaces, plus the one Ink hero card on the client home.

Type

  • Measured values (weights, reps, timers, counts) are always JetBrains Mono w700 with their unit.
  • Quicksand for headings and names, never below 15px, and below 17px use Inter w600 instead.
  • Inter for all other UI.

Content

  • Bahasa Indonesia by default, formal but warm. No em-dashes in Indonesian prose; the em-dash is a data glyph only.
  • Locked status labels: Sesuai Rencana · Perlu Perhatian · Berisiko Terlambat · Selesai · Belum Selesai. Qualitative only, never a score or a probability.
  • Every recommendation carries a why-chip. Unvalidated guidance is tagged menunggu validasi ahli.
  • The PT is the final decision-maker. The product never diagnoses.
  • No emoji. Unicode glyphs for inline affordances, Lucide 1.5px for named concepts, and flag any icon you add.

Merek

Horizontal
Horizontalnadi-logo-horizontal.svg · min. 110px lebar
Stacked
Stackednadi-logo-stacked.svg · min. 70px lebar
Mark
Marknadi-mark.svg · min. 16px
Mark mono
Mark mononadi-mark-mono.svg · satu warna
Wordmark
Wordmarknadi-wordmark.svg · tipe saja
Horizontal putih
Horizontal putihnadi-logo-horizontal-putih.svg · di atas Ink
Wordmark putih
Wordmark putihnadi-wordmark-putih.svg · di atas Ink

Logo: locked, six official forms, shipped in brand/ and wrapped by the Logo component. Clear space 14 units on every side; minimum 110px wide (horizontal), 70px wide (stacked), 16px (mark). Never redraw, restretch, recolor, add a second green, or append .fit.

nadi lowercase as logotype, Nadi as proper noun, NADI never.

Backgrounds: inside product content, flat token colors only. No images, gradients, patterns or textures behind data. Brand imagery is allowed on marketing surfaces, onboarding, empty states, and the session summary a client shares.

Warna

Skala dasar

Skala dasar menamai warnanya. Komponen hanya membaca token semantik di bawah.

Pulse (the one accent)

800#08684A
700#087858
500#10C98F
300#3FDCAB
100#BEE9D7
50#E7F7F1

800 hover / pressed accent · 700 Deep Pulse — accent for TEXT, icons, and the primary button fill on light (v2.1: value from pilot prototype v3) · 500 Pulse — accent for progress, check dots, the mark; never a button fill, never small text on light · 300 dark-mode accent · 100 tint border · 50 tint fill

Ink neutrals (light surfaces)

900#0D2137
600#3E4E5A
500#54646F
400#8296A1
200#D3DEDC
150#DCE6E4
100#E3E9E8
sunken#EDF3F2
mist#F4F8F7
cloud#FFFFFF

900 Nadi Ink — primary text, dark panels, lower field of the mark · 600 strong secondary text · 500 Slate — secondary text, captions · 400 muted text, placeholders · 200 chip + control borders · 150 progress track · 100 Line — hairline borders · sunken recessed fills · mist Mist — app background · cloud Cloud — card and panel surfaces

Navy (dark, in-session PT surfaces)

900#071522
800#0E2537
750#0A1D2C
700#1B384E
600#27485F
400#718794
300#9BAFBB
50#E7F0EE

Clay (pain / risk / alert only)

700#7E3624
600#A8442E
100#E8C4BA
50#F9EFEC
dark-bg#2B1D18
dark-border#57352B
dark-text#E8A493

Amber (Perlu Perhatian only)

700#8A5C1E
500#B0782C
100#E6D6B3
50#F6EEDF

700 darkened from the brand swatch so small text clears 4.5:1 · 500 graphic use only · 100 warn tint border

Ember (marketing only)

ember#FF6A4D

Token semantik

Nilai terang dan gelap berdampingan. Klik baris untuk menyalin var(--token).

tokenpemakaianteranggelapsalin
Permukaan
--bgMist — app background#F4F8F7#071522
--surfaceCloud — card and panel surfaces#FFFFFF#0E2537
--surface-sunkenrecessed fills#EDF3F2#0A1D2C
--borderLine — hairline borders#E3E9E8#1B384E
--trackprogress track#DCE6E4#1B384E
Teks
--textNadi Ink — primary text, dark panels, lower field of the mark#0D2137#E7F0EE
--text-softstrong secondary text#3E4E5A#9BAFBB
--text-subSlate — secondary text, captions#54646F#9BAFBB
--text-mutedmuted text, placeholders#8296A1#718794
Aksen
--accentaccent for text, icons, links, active borders#087858#3FDCAB
--button-fillprimary button fill — Deep Pulse (v2.1)#087858#3FDCAB
--button-labellabel ON --button-fill — white, 5.5:1#FFFFFF#071522
--accent-fillaccent for filled areas: progress, check dots (not buttons)#10C98F#3FDCAB
--accent-stronghover, one step darker#08684A#10C98F
--accent-contrastlabel ON --accent-fill (check dots) — Ink, never white#0D2137#071522
--accent-tinttint fill#E7F7F1#0F2E29
--accent-tint-bordertint border#BEE9D7#1E4A3E
--chip-borderchip + control borders#D3DEDC#27485F
Alert dan status
--alertpain / risk / alert only#A8442E#E8A493
--alert-textpain / risk / alert only#7E3624#E8A493
--alert-bgpain / risk / alert only#F9EFEC#2B1D18
--alert-borderpain / risk / alert only#E8C4BA#57352B
--status-okDeep Pulse — accent for TEXT, icons, and the primary button fill on light (v2.1: value from pilot prototype v3)#087858#3FDCAB
--status-warndarkened from the brand swatch so small text clears 4.5:1#8A5C1E#D9A05C
--status-riskpain / risk / alert only#A8442E#E8A493
--warn-texttext on --warn-bg, same as --status-warn#8A5C1E#D9A05C
--warn-bgPerlu Perhatian card and tag fill#F6EEDF#2E2414
--warn-borderalways pairs with --warn-bg#E6D6B3#5A4523

Rasio warna

70% neutral · 22% Ink · 8% Pulse. Angka dari komentar tokens/layout.css; Ember di bawah 3% dan hanya di marketing.

Tipografi

Quicksand
--font-display Headings, names, client greetings, marketing. Weight 600/700. NEVER below 15px, and prefer --font-body w600 for headings under 17px: Quicksand's rounded forms lose authority at small sizes on data-dense screens.
Inter
--font-body Body, labels, buttons, inputs, and section headings below 17px. Weight 400/600.
JetBrains Mono
--font-data Every measured value: weights, reps, timers, counts, dates, kickers. Weight 700. Always carries its unit. Never used for human speech or client-facing sentences.
Halo, Sari--text-hero · 24px · Quicksand 700
Goblet Squat--text-title · 22px · Quicksand 600
Sesi berikutnya--text-h2 · 17px · Quicksand 600
Rekomendasi--text-h3 · 15px · Inter 600
Masih sesuai rencana untuk target 12 minggu.--text-body · 14px · Inter 400
Pertahankan jalan kaki minggu ini.--text-small · 12.5px · Inter 400
Nama lengkap--text-label · 12px · Inter 600
LATIHAN 3 DARI 6--text-micro · 11px · JetBrains Mono 700

Quicksand tidak pernah di bawah 15px; judul bagian di bawah 17px memakai Inter w600. Nilai terukur selalu JetBrains Mono w700 dengan satuannya.

Jarak

Spasi

--s-14px
--s-28px
--s-312px
--s-416px
--s-524px

Layar pad 16px, kartu pad 12 sampai 14px, jarak antar-saudara 6 sampai 10px.

Radius

--r-screen 18pxphone screen container
--r-card 11pxcards, list rows
--r-btn 10pxbuttons, fields
--r-pill 999pxstatus pills, chips

Garis dan elevasi

hairline 1pxkartu standar
1.5px aksenelemen aktif atau berikutnya, satu per layar
tint + tint borderkartu status positif

Bayangan: tidak ada. Hierarki datang dari tint dan garis, bukan elevasi.

Ikon

selesai
aksi maju
buka
tutup
·pemisah

Named concepts (nutrition, sleep, recovery, cardio) use Lucide at 1.5px stroke with round caps, which matches the mark's rounded geometry — Ink on marketing, Deep Pulse in-app. Flag any icon added to the set.

selesaibelum

Indikator centang 18px: --accent-fill dengan ✓ Ink saat selesai, garis hairline saat belum.

Komponen

Contoh hidup dari components/*/*.card.html, dirender oleh React di dalam bingkai. Kartu selalu terang dan diskalakan agar muat; hanya LiveLogger yang gelap. Tema bingkai mengikuti kartunya, bukan halaman ini.

Actions buka terpisah ▸

Button variants · why-chips · reason chips

  • Button the app's only button — Deep Pulse fill for the single primary action per screen, outline/ghost for the rest.
  • Chip pill chip for why-provenance on recommendations (mono) and tap-to-pick reasons (sans).

Data buka terpisah ▸

Set rows · measurement tiles · client tasks

  • SetRow one logged set in the live workout logger — label, mono value, ✓ or the catat action.
  • StatTile small baseline-measurement tile (mono value over a quiet label), used in 3-up grids on assessment summaries.
  • TaskItem client Today-list task row with a circular check.

Logo buka terpisah ▸

The locked logo in its six official forms

  • Logo the locked Nadi logo in its six official forms. Never redraw it, never invent a variant.

Status buka terpisah ▸

Qualitative pills · clay risk flags · Pulse progress

  • ProgressBar thin Pulse progress bar with a mono data caption.
  • RiskFlag clay-tinted flag for pain and risk only, never for generic warnings or emphasis.
  • StatusPill outlined qualitative status pill (Sesuai Rencana / Perlu Perhatian / Berisiko Terlambat / Selesai / Belum Selesai).

Surfaces buka terpisah ▸

Cards, tint cards, and labelled fields

  • Card the standard card — hairline border, 11px radius, no shadow; tint variant for status.
  • Input labelled text field (new-client form, free-text reasons).

Layar

Live logger (dark) · Today klien · Ringkasan asesmen · buka terpisah ▸

  • LiveLogger.jsx — PT mid-session logger, dark ([data-nadi-theme="dark"] wrapper). Interactive: tap "catat ▸" or the button to log set 3.
  • ClientToday.jsx — client companion Today screen, light, with the one Ink hero card allowed on this surface. Interactive: toggle tasks.
  • AssessmentSummary.jsx — PT assessment summary, light.

Terbuka

Two questions are still owned by the founders and are deliberately not settled in this system:

  1. Client app weight. Marketing treats the client as the primary audience; this system still ships the client app as a light companion. Either the app grows or the landing-page promise narrows.
  2. How far dark mode may spread beyond the live logger and rest timer.