I discovered that I can append an option to the ft query that allows wildcards at the start of the search string. I added a searchClauseOptions variable
let $searchClauseOptions := '<options><leading-wildcard>yes</leading-wildcard></options>'
and then passed that in as an argument to the search clause:
fn:concat('[tei:text/tei:body[ft:query(.,"', $searchterm, '",', $searchClauseOptions, ')]]')
There's a lot of escaping of string delimiters as that search clause itself ends up as a string which is eval'd to generate the results.