Hub-Inhalte: Claims korrigiert + Widerrufs-UI zurueckgebaut (B2B-only, E2)

- Registrierungs-Schritt ehrlich beschrieben (E-Mail/Google, Freischaltung
  nach E-Mail-Bestaetigung statt 'direkt freigeschaltet'; Magic-Link ist
  nur Anmeldeweg)
- Newsroom-Karte: 'getrennte Berechtigungen'/'mehrere Redakteure' durch
  belegbare Aussagen ersetzt (keine Team-Verwaltung im Panel)
- Kuendigungs-FAQ nach E5 (Jahreszahlweise 12 Monate, danach monatlich)
  + Link auf die Selfservice-Kuendigungsseite
- B2B-Erkennbarkeits-Satz im Tarife-Intro (AGB v0.6 / T14)
- Wording T16: 'Inhaltsprüfung' statt Redakteurs-Versprechen; 'kein
  automatisierter Durchlauf'-Behauptung entfernt
- Widerrufs-Button + Modal-Includes entfernt (Entscheidung E2 B2B-only,
  T3neu: Kuendigungsbutton bleibt freiwillig); Backend/Route bleibt
  schlafend erhalten, reaktivierbar bei B2C-Oeffnung
- Hub-FAQ/Footer verlinken die API-Seite statt der toten docs-Route

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-07-03 15:35:03 +00:00
parent f46795ba77
commit 9c9f7f7144
8 changed files with 47 additions and 319 deletions

View file

@ -54,7 +54,7 @@
<ul class="space-y-2 text-[13px] text-white/75 list-none p-0 m-0">
<li><a href="{{ route('home') }}#funktion" class="hover:text-white transition-colors">So funktioniert es</a></li>
<li><a href="{{ route('home') }}#familie" class="hover:text-white transition-colors">Die Portale</a></li>
<li><a href="{{ route('docs.api.v1') }}" class="hover:text-white transition-colors">API-Referenz</a></li>
<li><a href="{{ route('api', ['edition' => 'de']) }}" class="hover:text-white transition-colors">API-Referenz</a></li>
</ul>
</div>
@ -66,14 +66,10 @@
<li><a href="{{ route('datenschutz', ['edition' => 'de']) }}" class="hover:text-white transition-colors">Datenschutz</a></li>
<li><a href="{{ route('cookies', ['edition' => 'de']) }}" class="hover:text-white transition-colors">Cookies</a></li>
</ul>
{{-- Gesetzliche Buttons: Widerruf (Modal) + Kündigungsbutton § 312k BGB
(„Verträge hier kündigen", ständig verfügbar, führt unmittelbar
auf die Bestätigungsseite). --}}
{{-- Selfservice-Kündigung ohne Login (Entscheidung E2/T3neu: B2B-only,
der Button bleibt freiwillig über den B2B-Standard hinaus erhalten;
der frühere Widerrufs-Button entfällt — reaktivierbar bei B2C-Öffnung). --}}
<div class="mt-4 flex flex-col items-start gap-2.5">
<button type="button" x-data @click="$dispatch('open-withdrawal-modal')"
class="inline-flex items-center justify-center px-4 py-2 text-[12.5px] font-semibold text-white border border-white/40 hover:border-white hover:bg-white/10 rounded-[4px] transition-colors cursor-pointer">
Vertrag widerrufen
</button>
<a href="{{ route('kuendigung', ['edition' => 'de']) }}"
class="inline-flex items-center justify-center px-4 py-2 text-[12.5px] font-semibold text-white border border-white/40 hover:border-white hover:bg-white/10 rounded-[4px] transition-colors">
Verträge hier kündigen

View file

@ -69,7 +69,6 @@
@if ($isHub)
<x-web.hub.contact-modal />
<x-web.hub.withdrawal-modal />
<x-web.hub.site-footer />
@else
<x-web.site-footer />

View file

