354 lines
10 KiB
Vue
354 lines
10 KiB
Vue
<script setup>
|
|
import { computed } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import LandingSiteMenu from '@/features/landing/components/LandingSiteMenu.vue';
|
|
import { usePublicPageMeta } from '@/features/landing/publicPageMeta.js';
|
|
|
|
const { t } = useI18n();
|
|
|
|
usePublicPageMeta({
|
|
title: computed(() => t('public.landing.meta.title')),
|
|
description: computed(() => t('public.landing.meta.description')),
|
|
path: '/',
|
|
});
|
|
|
|
const pillarKeys = ['singleSource', 'collaboration', 'ownership'];
|
|
const focusMetricKeys = ['clients', 'campaigns', 'contentItems'];
|
|
const proofKeys = ['reviews', 'handoff', 'traceability'];
|
|
const mockupRowKeys = ['reel', 'launch', 'newsletter'];
|
|
|
|
const pillars = computed(() => [
|
|
...pillarKeys.map(key => ({
|
|
eyebrow: t(`public.landing.pillars.${key}.eyebrow`),
|
|
title: t(`public.landing.pillars.${key}.title`),
|
|
})),
|
|
]);
|
|
|
|
const focusMetrics = computed(() =>
|
|
focusMetricKeys.map(key => ({
|
|
label: t(`public.landing.focus.${key}.label`),
|
|
description: t(`public.landing.focus.${key}.description`),
|
|
}))
|
|
);
|
|
|
|
const proofPoints = computed(() =>
|
|
proofKeys.map(key => ({
|
|
label: t(`public.landing.proof.${key}.label`),
|
|
value: t(`public.landing.proof.${key}.value`),
|
|
}))
|
|
);
|
|
|
|
const mockupRows = computed(() =>
|
|
mockupRowKeys.map(key => ({
|
|
title: t(`public.landing.mockup.${key}.title`),
|
|
meta: t(`public.landing.mockup.${key}.meta`),
|
|
status: t(`public.landing.mockup.${key}.status`),
|
|
}))
|
|
);
|
|
</script>
|
|
|
|
<template>
|
|
<div class="landing-page">
|
|
<LandingSiteMenu />
|
|
|
|
<main class="landing-shell">
|
|
<section
|
|
id="products"
|
|
class="hero-card"
|
|
>
|
|
<div class="hero-copy">
|
|
<div class="eyebrow">{{ t('public.landing.hero.eyebrow') }}</div>
|
|
<h1>{{ t('public.landing.hero.title') }}</h1>
|
|
<p>{{ t('public.landing.hero.description') }}</p>
|
|
<div class="proof-row">
|
|
<div
|
|
v-for="proof in proofPoints"
|
|
:key="proof.label"
|
|
>
|
|
<strong>{{ proof.value }}</strong>
|
|
<span>{{ proof.label }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="hero-actions">
|
|
<router-link to="/register">
|
|
<button class="primary">{{ t('public.landing.hero.primaryAction') }}</button>
|
|
</router-link>
|
|
</div>
|
|
<span class="cta-note">{{ t('public.landing.hero.ctaNote') }}</span>
|
|
</div>
|
|
|
|
<div
|
|
class="workflow-preview"
|
|
aria-hidden="true"
|
|
>
|
|
<div class="preview-bar">
|
|
<span>{{ t('public.landing.mockup.title') }}</span>
|
|
<strong>{{ t('public.landing.mockup.badge') }}</strong>
|
|
</div>
|
|
<div class="preview-list">
|
|
<div
|
|
v-for="row in mockupRows"
|
|
:key="row.title"
|
|
class="preview-row"
|
|
>
|
|
<div>
|
|
<strong>{{ row.title }}</strong>
|
|
<span>{{ row.meta }}</span>
|
|
</div>
|
|
<em>{{ row.status }}</em>
|
|
</div>
|
|
</div>
|
|
<div class="approval-card">
|
|
<span>{{ t('public.landing.mockup.approvalLabel') }}</span>
|
|
<strong>{{ t('public.landing.mockup.approvalValue') }}</strong>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="pillars-grid">
|
|
<article
|
|
v-for="pillar in pillars"
|
|
:key="pillar.title"
|
|
class="pillar-card"
|
|
>
|
|
<div class="eyebrow">{{ pillar.eyebrow }}</div>
|
|
<p>{{ pillar.title }}</p>
|
|
</article>
|
|
</section>
|
|
|
|
<section class="focus-card">
|
|
<div>
|
|
<div class="eyebrow">{{ t('public.landing.focus.eyebrow') }}</div>
|
|
<h2>{{ t('public.landing.focus.title') }}</h2>
|
|
<router-link
|
|
class="inline-cta"
|
|
to="/register"
|
|
>
|
|
{{ t('public.landing.hero.primaryAction') }}
|
|
</router-link>
|
|
</div>
|
|
<div class="focus-metrics">
|
|
<div
|
|
v-for="metric in focusMetrics"
|
|
:key="metric.label"
|
|
>
|
|
<strong>{{ metric.label }}</strong>
|
|
<span>{{ metric.description }}</span>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="final-cta">
|
|
<div>
|
|
<div class="eyebrow">{{ t('public.landing.finalCta.eyebrow') }}</div>
|
|
<h2>{{ t('public.landing.finalCta.title') }}</h2>
|
|
<p>{{ t('public.landing.finalCta.description') }}</p>
|
|
</div>
|
|
<router-link to="/register">
|
|
<button class="primary">{{ t('public.landing.hero.primaryAction') }}</button>
|
|
</router-link>
|
|
</section>
|
|
|
|
</main>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.landing-page {
|
|
@apply min-h-screen w-full;
|
|
}
|
|
|
|
.landing-shell {
|
|
@apply mx-auto flex w-full max-w-7xl flex-col gap-8 px-5 py-8 md:px-8 md:py-12;
|
|
}
|
|
|
|
.hero-card {
|
|
@apply grid gap-8 overflow-hidden rounded-[2rem] p-6 md:grid-cols-[1fr_0.88fr] md:p-10;
|
|
background: linear-gradient(145deg, #172033 0%, #25324b 65%, #314766 100%);
|
|
color: #fffaf2;
|
|
box-shadow: 0 30px 80px rgba(23, 32, 51, 0.18);
|
|
}
|
|
|
|
.hero-copy {
|
|
@apply flex flex-col gap-5;
|
|
}
|
|
|
|
.hero-copy h1 {
|
|
@apply max-w-3xl text-4xl font-black leading-tight md:text-6xl;
|
|
}
|
|
|
|
.hero-copy p {
|
|
@apply max-w-2xl text-base leading-7 md:text-lg;
|
|
color: rgba(255, 250, 242, 0.84);
|
|
}
|
|
|
|
.eyebrow {
|
|
@apply text-xs font-bold uppercase tracking-[0.26em];
|
|
color: #ffb26b;
|
|
}
|
|
|
|
.hero-actions {
|
|
@apply flex flex-col gap-3 sm:flex-row;
|
|
}
|
|
|
|
.hero-actions .primary,
|
|
.final-cta .primary {
|
|
@apply min-h-12 px-7 text-base;
|
|
box-shadow: 0 18px 40px rgba(255, 138, 61, 0.28);
|
|
}
|
|
|
|
.cta-note {
|
|
@apply text-sm font-semibold;
|
|
color: rgba(255, 250, 242, 0.72);
|
|
}
|
|
|
|
.proof-row {
|
|
@apply grid max-w-2xl gap-3 sm:grid-cols-3;
|
|
}
|
|
|
|
.proof-row div {
|
|
@apply rounded-[1rem] border p-4;
|
|
background: rgba(255, 250, 242, 0.08);
|
|
border-color: rgba(255, 250, 242, 0.12);
|
|
}
|
|
|
|
.proof-row strong {
|
|
@apply block text-2xl font-black;
|
|
color: #7dd3c7;
|
|
}
|
|
|
|
.proof-row span {
|
|
@apply mt-1 block text-xs font-bold uppercase leading-5 tracking-[0.12em];
|
|
color: rgba(255, 250, 242, 0.72);
|
|
}
|
|
|
|
.workflow-preview {
|
|
@apply flex flex-col gap-4 rounded-[1.5rem] p-4;
|
|
background: rgba(255, 250, 242, 0.1);
|
|
border: 1px solid rgba(255, 250, 242, 0.14);
|
|
}
|
|
|
|
.preview-bar {
|
|
@apply flex items-center justify-between gap-3 rounded-[1rem] bg-white/90 px-4 py-3;
|
|
color: #172033;
|
|
}
|
|
|
|
.preview-bar span,
|
|
.approval-card span {
|
|
@apply text-xs font-black uppercase tracking-[0.18em];
|
|
color: #0f766e;
|
|
}
|
|
|
|
.preview-bar strong {
|
|
@apply rounded-full px-3 py-1 text-xs font-black;
|
|
background: rgba(255, 138, 61, 0.14);
|
|
color: #b45309;
|
|
}
|
|
|
|
.preview-list {
|
|
@apply flex flex-col gap-3;
|
|
}
|
|
|
|
.preview-row {
|
|
@apply flex items-center justify-between gap-4 rounded-[1rem] bg-white/90 p-4;
|
|
color: #172033;
|
|
}
|
|
|
|
.preview-row strong {
|
|
@apply block text-sm font-black;
|
|
}
|
|
|
|
.preview-row span {
|
|
@apply mt-1 block text-xs font-semibold;
|
|
color: #44516a;
|
|
}
|
|
|
|
.preview-row em {
|
|
@apply rounded-full px-3 py-1 text-xs font-black not-italic;
|
|
background: rgba(15, 118, 110, 0.1);
|
|
color: #0f766e;
|
|
}
|
|
|
|
.approval-card {
|
|
@apply rounded-[1rem] bg-white/95 p-5;
|
|
color: #172033;
|
|
}
|
|
|
|
.approval-card strong {
|
|
@apply mt-2 block text-2xl font-black leading-tight;
|
|
}
|
|
|
|
.pillars-grid {
|
|
@apply grid gap-4 md:grid-cols-3;
|
|
}
|
|
|
|
.pillar-card {
|
|
@apply rounded-[1.5rem] p-6;
|
|
background: rgba(255, 255, 255, 0.84);
|
|
border: 1px solid rgba(23, 32, 51, 0.08);
|
|
box-shadow: 0 18px 40px rgba(23, 32, 51, 0.06);
|
|
}
|
|
|
|
.pillar-card p {
|
|
@apply mt-3 text-lg font-semibold leading-7;
|
|
color: #172033;
|
|
}
|
|
|
|
.focus-card {
|
|
@apply grid gap-6 rounded-[1.75rem] p-6 md:grid-cols-[1fr_1.1fr] md:p-8;
|
|
background: linear-gradient(135deg, rgba(255, 138, 61, 0.12), rgba(52, 211, 153, 0.1));
|
|
border: 1px solid rgba(23, 32, 51, 0.08);
|
|
}
|
|
|
|
.focus-card h2 {
|
|
@apply mt-3 text-2xl font-black leading-tight md:text-3xl;
|
|
color: #172033;
|
|
}
|
|
|
|
.inline-cta {
|
|
@apply mt-5 inline-flex h-11 items-center rounded-full px-5 text-sm font-black no-underline transition-colors;
|
|
background: #172033;
|
|
color: #fffaf2;
|
|
}
|
|
|
|
.inline-cta:hover {
|
|
background: #0f766e;
|
|
}
|
|
|
|
.focus-metrics {
|
|
@apply grid gap-4 md:grid-cols-3;
|
|
}
|
|
|
|
.focus-metrics div {
|
|
@apply rounded-[1.25rem] bg-white/70 p-5;
|
|
border: 1px solid rgba(23, 32, 51, 0.06);
|
|
}
|
|
|
|
.focus-metrics strong {
|
|
@apply block text-sm font-black uppercase tracking-[0.18em];
|
|
color: #0f766e;
|
|
}
|
|
|
|
.focus-metrics span {
|
|
@apply mt-2 block text-sm leading-6;
|
|
color: #3f4d63;
|
|
}
|
|
|
|
.final-cta {
|
|
@apply flex flex-col gap-6 rounded-[2rem] p-6 md:flex-row md:items-center md:justify-between md:p-10;
|
|
background: #172033;
|
|
color: #fffaf2;
|
|
box-shadow: 0 30px 80px rgba(23, 32, 51, 0.18);
|
|
}
|
|
|
|
.final-cta h2 {
|
|
@apply mt-3 max-w-3xl text-3xl font-black leading-tight md:text-5xl;
|
|
}
|
|
|
|
.final-cta p {
|
|
@apply mt-4 max-w-2xl text-base leading-7;
|
|
color: rgba(255, 250, 242, 0.78);
|
|
}
|
|
|
|
</style>
|