I solved this by including even more redundant information into the request URL: For each public transport type, I'm now repeating the "city node" and "around node".
I don't believe this is the best solution, but it's working well:
http://overpass-api.de/api/interpreter?data=[out:json];node["name"="CITY"];node(around:15000)["name"="STATION"]["highway"="bus_stop"];node["name"="CITY"];node(around:15000)["name"="STATION"]["railway"~"tram_stop|station|subway"];out;