@ -1,145 +0,0 @@
@extends('web.layouts.web-master')
@section('title', 'Kontakt')
@section('meta_description', 'Kontaktieren Sie uns per E-Mail, Telefon oder vor Ort – wir helfen Ihnen gerne weiter.')
@php
$brand = config('domains.domains.'.config('app.theme').'.brand', []);
$brandLabel = ($brand['name'] ?? 'businessportal').($brand['accent'] ?? '');
$contactEmail = $brand['contact_email'] ?? 'info@businessportal.de';
$contactMethods = [
['label' => 'E-Mail', 'value' => $contactEmail, 'href' => 'mailto:'.$contactEmail, 'note' => 'Antwort i. d. R. innerhalb von 24 Stunden'],
['label' => 'Telefon', 'value' => '+49 89 1234 5678', 'href' => 'tel:+498912345678', 'note' => 'Mo–Fr 9:00–18:00 Uhr'],
['label' => 'Adresse', 'value' => 'Maximilianstraße 35', 'href' => null, 'note' => '80539 München, Deutschland'],
['label' => 'Geschäftszeiten', 'value' => 'Mo–Fr 9:00–18:00', 'href' => null, 'note' => 'Sa–So geschlossen'],
];
@endphp
@section('content')
<x-web.static-page
eyebrow="Kontakt"
title="Kontakt"
lead="Wir sind für Sie da – per E-Mail, Telefon oder vor Ort in München. Wählen Sie den Weg, der Ihnen am besten passt."
breadcrumb="Kontakt"
>
{{-- Kontaktwege --}}
<div class="grid gap-px bg-bg-rule border border-bg-rule grid-cols-1 sm:grid-cols-2 lg:grid-cols-4">
@foreach ($contactMethods as $method)
<div class="bg-bg p-6">
<div class="eyebrow muted mb-2">{{ $method['label'] }}</div>
@if ($method['href'])
<a href="{{ $method['href'] }}" class="text-[15px] font-semibold text-ink hover:text-brand transition-colors break-words">{{ $method['value'] }}</a>
@else
<div class="text-[15px] font-semibold text-ink break-words">{{ $method['value'] }}</div>
@endif
<p class="text-[12px] text-ink-3 mt-1 mb-0">{{ $method['note'] }}</p>
</div>
@endforeach
</div>
{{-- Besuch / Anfahrt --}}
<div class="grid gap-8 lg:grid-cols-[1.2fr_1fr] mt-12">
<div class="pm-body">
<h2>Schreiben Sie uns</h2>
<p>
Haben Sie Fragen oder benötigen Sie Unterstützung? Schreiben Sie uns direkt an
<a href="mailto:{{ $contactEmail }}">{{ $contactEmail }}</a> – unser Team meldet sich
schnellstmöglich bei Ihnen zurück. Für häufige Fragen lohnt sich vorab ein Blick in unsere
<a href="{{ route('faq') }}">FAQ</a> oder das <a href="{{ route('hilfe') }}">Hilfe-Center</a>.
</p>
@if (session('contact-status'))
<div class="px-4 py-3 border border-bg-rule bg-bg-elev text-[13px] text-ink leading-relaxed mb-6" role="status">
{{ session('contact-status') }}
</div>
@else
<form method="POST" action="{{ route('kontakt.store') }}" class="space-y-5 mb-8" novalidate>
@csrf
<div class="grid gap-5 sm:grid-cols-2">
<div>
<label for="contact-name" class="block text-[12px] font-semibold text-ink mb-1.5">Ihr Name</label>
<input id="contact-name" type="text" name="name" value="{{ old('name') }}" required
autocomplete="name"
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-brand" />
@error('name')
<p class="mt-1 text-[12px] text-red-600">{{ $message }}</p>
@enderror
</div>
<div>
<label for="contact-email" class="block text-[12px] font-semibold text-ink mb-1.5">E-Mail-Adresse</label>
<input id="contact-email" type="email" name="email" value="{{ old('email') }}" required
autocomplete="email"
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-brand" />
@error('email')
<p class="mt-1 text-[12px] text-red-600">{{ $message }}</p>
@enderror
</div>
</div>
<div>
<label for="contact-message" class="block text-[12px] font-semibold text-ink mb-1.5">Ihre Nachricht</label>
<textarea id="contact-message" name="message" rows="6" required
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-brand"
placeholder="Wie können wir Ihnen helfen?">{{ old('message') }}</textarea>
@error('message')
<p class="mt-1 text-[12px] text-red-600">{{ $message }}</p>
@enderror
</div>
{{-- Bot-Schutz: versteckte Honeypot-Felder (siehe legal-request). --}}
<div class="hidden" aria-hidden="true">
<label for="contact-website">Website</label>
<input id="contact-website" type="text" name="website" tabindex="-1" autocomplete="off" value="{{ old('website') }}" />
<label for="contact-homepage">Homepage</label>
<input id="contact-homepage" type="text" name="homepage" tabindex="-1" autocomplete="off" value="{{ old('homepage') }}" />
</div>
<button type="submit"
class="bg-brand hover:bg-brand-deep text-white px-5 py-2.5 text-[13px] font-semibold transition-colors">
Nachricht senden
</button>
<p class="text-[11.5px] text-ink-3 leading-relaxed">
Ihre Angaben werden ausschließlich zur Bearbeitung Ihrer Anfrage verarbeitet.
Weitere Informationen in der
<a href="{{ route('datenschutz') }}" class="underline hover:text-ink">Datenschutzerklärung</a>.
</p>
</form>
@endif
<h3>Anfahrt</h3>
<p>
<strong>Öffentliche Verkehrsmittel:</strong> U-Bahn U4/U5 – Haltestelle Lehel; Tram 19 –
Haltestelle Maxmonument.<br>
<strong>Parken:</strong> Parkhaus Maximilianstraße (5 Min. Fußweg).
</p>
</div>
<aside class="border border-bg-rule bg-bg-elev p-6 h-max">
<div class="eyebrow muted mb-3">Hauptsitz</div>
<p class="text-[13.5px] leading-[1.6] text-ink-2 m-0">
{{ $brandLabel }}<br>
Maximilianstraße 35<br>
80539 München<br>
Deutschland
</p>
<div class="mt-5 pt-5 border-t border-bg-rule">
<div class="eyebrow muted mb-2">Schnelle Hilfe</div>
<p class="text-[12.5px] text-ink-3 m-0 mb-3">
Antworten auf die häufigsten Fragen finden Sie sofort online.
</p>
<a href="{{ route('faq') }}"
class="inline-flex items-center gap-1.5 px-4 py-2 text-[12.5px] font-semibold text-ink border border-bg-rule-strong hover:bg-bg transition-colors rounded-[2px]">
Zur FAQ
<svg width="11" height="11" viewBox="0 0 12 12" fill="none" aria-hidden="true">
<path d="M2 6h8M6 2l4 4-4 4" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</a>
</div>
</aside>
</div>
</x-web.static-page>
@endsection

