- Practice finish now grants win/loss XP via IBattleXpService.GrantAsync
with BattleXpMode.Practice. Response fields (get_class_experience,
class_experience, class_level) reflect post-grant totals.
- Uses req.ClassId from wire; no BattleContext lookup needed.
- Test asserts default XpPerWin=100 crosses classexp.csv L1=50 threshold
→ Level=2 + Exp=50 carry, persists to Viewer.Classes.
- Added loss-XP test asserting default XpPerLoss=25 stays under threshold.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>