# سجل التغييرات | CHANGELOG (GT-SIRM)

كلّ تغيير ملحوظ يُوثَّق هنا. التواريخ بصيغة YYYY-MM-DD.
الإصدارات تتبع [Semantic Versioning](https://semver.org/).

> **التبرّؤ الشرعيّ** يُعلَن مع كلّ إصدار — راجع [`README.md`](./README.md) و [`LICENSE`](./LICENSE).

---

## [0.12.8] — 2026-06-10

### 🔧 2 إصلاحات حَرِجة

#### (1) الاستيراد ما زال يَفتح في آخر مَجلّد
**السبب الفعليّ**: الـ`<input type="file">` كانت غالباً مَخفيّة بـCSS، والمستخدم يَنقر على الـ`.fu-area` parent الذي يَفتح dialog النَظام **مباشرةً** قبل أن يَصل الـclick لنا. الـlistener السابق على الـinput لم يَكن يُلتقَط.

**الإصلاح**:
- استَهداف الـ`.fu-area` parent بَدلاً من الـinput.
- `input.style.pointerEvents = "none"` لمَنع الـbrowser من تَوجيه الـclick إليه.
- `e.preventDefault() + e.stopPropagation()` على الـ`.fu-area` click.
- استِعلام `S.workDirSubfolders` من cache أو IPC مُباشرةً.
- fallback: إن لم يُوجد مَسار، يَفتح الـinput الطبيعيّ.

#### (2) تَعديل القالب يَعرض JSON خامّ — غير مَفهوم
**السبب**: حاولتُ في v0.12.7 عَرض محرِّر JSON مَع textarea للحالة. هذا غير ملائم للمستخدم العاديّ.

**الإصلاح — نَهج "تَطبيق-وَتَعديل"**:
عند الضَغط على ✏️ تَعديل في بطاقة قالب:
1. القالب يُطبَّق على الواجهة (`applyState`).
2. الانتقال لـtab-rec تلقائياً.
3. **بانر تَعديل** يَظهر في أعلى الشاشة:
   ```
   🛠️ تُعدِّل قالب "ذهبي ساطع" — اضبط ما تُريد ثمّ احفظ
   [حقل اسم] [💾 احفظ التَعديلات] [❌ إلغاء]
   ```
4. المُستخدم يُعدّل الإعدادات في الواجهة كالمعتاد.
5. عند الحفظ: `captureState()` → يَستبدل حالة القالب القديم + تَحديث التاريخ.

النَهج طبيعيّ ومَألوف، لا JSON.

📦 PWA cache → v53.

---

## [0.12.7] — 2026-06-10 — 5 تَحسينات

### 🐛 إصلاحات + ميزات جديدة

#### (1) العَطل الجَوهريّ في فتح dialog مَع defaultPath
IPC `dialog-open` كان يَتجاهل `opts.defaultPath` تَماماً. كلّ مَكان يُمرّر `defaultPath` لا يَستفِد منه — Electron يَفتح في "آخر مَكان". الإصلاح: إضافة `defaultPath` للـcall + `mkdir -p` المَسار قبل الاستخدام.

النَتيجة: 🎤 صوت تلاوة مخصّص يَفتح في `custom-audio/` دائماً. 🎥 فيديو تلاوة يَفتح في `recitations/`. كلّ مَرّة، حتى لو نَقل المستخدم لمَكان آخر سابقاً.

#### (2) حَذف قسم "📐 مقاس الفيديو" من تَبويب التلاوة
نُقل بالكامل للإعدادات (نسبة العرض). الـradio `name="fmt"` يَبقى مَخفيّاً للتَوافق.

#### (3) "🎨 ثيم جاهز" → "🎨 سمة جاهزة" + خلفيّة تلقائيّة
- التَّسمية مُحدَّثة في الواجهة.
- عند اختيار سمة، نَوع الخلفيّة يَنتقل تلقائياً لـ"تَدرّج" (السمة تُعرَّف بألوان التَدرّج، فبَقاؤها على "صورة/فيديو" بلا معنى).

#### (4) القوالب — تَعديل خصائص inline
زرّ "✏️ تَعديل" جديد في كلّ بطاقة قالب يَكشف نَموذج محرِّر:
- حقل اسم القالب.
- محرِّر JSON للحالة (متقدّم — للمستخدمين الذين يَحتاجون تَعديلاً دَقيقاً).
- "💾 حفظ التَعديلات" / "إلغاء".

#### (5) القوالب — مهلة تَراجع 5 ثوانٍ عند الحذف
عند الضَغط على 🗑️:
- يُحذف القالب فوراً (UI يَستجيب).
- toast بزرّ "↩️ تَراجع" يَظهر أَسفل الشاشة 5 ثوانٍ.
- إن نَقر المستخدم → القالب يُستعاد بالمَوقع نَفسه.
- بَعد 5 ثوانٍ بدون تَراجع → الحذف نَهائيّ.

📦 PWA cache → v52.

---

## [0.12.6] — 2026-06-10 — 4 إصلاحات

### 🐛 4 إصلاحات في تَجربة المستخدم

#### (1) القوالب المُخصَّصة لا تَستجيب لـ"تطبيق" و "حذف"
**السبب**: CSP في `index.html` يُحظر `onclick=""` inline (`script-src 'self'` بدون `unsafe-inline`).
**الإصلاح**: `data-tpl-apply` و `data-tpl-del` + delegated event listeners في `renderTemplates()`.

#### (2) نسبة العرض في الإعدادات (radio 4 خِيارات) لا تُغَيِّر شيئاً
**السبب**: `name="ratio"` في الإعدادات (السطر 1702 في HTML) لم يُربط بأيّ handler. الـradio الفعليّ في تَبويب المشهد اسمه `name="fmt"` ويُعالَج عبر `onFmtChange`.
**الإصلاح**: في `initEventListeners`، ربط `name="ratio"` لـ:
1. مُزامنة مع `name="fmt"` (تَحديث الـchecked المُكافِئ).
2. استدعاء `onFmtChange()`.

#### (3) القالب الجاهز يَعود إلى "اختر قالباً" بعد الاختيار
**السبب**: `onPresetChange` كان فيه `setTimeout(() => { e.target.value = ""; }, 100)` لتَمكين إعادة اختيار نَفس القيمة.
**الإصلاح**: حَذف إعادة الضَبط. القيمة تَبقى ظاهرة لأنّها مَعلومة مهمّة للمستخدم.

#### (4) زرّ الاستيراد يَفتح من المنزل لا من مجلّد العمل المُختَصّ
**السبب**: `<input type="file">` لا يَدعم `defaultPath` (قَيد API الويب).
**الحلّ**: `installWorkdirInputInterceptor()` يَعترض النَقر على inputs المُحدَّدة في `FILE_INPUT_WORKDIR_MAP`:
- `bg-vid-input` → `bg-videos/`
- `bg-audio-input` → `bg-audio/`
- `bg-img-input` → `bg-videos/` (مَعتاد للخَلفيّات)
- `recvid-file` → `recitations/`
- `free-audio-file` → `custom-audio/`
- `logo-input` → `logos/`

يَفتح Electron `dialog-open` مع `defaultPath` المُختَصّ + filters صحيحة. يَقرأ المَلفّ عبر IPC، يَبني File، يُسلّمه للـhandler الأصليّ (نَفس مَسار الـv0.8.8).

📦 PWA cache → v51.

---

## [0.12.5] — 2026-06-10

### 📁 مَسارات الحوار الافتراضيّة تَنفتح في مجلّد العمل

#### المُشكلة
عند الضغط على "تَصدير"، نافذة "احفظ الملفّ" تَفتح في مَسار النظام الافتراضيّ (المنزل عادةً) بدل مجلّد `exports/` من مجلّد العمل. نَفس الشيء لـ"حفظ المشروع" و"فتح مشروع".

#### الإصلاح
**التَصدير** (`startExport`):
- آخر مَسار حفظ في localStorage **أوّلاً** (احتراماً لاختيار المستخدم السابق).
- إن لم يُوجد → `{workDir}/exports/` تلقائياً.
- إن لم يُوجد مجلّد عمل → افتراضيّ النظام.

**حفظ المشروع** (`project-save-dialog` IPC):
- اسم بدون مَسار → `{workDir}/projects/{filename}.gtsirm`.
- اسم نِسبيّ → يُكمَّل بمَسار `projects/`.
- اسم مُطلَق → كما هو.

**فتح المشروع** (`project-open-dialog` IPC):
- يَفتح في `{workDir}/projects/` افتراضياً.

#### الفنّيّ
- دالّة جديدة `workdirSubPath(subKey)` في main.js تَعود بمَسار المجلّد الفرعيّ من حفظ الإعدادات.
- في app.js: `S.workDirSubfolders.exports` كَـfallback إن كان localStorage فارغاً.

#### الأولويّة العامّة
1. اختيار المستخدم السابق (localStorage)
2. مجلّد العمل المُختَصّ
3. افتراضيّ النظام

📦 PWA cache → v50.

---

## [0.12.4] — 2026-06-10

### 🎬 نَهج 3 خِيارات في قسم الاستيراد بالمشهد

#### المُكان
قسم "📥 استيراد وسائط" في تَبويب المشهد (الذي يَستخدم yt-dlp/wget/aria2c لتَنزيل الخَلفيّات).

#### المُشكلة
كان يَعتمد على الإعدادات العامّة `S.dlSaveMode` / `S.dlSavePath` (المُخفيّة في الإعدادات بعد v0.12.2). المستخدم بدون مَسار في الإعدادات → لا يَستطيع تَخصيص مَكان الحفظ هنا.

#### الإصلاح
نَفس نَمط v0.12.3:
- 📁 **مؤقت (/tmp)** — للتَجارب
- 💾 **مجلّد العمل (افتراضيّ، مُختار)** — تَوجيه ذكيّ:
  - 🎥 فيديو → `bg-videos/`
  - 🔊 صوت → `bg-audio/`
  - 🖼️ صورة → `logos/`
- 🗂️ **مَسار يَدويّ مُخصَّص** — يَكشف حقل المَسار + زرّ تَصفّح

#### الفنّيّ
- `<input name="bgdl-save-mode">` مع 3 radio buttons.
- `#bgdl-path-row` يَظهر فقط مع `manual`.
- زرّ `#bgdl-browse` يُفتح dialog لاختيار المَسار.
- `runYtdlpDownload` يَستخدم القيم المحلّيّة بدل `S.dl*` العامّة.

📦 PWA cache → v49.

---

## [0.12.3] — 2026-06-10 — إصلاح حرج

### 💾 مجلّد العمل أصبح الافتراضيّ في تَنزيلات yt-dlp

#### المُشكلة في v0.12.2
الـUI كان يَعرض خِيارَين: 📁 مؤقت / 💾 دائم. عند اختيار "💾 دائم"، الكود يَستخدم التَوجيه الذكيّ **فقط إذا كان حقل المَسار اليَدويّ فارغاً**. لكنّ المستخدم لديه مَسار محفوظ من جَلسة سابقة → الكود يَتجاوز التَوجيه الذكيّ ويَستخدم مَسار قَديم.

#### الحلّ — 3 خِيارات صَريحة
بَدلاً من تَخمين نِيّة المستخدم، نَطلب اختياراً صَريحاً:
- 📁 **مؤقت (/tmp)** — يُحذف عند إعادة التَشغيل
- 💾 **مجلّد العمل (افتراضيّ)** ← **المُختار مُسبَقاً**، يَنزل في المجلّد الفَرعيّ تلقائياً
- 🗂️ **مَسار يَدويّ مُخصَّص** — يَكشف حقل المَسار

كلّ خِيار له نِيّة واضحة، لا غُموض.

#### في كلّ قسم تَنزيل
- 🎤 صوت تلاوة مخصّص: 💾 افتراضيّ → `custom-audio/`
- 🎥 فيديو تلاوة جاهز: 💾 افتراضيّ → `recitations/`
- (لاحقاً سَيُطبَّق على باقي أقسام التَنزيل)

#### التَطبيق
- `recvid-dl-mode` و `free-audio-dl-mode`: 3 radio بدل 2.
- القيمة الافتراضيّة `workdir` (مُختارة).
- `recvid-dl-path-row` يَظهر فقط مع `manual`.
- JS تَرجم الاختيار للـIPC:
  - `workdir` → `dlSaveMode: "permanent"` + `workdirSubfolderKey: <key>`
  - `manual` → `dlSaveMode: "permanent"` + `dlSavePath: <path>`
  - `temporary` → `dlSaveMode: "temporary"`

📦 PWA cache → v48.

---

## [0.12.2] — 2026-06-10

### ⬇️ تَوجيه ذكيّ لتَنزيلات yt-dlp حسب نوع المصدر

#### المُشكلة
"مجلد حفظ الوسائط" كان يَطلب من المستخدم اختيار مَسار واحد لكلّ التَنزيلات. لكنّ المستخدم لديه 4 أنواع مَصادر مُختلفة (فيديو خلفيّة، صوت خلفيّة، صوت تلاوة، فيديو تلاوة)، وكلّ نَوع يَخدم وَظيفة مُختلفة. إجبارها على مَسار مُوحَّد يُلغي فائدة بنية مجلّد العمل.

#### الحلّ
**تَوجيه ذكيّ تلقائيّ** — عند اختيار 💾 دائم في أيّ قسم تَنزيل، يَذهب المَلفّ تلقائياً للمجلّد الفرعيّ المناسب من مجلّد العمل:

| القِسم | المجلّد الفَرعيّ |
|---|---|
| 🎬 خلفيّة فيديو (المشهد) | `bg-videos/` |
| 🎵 صوت خلفيّة (المشهد) | `bg-audio/` |
| 🎤 صوت تلاوة مخصّص | `custom-audio/` |
| 🎥 فيديو تلاوة جاهز | `recitations/` |
| 🖼️ صورة خلفيّة | `logos/` |

#### التَّطبيق الفنّيّ
- IPC `ytdlp-download` يَستقبل `workdirSubfolderKey` جديد.
- الأولويّة: `workdirSubfolderKey` (تَوجيه ذكيّ) → `dlSavePath` (يَدويّ) → `/tmp`.
- `runRecvidYtdlpDownload`, `runFreeAudioYtdlpDownload`, `runYtdlpDownload` (للمشهد) كلّها تُمرّر الـkey المناسب لكلّ نَوع.
- إذا اختار المستخدم 🗂️ "مَسار يَدويّ"، يَتجاوز التَوجيه الذكيّ.

#### الإعدادات
قسم "مجلد حفظ الوسائط" أُعيد تَصميمه:
- لا حُقول إدخال مَسار رئيسيّة (لم تَعد ضَروريّة).
- جَدول واضح يَشرح: كلّ نَوع → مجلّده.
- الإعدادات القَديمة (radio + text input) مَخفيّة لكنّها مَوجودة لـbackward-compat.

📦 PWA cache → v47.

---

## [0.12.1] — 2026-06-10

### 🗂️ إعادة هَيكلة تَبويب الإعدادات: جيوب قابلة للطيّ + ترتيب جديد

#### الفكرة
كثرة أقسام الإعدادات تُربك المستخدم. الحلّ: كلّ قسم في "جيب" قابل للفتح/الإغلاق، يَفتحه عند الحاجة فقط.

#### التَّطبيق
- كلّ `<div class="sec">` في tab-settings → `<details class="sec">` + `<summary class="sec-t">`.
- CSS بسيط: سَهم ▸/▾ يَدور حسب حال الجيب، hover يُغيّر اللون.
- قسم واحد فقط مَفتوح افتراضياً: **📐 نسبة العرض** (أوّل قرار في صناعة المقطع).

#### الترتيب الجديد
1. 📐 نسبة العرض (مَفتوح افتراضياً) ← كان في الوسط، نُقل للأعلى
2. 🎯 قالب جاهز للمنصة
3. 🎬 جودة التصدير
4. 📦 وحدات المحتوى
5. **📁 مجلّد العمل** (v0.12) ← نُقل تحت الوحدات كما طُلب
6. 📁 مجلد حفظ الوسائط (yt-dlp) ← مُكمِّل لمجلّد العمل، مع note توضّح العَلاقة
7. 💾 الحفظ التلقائي
8. 🔊 الصوت عند المعاينة
9. 📱 عرض الأدوات
10. 🎬 إعدادات ffmpeg
11. 🖥️ معلومات النظام
12. 🗑️ إعادة الضبط

#### إصلاح تَصميم قسم مجلّد العمل
- `desktop-only` بدون `blk` كان يُطبّق `display: flex` على القسم، فيَنكسر تَخطيط النصّ. **أُصلِح**: `desktop-only blk`.
- إزالة `direction: ltr` غير الضروريّ من حقل المسار (الـ`<input class="fc">` يَتعامل مع RTL تلقائياً).

📦 PWA cache → v46.

---

## [0.12.0] — 2026-06-10

### 📁 مجلّد العمل الافتراضيّ (سطح المكتب)

#### الفكرة
كلّ مَصادر مَشاريع المستخدم في مَكان واحد منظَّم بدل التَّشتّت في مَسارات مَتفرّقة.

#### البنية
عند أوّل تَشغيل، يُنشَأ تلقائياً:
```
~/Documents/مجلد عمل ريلز إسلامية/
├── 📁 projects/      — ملفّات .gtsirm
├── 🎬 bg-videos/     — فيديوهات الخلفيّة
├── 🎵 bg-audio/      — صوت الخلفيّة
├── 🎥 recitations/   — فيديوهات التَلاوة الجاهزة
├── 🎤 custom-audio/  — الصوت المخصّص (yt-dlp → OGG)
├── 🖼️ logos/         — الشعارات
├── 📤 exports/       — المقاطع المُصدَّرة
├── 🎙️ recordings/    — تَسجيلات الميكروفون
└── اقرأني.md         — دليل المجلّدات
```

#### الإعدادات الجديدة
- **📁 مجلّد العمل** — قسم في تَبويب الإعدادات يَعرض المَسار الحاليّ.
- **📂 فَتح المجلّد** — يَفتحه في file manager للنظام (xdg-open / Finder).
- **🚚 نَقل المجلّد** — يَختار مَسار جديد + يَسأل إن كانت المُحتويات تَنتقل أم لا.
- **📥 اقتراح نَسخ الملفّات الخارجيّة** (مفعَّل افتراضياً) — عند رَفع مَلفّ من خارج المجلّد، يَسأل إن كنت تُريد نَسخه إلى المجلّد الفرعيّ المناسب.

#### الفنّيّ
- **5 IPCs جديدة** في `main.js`:
  - `workdir-get` — يَعود بالمَسار + المجلّدات الفرعيّة.
  - `workdir-ensure` — يُنشِئ البنية.
  - `workdir-move` — يَنقل المجلّد (مع نَسخ المحتويات اختيارياً).
  - `workdir-import-file` — يَنسخ مَلفّاً خارجيّاً إلى مجلّد فَرعيّ.
  - `workdir-open` — `shell.openPath`.
- **إعدادات**: تُخزَّن في `~/.config/GT-SIRM/work-dir-config.json` (`app.getPath("userData")`).
- **README العربيّ**: يُولَّد كـ`اقرأني.md` يَشرح المجلّدات الفرعيّة.

#### حدود v0.12.0
- **Android**: لاحقاً في v0.12.1 (`@capacitor/filesystem`).
- **الويب**: لا يُمكنه إنشاء مجلّدات حقيقيّة في HDD (مَخطَّط: OPFS لاحقاً).
- **maybeImportToWorkDir**: دالّة جاهزة، لم تُدمَج في كلّ handlers الرفع بَعد — يُمكن إضافتها تَدريجياً في v0.12.1.

📦 PWA cache → v45.

---

## [0.11.3] — 2026-06-10

### 💾 إصلاحات الحفظ التلقائيّ

#### العَطل الأوّل: علامة "غير محفوظ" تَبقى رغم نجاح الحفظ التلقائيّ
**الويب**: `localStorage.setItem("gt_sirm_autosave_blob", ...)` كان يَنجح لكن `clearProjectDirty()` لا يُستدعى. النَتيجة: عند إغلاق التطبيق، `beforeunload` يَفجِّر تَحذير "تغييرات غير محفوظة" حتى بعد حفظ ناجح.

**الإصلاح**: استدعاء `clearProjectDirty()` بعد كلّ كتابة ناجحة في `localStorage`.

#### العَطل الثاني: سطح المكتب بدون مَسار `.gtsirm` → الحفظ التلقائيّ لا يَعمل أبداً
كانت الدالّة تَنتهي مبكراً إن لم يَكن `S.projectFilePath` مَوجوداً:
```
if (!S.projectFilePath && IS_DESKTOP_BUILD) return;
```
النَتيجة: المستخدم الذي لم يَحفظ يدوياً (أوّل جلسة) لا يَحصل على أيّ حفظ تلقائيّ.

**الإصلاح**: إن لم يَكن هناك مَسار، يَستخدم `localStorage` كـfallback (نَفس آليّة الويب، حدّ 4.5MB).

#### تغيير افتراضيّ: الحفظ التلقائيّ مُفعَّل افتراضياً
- توگل `autosave-on` يَبدأ مُفعَّلاً إن لم يَكن هناك قيمة محفوظة (`localStorage.getItem` ← `null` → `true`).
- الفترة الافتراضيّة 5 دقائق.
- المستخدم يَستطيع إلغاءها يدوياً، لكنّ الحال الأوّليّ أصبح "حماية بالافتراض".

#### حال الحفظ يَعرض الـmode الحاليّ
- إن كان `.gtsirm` مَوجوداً: 🟢 مُفعَّل — كلّ N دقيقة.
- إن كان localStorage fallback: 🟡 مُفعَّل — كلّ N دقيقة (في الذاكرة المحلّيّة — احفظ يدوياً .gtsirm لمسار دائم).

📦 PWA cache → v44.

---

## [0.11.2] — 2026-06-10 — إصلاح جوهريّ

### إصلاح تَشويش المؤثّرات في الملفّ المُصدَّر

#### العطل
في v0.11.1 كانت المؤثّرات تَعمل في التصدير لكنّ النَتيجة "مَشوَّشة وغير صافية" مقارنةً بالمعاينة. السبب الفنّيّ:
- `mixAudioToBuffer` كانت تَلفّ `bgBuffer` في حلقة `while` (لكلّ تَكرار source جديد).
- **بَنَت سلسلة FX جديدة لكلّ تَكرار** — كلّ سلسلة تُولّد IR عشوائيّاً مختلفاً عبر `createImpulseResponse` (ضوضاء بيضاء).
- N تَكرارات → N IRs مختلفة + N reverb tails تَتراكَب → تَشويش متَزايد كلّما طال المقطع.

#### الإصلاح
دالّة جديدة `preprocessBgBufferWithFX(bgBuffer, cfg, bgLoop, totalDuration)` تُنفِّذ:
1. تُنشِئ `OfflineAudioContext` بطول `totalDuration + 4s tail`.
2. تَضع تَكرارات `bgBuffer` (إن لزم) عبر `mixer` GainNode واحد.
3. تَطبّق سلسلة FX **مَرّة واحدة** على mixer (IR واحد فقط).
4. تُرنَدر إلى `effectiveBuffer` مَطبَّقاً عليه FX بالكامل.

في `mixAudioToBuffer`، عند تَفعيل المؤثّرات:
- يَستدعي `preprocessBgBufferWithFX` لإنشاء `effectiveBuffer`.
- يَضعه كـsource واحد في mixer التصدير الرَئيسيّ.
- لا حلقة + لا تَكرار FX.

عند عَدم تَفعيل المؤثّرات: المسار العاديّ (حلقة التَكرار البسيطة) يَبقى كما هو.

#### التَطبيق
- `export-engine.js` (سطح المكتب): `preprocessBgBufferWithFX`.
- `export-engine-web.js` (الويب): `_webPreprocessBgBufferWithFX` بنفس المنطق.

النَتيجة: الملفّ المُصدَّر = المعاينة بصوت صافٍ متَطابق.

📦 PWA cache → v43.

---

## [0.11.1] — 2026-06-10

### 🎛️ المؤثّرات الصوتيّة الآن مَطبَّقة في التصدير V2 أيضاً

#### العطل في v0.11.0
المؤثّرات كانت تَعمل في المعاينة الحيّة فقط. الملفّ المُصدَّر (V2 deterministic عبر OfflineAudioContext + ffmpeg/WebCodecs) كان يَخرج **بدون مؤثّرات** — لأنّ V2 يَتجاوز `S.exportDest` المُتّصل بالمعاينة.

#### الإصلاح
- **`export-engine.js`** (سطح المكتب): دوالّ `_exportCreateIR` + `_exportBuildFXChain` مُكرَّرة من app.js لاستقلال المحرّك. `mixAudioToBuffer` تَقبل `bgFXConfig` وتُطبّقه على `bgBuffer` داخل `OfflineAudioContext`.
- **`export-engine-web.js`** (الويب): نفس التَكرار بأسماء `_webExportCreateIR` + `_webExportBuildFXChain`. `mixAudioToBufferWeb` تَقبل `bgFXConfig`.
- **`app.js`** في كلا النسختين: عند بدء التصدير V2، يَجمع `bgFXConfig` من DOM:
  - إن كان recvid فاعِلاً + `recvid-fx-on` مفعَّل → `getFXConfig("recvid")`.
  - وإلّا إن كان `free-fx-on` مفعَّل → `getFXConfig("free")`.
  - وإلّا → `null` (يُتجاوز المحرّك تَطبيق المؤثّرات).

#### النَتيجة
الصدى، الإكو، EQ، ومستوى الصوت — كلّها مَكتوبة في الملفّ المُصدَّر بالـbit-exact مع ما يَسمعه المستخدم في المعاينة.

📦 PWA cache → v42.

---

## [0.11.0] — 2026-06-10

### 🎛️ المؤثّرات الصوتيّة (Audio FX) في المعاينة

#### الميزة
قسمان جديدان داخل "🎤 صوت تلاوة مخصّص" و "🎥 فيديو تلاوة جاهز" — توگل "🎛️ مؤثّرات صوتيّة" غير مفعَّل افتراضياً والخصائص مَخفيّة. عند التفعيل تَظهر:

**🔊 مستوى الصوت** (0-200%)

**🌊 الصدى (Reverb)** بـ 5 إعدادات بيئة (synthetic IR — لا ملفّات خارجيّة):
- 🏠 غرفة صغيرة (0.3s decay)
- 🎙️ استوديو (0.5s)
- 🕌 مسجد صغير (1.5s)
- 🕌 مسجد كبير (3.0s) ← الافتراضيّ
- 🏛️ قاعة كبيرة (5.0s)
- ضابط شدّة (0-100%)

**🔁 الإكو (Delay)**:
- شدّة الإكو (0-100%)
- وقت التأخير (50-800ms)
- التغذية الراجعة (0-80%)

**🎚️ التسوية الصوتيّة (EQ 3-band)**:
- الجِير Bass (lowshelf @ 200Hz)
- الوسط Mid (peaking @ 1kHz)
- الحادّ Treble (highshelf @ 5kHz)
- كلّ ضابط من -12 إلى +12 dB

#### الفنّيّ
- **محرّك موحَّد**: `buildAudioFXChain(ctx, source, cfg)` يَعمل مع `AudioContext` و `OfflineAudioContext` معاً.
- **IR رقميّ**: `createImpulseResponse(ctx, preset)` يُولّد ضوضاء بيضاء تَتلاشى أُسّياً — لا ملفّات IR خارجيّة، يَعمل تحت `file://`.
- **سلسلة المسار**: source → inputGain → EQ (lowshelf → peaking → highshelf) → splitter → (dry + reverb wet + echo wet) → mixer → destinations.
- **applyBgAudioFXLive** و **applyRecVidFXLive** يُعيدان بناء السلسلة عند كلّ تغيير في توگل/سلايدر — قد يُسبَّب صوت click بسيط لكن مَقبول.
- **مَوصول بـ**: live preview + analyser الذبذبات + S.exportDest (تَسجيل MediaRecorder للتصدير V1).

#### حدود v0.11.0
- التصدير V2 (المُحدِّد لـffmpeg في سطح المكتب وWebCodecs في الويب) لا يُطبّق المؤثّرات بَعد. سَيُضاف في v0.11.1 بتَطبيق `buildAudioFXChain` داخل `mixAudioToBuffer` على `OfflineAudioContext`.
- المعاينة + تصدير V1 (MediaRecorder) يَعملان بالمؤثّرات الآن.

📦 PWA cache → v41.

---

## [0.10.0] — 2026-06-09

### 🌟 ثلاث وحدات جديدة: أسماء الله الحسنى + الأدعية + الحِكَم

#### ✨ وحدة أسماء الله الحسنى
- **100 اسم** (99 + الصبور) مع المعنى المُختصَر والشاهد القرآنيّ.
- **المصدر**: القائمة المرويّة في صحيح الترمذي (3507) + شروح ابن القيّم وابن عثيمين.
- بحث متطبَّع في الاسم وفي المعنى.
- زرّان للتطبيق:
  - **📥 تطبيق الاسم الحاليّ** — شريحة واحدة (الاسم + المعنى + الشاهد).
  - **📥 تطبيق كلّ الأسماء** — 100 شريحة بالتتابع لمقاطع طويلة.
- ملفّ `asma-data.js` (24 KB).

#### 🤲 وحدة الأدعية المأثورة
- **32 دعاءً** في **5 فئات**:
  - 📖 أدعية من القرآن الكريم (10).
  - 🌊 أدعية الكرب والشدّة (4).
  - 🌅 أدعية الصباح والمساء (3).
  - 🤲 أدعية يوميّة موصى بها (5).
  - ✨ أدعية الاستخارة والاستغفار (6).
- كلّ دعاء بـ: النصّ المُشكَّل، المصدر الدقيق (سورة:آية أو الصحيحان/السنن مع الترقيم)، المناسبة.
- ✂️ **توگل التقسيم الذكيّ** (مفعَّل افتراضياً) — يَفصل الدعاء على الترقيم وآيات القرآن.
- ملفّ `duas-data.js` (14 KB).

#### 🌟 وحدة الحِكَم والمواعظ
- **32 قولاً** في **4 فئات**:
  - 👥 حِكَم الصحابة رضوان الله عليهم (8).
  - 📖 حِكَم التابعين (8).
  - 🕌 حِكَم الأئمّة الأربعة (8).
  - ✒️ حِكَم ابن القيّم وابن تيمية (8).
- كلّ حكمة بـ: النصّ، اسم القائل، المرجع الكتابيّ (نهج البلاغة، حلية الأولياء، سير أعلام النبلاء، مدارج السالكين، إلخ).
- ✂️ **توگل التقسيم الذكيّ** + يُضاف القائل كشريحة أخيرة تلقائياً.
- ملفّ `hikam-data.js` (11 KB).

#### الفنّيّ
- 3 ملفّات بيانات classic script: `asma-data.js` + `duas-data.js` + `hikam-data.js`.
- 3 وحدات في `MODULES` بـ `impl: true` — قابلة للتفعيل في الإعدادات (المنع المتبادل ساري).
- 3 دوالّ `initX` + 3 دوالّ `applyX` بنفس النمط الموحَّد (نمط الحديث/الأذكار).
- مساعد جديد `clearOtherSourcesUI()` — يُنظّف معاينات + أزرار الوحدات الأخرى عند تطبيق وحدة جديدة.
- يَستعمل `splitArabicTextSmart` (المُنشَأة في v0.9.1) للأدعية والحِكَم.
- Service Worker يُخزِّن الملفّات الثلاثة (cache v40).
- `build-apk.sh` يَنسخ الملفّات الجديدة إلى `www/`.

#### التوثيق
- README + ROADMAP محدَّثان (v0.10.0 منجَزة).
- توگلات الإعدادات: شارات "قريباً" → "v0.10" + إزالة `disabled`.

📦 PWA cache → v40.

---

## [0.9.1] — 2026-06-09

### 🪓 التقسيم الذكيّ للأذكار

#### العطل
عند تطبيق ذكر طويل من حصن المسلم (مثل أذكار الصباح/المساء التي تَحوي آية الكرسي، أو الأذكار الموسَّعة)، كان النصّ يَخرج كشريحة واحدة عملاقة — يَتعذّر استخدامها في الإنتاج كمقاطع منفصلة.

#### الإصلاح
- دالّة جديدة `splitArabicTextSmart(text)` تَفهم:
  - **آيات القرآن** المُحاطة بـ `﴿﴾` → تُفصَل كشرائح مستقلّة (مع تقسيم الآيات الطويلة على `* ۝ ۞`).
  - **الأقواس المضاعفة** `((...))` والمعقوفات `[[...]]` → تُنظَّف.
  - **الأقواس المفردة** `(...)` و `[...]` → يُبقى محتواها مع تنظيف الأقواس.
  - **الترقيم العربيّ والإنجليزيّ** `. ، ؛ ؟ !` → نقاط فصل طبيعيّة.
  - الترتيب الأصليّ للنصّ مَحفوظ (التعويذة قبل الآية تَبقى قبلها، إلخ).
  - الجُمَل القصيرة جدّاً (< 18 حرف) تُدمَج مع سابقتها لتجنّب الجُمل المُبتورة.

#### الواجهة
- توگل جديد ✂️ "تقسيم الذكر تلقائياً إلى شرائح" — مفعَّل افتراضياً.
- يَعمل مع توگل التكرار الموجود مُسبَقاً: إن كان الذكر "3 مرّات" والتقسيم يُعطي 4 شرائح، يَنتج 12 شريحة (3 × 4).

#### مثال
"أَعُوذُ بِاللَّهِ ... ﴿اللَّهُ لاَ إِلَهَ إِلاَّ هُوَ ... لاَ تَأْخُذُهُ سِنَةٌ وَلاَ نَوْمٌ﴾"

قبل: 1 شريحة (نصّ مدموج).
بعد: 3 شرائح (التعويذة + الجزء الأوّل من الآية + الجزء الثاني).

📦 PWA cache → v39.

---

## [0.9.0] — 2026-06-09

### 🕊️ وحدة الأذكار — استيراد كامل من GT-HISNMUSLIM

#### المصدر
البيانات مأخوذة من مشروع [GT-HISNMUSLIM](https://github.com/SalehGNUTUX/GT_HISNMUSLIM) — تطبيق "حصن المسلم" المفتوح المصدر للمؤلِّف نفسه (SalehGNUTUX). هذا تجسيد لمبدأ "**برامجنا المترابطة في خدمة بعضها البعض**".

#### المحتوى
- **132 فئة** من الأذكار المحقَّقة.
- **267 ذكراً** مع نصّ كامل + عدد التكرار + روابط صوتيّة احتياطيّة من hisnmuslim.com.
- أبرز الفئات: أذكار الصباح والمساء (24 ذكراً)، أذكار النوم (13)، أذكار الاستيقاظ (4)، أذكار بعد الصلاة، الطعام، السفر، المسجد...

#### الواجهة (مكرَّرة من نمط وحدة الحديث)
في `tab-rec` بعد قسم الحديث الشريف:
- 🕊️ التوگل + قسم `data-module="azkar"`.
- قائمة منسدلة للفئة (مع الأيقونات والعدد).
- بحث متطبَّع (`normalizeArabic`) في كلّ نصّ الذكر.
- معاينة بنصّ كامل + علامة "🔁 يُكرَّر N مرّات" إن كان متعدّد التكرار.
- 🔁 توگل "إنشاء شريحة لكلّ تكرار" (مفعّل افتراضياً):
  - ON: ذكر بعدد 3 → 3 شرائح بنفس النصّ.
  - OFF: شريحة واحدة بنصّ "ذكر... (3× مرّات)".
- زرّ "📥 تطبيق الذكر كنصّ المقطع".
- زرّ "🎚️ ضبط توقيت كلّ شريحة" (يَستعمل `openPerSliceSmart` الموحَّد).

#### الفنّيّ
- ملفّ جديد `azkar-data.js` (~106 KB، classic script يَنتُج `window.AZKAR_DATA`).
- `MODULES.azkar.impl = true` — أصبحت وحدة قابلة للتفعيل في الإعدادات.
- `applyAzkar(z, cat)` يَستخدم نفس بنية `applyHadith` (S.verses + S.freePerSlice + sync to audio).
- المصدر يُحفَظ في `verses[i].source`: "حصن المسلم · {الفئة} · رقم {n} (×{count})".
- خاصيّة جديدة في `S.verses[i]`: `azkar: true` لتمييز شرائح الأذكار.
- Service Worker يُخزِّن `./azkar-data.js` ضمن الأصول الاختياريّة.

#### التوثيق
- ذُكر المصدر في:
  - `README.md` — وصف وحدة الأذكار + رابط GT-HISNMUSLIM.
  - `ROADMAP.md` — تأشير v0.9.0 منجَزة (نُقلت من v0.8.0 الأصليّة في الخارطة).
  - `index.html` — بطاقة جديدة في صفحة الموقع: "🤝 برامجنا في خدمة بعضها".
  - `CHANGELOG.md` — هذا الإصدار.

📦 PWA cache → v38.

---

## [0.8.16] — 2026-06-09

### إصلاح: قسم "✍️ النصّ الحرّ" أصبح مرئيّاً دائماً

**العطل**: بعد المنع المتبادل في v0.8.14، أصبحت القاعدة "وحدة واحدة فقط مفعّلة". مع وضع الافتراضيّ على القرآن، اختفى قسم النصّ الحرّ لأنّه كان يحمل `data-module="free"`.

**الإصلاح**:
- حُذف `data-module="free"` من قسم النصّ الحرّ — أصبح مرئيّاً دائماً كأداة عامّة.
- حُذف مدخل `free` من `MODULES` (لم يعد وحدة محتوى).
- المنع المتبادل يبقى ساري المفعول على الوحدات الفعليّة (القرآن، الحديث، الأذكار، أسماء الله الحسنى، الأدعية، الحِكَم).
- المنطق الجديد: النصّ الحرّ ليس "وحدة محتوى" بل "أداة تحرير" — يستخدمها المستخدم لكتابة أيّ نصّ يدوياً.

📦 PWA cache → v37.

---

## [0.8.15] — 2026-06-09 — إصلاح طارئ

### إصلاح بنية HTML المعطوبة في v0.8.14

**العطل**: في v0.8.14 استخدم سكربت Python للنقل regex غير دقيق فاستخرج جزءاً فقط من قسم "🎤 صوت تلاوة مخصّص" وترك بقايا داخل قسم النصّ الحرّ. النتيجة: الأقسام التالية تتداخل بنيوياً ولا تظهر بشكل صحيح في الواجهة.

**الإصلاح**:
- أُعيدت الملفّات إلى حالة v0.8.13 ثمّ نُفّذ النقل عبر Edit مع تحديد دقيق للحدود (لا regex).
- حُذفت كتلة Custom Audio كاملةً من قسم النصّ الحرّ (السطور 593-654 في النسخة القديمة).
- أُدرج القسم الجديد المستقلّ بعد قسم الحديث مباشرةً (مع كلّ مكوّناته: التوگل + الرفع + تنزيل yt-dlp + trim + 📏).
- التوازن النهائيّ: 640/640 (سطح المكتب) و 555/555 (الويب).

### تذكير: التغييرات المنقولة من v0.8.14
- 🎤 صوت تلاوة مخصّص في قسم مستقلّ بعد الحديث.
- المنع المتبادل بين الوحدات في الإعدادات (وحدة واحدة فقط مفعّلة).
- الافتراضيّ الجديد: القرآن وحده مفعّل.
- `enforceSingleModuleActive()` يهاجِر الحالات السابقة.

📦 PWA cache → v36.

---

## [0.8.14] — 2026-06-09

### 🎤 صوت تلاوة مخصّص في قسم مستقلّ + منع متبادل بين الوحدات

#### 1) فصل "🎤 صوت تلاوة مخصّص" عن قسم النصّ الحرّ
- كان مدمجاً مع النصّ الحرّ في `<div class="sec" data-module="free">`.
- نُقل إلى **قسم مستقلّ** يأتي **مباشرة بعد الحديث الشريف**.
- الفصل يعكس فلسفة جديدة: الصوت المخصّص خدمة عامّة لكلّ الوحدات (قرآن، حديث، نصّ حرّ، وحدات مستقبليّة)، ليس جزءاً من وحدة النصّ.
- الترتيب الجديد في tab-rec:
  1. ✍️ النصّ الحرّ (محرّر فقط، بلا صوت)
  2. 📖 السورة والآيات
  3. 🎤 القارئ
  4. 📜 الحديث الشريف
  5. **🎤 صوت تلاوة مخصّص** ← هنا
  6. ⏱️ توقيت تفصيليّ لكلّ شريحة
  7. 🎥 فيديو تلاوة جاهز

#### 2) المنع المتبادل في إعدادات الوحدات (Mutex)
- في تبويب الإعدادات، كان يمكن تفعيل كلّ الوحدات معاً.
- الآن: تفعيل أيّ وحدة يُلغي تلقائياً جميع الباقي (radio-like behavior على toggles).
- `enforceSingleModuleActive(state)` يهاجِر الحالات السابقة: لو محفوظ أكثر من واحدة مفعّلة، تبقى الأولى فقط.
- الافتراضيات الجديدة: **القرآن وحده مفعّل**، البقيّة معطّلة.
- حُذف `alwaysOn: true` من الـfree.
- toast يُعلِم المستخدم بالتفعيل/الإلغاء.

📦 PWA cache bump → v35.

---

## [0.8.13] — 2026-06-09

### إصلاح: trim المعاينة يلفّ خارج النطاق + زرّ المدّة الكاملة

#### العطل في المعاينة
عند رفع صوت بمدّة كاملة (مثلاً 60s) وضبط trim من 4s إلى 60s، الصوت كان يبدأ من 4s صحيحاً، لكن بعد بلوغ النهاية يلفّ تلقائياً إلى **الجزء المُجتزَأ** (0→4s) قبل أن يلتقط معالج timeupdate حدث trim.end.

**السبب**: `S.bgAudioEl.loop = true` (من `onBgAudio`) يلفّ HTMLAudioElement أصلياً إلى `currentTime = 0`. معالج `timeupdate` يَفصل ~250ms بين الأحداث، فإن كانت `trim.end ≈ duration` يفوز الـloop الأصليّ.

**الإصلاح**:
- عند تفعيل trim: `S.bgAudioEl.loop = false` يدويّاً.
- معالج `timeupdate` يَلفّ يدويّاً إلى `trim.start` (بدلاً من إيقاف).
- معالج `ended` احتياطيّ: يقفز إلى `trim.start` ويُعيد التشغيل.
- عند `clearFreeAudioTrim`: يُستعاد `loop = ge("bg-loop")` الأصليّ.

#### الإصلاح في التصدير
التصدير يستخدم `getBgAudioTrim()` ويمرّر `bgAudioTrim` لمحرّك V2 الذي يستدعي `sliceAudioBuffer(bgBuffer, start, end)` قبل الخلط. الكود كان صحيحاً بالفعل — لا تغيير مطلوب. التصدير يحترم trim تماماً (لا تكرار، لا جزء مُجتزَأ).

#### 📏 زرّ "المدّة الكاملة" بجانب حقل النهاية
- يقرأ `S.bgAudioEl.duration` ويملأ `free-audio-trim-end` تلقائياً.
- يَطلق `input` event ليُحدِّث trim المعاينة فوراً.
- إنذار إن لم يكن صوت مرفوعاً بعد.

📦 PWA cache bump → v34.

---

## [0.8.12] — 2026-06-09

### زرّ لصق + زرّ مسح في حقلَيْ رابط التنزيل

- 📋 **لصق**: يقرأ من `navigator.clipboard.readText()` ويملأ الحقل تلقائياً (مع `trim()`).
- ✕ **مسح**: يفرغ الحقل و يضع تركيز عليه.
- مضاف في:
  - `free-audio-dl-url` (تنزيل صوت في النصّ الحرّ).
  - `recvid-dl-url` (تنزيل فيديو التلاوة).
- الدالّتان `pasteToInput(id)` و `clearInput(id)` مرشَّحتان لأيّ حقل آخر في المستقبل.
- في حال رفض المتصفّح الحافظة (سياق غير آمن مثلاً)، يُعرض toast: "تعذّر الوصول للحافظة — الصق يدويّاً (Ctrl+V)".

📦 PWA cache bump → v33.

---

## [0.8.11] — 2026-06-09 — HOTFIX

### إصلاح: yt-dlp لا يعرف "ogg" كاسم صيغة

**العطب**: عند تنزيل صوت من SoundCloud (وغيرها) كان البرنامج يمرّر `--audio-format ogg` لـ yt-dlp فيُجيب `invalid audio format "ogg" given`.

**السبب**: yt-dlp يتعامل مع **الكوديك**، لا اسم الحاوية. صيغ `--audio-format` المسموحة:
- `best, aac, alac, flac, m4a, mp3, opus, vorbis, wav`

الكوديك المناسب لحاوية `.ogg` هو **`vorbis`** (وملفّ الإخراج يكون `.ogg` تلقائياً).

**الإصلاح** في `main.js`:
- ترجمة `"ogg"` → `"vorbis"` قبل تمريرها لـ yt-dlp.
- التحقّق ضدّ القائمة المسموحة؛ أيّ صيغة غير معروفة تسقط لـ mp3.

النتيجة: التنزيل من SoundCloud يعمل ويُنتج `.ogg`.

📦 PWA cache bump → v32.

---

## [0.8.10] — 2026-06-09

### حقل تنزيل yt-dlp داخل قسم "🎥 فيديو تلاوة جاهز" (سطح المكتب فقط)

نفس آليّة v0.8.9 لكن للفيديو بدل الصوت:
- `<details>` جديد داخل `recvid-ctrl` بعنوان "⬇️ تنزيل فيديو تلاوة من رابط (يوتيوب/مباشر → MP4)".
- نفس واجهة الاختيار: URL + مؤقت/دائم + مسار + تصفّح + زرّ تنزيل + سجلّ.
- `runRecvidYtdlpDownload` يستدعي `ytdlp-download` بـ `type: "video"` (لا تحويل للصوت) + جودة `bestvideo[height<=1080]+bestaudio/best[height<=1080]`.
- بعد التنزيل:
  1. `read-downloaded-file` → بايتات.
  2. كشف امتداد الملفّ (mp4/webm/mkv/mov) → MIME المناسب.
  3. `new File([bytes], name, {type: mime})`.
  4. `onRecVidFile({files: [file], value: ""})` — نفس مسار الرفع اليدويّ.

النتيجة: تظهر معلومات الفيديو في `recvid-info` وتعمل كلّ مزايا recvid (إزالة الخلفيّة، scaling، التصدير).

📦 PWA cache bump → v31 (سطح المكتب فقط).

---

## [0.8.9] — 2026-06-09

### حقل تنزيل yt-dlp داخل قسم "🎤 صوت تلاوة مخصّص" (سطح المكتب فقط)

**الفكرة**: بدلاً من فتح تبويب المشهد ثم العودة لقسم الصوت، أصبح بإمكان المستخدم تنزيل الصوت من رابط (يوتيوب/فيديو) **مباشرة من قسم الصوت المخصّص** ويُعتمد تلقائياً.

#### التفاصيل
- **`<details>` جديد** داخل `free-audio-ctrl` بعنوان "⬇️ تنزيل صوت من رابط (يوتيوب/فيديو → OGG)":
  - حقل URL.
  - 📁 مؤقت (/tmp) أو 💾 دائم + حقل مسار + زرّ تصفّح.
  - ⬇️ زرّ تنزيل + ✕ إلغاء.
  - سجلّ نصّيّ مباشر للتنزيل (max 90px قابل للتمرير).
- **IPC ytdlp-download** قبل الآن mp3 فقط؛ الآن يدعم `audioFormat` (افتراضي mp3، نمرّر `"ogg"` من هذا القسم).
- **آليّة الاعتماد التلقائيّ**:
  1. yt-dlp → ملفّ OGG على القرص (مؤقت أو في المسار المختار).
  2. `read-downloaded-file` → بايتات الملفّ.
  3. `new File([bytes], name, {type: "audio/ogg"})`.
  4. `handleFreeAudioFile(file)` — نفس مسار الرفع اليدويّ → يتولّى connecting audio context + بطاقة المعلومات + `syncVersesToActiveAudio`.

النتيجة: لا يحتاج المستخدم رفع الملفّ يدويّاً بعد التنزيل. إن كان الرابط فيديو، yt-dlp يستخرج الصوت تلقائياً ويحوّل إلى OGG.

📦 PWA cache bump → v30 (الإصلاح سطح-مكتب فقط).

---

## [0.8.8] — 2026-06-09

### إصلاح: الفيديو المُنزَّل عبر yt-dlp يظهر الآن في بطاقة التحكّم

**المشكلة**: عند تنزيل فيديو خلفيّة عبر yt-dlp، كان يضبط `S.bgVid` فقط ويعمل كخلفية، لكن لا تظهر بطاقة التحكّم (الصوت، الموضع، الحذف) لأنّه لا يُضاف إلى `S.bgVidItems` التي ترسم البطاقات. اضطرّ المستخدم لإعادة البحث عن الملفّ في القرص ورفعه يدويّاً.

**الإصلاح** (سطح المكتب فقط):
- IPC جديد `read-downloaded-file` في `main.js` — يقرأ أيّ ملفّ من القرص (لا قيد على /tmp).
- exposed كـ `window.SIRM.readDownloadedFile` في `preload.js`.
- `applyDownloadedMedia` للفيديو: يقرأ البايتات → يبني `new File(...)` → يستدعي `addBgVidItem(file)` كما لو رفعه المستخدم من زرّ الاستيراد. النتيجة: تظهر بطاقة التحكّم في القائمة فوراً.
- fallback للسلوك القديم إن فشل قراءة الملفّ (إنذار للمستخدم).

📦 PWA cache bump → v29 (الإصلاح سطح-مكتب فقط؛ لا أثر للويب).

---

## [0.8.7] — 2026-06-08 — HOTFIX

### إصلاح حرج: عَطَب بنية HTML من v0.8.5/0.8.6

**العطب**: في v0.8.5 ترك سكربت النقل أحرفاً يتيمة (`<` بدلاً من `</div>` في L555/454) + `</div>` ناقصة لإغلاق tab-rec. النتيجة: المعاينة (`#preview` + `#cv`) أصبحت **داخل أحد الأقسام** بدل أن تكون في عمودها الجانبيّ المستقلّ → الواجهة مشوَّهة كلّياً.

**الإصلاح**:
- استُبدلت `          <` بـ `          </div>` لإغلاق توگل النصّ الحرّ.
- أُضيفت `</div>` ناقصة لإغلاق `tab-rec` قبل افتتاح `tab-scene`.
- الآن المحصِّلة: 624 `<div>` و 624 `</div>` في سطح المكتب (551/551 في الويب).

📦 PWA cache bump → v28.

---

## [0.8.6] — 2026-06-08

### إصلاح حرج: قسم النصّ الحرّ + زرّ توقيت ذكيّ

#### 1) إعادة بناء قسم "✍️ النصّ الحرّ" بأكمله في الأعلى
**المشكلة**: في v0.8.5 نُقل فقط رأس القسم + توگل التفعيل إلى الأعلى، أمّا المحرّر + textarea + زرّ التطبيق + قسم الصوت المخصّص + trim فبقيت في الوسط (سكربت Python كان يقطع عند أوّل `</div>`).

**الإصلاح**: نُقل القسم **كاملاً** إلى رأس tab-rec:
- 🔗 تفعيل المحرّر + textarea + 🔄 المزامنة + 🎤 صوت مخصّص + ✂️ trim — كلّها في الأعلى.
- حُذفت الـ`/div>` اليتيمة التي تركها سكربت v0.8.5.

#### 2) زرّ "🎚️ ضبط توقيت كلّ شريحة ↓" أصبح ذكيّاً
**المشكلة**: عند تطبيق حديث ثم تطبيق نصّ حرّ ثم النقر على الزرّ، كانت قائمة الشرائح تعرض **شرائح الحديث القديمة**.

**الإصلاح**: دالّة موحَّدة `openPerSliceSmart()` تُنفِّذ في كلّ نقرة:
1. تُفعِّل التوقيت التفصيلي.
2. **تمسح `S.freePerSlice` السابقة** لإجبار إعادة البناء.
3. تُعيد البناء من `S.verses` الحاليّة (تلقائياً تكتشف free/hadith).
4. تُزامن مع الصوت النشط (recvid > trim > bgAudio).
5. ترسم القائمة + تنتقل سلِساً.

نفس الزرّ يُستعمل من النصّ الحرّ + الحديث (+ مرشَّح للوحدات المستقبليّة).

#### 3) إعادة المزامنة عند تغيير trim
- `applyFreeAudioTrim` يستدعي `syncVersesToActiveAudio` الآن.
- نتيجة: تغيير "من/إلى" الصوت → الشرائح تُعاد توزيعها فوراً.

📦 PWA cache bump → v27.

---

## [0.8.5] — 2026-06-08

### إعادة بناء تدفّق المصادر + إصلاح مزامنة الصوت

#### 1) محرّر النصّ الحرّ في الأعلى دائماً + غير مفعّل افتراضياً
- نُقل قسم "✍️ النصّ الحرّ & 🎤 صوت مخصّص" إلى رأس تبويب التلاوة.
- التوگل `free-text-on` لا يُستعاد من `localStorage` بعد الآن — يبدأ دائماً غير مفعّل.

#### 2) زرّ "🎚️ ضبط توقيت كلّ شريحة ↓" داخل النصّ الحرّ
- يظهر بعد النقر على "✅ تطبيق النصّ".
- النقر عليه: يُفعِّل التوقيت التفصيلي + ينتقل تلقائياً إلى القسم (smooth scroll).
- نفس النمط في الحديث (`open-per-slice-from-hadith`).
- مرشَّح للوحدات المستقبليّة (الأذكار/الأدعية/الحِكَم).

#### 3) إصلاح "احترام مدّة الصوت" في المعاينة والتصدير
**المشكلة**: عند رفع صوت تلاوة/حديث/دعاء مخصّص، أحياناً المقطع المُصدَّر يطول/يقصُر عن الصوت → الصوت يتكرّر أو يُجتزَأ.

**الحلّ**:
- `getActiveAudioDuration()` — دالّة مُوحَّدة تكتشف المصدر الصوتيّ النشط (recvid > trim > bgAudio).
- `calcEffectiveSliceDuration` يستخدمها — تُطبَّق على النصّ الحرّ **والحديث**.
- `applyHadith` يستخدم `calcEffectiveSliceDuration` الآن (كان baseDur ثابتاً).
- `syncVersesToActiveAudio()` — تُستدعى بعد رفع صوت/فيديو جديد → تُعيد توزيع المدد لتُساوي مجموعها مدّة الصوت.
- النتيجة: مجموع مدد الشرائح = مدّة الصوت بالضبط، لا تكرار ولا اقتطاع.

#### 4) recvid + bgVideo: تطابق مدّة المقطع
- بفضل (3): عند تفعيل recvid + تطبيق حديث → الشرائح تُوزَّع تلقائياً على مدّة recvid.
- التصدير يستخدم مدّة recvid كأصل، وفيديو الخلفية يُلَفّ/يُقَصّ لمطابقتها.

📦 PWA cache bump → v26.

---

## [0.8.4] — 2026-06-08

### تركيب الحديث + إصلاحات الواجهة

#### 1) الحديث = راوي + قال رسول الله ﷺ + متن (3+ شرائح)
- `parseHadithStructure(text)` يكتشف صيغة "قَالَ رَسُولُ اللهِ صَلَّى اللَّهُ عَلَيْهِ وَسَلَّمَ" ويحلِّل النصّ إلى 3 أجزاء:
  - **الراوي**: "عَنْ X رَضِيَ اللَّهُ عَنْهُ" (شريحة مستقلّة)
  - **مقولة النبيّ**: "قَالَ رَسُولُ اللهِ صَلَّى اللَّهُ عَلَيْهِ وَسَلَّمَ" (شريحة ثابتة)
  - **المتن**: مقسَّم على نقاط الترقيم (شرائح متعدّدة)
- 6 أنماط regex لاكتشاف صيغ مختلفة (بالتشكيل أو بدون).

#### 2) "🧹 تنظيف مقدّمة الإسناد" يحذف الراوي فقط
- مع التفعيل: تختفي شريحة الراوي، **تبقى** شريحة "قَالَ رَسُولُ اللهِ ﷺ" + المتن.
- مع الإلغاء: تظهر الشرائح الثلاثة (راوي + مقولة + متن).
- كلّ شريحة قابلة للتعطيل يدوياً من قائمة التوقيت التفصيلي.

#### 3) زرّ "🎚️ ضبط توقيت كلّ شريحة" لا يُفعِّل النصّ الحرّ
- كان يُفعِّل `free-text-on` عن طريق الخطأ → حُذف.
- الآن: يُفعِّل فقط `free-per-slice` ثم scrollIntoView إلى القسم.

#### 4) قسم "⏱️ توقيت تفصيليّ لكلّ شريحة" نُقل لأعلى
- كان بعد "✍️ النصّ الحرّ & 🎤 صوت مخصّص" → نُقل **قبله**.
- الترتيب الجديد:
  1. 🎥 فيديو تلاوة جاهز
  2. 📜 الحديث الشريف
  3. **⏱️ توقيت تفصيليّ لكلّ شريحة** ← هنا
  4. ✍️ النصّ الحرّ & 🎤 صوت مخصّص
  5. 🎥 فيديو تلاوة جاهز (الثاني)

📦 PWA cache bump → v25.

---

## [0.8.3] — 2026-06-08

### إعادة هيكلة كبرى للتوقيت + بيانات الأحاديث

#### 1) قسم "⏱️ توقيت تفصيليّ لكلّ شريحة" مستقلّ
- نُقل من داخل قسم النصّ الحرّ إلى **قسم خاصّ به** بعد قسم النصّ الحرّ.
- يبقى ظاهراً دائماً (لا يختفي مع إخفاء النصّ الحرّ).
- `buildPerSliceList` يُحدَّث: يبني من `S.verses` إن كانت لمصدر نصّيّ (free/hadith)، وإلّا من textarea النصّ الحرّ.
- يعمل تلقائياً مع: النصّ الحرّ، الحديث الشريف، (لاحقاً: الأذكار، الأدعية، الحِكَم).

#### 2) منع التداخل بين المصادر
- `applyHadith` يُلغي `free-text-on` تلقائياً + يبدّل المصدر.
- `applyFreeText` يُخفي معاينة الحديث وزرّ تطبيقه + زرّ ضبط الشرائح.
- ضمانة: لا يمكن أن يكون مصدران مفعَّلَين في وقت واحد.

#### 3) رمز "ﷺ" استُبدِل بـ "صَلَّى اللَّهُ عَلَيْهِ وَسَلَّمَ"
- 63 موقعاً في النووية + رياض الصالحين.
- "النّبيّ" → "النَّبِيِّ"، "رسول الله" → "رَسُولِ اللهِ" في السياقات الإسناديّة.

#### 4) جميع الأحاديث لها مطلع إسناد كامل
- الأربعون النووية: كانت تبدأ بالمتن مباشرةً → الآن تبدأ بـ "عَنْ [الراوي] رَضِيَ اللَّهُ عَنْهُ قَالَ قَالَ رَسُولُ اللهِ صَلَّى اللَّهُ عَلَيْهِ وَسَلَّمَ: [المتن]".
- النصوص التي كانت تبدأ بحوار (مثل #2 حديث جبريل، #16 أوصني) تبقى كما هي.
- تنظيف المقدّمة (`hadith-clean-isnad`) الآن **يعمل على جميع الأحاديث**.

#### 5) تشكيل جزئيّ
- "رَضِيَ اللَّهُ عَنْهُ/عَنْهَا/عَنْهُمَا" مُشكَّلة كاملاً.
- "قَالَ"، "عَنْ"، "النَّبِيِّ"، "رَسُولِ اللهِ"، "سَمِعْتُ" مُشكَّلة.
- بقيّة النصّ بتشكيل جزئيّ على الكلمات الحاسمة (مكتوب بأيدي البشر — التشكيل الكامل لجميع الكلمات يتطلّب تحرير يدوي شامل في إصدار لاحق).

📦 PWA cache bump → v24.

---

## [0.8.2] — 2026-06-08

### إصلاحات وحدة الحديث

#### 1) زرّ "🎚️ ضبط توقيت كلّ شريحة" داخل قسم الحديث
- يظهر بعد تطبيق حديث.
- بالنقر: يُفعِّل توگل `free-per-slice` + `free-text-on` تلقائياً، ويسحب الـ viewport إلى قائمة الشرائح.
- المستخدم يصل مباشرةً للتحكّم بمدّة وتفعيل كلّ شريحة.

#### 2) تنظيف الإسناد يعمل فعلاً الآن
- أنماط `cleanHadithIsnad` أُعيد كتابتها لتستهدف رمز "ﷺ" أو "صلّى الله عليه وسلّم" + ":" + الفعل الاختياريّ.
- 4 أنماط تغطّي: `ﷺ:`، `ﷺ يقول:`، `قال رسول الله ﷺ:`، `قال النّبيّ ﷺ:`.
- **بيانات رياض الصالحين أُعيد بناؤها** بإسناد كامل داخل `text` ليكون للزرّ فعلٌ ملموس.

#### 3) رياض الصالحين: 50 حديثاً غير مكرَّر مع النووية
- أبواب جديدة منتقاة: الإخلاص، التوبة، الصبر، الصدق، اغتنام الصحّة، الذكر، الصدقة، العلم، برّ الوالدين، صلة الرحم، التواضع، الدعاء، الاستغفار، قيام الليل، الصيام، البكاء من خشية الله، الزهد، العفو، التعاون على البرّ، الرحمة، رحمة الصبيان، حفظ اللسان، النهي عن الغيبة، الستر، السلام، عيادة المريض، اتباع الجنائز، الوضوء، الأذان، الصفّ الأول، الجمعة، الجهاد، الإنفاق، قراءة القرآن، سورة الإخلاص، سورة الكهف، الصلاة على النبيّ، صلاة الفجر والعصر، الحياء، الأمانة، القناعة، الرفق، حسن الخلق، الجار، عمل الصالح في رمضان، الداعي إلى الهدى، العمل الدائم، الأخوّة في الله.
- لا تكرار مع الأربعون النووية (تمّ التحقّق).

#### 4) البحث الموحَّد عبر جميع المصادر
- الـ dropdown الأوّل: "🔍 جميع المصادر (للبحث الموحَّد)" كخيار افتراضيّ.
- البحث يُعرَض لأحاديث **جميع المجموعات** مع وسم بداية يُبيّن المصدر مثل: `[الأربعون النووية] 12. ...`.
- اختيار مجموعة محدّدة يُقيِّد البحث بها فقط.

📦 PWA cache bump → v23.

---

## [0.8.1] — 2026-06-08

### تحسينات شاملة (نصّ + شرائح + حديث)

#### 📐 منزلق إزاحة عموديّة للنصّ (Y offset)
- في قسم "🎨 تنسيق النص" بجانب موضع النصّ.
- نطاق: −50% → +50% من ارتفاع الشاشة.
- يُطبَّق على `startY` في `drawVerse` بعد حساب `tpos`.

#### ✅ تفعيل/إلغاء كلّ شريحة على حدة
- checkbox لكلّ شريحة في قائمة "⏱️ توقيت تفصيليّ".
- الشريحة المعطّلة: `aya.enabled = false`.
- في `drawVerse`: `if (aya.enabled === false) return;` — تبقى في الزمن لكن النصّ لا يُرسم (خلفيّة + موجات صوتيّة فقط).

#### 📜 تحسينات وحدة الحديث
- **توقيت تفصيليّ للحديث**: `applyHadith` يملأ الآن `S.freePerSlice` تلقائياً مع `renderPerSliceList`.
- **تنظيف مقدّمة الإسناد** (`hadith-clean-isnad` toggle، افتراضي ON):
  - `cleanHadithIsnad(text)` يحذف "عن X قال سمعت رسول الله ﷺ يقول".
  - 3 أنماط regex لتغطية الصياغات الشائعة.
  - الحدّ الأقصى للحذف: 70% من النصّ (حماية).
- **مجموعة جديدة: رياض الصالحين** (20 حديثاً منتقاة):
  - أبواب: الإخلاص، التّوبة، الصّبر، الصّدق، المراقبة، التّقوى، الذّكر، الصّدقة، العلم، برّ الوالدين، صلة الرّحم، الجار، التّواضع، الدّعاء، الاستغفار، الجماعة، قيام اللّيل، الصّيام، الصّبر على البلاء.
  - بدايات مع الإسناد لتتوافق مع `cleanHadithIsnad`.

#### 🔛 توضيح قسم التوقيت العامّ
- ترويسة جديدة: "⏱️ التوقيت (لوحدة القرآن فقط)".
- ملاحظة تشرح: عند تفعيل النصّ الحرّ/الحديث/recvid يُتجاهَل تماماً ويُستخدم التوقيت التفصيلي.
- لا تغيير في المنطق — كان فعلياً يخصّ القرآن لكنّ التسمية كانت مُبهمة.

📦 PWA cache bump → v22.

---

## [0.8.0] — 2026-06-07

### 📜 وحدة الحديث الشريف

#### المحتوى الأوّليّ
- **الأربعون النووية** كاملة (40 حديثاً) — تأليف الإمام النووي رحمه الله، انتُقيت من الصحيحين وغيرهما.
- كلّ حديث يحتوي: رقمه، باب/موضوع، الراوي، النصّ الكامل، المصدر، الدرجة (صحيح/حسن/قدسيّ).

#### الواجهة
- قسم جديد في تبويب التلاوة بعد قسم القارئ: **📜 الحديث الشريف** (`data-module="hadith"`).
- 4 عناصر:
  - **مُنتقي المجموعة** (dropdown — قابل للتوسّع لاحقاً)
  - **بحث في النصّ** (مع تطبيع التشكيل العربيّ)
  - **قائمة الأحاديث** (size=6 يعرض ~60 حرفاً من بداية كلّ حديث)
  - **معاينة الحديث** الكاملة + الراوي + المصدر + شارة الدرجة
- زرّ **📥 تطبيق الحديث كنصّ المقطع** يفعّل النصّ كشرائح.

#### المعمار
- `hadith-data.js` ملفّ classic script (يعمل تحت `file://`).
- `window.HADITH_DATA = { version, collections: [...] }`.
- `initHadithModule()`: يربط dropdowns/search/preview/apply.
- `applyHadith(h, coll)`:
  - يقسم النصّ بـ `[.،؛!؟]+` إلى شرائح.
  - يضع `S.verses` بـ `{free: true, hadith: true, source: "النووية · حديث 12 (حسن)"}`.
  - مدّة كلّ شريحة من `free-slice-dur` (افتراضي 4s).

#### Module Manager
- `MODULES.hadith.impl = true` (كان false في v0.3.0).
- توگل `mod-hadith` في تبويب الإعدادات مُفعَّل بدل disabled.
- عند تعطيله: قسم الحديث يختفي تلقائياً (CSS `data-module:not(.module-active)`).

#### Service Worker (الويب)
- `hadith-data.js` مُضاف إلى قائمة الـcache (OPTIONAL).

📦 PWA cache bump → v21.

---

## [0.7.5] — 2026-06-07

### إصلاح تداخل الصوت في وضع recvid

#### المشكلة
- المستخدم: فتح مشروع محفوظ ثم رفع فيديو تلاوة جديد.
- في المعاينة: صوت الفيديو الجديد + صوت المشروع القديم (خافت) يتداخلان.
- في التصدير: النصّ الجديد لكن الصوت القديم!

#### السبب
- المشروع المحفوظ يحتوي bgAudioFile سابق.
- عند فتح المشروع، bgAudioEl يُحمَّل ويُوصَّل بـAudioContext.
- المستخدم يرفع recvid جديد → recVidEl يُوصَّل أيضاً.
- المعاينة: كلا المصدرَين يصلان `ctx.destination` → تداخل.
- التصدير V2: `mixAudioToBuffer` يستخدم `bgBuffer` (من bgAudio القديم)، فيديو التلاوة الجديد لا يُضاف للخلط offline.

#### الحلّ (v0.7.5)
1. **startPlayer**: إذا `recvid-on` مُفعَّل → لا تُشغّل bgAudioEl، بل pause.
2. **V2 export (mixAudioToBuffer setup)**:
   - إذا recvid مُفعَّل: استخدم `S.recVidFile.arrayBuffer()` و decode كـ AudioBuffer ثمّ مرّره كـ `bgBuffer`.
   - bgAudio القديم يُتجاهَل في الخلط.
- في الديسكتوب: `decodeAudioData(await S.recVidFile.arrayBuffer())`.
- في الويب: نفس النمط في `startWebExportV2`.

#### النتيجة
- recvid = مصدر الصوت الوحيد عند تفعيله.
- لا تداخل في المعاينة، الصوت الصحيح في التصدير.

📦 PWA cache bump → v20.

---

## [0.7.4] — 2026-06-07

### إصلاح: استعادة سلوك أبعاد الكانفاس الافتراضيّ

تمّ التراجع عن `autoFitCanvasToVideo` لأنّه يكسر التزامن مع FMT preset
ويتسبّب في تشوّه المعاينة والتصدير. الكانفاس يبقى عند الـ FMT المختار
وفيديو التلاوة يُرسم بداخله مع نمط الملاءمة المُختار (contain افتراضياً).

السبب: تغيير cv.width/height ديناميكياً يربك FMT_SIZES و export resolution.

### 📐 ضبط أبعاد الكانفاس (محذوف)

#### المشكلة
- المعاينة كانت تحافظ على أبعاد FMT الافتراضيّة (9:16 مثلاً).
- إذا فيديو التلاوة 16:9، يظهر مع letterbox أو cover crop.
- المستخدم يتوقّع: الكانفاس يتوافق مع أبعاد الفيديو المرفوع.

#### الحلّ — `autoFitCanvasToVideo(vw, vh)`
- يُستدعى في `onRecVidFile.onloadedmetadata`.
- إذا نسبة الفيديو ضمن 5% من أحد presets (9:16, 16:9, 1:1, 4:5):
  - يُفعِّل الـ radio الموافق → الكانفاس يأخذ الـ preset.
  - Toast: "📐 ضُبط الكانفاس على {fmt} ({W}×{H})".
- وإلّا (نسبة غير قياسيّة):
  - يضبط `cv.width = videoWidth`, `cv.height = videoHeight` مباشرةً.
  - يستدعي `fitCanvas()` لضبط حجم العرض في الواجهة.
  - Toast: "📐 ضُبط الكانفاس على أبعاد الفيديو {W}×{H}".

📦 PWA cache bump → v19.

---

## [0.7.3] — 2026-06-07

### 🐛 إصلاحات: فيديو التلاوة في التصدير + Refresh الصفحة على الويب

#### 1) فيديو التلاوة كان يبقى ثابتاً في التصدير
- **V2 الحتميّ** (Desktop ffmpeg / Web WebCodecs): الفيديو لم يكن يُسحَب لزمن الإطار قبل drawFrame.
- الحلّ: قبل كلّ `drawFrame(t)`، نُجري `await seekVideoToTime(S.recVidEl, t)` ينتظر `seeked` event.
- timeout أمان 800ms لتجنّب التعليق إذا فشل الـ seek.

#### 2) V1 الحيّ (MediaRecorder): الفيديو لم يكن يُشغَّل
- في بداية التصدير الحيّ: `S.recVidEl.currentTime = 0; play()`.
- في نهاية `stopExportSources()`: إيقافه وإعادته إلى 0.

#### 3) Refresh الصفحة على الويب لا يُحذِّر
- السبب: `beforeunload` يعتمد على `S.projectDirty` لكن رفع الملفّات لم يكن يُحدِّث الحالة.
- الحلّ: استدعاء `markProjectDirty()` في:
  - `onBgMedia` (صورة + فيديو خلفية)
  - `onBgAudio` (صوت خلفية)
  - `addBgVidItem` (كلّ مقطع playlist)
  - `onRecVidFile` (فيديو التلاوة)
- الآن أيّ رفع ملفّ → `S.projectDirty = true` → refresh يعرض تنبيه المتصفّح.

📦 PWA cache bump → v18.

---

## [0.7.2] — 2026-06-07

### 🐛 إصلاح: فيديو التلاوة لا يُستعاد عند فتح المشروع

#### المشكلة
- المستخدم أبلغ: حفظ المشروع → إعادة فتحه → يستعيد الإعدادات وفيديو الخلفيّة، **لكن فيديو التلاوة الجاهز (recVideo) مفقود**.

#### السبب
- `serializeProject()` لم تكن تُضمّن `S.recVidFile` في قائمة الأصول.
- `restoreAssetFromDataURL()` لم يكن لديها فرع `recVideo`.
- النتيجة: التوگل يعود إلى `on` (من DOM) لكن الفيديو نفسه ليس في الملفّ.

#### الحلّ
- في `serializeProject()`: إضافة مصدر جديد `{ key: "recVideo", ... }` يُضمَّن إذا ≤50MB.
- في `restoreAssetFromDataURL()`: فرع `asset.key === "recVideo"` يستدعي `onRecVidFile(fakeInput)`.
- النتيجة: الفيديو يُستعاد كما الباقي + يتمّ إعادة ربط Audio routing + تحديث verses تلقائياً.

📦 PWA cache bump → v17.

---

## [0.7.1] — 2026-06-07

### 🎨 لون قابل للاختيار لإزالة الخلفيّة + Chromakey للشعار

#### 1) فيديو التلاوة — لون خلفيّة قابل للتغيير
- color picker جديد `recvid-bgcolor` (افتراضي `#000000`).
- 4 presets: ⚫ أسود · ⚪ أبيض · 🟢 أخضر · 🔵 أزرق.
- الخوارزميّة الجديدة `removeBgColorFromRegion` تتكيّف تلقائياً:
  - **أسود** (luminance < 60) → `Math.max(r,g,b)` threshold.
  - **أبيض** (luminance > 195) → `Math.min(r,g,b)` threshold.
  - **ألوان** → مسافة YCbCr (Cb, Cr distance) مثل chromakey.

#### 2) Chromakey للشعار (قسم 🖼️ شعار مخصص)
- توگل جديد `logo-chroma-on` (افتراضي OFF — لا يأخذ مساحة).
- color picker `logo-chroma-color` (افتراضي `#ffffff` — للشعارات بخلفيّة بيضاء).
- 3 presets: ⚪ أبيض · ⚫ أسود · 🟢 أخضر.
- المنزلقان: العتبة + النعومة.
- يطبَّق على canvas off-screen قبل composite الشعار → جودة عالية بلا تشويه.

#### المعمار التقنيّ
- `removeBgColorFromRegion` دالّة موحّدة تخدم recvid والشعار.
- `removeBlackBackground` تبقى كـalias للتوافق العكسيّ.
- canvas off-screen قابل لإعادة الاستخدام لكلّ من recvid والشعار.

📦 PWA cache bump → v16.

---

## [0.7.0] — 2026-06-07

### 🎥 فيديو تلاوة جاهز

#### الميزة الجديدة
- قسم جديد في تبويب "📖 التلاوة" بعد قسم النصّ الحرّ.
- **توگل** `recvid-on` (افتراضي OFF) — لا يأخذ مساحة عند الإلغاء.
- عند التفعيل: ارفع فيديو مُعدّ مسبقاً (صوت + نصّ على خلفيّة سوداء) → يحلّ محلّ القرآن/النصّ الحرّ.
- صوت الفيديو = صوت التلاوة (متّصل بـ analyser و exportDest).

#### التحكّم في المقاس والموضع
- 4 أنماط ملاءمة:
  - **احتواء** (افتراضي، يحافظ على النسبة)
  - **تغطية كاملة**
  - **تمديد** (يملأ كاملاً، قد يشوّه)
  - **الحجم الأصليّ**
- موضع X/Y: −50% إلى +50% من أبعاد الشاشة.
- حجم نسبيّ: 20% إلى 200%.

#### إزالة الخلفيّة السوداء
- **عتبة السواد** (0–100، افتراضي 25) — حدّ السطوع الذي يُعتبر دونه أسوداً.
- **النعومة** (0–50، افتراضي 10) — تدرّج الحواف بين الشفّاف والمعتم.
- المعيار: `Math.max(r, g, b)` (أكثر دقّة من luminance لاكتشاف النصّ الأبيض على أسود).
- يطبَّق على المنطقة المرسومة فقط لتوفير زمن المعالجة.

#### التكامل مع المشغّل
- play/pause يتزامن مع الفيديو تلقائياً.
- pause يُعيد الفيديو إلى 0 (متاح للتصدير الحتميّ).
- `S.verses` يصبح شريحة واحدة بمدّة = `video.duration` → التصدير يلتقط الفيديو كاملاً.

#### Audio routing
- المسار الصوتيّ للفيديو يُوصَّل بـ:
  - `ctx.destination` (للمعاينة)
  - `S.analyser` (للذبذبات)
  - `S.exportDest` (للتصدير)

#### ملاحظات
- يعمل في المعاينة + V1 الحيّ (WebCodecs/canvas stream).
- V2 الحتميّ في الديسكتوب: الفيديو يحتاج pre-extract للإطارات (مؤجّل لـ v0.7.1).

📦 PWA cache bump → v15.

---

## [0.6.0] — 2026-06-07

### 🎭 Chromakey (شاشة خضراء)

#### الميزة الجديدة
- قسم جديد في تبويب "🎬 المشهد" قبل "🎞️ حركة الخلفية".
- 4 ضوابط:
  - 🎨 **اللون** — color picker + presets (أخضر `#00b140`، أزرق `#0047bb`).
  - 🔄 **التشابه** (similarity 0-100، افتراضي 30) — حسّاسيّة المطابقة.
  - 🌫️ **النعومة** (smoothness 0-100، افتراضي 15) — تدرّج الحواف.
  - 🧹 **إزالة الانعكاس** (spill 0-100، افتراضي 20) — تقليل اللون المتسرّب على الموضوع.

#### المعمار
- خوارزميّة في فضاء **YCbCr** (دقّة لونيّة أعلى من RGB المباشر).
- مسافة لونيّة (Cb,Cr) → ألفا تدريجيّ بين `similarity` و `similarity+smoothness`.
- Spill suppression: اطرح المكوّن المفرط (أخضر/أزرق/أحمر) نحو متوسّط القناتَين الأخرتَين.

#### التكامل مع drawBg
- عند تفعيل Chromakey مع وسائط (صورة/فيديو):
  1. ارسم التدرّج على ctx الرئيسيّ.
  2. ارسم الوسائط على canvas off-screen قابل لإعادة الاستخدام.
  3. طبّق `applyChromakeyToCanvas` على الـoff-screen.
  4. composite نتيجة الـoff-screen فوق التدرّج.
- النتيجة: مساحات اللون المُختار تكشف عن التدرّج تحتها.

#### يعمل تلقائياً في التصدير
- المعاينة والتصدير يشتركان في نفس `drawFrame` → لا حاجة لمرشّحات ffmpeg/WebCodecs إضافيّة.
- نفس الجودة في الـ V2 deterministic export.

📦 PWA cache bump → v14.

---

## [0.5.8] — 2026-06-07

### 🐛 إصلاحات حرجة لحفظ المشاريع + ترتيب اسم السورة

#### 1) المصادر الخارجيّة لم تكن تُستعاد عند الاستيراد
- السبب: `restoreAssetFromDataURL` كانت تستدعي دوالّ غير موجودة (`handleBgImageFile`, `addBgVidItemFromFile`).
- الحلّ: تستخدم الآن الدوالّ الموجودة فعلاً (`onBgMedia`, `onBgAudio`, `addBgVidItem`) عبر fake input.
- أيضاً: `S.bgImgFile` و `S.bgAudioFile` لم تكن تُحفظ → أُضيفت إلى `onBgMedia` و `onBgAudio`.
- أسماء حقول الفيديو صُحِّحت: `audioEnabled`/`audioGain` بدلاً من `audioOn`/`audioVol`.

#### 2) حوار الإغلاق الثلاثيّ (إلغاء/حفظ/إنهاء دون حفظ)
- في الديسكتوب: `beforeunload` لا يدعم حوارات مخصّصة في Electron.
- الحلّ: `main.js` يعترض `close` event ويبعث IPC `request-close-confirm`.
- الـ renderer يعرض modal بثلاث خيارات. عند اختيار "إنهاء" يبعث `confirmClose` IPC.
- على الويب: `beforeunload` يعرض تنبيه المتصفّح الافتراضي (قيود الأمان).

#### 3) ترتيب قسم "اسم السورة"
- نُقل إلى **أعلى تبويب النصوص** (بدلاً من المنتصف).
- يبقى مُحمّلاً بـ `data-module="quran"` فيختفي عند إلغاء الوحدة.
- v0.5.8 إضافة: عند إلغاء وحدة القرآن → `sname-on.checked = false` تلقائياً.

📦 PWA cache bump → v13.

---

## [0.5.7] — 2026-06-07

### 💾 نظام حفظ/فتح المشاريع (.gtsirm)

#### إعادة ترتيب قسم النصوص
- نُقل قسم "🎨 تنسيق النص" ليصبح **تحت "🎬 عنوان المقطع"** و**فوق "📿 اسم السورة"** و"🖋️ الخط".

#### حفظ المشروع
- صيغة `.gtsirm` JSON (format=GT-SIRM-Project, formatVersion=1).
- زرّ 💾 **المشروع** في رأس الصفحة + زرّ 📂 **فتح**.
- يحفظ: كلّ إعدادات DOM + الوحدات + النصّ الحرّ + التوقيت التفصيلي + المصادر.
- **الوضع الهجين**: مصادر ≤50MB تُضمَّن (Base64)؛ الأكبر تُدرج كـ "missing".
- مصادر مدعومة: bgVideo (متعدّد) · bgImage · bgAudio · logo.

#### Desktop integration
- File Association في `package.json` (`electron-builder.fileAssociations`).
- النقر المزدوج على `.gtsirm` يفتحه في GT-SIRM (بعد التحزيم).
- `requestSingleInstanceLock` يمرّر الملفّ للنسخة الجارية.
- `open-file` event للـ macOS.
- IPC handlers جديدة: `project-save-dialog`, `project-open-dialog`, `project-write`, `project-read`, `project-asset-check`, `project-asset-read`.

#### الحفظ التلقائي
- قسم في تبويب الإعدادات: توگل + اختيار المدّة (1/5/10/15/30 دقيقة).
- ديسكتوب: يحفظ صامتاً إلى آخر مسار مع toast بعد كلّ حفظ.
- ويب: يحفظ في `localStorage["gt_sirm_autosave_blob"]` (حدّ 4.5MB).
- يحفظ فقط عند وجود تغييرات (`S.projectDirty`).

#### حماية الإغلاق
- `beforeunload`: تحذير عند وجود تغييرات غير محفوظة.
- علامة `●` بجانب اسم المشروع في تاب المتصفّح + subtitle.

#### المصادر المفقودة
- عند الفتح: نافذة modal تعرض كلّ مصدر مفقود مع:
  - اسم المصدر + نوعه + سبب الفقد.
  - input للاختيار اليدويّ لبديل من القرص.
- زرّان: تخطّي الكلّ / تطبيق.

📦 PWA cache bump → v12.

---

## [0.5.6] — 2026-06-07

### 🎬 عنوان مخصّص للمقطع

#### الميزة
- قسم جديد في أعلى تبويب "✍️ النصوص": **🎬 عنوان المقطع**.
- حقل نصّ حرّ (حتى 80 حرفاً) للعنوان (مثلاً: "تأمّلات في سورة البقرة").
- تحكّم كامل:
  - الموضع العمودي 0%-40% من ارتفاع الشاشة.
  - حجم الخطّ 20%-220%.
  - اللون (color picker).
  - 4 تأثيرات: ظلّ / توهّج / حدود / بدون.
- يستخدم الخطّ العامّ من قسم "🖋️ الخط".

#### توگل التفعيل
- `vtitle-on` للتحكّم في الإظهار/الإخفاء.
- مستقلّ عن وحدة القرآن — لا يختفي عند إلغائها.
- ملاحظة في الواجهة تنبّه لتجنّب التعارض مع اسم السورة.

#### المعمار
- دالّة `drawVideoTitle(ctx, W, H)` تُستدعى بعد `drawSurahName` مباشرةً.
- نفس النمط المعمول به في `drawSurahName` (Save/restore + RTL + text-align center).

📦 PWA cache bump → v11.

---

## [0.5.5] — 2026-06-07

### 🐛 إصلاح حرج: التوقيت التفصيلي لم يكن يظهر في المعاينة

#### المشكلة
- التصدير كان يحترم `verses[i].manualDuration` (صحيح).
- المعاينة عبر `getEffectiveDur(i)` تقرأ من `S.ayaDurations[i]` (لا من verses).
- في `applyFreeText`: السطر `S.ayaDurations = []` كان يفرّغها بلا إعادة ملء.
- النتيجة: المعاينة تتجاهل المدد الفرديّة، التصدير يحترمها → عدم تطابق.

#### الحلّ
- في `applyFreeText` بعد بناء `S.verses`:
  ```js
  S.ayaDurations = S.verses.map(v => v.manualDuration || dur);
  ```
- الآن المعاينة والتصدير يقرآن من نفس المصدر منطقياً.

📦 PWA cache bump → v10.

---

## [0.5.4] — 2026-06-07

### 🔛 توگل تفعيل/إلغاء قسم التوقيت العامّ

#### المشكلة
- إعدادات قسم "⏱️ التوقيت" (مدّة آية + مدّة الانتقال + فاصل الصمت) كانت تتداخل مع التوقيت التفصيلي للنصّ الحرّ.
- فاصل الصمت `aya-gap` كان يُضاف فوق المدّة الدقيقة لكلّ شريحة، يفسد المزامنة.

#### الحلّ
- توگل رئيسيّ جديد **🔛 تفعيل قسم التوقيت العامّ** (مفعَّل افتراضياً — توافق خلفيّ).
- عند الإلغاء:
  - الواجهة تخفت (opacity 0.4) و pointer-events: none.
  - `getAyaGap()` يرجع 0 → لا فاصل صمت إضافيّ.
  - الإعدادات تبقى محفوظة (لم تُحذف، فقط مُعطَّلة).
- يحفظ في `localStorage[gt_sirm_timing_master_on]`.

#### الاستخدام النموذجيّ
- النصّ الحرّ بتوقيت تفصيلي → ألغِ التوگل → المدد الفرديّة تُطبَّق دون تداخل.
- آيات القرآن بصوت قارئ → فعّل التوگل → استخدم فاصل الصمت كالمعتاد.

📦 PWA cache bump → v9.

---

## [0.5.3] — 2026-06-07

### 🔄 مزامنة فوريّة للتوقيت التفصيلي مع المعاينة

#### المشكلة
- تعديل مدّة شريحة في القائمة كان يُحدّث `S.freePerSlice` فقط.
- محرّك المعاينة يقرأ من `S.ayaDurations[i]` و `S.verses[i].manualDuration`.
- النتيجة: لا يظهر أثر التعديل حتى يضغط المستخدم "تطبيق النصّ".

#### الحلّ
- دالّة `syncPerSliceToPlayback` تنشر التعديل فوراً:
  - `S.verses[i].manualDuration = it.dur`
  - `S.ayaDurations[i] = it.dur`
  - تستدعى بعد كلّ تعديل + بعد إعادة التوزيع + بعد التوزيع المتساوي.
  - حارس: تطبَّق فقط إذا كانت verses تخصّ النصّ الحرّ (free=true لكلّها).
- `updateAyaUI()` تُستدعى بعدها لتحديث شريط التقدّم.

النتيجة: شريحة كانت 4s → 3s = الانتقال يحدث عند 3s بدلاً من 4s فوراً.

📦 PWA cache bump → v8.

---

## [0.5.2] — 2026-06-07

### 🔒 إعادة توزيع تلقائيّة لمدّة الشرائح

#### المنطق
- توگل جديد **🔒 ثبّت الإجمالي** داخل قسم التوقيت التفصيلي (مفعَّل افتراضياً).
- عند تقليل مدّة شريحة → الثواني المنتقصة تُوزَّع على باقي الشرائح بالتناسب.
- عند زيادة مدّة شريحة → الثواني الإضافيّة تُؤخذ من باقي الشرائح بالتناسب.
- الإجمالي يبقى ثابتاً → مزامنة مستقرّة مع الصوت + ظهور كلمة بكلمة متّسق.
- حدّ أدنى صارم: 0.5s لكلّ شريحة (لا يمكن نزع الكلّ من شريحة واحدة).
- تصحيح drift التقريب على آخر شريحة غير المعدَّلة.

#### السلوك التفاعليّ
- `input event → change event`: التوزيع يحدث بعد الإنهاء (blur/Enter)، لا بعد كلّ ضغطة.
- عند إلغاء التوگل → تعديل حرّ (الإجمالي يتغيَّر، السلوك القديم v0.5.1).
- يحفظ في `localStorage[gt_sirm_free_per_slice_lock]`.

📦 PWA cache bump → v7.

---

## [0.5.1] — 2026-06-07

### 🔧 ضبط دقيق للتوقيت + إصلاح تحذير الويب

#### 🔄 توگل المزامنة التلقائيّة
- توگل جديد "🔄 مزامنة المدّة تلقائياً مع الصوت" في محرّر النصّ الحرّ.
- مفعَّل افتراضياً (سلوك v0.4.9).
- عند الإلغاء: المنزلق يعود لعمله الكامل (0.5 → 30 ثانية).
- يحفظ في localStorage.

#### ⏱️ التوقيت التفصيلي لكلّ شريحة
- توگل جديد "⏱️ توقيت تفصيليّ" يكشف قائمة لكلّ شريحة مع input مدّة فرديّ.
- زرّ "🔄 توليد القائمة" يبني/يحدّث القائمة من النصّ الحاليّ.
- زرّ "⚖️ توزيع" يقسّم مدّة الصوت بالتساوي على الشرائح.
- إحصائيّات حيّة: الإجمالي + فرق عن مدّة الصوت.
- المدد الفرديّة محفوظة في `S.freePerSlice = [{text, dur}]`.

#### 🐛 إخفاء تحذير الويب "تعذر جلب الصوت"
- لم يعد يظهر عند تصدير النصّ الحرّ (لا صوت قارئ مقصود).
- منطق الفحص: `if (loadedCount === 0 && !skipReciter)`.

---

## [0.5.0] — 2026-06-07

### 🚀 مرونة الاستيراد الكاملة

#### 📥 Smart Drag-Drop عامّ
- اسحب أيّ ملفّ إلى نافذة التطبيق → اكتشاف نوعه تلقائياً وتطبيقه:
  - 🖼️ صورة → خلفية صورة (يفعّل radio "خلفية: صورة")
  - 🎥 فيديو → خلفية فيديو (يفعّل radio "خلفية: فيديو")
  - 🎵 صوت → تلاوة مخصّصة (يفعّل توگل "🎤 صوت مخصّص")
- Overlay بصريّ أنيق يظهر أثناء السحب، يختفي عند الإفلات.
- يدعم سحب عدّة ملفّات دفعةً واحدة.

#### 📋 لصق من الحافظة (Ctrl+V)
- نسخ صورة من المتصفّح أو ملصق من القصّ → لصق مباشر في GT-SIRM.
- يعمل على أيّ تبويب نشط.

#### 🔇 توگل كتم صوت الفيديو الأصليّ
- في قسم فيديو الخلفية: توگل "كتم الصوت الأصليّ للفيديو".
- مفيد عند استخدام تلاوة مخصّصة بدلاً من صوت الفيديو.
- يطبَّق فوراً على المعاينة + التصدير.
- يحترم per-clip `audioEnabled` عند إلغاء الكتم العامّ.

#### ↺ زرّ "إعادة من البداية" في المشغّل
- زرّ ↺ جديد في شريط المشغّل (بجانب ⏮ ⏭).
- يُعيد:
  - الشريحة/الآية إلى 1
  - صوت القارئ إلى 0
  - الصوت المخصّص إلى `trim.start` (أو 0)
  - فيديو الخلفية إلى 0
  - قائمة الفيديو إلى المقطع الأول
- يحافظ على حالة التشغيل (إذا كان يعمل، يستأنف بعد 60ms).

---

## [0.4.9] — 2026-06-07

### 🛠️ إصلاحات حرجة في التصدير والمزامنة

#### 🔴 إصلاح خطأ `Failed to construct 'AudioBuffer'`
- كان `sliceAudioBuffer` يحوي كود ميّت يستدعي `new AudioBuffer()` بدون وسطاء.
- حُذف السطر — الآن يعتمد على `OfflineAudioContext.createBuffer` فقط.

#### 🎚️ مزامنة دقيقة بين النصّ والصوت المخصّص
- `calcEffectiveSliceDuration` أصبحت ذكيّة:
  - **مع trim** → مدّة النصّ تطابق مدّة trim بالضبط.
  - **بدون trim + صوت محمَّل** → مدّة النصّ = مدّة الصوت الكاملة.
  - **بدون صوت** → القيمة من المنزلق كما اعتاد المستخدم.
- `updateFreeTextStats` تعرض إشعار `🔄 مُتزامن مع الصوت (Xs/شريحة)` لمصارحة المستخدم.

#### ⏯️ trim handler لا يُكرّر بعد الآن
- بدلاً من loop عند end، يقف الصوت طبيعياً بانتظار آخر شريحة نصّ.
- النصّ والصوت يبدآن ويتوقّفان معاً.

#### 🎵 ذبذبات صوت التصدير مطابقة للمعاينة (مهمّ جداً)
- إعادة كتابة `precomputeWaveDataForExport` ليطابق سلوك `AnalyserNode`:
  - `smoothingTimeConstant = 0.82` (انسيابيّة نزول/صعود مماثلة للمعاينة).
  - مقياس **dB من -100 إلى -30** (نفس Web Audio API الافتراضيّ).
  - **نافذة Blackman** أدقّ من Hann (مطابقة AnalyserNode).
  - مزج stereo → mono قبل التحليل.

#### 🐛 التصدير كان يجلب صوت القارئ مع النصّ الحرّ
- في `startExportDesktop` و `startWebExportV2`: إضافة حارس `skipReciter`.
- للآيات `free === true` أو `audio === null` → لا fetch لـ everyayah.com.
- المدّة تُحسب من `manualDuration` لا من `S.ayaDurations` (الذي كان فارغاً).

#### 🔢 رقم الآية يظهر فقط للقرآن
- في `drawVerse`: `if (!aya.free)` حول الرسم.
- النصّ الحرّ والحديث والأذكار لن تحمل رقماً مزخرفاً.

#### ✂️ Trim للصوت المخصّص يُحترَم في التصدير
- `getBgAudioTrim()` تُعطي أولويّة لـ `S.freeAudioTrim` قبل trim الكلاسيكي.

#### 🛡️ حماية وحدة القرآن
- عند إلغاء الوحدة: تنظيف verses + translations + إيقاف الصوت + `_recGen++` لإلغاء fetches الجارية.
- `loadVerses` / `loadTranslations`: حارس مبكر يخرج إذا الوحدة مُلغاة.

#### 🎨 تحسينات بصريّة
- الأيقونة تملأ كامل إطارها (`object-fit: cover` + `background: transparent`).
- مسارات الأيقونة في HTML تُصلَح إلى `../../GT-SIRM-icons/...`.
- إزالة معالجات `onerror=` المضمَّنة (لا تتوافق مع CSP).
- رقم الإصدار في تبويب "حول" + كل الملفّات: `0.4.9`.

#### 🎤 محرّر النصّ + الصوت — توگلان مستقلّان
- "🔗 تفعيل محرّر النصّ" يُظهر/يُخفي محرّر النصّ (المحتوى محفوظ).
- "🎤 استخدام صوت تلاوة مخصّص" يُظهر/يُخفي مستورد الصوت (مستقلّ).
- يمكن استخدام صوت مخصّص بدون نصّ حرّ (مع آيات القرآن).
- زرّ ↺ "إعادة" مستقلّ للصوت يحترم `trim.start`.

#### 📖 وحدة القرآن: استيراد النصّ فقط
- توگل "🔇 استيراد النصّ فقط" يحمّل آيات القرآن **نصّاً** بدون صوت قارئ.
- يفعّل توگل الصوت المخصّص تلقائياً لربط تلاوة محليّة.

---

## [0.4.0 → 0.4.6] — 2026-06-06/07 (تطوير محرّر النصّ الحرّ)

- **v0.4.0** محرّر النصّ الحرّ: textarea + إحصاء الشرائح + توقيت + قوالب محفوظة.
- **v0.4.1** توگل ربط/فصل + استيراد صوت خارجيّ + drag-drop.
- **v0.4.2** زرّ ↺ "إعادة من البداية" + مزامنة الصوت عند إعادة التطبيق.
- **v0.4.3** "🔇 استيراد النصّ فقط" في قسم القرآن.
- **v0.4.4** فصل توگل النصّ عن توگل الصوت + تقطيع زمنيّ (✂️ from/to).
- **v0.4.5** حماية إلغاء وحدة القرآن (تنظيف + إلغاء fetches).
- **v0.4.6** تنظيف بقايا الترجمة/المدد + إعادة ربط trim عند تبديل ملفّ + زرّ إعادة للصوت المخصّص.

---

## [0.3.0] — 2026-06-06 — Module Manager

- توگل لكلّ وحدة محتوى في الإعدادات (قرآن/حديث/أذكار/أسماء/أدعية/حِكَم/نصّ حرّ).
- `data-module` على كلّ قسم + CSS موحَّد للإخفاء/الإظهار.
- 5 أقسام قرآنية معلَّمة + زرّ تبويب التلاوة + تبويب الدفعي.
- حفظ الحالة في `localStorage[gt_sirm_modules_v1]`.

---

## [0.1.0] — 2026-06-06 (Pre-alpha — Scaffolding)

### 🌱 إنشاء البنية الأساسيّة

- إنشاء مستودع GT-SIRM المستقلّ بنسختَيه:
  - `GT-SIRM-DESKTOP/` لنسخة Electron + Linux
  - `GT-SIRM-WEB/` لنسخة PWA متعدّدة المتصفّحات
- ملفات تعريفيّة مشتركة في الجذر: `README.md` · `LICENSE` · `ROADMAP.md` · `CLAUDE.md`
- إعلان النيّة والتبرّؤ في `README.md` و `LICENSE` و موقع GitHub Pages
- صفحة الموقع الرسميّ (`index.html`) — تعرّف بالمشروع وتوفّر:
  - زرّ تنزيل نسخة سطح المكتب لـ GNU/Linux
  - زرّ تشغيل مباشر لنسخة الويب
- ملفّات تقنيّة هيكليّة (Skeleton) لكلتا النسختَين — جاهزة لتلقّي fork من GT-SQRM v3.0.0 في v0.2

### 🎯 الميزات المخطَّطة للإصدارات القادمة
راجع [`ROADMAP.md`](./ROADMAP.md) للتفصيل.

| الإصدار | المحتوى |
|---|---|
| **v0.2** | Fork من GT-SQRM v3.0 + توحيد البادئات إلى `gt_sirm_` |
| **v0.3** | Module Manager + `data-module` + تبويب الوحدات |
| **v0.4** | محرّر النصّ الحرّ |
| **v0.5** | مرونة الاستيراد الكاملة + فصل الصوت عن الفيديو |
| **v0.6** | أداة Chromakey (WebGL shader + ffmpeg filter) |
| **v0.7** | وحدة الحديث الشريف |
| **v0.8** | وحدة الأذكار (من حصن المسلم) |
| **v0.9** | أسماء الله الحسنى + الأدعية + الحِكَم |
| **v0.10** | تسجيل الميكروفون + TTS |
| **v1.0** | تحزيم ونشر — release موحَّد على GitHub |

---

> **ملاحظة**: تفاصيل التغييرات الخاصّة بكلّ نسخة على حِدَة في `GT-SIRM-DESKTOP/CHANGELOG.md` و `GT-SIRM-WEB/CHANGELOG.md`.
