Implement char-weighted median aggregation of per-span readability
scores into a page-level score stored in extraction_quality.readability.
Algorithm:
- Collect (score, char_count) pairs from spans
- Sort by score ascending
- Walk sorted list accumulating character counts
- Return score at half-total-char position
Acceptance criteria:
- Single span: returns its score
- Multiple spans: char-weighted median (longer spans count more)
- Empty page: returns 0.0
- All-perfect: returns 1.0
Closes: pdftract-oh30a
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>