Add docs/DESIGN_SYSTEM.md capturing Phase 2 visual identity: - Chosen direction (warm premium, work-forward) and its principles. - Documents existing color/surface/brand/status/border/hero tokens with light + dark values and an accent-budget usage rule. - Fonts (Museo Latin, Dubai Arabic) and a defined type scale + Arabic overrides. - Radius, elevation, container and spacing-rhythm guidance, motion, component conventions, and do/don't. Colors and fonts are owner-fixed and unchanged.
8.5 KiB
Design System — mohfarawati.de
The visual language for the public site and admin. This documents the token
system that already lives in app/globals.css and tailwind.config.ts, and
defines the layers that are still missing (type scale, spacing rhythm) so the
site has one consistent, premium base before any page is redesigned.
Source of truth for values: app/globals.css (:root + .dark). Tailwind
mappings: tailwind.config.ts. This file is the usage guide for those tokens.
Direction: Warm Premium (work-forward)
Chosen visual direction. Every design decision serves these principles:
- The work is the hero. Layouts lead with project imagery and a strong title hierarchy; chrome stays quiet.
- One decisive accent. The warm red-orange brand color appears sparingly — primary CTAs, one highlighted word, active/selected states, focus. Everything else is neutral ink on light/dark surfaces. Accent is a punctuation mark, not a background.
- Generous whitespace + restraint. Space and type hierarchy carry the premium feel — not borders, gradients, or decoration. "Too busy" is the default failure mode; cut before adding.
- Depth, softly. Elevation via one soft shadow layer and the large 24px radius already in the tokens. Avoid stacking shadows or heavy borders.
- Light + dark parity. Every token has a dark value; never hardcode a hex.
- Arabic is first-class. RTL layout, no uppercase or letter-spacing on Arabic text, slightly looser line-height. Latin uses Museo, Arabic uses Dubai.
Colors and fonts are fixed by the owner and are not changed by this system — it only organizes and documents them and adds the missing scale layers.
1. Color tokens
All colors are HSL channel triplets consumed as hsl(var(--token)). Light is
:root, dark is .dark.
Base
| Token | Light | Dark | Use |
|---|---|---|---|
--background |
0 0% 100% |
222 22% 8% |
Page canvas |
--foreground |
222 24% 10% |
210 20% 96% |
Primary ink |
--muted |
220 14% 96% |
222 16% 14% |
Quiet fills |
--muted-foreground |
220 10% 42% |
217 10% 64% |
Secondary text |
Surfaces (elevation ramp)
| Token | Light | Dark | Use |
|---|---|---|---|
--surface-1 |
0 0% 100% |
222 22% 9% |
Base card |
--surface-2 |
220 16% 97% |
222 18% 12% |
Raised card / section tint |
--surface-3 |
220 14% 94% |
222 16% 15% |
Highest / hover |
--surface-inverse |
222 24% 12% |
210 20% 96% |
Inverted blocks |
Step surfaces 1 → 2 → 3 for hierarchy. Do not invent intermediate greys.
Brand + semantic (use sparingly)
| Token | Light | Dark | Use |
|---|---|---|---|
--brand-primary / --primary / --ring |
9 73% 50% |
9 78% 56% |
The one accent: CTAs, highlight word, focus |
--brand-secondary |
12 64% 58% |
12 74% 64% |
Accent gradient partner, live dots |
--primary-foreground |
210 40% 98% |
210 40% 98% |
Text on accent |
--destructive |
0 84% 60% |
0 63% 31% |
Errors only |
Status
| Token | Light | Dark |
|---|---|---|
--status-success / --status-success-soft |
145 63% 42% / 145 58% 92% |
145 68% 66% / 145 36% 18% |
--status-warning / --status-warning-soft |
36 92% 44% / 41 96% 90% |
42 96% 66% / 35 40% 18% |
Reserved for real state (success/warning feedback), never decoration.
Lines + hero
| Token | Light | Dark | Use |
|---|---|---|---|
--border |
220 13% 90% |
222 14% 18% |
Default hairline |
--border-strong |
220 11% 82% |
222 12% 26% |
Emphasis divider |
--hero-base / --hero-ink |
260 22% 95% / 226 43% 11% |
222 24% 10% / 210 20% 96% |
Hero backdrop base + ink |
Tailwind exposes these as bg-background, text-foreground, bg-surface-2,
text-brand-primary, border-border, bg-status-success-soft, etc.
Accent budget: at most one accent-filled element per view (usually the primary CTA). Additional emphasis uses ink weight/size, not more color.
2. Typography
Fonts (fixed)
| Script | Family | Variable | Utility | Weights |
|---|---|---|---|---|
| Latin (default) | Museo Sans Rounded | --font-museo |
.font-latin |
300, 500, 700, 900 |
| Arabic | Dubai | --font-dubai |
.font-arabic |
300, 400, 700 |
Applied on body (Latin) and html[lang="ar"] (Arabic) in globals.css.
Type scale (to add as tokens in 2.3)
A single documented scale replaces ad-hoc sizes. Latin values; Arabic overrides noted below.
| Role | Size (clamp) | Weight | Line-height | Tracking |
|---|---|---|---|---|
display |
clamp(2.75rem, 8vw, 5.5rem) |
900 | 0.95 | -0.03em |
h1 |
clamp(2.25rem, 5vw, 3.5rem) |
700 | 1.05 | -0.02em |
h2 |
clamp(1.75rem, 3.5vw, 2.5rem) |
700 | 1.1 | -0.015em |
h3 |
1.375rem (22px) |
700 | 1.2 | -0.01em |
title |
1.125rem (18px) |
500 | 1.3 | 0 |
body-lg |
1.125rem (18px) |
400 | 1.7 | 0 |
body |
1rem (16px) |
400 | 1.7 | 0 |
small |
0.875rem (14px) |
400 / 500 | 1.6 | 0 |
caption |
0.8125rem (13px) |
500 | 1.5 | 0 |
overline |
0.75rem (12px) |
500 | 1.4 | 0.14em, uppercase |
Arabic overrides: never uppercase, never letter-spacing (breaks joins);
add ~0.1 to line-height on display/h1/h2; cap weight at 700 (Dubai has no 900).
The overline role for Arabic uses normal tracking and normal case.
Only two Latin weights per view in body copy (regular 400 + one bold). Reserve
900 for display only.
3. Radius
| Token | Value | Use |
|---|---|---|
--radius-surface |
24px |
Cards, panels, large containers (rounded-surface / lg / xl) |
--radius-nested |
16px |
Nested elements, inputs, buttons (rounded-nested / sm / md) |
--radius-pill |
9999px |
Pills, badges, toggles (rounded-pill) |
The generous 24px surface radius is part of the premium feel — keep it consistent; do not mix arbitrary radii.
4. Elevation (shadows)
| Token | Use |
|---|---|
--shadow-xs / shadow-xs |
Subtle lift (hairline cards) |
--shadow-sm / shadow-sm |
Small controls, pills |
--shadow-card / shadow-card |
Default raised card |
--shadow-panel / shadow-panel |
Floating panel / glass surface |
--shadow-md, --shadow-lg |
Reserved for overlays; use rarely |
Discipline: most surfaces are flat with a hairline border. Raise with one
shadow layer at a time. Never stack shadow-lg on nested elements.
5. Spacing + layout
Containers
| Token | Value | Use |
|---|---|---|
--container-narrow |
48rem |
Reading width, forms |
--container-default |
72rem |
Standard page content |
--container-wide |
80rem |
Galleries, wide grids |
--container-admin |
88rem |
Admin workspace |
Header: --header-height: 4.5rem.
Vertical rhythm (to formalize in 2.3)
Existing: --section-space: 3.5rem, --content-space: 1.5rem
(spacing.section, spacing.content).
Premium layouts need more air. Recommended section rhythm to add:
| Token | Value | Use |
|---|---|---|
section-sm |
3rem |
Tight sections |
section |
5rem (mobile) → 7rem (lg) |
Default between major sections |
section-lg |
8rem+ |
Hero-adjacent breathing room |
Internal gaps use rem steps: 1rem, 1.5rem, 2rem.
6. Motion
framer-motion, restrained. Entrance pattern (see components/layout/site-hero.tsx):
- item:
opacity 0→1,y 16→0,duration 0.54, ease[0.22, 1, 0.36, 1] - container stagger:
0.13, delay0.08
Rules: entrance + hover only; respect prefers-reduced-motion; no looping or
attention-grabbing motion on content.
7. Component conventions
- Cards route through
components/ui/app-card.tsx(AppCardwithlevel/layer/padding). Uselevelto express hierarchy — do not restyle cards ad hoc. - Buttons: one
primary(accent) per view; othersoutline/ghost. - Badges:
success/warningvariants map to status tokens;outlinefor neutral tags. - Inputs:
--radius-nested,--border, focus uses--focus-ring. - Inline feedback (admin):
components/admin/admin-flash.tsx.
8. Do / Don't
Do
- Lead with imagery and whitespace; let type hierarchy do the work.
- Use the accent once per view, deliberately.
- Keep one radius language (24 / 16 / pill) and one shadow layer.
- Test every screen in light and dark, and Arabic RTL.
Don't
- Fill backgrounds with brand color or gradients.
- Add a second accent hue.
- Apply uppercase/letter-spacing to Arabic text.
- Stack shadows or mix arbitrary radii/greys.
- Put decoration where whitespace would do.