my final ELF binary is around 208kB
Yes, because ELF ain't raw machine code. It is a universal executable format which has relocation info, dynamic loading info, different secrions for read-only data, writable data and code, etc. Most of these are irrelevant on a microcontroller since it has no OS, no dynamic loading facilities, so most of the extra info can be stripped off.
the Intel Hex binary is about 41kB. AVRDUDE tells me it's uploading about 18kB.
Two reasons. One, an Intel hex file contains checksums on the end of each line. If you, using a reasonable average line length, cut these, you can expect the file to shrink by a few percents, for example to 36kB. Then, there's a reason Intel Hex files are named 'hex' files. They don't contain raw binary data but raw binary data in hexadecimal form - i. e. one real byte is encoded using two bytes. So when AVRdude uploads the code, it converts it to raw binary (that's what the AVRs processor can run), and then the data size is again decreased by 50%.