@dzhechkov/keysarium 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/README.md +50 -3
  2. package/bin/cli.js +0 -0
  3. package/package.json +5 -3
  4. package/templates/.claude/commands/analyst-manual.md +38 -0
  5. package/templates/.claude/commands/casarium.md +55 -4
  6. package/templates/.claude/commands/feature-adr.md +8 -0
  7. package/templates/.claude/rules/trust-tiers.md +5 -0
  8. package/templates/.claude/shards/feature-adr.shard.md +64 -10
  9. package/templates/.claude/shards/phase-ai-factory.shard.md +109 -0
  10. package/templates/.claude/skills/ai-factory-mapper/README.md +90 -0
  11. package/templates/.claude/skills/ai-factory-mapper/SKILL.md +309 -0
  12. package/templates/.claude/skills/ai-factory-mapper/assets/report-template.md +123 -0
  13. package/templates/.claude/skills/ai-factory-mapper/references/catalog.md +230 -0
  14. package/templates/.claude/skills/ai-factory-mapper/references/coverage-formula.md +219 -0
  15. package/templates/.claude/skills/ai-factory-mapper/references/decomposition-checklist.md +183 -0
  16. package/templates/.claude/skills/ai-factory-mapper/references/pattern-library.md +312 -0
  17. package/templates/.claude/skills/ai-factory-mapper/scripts/build_docx_report.js +423 -0
  18. package/templates/.claude/skills/analyst-manual-full/SKILL.md +286 -0
  19. package/templates/.claude/skills/edu-site-generator/SKILL.md +254 -0
  20. package/templates/.claude/skills/edu-site-generator/examples/sample-course-structure.md +116 -0
  21. package/templates/.claude/skills/edu-site-generator/modules/00-content-analysis.md +84 -0
  22. package/templates/.claude/skills/edu-site-generator/modules/01-course-structure.md +75 -0
  23. package/templates/.claude/skills/edu-site-generator/modules/02-data-generation.md +186 -0
  24. package/templates/.claude/skills/edu-site-generator/modules/03-scaffold.md +249 -0
  25. package/templates/.claude/skills/edu-site-generator/modules/04-components.md +130 -0
  26. package/templates/.claude/skills/edu-site-generator/modules/05-gamification.md +163 -0
  27. package/templates/.claude/skills/edu-site-generator/modules/06-deploy.md +88 -0
  28. package/templates/.claude/skills/edu-site-generator/modules/07-verification.md +97 -0
  29. package/templates/.claude/skills/edu-site-generator/references/component-templates.md +436 -0
  30. package/templates/.claude/skills/edu-site-generator/references/data-schemas.md +164 -0
  31. package/templates/.claude/skills/edu-site-generator/references/exercise-catalog.md +110 -0
  32. package/templates/.claude/skills/edu-site-generator/references/tech-stack.md +69 -0
  33. package/templates/.claude/skills/feature-adr/SKILL.md +245 -59
  34. package/templates/.claude/skills/feature-adr/modules/03-adr.md +43 -0
  35. package/templates/.claude/skills/feature-adr/modules/03.5-ideation-swarm.md +180 -0
  36. package/templates/.claude/skills/feature-adr/modules/06-implementation-plan.md +56 -7
  37. package/templates/.claude/skills/feature-adr/modules/08-qe.md +87 -23
  38. package/templates/.claude/skills/feature-adr/modules/09-fleet-qe.md +305 -0
  39. package/templates/.claude/skills/feature-adr/references/agentic-qe/README.md +143 -0
  40. package/templates/.claude/skills/feature-adr/references/agentic-qe/brutal-honesty-review.md +240 -0
  41. package/templates/.claude/skills/feature-adr/references/agentic-qe/chaos-engineering-resilience.md +163 -0
  42. package/templates/.claude/skills/feature-adr/references/agentic-qe/code-goal-planner.md +446 -0
  43. package/templates/.claude/skills/feature-adr/references/agentic-qe/enterprise-integration-testing.md +111 -0
  44. package/templates/.claude/skills/feature-adr/references/agentic-qe/mutation-testing.md +236 -0
  45. package/templates/.claude/skills/feature-adr/references/agentic-qe/performance-testing.md +315 -0
  46. package/templates/.claude/skills/feature-adr/references/agentic-qe/qcsd-ideation-swarm.md +126 -0
  47. package/templates/.claude/skills/feature-adr/references/agentic-qe/qcsd-production-swarm.md +108 -0
  48. package/templates/.claude/skills/feature-adr/references/agentic-qe/qe-coverage-analysis.md +193 -0
  49. package/templates/.claude/skills/feature-adr/references/agentic-qe/qe-requirements-validation.md +254 -0
  50. package/templates/.claude/skills/feature-adr/references/agentic-qe/regression-testing.md +233 -0
  51. package/templates/.claude/skills/feature-adr/references/agentic-qe/risk-based-testing.md +212 -0
  52. package/templates/.claude/skills/feature-adr/references/agentic-qe/security-testing.md +311 -0
  53. package/templates/.claude/skills/feature-adr/references/agentic-qe/shift-left-testing.md +231 -0
  54. package/templates/.claude/skills/feature-adr/references/agentic-qe/tdd-london-chicago.md +249 -0
  55. package/templates/.claude/skills/transcript-site-generator/SKILL.md +287 -0
  56. package/templates/.claude/skills/transcript-site-generator/examples/sample-text-only-site.md +123 -0
  57. package/templates/.claude/skills/transcript-site-generator/examples/sample-transcript-site.md +134 -0
  58. package/templates/.claude/skills/transcript-site-generator/modules/00-input-analysis.md +132 -0
  59. package/templates/.claude/skills/transcript-site-generator/modules/01-content-parsing.md +117 -0
  60. package/templates/.claude/skills/transcript-site-generator/modules/02-site-generation.md +293 -0
  61. package/templates/.claude/skills/transcript-site-generator/modules/03-interactivity.md +406 -0
  62. package/templates/.claude/skills/transcript-site-generator/modules/04-deploy.md +130 -0
  63. package/templates/.claude/skills/transcript-site-generator/modules/05-verification.md +155 -0
  64. package/templates/.claude/skills/transcript-site-generator/references/component-catalog.md +86 -0
  65. package/templates/.claude/skills/transcript-site-generator/references/data-schemas.md +123 -0
  66. package/templates/.claude/skills/transcript-site-generator/references/tech-stack.md +132 -0
  67. package/templates/CLAUDE.md +9 -2
  68. package/templates/docs/edu-site-generator/01-deployment-guide.md +911 -0
  69. package/templates/docs/edu-site-generator/02-admin-guide.md +901 -0
  70. package/templates/docs/edu-site-generator/03-user-guide.md +1008 -0
  71. package/templates/docs/edu-site-generator/04-infrastructure-requirements.md +489 -0
  72. package/templates/docs/edu-site-generator/05-architecture.md +902 -0
  73. package/templates/docs/edu-site-generator/06-user-flows.md +759 -0
  74. package/templates/docs/transcript-site-generator/01-deployment-guide.md +1042 -0
  75. package/templates/docs/transcript-site-generator/02-admin-guide.md +918 -0
  76. package/templates/docs/transcript-site-generator/03-user-guide.md +925 -0
  77. package/templates/docs/transcript-site-generator/04-infrastructure-requirements.md +482 -0
  78. package/templates/docs/transcript-site-generator/05-architecture.md +1068 -0
  79. package/templates/docs/transcript-site-generator/06-user-flows.md +855 -0