View file

@ -157,8 +157,8 @@
</form>
<p class="text-[12px] text-ink-3 leading-[1.6] mt-8 mb-0">
Hinweis: Möchten Sie stattdessen einen kürzlich geschlossenen Vertrag innerhalb der
14-tägigen Frist widerrufen, nutzen Sie bitte den Button „Vertrag widerrufen" im Fußbereich dieser Seite.
Hinweis: Angemeldet geht es noch schneller — in Ihrem Konto unter „Buchungen &amp; Add-ons"
kündigen Sie Ihr Abo mit wenigen Klicks.
</p>
@endif
</div>

View file

@ -265,11 +265,11 @@
</h3>
<p class="text-[13.5px] leading-[1.6] text-ink-2 mt-3 m-0">
Jeder Newsroom mit Logo, Kontaktperson, Themen-Schwerpunkten und vollständiger Mitteilungs-Historie.
Mehrere Newsrooms pro Konto möglich, mit getrennten Berechtigungen.
Mehrere Newsrooms pro Konto möglich — etwa für Agenturen mit mehreren Marken.
</p>
<ul class="mt-5 space-y-1.5 text-[12.5px] text-ink-3 list-none p-0">
<li class="flex items-center gap-2"><span class="w-1 h-1 bg-hub rounded-full"></span> Mehrere
Redakteure pro Newsroom</li>
<li class="flex items-center gap-2"><span class="w-1 h-1 bg-hub rounded-full"></span> Eigene
Newsroom-Seite auf beiden Portalen</li>
<li class="flex items-center gap-2"><span class="w-1 h-1 bg-hub rounded-full"></span> Logo und
Pressekontakte je Newsroom</li>
<li class="flex items-center gap-2"><span class="w-1 h-1 bg-hub rounded-full"></span> Vollständige
@ -326,8 +326,8 @@
</div>
<div class="text-[16.5px] font-semibold text-ink tracking-[-0.2px] mb-2">Registrieren</div>
<p class="text-[12.5px] text-ink-2 leading-[1.55] m-0">
Konto in unter zwei Minuten anlegen. Mit E-Mail oder über Magic-Link. Direkt freigeschaltet für
beide Portale.
Konto in unter zwei Minuten anlegen — mit E-Mail und Passwort oder Google-Konto. Nach
Bestätigung Ihrer E-Mail-Adresse ist das Konto für beide Portale freigeschaltet.
</p>
</li>
<li class="relative px-7 py-7 border-r border-b lg:border-b-0 border-bg-rule">
@ -373,9 +373,10 @@
<hr class="rule-strong" />
<div class="mt-5 px-5 py-3 bg-bg-card-warm border-l-2 border-accent text-[12.5px] text-ink-2 leading-[1.55]">
<strong class="text-ink font-semibold">Die Prüfung</strong> ist Teil unseres
Qualitätsversprechens — keine PR-Wand, kein automatisierter Durchlauf. Das gilt für alle Tarife, auch den
Starter.
<strong class="text-ink font-semibold">Die Inhaltsprüfung</strong> ist Teil unseres
Qualitätsversprechens: Jede Mitteilung wird vor der Veröffentlichung gegen unsere
Veröffentlichungsrichtlinien geprüft — bei einer Ablehnung erhalten Sie die Begründung und können eine
Überprüfung verlangen. Das gilt für alle Tarife, auch den Starter.
</div>
</section>
@ -391,11 +392,13 @@
Ein Konto, beide Portale. Keine versteckten Aufschläge für Reichweite.
</h2>
<p class="text-[14.5px] text-ink-2 leading-[1.55] m-0 mt-4 max-w-[640px]">
Alle Tarife enthalten die Prüfung, Ihren eigenen Newsroom und die
Alle Tarife enthalten die Inhaltsprüfung, Ihren eigenen Newsroom und die
Veröffentlichung auf <strong class="text-ink font-semibold"><x-web.brand-mark
brand="presseecho" :serif="false" /></strong> und <strong
class="text-ink font-semibold"><x-web.brand-mark brand="businessportal24"
:serif="false" /></strong> ohne Mehrkosten.
:serif="false" /></strong> ohne Mehrkosten. Unser Angebot richtet sich
ausschließlich an Unternehmen, Selbstständige und Agenturen — die Veröffentlichung
erfolgt stets über Ihr Firmenprofil.
</p>
</div>
@ -671,7 +674,7 @@
<p class="text-[15px] lg:text-[16px] leading-[1.7] text-ink-2 m-0">
Über <x-web.brand-mark brand="pressekonto" :serif="false" /> veröffentlichen Unternehmen,
Verbände und öffentliche Einrichtungen aus Deutschland, Österreich und der Schweiz.
Jeder Newsroom wird redaktionell geprüft, bevor Mitteilungen erscheinen — die
Jede Mitteilung durchläuft vor der Veröffentlichung unsere Inhaltsprüfung — die
Veröffentlichungen unterliegen unserem Qualitätsstandard und bleiben im Archiv
beider Portale dauerhaft auffindbar.
</p>
@ -755,10 +758,11 @@
</svg>
</summary>
<div class="pb-5 text-[13.5px] text-ink-2 leading-[1.65] max-w-[640px]">
Sobald Sie eine Mitteilung einreichen, prüfen unsere Redakteure formale Korrektheit,
Quellenqualität, Themenrelevanz und Plausibilität — werktags in der Regel am selben Tag.
Bei Rückfragen erhalten Sie Feedback direkt an der Mitteilung — kein PR-Filter,
sondern verlegerische Qualitätssicherung.
Sobald Sie eine Mitteilung einreichen, wird sie auf formale Korrektheit, Quellenqualität,
Themenrelevanz und die Einhaltung unserer Veröffentlichungsrichtlinien geprüft — werktags
in der Regel am selben Tag. Bei einer Ablehnung erhalten Sie die Begründung direkt an der
Mitteilung und können eine Überprüfung verlangen; ein abgelehnter Beitrag verbraucht kein
Kontingent.
</div>
</details>
@ -810,9 +814,14 @@
</svg>
</summary>
<div class="pb-5 text-[13.5px] text-ink-2 leading-[1.65] max-w-[640px]">
Ja. Monats-Tarife sind monatlich kündbar, Jahres-Tarife laufen bis zum Ende des bezahlten
Zeitraums. Ihr Konto und Ihre Newsroom-Archive bleiben dauerhaft bestehen — auch nach Kündigung
sind veröffentlichte Mitteilungen weiter im Archiv auffindbar.
Ja, alle Tarife sind monatlich kündbar. Bei jährlicher Zahlweise läuft der bereits bezahlte
Zeitraum bis zum Ende der zwölf Monate; danach wird monatlich abgerechnet, sofern Sie nicht
erneut die jährliche Zahlweise wählen. Kündigen können Sie direkt im Konto oder ohne
Anmeldung über <a
class="text-hub underline underline-offset-[3px] decoration-hub/30 hover:decoration-hub"
href="{{ route('kuendigung', ['edition' => 'de']) }}">unsere Kündigungsseite</a>.
Ihr Konto und Ihre Newsroom-Archive bleiben bestehen — auch nach Kündigung sind
veröffentlichte Mitteilungen weiter im Archiv auffindbar.
</div>
</details>
@ -868,10 +877,11 @@
</summary>
<div class="pb-5 text-[13.5px] text-ink-2 leading-[1.65] max-w-[640px]">
Ja — eine Token-basierte REST-API zum Einreichen von Mitteilungen, Statusabfragen und
Bild-Upload. Die technische Dokumentation finden Sie unter <a
Bild-Upload. Die technische Dokumentation finden Sie auf unserer <a
class="text-hub underline underline-offset-[3px] decoration-hub/30 hover:decoration-hub"
href="{{ route('docs.api.v1') }}">/docs/api/v1</a>. Den API-Zugang erhalten Sie
auf Anfrage über den Support.
href="{{ route('api', ['edition' => 'de']) }}">API-Seite</a>. Ihre API-Tokens
erstellen Sie direkt in Ihrem Konto — Voraussetzung ist eine aktive Buchung
(Tarif oder Einzel-Pressemitteilung).
</div>
</details>
</div>
@ -932,7 +942,6 @@
</main>
<x-web.hub.contact-modal />
<x-web.hub.withdrawal-modal />
<x-web.hub.site-footer />
@endsection

