Center-align the testimonial card (text + attribution row), then
size the quote based on character count so short, punchy quotes get
the spotlight and long ones tighten down:
is-xshort (<=90 chars) 3rem cap
is-short (<=180 chars) 2.25rem cap
is-medium (<=320 chars) 1.55rem cap (the previous baseline)
is-long (<=520 chars) 1.20rem cap
is-xlong (>520 chars) 1.05rem cap
Counts use [...str] so grapheme-cluster emoji (skin-tone, ZWJ) count
as a single visual character instead of inflating the length.
Crossfade: drop the secondary translateY (it stuttered against
centered content), bump duration 600ms -> 1100ms, swap easing to
cubic-bezier(0.65, 0, 0.35, 1) for a softer in/out, and add
will-change:opacity so the browser keeps the layer on the GPU.