# DESIGN.md · نظام تصميم بيت العمر

> مرجع شامل لفلسفة التصميم، الـ tokens، المكونات، التفاعلات، والمعمارية. يغطّي الصفحات الثلاث (`villa-plan.html`، `timeline.html`، `financial-plan.html`).

**آخر تحديث:** 2026-04-27

---

## 1. الفلسفة

### الإلهام
- **Tesla UI** — تباين عالٍ، خلفيات سوداء نقية في الوضع الليلي، مونوكروم غير دافئ، مساحات بيضاء سخية، أيقونات بسيطة
- **Apple HIG** — حواف Squircle بانحناءات عالية، Apple-style easing curves، حركات سلسة طويلة (300–600ms)
- **iOS app switcher** — انتقالات الصفحات بـ scale + fade

### المبادئ
1. **التباين الحاد بين البطاقة والخلفية** — بيضاء نقية على رمادي بارد فاتح (نهاري)، أو على أسود نقي (ليلي)
2. **الأرقام أبطال الصفحة** — أحجام كبيرة، `tabular-nums`, `direction: ltr` داخل سياق RTL
3. **زجاجية انتقائية** — `backdrop-filter: blur` للعناصر العائمة (`.float-card`) و sticky header و pill nav عند النزول. ليست في كل مكان
4. **حركة دقيقة** — انتقالات 200–600ms مع easing مدروس (Apple-like)
5. **النص العربي + الأرقام اللاتينية** — `123` فقط، لا `١٢٣`
6. **State persisted server-side** — كل قيمة تتزامن مع `state.json`/`timeline.json` على iCloud عبر سيرفر محلي

---

## 2. Color Tokens

كل الألوان CSS variables. التبديل بين النهاري/الليلي يحدث بـ `data-theme` على `<html>` (يُضبط من inline script في `<head>` قبل أي رسم لمنع الفلاش).

### الوضع النهاري
```css
--bg: #eef2f6;          /* رمادي بارد فاتح جداً (slate undertone) */
--bg-2: #e7ecf2;
--card: #ffffff;
--card-soft: #f4f7fa;
--card-elev: #ffffff;
--card-dark: #0e0e0e;   /* للعناصر التي تبقى داكنة */
--ink: #0a0a0a;
--ink-2: #2c2c2c;
--ink-3: #6c6c6c;
--ink-4: #a8a8a8;
--line: rgba(15,23,42,0.08);
--line-2: rgba(15,23,42,0.04);
--accent: #1f4dd6;
--success: #15803d;
--danger: #c41e1e;
--warning: #b45309;
```

### الوضع الليلي
```css
--bg: #000000;
--bg-2: #0a0a0a;
--card: #141414;
--card-soft: #0a0a0a;
--card-elev: #1c1c1c;
--ink: #ffffff;
--ink-2: #d4d4d4;
--ink-3: #8a8a8a;
--ink-4: #525252;
--line: rgba(255,255,255,0.08);
--line-2: rgba(255,255,255,0.04);
--accent: #5990E5;
--success: #4ade80;
--danger: #ef4444;
--warning: #fbbf24;
```

### Glass tokens
```css
/* Light */
--glass: rgba(255,255,255,0.45);
--glass-border: rgba(255,255,255,0.55);
--header-bg: rgba(238,242,246,0.55);
--glass-icon: rgba(15,23,42,0.06);

/* Dark */
--glass: rgba(20,20,20,0.35);
--glass-border: rgba(255,255,255,0.10);
--header-bg: rgba(0,0,0,0.55);
--glass-icon: rgba(255,255,255,0.08);
```

---

## 3. Typography

```css
font-family: "SF Pro Display", "SF Arabic", -apple-system, BlinkMacSystemFont,
             system-ui, "Helvetica Neue", sans-serif;
```

### الأرقام
كل رقم لاتيني يُلَفّ بـ `<span class="num">`:
```css
.num {
  font-family: "SF Pro Display", -apple-system, "Helvetica Neue", sans-serif;
  font-feature-settings: "tnum", "lnum";
  direction: ltr;
  unicode-bidi: isolate;
  display: inline-block;
}
```

### مقاييس
| الاستخدام | الحجم | السمك |
|---|---|---|
| Hero title | 56–64px | 600 |
| Big stat / verdict | 30–48px | 600 |
| Card title | 14px | 500 |
| Card sub (UPPERCASE) | 10.5px | 500 |
| Body | 13–14px | 400 |
| Meta | 11–12px | 400 |

---

## 4. Spacing, Radii, Shadows

### Border Radius (Squircle approximation)
```css
--r-card: 28px;   /* البطاقات */
--r-md: 18px;     /* أزرار، badges */
--r-sm: 12px;     /* صغيرة */

/* Hero */ border-radius: 32px;
/* Pills */ border-radius: 999px;
```

