v3 rewrite: - _call_openrouter(): single HTTP call, never raises, always returns dict - Removed Gemini SDK, _retry_with_backoff, _generate dispatcher - Image resize (max 1024px JPEG) stays - Detailed logging: ai.call.start → ai.call.response → ai.call.success/timeout - All error paths return structured dicts, never propagate exceptions