lcd menu help

I would change each "nthScreen" function to manage its own processes. So you call the nthScreen() function every single time through the loop. It then looks at what state it's in: has it just entered that screen? Is it time for a blink? Keep a few local variables inside the function as static so that it can remember what went on before.

For example...

void firstScreen(bool hasChanged)
{
  // call this hundreds of times per second.
  //hasChanged tells us that the overall screen state has changed, so we need to re-display the whole screen
  static unsigned long localLastMillis;
  static bool blinkStatus=true;
  const unsigned long blinkInterval = 1000; //milliseconds, interval between blinks
  if(hasChanged) {
    //Draw the full screen
    lcd.clear();
    lcd.setCursor(0, 0); // Column, line
    lcd.print("      MY INTRO      ");
    lcd.setCursor(0, 2);
    lcd.print("       SPLASH       ");
    lcd.setCursor(0, 3);
    lcd.print("       SCREEN       ");
  }
  if((millis()-localLastMillis > blinkInterval && blinkStatus) || hasChanged) {
    //either the timer expired or we've just changed the screen and we need to show the blinking text
    lcd.setCursor(0, 1);
    lcd.print("      BLINKING      ");
    blinkStatus = false;
    localLastMillis = millis();
  }
  if(millis()-localLastMillis > blinkInterval && !blinkStatus) {
    //time to blink the text off
    lcd.setCursor(0, 1);
    lcd.print("                    ");
    blinkStatus = true;
    localLastMillis = millis();
  }
  
}

Since these functions are being called all the time, you may even wish to put the button-handling code inside them. That way the same button can do different things depending on what screen you are on. (Do the debounce outside the screen functions.)