### Shadows
```css
/* Light */
--shadow: 0 1px 2px rgba(0,0,0,0.05), 0 8px 24px rgba(0,0,0,0.04);
--shadow-lg: 0 2px 4px rgba(0,0,0,0.06), 0 24px 60px rgba(0,0,0,0.08);

/* Dark — أعمق */
--shadow: 0 1px 2px rgba(0,0,0,0.4), 0 8px 24px rgba(0,0,0,0.3);
```

---

## 5. Layout System

### الهيكل العام
```
┌─────────────────────────────────────┐
│ App (grid: 72px sidebar | 1fr main) │
│                                      │
│  Sidebar           │  Main           │
│  ├ logo            │  ┌────────────┐ │
│  ├ nav (icons)     │  │ App Header │ │ ← sticky + glass
│  └ avatar          │  │  ├ status  │ │
│  (sticky 100vh)    │  │  └ topbar  │ │
│                    │  └────────────┘ │
│                    │  Hero           │
│                    │  Sections       │
│                    │  Bottom strip   │
└─────────────────────────────────────┘
```

### Grids
```css
.g3  { grid-template-columns: repeat(3, 1fr); }
.g4  { grid-template-columns: repeat(4, 1fr); }
.g12 { grid-template-columns: repeat(12, 1fr); }
.s3 .s4 .s5 .s6 .s7 .s8 .s12  /* spans */
```

### Breakpoints
- `1200px` — تقليص hero
- `1024px` — إخفاء sidebar، تحويل grids
- `720px` — موبايل، stack everything

---

## 6. الصفحات الثلاث

### A. `villa-plan.html` (الداشبورد)
4 أقسام:
1. **المدخلات الأساسية** — 3 بطاقات (شخصي، الجاهزة، البناء)
2. **المقارنة مع الفيلا الجاهزة** — مكونات التكلفة (s7) + ملخص الفرق (s5)
3. **التدفق النقدي الشهري** — قسطين + توزيع الراتب (ring chart)
4. **السوق والمخاطر** — مؤشرات GASTAT + خريطة المخاطر

> **مُحذوف:** التوصية الذكية، VOO portfolio، استراتيجية التفاوض (نُقلت). التكاليف المخفية مؤجلة (في `context.md`).

### B. `timeline.html` (رحلة البناء)
6 مراحل عمودية (Phases) متصلة بخط زمني:
1. التحضير الأولي
2. البحث عن الأرض واقتنائها
3. التصميم والرخصة
4. تمويل البناء
5. تنفيذ البناء
6. التسليم والاستلام

كل مرحلة: status (planned/active/done) + tasks + phase note. كل task: text + done + owner + completedDate + subtasks (مع owner + dueDate inline) + note + files.

Skeleton placeholders تظهر قبل تحميل JSON من السيرفر (أنيميشن shimmer).

### C. `financial-plan.html` (الخطة المالية)
6 أقسام:
1. **القرض العقاري** — معطيات + جدول amortization 25 سنة (تناقص الرصيد)
2. **القرض الشخصي** — flat-rate murabaha 5 سنوات + تقسيم تسلا/الوديعة
3. **توزيع الراتب الشهري** — ring chart (نفس الموجود في الداشبورد)
4. **السنة الأولى** — جدول شهري 12 شهر (راتب، قروض، متبقي، VOO، رصيد)
5. **محفظة VOO** — 3 سيناريوهات (7%, 10%, 13%) + bars شهرية
6. **ما بعد القرض الشخصي** — التحوّل عند تحرّر 31,867 ر.س/شهر بعد 5 سنوات

---

## 7. مكتبة المكونات

### .card
```html
<div class="card" data-views="overview ready">
  <div class="card-head">
    <div>
      <div class="card-title">العنوان</div>
      <div class="card-sub">SUB</div>
    </div>
    <button class="card-action"><svg>↗</svg></button>
  </div>
  <!-- محتوى -->
</div>
```

### .row (input row)
```html
<div class="row">
  <span class="lab">المسمى</span>
  <span class="val">
    <input class="ed num" data-key="myKey" value="100,000">
    <span class="unit">ر.س</span>
  </span>
</div>
```
`.row.derived` — قيمة محسوبة (خلفية soft + bold)

### .badge / .chip
```html
<span class="badge success">موصى به</span>
<span class="badge warning">3.9م</span>
<span class="badge danger">5</span>
<span class="badge accent">2.99%</span>
<span class="chip"><span class="dot" style="background:var(--ink)"></span> الجاهزة</span>
```

