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.