You could also use a mask, which would allow things like fuzzy edges. As a starting point, you can replace the clip-path in your example with this:
mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="200%25" height="200%25"><circle r="160" cx="50%25" cy="50%25" fill="white"/></svg>') calc(var(--x) - 100%) calc(var(--y) - 100%) / 200% 200%;
This doesn’t seem to work below one screenful of content, though, and I’m not sure why and don’t intend to spend the time required to
make it work. The SVG size technique I’ve used is a bit dodgy (in a fun kind of way) anyway. You’d probably be better to have a separate `position: fixed` element that sits on top of everything, and apply the mask to it.