ffc8c31130
First step of breaking up the 2914-line server/index.js. Pulled out the zero-state, no-side-effects helpers: • sendEvent(res, event, data) — writes one SSE frame • extractVideoId(url) — YouTube URL → 11-char id • formatTime(seconds) — seconds → 'M:SS' or 'H:MM:SS' • parseTimestampedTranscript(text) — Gemini transcript text → entries[] • safeText(result) — robust .text getter for Gemini responses • retryGemini(fn, opts) — 503/429/network retry with linear backoff server/index.js: 2914 → 2828 lines. server/util.js : new, 113 lines. Smoke tested: server boots, /api/license-status responds. No behavior change.