Testimonials: center, scale by length, smoother fade

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.
This commit is contained in:
Joel Brock
2026-05-15 17:33:29 -07:00
parent e1b3bc7d43
commit b257d92636
2 changed files with 47 additions and 14 deletions

View File

@@ -117,8 +117,15 @@
const isFavicon = !(it.image || it.icon);
const initial = (it.name || it.org || "·").trim().charAt(0).toUpperCase();
const meta = [it.role, it.org].filter(Boolean).join(", ");
const len = [...String(it.quote || "")].length;
const lengthClass =
len <= 90 ? " is-xshort" :
len <= 180 ? " is-short" :
len <= 320 ? " is-medium" :
len <= 520 ? " is-long" :
" is-xlong";
return `
<${tag} class="card card--testimonial reveal" ${attrs}>
<${tag} class="card card--testimonial reveal${lengthClass}" ${attrs}>
<span class="testimonial__mark" aria-hidden="true">&ldquo;</span>
<blockquote class="testimonial__quote">${esc(it.quote)}</blockquote>
<figcaption class="testimonial__by">