View file

@ -1,131 +0,0 @@
@extends('web.layouts.web-master')
@section('title', 'Über uns')
@section('meta_description', 'Wir verbinden Unternehmen mit Medien, Journalisten und Multiplikatoren im deutschsprachigen Raum.')
@php
$brand = config('domains.domains.'.config('app.theme').'.brand', []);
$brandLabel = ($brand['name'] ?? 'businessportal').($brand['accent'] ?? '');
// Platzhalter-Kennzahlen — vor Go-Live mit echten Werten ersetzen.
$stats = [
['value' => '250.000+', 'label' => 'Veröffentlichte Meldungen'],
['value' => '15.000+', 'label' => 'Registrierte Unternehmen'],
['value' => '2,5 Mio.', 'label' => 'Monatliche Leser'],
['value' => '40+', 'label' => 'Länder'],
];
$values = [
['title' => 'Qualität vor Quantität', 'text' => 'Wir setzen auf redaktionelle Qualität und kuratieren Inhalte sorgfältig, um höchste Standards zu gewährleisten.'],
['title' => 'DACH-Expertise', 'text' => 'Spezialisiert auf den deutschsprachigen Raum mit tiefem Verständnis für regionale Besonderheiten.'],
['title' => 'Kundenfokus', 'text' => 'Ihre Zufriedenheit steht im Mittelpunkt. Wir bieten persönlichen Support und maßgeschneiderte Lösungen.'],
['title' => 'Innovation & Technologie', 'text' => 'Kontinuierliche Weiterentwicklung unserer Plattform mit modernsten Technologien und Features.'],
];
$team = [
['name' => 'Dr. Michael Weber', 'role' => 'Gründer & CEO', 'bio' => '15+ Jahre Erfahrung in PR und Unternehmenskommunikation'],
['name' => 'Sarah Hoffmann', 'role' => 'Chief Technology Officer', 'bio' => 'Expertin für digitale Plattformen und Skalierung'],
['name' => 'Thomas Schneider', 'role' => 'Head of Customer Success', 'bio' => 'Spezialist für Kundenzufriedenheit und Account Management'],
['name' => 'Lisa Müller', 'role' => 'Head of Content & Quality', 'bio' => 'Journalistin mit Schwerpunkt digitale Medien'],
];
$timeline = [
['year' => '10', 'title' => 'Gründung', 'text' => 'Start als kleines Start-up mit der Vision, PR zu demokratisieren.'],
['year' => '13', 'title' => 'Expansion', 'text' => 'Erreichen von 1.000 registrierten Unternehmen.'],
['year' => '16', 'title' => 'Wachstum', 'text' => 'Launch der Premium-Features und Enterprise-Lösungen.'],
['year' => '19', 'title' => 'Innovation', 'text' => 'Einführung KI-gestützter Reichweiten-Analytics.'],
['year' => '22', 'title' => 'Marktführer', 'text' => 'Über 10.000 aktive Unternehmenskunden im DACH-Raum.'],
['year' => '25', 'title' => 'Zukunft', 'text' => 'Internationalisierung und neue KI-Features.'],
];
@endphp
@section('content')
<x-web.static-page
eyebrow="Über uns"
title="Über {{ $brandLabel }}"
lead="Wir verbinden Unternehmen mit Medien, Journalisten und Multiplikatoren im deutschsprachigen Raum – als Plattform für redaktionell geprüfte Unternehmenskommunikation."
breadcrumb="Über uns"
>
{{-- Kennzahlen --}}
<div class="grid gap-px bg-bg-rule border border-bg-rule grid-cols-2 lg:grid-cols-4">
@foreach ($stats as $stat)
<div class="bg-bg p-6 text-center">
<div class="font-serif text-[30px] font-semibold tracking-[-0.6px] text-brand leading-none">{{ $stat['value'] }}</div>
<div class="text-[12px] text-ink-3 mt-2">{{ $stat['label'] }}</div>
</div>
@endforeach
</div>
{{-- Mission --}}
<div class="grid gap-8 lg:grid-cols-[0.8fr_1.2fr] mt-14">
<div>
<div class="eyebrow muted mb-1">Unsere Mission</div>
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0">Professionelle Kommunikation für alle zugänglich machen</h2>
</div>
<div class="pm-body">
<p>
Wir glauben daran, dass jedes Unternehmen – unabhängig von Größe oder Budget – die Möglichkeit
haben sollte, seine Geschichte zu erzählen und mit relevanten Zielgruppen zu kommunizieren.
</p>
<p>
{{ $brandLabel }} demokratisiert professionelle PR-Arbeit durch innovative Technologie, faire
Preismodelle und exzellenten Service. Wir schaffen Sichtbarkeit für wichtige Unternehmens­nachrichten
und verbinden Organisationen mit den Menschen, die ihre Botschaften lesen und teilen möchten.
</p>
</div>
</div>
{{-- Werte --}}
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">Unsere Werte</h2>
<div class="grid gap-px bg-bg-rule border border-bg-rule grid-cols-1 sm:grid-cols-2 lg:grid-cols-4">
@foreach ($values as $value)
<div class="bg-bg p-6">
<h3 class="text-[14px] font-semibold text-ink m-0 mb-2">{{ $value['title'] }}</h3>
<p class="text-[12.5px] leading-[1.55] text-ink-2 m-0">{{ $value['text'] }}</p>
</div>
@endforeach
</div>
{{-- Team --}}
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">Unser Team</h2>
<div class="grid gap-px bg-bg-rule border border-bg-rule grid-cols-1 sm:grid-cols-2 lg:grid-cols-4">
@foreach ($team as $member)
<div class="bg-bg p-6">
<h3 class="text-[14px] font-semibold text-ink m-0">{{ $member['name'] }}</h3>
<div class="text-[12px] font-semibold text-brand mt-0.5 mb-2">{{ $member['role'] }}</div>
<p class="text-[12.5px] leading-[1.55] text-ink-3 m-0">{{ $member['bio'] }}</p>
</div>
@endforeach
</div>
{{-- Geschichte / Timeline --}}
<h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-5">Unsere Geschichte</h2>
<div class="border-l-2 border-bg-rule pl-6 space-y-7 max-w-[760px]">
@foreach ($timeline as $milestone)
<div class="relative">
<span class="absolute -left-[31px] top-0 flex items-center justify-center w-6 h-6 rounded-full bg-brand text-white text-[10px] font-bold">{{ $milestone['year'] }}</span>
<h3 class="text-[14px] font-semibold text-ink m-0">{{ $milestone['title'] }}</h3>
<p class="text-[12.5px] leading-[1.55] text-ink-2 mt-1 mb-0">{{ $milestone['text'] }}</p>
</div>
@endforeach
</div>
{{-- CTA --}}
<div class="mt-14 border border-bg-rule bg-bg-elev p-6 sm:p-8 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-5">
<div>
<h2 class="font-serif text-[20px] font-semibold tracking-[-0.3px] text-ink m-0">Werden Sie Teil unserer Geschichte</h2>
<p class="text-[13px] text-ink-2 mt-1.5 mb-0">Veröffentlichen Sie Ihre nächste Pressemitteilung redaktionell geprüft und dauerhaft auffindbar.</p>
</div>
<div class="flex flex-wrap gap-3 flex-shrink-0">
<a href="{{ route('veroeffentlichen') }}"
class="inline-flex items-center justify-center gap-1.5 px-5 py-2.5 text-[12.5px] font-semibold text-white bg-brand hover:bg-brand-deep rounded-[2px] transition-colors">
Jetzt veröffentlichen
</a>
<a href="{{ route('preise') }}"
class="inline-flex items-center justify-center gap-1.5 px-5 py-2.5 text-[12.5px] font-semibold text-ink border border-bg-rule-strong hover:bg-bg transition-colors rounded-[2px]">
Preise ansehen
</a>
</div>
</div>
</x-web.static-page>
@endsection

