What do you suggest?
your whole construct depends on runOnce not displaying to the menu but this does not prevent entering in the first waiting while() in case of an issue and so you don’t see all what’s happening.
If I had to debug this I would:
1] Just to be sure to capture all cases I would change
else if (menu >= 'e')
{
Serial.println ("Choose Options A through D");
}
into
else
{
Serial.println ("Choose Options A through D");
}
numbers being before letters in ASCII you would see if you end up in the top of the loop expecting a number
2] I would also add serial.print to show where you are in the code
If I had to write this I would:
3] actually rewrite the whole thing differently, as a small state machine: you should not have two active waiting while() blocking your code. the loop should just spin always, listening for Serial and you could have a variable memorizing at which menu level you are and the state machine deciding what is the next menu based on current menu and character entry