### .float-card (glassmorphism)
بطاقة عائمة فوق الفيلا في Hero:
```css
background: var(--glass);
backdrop-filter: blur(24px) saturate(180%);
border: 1px solid var(--glass-border);
```

### Allocation Ring
SVG circle مع 3 أقواس:
- 🔵 `accent` = قرض شخصي (يبدأ)
- ⚪ `ink` = قسط عقاري (يكمل)
- 🟢 `success` = استثمار شهري (أسهم) — الجزء الثالث
- ⭕ المتاح المتبقي = الجزء غير المرسوم

كل قوس له `stroke-dasharray` و `stroke-dashoffset` محسوبين من `2π × 54`.

### Personal Loan (flat-rate murabaha)
```js
total_profit = principal × annual_rate × years
total_paid = principal + total_profit
monthly = total_paid / (years × 12)
```
مع تقسيم بصري أسفل المبلغ:
- ↳ سُدِّد لتسوية سيارة تسلا (الأهلي)
- ↳ أُضيف للوديعة الاستثمارية

### Loan Split (للقرض العقاري)
```js
own_funds = deposit + support
loan_for_land = max(0, land_cost − own_funds)
loan_for_construction = max(0, construction_total − remaining_after_land)
```

---

## 8. التفاعلات

### Theme Toggle
- Inline script في `<head>` يقرأ من `localStorage.getItem('villa-theme')` ويضبط `documentElement.dataset.theme` قبل أي رسم
- زر فيه أيقونتي ☀ و ☾ دائماً ظاهرتان، الـ knob ينزلق بينهما
- عند الضغط: يبدّل الثيم على body + html ويحفظ في localStorage

### Eye Toggle (الحجب)
- العناصر الحساسة لها `data-mask`
- `body.masked` تفعّل الحجب
- `applyMask()` يستبدل text/value بنقاط `•` (3–7 عشوائياً) ويحفظ الأصلي في `dataset.orig`
- `unmaskAll()` يستعيد القيم
- **افتراضياً: الحجب مُعطَّل** (الأرقام ظاهرة عند الفتح)

### Sticky Header + Glass Pill
- `.app-header` sticky مع backdrop-filter
- عند `window.scrollY > 80`، body يحصل على class `scrolled`:
  - الـ statusbar + brand + tools يختفون (opacity 0)
  - الـ header background يصير شفاف
  - الـ `.pill-nav` يأخذ glass effect قوي ويبقى عائماً فوق المحتوى

### View Filter (في الداشبورد فقط)
كل بطاقة تأخذ `data-views="overview ready build cash"`. الضغط على tab يضع `body[data-view="ready"]` (مثلاً)، والـ CSS يخفي:
```css
body[data-view="ready"] [data-views]:not([data-views~="ready"]) { display: none; }
```

### Cross-document View Transitions
```css
@view-transition { navigation: auto; }
@keyframes vt-page-out { ... }
@keyframes vt-page-in { ... }
::view-transition-old(root) { animation: 360ms cubic-bezier(0.32, 0.72, 0, 1) both vt-page-out; }
::view-transition-new(root) { animation: 580ms cubic-bezier(0.16, 1, 0.3, 1) both vt-page-in; }
```
في `timeline.html` يضاف pagereveal handler يؤخّر بدء الـ transition حتى يجهز render الـ phases (يمنع ظهور الـ skeleton أثناء الانتقال).

### Sidebar Navigation
- الأيقونات `<a>` تنتقل بين الصفحات
- الأيقونات `<button>` تنزّل لأقسام داخل نفس الصفحة (smooth scroll)

### Persistence
```js
function saveState() {
  setTimeout(() => fetch('/state.json', { method: 'POST', body: JSON.stringify(S) }), 500);
}
async function loadState() {
  const saved = await fetch('/state.json').then(r => r.json());
  for (const k in saved) if (k in S) S[k] = saved[k];
}
```
`saveState` يُستدعى بعد كل `recalc()`.

### File Upload (timeline)
```js
fetch('/upload?phase=p1&task=t1', {
  method: 'POST',
  headers: { 'X-Filename': encodeURIComponent(file.name) },
  body: file,
})
```
السيرفر يحفظ في `attachments/<phase>/<task>/<filename>` مع sanitization.

---

## 9. المعمارية

### السيرفر (`server.py`)
- Python stdlib فقط (لا dependencies)
- `ThreadingHTTPServer` على المنفذ 8765
- يقدّم static files من project dir
- Endpoints:
  - `GET /<page>.html` — صفحات
  - `GET /state.json` — قراءة الحالة
  - `POST /state.json` — حفظ (atomic write)
  - `GET /timeline.json` — قراءة بيانات الرحلة
  - `POST /timeline.json` — حفظ
  - `POST /upload?phase=<id>&task=<id>` — رفع ملف
  - `POST /delete-file` — حذف ملف
