The libraries from Adafruit and elsewhere assume you are using the Arduino IDE. If you choose not to use that you will have difficulties compiling your own code. The header files you ask about are in the IDE download. You can always grab a copy of that and put the appropriate .h files into your "include" search path.
However, in my io.h file, there is a long list of #if defined (AVR_various_names).
Well, do a test compile using the Arduino IDE, using "verbose compiling" and see what defines are generated for your particular board (which you haven't mentioned). There won't be that many of them. Then you can put that on the build commands for your IDE.
Or can I avoid all this and somehow create C++ classes independently?
You can create C++ classes inside the Arduino IDE. I don't see how this relates to your other issues.
The Arduino IDE basically generates build commands for avr-g++ - it isn't some horrible beast you should avoid using.
Answer from Nick Gammon on Stack ExchangeCreating a library of C++ classes for Arduino; How to #include "Arduino.h", "WProgram.h"? - Arduino Stack Exchange
What is Wprogram.h library?
header - cannot open source file "WProgram.h" in VSCode - Arduino Stack Exchange
fatal error: WProgram.h: No such file or directory #include "WProgram.h"
The libraries from Adafruit and elsewhere assume you are using the Arduino IDE. If you choose not to use that you will have difficulties compiling your own code. The header files you ask about are in the IDE download. You can always grab a copy of that and put the appropriate .h files into your "include" search path.
However, in my io.h file, there is a long list of #if defined (AVR_various_names).
Well, do a test compile using the Arduino IDE, using "verbose compiling" and see what defines are generated for your particular board (which you haven't mentioned). There won't be that many of them. Then you can put that on the build commands for your IDE.
Or can I avoid all this and somehow create C++ classes independently?
You can create C++ classes inside the Arduino IDE. I don't see how this relates to your other issues.
The Arduino IDE basically generates build commands for avr-g++ - it isn't some horrible beast you should avoid using.
The #if defined (AVR_<various_names>) you see here have nothing to do
with Arduino: this is the avr-libc trying to import the IO register
definitions for the AVR chip you are using. Whenever you compile an AVR
program, you pass the option -mmcu=<mcu-name> to avr-gcc, and it
automatically defines the proper macro. For example, the Arduino Uno is
built around an ATmega328P. Programs for the Uno must then be compiled
with -mmcu=atmega328p, which makes the compiler define
__AVR_ATmega328P__, which directs the avr-libc to
#include <avr/iom328p.h>, which contains all the IO register
definitions for that chip.
As for the ARDUINO macro, this one is defined by the Arduino IDE to be
the version of you Arduino installation, without the dots. For example,
if you downloaded the core files from Arduino 1.8.2, then you should
compile with -DARDUINO=182.
Also, you should avoid copying all the library headers to your project,
and instead use the proper -I options. And don't forget to tell the
compiler your clock frequency with -DF_CPU=..., as it is needed by
some avr-libc and Arduino stuff.
In the end, you will see you need quite a lot of compiler options to properly compile Arduino code. The easiest way to do it is definitely to use the Arduino IDE, as it handles all this for you. If you don't like the IDE (understandable...), you could try Arduino Builder, which should be entirely compatible. If you want to compile from just a Makefile, I recommend you take a look at Sudar Muthu’s Arduino Makefile.
I landed here in the same position as you, and after researching the comments mentioning -DARDUINO=10813 and some more googling I found: https://github.com/microsoft/vscode-arduino/issues/1148
This led me to adding one more line to defines in my c_cpp_properties.json
and this also removed the squiggly!
{
"configurations": [
{
...
"defines": [
"USBCON",
"ARDUINO=10813"
],
...
}
],
}```
The answer
Like I said in the question, I found the answer after doing some searching while typing up the question itself and I want to explain it for future squiggle-haters :)
WProgram.h vs Arduino.h
I did a bunch of searching to try to track down what's going on and I eventually found this helpful (and depending on the veracity of the source, kind of sad) bit of history:
There is history of the arduino project not everyone was aware of or supposed to know. I only this much: this all started with some graduate student(s) that created the wiring platform and IDE, called wiring board and wiring "programming language". This project is still active with active users like the arduino project. Then the arduino folks decide to create the arduino project based on wiring project so they took the wiring IDE (which took from the original Processing IDE), including all the libraries etc. and created the first Arduino board (slightly different than wiring board, cheaper!) called it arduino. Arduino project has not very positively acknowledged the wiring project as the source of their project and wiring folks didn't take it very well.
Now, that WProgram.h, is a definition file created by and for the wiring project and board. That's why it has a W on it. It has been in Arduino IDE since its beginning and was replaced by Arduino.h only recently when Arduino 1.0 was released. Now all Arduino 1.0+ IDE will use Arduino.h and not WProgram.h so if you have that plus some other old stuff, you will have to make changes to work with Arduino 1.0+ IDE.
The temp fix
With that in mind I dove into the source file for the Adafruit_MPR121.h library and found where it includes the WProgram.h header file and commented it out.

It's also worth pointing out that the pre-compiler conditional here supports the renaming of the file in newer versions of Arduino.

I labeled this section of the answer as "The temp fix" because it involves modifying a 3rd party dependency which is normally not a great idea. Yeah it fixes it now, but as soon as I need to update this library that edit is going to get blown away and I'd need to manually do it again. In this case the update is pretty minimal so maybe that's no big deal, but if the fix was more involved, like a heavy edit, that would be a real big pain in the butt and could cause other unforeseen consequences (and I played half-life as a kid so I know that's not good).
The better fix
Normally I would say the better fix for this would be to clone the source repository, make the fix there, and do a pull request so the dependency itself gets updated at the source (if someone approves and merges the PR).
But this is a bit different, the conditional in there is actually fine as it adds backwards compatibility. It's there so that the library can support both pre-1.0 and post-1.0 arduino IDE versions. If we did a PR to cut out the WProgram.h reference we'd add in breaking code for anyone on the older versions.
So, the better solution is to appease my local compiler.
We know that the Arduino.h header for all intents and purposes is the same as the WProgram.h, so a almost-full-proof solution would be to fake out the WProgram.h file on my computer to appease the compiler.

An important part to note here is that to make sure I faked it out correctly I went to the arduino repository, scrolled back through the tags, found the last tag before they switched to 1.0+, and found the WProgram.h file. Once there I grabbed the same pre-compiler check and definition for the WProgram header so I could be sure I did the correct define for the WProgram name.

This feels like a bit of overkill because it protects me from other headers being included with the same string defined, but if that happened it would be because I have the WProgram file anyway, but I figured if I was going to fake it out I'd do it right.
This could backfire if I include a library that only includes WProgram.h and not the Arduino.h in that arduino version check conditional, but this would 100% be the case for a correction and pull request for that library.
Summary
So now I know that the Arduino.h file is the reason I'm able to compile everything correctly even with the red squiggle, I have a faked out WProgram.h so that my compiler can find something when looking for the file and, most importantly, I no longer need to look at those red squiggles under the includes :)

Next step, figure out the same thing for Sam.h :P
The header file either doesn't exist or the path to it's directory isn't in the includes path. Check Project -> Properties -> c/c++ build -> Settings -> includes -> include paths and make sure the folder that Wprogram.h is in is included in that list.
A Google search suggests that Wprogram.h has been renamed to Arduino.h. Try including that file instead.