feat(marketing): cross-device pricing-hero + Header-Nav statt Tabbar (live prod)

- Pricing: Device-Hero-Reihe (iPhone/Android/Mac/Windows) + Tagline 'ein Abo,
  alle Geräte' — heroicons (offline gebündelt)
- Layout: Floating-Tabbar raus -> Header-Nav (Desktop) / Hamburger (mobil)
- Locales: cross_device_tagline + Geräte-Matrix-Texte

Deployed: rebreak.org (marketing-prod) via deploy-marketing.sh

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
chahinebrini 2026-06-07 22:56:14 +02:00
parent 7ad8625d8e
commit e0cb0517fc
4 changed files with 81 additions and 57 deletions

View File

@ -1,36 +1,61 @@
<template>
<div data-layout="default" class="flex flex-col overflow-hidden bg-default text-highlighted"
:style="{ height: vpHeight + 'px' }">
<!-- Header sticky, innerhalb des Flex-Flows -->
<header class="shrink-0 h-16 border-b border-default bg-default/95 backdrop-blur-md">
<!-- Header sticky -->
<header class="shrink-0 h-16 border-b border-default bg-default/95 backdrop-blur-md relative z-50">
<div class="max-w-6xl mx-auto px-4 sm:px-6 h-full flex items-center justify-between">
<NuxtLink to="/" class="flex items-center gap-2">
<NuxtLink to="/" class="flex items-center gap-2" @click="menuOpen = false">
<div class="w-8 h-8 rounded-lg bg-primary flex items-center justify-center">
<UIcon name="i-heroicons-shield-check" class="text-white" />
</div>
<span class="font-bold text-lg text-highlighted">ReBreak</span>
</NuxtLink>
<nav class="hidden sm:flex items-center gap-6 text-sm text-muted">
<NuxtLink to="/pricing" class="hover:text-highlighted transition-colors">{{ $t("nav.pricing") }}</NuxtLink>
<NuxtLink to="/resources" class="hover:text-highlighted transition-colors">{{ $t("nav.resources") }}</NuxtLink>
<!-- Desktop-Nav (große Screens) -->
<nav class="hidden md:flex items-center gap-6 text-sm text-muted">
<NuxtLink v-for="link in navLinks" :key="link.to" :to="link.to"
class="transition-colors"
:class="isActive(link.to) ? 'text-highlighted font-semibold' : 'hover:text-highlighted'">
{{ link.label }}
</NuxtLink>
</nav>
<!-- App-Download CTA statt Login (Marketing hat keine Auth) -->
<div class="flex items-center gap-3">
<a href="https://apps.apple.com/app/rebreak" target="_blank" rel="noopener">
<div class="flex items-center gap-2">
<a href="https://apps.apple.com/app/rebreak" target="_blank" rel="noopener" class="hidden sm:block">
<UButton size="sm" color="primary">{{ $t("nav.download_app") }}</UButton>
</a>
<!-- Hamburger (kleine Screens) -->
<UButton class="md:hidden" color="neutral" variant="ghost" size="md"
:icon="menuOpen ? 'i-heroicons-x-mark' : 'i-heroicons-bars-3'"
:aria-label="menuOpen ? 'Menü schließen' : 'Menü öffnen'" @click="menuOpen = !menuOpen" />
</div>
</div>
<!-- Mobile-Menü (Slide-Down aus dem Header) -->
<Transition enter-active-class="transition duration-150 ease-out" enter-from-class="opacity-0 -translate-y-2"
enter-to-class="opacity-100 translate-y-0" leave-active-class="transition duration-100 ease-in"
leave-from-class="opacity-100 translate-y-0" leave-to-class="opacity-0 -translate-y-2">
<nav v-if="menuOpen"
class="md:hidden absolute top-16 inset-x-0 border-b border-default bg-default/98 backdrop-blur-md px-4 py-3 flex flex-col gap-1 shadow-lg">
<NuxtLink v-for="link in navLinks" :key="link.to" :to="link.to" @click="menuOpen = false"
class="flex items-center gap-3 px-3 py-3 rounded-xl text-sm transition-colors"
:class="isActive(link.to) ? 'bg-elevated text-highlighted font-semibold' : 'text-muted hover:bg-elevated'">
<UIcon :name="link.icon" class="size-5 shrink-0" />
{{ link.label }}
</NuxtLink>
<a href="https://apps.apple.com/app/rebreak" target="_blank" rel="noopener" class="mt-2">
<UButton block color="primary">{{ $t("nav.download_app") }}</UButton>
</a>
</nav>
</Transition>
</header>
<!-- Scrollbarer Inhalt -->
<div class="flex-1 overflow-y-auto">
<div class="flex-1 overflow-y-auto" @click="menuOpen = false">
<slot />
<!-- DSGVO-Pflicht: Datenschutz + Impressum public erreichbar -->
<footer class="border-t border-default mt-12 pb-24 md:pb-6 pt-6 px-4">
<footer class="border-t border-default mt-12 pb-6 pt-6 px-4">
<div
class="max-w-6xl mx-auto flex flex-col sm:flex-row items-center justify-between gap-3 text-xs text-muted">
<p>© {{ new Date().getFullYear() }} Rebreak</p>
@ -44,21 +69,6 @@
</div>
</footer>
</div>
<!-- Floating Pill Tab-Bar (Mobile) -->
<div class="fixed bottom-3 left-4 right-4 z-50 pointer-events-none">
<nav
class="pointer-events-auto max-w-lg mx-auto bg-white/80 dark:bg-elevated backdrop-blur-md rounded-4xl shadow-[0_4px_24px_rgba(0,0,0,0.12)] dark:shadow-[0_4px_24px_rgba(0,0,0,0.3)] ring-1 ring-black/10 dark:ring-white/10 px-2 py-1.5">
<div class="flex items-center">
<NuxtLink v-for="tab in tabs" :key="tab.to" :to="tab.to"
class="relative flex-1 flex flex-col items-center gap-0.5 px-1 py-1.5 rounded-3xl transition-colors"
:class="isActive(tab.to) ? 'text-primary-400' : 'text-muted'">
<UIcon :name="isActive(tab.to) ? tab.iconActive : tab.icon" class="size-6 shrink-0" />
<span class="text-[10px] leading-none whitespace-nowrap font-semibold">{{ tab.label }}</span>
</NuxtLink>
</div>
</nav>
</div>
</div>
</template>
@ -66,28 +76,18 @@
const { height: vpHeight } = useViewportHeight();
const route = useRoute();
const { t } = useI18n();
const menuOpen = ref(false);
const tabs = computed(() => [
{
to: "/",
icon: "i-heroicons-home",
iconActive: "i-heroicons-home-solid",
label: t('pricing.footer_home'),
},
{
to: "/pricing",
icon: "i-heroicons-credit-card",
iconActive: "i-heroicons-credit-card-solid",
label: t('pricing.footer_pricing'),
},
{
to: "/resources",
icon: "i-heroicons-book-open",
iconActive: "i-heroicons-book-open-solid",
label: t('pricing.footer_resources'),
},
// Eine Nav-Quelle für Desktop-Header UND Mobile-Hamburger (keine Tabbar mehr).
const navLinks = computed(() => [
{ to: "/", icon: "i-heroicons-home", label: t('pricing.footer_home') },
{ to: "/pricing", icon: "i-heroicons-credit-card", label: t('nav.pricing') },
{ to: "/resources", icon: "i-heroicons-book-open", label: t('nav.resources') },
]);
// Menü bei Routenwechsel schließen
watch(() => route.path, () => { menuOpen.value = false; });
function isActive(to: string) {
if (to === "/") return route.path === "/";
return route.path.startsWith(to);

View File

@ -146,6 +146,7 @@
"title": "Dein Weg, dein Tempo",
"subtitle_start": "Jetzt starten ",
"subtitle_end": "wähle deinen Plan.",
"cross_device_tagline": "Ein Abo schützt alle deine Geräte Handy und Computer, geräteübergreifend.",
"pro_meaning_title": "Was bedeutet Pro wirklich?",
"pro_meaning_desc": "Mit Pro trägst du aktiv dazu bei, dass die ReBreak Blocklist für alle wächst. Du kannst Domains direkt hinzufügen und Einreichungen anderer Nutzer prüfen. Du leitest Gruppen, hast keinen KI-Gedächtnisverlust und stehst an der Spitze für alle, die noch kämpfen.",
"comparison_title": "Was ist inklusive?",
@ -172,11 +173,11 @@
"plan_pro_desc": "Voller Schutz für ein Gerät alles, was du im Alltag brauchst.",
"plan_pro_btn": "Pro starten",
"plan_legend_title": "Legend",
"plan_legend_desc": "Maximaler Schutz für bis zu 3 Geräte inkl. Selbstbindungs-Modus.",
"plan_legend_desc": "Lückenloser Schutz auf bis zu 5 Geräten inkl. Selbstbindungs-Modus.",
"plan_legend_btn": "Legend starten",
"plan_loading": "Wird geladen...",
"plan_recommended": "Empfohlen",
"feat_pro_devices": "1 Gerät (iOS, Android oder macOS)",
"feat_pro_devices": "2 Geräte 1 Smartphone (iOS/Android) + 1 Computer (Mac oder Windows)",
"feat_pro_domains": "5 eigene Domains (rückfüllbar)",
"feat_pro_mail": "Echtzeit-Mail-Schutz (IMAP-IDLE, 2 Konten)",
"feat_blocklist": "ReBreak Blocklist (208k+ Domains)",
@ -189,7 +190,7 @@
"feat_buddy": "Buddy System",
"feat_urge_stats": "Urge-Statistiken & Muster",
"feat_all_pro": "Alles aus Pro",
"feat_legend_devices": "Bis zu 3 Geräte (iOS, Android, macOS)",
"feat_legend_devices": "5 Geräte 3 mobil (iOS/Android) + 2 stationär (Mac & Windows)",
"feat_legend_domains": "Unbegrenzte eigene Domains",
"feat_legend_mail": "Echtzeit-Mail-Schutz (IMAP-IDLE, unbegrenzte Konten)",
"feat_legend_binder": "RebReakBinder Selbstbindungs-Modus (opt-in, macOS)",
@ -213,8 +214,8 @@
"comp_add_domain": "Domains zur Blocklist hinzufügen",
"comp_validate": "Community-Domains validieren",
"comp_groups": "Gruppen gründen & leiten",
"comp_pro_devices": "1",
"comp_legend_devices": "bis 3",
"comp_pro_devices": "2 (1 mobil + 1 Computer)",
"comp_legend_devices": "5 (3 mobil + 2 Computer)",
"comp_pro_domains": "5 (rückfüllbar)",
"comp_legend_domains": "Unbegrenzt",
"comp_pro_mail_val": "Echtzeit · 2 Konten",
@ -224,7 +225,7 @@
"faq1_q": "Muss ich eine E-Mail-Adresse angeben?",
"faq1_a": "Ja, für die Registrierung wird eine E-Mail-Adresse benötigt. Deine Daten werden ausschließlich auf deutschen Servern gespeichert und verarbeitet vollständig anonym, nach strengen DSGVO-Standards. Kein Name, kein Standort, kein Nutzungsverhalten wird an Dritte weitergegeben.",
"faq2_q": "Was ist der Unterschied zwischen Pro und Legend?",
"faq2_a": "Pro schützt EIN Gerät mit Echtzeit-Mail-Schutz (IMAP-IDLE, 2 Konten), ReBreak Blocklist (208k+ Domains) und Lyra mit Streak/Urge-Stats. Legend deckt BIS ZU 3 Geräte ab, hat unbegrenzte Mail-Konten und Domains, schaltet den RebReakBinder-Selbstbindungs-Modus (macOS) frei und gibt dir Lyra mit Langzeit-Gedächtnis sowie Gruppen-Leitung.",
"faq2_a": "Pro schützt 2 Geräte dein Smartphone und deinen Computer (Mac oder Windows) mit Echtzeit-Mail-Schutz (IMAP-IDLE, 2 Konten), ReBreak Blocklist (208k+ Domains) und Lyra mit Streak/Urge-Stats. Legend deckt BIS ZU 5 Geräte ab (3 mobil + 2 stationär), hat unbegrenzte Mail-Konten und Domains, schaltet den Rebreak-Magic-Selbstbindungs-Modus frei und gibt dir Lyra mit Langzeit-Gedächtnis sowie Gruppen-Leitung.",
"faq3_q": "Welche Zahlungszyklen gibt es?",
"faq3_a": "Monatlich (voller Preis) oder jährlich (Spare 39%). Du kannst jederzeit wechseln.",
"faq4_q": "Kann ich jederzeit kündigen?",

View File

@ -146,6 +146,7 @@
"title": "Your path, your pace",
"subtitle_start": "Start now ",
"subtitle_end": "choose your plan.",
"cross_device_tagline": "One subscription protects all your devices phone and computer, everywhere.",
"pro_meaning_title": "What does Pro really mean?",
"pro_meaning_desc": "With Pro you actively contribute to growing the ReBreak blocklist for everyone. You can add domains directly and review submissions from other users. You lead groups, have no AI memory loss and stand at the forefront for everyone still fighting.",
"comparison_title": "What's included?",
@ -172,11 +173,11 @@
"plan_pro_desc": "Full protection for one device everything you need day to day.",
"plan_pro_btn": "Start Pro",
"plan_legend_title": "Legend",
"plan_legend_desc": "Maximum protection for up to 3 devices incl. self-binding mode.",
"plan_legend_desc": "Seamless protection on up to 5 devices incl. self-binding mode.",
"plan_legend_btn": "Start Legend",
"plan_loading": "Loading...",
"plan_recommended": "Recommended",
"feat_pro_devices": "1 device (iOS, Android or macOS)",
"feat_pro_devices": "2 devices 1 smartphone (iOS/Android) + 1 computer (Mac or Windows)",
"feat_pro_domains": "5 custom domains (refillable)",
"feat_pro_mail": "Real-time mail protection (IMAP IDLE, 2 accounts)",
"feat_blocklist": "ReBreak Blocklist (208k+ domains)",
@ -189,7 +190,7 @@
"feat_buddy": "Buddy System",
"feat_urge_stats": "Urge statistics & patterns",
"feat_all_pro": "Everything in Pro",
"feat_legend_devices": "Up to 3 devices (iOS, Android, macOS)",
"feat_legend_devices": "5 devices 3 mobile (iOS/Android) + 2 desktop (Mac & Windows)",
"feat_legend_domains": "Unlimited custom domains",
"feat_legend_mail": "Real-time mail protection (IMAP IDLE, unlimited accounts)",
"feat_legend_binder": "RebReakBinder self-binding mode (opt-in, macOS)",
@ -213,8 +214,8 @@
"comp_add_domain": "Add domains to blocklist",
"comp_validate": "Validate community domains",
"comp_groups": "Create & lead groups",
"comp_pro_devices": "1",
"comp_legend_devices": "up to 3",
"comp_pro_devices": "2 (1 mobile + 1 computer)",
"comp_legend_devices": "5 (3 mobile + 2 desktop)",
"comp_pro_domains": "5 (refillable)",
"comp_legend_domains": "Unlimited",
"comp_pro_mail_val": "Real-time · 2 accounts",
@ -224,7 +225,7 @@
"faq1_q": "Do I need to provide an email address?",
"faq1_a": "Yes, an email address is required for registration. Your data is stored and processed exclusively on German servers fully anonymously, according to strict GDPR standards.",
"faq2_q": "What's the difference between Pro and Legend?",
"faq2_a": "Pro protects ONE device with real-time mail protection (IMAP IDLE, 2 accounts), ReBreak Blocklist (208k+ domains) and Lyra with streak/urge stats. Legend covers UP TO 3 devices, has unlimited mail accounts and domains, unlocks the RebReakBinder self-binding mode (macOS) and gives you Lyra with long-term memory plus group leadership.",
"faq2_a": "Pro protects 2 devices your smartphone and your computer (Mac or Windows) with real-time mail protection (IMAP IDLE, 2 accounts), ReBreak Blocklist (208k+ domains) and Lyra with streak/urge stats. Legend covers UP TO 5 devices (3 mobile + 2 desktop), has unlimited mail accounts and domains, unlocks the Rebreak Magic self-binding mode and gives you Lyra with long-term memory plus group leadership.",
"faq3_q": "What billing cycles are available?",
"faq3_a": "Monthly (full price) or yearly (save 39%). You can switch at any time.",
"faq4_q": "Can I cancel at any time?",

View File

@ -23,6 +23,20 @@
</span>
</h1>
<!-- Geräteübergreifender Schutz Device-Hero -->
<div class="mt-8 flex flex-col items-center gap-4">
<p class="text-sm text-muted max-w-md">{{ $t('pricing.cross_device_tagline') }}</p>
<div class="flex items-center justify-center gap-4 sm:gap-6">
<div v-for="d in crossDevices" :key="d.label" class="flex flex-col items-center gap-2">
<div
class="w-14 h-14 rounded-2xl bg-elevated border border-default flex items-center justify-center">
<UIcon :name="d.icon" class="text-primary-300 text-2xl" />
</div>
<span class="text-xs text-muted font-medium">{{ d.label }}</span>
</div>
</div>
</div>
<!-- Billing Cycle Picker -->
<div class="flex items-center justify-center gap-2 mt-8">
<button v-for="opt in billingOptions" :key="opt.value" @click="billing = opt.value"
@ -163,6 +177,14 @@ const billingOptions = computed(() => [
{ value: 'yearly', label: t('pricing.billing_yearly'), badge: t('pricing.billing_save_pct') },
] as const);
// Geräteübergreifend: ein Abo, alle Plattformen (heroicons sind offline gebündelt).
const crossDevices = [
{ icon: 'i-heroicons-device-phone-mobile', label: 'iPhone' },
{ icon: 'i-heroicons-device-phone-mobile', label: 'Android' },
{ icon: 'i-heroicons-computer-desktop', label: 'Mac' },
{ icon: 'i-heroicons-computer-desktop', label: 'Windows' },
];
const proMonthly = 3.99;
const legendMonthly = 7.99;