@@ -0,0 +1,1068 @@
1
+ # Архитектура @dzhechkov/skills-transcript-site
2
+
3
+ ## Содержание
4
+
5
+ 1. [Обзор системы и философия проектирования](#1-обзор-системы-и-философия-проектирования)
6
+ 2. [Компоненты системы](#2-компоненты-системы)
7
+ 3. [MODULE: Input Analysis](#3-module-input-analysis)
8
+ 4. [MODULE: Content Parsing](#4-module-content-parsing)
9
+ 5. [MODULE: Site Generation](#5-module-site-generation)
10
+ 6. [MODULE: Interactivity](#6-module-interactivity)
11
+ 7. [MODULE: Deploy](#7-module-deploy)
12
+ 8. [MODULE: Verification](#8-module-verification)
13
+ 9. [Поток данных (Data Flow)](#9-поток-данных-data-flow)
14
+ 10. [Выбор технологического стека](#10-выбор-технологического-стека)
15
+ 11. [Архитектура безопасности](#11-архитектура-безопасности)
16
+ 12. [SEO архитектура](#12-seo-архитектура)
17
+ 13. [Доступность (Accessibility)](#13-доступность-accessibility)
18
+ 14. [Расширяемость](#14-расширяемость)
19
+ 15. [Проектные решения и компромиссы](#15-проектные-решения-и-компромиссы)
20
+
21
+ ---
22
+
23
+ ## 1. Обзор системы и философия проектирования
24
+
25
+ `@dzhechkov/skills-transcript-site` -- это скилл для Claude Code, генерирующий интерактивные веб-сайты из текстовых транскриптов и YouTube-видео. Ключевая идея: **zero-build, CDN-first, vanilla JS**. Выходной артефакт -- один (или несколько) HTML-файл(ов), готовых к открытию в браузере или деплою на GitHub Pages.
26
+
27
+ ### Фундаментальные принципы
28
+
29
+ **1. Zero Build Step (нулевой шаг сборки)**
30
+
31
+ Никаких webpack, vite, esbuild, rollup. Никаких node_modules. Никаких package.json в выходной директории. Результат -- plain HTML, который открывается в браузере напрямую. Это критически важно для аудитории, которая не является фронтенд-разработчиками.
32
+
33
+ **2. CDN-First (CDN в приоритете)**
34
+
35
+ Tailwind CSS подключается через Play CDN. Font Awesome -- через cdnjs. YouTube -- через iframe API. Никаких локальных зависимостей. Это позволяет генерировать один self-contained файл без дополнительных assets.
36
+
37
+ **3. Vanilla JS (чистый JavaScript)**
38
+
39
+ Никаких React, Vue, Svelte, jQuery. Вся интерактивность реализована на vanilla JavaScript с event delegation. Это обеспечивает:
40
+ - Нулевую зависимость от фреймворков
41
+ - Минимальный размер JS-кода (~5-10 KB)
42
+ - Полную прозрачность и читаемость кода
43
+ - Отсутствие необходимости в системе модулей
44
+
45
+ **4. Static-Only Output (только статика)**
46
+
47
+ Выходные файлы не требуют сервера для работы. Нет API-эндпоинтов, нет серверного рендеринга, нет баз данных. Файл `index.html` открывается через `file://` протокол или любой статический хостинг.
48
+
49
+ **5. Progressive Enhancement (прогрессивное улучшение)**
50
+
51
+ Базовый HTML-контент (текст транскрипта) читается без JavaScript. Интерактивные фичи (поиск, dark mode, timestamp sync) добавляются как enhancement -- сайт остаётся функциональным при их отключении.
52
+
53
+ ---
54
+
55
+ ## 2. Компоненты системы
56
+
57
+ ### Текстовая карта компонентов
58
+
59
+ ```
60
+ @dzhechkov/skills-transcript-site
61
+ +-- SKILL.md <-- Точка входа, оркестратор 6 шагов
62
+ |
63
+ +-- modules/ <-- 6 модулей пайплайна
64
+ | +-- input-analysis.md <-- Шаг 1: source detection, yt-dlp, language
65
+ | +-- content-parsing.md <-- Шаг 2: sections, speakers, timestamps
66
+ | +-- site-generation.md <-- Шаг 3: HTML template, Tailwind, SEO
67
+ | +-- interactivity.md <-- Шаг 4: search, TOC, dark mode, sync
68
+ | +-- deploy.md <-- Шаг 5: GitHub Pages, robots, sitemap
69
+ | +-- verification.md <-- Шаг 6: HTML/JS/CSS/SEO/a11y checks
70
+ |
71
+ +-- references/ <-- Справочные материалы
72
+ | +-- html-template.md <-- Базовый HTML шаблон
73
+ | +-- tailwind-config.md <-- Конфигурация Tailwind CDN
74
+ | +-- seo-checklist.md <-- OG, Twitter Cards, JSON-LD
75
+ | +-- accessibility-guide.md <-- Skip-nav, ARIA, keyboard nav
76
+ |
77
+ +-- examples/ <-- Примеры
78
+ +-- sample-podcast.md <-- Пример: подкаст
79
+ +-- sample-youtube.md <-- Пример: YouTube видео
80
+ ```
81
+
82
+ ```
83
+ .claude/commands/ <-- Slash-команды
84
+ +-- transcript-site.md <-- /transcript-site -- полный пайплайн
85
+ +-- transcript-site-generate.md <-- /transcript-site-generate -- только HTML
86
+ +-- transcript-site-deploy.md <-- /transcript-site-deploy -- только деплой
87
+ ```
88
+
89
+ ```
90
+ .claude/rules/
91
+ +-- transcript-site-quality.md <-- Автоматические правила качества
92
+ ```
93
+
94
+ ### Mermaid-диаграмма компонентов
95
+
96
+ ```mermaid
97
+ graph TB
98
+ subgraph "Точки входа (Commands)"
99
+ FULL["/transcript-site<br/>Полный пайплайн"]
100
+ GEN["/transcript-site-generate<br/>Только генерация"]
101
+ DEP["/transcript-site-deploy<br/>Только деплой"]
102
+ end
103
+
104
+ subgraph "Ядро Skill"
105
+ SKILL["SKILL.md<br/>Оркестратор"]
106
+ end
107
+
108
+ subgraph "Модули (6 шагов)"
109
+ M1["modules/input-analysis.md<br/>Шаг 1"]
110
+ M2["modules/content-parsing.md<br/>Шаг 2"]
111
+ M3["modules/site-generation.md<br/>Шаг 3"]
112
+ M4["modules/interactivity.md<br/>Шаг 4"]
113
+ M5["modules/deploy.md<br/>Шаг 5"]
114
+ M6["modules/verification.md<br/>Шаг 6"]
115
+ end
116
+
117
+ subgraph "Справочники"
118
+ HTML["references/html-template.md"]
119
+ TW["references/tailwind-config.md"]
120
+ SEO["references/seo-checklist.md"]
121
+ A11Y["references/accessibility-guide.md"]
122
+ end
123
+
124
+ subgraph "Правила (автоматически)"
125
+ RULES["rules/transcript-site-quality.md"]
126
+ end
127
+
128
+ FULL --> SKILL
129
+ GEN --> SKILL
130
+ DEP --> SKILL
131
+ SKILL --> M1 --> M2 --> M3 --> M4 --> M5 --> M6
132
+ M3 --> HTML
133
+ M3 --> TW
134
+ M3 --> SEO
135
+ M4 --> A11Y
136
+ RULES -.->|"автоматически"| M3
137
+ RULES -.->|"автоматически"| M6
138
+ ```
139
+
140
+ ---
141
+
142
+ ## 3. MODULE: Input Analysis
143
+
144
+ ### Назначение
145
+
146
+ Определение типа входных данных (YouTube URL, текст, файл), извлечение метаданных и подготовка сырого транскрипта для парсинга.
147
+
148
+ ### Архитектура определения источника
149
+
150
+ ```mermaid
151
+ graph LR
152
+ INPUT["Входные данные"] --> DETECT{"Определение типа"}
153
+ DETECT -->|"youtube.com / youtu.be"| YOUTUBE["YouTube URL"]
154
+ DETECT -->|"Путь к файлу"| FILE["Файл"]
155
+ DETECT -->|"Текст в чате"| TEXT["Вставленный текст"]
156
+ DETECT -->|"URL + --text путь"| COMBINED["Комбинированный"]
157
+
158
+ YOUTUBE --> YTDLP["yt-dlp extraction"]
159
+ YTDLP --> META["Метаданные:<br/>title, duration, channel,<br/>upload date, thumbnail"]
160
+ YTDLP --> SUBS["Субтитры:<br/>auto or manual"]
161
+
162
+ FILE --> FREAD["Чтение файла"]
163
+ FREAD --> FDETECT["Определение формата:<br/>plain, SRT, VTT, speaker-labeled"]
164
+
165
+ TEXT --> TDETECT["Определение формата"]
166
+
167
+ COMBINED --> YTDLP
168
+ COMBINED --> FREAD
169
+
170
+ META --> LANG["Language Detection"]
171
+ SUBS --> LANG
172
+ FDETECT --> LANG
173
+ TDETECT --> LANG
174
+
175
+ LANG --> OUTPUT["Output:<br/>sourceType, metadata,<br/>rawTranscript, language"]
176
+ ```
177
+
178
+ ### Language Detection
179
+
180
+ Определение языка использует трёхуровневый подход:
181
+
182
+ ```
183
+ Уровень 1: Метаданные YouTube (если доступны)
184
+ -> subtitle lang: "en" -> English
185
+ -> subtitle lang: "ru" -> Russian
186
+
187
+ Уровень 2: Кодировка символов
188
+ -> Кириллица (U+0400-U+04FF) > 30% -> Russian
189
+ -> CJK (U+4E00-U+9FFF) > 10% -> Chinese/Japanese/Korean
190
+ -> Latin -> дальнейший анализ
191
+
192
+ Уровень 3: Стоп-слова
193
+ -> Высокая частотность "the", "and", "is" -> English
194
+ -> Высокая частотность "и", "в", "на" -> Russian
195
+ -> ...
196
+ ```
197
+
198
+ ### yt-dlp Integration Protocol
199
+
200
+ ```bash
201
+ # Шаг 1: Извлечение метаданных (JSON)
202
+ yt-dlp --dump-json --no-download "URL"
203
+
204
+ # Шаг 2: Извлечение субтитров
205
+ yt-dlp --write-auto-sub --sub-lang "DETECTED_LANG" \
206
+ --sub-format vtt --skip-download \
207
+ --output "/tmp/transcript" "URL"
208
+
209
+ # Шаг 3: Парсинг VTT файла
210
+ # Удаление дублей, нормализация timestamps, объединение фрагментов
211
+ ```
212
+
213
+ ### Anti-Patterns модуля
214
+
215
+ | Anti-Pattern | Сигнал обнаружения | Обязательное исправление |
216
+ |-------------|--------------------|-----------------------|
217
+ | Пустой транскрипт | Менее 50 слов после извлечения | Предложить ввод вручную |
218
+ | Битая кодировка | Наличие U+FFFD (replacement character) | Предложить повторное извлечение или конвертацию |
219
+ | Неопределённый язык | Confidence < 0.6 | Запросить у пользователя |
220
+ | yt-dlp timeout | Нет ответа > 30 секунд | Предложить ввод вручную |
221
+
222
+ ---
223
+
224
+ ## 4. MODULE: Content Parsing
225
+
226
+ ### Назначение
227
+
228
+ Разбиение сырого транскрипта на структурированные секции с определением спикеров, извлечением временных меток и ключевых цитат.
229
+
230
+ ### Алгоритм секционирования
231
+
232
+ ```mermaid
233
+ flowchart TD
234
+ RAW["Сырой транскрипт"] --> HAS_TS{"Есть\nтайм-коды?"}
235
+
236
+ HAS_TS -->|"Да"| TS_SPLIT["Анализ пауз и смены тем:<br/>1. Паузы > 5 сек = boundary candidate<br/>2. Смена спикера = boundary<br/>3. Тематический сдвиг (keyword analysis)"]
237
+ HAS_TS -->|"Нет"| PARA_SPLIT["Анализ параграфов:<br/>1. Двойной перенос строки = boundary<br/>2. Каждые 500-800 слов если нет переносов<br/>3. Markdown заголовки (#) = boundary"]
238
+
239
+ TS_SPLIT --> SECTIONS["Массив секций"]
240
+ PARA_SPLIT --> SECTIONS
241
+
242
+ SECTIONS --> SPEAKERS{"Определение\nспикеров"}
243
+
244
+ SPEAKERS -->|"Именованные<br/>(Host:, Guest:)"| NAMED["Именованные спикеры"]
245
+ SPEAKERS -->|"Неявные<br/>(чередование)"| UNNAMED["Speaker A, Speaker B"]
246
+ SPEAKERS -->|"Один спикер"| SINGLE["Без меток спикеров"]
247
+
248
+ NAMED --> QUOTES["Извлечение ключевых цитат:<br/>- Длинные предложения (> 20 слов)<br/>- Вопросительные предложения<br/>- Предложения с числами/статистикой"]
249
+ UNNAMED --> QUOTES
250
+ SINGLE --> QUOTES
251
+
252
+ QUOTES --> OUTPUT["Output:<br/>sections[], speakers[],<br/>timestamps[], quotes[]"]
253
+ ```
254
+
255
+ ### Формат секции (внутренний)
256
+
257
+ ```json
258
+ {
259
+ "id": "section-03",
260
+ "title": "Main Discussion Part 1",
261
+ "startTime": 225,
262
+ "endTime": 372,
263
+ "speaker": "Guest",
264
+ "wordCount": 1204,
265
+ "content": "...",
266
+ "timestamps": [
267
+ { "time": 225, "label": "3:45", "text": "Let me explain..." },
268
+ { "time": 245, "label": "4:05", "text": "The key insight is..." }
269
+ ],
270
+ "quotes": [
271
+ { "text": "The key insight is that...", "time": 245 }
272
+ ]
273
+ }
274
+ ```
275
+
276
+ ### Speaker Detection
277
+
278
+ ```
279
+ Паттерн 1: Явные метки
280
+ "Host:" / "Guest:" / "Dr. Smith:" -> Именованные
281
+
282
+ Паттерн 2: SRT/VTT метаданные
283
+ <v Speaker 1> -> Извлечь имена из voice tags
284
+
285
+ Паттерн 3: Чередование
286
+ Абзац 1 -> Speaker A
287
+ Абзац 2 -> Speaker B (если стиль отличается)
288
+ Абзац 3 -> Speaker A (возврат)
289
+
290
+ Паттерн 4: Монолог
291
+ Один голос -> Без меток спикеров
292
+ ```
293
+
294
+ ---
295
+
296
+ ## 5. MODULE: Site Generation
297
+
298
+ ### Назначение
299
+
300
+ Трансформация структурированных данных (секции, спикеры, timestamps) в полноценную HTML-страницу с Tailwind CSS, SEO-тегами и семантической разметкой.
301
+
302
+ ### HTML Template Architecture
303
+
304
+ ```mermaid
305
+ graph TB
306
+ subgraph "HTML Document"
307
+ HEAD["head<br/>- charset, viewport<br/>- SEO meta (OG, Twitter, JSON-LD)<br/>- Tailwind CDN script<br/>- Font Awesome CDN<br/>- tailwind.config<br/>- Print stylesheet<br/>- CSP meta tag"]
308
+
309
+ BODY["body<br/>class: bg-white dark:bg-gray-900"]
310
+
311
+ subgraph "Layout"
312
+ SKIP["a.skip-nav<br/>(screen-reader only)"]
313
+ NAV["nav<br/>- Title<br/>- Dark mode toggle<br/>- Search button<br/>- Hamburger (mobile)"]
314
+ PROGRESS["div.progress-bar<br/>(reading progress)"]
315
+
316
+ subgraph "Content area"
317
+ ASIDE["aside<br/>Table of Contents<br/>(sticky sidebar desktop,<br/>drawer mobile)"]
318
+ MAIN["main<br/>- Stats bar<br/>- YouTube embed (optional)<br/>- Section 1..N<br/> - Section heading<br/> - Timestamp links<br/> - Speaker labels<br/> - Transcript text<br/> - Copy quote buttons"]
319
+ end
320
+
321
+ FOOTER["footer<br/>- Credits<br/>- Print button<br/>- Stats"]
322
+ end
323
+
324
+ BTT["button#back-to-top<br/>(floating)"]
325
+
326
+ SEARCH_MODAL["div#search-modal<br/>- Input field<br/>- Results count<br/>- Navigation arrows"]
327
+
328
+ JS["script<br/>- Dark mode logic<br/>- Search logic<br/>- TOC scroll-spy<br/>- YouTube sync<br/>- Copy logic<br/>- Back-to-top<br/>- Progress bar"]
329
+ end
330
+ ```
331
+
332
+ ### Tailwind Configuration
333
+
334
+ ```javascript
335
+ tailwind.config = {
336
+ darkMode: 'class',
337
+ theme: {
338
+ extend: {
339
+ colors: {
340
+ primary: {
341
+ 50: '#eef2ff',
342
+ 100: '#e0e7ff',
343
+ 200: '#c7d2fe',
344
+ 300: '#a5b4fc',
345
+ 400: '#818cf8',
346
+ 500: '#6366f1',
347
+ 600: '#4f46e5',
348
+ 700: '#4338ca',
349
+ 800: '#3730a3',
350
+ 900: '#312e81',
351
+ 950: '#1e1b4e'
352
+ }
353
+ }
354
+ }
355
+ }
356
+ }
357
+ ```
358
+
359
+ Цвета `primary` автоматически заменяются на выбранную тему (indigo, emerald, rose, etc.).
360
+
361
+ ### SEO Meta Generation
362
+
363
+ ```mermaid
364
+ graph LR
365
+ SOURCE{"Тип<br/>источника"} -->|"YouTube"| YT_SEO["og:type = video<br/>JSON-LD: VideoObject<br/>og:image = thumbnail<br/>og:video = embed URL"]
366
+ SOURCE -->|"Текст"| TEXT_SEO["og:type = article<br/>JSON-LD: Article<br/>og:image = placeholder<br/>article:word_count"]
367
+ ```
368
+
369
+ ---
370
+
371
+ ## 6. MODULE: Interactivity
372
+
373
+ ### Назначение
374
+
375
+ Добавление интерактивных JavaScript-фич к сгенерированному HTML. Все фичи реализованы на vanilla JS без фреймворков и без build-шагов.
376
+
377
+ ### Архитектура фич
378
+
379
+ ```
380
+ +-- Dark Mode
381
+ | +-- Toggle button (sun/moon icons)
382
+ | +-- CSS class on <html> element
383
+ | +-- localStorage persistence
384
+ | +-- System preference detection (prefers-color-scheme)
385
+ |
386
+ +-- Search (Ctrl+K)
387
+ | +-- Modal dialog
388
+ | +-- Debounced input (300ms)
389
+ | +-- Regex-based matching (escapeRegex)
390
+ | +-- <mark> tag highlighting
391
+ | +-- Result count display
392
+ | +-- Enter/Shift+Enter navigation
393
+ | +-- Escape to close
394
+ |
395
+ +-- Table of Contents
396
+ | +-- Desktop: sticky sidebar
397
+ | +-- Mobile: hamburger drawer
398
+ | +-- IntersectionObserver scroll-spy
399
+ | +-- Active section highlighting
400
+ | +-- Click-to-scroll with smooth behavior
401
+ |
402
+ +-- YouTube Sync
403
+ | +-- iframe API (enablejsapi=1)
404
+ | +-- data-seek attributes on timestamp links
405
+ | +-- Event delegation for clicks
406
+ | +-- postMessage for seekTo()
407
+ | +-- Origin restriction on message handler
408
+ |
409
+ +-- Copy Quote
410
+ | +-- data-copy attributes on buttons
411
+ | +-- Clipboard API (navigator.clipboard.writeText)
412
+ | +-- Visual feedback (button text change, timeout reset)
413
+ | +-- Fallback: document.execCommand('copy')
414
+ |
415
+ +-- Back-to-Top
416
+ | +-- Floating button (fixed position)
417
+ | +-- Appears on scroll > 300px
418
+ | +-- Smooth scroll to top
419
+ |
420
+ +-- Progress Bar
421
+ | +-- Fixed position at top of page
422
+ | +-- Width = scrollY / (scrollHeight - clientHeight) * 100%
423
+ | +-- Primary color fill
424
+ |
425
+ +-- Reading Stats
426
+ | +-- Word count (computed from transcript text)
427
+ | +-- Reading time (wordCount / 200)
428
+ | +-- Section count
429
+ | +-- Speaker count
430
+ ```
431
+
432
+ ### Event Delegation Pattern
433
+
434
+ Все интерактивные элементы используют единый паттерн event delegation через `data-*` атрибуты:
435
+
436
+ ```javascript
437
+ document.addEventListener('click', function(e) {
438
+ // YouTube timestamp sync
439
+ const seekTarget = e.target.closest('[data-seek]');
440
+ if (seekTarget) {
441
+ e.preventDefault();
442
+ const seconds = parseInt(seekTarget.dataset.seek);
443
+ if (player && player.seekTo) {
444
+ player.seekTo(seconds, true);
445
+ }
446
+ return;
447
+ }
448
+
449
+ // Copy quote
450
+ const copyTarget = e.target.closest('[data-copy]');
451
+ if (copyTarget) {
452
+ e.preventDefault();
453
+ const text = copyTarget.dataset.copy;
454
+ navigator.clipboard.writeText(text).then(function() {
455
+ const original = copyTarget.textContent;
456
+ copyTarget.textContent = strings.copy_success;
457
+ setTimeout(function() { copyTarget.textContent = original; }, 2000);
458
+ });
459
+ return;
460
+ }
461
+
462
+ // TOC section navigation
463
+ const tocTarget = e.target.closest('[data-section]');
464
+ if (tocTarget) {
465
+ e.preventDefault();
466
+ const sectionId = tocTarget.dataset.section;
467
+ document.getElementById(sectionId).scrollIntoView({ behavior: 'smooth' });
468
+ return;
469
+ }
470
+
471
+ // Dark mode toggle
472
+ if (e.target.closest('#dark-mode-toggle')) {
473
+ toggleDarkMode();
474
+ return;
475
+ }
476
+ });
477
+ ```
478
+
479
+ Этот паттерн:
480
+ 1. Не использует inline event handlers (безопасно для CSP)
481
+ 2. Работает с динамически добавленными элементами
482
+ 3. Минимизирует количество event listeners
483
+ 4. Легко расширяется новыми `data-*` атрибутами
484
+
485
+ ### Search Implementation
486
+
487
+ ```mermaid
488
+ sequenceDiagram
489
+ actor U as Пользователь
490
+ participant I as Input Field
491
+ participant D as Debounce (300ms)
492
+ participant S as performSearch()
493
+ participant DOM as DOM
494
+
495
+ U->>I: Ctrl+K (открыть modal)
496
+ U->>I: Ввод текста "machine learning"
497
+
498
+ I->>D: onChange event
499
+ Note over D: Ждём 300ms без новых событий
500
+
501
+ D->>S: performSearch("machine learning")
502
+
503
+ S->>S: escapeRegex("machine learning")
504
+ S->>S: new RegExp(escaped, 'gi')
505
+
506
+ S->>DOM: Удалить все <mark> теги
507
+ S->>DOM: Найти совпадения в .transcript-text
508
+ S->>DOM: Обернуть совпадения в <mark>
509
+ S->>DOM: Обновить счётчик: "Найдено: 12"
510
+ S->>DOM: Скролл к первому совпадению
511
+
512
+ U->>I: Enter (следующий результат)
513
+ I->>DOM: Скролл к следующему <mark>
514
+
515
+ U->>I: Escape (закрыть)
516
+ I->>DOM: Удалить все <mark>
517
+ I->>DOM: Скрыть modal
518
+ ```
519
+
520
+ ### IntersectionObserver Scroll-Spy
521
+
522
+ ```javascript
523
+ const observer = new IntersectionObserver(function(entries) {
524
+ entries.forEach(function(entry) {
525
+ if (entry.isIntersecting) {
526
+ // Убрать подсветку со всех TOC-элементов
527
+ document.querySelectorAll('[data-section]').forEach(function(el) {
528
+ el.classList.remove('bg-primary-100', 'dark:bg-primary-900', 'font-bold');
529
+ });
530
+ // Подсветить текущий
531
+ const tocLink = document.querySelector('[data-section="' + entry.target.id + '"]');
532
+ if (tocLink) {
533
+ tocLink.classList.add('bg-primary-100', 'dark:bg-primary-900', 'font-bold');
534
+ }
535
+ }
536
+ });
537
+ }, {
538
+ rootMargin: '-20% 0px -70% 0px',
539
+ threshold: 0
540
+ });
541
+
542
+ document.querySelectorAll('section[id^="section-"]').forEach(function(section) {
543
+ observer.observe(section);
544
+ });
545
+ ```
546
+
547
+ ---
548
+
549
+ ## 7. MODULE: Deploy
550
+
551
+ ### Назначение
552
+
553
+ Генерация конфигурации для деплоя сайта. Основная цель -- GitHub Pages через `docs/` директорию.
554
+
555
+ ### Архитектура деплоя
556
+
557
+ ```mermaid
558
+ graph TD
559
+ SITE["docs/index.html"] --> GIT["git add docs/"]
560
+ GIT --> PUSH["git push origin main"]
561
+ PUSH --> GH["GitHub Repository"]
562
+ GH --> PAGES["GitHub Pages<br/>Settings > Pages<br/>Source: main, /docs"]
563
+ PAGES --> CDN["GitHub CDN"]
564
+ CDN --> USER["Пользователь<br/>https://user.github.io/repo/"]
565
+
566
+ SITE --> ROBOTS["docs/robots.txt"]
567
+ SITE --> SITEMAP["docs/sitemap.xml"]
568
+ ```
569
+
570
+ ### GitHub Actions автоматизация (опционально)
571
+
572
+ ```yaml
573
+ # .github/workflows/deploy-pages.yml
574
+ name: Deploy Pages
575
+ on:
576
+ push:
577
+ branches: [main]
578
+ paths: ['docs/**']
579
+
580
+ permissions:
581
+ pages: write
582
+ id-token: write
583
+
584
+ jobs:
585
+ deploy:
586
+ environment:
587
+ name: github-pages
588
+ url: ${{ steps.deployment.outputs.page_url }}
589
+ runs-on: ubuntu-latest
590
+ steps:
591
+ - uses: actions/checkout@v4
592
+ - uses: actions/configure-pages@v4
593
+ - uses: actions/upload-pages-artifact@v3
594
+ with:
595
+ path: docs/
596
+ - id: deployment
597
+ uses: actions/deploy-pages@v4
598
+ ```
599
+
600
+ ---
601
+
602
+ ## 8. MODULE: Verification
603
+
604
+ ### Назначение
605
+
606
+ Валидация сгенерированного сайта по 7 категориям: HTML, JavaScript, CSS, SEO, Accessibility, Security, Performance.
607
+
608
+ ### Архитектура проверок
609
+
610
+ ```mermaid
611
+ graph TD
612
+ HTML_FILE["docs/index.html"] --> HTML_CHECK["HTML Checks (8)"]
613
+ HTML_FILE --> JS_CHECK["JS Checks (6)"]
614
+ HTML_FILE --> CSS_CHECK["CSS Checks (4)"]
615
+ HTML_FILE --> SEO_CHECK["SEO Checks (5)"]
616
+ HTML_FILE --> A11Y_CHECK["A11y Checks (5)"]
617
+ HTML_FILE --> SEC_CHECK["Security Checks (4)"]
618
+ HTML_FILE --> PERF_CHECK["Performance Checks (3)"]
619
+
620
+ HTML_CHECK --> REPORT
621
+ JS_CHECK --> REPORT
622
+ CSS_CHECK --> REPORT
623
+ SEO_CHECK --> REPORT
624
+ A11Y_CHECK --> REPORT
625
+ SEC_CHECK --> REPORT
626
+ PERF_CHECK --> REPORT
627
+
628
+ REPORT["Verification Report<br/>35 total checks"]
629
+ REPORT --> PASS{"Все<br/>прошли?"}
630
+ PASS -->|"Да"| DONE["PIPELINE COMPLETE"]
631
+ PASS -->|"Нет"| FIX["Отчёт с ошибками<br/>+ рекомендации исправления"]
632
+ ```
633
+
634
+ ### Полный перечень проверок
635
+
636
+ **HTML (8 проверок):**
637
+
638
+ | ID | Проверка |
639
+ |----|---------|
640
+ | HTML-01 | Валидная HTML5 структура (DOCTYPE, html, head, body) |
641
+ | HTML-02 | Все теги правильно закрыты |
642
+ | HTML-03 | Нет deprecated атрибутов (align, bgcolor, etc.) |
643
+ | HTML-04 | Атрибут lang на html элементе |
644
+ | HTML-05 | Charset meta tag (UTF-8) |
645
+ | HTML-06 | Viewport meta tag |
646
+ | HTML-07 | Семантические элементы (nav, main, aside, footer) |
647
+ | HTML-08 | Уникальные id атрибуты (нет дубликатов) |
648
+
649
+ **JavaScript (6 проверок):**
650
+
651
+ | ID | Проверка |
652
+ |----|---------|
653
+ | JS-01 | Нет синтаксических ошибок (парсинг скрипт-блока) |
654
+ | JS-02 | Event delegation (нет inline handlers) |
655
+ | JS-03 | escapeHtml() функция присутствует |
656
+ | JS-04 | escapeRegex() функция присутствует |
657
+ | JS-05 | Нет eval(), document.write() |
658
+ | JS-06 | Нет innerHTML с пользовательскими данными без escapeHtml |
659
+
660
+ **CSS (4 проверки):**
661
+
662
+ | ID | Проверка |
663
+ |----|---------|
664
+ | CSS-01 | Tailwind CDN или inline CSS загружен |
665
+ | CSS-02 | Dark mode классы присутствуют (dark:bg-*, dark:text-*) |
666
+ | CSS-03 | Print stylesheet присутствует (@media print) |
667
+ | CSS-04 | Responsive utilities (sm:, md:, lg:) используются |
668
+
669
+ **SEO (5 проверок):**
670
+
671
+ | ID | Проверка |
672
+ |----|---------|
673
+ | SEO-01 | Open Graph теги (og:title, og:description, og:image) |
674
+ | SEO-02 | Twitter Card теги |
675
+ | SEO-03 | JSON-LD structured data (Article или VideoObject) |
676
+ | SEO-04 | Canonical URL |
677
+ | SEO-05 | robots.txt и sitemap.xml сгенерированы |
678
+
679
+ **Accessibility (5 проверок):**
680
+
681
+ | ID | Проверка |
682
+ |----|---------|
683
+ | A11Y-01 | Skip-nav ссылка в начале body |
684
+ | A11Y-02 | ARIA roles на навигации и основном контенте |
685
+ | A11Y-03 | Keyboard navigation для search (Escape для закрытия) |
686
+ | A11Y-04 | aria-label на иконических кнопках |
687
+ | A11Y-05 | Контрастность текста (Tailwind default палитра проверена) |
688
+
689
+ **Security (4 проверки):**
690
+
691
+ | ID | Проверка |
692
+ |----|---------|
693
+ | SEC-01 | Нет inline event handlers (onclick, onload, onerror) |
694
+ | SEC-02 | SRI хеши на CDN-ресурсах |
695
+ | SEC-03 | CSP meta-тег |
696
+ | SEC-04 | postMessage origin проверка |
697
+
698
+ **Performance (3 проверки):**
699
+
700
+ | ID | Проверка |
701
+ |----|---------|
702
+ | PERF-01 | HTML размер < 200 KB |
703
+ | PERF-02 | Нет render-blocking ресурсов (кроме Tailwind CDN) |
704
+ | PERF-03 | Изображения с lazy loading (если есть) |
705
+
706
+ ---
707
+
708
+ ## 9. Поток данных (Data Flow)
709
+
710
+ ### End-to-end pipeline
711
+
712
+ ```mermaid
713
+ flowchart LR
714
+ subgraph "Input"
715
+ YT["YouTube URL"]
716
+ TXT["Text"]
717
+ FILE["File"]
718
+ end
719
+
720
+ subgraph "Step 1: Input Analysis"
721
+ YTDLP["yt-dlp"]
722
+ LANG["Language<br/>Detection"]
723
+ META["Metadata"]
724
+ end
725
+
726
+ subgraph "Step 2: Content Parsing"
727
+ SPLIT["Section<br/>Splitting"]
728
+ SPEAK["Speaker<br/>Detection"]
729
+ TS["Timestamp<br/>Mapping"]
730
+ QUOTE["Quote<br/>Extraction"]
731
+ end
732
+
733
+ subgraph "Step 3: Site Generation"
734
+ TMPL["HTML<br/>Template"]
735
+ TW["Tailwind<br/>Config"]
736
+ SEOG["SEO<br/>Meta Tags"]
737
+ end
738
+
739
+ subgraph "Step 4: Interactivity"
740
+ SEARCH["Search JS"]
741
+ TOC["TOC JS"]
742
+ DM["Dark Mode JS"]
743
+ SYNC["YouTube Sync JS"]
744
+ COPY["Copy JS"]
745
+ end
746
+
747
+ subgraph "Step 5: Deploy"
748
+ ROBOT["robots.txt"]
749
+ SMAP["sitemap.xml"]
750
+ end
751
+
752
+ subgraph "Step 6: Verification"
753
+ CHECK["35 Checks"]
754
+ end
755
+
756
+ subgraph "Output"
757
+ HTML["docs/index.html"]
758
+ end
759
+
760
+ YT --> YTDLP
761
+ TXT --> LANG
762
+ FILE --> LANG
763
+ YTDLP --> META
764
+ YTDLP --> LANG
765
+
766
+ META --> SPLIT
767
+ LANG --> SPLIT
768
+ SPLIT --> SPEAK
769
+ SPEAK --> TS
770
+ TS --> QUOTE
771
+
772
+ QUOTE --> TMPL
773
+ META --> SEOG
774
+ TMPL --> TW
775
+ TW --> SEOG
776
+
777
+ SEOG --> SEARCH
778
+ SEARCH --> TOC
779
+ TOC --> DM
780
+ DM --> SYNC
781
+ SYNC --> COPY
782
+
783
+ COPY --> ROBOT
784
+ ROBOT --> SMAP
785
+
786
+ SMAP --> CHECK
787
+ CHECK --> HTML
788
+ ```
789
+
790
+ ### Формат данных между шагами
791
+
792
+ | Шаг | Output | Формат |
793
+ |-----|--------|--------|
794
+ | 1 -> 2 | sourceType, metadata, rawTranscript, language | Internal object |
795
+ | 2 -> 3 | sections[], speakers[], timestamps[], quotes[] | Structured arrays |
796
+ | 3 -> 4 | htmlContent (string) | HTML string |
797
+ | 4 -> 5 | htmlWithJS (string), features[] | HTML string + feature list |
798
+ | 5 -> 6 | files (index.html, robots.txt, sitemap.xml) | File paths |
799
+ | 6 -> output | validationReport, status | Report + pass/fail |
800
+
801
+ ---
802
+
803
+ ## 10. Выбор технологического стека
804
+
805
+ ### Почему Tailwind CDN, а не другие CSS-решения?
806
+
807
+ | Альтернатива | Почему отвергнута |
808
+ |-------------|-------------------|
809
+ | Bootstrap CDN | Более тяжёлый (~200 KB CSS), менее гибкий для кастомизации |
810
+ | Plain CSS | Требует ~3x больше кода, сложнее поддерживать responsive и dark mode |
811
+ | Tailwind CLI | Требует Node.js для build-шага, противоречит zero-build философии |
812
+ | Inline styles | Не масштабируются, не поддерживают responsive и pseudo-классы |
813
+
814
+ Tailwind Play CDN -- единственное решение, которое сочетает мощность utility CSS с zero-build deployment.
815
+
816
+ ### Почему vanilla JS, а не React/Vue/Svelte?
817
+
818
+ | Альтернатива | Почему отвергнута |
819
+ |-------------|-------------------|
820
+ | React | Требует build (JSX -> JS), runtime ~130 KB, противоречит zero-build |
821
+ | Vue | Требует build или runtime compiler (~60 KB), избыточен для задачи |
822
+ | Svelte | Требует build (compile step), хотя компилируется в vanilla JS |
823
+ | Alpine.js | Ближайший кандидат (~15 KB), но добавляет ещё одну CDN-зависимость |
824
+ | jQuery | Устаревший, +87 KB, все нужные API есть в vanilla JS |
825
+
826
+ Vanilla JS достаточен для всех фич (search, dark mode, TOC, YouTube sync). Общий объём JS-кода: ~5-10 KB, что меньше, чем любой фреймворк.
827
+
828
+ ### Почему не React + Next.js + Vercel?
829
+
830
+ Это антитеза нашей архитектуры. Next.js требует:
831
+ - `npm install` (node_modules: ~200 MB)
832
+ - Build step (`next build`)
833
+ - Runtime server (SSR/ISR) или static export
834
+ - Framework lock-in
835
+ - Continuous deployment pipeline
836
+
837
+ Наше решение: один HTML-файл, открываемый в браузере.
838
+
839
+ ---
840
+
841
+ ## 11. Архитектура безопасности
842
+
843
+ ### XSS Prevention
844
+
845
+ Все пользовательские данные проходят через `escapeHtml()`:
846
+
847
+ ```
848
+ Транскрипт текст -> escapeHtml() -> innerHTML
849
+ Метаданные YouTube -> escapeHtml() -> innerHTML
850
+ Имена спикеров -> escapeHtml() -> innerHTML
851
+ Поисковые запросы -> escapeRegex() -> RegExp constructor
852
+ ```
853
+
854
+ Точки инъекции и их защита:
855
+
856
+ | Точка | Защита |
857
+ |-------|--------|
858
+ | Transcript content | `escapeHtml()` при вставке в DOM |
859
+ | Speaker names | `escapeHtml()` при вставке в DOM |
860
+ | Video title | `escapeHtml()` при вставке в DOM |
861
+ | Search input | `escapeRegex()` перед созданием RegExp |
862
+ | `data-*` атрибуты | Только числовые значения (timestamps) или pre-escaped |
863
+ | YouTube iframe src | Только `youtube.com/embed/` + alphanumeric video ID |
864
+
865
+ ### Event Delegation Security
866
+
867
+ ```
868
+ ЗАПРЕЩЕНО:
869
+ <button onclick="handleClick()"> -- inline handler
870
+ element.setAttribute('onclick', ...) -- dynamic inline handler
871
+
872
+ РАЗРЕШЕНО:
873
+ document.addEventListener('click', function(e) {
874
+ const target = e.target.closest('[data-action]');
875
+ ...
876
+ });
877
+ ```
878
+
879
+ ### SRI (Subresource Integrity)
880
+
881
+ Каждый CDN-ресурс включает `integrity` атрибут:
882
+
883
+ ```html
884
+ <script src="https://cdn.tailwindcss.com"
885
+ integrity="sha384-HASH"
886
+ crossorigin="anonymous"></script>
887
+ ```
888
+
889
+ ### postMessage Origin Restriction
890
+
891
+ ```javascript
892
+ window.addEventListener('message', function(event) {
893
+ // ОБЯЗАТЕЛЬНО: проверка origin
894
+ if (event.origin !== 'https://www.youtube.com') {
895
+ return; // Отклонить сообщения от других origins
896
+ }
897
+ // Обработка YouTube API events
898
+ });
899
+ ```
900
+
901
+ ---
902
+
903
+ ## 12. SEO архитектура
904
+
905
+ ### Тройная SEO-стратегия
906
+
907
+ ```
908
+ 1. Open Graph (Facebook, LinkedIn, Telegram, WhatsApp)
909
+ -> og:title, og:description, og:image, og:type, og:url
910
+
911
+ 2. Twitter Cards (Twitter/X)
912
+ -> twitter:card, twitter:title, twitter:description, twitter:image
913
+
914
+ 3. JSON-LD Structured Data (Google, Bing, Yandex)
915
+ -> @type: VideoObject (YouTube) или Article (text)
916
+ -> headline, description, datePublished, wordCount
917
+ -> transcript (для VideoObject)
918
+ ```
919
+
920
+ ### JSON-LD Architecture
921
+
922
+ ```mermaid
923
+ graph LR
924
+ SOURCE{"Тип<br/>источника"} -->|"YouTube"| VIDEO["@type: VideoObject"]
925
+ SOURCE -->|"Текст"| ARTICLE["@type: Article"]
926
+
927
+ VIDEO --> FIELDS_V["name, description,<br/>thumbnailUrl, uploadDate,<br/>duration, embedUrl,<br/>transcript"]
928
+
929
+ ARTICLE --> FIELDS_A["headline, description,<br/>datePublished, wordCount,<br/>articleBody"]
930
+
931
+ FIELDS_V --> JSONLD["script type=application/ld+json"]
932
+ FIELDS_A --> JSONLD
933
+ ```
934
+
935
+ ---
936
+
937
+ ## 13. Доступность (Accessibility)
938
+
939
+ ### Skip Navigation
940
+
941
+ ```html
942
+ <a href="#main-content" class="sr-only focus:not-sr-only focus:absolute focus:top-0 focus:left-0 focus:z-50 focus:bg-white focus:p-4">
943
+ Skip to main content
944
+ </a>
945
+ ```
946
+
947
+ ### ARIA Roles
948
+
949
+ ```html
950
+ <nav role="navigation" aria-label="Main navigation">
951
+ <main role="main" id="main-content">
952
+ <aside role="complementary" aria-label="Table of contents">
953
+ <footer role="contentinfo">
954
+ ```
955
+
956
+ ### Keyboard Navigation
957
+
958
+ | Клавиша | Действие |
959
+ |---------|---------|
960
+ | Ctrl+K / Cmd+K | Открыть поиск |
961
+ | Escape | Закрыть поиск / закрыть мобильное меню |
962
+ | Enter | Следующий результат поиска |
963
+ | Shift+Enter | Предыдущий результат поиска |
964
+ | Tab | Навигация между интерактивными элементами |
965
+
966
+ ### Контрастность
967
+
968
+ Tailwind default палитра обеспечивает WCAG AA контрастность:
969
+ - Текст `gray-900` на `white`: ratio 17.15:1
970
+ - Текст `gray-100` на `gray-900`: ratio 15.39:1
971
+ - Primary-600 на white: ratio > 4.5:1
972
+
973
+ ---
974
+
975
+ ## 14. Расширяемость
976
+
977
+ ### Кастомные темы
978
+
979
+ Создайте reference-файл с кастомной палитрой:
980
+
981
+ ```
982
+ .claude/skills/transcript-site-generator/references/custom-theme-corporate.md
983
+ ```
984
+
985
+ Содержимое:
986
+
987
+ ```markdown
988
+ # Custom Theme: Corporate
989
+
990
+ ## Tailwind Config Override
991
+
992
+ colors.primary = {
993
+ 50: '#f0fdf4',
994
+ ...
995
+ 900: '#14532d'
996
+ }
997
+
998
+ fontFamily.sans = ['Inter', 'system-ui']
999
+ ```
1000
+
1001
+ Использование:
1002
+
1003
+ ```
1004
+ /transcript-site [source] --theme custom-theme-corporate
1005
+ ```
1006
+
1007
+ ### Кастомные exercise types
1008
+
1009
+ Для обучающих транскриптов можно добавить интерактивные упражнения:
1010
+
1011
+ ```markdown
1012
+ # Custom Exercise: Quiz
1013
+
1014
+ ## HTML Template
1015
+ <div data-exercise="quiz" data-question="What was the main point?">
1016
+ <button data-answer="a">Option A</button>
1017
+ <button data-answer="b">Option B</button>
1018
+ </div>
1019
+
1020
+ ## JS Handler
1021
+ // Add to event delegation
1022
+ const exercise = e.target.closest('[data-answer]');
1023
+ if (exercise) { ... }
1024
+ ```
1025
+
1026
+ ### Кастомные verification checks
1027
+
1028
+ Добавьте проверки в `modules/verification.md`:
1029
+
1030
+ ```markdown
1031
+ ## Custom Checks
1032
+
1033
+ | ID | Проверка |
1034
+ |----|---------|
1035
+ | CUSTOM-01 | [Ваша проверка] |
1036
+ ```
1037
+
1038
+ ---
1039
+
1040
+ ## 15. Проектные решения и компромиссы
1041
+
1042
+ ### Почему один HTML-файл, а не SPA с роутингом?
1043
+
1044
+ Один файл проще деплоить, не требует серверного роутинга, работает через `file://`, не ломается при 404. Для транскриптов до 30K слов один файл достаточен. Multi-page chunking используется только для очень длинных транскриптов.
1045
+
1046
+ ### Почему Tailwind Play CDN, а не Tailwind CLI?
1047
+
1048
+ Tailwind CLI требует Node.js и build-шаг. Play CDN работает прямо в браузере. Документация Tailwind не рекомендует Play CDN для production, но для наших целей (50-100 KB HTML, посещаемость < 1000/день) это оправданный trade-off.
1049
+
1050
+ ### Почему event delegation, а не component-based?
1051
+
1052
+ Event delegation через `data-*` атрибуты:
1053
+ 1. Совместимо со строгим CSP (нет inline handlers)
1054
+ 2. Работает с одним event listener вместо десятков
1055
+ 3. Не требует framework для привязки событий
1056
+ 4. Прозрачно для отладки
1057
+
1058
+ ### Почему IntersectionObserver для scroll-spy?
1059
+
1060
+ Альтернативы:
1061
+ - `scroll` event + `getBoundingClientRect()` -- дорого по CPU, throttle необходим
1062
+ - `position: sticky` + CSS -- не даёт информации о текущей секции для TOC подсветки
1063
+
1064
+ IntersectionObserver -- нативный API, работает асинхронно, не блокирует main thread.
1065
+
1066
+ ### Почему не SSG (Hugo, Jekyll, Eleventy)?
1067
+
1068
+ SSG требуют установки, конфигурации, шаблонов. Наш скилл генерирует HTML напрямую через Claude Code -- это и есть "генератор статических сайтов", только AI-driven вместо template-driven.