Search ordered purely by date, so an event that matched only deep in its
description outranked a title match that happened to be further off — the
reported case was 'test' surfacing a holiday whose description contains
'protestantischer'.
Matching is now token-wise: the query splits on whitespace and every token
must appear in the title, location or description, in any order. EventSearchRanker
scores each token by field (title > location > description) and by position
(field start > word start > mid-word) and ranks an event by the weakest field
the query needed, falling back to the old nearest-first date order. Mid-word
matches still count so compounds keep working: 'termin' finds 'Zahnarzttermin'.
The final comparison also moved in-memory so case folds beyond ASCII ('ärzte'
now finds 'ÄRZTE'); SQL stays a pre-filter, substituting non-ASCII cased
letters with LIKE's single-character wildcard to stay a superset. Hits carry
their match spans and a description excerpt, which the row will render next.