The same CSS bug shipped three times because fixing it once didn't fix the ratio
A pill nested inside another pill needs real clearance between the two curves, or the inner shape visibly pokes into the outer border. Fixed once, fixed again elsewhere, then shipped a third time — inside new size variants of the very component already fixed.
Background
bopomofokids.com’s whole visual style is one
deliberate system — thick ink-colored outlines on every element, hard offset
shadows, no blur. Buttons and pills are always fully round
(rounded-full). A recurring pattern in that system is a segmented control:
a rounded-full colored pill representing the active option, sliding inside
another, larger rounded-full container — used for the header’s
language toggle, the settings panel’s various switches, and a mode’s own
in-game speed switcher.
That pattern has a geometry problem that isn’t visible from reading the class names, only from actually looking at the rendered result.
Why two nested full circles need real clearance
This isn’t a fixed pixel value you can set once and forget — it’s a ratio between the outer padding and the inner pill’s rendered height, and the pill’s rendered height depends on font size, line height, and how much text the label itself needs.
First two times
The bug shipped in two different components independently: the header/
settings Segmented component (at p-1) and BalloonMode’s own in-game
speed switcher (at p-1.5). Both were fixed the same way — more padding —
landing at p-1.5 and p-2 respectively. Two separate components, two
separate fixes, same underlying cause.
The third time — inside a component that was already fixed
Segmented later grew sm and xs size variants for a more compact header
toggle, added as part of a 2026-07-20 layout redesign. Both new variants
copied the already-fixed md variant’s border width, but reset the padding
back to p-1:
const SIZES = {
md: { box: 'border-3 p-1.5 gap-1', option: 'px-2.5 py-1.5 text-xs' },
sm: { box: 'border-3 p-1 gap-1', option: 'px-2 py-1 text-[11px]' }, // ← same bug, back again
xs: { box: 'border-2 p-1 gap-0.5', option: 'px-1.5 py-0.5 text-[10px]' }, // ← same bug, back again
};
App.tsx — Segmented size variants, before the third fix
Same component, same border width, same fix already shipped once for the
md size — and the exact same bug reappeared in the two new size variants,
because the fix that had already landed only touched the one size variant
that existed at the time. It was caught the very next day from a user’s
screenshot of the language toggle, and fixed the same way, again: bump the
padding, p-1 to p-1.5, on both new variants.
const SIZES = {
md: { box: 'border-3 p-1.5 gap-1', option: 'px-2.5 py-1.5 text-xs' },
sm: { box: 'border-3 p-1.5 gap-1', option: 'px-2 py-1 text-[11px]' },
xs: { box: 'border-2 p-1.5 gap-0.5', option: 'px-1.5 py-0.5 text-[10px]' },
};
App.tsx — Segmented size variants, after the third fix
Why the English label made it worse
The app’s language toggle can render either “中文|EN” or the equivalent in English UI copy, and English labels tend to run taller and wider than the Chinese ones they sit next to — more line-height needed for the same visual weight. That shrinks the effective clearance further without changing a single padding value: the same numeric padding produces less real headroom once the label inside the pill needs more vertical space. A control that passed a quick glance in Chinese could still fail in English at the exact same CSS values.
Takeaways
Fixing Segmented’s md variant didn’t fix Segmented — it fixed one
specific border-width-to-padding ratio. sm and xs are, in effect, new
components that happen to share a name and a file. Each new size variant
of a nested-pill control needs its own clearance check; having been wrong
once elsewhere in the same file doesn’t make a new variant immune.
The exact same padding value renders with different real clearance depending on how tall the label inside the pill needs to be — which depends on language, font, and text length. A control that looks fine in one language’s copy isn’t proven fine until checked in every language it actually ships with.
Nothing about p-1 vs p-1.5 looks obviously wrong when reading the
Tailwind classes — the bug only exists in the rendered geometry. When
adding or resizing any nested-pill control, screenshotting the real output
at its actual pixel size (not eyeballing a dev server at 100% zoom) is
what actually catches this, and it needs to happen for every new variant,
not once for the component as a whole.