But of course my loops have "delay" in them.
The issue with long delays is that they are not "interruptable": you push a button and the mcu doesn't respond.
You can use interrupts to cure that, or you can "interruptize" your long delays:
void mydelay(unsigned int dly) {
while (dly--) {
if(digitalRead(int_key)) break; //allows int_key to break mydelay, active high
delay(1);
}
}
Essentially, you have programmed the key presses to have a higher priority than the delays, the same concept as interrupts but without the interrupts.
AVRs excel in part because of their vectored interrupts. No one should be afraid of using them.