One thing to consider (It’s okay in this specific form):
Initially a field like “First name” is required and invalid (because it’s empty), but we only see the “Required”. That’s because both selector have the same specificity and the second rule overwrites the first one. You could separate them into span::before and span::after and then place them in different spots. For example replacing the valid/invalid indicator with a checkmark/cross after the input field.