The ID token is always a JWT when doing OIDC, and it makes sense in this situation.
Because the ID token is not a set of credentials, but signed information you’d use to create/update a user’s profile.
You can technically use JWTs as access tokens, as the spec doesn’t specify a format for access tokens, but in my experience they’re normally opaque bearer tokens.
The main reason I don't like the id token is that I've seen way too many instances of the ID token being used as a trusted identity assertion sent across multiple services or to third parties. This is very dangerous, since ID tokens tend to have longish expiry (several hours), are not revocable, and generally do not carry any concept of authorization (e.g. restricted scope).
It would have been better if instead of implementing ID tokens, OIDC only supported the authorization code flow and returned a JSON payload of claims (which nobody would incorrectly assume to be trustworthy).
I prefer saml 2.0 for jit provisioning.