Hooray! First, I split the UI into three columns (using another borderless table) to utilize as much screen space as possible. Previously, most of the screen was simply empty and yet scrolling was required to see the entire UI.
I shortened some UI elements like the pin mode grid, which no longer displays pins that cannot change mode at all (Serial RX/TX on pins 0 and 1, A0-A5), and I shrunk down the image grids from 32 pixels per image to 30.
Also, there are now step headers to guide users:
The step one header will update to include "uploading..." while an upload is in progress. Previously, the buttons would ask for a user port, then a promise would start which would compile the code for the Arduino and upload it, then finally reporting the result via alert(). This was a bit confusing as during that middle time there is no way to tell that an upload is in progress.
There is also now a system in place to detect changes to the Arduino code. A key in local storage keeps the SHA-1 hash of the Arduino code and is only updated if an attempt to upload is made using the buttons. If the hash in storage is not present or doesn't match the current hash of the code, a warning pops up asking the user to verify the code is correctly uploaded:
The warning disappears until page reload if the hide warning button is pressed, and disappears permanently until the next change in the Arduino code if the user attempts to upload the code.
I would also like to note that it took a lot of CSS to get all of this to work properly, but it is done.