

index.html
<!-- the score lives on the
root; CSS maps it to a
level and a colour -->
<div class="steep"
data-score="0">
<span class="steep-liquid"
aria-hidden="true">
<!-- strength is spoken,
not just coloured -->
<p class="steep-meter"
… aria-live="polite">steep.css
/* a score is only a level
and a colour */
.steep[data-score="2"] {
--steep-level: 52%; …
/* y1 above 1: the liquid
overshoots, settles */
.steep-liquid { …
height:
var(--steep-level);
transition: height 700ms
cubic-bezier(.34, 1.3, …steep.js
// JS writes the score;
// CSS does the rising
root.dataset.score =
String(s);
// a new level sloshes the
// surface: stretch, squash
if (s !== last) { …
wave.animate([ …
{ scale: '1 2.2' },
{ scale: '1 .7' }, …






