Post 21 · May 22nd, 2026
Dinner on the line for this challenge.
Cecil, Jaisen, TJ, and I are running a fitness challenge through the summer. The prize is simple: the winner gets an all-inclusive dinner at The Precinct steakhouse in Cincinnati while everyone is in town for ATP Cincinnati in August — paid for by the three losers. Stakes are real.
The scoring pulls from three Whoop metrics each day: Strain, Recovery, and Sleep. Each day the four of us are ranked 1–4 across those categories. The points stack daily. Whoever has the most at the end of summer eats for free. The three losers picks up the whole tab, Kobe A5 here I come.
Five days in. Here's where we stand.
I'm in front right now, but it's early. Cecil is pushing hard on Strain — he's averaging the highest of anyone at 12.0. TJ is consistent. Jaisen had a rough start to the challenge but he's the one who gave me the one-Amazon-order-a-week rule, so I'm not writing him off. The gap is real today. It won't necessarily stay that way.
| Date | Cecil | Collins | Jaisen | TJ |
|---|---|---|---|---|
| May 18 | ||||
| May 19 | ||||
| May 20 | ||||
| May 21 | ||||
| May 22 |
The scoreboard above uses nothing but HTML and CSS — no JavaScript, no charts library. Here's what makes each piece work.
Each player card has a thin horizontal bar that shows their score relative to the leader. The bar is built with two nested divs: an outer track and an inner fill. The fill's width is set inline using a calc() expression that does the math directly in the markup.
<div class="pts-bar-track">
<div class="pts-bar-fill"
style="width: calc(24 / 34 * 100%)">
</div>
</div>
The track gets overflow: hidden so the fill can never escape its container. The border-radius on both elements keeps the pill shape consistent even as the fill width changes.
.pts-bar-track {
width: 100%;
height: 5px;
background: #e7e5e4;
border-radius: 3px;
overflow: hidden;
}
.pts-bar-fill {
height: 100%;
background: #1c1917;
border-radius: 3px;
}
The leader card gets a darker border and a small "Leading" tag that drops from the top right corner. This is done with a single modifier class on the card and a position: absolute badge inside it. The badge is hidden by default with display: none and only shown when the parent has the .leader class.
.player-card.leader {
border-color: #1c1917;
}
.leader-tag {
display: none; /* hidden on all cards by default */
position: absolute;
top: -1px;
right: 14px;
}
.player-card.leader .leader-tag {
display: block; /* visible only on the leader */
}
Each card has three smaller bars for Strain, Recovery, and Sleep. They work the same way as the points bar — a track with an overflowing fill — just at 3px height instead of 5px. Each metric gets its own fill color class so they stay visually distinct without needing inline styles for color.
.fill-strain { background: #44403c; }
.fill-recovery { background: #57534e; }
.fill-sleep { background: #78716c; }
The three stat blocks sit in a CSS Grid with grid-template-columns: repeat(3, 1fr), which divides the available width into three equal columns automatically regardless of the card width.
The daily points table uses a row of small div circles instead of raw numbers. Each dot is 7px wide, 7px tall, and fully rounded. Filled dots are full opacity. Empty dots sit at 15% opacity — present but quiet. This lets you scan the week visually rather than reading integers.
.dot {
width: 7px; height: 7px;
border-radius: 50%;
background: #1c1917;
opacity: 0.15; /* empty state */
}
.dot.filled {
opacity: 1; /* active state */
}
The dots share the same HTML element. The only difference between filled and empty is that single class toggle. Simple system. Easy to update as scores come in.