You can read the raw markup I submitted with JSON.parse(document.querySelector("#trpc-dehydrated-state").innerText).queries.map(e=>e?.state?.data?.post).find(e=>e).blocks.at(-1).markdown.content!
The bulk of the character limit (96%) went to adding the hitcircles (~760 bytes each), so that's where I could save characters the most by being clever. Every byte in a hitcircle is the equivalent of 248 bytes in the final markup.
Here's an example of a hitnote (with whitespace added for clarity):
<details>
<summary style=list-style:none>
<div style="
position:absolute;
border-radius:100px;
animation:2s steps(2,jump-none) 89.62s slideupleft;
left:119px;
top:184px;
width:100px;
height:100px;
background:#825;
transform:scale(0);
cursor:pointer
">3
<div style="
position:absolute;
animation:2s linear 90.12s 1 reverse none running slideupleft;
width:200px;
height:200px;
pointer-events:none;
bottom:50px;
left:50px
">
<div style="
translate:-100px 100px;
border-radius:200px;
border:4px solid #825;
width:100%;
height:100%
"></div>
</div>
</div>
</summary>
<div style="
position:absolute;
border-radius:100px;
animation:1s steps(2,jump-none) -0.5s slideupleft;
width:100px;
height:100px;
background-color:#FFFA;
transform:scale(0);
left:119px;
top:184px
"></div>
<div style=height:1px></div>
</details>
The loose "3" is the current combo number, the nested divs are used for the approaching circle animation, and the 1px high div is what keeps track of the score.
I left out the style tag quotes where possible and I experimented a lot with what CSS I could get away with, looking at MDN to see which way of doing things would be the most compact. I do think there is opportunity to save more bytes here by carefully looking at the specs, but I wanted to finish this project in less than a day.
I did give up some savings for cross-browser compatibility though, eg I could've replaced steps(2,jump-none) with steps(2) and some clever size/position adjustments, but it would've caused some weird artifacts in Firefox.
I didn't need to save too many bytes elsewhere, but I did do some stuff, eg the number counter doesn't work past 299 because it helped save bytes.
I didn't use any existing minifiers or preprocessors, I just manually wrote the html as compact as I could and then put it through a quick python script that generated the hitnotes and removed whitespace.