- **Cache في الذاكرة** للملفات الكبيرة (`villa.png`) لتجنّب iCloud lock errors

### launchd
```
~/Library/LaunchAgents/
  ├── com.muath.villa-server.plist  → يشغّل server.py
  └── com.muath.villa-tunnel.plist  → cloudflared tunnel
```
كلاهما `KeepAlive=true` و `RunAtLoad=true`.

### Cloudflare Tunnel (Quick)
- مجاني، لا يحتاج account
- URL متغيّر مع كل إعادة تشغيل
- `villa-url` script يطبع الرابط الحالي من `/tmp/villa-tunnel.log`

---

## 10. State Model

كل صفحة لها كائن `S` داخل IIFE. الحقول المشتركة محفوظة في `state.json` على iCloud:

```js
const S = {
  // Personal finance
  salary, deposit, depositRate, personalLoan,

  // Ready villa
  readyPrice, taxRate, taxExempt, support,

  // Self-build
  landArea, landPrice, buildArea, buildPrice,
  elevator, rent, buildMonths,

  // Mortgage
  mortRateReady, mortRateBuild, term,

  // VOO
  vooMonthly, vooStart,

  // Hidden costs (UI removed pending Thursday meeting)
  hcPermits, hcUtilities, hcProfessional, hcExtras, hcFurniture, contingencyPct,
  insCAR, insProperty, insLife,
};
```

في `financial-plan.html` فيه إضافات:
```js
personalPrincipal: 1810351.93,   // إجمالي القرض الفعلي
personalTesla: 221732.24,        // المبلغ المسدّد للأهلي
personalRate: 1.09,
personalYears: 5,
personalStart: '2026-05',
loanForLand, loanForConstruction,  // محسوبة في loadState
vooYears: 5,
```

في `timeline.html` نموذج مختلف (`phases[]` بدل `S`).

---

## 11. Print / PDF

في الداشبورد `villa-plan.html` فقط. زر "تصدير التقرير" → popover بخيارين:
- **شخصي** — يفك القناع مؤقتاً، يفرض dark theme، يطبع
- **للغير** — يضيف `body.export-public` (يخفي `[data-sensitive]`)، يفرض dark theme، يطبع

```css
@media print {
  *, *::before, *::after {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }
  /* إخفاء UI chrome، الحفاظ على الثيم بكامل ألوانه */
  /* A4 landscape, 10mm margins */
}
body.export-public [data-sensitive] { display: none !important; }
```

البطاقات الحساسة (`data-sensitive`):
- الوضع المالي
- قسط الجاهزة
- قسط البناء
- توزيع الراتب
- إحصائية القسط في Hero

---

## 12. أشياء حرجة لاحترامها

- **محاذاة الأرقام:** `direction: ltr` و `tabular-nums` دائماً
- **العربي مع الأرقام:** `123` فقط، لا `١٢٣`
- **لون الفيلا:** لا تطبّق فلاتر CSS تغيّر ألوانها
- **الحجب:** أي حقل جديد حساس يجب إضافته إلى `MASKED_IDS` أو `MASKED_INPUT_KEYS`
- **الـ views:** أي بطاقة جديدة تحتاج `data-views="..."` لتظهر في الفلتر الصحيح
- **الـ sensitive:** أي بطاقة فيها معلومات شخصية تحتاج `data-sensitive` لتختفي في "تقرير للغير"
- **iCloud lock:** الملفات الكبيرة (PNG) قد تنقفل من iCloud؛ السيرفر يكاش في RAM، لا تعتمد على القراءة المباشرة في الـ critical path

---

## 13. التقنيات

- **HTML/CSS/JS بحت** — بدون أي framework
- **Python 3 stdlib** للسيرفر — بدون dependencies
- **Single-file pages** — كل صفحة self-contained مع CSS و JS مدمج
- **CSS Variables** للثيم
- **CSS Grid + Flexbox** للـ layout
- **`backdrop-filter`** للزجاجية
- **View Transitions API** للانتقالات
- **`@media print`** للـ PDF export
- **launchd** للتشغيل التلقائي
- **cloudflared** للوصول العام

---

## 14. مرجع سريع

```bash
# الحالة
launchctl list | grep villa

# الرابط العام
villa-url

# اللوقات
tail -f /tmp/villa-server.log
tail -f /tmp/villa-tunnel.log

# إعادة التشغيل
launchctl kickstart -k gui/$(id -u)/com.muath.villa-server
launchctl kickstart -k gui/$(id -u)/com.muath.villa-tunnel

# git
cd "~/Library/Mobile Documents/com~apple~CloudDocs/Me/AI/بيت العمر"
git status
git diff
git log --oneline
```
