Coach — Testimonials
A high-energy testimonials section for fitness coaches: swipeable quote cards pairing client photos, hard result stats and animated star ratings inside an accessible carousel with autoplay, dot navigation, keyboard controls and an aggregate rating summary.
MCP
Code
:root {
--bg: #0f1115;
--surface: #171a21;
--surface-2: #1f232c;
--lime: #c2f542;
--lime-d: #a3d62f;
--orange: #ff6b35;
--ink: #f2f4f0;
--muted: #9aa0a6;
--line: rgba(255, 255, 255, 0.1);
--line-2: rgba(255, 255, 255, 0.18);
--white: #fff;
--r-sm: 8px;
--r-md: 14px;
--r-lg: 20px;
}
* {
box-sizing: border-box;
}
html {
-webkit-text-size-adjust: 100%;
}
body {
margin: 0;
font-family: "Inter", system-ui, -apple-system, sans-serif;
line-height: 1.5;
color: var(--ink);
background:
radial-gradient(1100px 520px at 82% -8%, rgba(194, 245, 66, 0.12), transparent 60%),
radial-gradient(900px 480px at 5% 105%, rgba(255, 107, 53, 0.1), transparent 55%),
var(--bg);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
min-height: 100vh;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.wrap {
max-width: 1040px;
margin: 0 auto;
padding: clamp(28px, 6vw, 72px) clamp(16px, 4vw, 40px);
}
/* ---------- Header ---------- */
.t-head {
display: grid;
gap: 20px;
margin-bottom: 34px;
}
.eyebrow {
display: inline-flex;
align-items: center;
gap: 9px;
margin: 0;
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--lime);
}
.eyebrow .dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--lime);
box-shadow: 0 0 0 4px rgba(194, 245, 66, 0.18);
animation: pulse 2.4s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { box-shadow: 0 0 0 4px rgba(194, 245, 66, 0.18); }
50% { box-shadow: 0 0 0 8px rgba(194, 245, 66, 0.05); }
}
h1 {
margin: 0;
font-weight: 800;
font-size: clamp(1.9rem, 5.2vw, 3.15rem);
line-height: 1.05;
letter-spacing: -0.02em;
text-transform: uppercase;
}
h1 em {
font-style: normal;
color: var(--lime);
text-shadow: 0 0 32px rgba(194, 245, 66, 0.35);
}
.rating-summary {
display: inline-flex;
align-items: center;
gap: 16px;
padding: 14px 20px;
width: fit-content;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--r-md);
}
.rs-score {
font-size: 2.1rem;
font-weight: 800;
line-height: 1;
letter-spacing: -0.02em;
color: var(--lime);
}
.rs-meta {
display: grid;
gap: 4px;
}
.rs-stars {
display: flex;
gap: 3px;
}
.rs-stars span {
width: 15px;
height: 15px;
background: var(--lime);
-webkit-mask: var(--star) center / contain no-repeat;
mask: var(--star) center / contain no-repeat;
}
.rs-count {
margin: 0;
font-size: 0.82rem;
color: var(--muted);
}
.rs-count strong {
color: var(--ink);
}
/* star mask shared */
.rs-stars span,
.rating span {
--star: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2l2.9 6.26L22 9.27l-5 4.87L18.18 22 12 18.56 5.82 22 7 14.14l-5-4.87 7.1-1.01z'/%3E%3C/svg%3E");
}
/* ---------- Carousel ---------- */
.carousel {
position: relative;
}
.viewport {
overflow: hidden;
border-radius: var(--r-lg);
}
.track {
display: flex;
margin: 0;
padding: 0;
list-style: none;
transition: transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
will-change: transform;
}
.slide {
flex: 0 0 100%;
min-width: 0;
padding: 4px;
}
.card {
position: relative;
overflow: hidden;
display: grid;
gap: 20px;
padding: clamp(24px, 4vw, 40px);
background:
linear-gradient(180deg, var(--surface-2), var(--surface));
border: 1px solid var(--line);
border-radius: var(--r-lg);
box-shadow: 0 24px 60px -30px rgba(0, 0, 0, 0.8);
}
.card::before {
content: "";
position: absolute;
inset: 0 0 auto 0;
height: 3px;
background: linear-gradient(90deg, var(--lime), var(--orange));
opacity: 0.85;
}
.quote-mark {
position: absolute;
top: 6px;
right: 24px;
font-family: Georgia, serif;
font-size: 8rem;
line-height: 1;
color: var(--line-2);
pointer-events: none;
user-select: none;
}
.rating {
display: flex;
gap: 4px;
}
.rating span {
width: 20px;
height: 20px;
background: var(--line-2);
-webkit-mask: var(--star) center / contain no-repeat;
mask: var(--star) center / contain no-repeat;
transition: background 0.25s ease, transform 0.25s ease;
}
.rating span.on {
background: var(--lime);
}
blockquote {
margin: 0;
font-size: clamp(1.05rem, 2.4vw, 1.4rem);
font-weight: 500;
line-height: 1.45;
letter-spacing: -0.01em;
max-width: 60ch;
}
.stat {
display: flex;
align-items: baseline;
gap: 12px;
padding: 14px 18px;
width: fit-content;
background: rgba(194, 245, 66, 0.08);
border: 1px solid rgba(194, 245, 66, 0.25);
border-radius: var(--r-md);
}
.stat-num {
font-size: clamp(1.6rem, 4vw, 2.3rem);
font-weight: 800;
line-height: 1;
letter-spacing: -0.02em;
color: var(--lime);
font-variant-numeric: tabular-nums;
}
.stat-label {
font-size: 0.8rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--muted);
max-width: 16ch;
}
.who {
display: flex;
align-items: center;
gap: 14px;
padding-top: 6px;
border-top: 1px solid var(--line);
}
.avatar {
flex: 0 0 auto;
width: 52px;
height: 52px;
border-radius: 50%;
background: var(--surface-2) var(--img) center / cover no-repeat;
border: 2px solid var(--lime);
box-shadow: 0 0 0 4px rgba(194, 245, 66, 0.12);
}
.name {
margin: 0;
font-weight: 700;
font-size: 0.98rem;
}
.prog {
margin: 4px 0 0;
}
.badge {
display: inline-block;
padding: 3px 10px;
font-size: 0.68rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
border-radius: 999px;
}
.badge-lime {
color: #10140a;
background: var(--lime);
}
.badge-orange {
color: #1a0d06;
background: var(--orange);
}
/* ---------- Controls ---------- */
.controls {
display: flex;
align-items: center;
justify-content: center;
gap: 18px;
margin-top: 22px;
}
.nav {
display: grid;
place-items: center;
width: 46px;
height: 46px;
padding: 0;
border-radius: 50%;
border: 1px solid var(--line-2);
background: var(--surface);
color: var(--ink);
cursor: pointer;
transition: transform 0.18s ease, background 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}
.nav svg {
width: 22px;
height: 22px;
fill: none;
stroke: currentColor;
stroke-width: 2.4;
stroke-linecap: round;
stroke-linejoin: round;
}
.nav:hover {
background: var(--lime);
color: #10140a;
border-color: var(--lime);
transform: translateY(-2px);
box-shadow: 0 8px 22px -8px rgba(194, 245, 66, 0.6);
}
.nav:active {
transform: translateY(0) scale(0.94);
}
.dots {
display: flex;
align-items: center;
gap: 9px;
}
.dots button {
width: 9px;
height: 9px;
padding: 0;
border: 0;
border-radius: 999px;
background: var(--line-2);
cursor: pointer;
transition: width 0.3s ease, background 0.3s ease;
}
.dots button[aria-selected="true"] {
width: 26px;
background: var(--lime);
}
.dots button:hover {
background: var(--muted);
}
.dots button[aria-selected="true"]:hover {
background: var(--lime-d);
}
.progress {
height: 3px;
margin: 18px auto 0;
max-width: 240px;
background: var(--line);
border-radius: 999px;
overflow: hidden;
}
.progress span {
display: block;
height: 100%;
width: 0;
background: linear-gradient(90deg, var(--lime), var(--orange));
border-radius: inherit;
}
/* ---------- CTA row ---------- */
.cta-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 14px;
justify-content: center;
margin-top: 34px;
}
.cta {
display: inline-flex;
align-items: center;
gap: 9px;
padding: 14px 26px;
font-weight: 800;
font-size: 0.9rem;
text-transform: uppercase;
letter-spacing: 0.05em;
text-decoration: none;
color: #10140a;
background: var(--lime);
border-radius: 999px;
box-shadow: 0 0 0 rgba(194, 245, 66, 0);
transition: transform 0.18s ease, box-shadow 0.25s ease, background 0.18s ease;
}
.cta svg {
width: 18px;
height: 18px;
fill: none;
stroke: currentColor;
stroke-width: 2.6;
stroke-linecap: round;
stroke-linejoin: round;
transition: transform 0.2s ease;
}
.cta:hover {
background: var(--lime-d);
transform: translateY(-2px);
box-shadow: 0 12px 34px -10px rgba(194, 245, 66, 0.7);
}
.cta:hover svg {
transform: translateX(4px);
}
.cta:active {
transform: translateY(0) scale(0.97);
}
.ghost {
padding: 12px 22px;
font-weight: 600;
font-size: 0.85rem;
color: var(--muted);
background: transparent;
border: 1px solid var(--line-2);
border-radius: 999px;
cursor: pointer;
transition: color 0.18s ease, border-color 0.18s ease, background 0.18s ease;
}
.ghost:hover {
color: var(--ink);
border-color: var(--muted);
background: var(--surface);
}
.ghost[aria-pressed="true"] {
color: var(--orange);
border-color: rgba(255, 107, 53, 0.5);
}
/* ---------- Focus ---------- */
:focus-visible {
outline: 3px solid var(--lime);
outline-offset: 3px;
border-radius: 6px;
}
.nav:focus-visible,
.dots button:focus-visible {
outline-offset: 4px;
}
/* ---------- Toast ---------- */
.toast {
position: fixed;
left: 50%;
bottom: 26px;
transform: translate(-50%, 20px);
padding: 12px 20px;
background: var(--lime);
color: #10140a;
font-weight: 700;
font-size: 0.88rem;
border-radius: 999px;
box-shadow: 0 14px 40px -12px rgba(0, 0, 0, 0.7);
opacity: 0;
pointer-events: none;
transition: opacity 0.28s ease, transform 0.28s ease;
z-index: 40;
}
.toast.show {
opacity: 1;
transform: translate(-50%, 0);
}
/* ---------- Responsive ---------- */
@media (max-width: 520px) {
.quote-mark {
font-size: 5.5rem;
right: 14px;
}
.stat {
flex-direction: column;
gap: 4px;
align-items: flex-start;
}
.stat-label {
max-width: none;
}
.rating-summary {
width: 100%;
}
.controls {
gap: 12px;
}
.cta-row {
flex-direction: column;
}
.cta,
.ghost {
width: 100%;
justify-content: center;
text-align: center;
}
}
@media (prefers-reduced-motion: reduce) {
* {
animation: none !important;
transition: none !important;
}
}(function () {
"use strict";
var carousel = document.getElementById("carousel");
var track = document.getElementById("track");
var slides = Array.prototype.slice.call(track.querySelectorAll(".slide"));
var dotsWrap = document.getElementById("dots");
var prevBtn = document.getElementById("prev");
var nextBtn = document.getElementById("next");
var bar = document.getElementById("bar");
var live = document.getElementById("live");
var pauseBtn = document.getElementById("pauseBtn");
var cta = document.getElementById("cta");
var toastEl = document.getElementById("toast");
var index = 0;
var count = slides.length;
var AUTOPLAY = 5200;
var timer = null;
var rafId = null;
var startTime = 0;
var paused = false;
var userPaused = false;
var reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
/* ----- toast helper ----- */
var toastTimer = null;
function toast(msg) {
toastEl.textContent = msg;
toastEl.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("show");
}, 2000);
}
/* ----- build dots ----- */
slides.forEach(function (_, i) {
var b = document.createElement("button");
b.type = "button";
b.setAttribute("role", "tab");
b.setAttribute("aria-label", "Testimonial " + (i + 1));
b.setAttribute("aria-selected", i === 0 ? "true" : "false");
b.addEventListener("click", function () {
goTo(i, true);
});
dotsWrap.appendChild(b);
});
var dots = Array.prototype.slice.call(dotsWrap.children);
/* ----- star fill for active slide ----- */
function fillStars(slide) {
var rating = slide.querySelector(".rating");
if (!rating) return;
var n = parseInt(rating.getAttribute("data-stars"), 10) || 0;
var stars = rating.querySelectorAll("span");
stars.forEach(function (s, i) {
if (i < n) {
setTimeout(
function () {
s.classList.add("on");
},
reduceMotion ? 0 : i * 90
);
} else {
s.classList.remove("on");
}
});
}
/* ----- animated stat counter ----- */
function countUp(slide) {
var el = slide.querySelector(".stat-num");
if (!el || el.dataset.done === "1") return;
var target = parseFloat(el.getAttribute("data-count"));
var suffix = el.getAttribute("data-suffix") || "";
var decimals = (el.getAttribute("data-count").split(".")[1] || "").length;
if (reduceMotion) {
el.textContent = target.toFixed(decimals) + suffix;
el.dataset.done = "1";
return;
}
var dur = 900;
var t0 = performance.now();
function tick(now) {
var p = Math.min((now - t0) / dur, 1);
var eased = 1 - Math.pow(1 - p, 3);
var val = target * eased;
el.textContent = val.toFixed(decimals) + suffix;
if (p < 1) requestAnimationFrame(tick);
else {
el.textContent = target.toFixed(decimals) + suffix;
el.dataset.done = "1";
}
}
requestAnimationFrame(tick);
}
/* ----- go to slide ----- */
function goTo(i, fromUser) {
index = (i + count) % count;
track.style.transform = "translateX(" + -index * 100 + "%)";
dots.forEach(function (d, di) {
d.setAttribute("aria-selected", di === index ? "true" : "false");
});
slides.forEach(function (s, si) {
s.setAttribute("aria-hidden", si === index ? "false" : "true");
});
var active = slides[index];
fillStars(active);
countUp(active);
var name = active.querySelector(".name");
live.textContent =
"Showing testimonial " + (index + 1) + " of " + count +
(name ? ", " + name.textContent : "");
if (fromUser) restartAutoplay();
}
function next(fromUser) {
goTo(index + 1, fromUser);
}
function prev(fromUser) {
goTo(index - 1, fromUser);
}
/* ----- autoplay + progress bar ----- */
function loop(now) {
if (paused || userPaused) return;
if (!startTime) startTime = now;
var elapsed = now - startTime;
var pct = Math.min(elapsed / AUTOPLAY, 1);
bar.style.width = pct * 100 + "%";
if (pct >= 1) {
startTime = 0;
bar.style.width = "0%";
next(false);
}
rafId = requestAnimationFrame(loop);
}
function startAutoplay() {
if (reduceMotion || userPaused) return;
cancelAnimationFrame(rafId);
startTime = 0;
bar.style.width = "0%";
paused = false;
rafId = requestAnimationFrame(loop);
}
function stopAutoplay() {
paused = true;
cancelAnimationFrame(rafId);
}
function restartAutoplay() {
if (userPaused) return;
startAutoplay();
}
/* ----- events ----- */
nextBtn.addEventListener("click", function () {
next(true);
});
prevBtn.addEventListener("click", function () {
prev(true);
});
carousel.addEventListener("mouseenter", stopAutoplay);
carousel.addEventListener("mouseleave", restartAutoplay);
carousel.addEventListener("focusin", stopAutoplay);
carousel.addEventListener("focusout", function (e) {
if (!carousel.contains(e.relatedTarget)) restartAutoplay();
});
document.addEventListener("visibilitychange", function () {
if (document.hidden) stopAutoplay();
else restartAutoplay();
});
/* keyboard: arrows + number keys */
carousel.setAttribute("tabindex", "0");
carousel.addEventListener("keydown", function (e) {
if (e.key === "ArrowRight") {
e.preventDefault();
next(true);
} else if (e.key === "ArrowLeft") {
e.preventDefault();
prev(true);
} else if (e.key >= "1" && e.key <= String(Math.min(count, 9))) {
e.preventDefault();
goTo(parseInt(e.key, 10) - 1, true);
}
});
/* touch / swipe */
var startX = 0;
var startY = 0;
var swiping = false;
track.addEventListener(
"touchstart",
function (e) {
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
swiping = true;
stopAutoplay();
},
{ passive: true }
);
track.addEventListener(
"touchend",
function (e) {
if (!swiping) return;
swiping = false;
var dx = e.changedTouches[0].clientX - startX;
var dy = e.changedTouches[0].clientY - startY;
if (Math.abs(dx) > 45 && Math.abs(dx) > Math.abs(dy)) {
if (dx < 0) next(true);
else prev(true);
} else {
restartAutoplay();
}
},
{ passive: true }
);
/* pause button */
pauseBtn.addEventListener("click", function () {
userPaused = !userPaused;
pauseBtn.setAttribute("aria-pressed", String(userPaused));
pauseBtn.textContent = userPaused ? "Resume autoplay" : "Pause autoplay";
if (userPaused) {
stopAutoplay();
bar.style.width = "0%";
toast("Autoplay paused");
} else {
startAutoplay();
toast("Autoplay resumed");
}
});
/* CTA */
cta.addEventListener("click", function (e) {
e.preventDefault();
toast("Nice — let's get to work! 💪");
});
/* ----- init ----- */
goTo(0, false);
startAutoplay();
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Coach — Testimonials</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<main class="wrap">
<section class="testimonials" aria-labelledby="t-title">
<header class="t-head">
<p class="eyebrow"><span class="dot"></span> Real clients · Real results</p>
<h1 id="t-title">They put in the work.<br /><em>Here's the proof.</em></h1>
<div class="rating-summary" role="group" aria-label="Aggregate client rating">
<div class="rs-score">4.9</div>
<div class="rs-meta">
<div class="rs-stars" aria-hidden="true">
<span></span><span></span><span></span><span></span><span></span>
</div>
<p class="rs-count">from <strong>1,284</strong> coached athletes</p>
</div>
</div>
</header>
<div
class="carousel"
id="carousel"
role="region"
aria-roledescription="carousel"
aria-label="Client testimonials"
>
<div class="viewport">
<ul class="track" id="track">
<!-- Slide 1 -->
<li class="slide" role="group" aria-roledescription="slide" aria-label="1 of 5">
<article class="card">
<span class="quote-mark" aria-hidden="true">“</span>
<div class="rating" role="img" aria-label="Rated 5 out of 5 stars" data-stars="5">
<span></span><span></span><span></span><span></span><span></span>
</div>
<blockquote>
I walked in unable to do a single pull-up. Twelve weeks later I'm repping sets of
eight. The programming was brutal and I loved every session.
</blockquote>
<div class="stat">
<span class="stat-num" data-count="24" data-suffix=" lb">0</span>
<span class="stat-label">Fat lost, muscle gained</span>
</div>
<footer class="who">
<span class="avatar" style="--img:url('https://images.unsplash.com/photo-1544005313-94ddf0286df2?w=160&h=160&fit=crop&crop=faces')"></span>
<div>
<p class="name">Maya Okonkwo</p>
<p class="prog"><span class="badge badge-lime">Strength Reset</span></p>
</div>
</footer>
</article>
</li>
<!-- Slide 2 -->
<li class="slide" role="group" aria-roledescription="slide" aria-label="2 of 5">
<article class="card">
<span class="quote-mark" aria-hidden="true">“</span>
<div class="rating" role="img" aria-label="Rated 5 out of 5 stars" data-stars="5">
<span></span><span></span><span></span><span></span><span></span>
</div>
<blockquote>
Coach rebuilt my running form from the ground up. Knocked almost four minutes off my
10K and my knees stopped screaming at me. Wild.
</blockquote>
<div class="stat">
<span class="stat-num" data-count="3.8" data-suffix=" min">0</span>
<span class="stat-label">Faster 10K time</span>
</div>
<footer class="who">
<span class="avatar" style="--img:url('https://images.unsplash.com/photo-1595152772835-219674b2a8a6?w=160&h=160&fit=crop&crop=faces')"></span>
<div>
<p class="name">Darnell Ruiz</p>
<p class="prog"><span class="badge badge-orange">Endurance Lab</span></p>
</div>
</footer>
</article>
</li>
<!-- Slide 3 -->
<li class="slide" role="group" aria-roledescription="slide" aria-label="3 of 5">
<article class="card">
<span class="quote-mark" aria-hidden="true">“</span>
<div class="rating" role="img" aria-label="Rated 4 out of 5 stars" data-stars="4">
<span></span><span></span><span></span><span></span><span></span>
</div>
<blockquote>
As a busy parent I never thought I'd stick with anything. The 30-minute home blocks
fit my life and I finally hit my first bodyweight squat PR.
</blockquote>
<div class="stat">
<span class="stat-num" data-count="118" data-suffix=" days">0</span>
<span class="stat-label">Longest streak, no misses</span>
</div>
<footer class="who">
<span class="avatar" style="--img:url('https://images.unsplash.com/photo-1573497019940-1c28c88b4f3e?w=160&h=160&fit=crop&crop=faces')"></span>
<div>
<p class="name">Priya Anand</p>
<p class="prog"><span class="badge badge-lime">Home HIIT</span></p>
</div>
</footer>
</article>
</li>
<!-- Slide 4 -->
<li class="slide" role="group" aria-roledescription="slide" aria-label="4 of 5">
<article class="card">
<span class="quote-mark" aria-hidden="true">“</span>
<div class="rating" role="img" aria-label="Rated 5 out of 5 stars" data-stars="5">
<span></span><span></span><span></span><span></span><span></span>
</div>
<blockquote>
I plateaued for two years lifting on my own. One quarter of real periodization and
my deadlift jumped past a number I'd chased forever.
</blockquote>
<div class="stat">
<span class="stat-num" data-count="85" data-suffix=" lb">0</span>
<span class="stat-label">Added to deadlift 1RM</span>
</div>
<footer class="who">
<span class="avatar" style="--img:url('https://images.unsplash.com/photo-1547425260-76bcadfb4f2c?w=160&h=160&fit=crop&crop=faces')"></span>
<div>
<p class="name">Theo Brandt</p>
<p class="prog"><span class="badge badge-orange">Powerbuild</span></p>
</div>
</footer>
</article>
</li>
<!-- Slide 5 -->
<li class="slide" role="group" aria-roledescription="slide" aria-label="5 of 5">
<article class="card">
<span class="quote-mark" aria-hidden="true">“</span>
<div class="rating" role="img" aria-label="Rated 5 out of 5 stars" data-stars="5">
<span></span><span></span><span></span><span></span><span></span>
</div>
<blockquote>
Post-injury I was terrified to train again. The rehab-first approach gave me my
confidence back and now I'm stronger than before I got hurt.
</blockquote>
<div class="stat">
<span class="stat-num" data-count="100" data-suffix="%">0</span>
<span class="stat-label">Back to full mobility</span>
</div>
<footer class="who">
<span class="avatar" style="--img:url('https://images.unsplash.com/photo-1580489944761-15a19d654956?w=160&h=160&fit=crop&crop=faces')"></span>
<div>
<p class="name">Lena Voss</p>
<p class="prog"><span class="badge badge-lime">Rebuild & Rise</span></p>
</div>
</footer>
</article>
</li>
</ul>
</div>
<div class="controls">
<button class="nav" id="prev" type="button" aria-label="Previous testimonial">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M15 6l-6 6 6 6" /></svg>
</button>
<div class="dots" id="dots" role="tablist" aria-label="Choose testimonial"></div>
<button class="nav" id="next" type="button" aria-label="Next testimonial">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9 6l6 6-6 6" /></svg>
</button>
</div>
<div class="progress" aria-hidden="true"><span id="bar"></span></div>
<p class="sr-only" id="live" aria-live="polite"></p>
</div>
<div class="cta-row">
<a class="cta" href="#" id="cta">Start your transformation
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
</a>
<button class="ghost" id="pauseBtn" type="button" aria-pressed="false">Pause autoplay</button>
</div>
</section>
</main>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>An energetic, dark-themed testimonials block built for personal-training and coaching landing pages. Each slide is a client quote card that stacks a circular photo, name and program badge with a bold result stat (weight lost, strength gained, minutes shaved off a run) and a five-star rating that fills in on view. The header carries an aggregate rating summary so prospects instantly read the social proof.
The cards live inside a fully keyboard-operable carousel. Users advance with the electric-lime arrow buttons, click the dot indicators, tap the number keys, or swipe on touch devices. Autoplay rotates through the roster and politely pauses on hover, focus or when the tab is hidden, while a slim progress bar shows how long until the next slide.
Everything is vanilla HTML, CSS and JavaScript with no dependencies. The layout collapses to a single-column, thumb-friendly view under 520px, respects prefers-reduced-motion, and exposes aria-live announcements plus visible focus rings so screen-reader and keyboard users get the same punchy experience.