Files
MohFarawati d1a1a67b84 docs(design-system): document warm-premium direction and token system
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.
2026-07-14 22:03:15 +02:00

232 lines
8.5 KiB
Markdown

# 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:
1. **The work is the hero.** Layouts lead with project imagery and a strong
title hierarchy; chrome stays quiet.
2. **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.
3. **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.
4. **Depth, softly.** Elevation via one soft shadow layer and the large 24px
radius already in the tokens. Avoid stacking shadows or heavy borders.
5. **Light + dark parity.** Every token has a dark value; never hardcode a hex.
6. **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`, delay `0.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` (`AppCard` with
`level`/`layer`/`padding`). Use `level` to express hierarchy — do not restyle
cards ad hoc.
- **Buttons**: one `primary` (accent) per view; others `outline`/`ghost`.
- **Badges**: `success`/`warning` variants map to status tokens; `outline` for
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.