Let me see if I can explain clearer:
Since you're using non-blocking, in Case 1, even if both a and b are 1, c is not assigned to out immediately, c is just scheduled to assign to out later, so when it comes to "else if (a)", obviously it is satisfied, so d is again scheduled to be assigned to out, so finally no matter what, you'll get out = d. But in Case 2, the second "else if (a && ~b) avoid that senario, so it is normal.
Try always use blocking assignment in combinational logic.