3DEX Testimonials
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:'Inter',sans-serif;background:#fff;color:#1a1a1a}
.testi{max-width:1200px;margin:0 auto;padding:56px 24px 64px}
.head{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;margin-bottom:40px}
.eyebrow{font-size:13px;font-weight:600;letter-spacing:.14em;color:#555;margin-bottom:10px}
h2{font-size:clamp(28px,4vw,42px);font-weight:800;line-height:1.1}
.viewport{overflow:hidden;cursor:grab;user-select:none;touch-action:pan-y}
.viewport.dragging{cursor:grabbing}
.track{display:flex;align-items:stretch;transition:transform .5s cubic-bezier(.22,.61,.36,1)}
.slide{flex:0 0 100%;padding:0 10px}
@media(min-width:720px){
.slide{flex:0 0 50%}
}
@media(min-width:1020px){
.slide{flex:0 0 33.3333%}
}
.card{
border:1px solid #e6e3dc;
padding:28px 26px 105px;
min-height:340px;
height:100%;
position:relative;
background:#fff;
transition:border-color .25s ease
}
.card:hover{border-color:#DDA968}
.stars{display:flex;gap:5px;margin-bottom:18px}
.stars svg{width:18px;height:18px;fill:#DDA968}
.quote{font-size:15px;line-height:1.7;color:#4a4a4a;overflow-wrap:anywhere}
.person{
position:absolute;
left:26px;
right:26px;
bottom:24px;
display:flex;
align-items:center;
gap:14px;
padding-top:18px;
border-top:1px solid #eee
}
.avatar{
width:48px;
height:48px;
border-radius:50%;
flex-shrink:0;
display:flex;
align-items:center;
justify-content:center;
color:#fff;
font-weight:700;
font-size:15px
}
.p-role{font-size:12px;line-height:1.5;color:#777}
.p-name{font-size:15px;font-weight:700;margin-top:3px;color:#1a1a1a}
.dots{
display:flex;
justify-content:center;
align-items:center;
flex-wrap:wrap;
gap:8px;
margin-top:32px
}
.dot{
width:8px;
height:8px;
border-radius:50%;
background:#e0ddd4;
border:none;
cursor:pointer;
padding:0;
transition:background .2s ease,width .2s ease
}
.dot.active{background:#DDA968;width:22px;border-radius:5px}
@media(max-width:600px){
.testi{padding:40px 14px 48px}
.head{align-items:center;gap:12px;margin-bottom:28px}
.slide{padding:0 5px}
.card{padding:24px 20px 100px}
.person{left:20px;right:20px}
.quote{font-size:14px}
}
@media(prefers-reduced-motion:reduce){
.track,.dot{transition:none}
}
OUR TESTIMONIALS
What our clients say
/*
These are illustrative sample testimonials, not verified client endorsements.
Replace them with genuine client feedback and approved client details before
publishing them as real testimonials.
*/
const data = [
{
name:"Alex Morgan",
role:"Product Manager",
initials:"AM",
color:"#c98b5c",
quote:"A successful software project starts with a clear understanding of business needs. A thoughtful development process can help teams turn their ideas into practical digital solutions."
},
{
name:"Sophia Bennett",
role:"Business Founder",
initials:"SB",
color:"#5c7fc9",
quote:"Choosing the right technology approach is an important step for any growing business. Clear priorities and a well-planned roadmap make the development journey easier to manage."
},
{
name:"Daniel Foster",
role:"Technology Lead",
initials:"DF",
color:"#4a9d7c",
quote:"Modern businesses need software that fits their workflows. Understanding technical requirements early helps teams plan a solution that supports their day-to-day operations."
},
{
name:"Olivia Carter",
role:"Operations Manager",
initials:"OC",
color:"#b05c9d",
quote:"Business automation can help reduce repetitive tasks and create more consistent processes. The key is identifying the right opportunities before implementing a new solution."
},
{
name:"James Wilson",
role:"IT Manager",
initials:"JW",
color:"#c95c5c",
quote:"System integration requires careful planning and a good understanding of existing infrastructure. A structured approach helps businesses identify dependencies and technical requirements."
},
{
name:"Emma Richardson",
role:"Product Designer",
initials:"ER",
color:"#64748b",
quote:"Good digital experiences should be easy to understand and navigate. Keeping user needs at the center of design decisions helps create more intuitive applications."
},
{
name:"William Brooks",
role:"SaaS Founder",
initials:"WB",
color:"#a16207",
quote:"Building a SaaS product involves more than writing code. Product priorities, scalability, user experience, and long-term maintenance all deserve attention from the beginning."
},
{
name:"Isabella Reed",
role:"Project Coordinator",
initials:"IR",
color:"#0f766e",
quote:"Clear communication is essential throughout software development. Documented requirements and regular discussions help keep project goals and expectations aligned."
},
{
name:"Ethan Parker",
role:"Digital Business Owner",
initials:"EP",
color:"#9333ea",
quote:"A well-designed website can make it easier for customers to understand a business and explore its services. Performance, accessibility, and usability all matter."
},
{
name:"Charlotte Evans",
role:"Innovation Lead",
initials:"CE",
color:"#0369a1",
quote:"AI solutions work best when they address a clearly defined problem. Evaluating data, business objectives, and implementation requirements helps teams make informed decisions."
},
{
name:"Benjamin Hayes",
role:"Engineering Manager",
initials:"BH",
color:"#be185d",
quote:"Scalable software requires thoughtful architecture and a clear understanding of future needs. Planning for maintainability early can help teams manage change over time."
},
{
name:"Amelia Brooks",
role:"E-commerce Consultant",
initials:"AB",
color:"#4d7c0f",
quote:"E-commerce technology should make product discovery and purchasing straightforward. A smooth customer journey depends on usability, reliable functionality, and clear information."
},
{
name:"Lucas Bennett",
role:"Business Analyst",
initials:"LB",
color:"#c2410c",
quote:"The most useful technology solutions begin with a clear understanding of existing challenges. Mapping business processes helps define requirements before development begins."
},
{
name:"Mia Thompson",
role:"Mobile Product Lead",
initials:"MT",
color:"#4338ca",
quote:"Mobile applications should be designed around how people actually use their devices. Straightforward navigation, responsive interfaces, and reliable performance are important considerations."
},
{
name:"Noah Mitchell",
role:"Technology Consultant",
initials:"NM",
color:"#0e7490",
quote:"Technology decisions should support business goals rather than add unnecessary complexity. Comparing possible approaches helps teams choose solutions that fit their requirements."
}
];
const star = `
`;
const track = document.getElementById("track");
const dotsWrap = document.getElementById("dots");
const viewport = document.getElementById("viewport");
let index = 0;
let perView = getPerView();
let autoTimer = null;
let startX = 0;
let currentX = 0;
let dragging = false;
function getPerView(){
const width = window.innerWidth;
if(width >= 1020) return 3;
if(width >= 720) return 2;
return 1;
}
function maxIndex(){
return Math.max(0, data.length - perView);
}
function renderCards(){
track.innerHTML = "";
data.forEach(person => {
const slide = document.createElement("div");
slide.className = "slide";
const card = document.createElement("div");
card.className = "card";
const stars = document.createElement("div");
stars.className = "stars";
stars.innerHTML = star.repeat(5);
const quote = document.createElement("p");
quote.className = "quote";
quote.textContent = person.quote;
const personDetails = document.createElement("div");
personDetails.className = "person";
const avatar = document.createElement("div");
avatar.className = "avatar";
avatar.style.backgroundColor = person.color;
avatar.textContent = person.initials;
const textDetails = document.createElement("div");
const role = document.createElement("div");
role.className = "p-role";
role.textContent = person.role;
const name = document.createElement("div");
name.className = "p-name";
name.textContent = person.name;
textDetails.appendChild(role);
textDetails.appendChild(name);
personDetails.appendChild(avatar);
personDetails.appendChild(textDetails);
card.appendChild(stars);
card.appendChild(quote);
card.appendChild(personDetails);
slide.appendChild(card);
track.appendChild(slide);
});
}
function renderDots(){
dotsWrap.innerHTML = "";
for(let i = 0; i goTo(i, true));
dotsWrap.appendChild(dot);
}
}
function update(){
const slideWidth = 100 / perView;
track.style.transform = `translateX(-${index * slideWidth}%)`;
document.querySelectorAll(".dot").forEach((dot, i) => {
dot.classList.toggle("active", i === index);
});
}
function goTo(i, manual = false){
index = Math.max(0, Math.min(i, maxIndex()));
update();
if(manual) restartAuto();
}
function next(){
index = index >= maxIndex() ? 0 : index + 1;
update();
}
function prev(){
index = index clearInterval(autoTimer));
viewport.addEventListener("mouseleave", () => {
if(!dragging) startAuto();
});
window.addEventListener("resize", () => {
const newPerView = getPerView();
if(newPerView !== perView){
perView = newPerView;
index = Math.min(index, maxIndex());
renderDots();
update();
}
});
function dragStart(x){
dragging = true;
startX = x;
currentX = x;
viewport.classList.add("dragging");
clearInterval(autoTimer);
track.style.transition = "none";
}
function dragMove(x){
if(!dragging) return;
currentX = x;
const delta = currentX - startX;
const slideWidth = 100 / perView;
track.style.transform =
`translateX(calc(-${index * slideWidth}% + ${delta}px))`;
}
function dragEnd(){
if(!dragging) return;
dragging = false;
viewport.classList.remove("dragging");
track.style.transition = "";
const delta = currentX - startX;
const threshold = viewport.offsetWidth / perView / 4;
if(delta > threshold) prev();
else if(delta {
if(event.button !== 0) return;
dragStart(event.clientX);
});
window.addEventListener("mousemove", event => dragMove(event.clientX));
window.addEventListener("mouseup", dragEnd);
viewport.addEventListener("touchstart", event => {
dragStart(event.touches[0].clientX);
}, {passive:true});
viewport.addEventListener("touchmove", event => {
dragMove(event.touches[0].clientX);
}, {passive:true});
viewport.addEventListener("touchend", dragEnd);
viewport.addEventListener("touchcancel", dragEnd);
renderCards();
renderDots();
update();
startAuto();