View file

@ -11,9 +11,10 @@ test('static pages on the hub domain render the hub shell', function (string $pa
// Hub-Kopf: Utility-Bar + Hub-Header statt Spoke-Gerüst.
->toContain('Publisher-Hub für')
->toContain('Publisher · Hub')
// Hub-Footer inkl. gesetzlichem Widerrufsbutton + Modals.
->toContain('Vertrag widerrufen')
->toContain('open-withdrawal-modal')
// Hub-Footer inkl. Selfservice-Kündigungsbutton + Kontakt-Modal.
// Der Widerrufs-Button entfällt (Entscheidung E2: B2B-only).
->toContain('Verträge hier kündigen')
->not->toContain('open-withdrawal-modal')
->toContain('open-contact-modal')
// Kein Spoke-Portal-Branding im Gerüst.
->not->toContain('Pressemitteilungen · DACH');

View file

@ -6,18 +6,17 @@ use App\Models\WithdrawalRequest;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;
test('the hub shows the legally required withdrawal button and two-step modal', function () {
test('the withdrawal ui is retired on the hub (B2B-only, decision E2)', function () {
/** @var TestCase $this */
// Der Widerrufs-Button/-Modal entfällt seit der B2B-only-Entscheidung
// (E2, 03.07.2026); der POST-Endpunkt bleibt schlafend erhalten und ist
// bei einer B2C-Öffnung reaktivierbar (samt archivierter Belehrung).
$response = $this->get('https://pressekonto.test/')->assertSuccessful();
$content = $response->getContent();
expect($content)
->toContain('Vertrag widerrufen')
->toContain('open-withdrawal-modal')
->toContain('action="'.route('widerruf.store').'"')
->toContain('Jetzt widerrufen')
// Kein Widerrufsgrund-Feld — darf gesetzlich nicht verlangt werden.
->not->toContain('name="reason"');
->not->toContain('Vertrag widerrufen')
->not->toContain('open-withdrawal-modal');
});
test('a withdrawal is persisted and both mails are sent immediately', function () {