Adds consultation leads, section editors, and the one-time content reset for this release. Co-authored-by: Cursor <cursoragent@cursor.com>
84 lines
4.3 KiB
Vue
84 lines
4.3 KiB
Vue
<template>
|
|
<section id="testimonials" class="py-24 bg-slate-50/70 dark:bg-[#070d19]/90 overflow-hidden relative">
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 items-center">
|
|
<div class="lg:col-span-7 relative flex justify-center items-center py-10 fade-item">
|
|
<div
|
|
v-for="(src, i) in decorAvatars"
|
|
:key="i"
|
|
class="absolute w-14 h-14 rounded-full bg-white dark:bg-slate-800 shadow-md p-1 border border-slate-200 dark:border-slate-700 opacity-60"
|
|
:class="i === 0 ? '-right-2 top-4' : '-right-4 bottom-6'"
|
|
aria-hidden="true"
|
|
>
|
|
<SafeImage :src="src" alt="" width="56" height="56" class="w-full h-full rounded-full object-cover" />
|
|
</div>
|
|
|
|
<figure class="relative z-10 w-full max-w-lg bg-white dark:bg-slate-900/95 rounded-3xl p-8 border border-slate-100 dark:border-slate-800 shadow-xl space-y-6 text-right">
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center gap-1.5 text-xs font-bold text-brand-600 dark:text-brand-400 bg-brand-50 dark:bg-brand-950/60 px-3 py-1 rounded-full border border-brand-100 dark:border-brand-900/50">
|
|
<svg class="w-4 h-4 text-brand-600 dark:text-brand-400" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
|
|
</svg>
|
|
<span>{{ t.badge }}</span>
|
|
</div>
|
|
<div class="text-slate-300 dark:text-slate-700" aria-hidden="true">
|
|
<svg class="w-8 h-8" fill="currentColor" viewBox="0 0 24 24">
|
|
<path d="M14.017 21v-7.391c0-5.704 3.731-9.57 8.983-10.609l.995 2.151c-2.432.917-3.995 3.638-3.995 5.849h4v10h-9.983zm-14.017 0v-7.391c0-5.704 3.748-9.57 9-10.609l.996 2.151c-2.433.917-3.996 3.638-3.996 5.849h3.983v10h-9.983z" />
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
|
|
<blockquote class="text-slate-800 dark:text-slate-100 text-lg font-bold leading-relaxed min-h-[60px]">
|
|
{{ t.quote }}
|
|
</blockquote>
|
|
|
|
<figcaption class="flex items-center justify-end gap-3 pt-4 border-t border-slate-100 dark:border-slate-800">
|
|
<div class="text-right">
|
|
<div class="font-bold text-slate-900 dark:text-white text-sm">{{ t.name }}</div>
|
|
<div class="text-xs text-slate-400 dark:text-slate-500 font-medium">{{ t.role }}</div>
|
|
</div>
|
|
<div class="w-12 h-12 rounded-full overflow-hidden border-2 border-brand-500 shadow-sm">
|
|
<SafeImage :src="t.avatarUrl" :alt="t.name" width="48" height="48" class="w-full h-full object-cover" />
|
|
</div>
|
|
</figcaption>
|
|
</figure>
|
|
</div>
|
|
|
|
<div class="lg:col-span-5 text-right space-y-5 fade-item">
|
|
<span class="text-xs font-bold text-slate-400 dark:text-slate-500">{{ t.eyebrow }}</span>
|
|
|
|
<h2 class="text-3xl sm:text-4xl font-black text-slate-900 dark:text-white leading-snug">
|
|
{{ t.titleLine1 }}
|
|
<br>
|
|
<span>{{ t.titleLine2 }}</span>
|
|
</h2>
|
|
|
|
<p class="text-base text-slate-600 dark:text-slate-300 leading-relaxed font-normal">
|
|
{{ t.body }}
|
|
</p>
|
|
|
|
<div class="pt-2">
|
|
<button
|
|
type="button"
|
|
class="inline-flex items-center gap-2.5 px-6 py-3 rounded-full bg-brand-600 text-white font-bold text-sm hover:bg-brand-700 active:scale-95 transition-all duration-300 shadow-md shadow-brand-600/25"
|
|
@click="consult.open()"
|
|
>
|
|
<svg class="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
|
|
</svg>
|
|
<span>{{ t.ctaLabel }}</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
const { section } = useSiteContent();
|
|
const t = section("testimonials");
|
|
const consult = useConsultModal();
|
|
const decorAvatars = computed(() => t.value.decorAvatars.slice(0, 2));
|
|
</script>
|