Or is there some voodoo by which the ANSI sequences get stripped from the output when redirected to a file?
Have you double checked with s hex editor what is in the txt file? Suppose it could also be your text editor that doesn't want to render those codes.
Not quite, but programs in general use some voodoo to detect when they are being redirected and won't output ANSI codes when they detect that.
Often there will be a flag to enable/disable color, or let it detect when color is desired. On Linux ls accepts the --color=WHEN parameter, where WHEN can be always (`ls --color=always > ls-with-ansi-codes.txt` will output color codes), it can be never (just don't output ANSI codes, no matter whether you detect output redirection) or it can be auto (will show colors when you execute `ls --color=auto` but not when you do `ls --color=auto > ls-without-ansi-codes.txt`).
Often times libraries that let you specify output color will helpfully query the capabilities of the output device, and avoid writing the control codes if it’s (for example) a plain text file.
On posix platforms, there's an API to check if a given file handle is a tty or not. https://github.com/corasaurus-hex/isatty/blob/main/isatty.c is an example of using the API, in a Janet context.
I assume that .NET's support for Linux/macOS is using that API decide if it should strip color codes or not.
I'm 99% sure it's inserting ANSI escape codes (I'm maintaining a terminal emulator myself, and really that's how everything works), but I could of course be wrong.
I am thinking that .foregroundColor and .backgroundColor do the same thing via legacy emulation in conhost.
Each screen location was two bytes, one byte for the character value, and one for the character attributes which were a set of bits that controlled red, green, blue and intensity for both the foreground color and background color.
Then you could write routines that would fill in a rectangular region with a color, scroll the text of a region up or down, and do all sorts of other windowy things. There were also interrupt routines you could call that did some of these, and certainly routines in Crt that did some of this. Then you were on your way to developing your own TUI library!
Alternatively, you would issue an interrupt call to put the screen into 320x200 256 color mode, get the address of that buffer ($B800 if memory serves), similarly overlay it with a typed grid, then start poking byte values in and getting all sorts of nice colors out of it. Super fun!!
I looked recently to see if an equivalent of Crt is still out there, but it doesn't look like any of the modern Pascal versions support it.
Short version: there is support for ANSI and VT sequences in the Windows console (which relatively recently got substantially expanded), but that's not what it speaks "natively"-- for Win32 console applications, there's a native console API that works by passing IOCTLs back and forth between the app and console driver.
(If you're writing a terminal emulator for Windows, you don't necessarily see this-- the new ConPTY mechanism you use to build these as of Windows 10 abstracts away the Windows specifics so you see text and VT sequences just as you would on *nix.)