How do you make a switch case run until another serial input is detected?
Use something like this (it is pseudo code so convert it to your sketch):

enum EState { NORMAL, SPECIAL } _state; // States
enum ENormalState { RED, YELLOW1, GREEN, YELLOW2 } _normalState; // State only valid when _state == NORMAL 
unsigned long _time; // _time only valid when _state == NORMAL

void loop() 
{
   if ('serial input available')
   {
      if ('input == ...')
      {
         _state = NORMAL;
      }
      else if ('input == ...')
      {
         _state = SPECIAL;
      }
      ...
   }

   switch (_state)
   {
   case NORMAL:
       if (_time + ... &gt; time())
       {
          // Change to next state
          switch (_normalState)
          {
          case RED:
              _normalState = YELLOW1;
              _time = time();
              break;

          case YELLOW1:
              _normalState = GREEN;
              _time = time();
              break;
          ...
          }

       setLight(_normalState); // Change the light according to the _normalState
       break;



   case SPECIAL:
       ...
       break;

   ...
   }
}


Ideas to improve/explain:


Try to make some specific functions for setting the light according to the current state
You do not need a delay
Split functions (like above, make a separate function for normal state, and specific state