Fix the flat drop on Linux and morph its play/pause in one shape

The kick wave in the vertex shader squared a negative number with pow(), which
GLSL leaves undefined. Mesa returns NaN there, so on Linux the drop's position
pinned to the clamp: it stayed a plain round sphere without wobble, and its
normals split it into a dark yin-yang. The squares are written out now, and the
normal comes from the slope of the displacement instead of two whole positions.

The play/pause icon is one shape whose corners move: each pause bar turns into
half of the play triangle, with a small swing in between, instead of two icons
faded over each other. It sits on a disc of frosted artwork with a lit rim, and a
ring round it shows the track's progress, or runs while the track loads, which
replaces the flat spinner. The surface calms down under the icon gradually
instead of jumping flat, a double-tap no longer flickers the icon, and a mouse
resting on the playing drop shows the pause bars faintly.

Also:
- Low-density desktop screens render the drop at twice the resolution.
- Quality steps follow the display's own frame rate and step back up again.
- A lost WebGL context brings the drop back once it is restored.
- A paused drop keeps breathing at a low frame rate on desktop.
- Without Web Audio (iOS) jumps in the waveform count as kicks, so the drop lands on drops there too.
- Artists without an image get their own colour from their name, so their drop no longer sinks into the page.
- z toggles zen mode: just the drop, bigger, and the music.
This commit is contained in:
nvrl committed 2026-11-01 19:04:18 +01:00
1 parent bcdca34244
commit 2dcca0bc94
9 files changed
+346 -110

No files matched your search

+8 -1
View File
@@ -285,7 +285,8 @@ button.danger:not(.link) { background: var(--accent); border: none; color: #fff;
}
.card.liquid .content > :not(.art) { position: relative; z-index: 1; }
.card.liquid .title { text-shadow: 0 2px 16px #000b; }
.card.liquid .initial, .card.liquid .paused-badge { display: none; }
/* The drop shows loading as a ring of its own. */
.card.liquid .initial, .card.liquid .paused-badge, .card.liquid .spinner { display: none; }
/* Hidden, not removed: it takes itself away when its animation ends. */
.card.liquid .flash { visibility: hidden; }
@media (pointer: fine) {
@@ -738,6 +739,12 @@ button.primary svg { width: 1em; height: 1em; }
}
}
/* Zen: nothing but the drop, bigger, and the music. */
body.zen #bar, body.zen .actions, body.zen .chips, body.zen .desc, body.zen .counts,
body.zen .why, body.zen .byline button, body.zen #feed-status { display: none; }
body.zen .art { width: min(30rem, 62vh, 86vw); }
body.zen .content { gap: 0.3rem; }
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}