diff --git a/TODO.md b/TODO.md
index 48028c5..d24c099 100644
--- a/TODO.md
+++ b/TODO.md
@@ -120,7 +120,42 @@
---
-### 6. π ΠΡΠ» ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠΉ HTTP (`httpx.AsyncClient` Ρ Keep-Alive)
+### 6. π ΠΠ°ΠΏΠΎΠΌΠΈΠ½Π°Π½ΠΈΠ΅ ΠΏΠΎΠ·ΠΈΡΠΈΠΈ ΡΡΠ΅Π½ΠΈΡ ΠΈ ΠΏΡΠΎΠ³ΡΠ΅ΡΡ Π³Π»Π°Π²Ρ (Scroll position, Chapter Progress & Auto-restore)
+- [x] **ΠΠ½Π΄ΠΈΠΊΠ°ΡΠΎΡ ΠΏΡΠΎΠ³ΡΠ΅ΡΡΠ° ΡΠ΅ΠΊΡΡΠ΅ΠΉ Π³Π»Π°Π²Ρ**:
+ - Π’ΠΎΠ½ΠΊΠΈΠΉ Π½Π΅ΠΎΠ½ΠΎΠ²ΡΠΉ ΠΏΡΠΎΠ³ΡΠ΅ΡΡ-Π±Π°Ρ Π² ΡΠ°ΠΏΠΊΠ΅ ΡΠΈΡΠ°Π»ΠΊΠΈ (`reader-chapter-progress-bar`), ΠΏΠ»Π°Π²Π½ΠΎ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°ΡΡΠΈΠΉ ΠΏΡΠΎΡΠ΅Π½Ρ ΠΏΡΠΎΡΠΈΡΠ°Π½Π½ΠΎΠ³ΠΎ Π² ΡΠ΅ΠΊΡΡΠ΅ΠΉ Π³Π»Π°Π²Π΅.
+ - ΠΡΠΎΡΠ΅Π½ΡΠ½ΡΠΉ Π±Π΅ΠΉΠ΄ΠΆ Π² ΡΠ΅Π½ΡΡΠ΅ ΡΡΠ»Π±Π°ΡΠ° ΡΠΈΡΠ°Π»ΠΊΠΈ ΡΡΠ΄ΠΎΠΌ Ρ Π²ΡΠ±ΠΎΡΠΎΠΌ Π³Π»Π°Π²Ρ (`reader-scroll-pct-badge`, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ `42%`).
+- [x] **ΠΠ²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ΅ ΡΠΎΡ
ΡΠ°Π½Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ·ΠΈΡΠΈΠΈ ΡΡΠ΅Π½ΠΈΡ**:
+ - ΠΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ΡΠΊΡΠΎΠ»Π»Π° ΡΠΈΡΠ°Π»ΠΊΠΈ Π² ΡΠ΅Π°Π»ΡΠ½ΠΎΠΌ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ (`handleReaderScroll`).
+ - ΠΠ³Π½ΠΎΠ²Π΅Π½Π½ΠΎΠ΅ ΡΠΎΡ
ΡΠ°Π½Π΅Π½ΠΈΠ΅ Π² `localStorage` (`notes_book_{id}_pos`: Π½ΠΎΠΌΠ΅Ρ Π³Π»Π°Π²Ρ, ΡΠΎΡΠ½ΡΠ΅ ΠΏΠΈΠΊΡΠ΅Π»ΠΈ `scrollTop`, Π΄ΠΎΠ»Ρ ΠΏΡΠΎΠ³ΡΠ΅ΡΡΠ° `fraction`).
+ - Π€ΠΎΠ½ΠΎΠ²Π°Ρ ΠΎΡΠΏΡΠ°Π²ΠΊΠ° ΠΏΡΠΎΠ³ΡΠ΅ΡΡΠ° Π½Π° Π±ΡΠΊΠ΅Π½Π΄ (`PUT /api/books/{id}/progress`) Ρ Π΄Π΅Π±Π°ΡΠ½ΡΠΎΠΌ 800 ΠΌΡ.
+ - ΠΠ°ΡΠ°Π½ΡΠΈΡΠΎΠ²Π°Π½Π½Π°Ρ ΡΠΈΠΊΡΠ°ΡΠΈΡ ΠΏΠΎΠ·ΠΈΡΠΈΠΈ ΠΏΡΠΈ Π·Π°ΠΊΡΡΡΠΈΠΈ/ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΈ ΡΡΡΠ°Π½ΠΈΡΡ ΡΠ΅ΡΠ΅Π· `beforeunload` + `navigator.sendBeacon`.
+- [x] **ΠΠ΅ΡΡΠΎΠ²Π½ΠΎΠ΅ Π²ΠΎΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ ΡΡΠ΅Π½ΠΈΡ ΠΏΡΠΈ ΠΏΠ΅ΡΠ΅Π·Π°Π³ΡΡΠ·ΠΊΠ΅ ΡΡΡΠ°Π½ΠΈΡΡ**:
+ - Π‘Π΅ΡΠ²ΠΈΡ Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅Ρ Π°ΠΊΡΠΈΠ²Π½ΡΠΉ ΡΠΊΡΠ°Π½ ΠΈ ID ΠΎΡΠΊΡΡΡΠΎΠΉ ΠΊΠ½ΠΈΠ³ΠΈ (`notes_active_book_id`).
+ - ΠΡΠΈ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΈ ΡΡΡΠ°Π½ΠΈΡΡ (`F5` ΠΈΠ»ΠΈ ΡΠ²Π°ΠΉΠΏ Π½Π° ΡΠ΅Π»Π΅ΡΠΎΠ½Π΅) ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ ΠΎΡΠΊΡΡΠ²Π°Π΅Ρ ΡΠΈΡΠ°Π»ΠΊΡ Π½Π° ΡΠΎΠΉ ΠΆΠ΅ ΠΊΠ½ΠΈΠ³Π΅, ΡΠΎΠΉ ΠΆΠ΅ Π³Π»Π°Π²Π΅ ΠΈ Π²ΠΎΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅Ρ ΡΠΎΡΠ½ΡΡ ΠΏΠΎΠ·ΠΈΡΠΈΡ ΡΠΊΡΠΎΠ»Π»Π° Π²ΠΏΠ»ΠΎΡΡ Π΄ΠΎ ΠΏΠΈΠΊΡΠ΅Π»Ρ.
+
+---
+
+### 7. π ΠΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠ° ΡΡΠ΅Π½ΠΈΡ PDF (Cisco CCNA, O'Reilly & Tech Books Ρ ΠΎΠ³Π»Π°Π²Π»Π΅Π½ΠΈΠ΅ΠΌ ΠΈ ΡΠ΅ΠΊΡΡΠΎΠ²ΡΠΌ ΡΠ»ΠΎΠ΅ΠΌ)
+- [ ] **ΠΠ΅Π³ΠΊΠΎΠ²Π΅ΡΠ½ΡΠΉ Pure-Python ΠΏΠ°ΡΡΠ΅Ρ (`pypdf`, Zero C-Dependency)**:
+ - ΠΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ `pypdf` (< 400 ΠΠ, ΡΠΈΡΡΡΠΉ Python, Π±Π΅Π· ΡΠ°Π·Π΄ΡΠ²Π°Π½ΠΈΡ Docker-ΠΎΠ±ΡΠ°Π·Π° ΠΈ Π±Π΅Π· ΡΠΈΡΡΠ΅ΠΌΠ½ΡΡ
Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊ `poppler-utils` / `mupdf`).
+- [ ] **ΠΠ·Π²Π»Π΅ΡΠ΅Π½ΠΈΠ΅ ΠΎΠ³Π»Π°Π²Π»Π΅Π½ΠΈΡ ΠΈ Π·Π°ΠΊΠ»Π°Π΄ΠΎΠΊ PDF (`reader.outline`)**:
+ - ΠΠ·Π²Π»Π΅ΡΠ΅Π½ΠΈΠ΅ Π°Π²ΡΠΎΡΡΠΊΠΎΠ³ΠΎ ΠΎΠ³Π»Π°Π²Π»Π΅Π½ΠΈΡ (ToC / Bookmarks), ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΠΎΠ³ΠΎ Π΄Π»Ρ ΠΊΠ½ΠΈΠ³ Cisco Press (CCNA Official Cert Guide), O'Reilly ΠΈ Wiley.
+ - Π Π°Π·Π±ΠΈΠ²ΠΊΠ° ΠΊΠ½ΠΈΠ³ΠΈ Π½Π° Π»ΠΎΠ³ΠΈΡΠ΅ΡΠΊΠΈΠ΅ Π³Π»Π°Π²Ρ ΠΈ ΡΠ°Π·Π΄Π΅Π»Ρ (`Part I`, `Chapter 1`, `Chapter 2`) ΡΠΎΡΠ½ΠΎ ΠΏΠΎ ΠΎΠ³Π»Π°Π²Π»Π΅Π½ΠΈΡ Π°Π²ΡΠΎΡΠ°.
+- [ ] **Fallback-ΡΠ°Π·Π±ΠΈΠ²ΠΊΠ° ΠΏΡΠΈ ΠΎΡΡΡΡΡΡΠ²ΠΈΠΈ ΠΎΠ³Π»Π°Π²Π»Π΅Π½ΠΈΡ**:
+ - ΠΡΠΈ ΠΎΡΡΡΡΡΡΠ²ΠΈΠΈ PDF-Π·Π°ΠΊΠ»Π°Π΄ΠΎΠΊ β Π°Π²ΡΠΎΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ² ΡΠ΅ΡΠ΅Π· regex (`Chapter \d+`, `ΠΠ»Π°Π²Π° \d+`) ΠΈΠ»ΠΈ Π³ΡΡΠΏΠΏΠΈΡΠΎΠ²ΠΊΠ° ΡΡΡΠ°Π½ΠΈΡ ΠΏΠΎΡΡΠΈΡΠΌΠΈ ΠΏΠΎ ~12β15 ΡΡΡΠ°Π½ΠΈΡ.
+- [ ] **ΠΡΠΈΡΡΠΊΠ° ΡΡΠΌΠ° ΠΈ ΠΊΠΎΠ»ΠΎΠ½ΡΠΈΡΡΠ»ΠΎΠ²**:
+ - Π€ΠΈΠ»ΡΡΡΠ°ΡΠΈΡ ΠΏΠΎΠ²ΡΠΎΡΡΡΡΠΈΡ
ΡΡ Π²Π΅ΡΡ
Π½ΠΈΡ
/Π½ΠΈΠΆΠ½ΠΈΡ
ΠΊΠΎΠ»ΠΎΠ½ΡΠΈΡΡΠ»ΠΎΠ² (Β«CCNA 200-301 Official Cert GuideΒ», Β«Page 45 of 900Β»).
+- [ ] **Π‘ΠΎΡ
ΡΠ°Π½Π΅Π½ΠΈΠ΅ CLI/Console Π±Π»ΠΎΠΊΠΎΠ²**:
+ - Π Π°ΡΠΏΠΎΠ·Π½Π°Π²Π°Π½ΠΈΠ΅ ΠΊΠΎΠ½ΡΠΎΠ»ΡΠ½ΠΎΠ³ΠΎ Π²ΡΠ²ΠΎΠ΄Π° ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄ ΡΠ΅ΡΠ΅Π²ΠΎΠ³ΠΎ ΠΎΠ±ΠΎΡΡΠ΄ΠΎΠ²Π°Π½ΠΈΡ (`Router# show ip interface brief`, `Switch(config)#`) ΠΈ ΠΎΠ±ΠΎΡΠ°ΡΠΈΠ²Π°Π½ΠΈΠ΅ Π² Π±Π»ΠΎΠΊΠΈ ΠΊΠΎΠ΄Π° Markdown Π΄Π»Ρ ΡΠΈΡΠ°Π»ΠΊΠΈ Ρ ΠΊΠ½ΠΎΠΏΠΊΠΎΠΉ Β«ΠΠΎΠΏΠΈΡΠΎΠ²Π°ΡΡΒ».
+- [ ] **ΠΠ°ΡΠΈΡΠ° ΠΎΡ ΡΠΊΠ°Π½ΠΎΠ² Π±Π΅Π· OCR (Scanned PDF Guard)**:
+ - ΠΠ°Π»ΠΈΠ΄Π°ΡΠΈΡ Π½Π°Π»ΠΈΡΠΈΡ ΡΠ΅ΠΊΡΡΠΎΠ²ΠΎΠ³ΠΎ ΡΠ»ΠΎΡ: Π΅ΡΠ»ΠΈ ΡΡΠΌΠΌΠ°ΡΠ½ΡΠΉ ΠΎΠ±ΡΡΠΌ ΠΈΠ·Π²Π»Π΅ΡΡΠ½Π½ΠΎΠ³ΠΎ ΡΠ΅ΠΊΡΡΠ° < 100 ΡΠ»ΠΎΠ², Π²ΠΎΠ·Π²ΡΠ°Ρ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠ²Π½ΠΎΠΉ ΠΎΡΠΈΠ±ΠΊΠΈ Ρ ΠΏΡΠ΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠ΅ΠΊΡΡΠΎΠ²ΡΠΉ PDF ΠΈΠ»ΠΈ OCR.
+- [ ] **ΠΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ Π² ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ ΡΠΈΡΠ°Π»ΠΊΠΈ**:
+ - Π Π°Π·ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Π·Π°Π³ΡΡΠ·ΠΊΠΈ `.pdf` Π² ``.
+ - ΠΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ ΠΊΠ½ΠΎΠΏΠΊΠΈ Π² Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ΅: `π ΠΠ°Π³ΡΡΠ·ΠΈΡΡ EPUB / PDF / TXT`.
+
+---
+
+### 8. π ΠΡΠ» ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠΉ HTTP (`httpx.AsyncClient` Ρ Keep-Alive)
- [ ] Π [`app/dictionary.py`](file:///home/ai-projects/services/study.qpid.pro/app/dictionary.py) ΡΠΎΠ·Π΄Π°ΡΡ ΡΠΈΠ½Π³Π»ΡΠΎΠ½-ΠΊΠ»ΠΈΠ΅Π½Ρ `get_http_client()` Ρ ΠΏΡΠ»ΠΎΠΌ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠΉ:
```python
limits = httpx.Limits(max_keepalive_connections=10, max_connections=20)
@@ -130,7 +165,7 @@
---
-### 7. ποΈ Π’ΡΠ½ΠΈΠ½Π³ SQLite PRAGMA ΠΈ ΡΠΎΡΡΠ°Π²Π½ΡΡ
ΠΈΠ½Π΄Π΅ΠΊΡΠΎΠ²
+### 9. ποΈ Π’ΡΠ½ΠΈΠ½Π³ SQLite PRAGMA ΠΈ ΡΠΎΡΡΠ°Π²Π½ΡΡ
ΠΈΠ½Π΄Π΅ΠΊΡΠΎΠ²
- [ ] Π [`app/database.py`](file:///home/ai-projects/services/study.qpid.pro/app/database.py):
- ΠΡΠ½Π΅ΡΡΠΈ `PRAGMA journal_mode=WAL;` Π² `init_db()` (ΡΠ±ΡΠ°ΡΡ ΠΈΠ·Π±ΡΡΠΎΡΠ½ΡΠΉ Π²ΡΠ·ΠΎΠ² ΠΏΡΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ Π·Π°ΠΏΡΠΎΡΠ΅).
- ΠΠΊΠ»ΡΡΠΈΡΡ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ ΠΏΠ°ΠΌΡΡΠΈ Linux:
@@ -143,13 +178,13 @@
---
-### 8. βοΈ ΠΠ΅-Π±Π»ΠΎΠ°ΡΠΈΠ½Π³ Π²Π½Π΅ΡΠ½ΠΈΡ
ΠΏΠ°ΡΡΠ΅ΡΠΎΠ² (YAGNI)
+### 10. βοΈ ΠΠ΅-Π±Π»ΠΎΠ°ΡΠΈΠ½Π³ Π²Π½Π΅ΡΠ½ΠΈΡ
ΠΏΠ°ΡΡΠ΅ΡΠΎΠ² (YAGNI)
- [ ] Π£Π΄Π°Π»ΠΈΡΡ Π»ΠΈΡΠ½ΠΈΠΉ ΡΠ΅ΡΠ΅Π²ΠΎΠΉ ΠΎΠΏΡΠΎΡ Datamuse (`fetch_datamuse`) β ΠΎΠ½ Π΄ΡΠ±Π»ΠΈΡΡΠ΅Ρ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡ ΠΈ ΠΏΠ΅ΡΠ΅Π³ΡΡΠΆΠ°Π΅Ρ ΠΎΡΠ²Π΅Ρ Π½Π΅ΡΠ΅Π»Π΅Π²Π°Π½ΡΠ½ΡΠΌΠΈ ΡΠΈΡΠΌΠ°ΠΌΠΈ.
- [ ] Π£ΠΏΡΠΎΡΡΠΈΡΡ Ρ
ΡΡΠΏΠΊΠΈΠΉ regex-ΠΏΠ°ΡΡΠΈΠ½Π³ ΡΠ°Π·ΠΌΠ΅ΡΠΊΠΈ Wikitext, ΠΎΠΏΠΈΡΠ°ΡΡΡ Π½Π° ΡΡΠ°Π±ΠΈΠ»ΡΠ½ΡΠ΅ REST JSON ΡΠ½Π΄ΠΏΠΎΠΈΠ½ΡΡ.
---
-### 9. π ΠΠΎΠΊΠ°Π»ΡΠ½ΡΠΉ ΠΎΡΡΠ»Π°ΠΉΠ½-ΡΠ»ΠΎΠ²Π°ΡΡ (99%+ ΠΏΠΎΠΊΡΡΡΠΈΡ ΡΠΎ ΡΠ»ΠΎΠ²ΠΎΡΠΎΡΠΌΠ°ΠΌΠΈ, SQLite 10β20 ΠΠ)
+### 11. π ΠΠΎΠΊΠ°Π»ΡΠ½ΡΠΉ ΠΎΡΡΠ»Π°ΠΉΠ½-ΡΠ»ΠΎΠ²Π°ΡΡ (99%+ ΠΏΠΎΠΊΡΡΡΠΈΡ ΡΠΎ ΡΠ»ΠΎΠ²ΠΎΡΠΎΡΠΌΠ°ΠΌΠΈ, SQLite 10β20 ΠΠ)
- [ ] Π‘ΠΎΠ·Π΄Π°ΡΡ Π² SQLite ΡΠ°Π±Π»ΠΈΡΡ:
```sql
CREATE TABLE IF NOT EXISTS offline_dictionary (
@@ -171,7 +206,7 @@
---
-### 10. π§© ΠΠΎΠ΄ΡΠ»ΡΠ½ΠΎΡΡΡ ΡΡΠΎΠ½ΡΠ΅Π½Π΄Π° Π½Π° Π½Π°ΡΠΈΠ²Π½ΡΡ
ES-ΠΌΠΎΠ΄ΡΠ»ΡΡ
(Π±Π΅Π· Webpack/Vite)
+### 12. π§© ΠΠΎΠ΄ΡΠ»ΡΠ½ΠΎΡΡΡ ΡΡΠΎΠ½ΡΠ΅Π½Π΄Π° Π½Π° Π½Π°ΡΠΈΠ²Π½ΡΡ
ES-ΠΌΠΎΠ΄ΡΠ»ΡΡ
(Π±Π΅Π· Webpack/Vite)
- [ ] ΠΠ΅ΡΠ΅Π²Π΅ΡΡΠΈ [`app/static/js/app.js`](file:///home/ai-projects/services/study.qpid.pro/app/static/js/app.js) Π½Π° Π½Π°ΡΠΈΠ²Π½ΡΠΉ Π±ΡΠ°ΡΠ·Π΅ΡΠ½ΡΠΉ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡ `
+