I'll try to give a rough overview of what's going on here.
The function z produces the puddle (ahem - "event horizon") through a technique I accidentally found from "orthogonal" raymarching. The accident being the value is supposed to be the distance of an incrementing ray for an SDF (signed distance function), but instead the distance is completely replaced on each recursion resulting in the reflected fluid appearance. I think this is due to the ray distance oscillating backwards and forwards in a way that is similar enough to neighboring rays to not appear noisy while giving the appearance of reflection. The exact functions used for the SDF are not so important so long as it incorporates itself.
fillRect is doing pretty much everything else, by painting each pixel. To achieve shading without fillStyle, the width and height arguments are varied between 0 and 1 to give grey scale shading due to subpixel anti-aliasing. Speculative edges are also achieved with negative values (0 to -1) which creates white gaps and fill adjacent pixels instead.
The chevrons are sampled from a radial fractal a*20-r&44 where 'a' is the angle of the current position wrapped in some periodic function (cosine), and 'r' is the radius. The bitwise AND operator is the key in generating these types of patterns (although OR and XOR also work very well producing other types of patterns), the constants are found through - a lot - of trial and error. In this case the result of the fractal is used as a "truthy" condition (i.e non zero) to toggle between the shaded sides (X/48 or Y/48) and 1 (the dark bits).
Some other hacky details: S and T are the X and Y pixel positions, these names are used so that they can be referenced before they have been assigned because these names have already been assigned unused functions by dwitter. This saves some characters by allowing me to define X and Y inside of atan2 while also passing them as arguments, at the cost of the fillRect X Y position being invalid for the first pixel and from the previous iteration on the rest.
I'm finding a recurring property of dweets that end up packing a lot in - is sharing significant portions of code for different purposes, in this case it's fairly straight forward but still a big win in terms of characters: S, T and r are only defined once and used for both the puddle and the ring. This type of size optimization always gives a lot more road than syntactic wrangling, which while important are only finishing touches. However they cannot be forced, ideas with enough shared code can only be found.
Feel free to ask me anything else.