Code which can be fixed easily isn't "legacy". Code where a replacement would need to be bug-for-bug compatible in order to avoid breaking things is "legacy".
You could be writing legacy code today.
But other things change. The library changed its interface. You coded your crypto lib when MAC-then-Ecrypt was all the rage. You aren't handling HTTP/1.0 headers. Windows 7 doesn't even have those 16-bit drivers any more.
I hate the "throw everything away and rewrite with the brand new frame work every two years" that some parts of the web development community seem to have (and then get angered when you ask about a version over six months old because it is what you installed everywhere). But sometimes software does rot if it's old and no one is trying to keep it up-to-date.
The great thing about this definition is that it doesn't matter how old the code is - if it can be changed without worry about introducing unwanted behaviour because of test coverage, then it's not legacy.
It also means that you can write new legacy code right now!
I once made the argument that a team within my organization was actively producing new legacy code. It wasn't my most diplomatic moment.
It's always the function that's been rewritten twenty times that gets labelled as legacy code.