Update: Looks like I got caught up in a correlation that was not in fact the cause of the problem. Problem was actually an unrelated issue in how CSS files were deployed. See my answer below for details.
I have @font-face working well in WebKit (Safari and Chrome) and Opera, but not in Firefox 3.5 or IE 8.
Per recommendations by Google and others, I serve all static assets, including CSS, from a separate domain from my main site. If I serve everything from the same domain, it works fine in all browsers (note: this means that answers about CSS syntax are useless. I already have all of that figured out and working great. This is ONLY about the cross-domain issues).
If I serve CSS and font files from my static assets domain, and have the static assets server set the appropriate access-control header (Access-Control-Allow-Origin), which should work, it works everywhere except FF 3.5 and IE.
What do I need to do to make this work?
The best answer I've discovered so far, in hopes that it helps someone else:
As far as I can tell, the key issue is whether the CSS file (not the font file) is loaded cross-domain. If I load the CSS file with the @font-face declarations from my static assets domain, nothing I do will make the fonts work in FF or IE, regardless of the access control headers. If I load the CSS file from the same domain as the page, or I just move my @font-face declarations into a style block in the page head, then it works in all browsers (I can even load the font files cross-domain as long as I have the access control header set).
To summarize: AFAICT, FF 3.5 and IE 8 will refuse to honor @font-face declarations in a cross-domain-loaded CSS file, no matter what.
I would love to be corrected on this if anyone knows better and can point out what else I might be doing wrong.
Indeed, I was wrong. It turns out the CSS-compressor we were using for deploying assets to be served from the dedicated domain was wrapping the entire chunk of CSS with "@media screen { ... }". I carefully compared the @font-face rules to be sure the compressor didn't mess with them, but never checked the very beginning and end of the CSS file to catch that wrapping. When I switched to serving same-domain, that wrapping didn't happen.
As it turns out, IE and Firefox do not honor @font-face declarations wrapped inside @media: Safari, Chrome and Opera do.
Sigh.