I just learned that Ping uses ICMP directly, i.e. it bypasses the transport layer. How is that possible? Shouldn't an application (L5) use UDP or TCP in the transport layer (L4)? The way I know it is that every layer is blind to everything that is 2 layers down, i.e. an application interfaces with L4 using sockets, but is blind to L3 down to L1.
When one says "Ping", they refer to ICMP ping, as that is what the original ping is. ICMP actually works on a lower level than the UDP & TCP transport protocols and does not use ports:
ICMP, uses the basic support of IP as if it were a higher level protocol, however, ICMP is actually an integral part of IP, and must be implemented by every IP module.
That is mostly because ICMP is used to report errors as IP is not completely reliable on its own. So, ICMP is a lower-level protocol that uses IP, not TCP/UDP. Ping is just a tool that uses ICMP (thanks to low-level C), however, ICMP isn't just ping or traceroute, its main purpose is completely different as I noted.
And I don't know how you've learned that layers are blind for below layers. That is not true, or at least to my knowledge. Ping can use any protocol it wishes by implementing it in C.
Low-level languages like C have direct access to system IP-based modules, thus it is possible to use any such protocol by using C (and almost any other language written in C nowadays).
To explain more explicitly (tl;dr):
Ping is an ICMP-based tool, it does not use TCP and UDP, thus it doesn't work with ports (as a protocol does not need ports, only services do). It does not require the functionality of higher-level protocols such as TCP, so it doesn't implement them. And despite ping being an application, it works on ICMP and uses no port.