Editorial-Frontend: oeffentliche Unterseiten, Preise & Linkpflege
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled

Oeffentliche Strecke durchgaengig auf das Editorial-Design umgestellt und
datengetrieben gemacht:

- Newsrooms-Verzeichnis + Newsroom-Detailseiten (Suche, Pagination)
- Preise-Seite neu (Abos via Plan, Einzel-PM via config/billing, Add-ons via
  config/credits); Texte ausgelagert nach lang/{de,en}/pricing.php
- Pricing-Teaser-Komponente auf den Startseiten + Preise-Link in Header/Footer
- Statische Seiten im Editorial-Design ueber neue Komponente x-web.static-page:
  impressum, datenschutz, agb, cookies, faq (Akkordeon), hilfe, kontakt,
  ueber-uns, api (altes Theme/gradient-hero entfernt)
- Header/Footer-Linkpflege: tote #-Anker raus, FAQ/Hilfe/Cookies verlinkt,
  "Anmelden" fuehrt in den Hub
- Legacy-URL-Redirects (.html, presskit->newsroom, Regionen)
- Datums-Bugfix in Feed-Komponenten

Tests: NewsroomPage, PreisePage, PricingTeaser, StaticPages, NavigationLinks,
LegacyRedirect. Doku in docs/frontend aktualisiert.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Kevin Adametz 2026-06-17 16:08:46 +00:00
parent 82abdf6bd6
commit 028b059975
34 changed files with 2842 additions and 3102 deletions

View file

@ -2,6 +2,23 @@
> der oeffentlichen Strecke. Welcher Punkt bereits umgesetzt ist, ist > der oeffentlichen Strecke. Welcher Punkt bereits umgesetzt ist, ist
> jeweils mit einer kurzen IST-Notiz markiert. > jeweils mit einer kurzen IST-Notiz markiert.
> **Update 17.06.2026 — Bestands-URL-Mapping (Launch-Vorbereitung).** Die
> komplette URL-Struktur der Altseite (siehe `docs/frontend/Struktur Frontend.md`)
> ist jetzt per 301 auf die neue Struktur abgebildet: englische Alt-Slugs
> (`login`, `contact`, `imprint`, `terms`, `privacypolicy`, `pricelist`,
> `service`) → neue deutsche Pfade bzw. Hub, `/presse/*`-Ratgeber → `/faq`,
> `presskit/{id}/{slug}` → `/newsroom/{slug}` (Feinmapping über
> `companies.legacy_id`, Fallback `/newsrooms`), entfallene Sprachvarianten
> `de-ch`/`de-at` → `/de`. Region-Übersichten (`/region/{slug}`) sind bewusst
> ein späterer Schritt. Implementierung in `routes/web.php`; Test:
> `tests/Feature/Web/LegacyRedirectTest.php`.
> **Update 17.06.2026 — Newsrooms.** Newsroom-Markenseiten pro Unternehmen
> (`/{edition}/newsroom/{slug}`) und das Newsrooms-Verzeichnis
> (`/{edition}/newsrooms`) sind im Editorial-Design mit echten Daten
> umgesetzt (siehe Punkt 4). Neue server-seitige Pagination-Komponente
> `x-web.pagination`. Test: `tests/Feature/Web/NewsroomPageTest.php`.
> **Update 16.06.2026 — Editorial-Relaunch & Ausgaben-Routing.** > **Update 16.06.2026 — Editorial-Relaunch & Ausgaben-Routing.**
> Die oeffentliche Strecke wurde auf ein gemeinsames Editorial-Design > Die oeffentliche Strecke wurde auf ein gemeinsames Editorial-Design
> (Komponenten `x-web.site-header` / `x-web.site-footer`, Design-Tokens in > (Komponenten `x-web.site-header` / `x-web.site-footer`, Design-Tokens in
@ -45,6 +62,7 @@ _IST 21.05.2026_: noch nicht umgesetzt.
**4. Newsroom-Seite eines Unternehmens** – `/newsroom/[slug]` Markenseite eines Premium-Publishers mit eigener URL, Logo, allen PMs des Unternehmens. Ist gleichzeitig Verkaufsargument für Pro-/Agency-Tarif und SEO-Vorteil für die Unternehmen. **4. Newsroom-Seite eines Unternehmens** – `/newsroom/[slug]` Markenseite eines Premium-Publishers mit eigener URL, Logo, allen PMs des Unternehmens. Ist gleichzeitig Verkaufsargument für Pro-/Agency-Tarif und SEO-Vorteil für die Unternehmen.
_IST 21.05.2026_: Layout vorhanden (`web/newsrooms.blade.php`), Daten-Anbindung pro Firma noch offen. _IST 21.05.2026_: Layout vorhanden (`web/newsrooms.blade.php`), Daten-Anbindung pro Firma noch offen.
_IST 17.06.2026_: umgesetzt im Editorial-Design mit echten Daten. **Markenseite** `web/newsroom.blade.php` (Route `newsroom`, URL `/{edition}/newsroom/{slug}`): Logo/Initiale, Boilerplate, Website, Branchen der Firma, Kennzahlen (gesamt/30 Tage/heute/Aufrufe/seit Jahr), Top-Meldung und paginierte Meldungsliste (`x-web.pagination`), Sidebar (Meistgelesen, Publisher-CTA). 404 bei unbekanntem Slug oder Firma ohne veröffentlichte Meldung. Zusätzlich **Verzeichnis** `web/newsrooms.blade.php` (Route `newsrooms`, URL `/{edition}/newsrooms`): Karten-Grid aller aktiven Newsrooms mit Meldungs-/Aktivitätszahlen, Namens-Suche (`?q=`) und Pagination. `x-web.active-newsrooms` verlinkt jetzt über `route('newsroom', …)`. Legacy-`.html`-URLs (`/newsrooms.html`, `/newsroom/{slug}.html`) per 301. Test: `tests/Feature/Web/NewsroomPageTest.php`.
**5. Such-Ergebnisseite** – `/suche?q=...` Volltextsuche mit Filtern (Erweiterte Suche schreibt in URL-Parameter, dadurch teilbar/bookmarkbar). **5. Such-Ergebnisseite** – `/suche?q=...` Volltextsuche mit Filtern (Erweiterte Suche schreibt in URL-Parameter, dadurch teilbar/bookmarkbar).
_IST 21.05.2026_: Layout vorhanden (`web/suche.blade.php`), Volltextsuche noch nicht aktiv. _IST 21.05.2026_: Layout vorhanden (`web/suche.blade.php`), Volltextsuche noch nicht aktiv.
@ -61,6 +79,7 @@ _IST 16.06.2026_: Landing-Seite im Editorial-Design neu aufgebaut, echte Kennzah
**8. Tarife & Preise** – `/preise` _(oder als Modal aus mehreren Stellen aufrufbar)_ Da Tarife auch im Modal aus dem CTA aufgerufen werden, ist die Frage: brauchen wir die Seite? Antwort ja, weil SEO ("Pressemitteilung veröffentlichen Preise" ist eine wichtige Suche) und weil sie verlinkbar sein muss aus AGB, Footer, Mediadaten. **8. Tarife & Preise** – `/preise` _(oder als Modal aus mehreren Stellen aufrufbar)_ Da Tarife auch im Modal aus dem CTA aufgerufen werden, ist die Frage: brauchen wir die Seite? Antwort ja, weil SEO ("Pressemitteilung veröffentlichen Preise" ist eine wichtige Suche) und weil sie verlinkbar sein muss aus AGB, Footer, Mediadaten.
_IST 21.05.2026_: Layout vorhanden (`web/preise.blade.php`), echte Tarife noch nicht hinterlegt (Tarif-Modul siehe `Presseportal – Konzept für Relaunch.md` Abschnitt 8). _IST 21.05.2026_: Layout vorhanden (`web/preise.blade.php`), echte Tarife noch nicht hinterlegt (Tarif-Modul siehe `Presseportal – Konzept für Relaunch.md` Abschnitt 8).
_IST 17.06.2026_: Tarife sind jetzt **datengetrieben** aus dem System (`Plan::active()`) auf der **Startseite** als Tarif-Teaser sichtbar (neue Komponente `x-web.pricing-teaser`, Preis/Quota/Tageslimit/Jahrespreis je Tarif, „Beliebt"-Hervorhebung). Der **Preise-Link** ist auf jeder Portalseite präsent: in der Header-Utility-Bar (neu) und im Footer („Tarife & Pakete", bestand bereits). Test: `tests/Feature/Web/PricingTeaserTest.php`. **Offen**: Die eigentliche `/preise`-Seite (`web/preise.blade.php`) ist noch im alten Theme mit Platzhalter-Tarifen — Editorial-Rebuild mit `x-web.pricing-teaser`/echten Plänen ist der nächste Schritt.
**9. Mediadaten / Werbung** – `/mediadaten` oder `/werben` Für Mediaplaner und potentielle Werbekunden: alle buchbaren Slot-Typen (Top-Slot, Highlights, Newsletter, Branchen-Sponsoring), Reichweiten-Daten, Preise, Booking-Kontakt. Pflicht-Seite für jede Plattform mit Anzeigeninventar. **9. Mediadaten / Werbung** – `/mediadaten` oder `/werben` Für Mediaplaner und potentielle Werbekunden: alle buchbaren Slot-Typen (Top-Slot, Highlights, Newsletter, Branchen-Sponsoring), Reichweiten-Daten, Preise, Booking-Kontakt. Pflicht-Seite für jede Plattform mit Anzeigeninventar.
_IST 21.05.2026_: nicht umgesetzt. _IST 21.05.2026_: nicht umgesetzt.

View file

@ -0,0 +1,150 @@
## 1. Hauptnavigation (rechts oben)
| Seite | Link | Dahinter | Relaunch |
| ------------- | ----------------------- | ---------------------------------- | -------------------------------------------------------------------------------------------- |
| Home | `/` | Startseite | **Portal** |
| Registrierung | `/de/registration.html` | Account-Anlage | → **Hub** (pressekonto) |
| Login | `/de/login.html` | Anmeldung | → **Hub** (Sanctum, kein eigener Login am Portal) |
| Preisliste | `/de/pricelist.html` | Tarife | → **Hub** (neue Tarifstruktur Einzel/Starter/…/Agency) |
| Service | `/de/service.html` | Leistungsübersicht / Verkaufsseite | wird zu veroeffentlichen |
| Kontakt | `/de/contact.html` | Kontakt | **Portal** + Hub (auch hier muss deutlich werden, dass der Hub das ganze Backend System ist) |
## 2. Region/Sprache
| Variante | Link | Relaunch |
| ------------ | -------- | ---------- |
| Deutsch | `/` | **Portal** |
| Deutsch (CH) | `/de-ch` | raus |
| Deutsch (AT) | `/de-at` | raus |
| English | `/en` | Portal |
## 3. „Presse"-Dropdown — Ratgeber/SEO-Content (12 Seiten)
Das ist editorial wertvollster Teil: statische Ratgeber-Seiten, die wahrscheinlich organischen Long-Tail-Traffic ziehen.
|Seite|Link|
|---|---|
|Pressemitteilung schreiben|`/de/presse/pressemitteilung-schreiben.html`|
|Aufbau Pressemitteilung|`/de/presse/pressemitteilung-aufbau.html`|
|Pressemitteilung Nutzen & Einsatz|`/de/presse/pressemitteilung-nutzen.html`|
|Pressemappe|`/de/presse/pressemappe.html`|
|Redakteure & Journalisten|`/de/presse/redakteure-journalisten.html`|
|Pressemitteilung Beispiel|`/de/presse/pressemitteilung-beispiel.html`|
|Pressekonferenz|`/de/presse/pressekonferenz.html`|
|Deutsche Presse Agentur|`/de/presse/deutsche-presseagentur.html`|
|Redaktion|`/de/presse/redaktion.html`|
|Pressestelle|`/de/presse/pressestelle.html`|
|Pressesprecher|`/de/presse/pressesprecher.html`|
|Presseausweis|`/de/presse/presseausweis.html`|
**Relaunch:** Diese URLs unbedingt 1:1 erhalten oder sauber 301-redirecten — hier steckt der SEO-Wert. Editorial passen sie zu beiden Portalen, ggf. sogar besser zu presseecho (Kontexttiefe). Entscheidung offen, wo sie inhaltlich angesiedelt werden.
Hier würde ich eine FAQ Seite machen, die alle Themen beinhaltet und sauber 301-redirectet
## 4. Kategorien (14 Stück)
`/de/category/{slug}.html` — Listenseiten je Themenrubrik:
Handel · IT · Finanzen · Reisen · Kultur · Politik · Medizin · Sport · Motor/Verkehr · Haus · Mode · Sonstiges · Wissenschaft/Forschung · Recht
**Relaunch:** Diese Kategoriestruktur ist die Backbone für Migration + Boost-Logik (Kategorieseiten sind Teil deiner Boost-Platzierung). Beim Relaunch zu prüfen: Übernimmst du alle 14 unverändert, oder konsolidierst du? „Sonstiges" als Auffangbecken ist für deine Content-Score-/Trust-Logik suboptimal.
## 5. Content-/Detailseiten (die eigentlichen Templates)
|Typ|URL-Muster|Funktion|Relaunch|
|---|---|---|---|
|PM-Detailseite|`/de/{slug}.html`|Einzelne Pressemitteilung|**Portal** — Kern-Template|
|Kategorie-Liste|`/de/category/{slug}.html`|PMs je Rubrik, paginiert|**Portal**|
|Pressemappe (Presskit)|`/de/presskit/{id}/{slug}.html`|Firmenprofil + alle PMs der Firma|**Portal** = deine „Firmen-Detailseite"|
|Stream + Paginierung|`/de?page=N`|732 Seiten Archiv|**Portal** — aber Paginierungs-/Indexierungsstrategie überdenken|
Die Presskit-Seite entspricht funktional exakt deiner geplanten **Firmen-Detailseite** (Header, Stammdaten, Boilerplate, Kontakt, gefilterte PM-Liste). Gutes Mapping — du baust das also nicht neu, sondern modernisierst ein bestehendes Konstrukt.
## 6. Footer / Legal
| Seite | Link | Relaunch |
| ----------- | ------------------------ | -------------------------------------------------- |
| Impressum | `/de/imprint.html` | **Portal** + Hub (pflicht, pro Domain) |
| AGB | `/de/terms.html` | **Hub** (Vertragsbeziehung läuft über pressekonto) |
| Datenschutz | `/de/privacypolicy.html` | **Portal** + Hub |
---
## Einordnung für den Relaunch
Wenn ich das gegen deine Hub-and-Spoke-Architektur lege, fällt die Seitenmenge in drei klare Eimer:
**Bleibt am Portal (businessportal24.com & presseecho.de = öffentlicher Spoke):** Home/Stream, PM-Detail, Kategorie-Listen, Pressemappe/Firmen-Detail, Ratgeber-Seiten, Impressum, Datenschutz, Kontakt.
**Wandert in den Hub (pressekonto):** Registrierung, Login, Preisliste/Tarife, AGB, und alles dahinter (PM erstellen, Pressemappe anlegen, Account). Das deckt sich mit deinem Prinzip „Portale haben keine eigenen Login-Systeme".
---
## Relaunch-Mapping der Bestands-URLs (IST 17.06.2026)
Alle Alt-URLs werden per **301** auf die neue Struktur geleitet (Implementierung
in `routes/web.php`, Closure `$htmlRedirect` + Regions-Routen; Test:
`tests/Feature/Web/LegacyRedirectTest.php`). Die neue Struktur liegt unter dem
Ausgaben-Präfix `/{de|en}/…`.
| Alt-URL (Altsystem) | Ziel (301) | Status |
| ------------------------------------ | ---------------------------------- | ------ |
| `/` | `/de` (Default-Ausgabe) | ✅ |
| `/de/{slug}.html` (PM) | `/de/press-release/{slug}` | ✅ |
| `/de/category/{slug}.html` | `/de/category/{slug}` | ✅ |
| `/de/presskit/{id}/{slug}.html` | `/de/newsroom/{slug}` *(Lookup über `companies.legacy_id`; Fallback `/newsrooms`)* | ✅ |
| `/de/presse/*.html` (12 Ratgeber) | `/de/faq` (konsolidiert) | ✅ |
| `/de/pricelist.html` | `/de/preise` | ✅ |
| `/de/service.html` | `/de/veroeffentlichen` | ✅ |
| `/de/contact.html` | `/de/kontakt` | ✅ |
| `/de/imprint.html` | `/de/impressum` | ✅ |
| `/de/terms.html` | `/de/agb` | ✅ |
| `/de/privacypolicy.html` | `/de/datenschutz` | ✅ |
| `/de/registration.html` | Hub `pressekonto/register` | ✅ |
| `/de/login.html` | Hub `pressekonto/login` | ✅ |
| `/de/kategorien.html` (Übersicht) | `/de` (Übersicht entfällt) | ✅ |
| `/de-ch`, `/de-at` (+ Subpfade) | `/de` | ✅ |
**Bewusst auf später verschoben (eigene Slice):**
- **Regionen-Übersichten** `/region/{slug}` (Punkt 3 der öffentlichen Strecke) –
aktuell leiten nur die entfallenen Sprachvarianten `de-ch`/`de-at` auf `/de`.
- **Tarife/AGB im Hub**: `pricelist` zeigt vorerst auf die öffentliche
SEO-Seite `/preise`; die buchbare Tarifstruktur (Checkout) lebt im Hub.
**Erledigtes Feinmapping:**
- **Presskit→Newsroom**: `presskit/{id}/{slug}` löst über den Unique-Index
`companies.(legacy_portal, legacy_id)` den heutigen Newsroom auf und leitet
301 direkt auf `/newsroom/{slug}` (nur bei aktiver Firma mit ≥1 veröffentlichter
Meldung; sonst Fallback `/newsrooms`).
- **Preise datengetrieben & überall sichtbar**: Tarif-Teaser auf der Startseite
aus `Plan::active()` (`x-web.pricing-teaser`); Preise-Link in Header-Utility-Bar
und Footer. Test: `tests/Feature/Web/PricingTeaserTest.php`.
- **Statische Seiten im Editorial-Design** (Rebuild abgeschlossen): Pflicht-
seiten `impressum`, `datenschutz`, `agb`, `cookies` (Prosa über `.pm-body`)
sowie `faq` (natives `<details>`-Akkordeon), `hilfe` (Support-Landing),
`kontakt` (Kontaktwege; Formular wartet auf POST-Handler — als TODO markiert),
`ueber-uns` (Kennzahlen/Mission/Werte/Team/Timeline) und `api`
(Features/Code-Beispiel/Integrationen). Tote Doku-/Anker-Links durch echte
Ziele bzw. Hinweise ersetzt. Gemeinsames Gerüst: `x-web.static-page`.
- **Header/Footer-Linkpflege**: `site-header`/`site-footer` ohne tote `#`-Links —
FAQ/Hilfe/Cookies verlinkt, „Anmelden" führt in den Hub
(`{domain_portal_url}/login`), nicht verlinkte Platzhalter entfernt.
Test: `tests/Feature/Web/NavigationLinksTest.php`.
Gemeinsames Gerüst: wiederverwendbare Komponente `x-web.static-page`
(site-header, Breadcrumb, Masthead, site-footer). Altes Theme
(`livewire:web.header`, `gradient-hero`) entfernt. Rechtstexte sind weiterhin
Platzhalter (vor Go-Live ersetzen). Test: `tests/Feature/Web/StaticPagesTest.php`.
- **`/preise`-Seite im Editorial-Design** (Rebuild abgeschlossen): Reihenfolge
Abo-Tarife → Einzel-PM → Add-ons. Datengetrieben über `Plan::active()`,
`config('billing.single_pm_price_cents')` und `config('credits.*')`; Route
`$preisePage`-Closure. Texte ausgelagert in `lang/{de,en}/pricing.php`
(Schlüssel `pricing.*`), damit Portal/Hub einheitlich ziehen können. Add-on-
Lineup (Magic-Link-Pfade) ist mit TODO-Kommentaren als „noch im Rework"
markiert. Test: `tests/Feature/Web/PreisePageTest.php`.

103
lang/de/pricing.php Normal file
View file

@ -0,0 +1,103 @@
<?php
/*
|--------------------------------------------------------------------------
| Preise-Seite (öffentliches Portal) — ausgelagerte Inhalte
|--------------------------------------------------------------------------
|
| Alle Texte der öffentlichen Preise-Seite (resources/views/web/preise.blade.php).
| Bewusst zentral hier, damit Portal-Seite, Hub und ggf. das User-Backend
| dieselben Formulierungen ziehen können. Zahlen/Preise kommen NICHT aus dieser
| Datei, sondern aus dem System (Plan-Modell, config/billing.php, config/credits.php).
|
| HINWEIS: Die korrespondierende In-App-Buchungsseite
| (resources/views/livewire/customer/bookings.blade.php) wird gerade überarbeitet.
| Teile dieser Texte (v. a. Add-on-Lineup) können sich noch ändern.
|
*/
return [
'meta_title' => 'Preise & Tarife – Pressemitteilungen veröffentlichen',
'meta_description' => 'Transparente Tarife für Pressemitteilungen: Abo mit Monatskontingent, Einzelveröffentlichung und flexible Add-ons. Alle Preise netto zzgl. USt.',
'eyebrow' => 'Tarife & Preise',
'headline' => 'Transparente Preise für jede Reichweite',
'intro' => 'Veröffentlichen Sie regelmäßig im Abo mit monatlichem Kontingent oder einzeln ohne Bindung. Add-ons buchen Sie flexibel dazu. Alle Preise sind Nettopreise zzgl. gesetzlicher USt.',
// 1. Abo-Tarife (Daten: Plan::active())
'plans' => [
'eyebrow' => 'Abo-Tarife',
'title' => 'Abo-Tarife mit Monatskontingent',
'subtitle' => 'Monatlich kündbar. Im Jahrestarif sind zwei Monate gratis enthalten.',
'per_month' => '/ Monat',
'per_year' => '/ Jahr',
'net' => 'netto zzgl. USt.',
'yearly_hint' => ':price € / Jahr · 2 Monate gratis',
'quota' => ':count Pressemitteilungen / Monat',
'daily_limit' => 'max. :count Veröffentlichungen / Tag',
'no_daily_limit' => 'Ohne Tageslimit',
'included' => 'Redaktionelle Prüfung & Veröffentlichung inklusive',
'cta' => 'Tarif wählen',
'popular' => 'Beliebt',
'empty' => 'Tarife werden in Kürze veröffentlicht.',
// TODO: Enterprise-Kontaktadresse zentralisieren, sobald final.
'enterprise' => 'Mehr Veröffentlichungen, mehrere Marken oder Sonderkonditionen? Enterprise-Konditionen erhalten Sie auf Anfrage über den Support.',
],
// 2. Einzel-Pressemitteilung (Daten: config('billing.single_pm_price_cents'))
'single' => [
'eyebrow' => 'Ohne Abo',
'title' => 'Einzel-Pressemitteilung',
'description' => 'Genau eine Veröffentlichung inklusive redaktioneller Prüfung. Bezahlt wird erst bei Veröffentlichung – abgelehnte Mitteilungen kosten nichts.',
'price_suffix' => 'pro Veröffentlichung',
'net' => 'netto zzgl. USt.',
'cta' => 'Einzeln veröffentlichen',
],
// 3. Add-ons & Einzelkosten (Daten: config('credits'))
'addons' => [
'eyebrow' => 'Add-ons',
'title' => 'Add-ons & Einzelkosten',
'subtitle' => '1 Credit = 1 €. Add-ons buchen Sie flexibel aus Ihrem Guthaben – größere Credit-Pakete enthalten Bonus-Guthaben.',
'credits_unit' => 'Credits',
'from' => 'ab',
'extra_pm' => [
'title' => 'Extra-Pressemitteilung',
'description' => 'Eine weitere Veröffentlichung, wenn das Monatskontingent ausgeschöpft ist – ohne Tarifwechsel. Der Preis sinkt mit höherem Tarif.',
'tier_label' => 'Tarif',
'price_label' => 'Preis je PM',
],
'boost' => [
'title' => 'Boost-Platzierung',
'description' => 'Prominente Platzierung Ihrer Meldung auf der Startseite und der passenden Branchenseite.',
'days' => ':count Tage',
],
'proof_pdf' => [
'title' => 'Veröffentlichungsnachweis (PDF)',
'description' => 'Offizieller Nachweis Ihrer Veröffentlichung als PDF-Dokument – ideal für Reporting und Archiv.',
'unit' => 'pro Nachweis',
],
'packs' => [
'title' => 'Credit-Pakete',
'description' => 'Guthaben aufladen und flexibel für Add-ons einsetzen. Größere Pakete enthalten Bonus-Credits.',
'credits' => ':count Credits',
'bonus' => '+:count Bonus',
'net' => 'netto',
],
// TODO: Diese Leistungen hängen am Magic-Link-/Bookings-Rework — Lineup
// und Preise final abstimmen, sobald die In-App-Seite steht.
'more' => [
'title' => 'Weitere Leistungen',
'correction' => 'Inhaltliche Korrektur',
'update' => 'Update / Ergänzung',
'depublish' => 'Depublizieren',
],
],
'vat_note' => 'Alle Preise sind Nettopreise und verstehen sich zzgl. der gesetzlichen Umsatzsteuer. Die Abrechnung erfolgt sicher über unseren Zahlungsdienstleister.',
];

97
lang/en/pricing.php Normal file
View file

@ -0,0 +1,97 @@
<?php
/*
|--------------------------------------------------------------------------
| Pricing page (public portal) — externalised content
|--------------------------------------------------------------------------
|
| English counterpart of lang/de/pricing.php. Prices/numbers do NOT live here;
| they are read from the system (Plan model, config/billing.php, config/credits.php).
|
| NOTE: The in-app booking page (livewire/customer/bookings.blade.php) is still
| being reworked. Some of these strings (mainly the add-on line-up) may change.
|
*/
return [
'meta_title' => 'Pricing & Plans – Publish press releases',
'meta_description' => 'Transparent pricing for press releases: subscription with a monthly quota, single publication and flexible add-ons. All prices net, plus VAT.',
'eyebrow' => 'Plans & Pricing',
'headline' => 'Transparent pricing for every reach',
'intro' => 'Publish regularly on a subscription with a monthly quota, or one-off without commitment. Add-ons are booked flexibly on top. All prices are net, plus statutory VAT.',
// 1. Subscription plans (data: Plan::active())
'plans' => [
'eyebrow' => 'Subscriptions',
'title' => 'Subscriptions with a monthly quota',
'subtitle' => 'Cancel monthly. The annual plan includes two months free.',
'per_month' => '/ month',
'per_year' => '/ year',
'net' => 'net, plus VAT.',
'yearly_hint' => ':price € / year · 2 months free',
'quota' => ':count press releases / month',
'daily_limit' => 'max. :count publications / day',
'no_daily_limit' => 'No daily limit',
'included' => 'Editorial review & publication included',
'cta' => 'Choose plan',
'popular' => 'Popular',
'empty' => 'Plans will be published shortly.',
'enterprise' => 'More publications, multiple brands or special terms? Enterprise conditions are available on request via support.',
],
// 2. Single press release (data: config('billing.single_pm_price_cents'))
'single' => [
'eyebrow' => 'No subscription',
'title' => 'Single press release',
'description' => 'Exactly one publication including editorial review. You only pay on publication – rejected releases are free.',
'price_suffix' => 'per publication',
'net' => 'net, plus VAT.',
'cta' => 'Publish a single release',
],
// 3. Add-ons & individual costs (data: config('credits'))
'addons' => [
'eyebrow' => 'Add-ons',
'title' => 'Add-ons & individual costs',
'subtitle' => '1 credit = 1 €. Add-ons are booked flexibly from your balance – larger credit packs include bonus credits.',
'credits_unit' => 'credits',
'from' => 'from',
'extra_pm' => [
'title' => 'Extra press release',
'description' => 'One more publication when your monthly quota is used up – without changing plans. The price drops with a higher plan.',
'tier_label' => 'Plan',
'price_label' => 'Price per release',
],
'boost' => [
'title' => 'Boost placement',
'description' => 'Prominent placement of your release on the homepage and the matching industry page.',
'days' => ':count days',
],
'proof_pdf' => [
'title' => 'Proof of publication (PDF)',
'description' => 'Official proof of your publication as a PDF document – ideal for reporting and archiving.',
'unit' => 'per proof',
],
'packs' => [
'title' => 'Credit packs',
'description' => 'Top up your balance and use it flexibly for add-ons. Larger packs include bonus credits.',
'credits' => ':count credits',
'bonus' => '+:count bonus',
'net' => 'net',
],
'more' => [
'title' => 'Further services',
'correction' => 'Content correction',
'update' => 'Update / addition',
'depublish' => 'Unpublish',
],
],
'vat_note' => 'All prices are net and exclude statutory VAT. Billing is handled securely via our payment provider.',
];

View file

@ -33,7 +33,7 @@
$count = (int) ($company['count'] ?? 0); $count = (int) ($company['count'] ?? 0);
$color = $company['color'] ?? $palette[$index % count($palette)]; $color = $company['color'] ?? $palette[$index % count($palette)];
$slug = $company['slug'] ?? null; $slug = $company['slug'] ?? null;
$href = $slug ? url('/newsroom/'.$slug) : route('newsrooms'); $href = $slug ? route('newsroom', ['slug' => $slug]) : route('newsrooms');
$isLast = $loop->last; $isLast = $loop->last;
@endphp @endphp
<a href="{{ $href }}" <a href="{{ $href }}"

View file

@ -21,11 +21,11 @@
if ($published) { if ($published) {
$timeLine = $published->format('H:i'); $timeLine = $published->format('H:i');
if ($published->isToday()) { if ($published->isToday()) {
$dateLine = $published->translatedFormat('j. MMM'); $dateLine = $published->translatedFormat('j. M');
} elseif ($published->isYesterday()) { } elseif ($published->isYesterday()) {
$dateLine = 'Gestern'; $dateLine = 'Gestern';
} else { } else {
$dateLine = $published->translatedFormat('j. MMM'); $dateLine = $published->translatedFormat('j. M');
} }
$datetimeAttr = $published->toIso8601String(); $datetimeAttr = $published->toIso8601String();
} else { } else {

View file

@ -1,82 +1,44 @@
@props([ @props([
'currentPage' => 1, 'paginator' => null,
'totalPages' => 10,
'showFirstLast' => true,
'maxVisible' => 5,
]) ])
@php @if ($paginator && $paginator->hasPages())
$hasPrevious = $currentPage > 1; @php
$hasNext = $currentPage < $totalPages; $start = max(1, $paginator->currentPage() - 2);
$end = min($paginator->lastPage(), $paginator->currentPage() + 2);
// Berechne sichtbare Seitenzahlen @endphp
$visiblePages = []; <nav class="mt-8 flex items-center justify-center gap-1.5" aria-label="Seitennummerierung">
@if ($paginator->onFirstPage())
if ($totalPages <= $maxVisible) { <span class="inline-flex items-center justify-center w-9 h-9 border border-bg-rule text-ink-4 opacity-40 cursor-not-allowed" aria-hidden="true">
// Zeige alle Seiten wenn weniger als maxVisible <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path d="M15 19l-7-7 7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
$visiblePages = range(1, $totalPages); </span>
} else { @else
// Berechne dynamischen Bereich <a href="{{ $paginator->previousPageUrl() }}" rel="prev"
$start = max(1, $currentPage - floor($maxVisible / 2)); class="inline-flex items-center justify-center w-9 h-9 border border-bg-rule-strong text-ink hover:bg-bg-elev transition-colors"
$end = min($totalPages, $start + $maxVisible - 1); aria-label="Vorherige Seite">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path d="M15 19l-7-7 7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
// Korrigiere Start wenn am Ende </a>
if ($end - $start < $maxVisible - 1) {
$start = max(1, $end - $maxVisible + 1);
}
$visiblePages = range($start, $end);
}
$showStartEllipsis = $visiblePages[0] > 1;
$showEndEllipsis = end($visiblePages) < $totalPages;
@endphp
<nav class="flex justify-center mt-12" aria-label="Seitennummerierung">
<div class="flex items-center gap-2">
<!-- Vorherige Seite -->
<button
class="pagination-btn pagination-nav {{ !$hasPrevious ? 'disabled:opacity-50 disabled:cursor-not-allowed' : '' }}"
{{ !$hasPrevious ? 'disabled' : '' }} aria-label="Vorherige Seite"
@if ($hasPrevious) onclick="window.location.href='?page={{ $currentPage - 1 }}'" @endif>
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
</svg>
</button>
<!-- Erste Seite + Ellipsis -->
@if ($showStartEllipsis && $showFirstLast)
<button class="pagination-btn" onclick="window.location.href='?page=1'">
1
</button>
<span class="px-2 text-zinc-600 dark:text-zinc-400">...</span>
@endif @endif
<!-- Sichtbare Seitenzahlen --> @foreach ($paginator->getUrlRange($start, $end) as $page => $url)
@foreach ($visiblePages as $page) @if ($page === $paginator->currentPage())
<button class="pagination-btn {{ $page === $currentPage ? 'pagination-active' : '' }}" <span class="inline-flex items-center justify-center min-w-9 h-9 px-2 border border-brand bg-brand text-white text-[13px] font-mono" aria-current="page">{{ $page }}</span>
{{ $page === $currentPage ? 'aria-current="page"' : '' }} @else
@if ($page !== $currentPage) onclick="window.location.href='?page={{ $page }}'" @endif> <a href="{{ $url }}"
{{ $page }} class="inline-flex items-center justify-center min-w-9 h-9 px-2 border border-bg-rule-strong text-ink hover:bg-bg-elev text-[13px] font-mono transition-colors">{{ $page }}</a>
</button> @endif
@endforeach @endforeach
<!-- Ellipsis + Letzte Seite --> @if ($paginator->hasMorePages())
@if ($showEndEllipsis && $showFirstLast) <a href="{{ $paginator->nextPageUrl() }}" rel="next"
<span class="px-2 text-zinc-600 dark:text-zinc-400">...</span> class="inline-flex items-center justify-center w-9 h-9 border border-bg-rule-strong text-ink hover:bg-bg-elev transition-colors"
<button class="pagination-btn" onclick="window.location.href='?page={{ $totalPages }}'"> aria-label="Nächste Seite">
{{ $totalPages }} <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path d="M9 5l7 7-7 7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button> </a>
@else
<span class="inline-flex items-center justify-center w-9 h-9 border border-bg-rule text-ink-4 opacity-40 cursor-not-allowed" aria-hidden="true">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path d="M9 5l7 7-7 7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</span>
@endif @endif
</nav>
<!-- Nächste Seite --> @endif
<button
class="pagination-btn pagination-nav {{ !$hasNext ? 'disabled:opacity-50 disabled:cursor-not-allowed' : '' }}"
{{ !$hasNext ? 'disabled' : '' }} aria-label="Nächste Seite"
@if ($hasNext) onclick="window.location.href='?page={{ $currentPage + 1 }}'" @endif>
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
</svg>
</button>
</div>
</nav>

View file

@ -0,0 +1,104 @@
@props([
'plans' => null,
'popular' => 'business',
'pricingHref' => null,
'submitHref' => null,
])
@php
// Datengetrieben aus dem Tarif-Katalog (plans). Fällt die Tabelle leer aus,
// wird die Sektion komplett ausgeblendet.
$plans = $plans ?? \App\Models\Plan::active()->get();
$pricingHref ??= route('preise');
$submitHref ??= route('veroeffentlichen');
$fmtPrice = static fn (int $cents): string => number_format($cents / 100, $cents % 100 === 0 ? 0 : 2, ',', '.');
@endphp
@if ($plans->isNotEmpty())
<section class="max-w-layout mx-auto px-8 mt-16">
<header class="flex items-baseline justify-between mb-4 flex-wrap gap-3">
<h2 class="font-serif text-[28px] font-semibold m-0 tracking-[-0.3px] text-ink">Tarife &amp; Pakete</h2>
<a href="{{ $pricingHref }}" class="eyebrow muted hover:text-ink transition-colors inline-flex items-center gap-1.5 cursor-pointer">
Alle Details
<svg width="10" height="10" 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>
</header>
<hr class="rule-strong">
<div class="grid gap-px bg-bg-rule border border-bg-rule grid-cols-1 sm:grid-cols-2 lg:grid-cols-4">
@foreach ($plans as $plan)
@php
$isPopular = $plan->slug === $popular;
$hasMonthly = (int) $plan->monthly_price_cents > 0;
@endphp
<div class="relative flex flex-col p-6 bg-bg {{ $isPopular ? 'ring-1 ring-inset ring-brand' : '' }}">
@if ($isPopular)
<span class="absolute top-0 right-0 inline-flex items-center px-2.5 py-1 text-[9.5px] font-bold uppercase tracking-[0.14em] text-white bg-brand">
Beliebt
</span>
@endif
<div class="eyebrow muted mb-2">{{ $plan->name }}</div>
<div class="flex items-baseline gap-1.5 mb-1">
<span class="font-serif text-[34px] font-semibold leading-none tracking-[-0.6px] text-ink">{{ $fmtPrice((int) $plan->monthly_price_cents) }}&nbsp;€</span>
@if ($hasMonthly)
<span class="text-[12px] text-ink-3">/&nbsp;Monat</span>
@endif
</div>
@if ($hasMonthly && (int) $plan->yearly_price_cents > 0)
<div class="text-[11.5px] text-ink-3 mb-4">
{{ $fmtPrice((int) $plan->yearly_price_cents) }}&nbsp;€ / Jahr
<span class="text-gain font-medium">· 2 Monate gratis</span>
</div>
@else
<div class="mb-4"></div>
@endif
<ul class="space-y-2 mb-6 flex-1 list-none p-0 m-0 text-[12.5px] text-ink-2">
<li class="flex items-baseline gap-2">
<span class="font-mono text-[12px] font-semibold text-ink">{{ $plan->press_release_quota }}</span>
<span>Pressemitteilungen / Monat</span>
</li>
@if ($plan->daily_limit !== null)
<li class="flex items-baseline gap-2">
<span class="font-mono text-[12px] font-semibold text-ink">{{ $plan->daily_limit }}</span>
<span>max. pro Tag</span>
</li>
@else
<li class="flex items-baseline gap-2 text-ink-3">
<span class="font-mono text-[12px]">∞</span>
<span>kein Tageslimit</span>
</li>
@endif
</ul>
<a href="{{ $pricingHref }}"
class="inline-flex items-center justify-center gap-1.5 w-full px-4 py-2.5 text-[12.5px] font-semibold rounded-[2px] transition-colors cursor-pointer
{{ $isPopular ? 'bg-brand text-white hover:bg-brand-deep' : 'border border-bg-rule-strong text-ink hover:bg-bg-elev' }}">
Auswählen
<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>
@endforeach
</div>
<div class="flex items-center justify-between gap-4 flex-wrap mt-5">
<p class="text-[12px] text-ink-3 m-0">
Alle Preise zzgl. MwSt. · Jederzeit kündbar · Auch ohne Abo als Einzelveröffentlichung möglich.
</p>
<a href="{{ $submitHref }}" class="inline-flex items-center gap-1.5 text-[12.5px] font-semibold text-brand hover:text-brand-deep transition-colors cursor-pointer whitespace-nowrap">
Direkt veröffentlichen
<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>
</section>
@endif

View file

@ -52,9 +52,7 @@
<ul class="space-y-2 text-[13px] text-white/75 list-none p-0 m-0"> <ul class="space-y-2 text-[13px] text-white/75 list-none p-0 m-0">
<li><a href="{{ route('veroeffentlichen') }}" class="cursor-pointer hover:text-white transition-colors">Veröffentlichen</a></li> <li><a href="{{ route('veroeffentlichen') }}" class="cursor-pointer hover:text-white transition-colors">Veröffentlichen</a></li>
<li><a href="{{ route('preise') }}" class="cursor-pointer hover:text-white transition-colors">Tarife &amp; Pakete</a></li> <li><a href="{{ route('preise') }}" class="cursor-pointer hover:text-white transition-colors">Tarife &amp; Pakete</a></li>
<li><a href="#" class="cursor-pointer hover:text-white transition-colors">Verifizierter Newsroom</a></li>
<li><a href="{{ route('api') }}" class="cursor-pointer hover:text-white transition-colors">API &amp; RSS</a></li> <li><a href="{{ route('api') }}" class="cursor-pointer hover:text-white transition-colors">API &amp; RSS</a></li>
<li><a href="#" class="cursor-pointer hover:text-white transition-colors">Mediendaten</a></li>
</ul> </ul>
</div> </div>
@ -62,8 +60,9 @@
<div class="eyebrow mb-3.5">Unternehmen</div> <div class="eyebrow mb-3.5">Unternehmen</div>
<ul class="space-y-2 text-[13px] text-white/75 list-none p-0 m-0"> <ul class="space-y-2 text-[13px] text-white/75 list-none p-0 m-0">
<li><a href="{{ route('ueber-uns') }}" class="cursor-pointer hover:text-white transition-colors">{{ $aboutLabel }}</a></li> <li><a href="{{ route('ueber-uns') }}" class="cursor-pointer hover:text-white transition-colors">{{ $aboutLabel }}</a></li>
<li><a href="#" class="cursor-pointer hover:text-white transition-colors">Redaktion</a></li>
<li><a href="{{ route('kontakt') }}" class="cursor-pointer hover:text-white transition-colors">Kontakt</a></li> <li><a href="{{ route('kontakt') }}" class="cursor-pointer hover:text-white transition-colors">Kontakt</a></li>
<li><a href="{{ route('faq') }}" class="cursor-pointer hover:text-white transition-colors">FAQ</a></li>
<li><a href="{{ route('hilfe') }}" class="cursor-pointer hover:text-white transition-colors">Hilfe-Center</a></li>
<li><a href="{{ route('impressum') }}" class="cursor-pointer hover:text-white transition-colors">Impressum</a></li> <li><a href="{{ route('impressum') }}" class="cursor-pointer hover:text-white transition-colors">Impressum</a></li>
<li><a href="{{ route('datenschutz') }}" class="cursor-pointer hover:text-white transition-colors">Datenschutz</a></li> <li><a href="{{ route('datenschutz') }}" class="cursor-pointer hover:text-white transition-colors">Datenschutz</a></li>
</ul> </ul>
@ -75,8 +74,8 @@
<span>{{ $legal }}</span> <span>{{ $legal }}</span>
<span class="flex items-center gap-4 flex-wrap"> <span class="flex items-center gap-4 flex-wrap">
<a href="{{ route('agb') }}" class="cursor-pointer hover:text-white transition-colors">AGB</a> <a href="{{ route('agb') }}" class="cursor-pointer hover:text-white transition-colors">AGB</a>
<a href="#" class="cursor-pointer hover:text-white transition-colors">Cookie-Einstellungen</a> <a href="{{ route('cookies') }}" class="cursor-pointer hover:text-white transition-colors">Cookies</a>
<a href="{{ route('datenschutz') }}" class="cursor-pointer hover:text-white transition-colors">DSGVO</a> <a href="{{ route('datenschutz') }}" class="cursor-pointer hover:text-white transition-colors">Datenschutz</a>
</span> </span>
</div> </div>
</div> </div>

View file

@ -84,8 +84,9 @@
</strong> </strong>
</span> </span>
<span class="hidden lg:inline-block w-px h-[14px] bg-ink-on-dark-rule"></span> <span class="hidden lg:inline-block w-px h-[14px] bg-ink-on-dark-rule"></span>
<a href="#newsletter" class="hidden lg:inline cursor-pointer hover:text-ink-on-dark transition-colors">Newsletter</a> <a href="{{ route('preise') }}" class="cursor-pointer font-medium text-ink-on-dark hover:text-brand transition-colors">Preise</a>
<a href="#rss" class="hidden lg:inline cursor-pointer hover:text-ink-on-dark transition-colors">RSS</a> <span class="hidden lg:inline-block w-px h-[14px] bg-ink-on-dark-rule"></span>
<a href="{{ route('faq') }}" class="hidden lg:inline cursor-pointer hover:text-ink-on-dark transition-colors">FAQ</a>
<a href="{{ route('api') }}" class="hidden lg:inline cursor-pointer hover:text-ink-on-dark transition-colors">API</a> <a href="{{ route('api') }}" class="hidden lg:inline cursor-pointer hover:text-ink-on-dark transition-colors">API</a>
</span> </span>
</div> </div>
@ -141,8 +142,8 @@
</svg> </svg>
</button> </button>
{{-- Anmelden --}} {{-- Anmelden: führt in den Hub (Portal-Domain). --}}
<a href="#anmelden" <a href="{{ rtrim(config('domains.domain_portal_url', config('app.url')), '/') }}/login"
class="inline-flex items-center gap-2 px-2 sm:px-3 lg:px-4 py-2 lg:py-2.5 text-[13px] font-semibold text-ink rounded-[2px] cursor-pointer hover:text-brand transition-colors" class="inline-flex items-center gap-2 px-2 sm:px-3 lg:px-4 py-2 lg:py-2.5 text-[13px] font-semibold text-ink rounded-[2px] cursor-pointer hover:text-brand transition-colors"
aria-label="Anmelden"> aria-label="Anmelden">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" class="sm:hidden" aria-hidden="true"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" class="sm:hidden" aria-hidden="true">

View file

@ -0,0 +1,57 @@
@props([
'eyebrow' => null,
'title' => '',
'lead' => null,
'updated' => null,
'breadcrumb' => null,
])
{{--
Editorial-Gerüst für statische/Info-Seiten (Pflichtseiten, FAQ, Hilfe …).
Liefert site-header, Breadcrumb, Masthead und site-footer; der Seiteninhalt
kommt als Slot. Prosa-Seiten wrappen ihren Inhalt in `.pm-body` (zentrale
Editorial-Typografie aus shared-styles.css).
--}}
@php
$brandConfig = config('domains.domains.'.config('app.theme').'.brand', []);
$brandName = $brandConfig['name'] ?? 'businessportal';
$brandAccent = $brandConfig['accent'] ?? '24';
@endphp
<x-web.site-header />
<main class="bg-bg text-ink">
{{-- Breadcrumb --}}
<div class="border-b border-bg-rule">
<div class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 py-2.5 flex items-center gap-2 text-[12px] text-ink-3">
<a href="{{ route('web.home') }}" class="hover:text-ink transition-colors">{{ $brandName }}{{ $brandAccent }}</a>
@if ($breadcrumb)
<span class="text-ink-4" aria-hidden="true">›</span>
<span class="text-ink">{{ $breadcrumb }}</span>
@endif
</div>
</div>
{{-- Masthead --}}
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 pt-8 lg:pt-10">
@if ($eyebrow)
<div class="eyebrow mb-3">{{ $eyebrow }}</div>
@endif
<h1 class="font-serif text-[34px] sm:text-[44px] font-semibold m-0 leading-[1.05] tracking-[-1px] text-ink">{{ $title }}</h1>
@if ($lead)
<p class="font-serif text-[16px] leading-[1.55] m-0 mt-4 max-w-[680px] text-ink-2">{{ $lead }}</p>
@endif
@if ($updated)
<p class="text-[12px] text-ink-3 m-0 mt-3">{{ $updated }}</p>
@endif
<hr class="rule-strong mt-6">
</section>
{{-- Inhalt --}}
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 mt-8 pb-16">
{{ $slot }}
</section>
</main>
<x-web.site-footer />

View file

@ -129,7 +129,7 @@ new class extends Component
$inFeedAd = [ $inFeedAd = [
'time' => '12:14', 'time' => '12:14',
'date' => now()->translatedFormat('j. MMM'), 'date' => now()->translatedFormat('j. M'),
'category' => 'Cloud · Software', 'category' => 'Cloud · Software',
'title' => 'Microsoft Azure: Neue EU-Region Frankfurt mit DSGVO-zertifizierter KI-Infrastruktur', 'title' => 'Microsoft Azure: Neue EU-Region Frankfurt mit DSGVO-zertifizierter KI-Infrastruktur',
'company' => 'Microsoft Deutschland GmbH', 'company' => 'Microsoft Deutschland GmbH',

View file

@ -1,158 +1,105 @@
@extends('web.layouts.web-master') @extends('web.layouts.web-master')
@section('title', 'AGB - Business Portal 24') @section('title', 'Allgemeine Geschäftsbedingungen')
@section('meta_description', 'Allgemeine Geschäftsbedingungen für die Nutzung der Plattform.')
@section('content') @section('content')
<x-web.static-page
eyebrow="Rechtliches"
title="Allgemeine Geschäftsbedingungen"
breadcrumb="AGB"
updated="Stand: Januar 2025"
>
{{-- Platzhalter-Text — vor Go-Live durch die finalen AGB ersetzen. --}}
<div class="pm-body max-w-[760px]">
<h2>§ 1 Geltungsbereich</h2>
<p>
Diese Allgemeinen Geschäftsbedingungen (AGB) gelten für alle Verträge zwischen der Business Portal
GmbH (im Folgenden „Anbieter") und ihren Kunden (im Folgenden „Kunde" oder „Nutzer") über die
Nutzung der Plattform Business Portal.
</p>
<p>
Abweichende, entgegenstehende oder ergänzende AGB des Kunden werden nicht Vertragsbestandteil, es
sei denn, der Anbieter stimmt ihrer Geltung ausdrücklich schriftlich zu.
</p>
<main class="min-h-screen flex flex-col bg-white dark:bg-zinc-950 transition-colors duration-200"> <h2>§ 2 Vertragsgegenstand</h2>
<livewire:web.burger-menu /> <p>
<livewire:web.header /> Der Anbieter stellt dem Kunden eine Online-Plattform zur Veröffentlichung von Pressemitteilungen
zur Verfügung. Der Funktionsumfang richtet sich nach dem gewählten Tarif.
</p>
<p>Der Anbieter ist berechtigt, Subunternehmer zur Vertragserfüllung einzusetzen.</p>
<!-- Hero Section --> <h2>§ 3 Vertragsschluss und Registrierung</h2>
<section class="relative overflow-hidden text-white py-16 animate-fade-in" <p>
style="background: var(--gradient-hero);"> Der Vertrag kommt durch die Registrierung des Kunden und die Bestätigung durch den Anbieter
<div class="container mx-auto px-4 text-center"> zustande. Die Registrierung ist nur volljährigen, unbeschränkt geschäftsfähigen Personen gestattet.
<h1 class="text-4xl md:text-5xl font-bold mb-4 animate-fade-in-up"> </p>
Allgemeine Geschäftsbedingungen <p>
</h1> Der Kunde verpflichtet sich, bei der Registrierung wahre und vollständige Angaben zu machen und
</div> diese aktuell zu halten.
</section> </p>
<!-- Content Section --> <h2>§ 4 Leistungsumfang</h2>
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200"> <p>
<div class="container mx-auto px-4"> Der konkrete Leistungsumfang richtet sich nach dem gewählten Tarif. Eine Beschreibung der Tarife
<div class="max-w-4xl mx-auto"> findet sich auf der Preisseite der Website.
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-8 md:p-12 transition-colors duration-200"> </p>
<p>
Der Anbieter ist berechtigt, die Dienste weiterzuentwickeln und Funktionen zu ändern, sofern dies
die Vertragserfüllung nicht wesentlich beeinträchtigt.
</p>
<div class="mb-8"> <h2>§ 5 Verfügbarkeit</h2>
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">§ 1 Geltungsbereich</h2> <p>
<p class="text-zinc-600 dark:text-zinc-400 mb-4"> Der Anbieter stellt die Plattform mit einer Verfügbarkeit von mindestens 98 % im Jahresmittel zur
Diese Allgemeinen Geschäftsbedingungen (AGB) gelten für alle Verträge zwischen der Business Portal GmbH (im Folgenden „Anbieter") Verfügung. Ausgenommen hiervon sind Wartungsarbeiten sowie Ausfälle, die nicht im Einflussbereich
und ihren Kunden (im Folgenden „Kunde" oder „Nutzer") über die Nutzung der Plattform Business Portal. des Anbieters liegen.
</p> </p>
<p class="text-zinc-600 dark:text-zinc-400">
Abweichende, entgegenstehende oder ergänzende AGB des Kunden werden nicht Vertragsbestandteil, es sei denn, der Anbieter
stimmt ihrer Geltung ausdrücklich schriftlich zu.
</p>
</div>
<div class="mb-8"> <h2>§ 6 Pflichten des Kunden</h2>
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">§ 2 Vertragsgegenstand</h2> <p>Der Kunde verpflichtet sich:</p>
<p class="text-zinc-600 dark:text-zinc-400 mb-4"> <ul>
Der Anbieter stellt dem Kunden eine Online-Plattform zur Veröffentlichung von Pressemitteilungen zur Verfügung. <li>Nur rechtmäßige Inhalte zu veröffentlichen</li>
Der Funktionsumfang richtet sich nach dem gewählten Tarif. <li>Keine Rechte Dritter zu verletzen</li>
</p> <li>Die Zugangsdaten vertraulich zu behandeln</li>
<p class="text-zinc-600 dark:text-zinc-400"> <li>Den Account nicht an Dritte weiterzugeben</li>
Der Anbieter ist berechtigt, Subunternehmer zur Vertragserfüllung einzusetzen. <li>Die Plattform nicht missbräuchlich zu nutzen</li>
</p> </ul>
</div>
<div class="mb-8"> <h2>§ 7 Vergütung und Zahlung</h2>
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">§ 3 Vertragsschluss und Registrierung</h2> <p>
<p class="text-zinc-600 dark:text-zinc-400 mb-4"> Die Vergütung richtet sich nach dem gewählten Tarif. Alle Preise verstehen sich zzgl. der
Der Vertrag kommt durch die Registrierung des Kunden und die Bestätigung durch den Anbieter zustande. gesetzlichen Mehrwertsteuer.
Die Registrierung ist nur volljährigen, unbeschränkt geschäftsfähigen Personen gestattet. </p>
</p> <p>
<p class="text-zinc-600 dark:text-zinc-400"> Die Zahlung erfolgt im Voraus für den gewählten Abrechnungszeitraum (monatlich oder jährlich) per
Der Kunde verpflichtet sich, bei der Registrierung wahre und vollständige Angaben zu machen und diese aktuell zu halten. Kreditkarte, SEPA-Lastschrift oder anderen vom Anbieter akzeptierten Zahlungsmethoden.
</p> </p>
</div>
<div class="mb-8"> <h2>§ 8 Laufzeit und Kündigung</h2>
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">§ 4 Leistungsumfang</h2> <p>
<p class="text-zinc-600 dark:text-zinc-400 mb-4"> Der Vertrag wird für die gewählte Mindestlaufzeit geschlossen und verlängert sich automatisch um den
Der konkrete Leistungsumfang richtet sich nach dem gewählten Tarif. Eine Beschreibung der Tarife findet sich auf der gewählten Abrechnungszeitraum, sofern nicht gekündigt wird.
Preisseite der Website. </p>
</p> <p>
<p class="text-zinc-600 dark:text-zinc-400"> Die Kündigung muss schriftlich oder in Textform (z. B. E-Mail) unter Einhaltung einer Frist von 30
Der Anbieter ist berechtigt, die Dienste weiterzuentwickeln und Funktionen zu ändern, sofern dies die Vertragserfüllung Tagen zum Ende des Abrechnungszeitraums erfolgen.
nicht wesentlich beeinträchtigt. </p>
</p>
</div>
<div class="mb-8"> <h2>§ 9 Haftung</h2>
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">§ 5 Verfügbarkeit</h2> <p>
<p class="text-zinc-600 dark:text-zinc-400"> Der Anbieter haftet nur für Schäden, die auf einer vorsätzlichen oder grob fahrlässigen
Der Anbieter stellt die Plattform mit einer Verfügbarkeit von mindestens 98% im Jahresmittel zur Verfügung. Pflichtverletzung beruhen. Dies gilt nicht für Schäden aus der Verletzung des Lebens, des Körpers
Ausgenommen hiervon sind Wartungsarbeiten sowie Ausfälle, die nicht im Einflussbereich des Anbieters liegen. oder der Gesundheit.
</p> </p>
</div>
<div class="mb-8">
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">§ 6 Pflichten des Kunden</h2>
<p class="text-zinc-600 dark:text-zinc-400 mb-4">Der Kunde verpflichtet sich:</p>
<ul class="list-disc list-inside text-zinc-600 dark:text-zinc-400 mb-4">
<li>Nur rechtmäßige Inhalte zu veröffentlichen</li>
<li>Keine Rechte Dritter zu verletzen</li>
<li>Die Zugangsdaten vertraulich zu behandeln</li>
<li>Den Account nicht an Dritte weiterzugeben</li>
<li>Die Plattform nicht missbräuchlich zu nutzen</li>
</ul>
</div>
<div class="mb-8">
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">§ 7 Vergütung und Zahlung</h2>
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
Die Vergütung richtet sich nach dem gewählten Tarif. Alle Preise verstehen sich zzgl. der gesetzlichen Mehrwertsteuer.
</p>
<p class="text-zinc-600 dark:text-zinc-400">
Die Zahlung erfolgt im Voraus für den gewählten Abrechnungszeitraum (monatlich oder jährlich) per Kreditkarte,
SEPA-Lastschrift oder anderen vom Anbieter akzeptierten Zahlungsmethoden.
</p>
</div>
<div class="mb-8">
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">§ 8 Laufzeit und Kündigung</h2>
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
Der Vertrag wird für die gewählte Mindestlaufzeit geschlossen und verlängert sich automatisch um den gewählten
Abrechnungszeitraum, sofern nicht gekündigt wird.
</p>
<p class="text-zinc-600 dark:text-zinc-400">
Die Kündigung muss schriftlich oder in Textform (z.B. E-Mail) unter Einhaltung einer Frist von 30 Tagen zum Ende
des Abrechnungszeitraums erfolgen.
</p>
</div>
<div class="mb-8">
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">§ 9 Haftung</h2>
<p class="text-zinc-600 dark:text-zinc-400">
Der Anbieter haftet nur für Schäden, die auf einer vorsätzlichen oder grob fahrlässigen Pflichtverletzung beruhen.
Dies gilt nicht für Schäden aus der Verletzung des Lebens, des Körpers oder der Gesundheit.
</p>
</div>
<div class="mb-8">
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">§ 10 Schlussbestimmungen</h2>
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
Es gilt das Recht der Bundesrepublik Deutschland unter Ausschluss des UN-Kaufrechts.
</p>
<p class="text-zinc-600 dark:text-zinc-400">
Sollten einzelne Bestimmungen dieser AGB unwirksam sein oder werden, berührt dies die Wirksamkeit der übrigen Bestimmungen nicht.
</p>
</div>
<div>
<p class="text-sm text-zinc-500 dark:text-zinc-500">
Stand: Januar 2025
</p>
</div>
</div>
</div>
</div>
</section>
<livewire:web.footer />
</main>
<h2>§ 10 Schlussbestimmungen</h2>
<p>Es gilt das Recht der Bundesrepublik Deutschland unter Ausschluss des UN-Kaufrechts.</p>
<p>
Sollten einzelne Bestimmungen dieser AGB unwirksam sein oder werden, berührt dies die Wirksamkeit
der übrigen Bestimmungen nicht.
</p>
</div>
</x-web.static-page>
@endsection @endsection
@push('styles')
<style>
:root {
--color-primary: {{ $domainConfig['color_scheme']['primary'] ?? '#cf3628' }};
--color-secondary: {{ $domainConfig['color_scheme']['secondary'] ?? '#f0834a' }};
}
[x-cloak] { display: none !important; }
</style>
@endpush

View file

@ -1,280 +1,97 @@
@extends('web.layouts.web-master') @extends('web.layouts.web-master')
@section('title', 'API & Integrationen - Business Portal 24') @section('title', 'API & Integrationen')
@section('meta_description', 'Integrieren Sie unsere Dienste per REST-API: Pressemitteilungen programmatisch veröffentlichen, verwalten und abrufen.')
@php
$features = [
['title' => 'RESTful API', 'text' => 'Moderne REST-Architektur mit JSON-Responses für einfache Integration in jede Programmiersprache.'],
['title' => 'OAuth 2.0', 'text' => 'Sichere Authentifizierung mit OAuth 2.0 und API-Tokens für maximale Sicherheit.'],
['title' => 'Webhooks', 'text' => 'Echtzeit-Benachrichtigungen über Events wie Veröffentlichungen oder Statusänderungen.'],
['title' => 'Dokumentation', 'text' => 'Umfassende API-Dokumentation mit Code-Beispielen in verschiedenen Sprachen.'],
['title' => 'Rate Limiting', 'text' => 'Faire Rate Limits mit klaren Headern und automatischer Skalierung bei Bedarf.'],
['title' => 'SDKs', 'text' => 'Offizielle SDKs für PHP, JavaScript, Python und weitere Sprachen.'],
];
$integrations = ['WordPress', 'Zapier', 'Slack', 'HubSpot'];
@endphp
@section('content') @section('content')
<x-web.static-page
eyebrow="Entwickler"
title="API & Integrationen"
lead="Integrieren Sie unsere Dienste nahtlos in Ihre bestehenden Systeme und Workflows – per REST-API, Webhooks und SDKs."
breadcrumb="API"
>
{{-- Überblick --}}
<div class="pm-body max-w-[760px]">
<h2>Leistungsstarke REST-API</h2>
<p>
Unsere RESTful API ermöglicht es Ihnen, Pressemitteilungen programmatisch zu veröffentlichen, zu
verwalten und abzurufen – ideal für Unternehmen mit hohem Veröffentlichungsvolumen oder bestehenden
Content-Management-Systemen.
</p>
<p>
Die API ist vollständig dokumentiert und unterstützt moderne Authentifizierungsmethoden sowie
Webhooks für Echtzeit-Benachrichtigungen.
</p>
</div>
<main class="min-h-screen flex flex-col bg-white dark:bg-zinc-950 transition-colors duration-200"> {{-- Features --}}
<!-- Burger Menu Component --> <h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">API-Features</h2>
<livewire:web.burger-menu /> <div class="grid gap-px bg-bg-rule border border-bg-rule grid-cols-1 sm:grid-cols-2 lg:grid-cols-3">
@foreach ($features as $feature)
<!-- Header Component --> <div class="bg-bg p-6">
<livewire:web.header /> <h3 class="text-[14px] font-semibold text-ink m-0 mb-2">{{ $feature['title'] }}</h3>
<p class="text-[12.5px] leading-[1.55] text-ink-2 m-0">{{ $feature['text'] }}</p>
<!-- Hero Section -->
<section class="relative overflow-hidden text-white py-20 animate-fade-in"
style="background: var(--gradient-hero);">
<div class="container mx-auto px-4">
<div class="max-w-3xl mx-auto text-center">
<h1 class="text-4xl md:text-5xl font-bold mb-6 animate-fade-in-up">
API & Integrationen
</h1>
<p class="text-xl text-white/90 leading-relaxed animate-fade-in-up animation-delay-200">
Integrieren Sie Business Portal nahtlos in Ihre bestehenden Systeme und Workflows
</p>
</div> </div>
</div> @endforeach
<!-- Decorative Pattern --> </div>
<div class="absolute top-0 right-0 opacity-10">
<svg width="404" height="384" fill="none" viewBox="0 0 404 384">
<defs>
<pattern id="pattern-hero-api" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<rect x="0" y="0" width="4" height="4" fill="currentColor"/>
</pattern>
</defs>
<rect width="404" height="384" fill="url(#pattern-hero-api)"/>
</svg>
</div>
</section>
<!-- API Overview Section --> {{-- Code-Beispiel --}}
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200"> <h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">Schneller Einstieg</h2>
<div class="container mx-auto px-4"> <p class="text-[13px] text-ink-2 m-0 mb-4 max-w-[640px]">Veröffentlichen Sie Ihre erste Pressemitteilung in wenigen Zeilen Code.</p>
<div class="max-w-4xl mx-auto"> <div class="bg-[#16140f] border border-bg-rule-strong rounded-[3px] p-5 overflow-x-auto">
<div class="text-center mb-12"> <div class="text-[11.5px] text-white/45 mb-3 font-mono">// Beispiel: Pressemitteilung veröffentlichen</div>
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-4"> <pre class="text-[12.5px] leading-[1.6] font-mono text-[#9ad1a5] m-0"><code>curl -X POST https://api.example.com/v1/releases \
Leistungsstarke REST API
</h2>
<p class="text-lg text-zinc-600 dark:text-zinc-400">
Automatisieren Sie Ihre Presseveröffentlichungen und integrieren Sie unsere Dienste
</p>
</div>
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-8 md:p-12 transition-colors duration-200">
<p class="text-lg text-zinc-900 dark:text-zinc-100 leading-relaxed mb-6">
Unsere RESTful API ermöglicht es Ihnen, Pressemitteilungen programmatisch zu veröffentlichen, zu verwalten und abzurufen. Perfekt für Unternehmen mit hohem Veröffentlichungsvolumen oder bestehenden Content-Management-Systemen.
</p>
<p class="text-lg text-zinc-900 dark:text-zinc-100 leading-relaxed">
Die API ist vollständig dokumentiert und unterstützt moderne Authentifizierungsmethoden sowie Webhooks für Echtzeit-Benachrichtigungen.
</p>
</div>
</div>
</div>
</section>
<!-- API Features Section -->
<section class="py-16 bg-zinc-50/50 dark:bg-zinc-900/50 transition-colors duration-200">
<div class="container mx-auto px-4">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">
API Features
</h2>
<p class="text-zinc-600 dark:text-zinc-400 max-w-2xl mx-auto">
Alles, was Sie für eine nahtlose Integration benötigen
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 max-w-6xl mx-auto">
<!-- Feature 1 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
RESTful API
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Moderne REST-Architektur mit JSON-Responses für einfache Integration in jede Programmiersprache.
</p>
</div>
<!-- Feature 2 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
OAuth 2.0
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Sichere Authentifizierung mit OAuth 2.0 und API-Tokens für maximale Sicherheit.
</p>
</div>
<!-- Feature 3 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
Webhooks
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Erhalten Sie Echtzeit-Benachrichtigungen über Events wie Veröffentlichungen oder Statusänderungen.
</p>
</div>
<!-- Feature 4 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
Dokumentation
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Umfassende API-Dokumentation mit Code-Beispielen in verschiedenen Sprachen.
</p>
</div>
<!-- Feature 5 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
Rate Limiting
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Faire Rate Limits mit klaren Headern und automatischer Skalierung bei Bedarf.
</p>
</div>
<!-- Feature 6 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
SDKs
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Offizielle SDKs für PHP, JavaScript, Python und weitere Sprachen verfügbar.
</p>
</div>
</div>
</div>
</section>
<!-- Code Example Section -->
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200">
<div class="container mx-auto px-4">
<div class="max-w-4xl mx-auto">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">
Schneller Einstieg
</h2>
<p class="text-zinc-600 dark:text-zinc-400">
Veröffentlichen Sie Ihre erste Pressemitteilung in wenigen Zeilen Code
</p>
</div>
<div class="bg-zinc-900 dark:bg-zinc-950 rounded-xl border border-zinc-800 p-6 overflow-x-auto">
<div class="text-sm text-zinc-400 mb-4">// Example: Pressemitteilung veröffentlichen</div>
<pre class="text-green-400 font-mono text-sm"><code>curl -X POST https://api.businessportal.de/v1/releases \
-H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d '{ -d '{
"title": "Neue Produktankündigung", "title": "Neue Produktankündigung",
"content": "Unser neues Produkt...", "content": "Unser neues Produkt …",
"category": "wirtschaft", "category": "wirtschaft",
"publish_at": "2025-01-15T10:00:00Z" "publish_at": "2026-01-15T10:00:00Z"
}'</code></pre> }'</code></pre>
</div> </div>
{{-- TODO: Link auf die vollständige API-Dokumentation, sobald sie online ist. --}}
<p class="text-[12px] text-ink-3 m-0 mt-3">Die vollständige Dokumentation folgt. Bei Fragen zum API-Zugang hilft unser <a href="{{ route('kontakt') }}" class="text-brand hover:underline">Support</a>.</p>
<div class="mt-8 text-center"> {{-- Integrationen --}}
<a href="#" class="inline-flex items-center justify-center px-6 py-3 text-sm font-medium text-white rounded-lg shadow-md hover:shadow-lg transition-all" style="background: var(--gradient-hero);"> <h2 class="font-serif text-[26px] font-semibold tracking-[-0.4px] text-ink m-0 mt-14 mb-4">Native Integrationen</h2>
Zur vollständigen Dokumentation <div class="grid gap-px bg-bg-rule border border-bg-rule grid-cols-2 md:grid-cols-4">
</a> @foreach ($integrations as $integration)
</div> <div class="bg-bg p-6 flex items-center justify-center">
<span class="text-[13px] font-semibold text-ink-2">{{ $integration }}</span>
</div> </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">Starten Sie mit der API</h2>
<p class="text-[13px] text-ink-2 mt-1.5 mb-0">API-Zugang ist ab dem passenden Tarif verfügbar – Details finden Sie auf der Preisseite.</p>
</div> </div>
</section> <div class="flex flex-wrap gap-3 flex-shrink-0">
<a href="{{ route('preise') }}"
<!-- Integrations Section --> 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">
<section class="py-16 bg-zinc-50/50 dark:bg-zinc-900/50 transition-colors duration-200"> Preise ansehen
<div class="container mx-auto px-4"> </a>
<div class="text-center mb-12"> <a href="{{ route('kontakt') }}"
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-4"> 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]">
Native Integrationen Kontakt aufnehmen
</h2> </a>
<p class="text-zinc-600 dark:text-zinc-400 max-w-2xl mx-auto">
Verbinden Sie Business Portal mit Ihren Lieblings-Tools
</p>
</div>
<div class="grid grid-cols-2 md:grid-cols-4 gap-8 max-w-4xl mx-auto">
<!-- Integration logos would go here -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 flex items-center justify-center hover:shadow-lg transition-all">
<span class="text-zinc-600 dark:text-zinc-400 font-semibold">WordPress</span>
</div>
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 flex items-center justify-center hover:shadow-lg transition-all">
<span class="text-zinc-600 dark:text-zinc-400 font-semibold">Zapier</span>
</div>
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 flex items-center justify-center hover:shadow-lg transition-all">
<span class="text-zinc-600 dark:text-zinc-400 font-semibold">Slack</span>
</div>
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 flex items-center justify-center hover:shadow-lg transition-all">
<span class="text-zinc-600 dark:text-zinc-400 font-semibold">HubSpot</span>
</div>
</div>
</div> </div>
</section> </div>
</x-web.static-page>
<!-- CTA Section -->
<section class="py-16 text-white" style="background: var(--gradient-hero);">
<div class="container mx-auto px-4 text-center">
<div class="flex justify-center mb-6">
<svg class="h-16 w-16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
</svg>
</div>
<h2 class="text-3xl font-bold mb-4">
Starten Sie mit der API
</h2>
<p class="text-xl text-white/90 mb-8 max-w-2xl mx-auto">
API-Zugang ist ab dem Professional-Tarif verfügbar
</p>
<div class="flex gap-4 justify-center">
<a href="/preise" class="inline-flex items-center justify-center px-8 py-4 text-sm font-medium bg-white text-[var(--color-primary)] hover:bg-zinc-100 rounded-lg shadow-md hover:shadow-lg transition-all">
Preise ansehen
</a>
<a href="#" class="inline-flex items-center justify-center px-8 py-4 text-sm font-medium text-white border-2 border-white hover:bg-white/10 rounded-lg transition-all">
Dokumentation
</a>
</div>
</div>
</section>
<!-- Footer Component -->
<livewire:web.footer />
</main>
@endsection @endsection
@push('styles')
<style>
/* Domain-spezifische Color-Variablen für Inline-Styles */
:root {
--color-primary: {{ $domainConfig['color_scheme']['primary'] ?? '#cf3628' }};
--color-secondary: {{ $domainConfig['color_scheme']['secondary'] ?? '#f0834a' }};
}
/* Alpine.js Cloak */
[x-cloak] {
display: none !important;
}
</style>
@endpush

View file

@ -36,6 +36,8 @@
<x-web.industry-index :industries="($industryIndex ?? collect())->isNotEmpty() ? $industryIndex->toArray() : null" /> <x-web.industry-index :industries="($industryIndex ?? collect())->isNotEmpty() ? $industryIndex->toArray() : null" />
<x-web.pricing-teaser />
<x-web.newsletter-strip /> <x-web.newsletter-strip />
<x-web.quality-summary :stats="$homeStats ?? []" /> <x-web.quality-summary :stats="$homeStats ?? []" />

View file

@ -1,201 +1,120 @@
@extends('web.layouts.web-master') @extends('web.layouts.web-master')
@section('title', 'Cookie-Richtlinien - Business Portal 24') @section('title', 'Cookie-Richtlinien')
@section('meta_description', 'Informationen zu den auf dieser Website eingesetzten Cookies und deren Verwaltung.')
@section('content') @section('content')
<x-web.static-page
eyebrow="Rechtliches"
title="Cookie-Richtlinien"
breadcrumb="Cookies"
updated="Stand: Januar 2025"
>
{{-- Platzhalter-Text — vor Go-Live an das echte Cookie-/Consent-Setup anpassen. --}}
<div class="pm-body max-w-[760px]">
<h2>Was sind Cookies?</h2>
<p>
Cookies sind kleine Textdateien, die auf Ihrem Computer oder mobilen Gerät gespeichert werden, wenn
Sie eine Website besuchen. Sie ermöglichen es der Website, Ihr Gerät zu erkennen und bestimmte
Informationen über Ihre Nutzung zu speichern.
</p>
<p>
Wir verwenden Cookies, um Ihnen ein optimales Nutzungserlebnis zu bieten und unsere Website
kontinuierlich zu verbessern.
</p>
<main class="min-h-screen flex flex-col bg-white dark:bg-zinc-950 transition-colors duration-200"> <h2>Welche Cookies verwenden wir?</h2>
<livewire:web.burger-menu />
<livewire:web.header />
<!-- Hero Section --> <h3>1. Notwendige Cookies</h3>
<section class="relative overflow-hidden text-white py-16 animate-fade-in" style="background: var(--gradient-hero);"> <p>
<div class="container mx-auto px-4 text-center"> Diese Cookies sind für den Betrieb der Website unbedingt erforderlich und können nicht deaktiviert
<h1 class="text-4xl md:text-5xl font-bold mb-4 animate-fade-in-up"> werden. Beispiele:
Cookie-Richtlinien </p>
</h1> <ul>
<li>Session-Cookies (Anmeldung)</li>
<li>Sicherheits-Cookies (CSRF-Schutz)</li>
<li>Cookie-Einwilligungs-Cookies</li>
</ul>
<h3>2. Funktionale Cookies</h3>
<p>Diese Cookies ermöglichen erweiterte Funktionalitäten und Personalisierung. Beispiele:</p>
<ul>
<li>Spracheinstellungen</li>
<li>Dark-Mode-Präferenzen</li>
<li>Gespeicherte Filtereinstellungen</li>
</ul>
<h3>3. Analytische Cookies</h3>
<p>Diese Cookies helfen uns zu verstehen, wie Besucher mit unserer Website interagieren. Dienste:</p>
<ul>
<li>Google Analytics (anonymisiert)</li>
<li>Interne Analysetools</li>
</ul>
<h3>4. Marketing-Cookies</h3>
<p>Diese Cookies werden verwendet, um Ihnen relevante Werbung anzuzeigen. Beispiele:</p>
<ul>
<li>Remarketing-Cookies</li>
<li>Social Media Tracking</li>
</ul>
</div>
{{-- Cookie-Laufzeiten als editoriale Tabelle (außerhalb .pm-body für klare Rahmung). --}}
<div class="max-w-[760px] mt-8">
<h2 class="font-serif text-[22px] font-semibold tracking-[-0.3px] text-ink m-0 mb-4">Cookie-Laufzeiten</h2>
<div class="border border-bg-rule overflow-hidden">
<table class="w-full text-[13px] border-collapse">
<thead>
<tr class="text-left text-ink-3 bg-bg-elev border-b border-bg-rule">
<th class="font-medium px-4 py-2.5">Cookie-Typ</th>
<th class="font-medium px-4 py-2.5">Laufzeit</th>
</tr>
</thead>
<tbody class="divide-y divide-bg-rule">
<tr>
<td class="px-4 py-2.5 text-ink-2">Session-Cookies</td>
<td class="px-4 py-2.5 text-ink-2">Bis zum Schließen des Browsers</td>
</tr>
<tr>
<td class="px-4 py-2.5 text-ink-2">Funktionale Cookies</td>
<td class="px-4 py-2.5 text-ink-2">1 Jahr</td>
</tr>
<tr>
<td class="px-4 py-2.5 text-ink-2">Analytische Cookies</td>
<td class="px-4 py-2.5 text-ink-2">2 Jahre</td>
</tr>
<tr>
<td class="px-4 py-2.5 text-ink-2">Marketing-Cookies</td>
<td class="px-4 py-2.5 text-ink-2">1 Jahr</td>
</tr>
</tbody>
</table>
</div> </div>
</section> </div>
<!-- Content Section --> <div class="pm-body max-w-[760px] mt-8">
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200"> <h2>Wie können Sie Cookies verwalten?</h2>
<div class="container mx-auto px-4"> <p>Sie können Ihre Cookie-Einstellungen jederzeit ändern. Die meisten Browser erlauben es Ihnen:</p>
<div class="max-w-4xl mx-auto"> <ul>
<div <li>Cookies anzuzeigen und zu löschen</li>
class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-8 md:p-12 transition-colors duration-200"> <li>Cookies von Drittanbietern zu blockieren</li>
<li>Alle Cookies zu blockieren</li>
<div class="mb-8"> <li>Cookies beim Schließen des Browsers zu löschen</li>
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">Was sind Cookies?</h2> </ul>
<p class="text-zinc-600 dark:text-zinc-400 mb-4"> <p>
Cookies sind kleine Textdateien, die auf Ihrem Computer oder mobilen Gerät gespeichert Bitte beachten Sie, dass das Deaktivieren von Cookies die Funktionalität unserer Website
werden, wenn Sie eine Website besuchen. beeinträchtigen kann.
Sie ermöglichen es der Website, Ihr Gerät zu erkennen und bestimmte Informationen über Ihre </p>
Nutzung zu speichern.
</p>
<p class="text-zinc-600 dark:text-zinc-400">
Wir verwenden Cookies, um Ihnen ein optimales Nutzungserlebnis zu bieten und unsere Website
kontinuierlich zu verbessern.
</p>
</div>
<div class="mb-8">
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">Welche Cookies verwenden
wir?</h2>
<div class="mb-6">
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-3">1. Notwendige
Cookies</h3>
<p class="text-zinc-600 dark:text-zinc-400 mb-3">
Diese Cookies sind für den Betrieb der Website unbedingt erforderlich und können nicht
deaktiviert werden.
</p>
<div class="bg-zinc-50 dark:bg-zinc-950 rounded-lg p-4">
<p class="text-sm text-zinc-600 dark:text-zinc-400 mb-2"><strong>Beispiele:</strong></p>
<ul class="list-disc list-inside text-sm text-zinc-600 dark:text-zinc-400">
<li>Session-Cookies (Anmeldung)</li>
<li>Sicherheits-Cookies (CSRF-Schutz)</li>
<li>Cookie-Einwilligungs-Cookies</li>
</ul>
</div>
</div>
<div class="mb-6">
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-3">2. Funktionale
Cookies</h3>
<p class="text-zinc-600 dark:text-zinc-400 mb-3">
Diese Cookies ermöglichen erweiterte Funktionalitäten und Personalisierung.
</p>
<div class="bg-zinc-50 dark:bg-zinc-950 rounded-lg p-4">
<p class="text-sm text-zinc-600 dark:text-zinc-400 mb-2"><strong>Beispiele:</strong></p>
<ul class="list-disc list-inside text-sm text-zinc-600 dark:text-zinc-400">
<li>Spracheinstellungen</li>
<li>Dark-Mode-Präferenzen</li>
<li>Gespeicherte Filtereinstellungen</li>
</ul>
</div>
</div>
<div class="mb-6">
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-3">3. Analytische
Cookies</h3>
<p class="text-zinc-600 dark:text-zinc-400 mb-3">
Diese Cookies helfen uns zu verstehen, wie Besucher mit unserer Website interagieren.
</p>
<div class="bg-zinc-50 dark:bg-zinc-950 rounded-lg p-4">
<p class="text-sm text-zinc-600 dark:text-zinc-400 mb-2"><strong>Dienste:</strong></p>
<ul class="list-disc list-inside text-sm text-zinc-600 dark:text-zinc-400">
<li>Google Analytics (anonymisiert)</li>
<li>Interne Analysetools</li>
</ul>
</div>
</div>
<div class="mb-6">
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-3">4. Marketing-Cookies
</h3>
<p class="text-zinc-600 dark:text-zinc-400 mb-3">
Diese Cookies werden verwendet, um Ihnen relevante Werbung anzuzeigen.
</p>
<div class="bg-zinc-50 dark:bg-zinc-950 rounded-lg p-4">
<p class="text-sm text-zinc-600 dark:text-zinc-400 mb-2"><strong>Beispiele:</strong></p>
<ul class="list-disc list-inside text-sm text-zinc-600 dark:text-zinc-400">
<li>Remarketing-Cookies</li>
<li>Social Media Tracking</li>
</ul>
</div>
</div>
</div>
<div class="mb-8">
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">Cookie-Laufzeiten</h2>
<div class="overflow-x-auto">
<table class="min-w-full text-sm">
<thead class="bg-zinc-50 dark:bg-zinc-950">
<tr>
<th class="px-4 py-3 text-left text-zinc-900 dark:text-zinc-100">Cookie-Typ</th>
<th class="px-4 py-3 text-left text-zinc-900 dark:text-zinc-100">Laufzeit</th>
</tr>
</thead>
<tbody class="divide-y divide-zinc-200 dark:divide-zinc-800">
<tr>
<td class="px-4 py-3 text-zinc-600 dark:text-zinc-400">Session-Cookies</td>
<td class="px-4 py-3 text-zinc-600 dark:text-zinc-400">Bis zum Schließen des
Browsers</td>
</tr>
<tr>
<td class="px-4 py-3 text-zinc-600 dark:text-zinc-400">Funktionale Cookies</td>
<td class="px-4 py-3 text-zinc-600 dark:text-zinc-400">1 Jahr</td>
</tr>
<tr>
<td class="px-4 py-3 text-zinc-600 dark:text-zinc-400">Analytische Cookies</td>
<td class="px-4 py-3 text-zinc-600 dark:text-zinc-400">2 Jahre</td>
</tr>
<tr>
<td class="px-4 py-3 text-zinc-600 dark:text-zinc-400">Marketing-Cookies</td>
<td class="px-4 py-3 text-zinc-600 dark:text-zinc-400">1 Jahr</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="mb-8">
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">Wie können Sie Cookies
verwalten?</h2>
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
Sie können Ihre Cookie-Einstellungen jederzeit ändern. Die meisten Browser erlauben es
Ihnen:
</p>
<ul class="list-disc list-inside text-zinc-600 dark:text-zinc-400 mb-4">
<li>Cookies anzuzeigen und zu löschen</li>
<li>Cookies von Drittanbietern zu blockieren</li>
<li>Alle Cookies zu blockieren</li>
<li>Cookies beim Schließen des Browsers zu löschen</li>
</ul>
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
Bitte beachten Sie, dass das Deaktivieren von Cookies die Funktionalität unserer Website
beeinträchtigen kann.
</p>
</div>
<div class="mb-8">
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">Weitere Informationen</h2>
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
Weitere Informationen zum Datenschutz finden Sie in unserer <a href="/datenschutz"
class="text-[var(--color-primary)] hover:underline">Datenschutzerklärung</a>.
</p>
<p class="text-zinc-600 dark:text-zinc-400">
Bei Fragen zu unseren Cookie-Richtlinien kontaktieren Sie uns bitte unter:
<a href="mailto:datenschutz@businessportal.de"
class="text-[var(--color-primary)] hover:underline">datenschutz@businessportal.de</a>
</p>
</div>
<div>
<p class="text-sm text-zinc-500 dark:text-zinc-500">
Stand: Januar 2025
</p>
</div>
</div>
</div>
</div>
</section>
<livewire:web.footer />
</main>
<h2>Weitere Informationen</h2>
<p>
Weitere Informationen zum Datenschutz finden Sie in unserer
<a href="{{ route('datenschutz') }}">Datenschutzerklärung</a>.
</p>
<p>
Bei Fragen zu unseren Cookie-Richtlinien kontaktieren Sie uns bitte unter:
<a href="mailto:datenschutz@businessportal.de">datenschutz@businessportal.de</a>
</p>
</div>
</x-web.static-page>
@endsection @endsection
@push('styles')
<style>
:root {
--color-primary: {{ $domainConfig['color_scheme']['primary'] ?? '#cf3628' }};
--color-secondary: {{ $domainConfig['color_scheme']['secondary'] ?? '#f0834a' }};
}
[x-cloak] {
display: none !important;
}
</style>
@endpush

View file

@ -1,152 +1,98 @@
@extends('web.layouts.web-master') @extends('web.layouts.web-master')
@section('title', 'Datenschutzerklärung - Business Portal 24') @section('title', 'Datenschutzerklärung')
@section('meta_description', 'Informationen zur Verarbeitung personenbezogener Daten auf dieser Website.')
@section('content') @section('content')
<x-web.static-page
eyebrow="Rechtliches"
title="Datenschutzerklärung"
breadcrumb="Datenschutz"
updated="Stand: Januar 2025"
>
{{-- Platzhalter-Text — vor Go-Live durch die finale Datenschutzerklärung ersetzen. --}}
<div class="pm-body max-w-[760px]">
<h2>1. Datenschutz auf einen Blick</h2>
<h3>Allgemeine Hinweise</h3>
<p>
Die folgenden Hinweise geben einen einfachen Überblick darüber, was mit Ihren personenbezogenen
Daten passiert, wenn Sie diese Website besuchen. Personenbezogene Daten sind alle Daten, mit denen
Sie persönlich identifiziert werden können.
</p>
<main class="min-h-screen flex flex-col bg-white dark:bg-zinc-950 transition-colors duration-200"> <h3>Datenerfassung auf dieser Website</h3>
<livewire:web.burger-menu /> <p>
<livewire:web.header /> <strong>Wer ist verantwortlich für die Datenerfassung auf dieser Website?</strong><br>
Die Datenverarbeitung auf dieser Website erfolgt durch den Websitebetreiber. Dessen Kontaktdaten
können Sie dem Abschnitt „Hinweis zur Verantwortlichen Stelle" in dieser Datenschutzerklärung
entnehmen.
</p>
<!-- Hero Section --> <h2>2. Hosting</h2>
<section class="relative overflow-hidden text-white py-16 animate-fade-in" <p>Wir hosten die Inhalte unserer Website bei folgenden Anbietern:</p>
style="background: var(--gradient-hero);"> <h3>Externes Hosting</h3>
<div class="container mx-auto px-4 text-center"> <p>
<h1 class="text-4xl md:text-5xl font-bold mb-4 animate-fade-in-up"> Diese Website wird extern gehostet. Die personenbezogenen Daten, die auf dieser Website erfasst
Datenschutzerklärung werden, werden auf den Servern des Hosters / der Hoster gespeichert. Hierbei kann es sich v. a. um
</h1> IP-Adressen, Kontaktanfragen, Meta- und Kommunikationsdaten, Vertragsdaten, Kontaktdaten, Namen,
</div> Websitezugriffe und sonstige Daten, die über eine Website generiert werden, handeln.
</section> </p>
<!-- Content Section --> <h2>3. Allgemeine Hinweise und Pflichtinformationen</h2>
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200"> <h3>Datenschutz</h3>
<div class="container mx-auto px-4"> <p>
<div class="max-w-4xl mx-auto"> Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-8 md:p-12 transition-colors duration-200"> Ihre personenbezogenen Daten vertraulich und entsprechend den gesetzlichen Datenschutzvorschriften
sowie dieser Datenschutzerklärung.
</p>
<div class="mb-8"> <h2>4. Datenerfassung auf dieser Website</h2>
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">1. Datenschutz auf einen Blick</h2> <h3>Cookies</h3>
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-3">Allgemeine Hinweise</h3> <p>
<p class="text-zinc-600 dark:text-zinc-400 mb-4"> Unsere Internetseiten verwenden so genannte „Cookies". Cookies sind kleine Datenpakete und richten
Die folgenden Hinweise geben einen einfachen Überblick darüber, was mit Ihren personenbezogenen Daten passiert, auf Ihrem Endgerät keinen Schaden an. Sie werden entweder vorübergehend für die Dauer einer Sitzung
wenn Sie diese Website besuchen. Personenbezogene Daten sind alle Daten, mit denen Sie persönlich identifiziert werden können. (Session-Cookies) oder dauerhaft (permanente Cookies) auf Ihrem Endgerät gespeichert.
</p> </p>
</div> <h3>Server-Log-Dateien</h3>
<p>
Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten
Server-Log-Dateien, die Ihr Browser automatisch an uns übermittelt. Dies sind:
</p>
<ul>
<li>Browsertyp und Browserversion</li>
<li>verwendetes Betriebssystem</li>
<li>Referrer URL</li>
<li>Hostname des zugreifenden Rechners</li>
<li>Uhrzeit der Serveranfrage</li>
<li>IP-Adresse</li>
</ul>
<div class="mb-8"> <h2>5. Analyse-Tools und Werbung</h2>
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-3">Datenerfassung auf dieser Website</h3> <h3>Google Analytics</h3>
<p class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">Wer ist verantwortlich für die Datenerfassung auf dieser Website?</p> <p>
<p class="text-zinc-600 dark:text-zinc-400 mb-4"> Diese Website nutzt Funktionen des Webanalysedienstes Google Analytics. Anbieter ist die Google
Die Datenverarbeitung auf dieser Website erfolgt durch den Websitebetreiber. Dessen Kontaktdaten können Sie dem Abschnitt Ireland Limited („Google"), Gordon House, Barrow Street, Dublin 4, Irland.
„Hinweis zur Verantwortlichen Stelle" in dieser Datenschutzerklärung entnehmen. </p>
</p>
</div>
<div class="mb-8"> <h2>6. Newsletter</h2>
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">2. Hosting</h2> <h3>Newsletterdaten</h3>
<p class="text-zinc-600 dark:text-zinc-400 mb-4"> <p>
Wir hosten die Inhalte unserer Website bei folgenden Anbietern: Wenn Sie den auf der Website angebotenen Newsletter beziehen möchten, benötigen wir von Ihnen eine
</p> E-Mail-Adresse sowie Informationen, welche uns die Überprüfung gestatten, dass Sie der Inhaber der
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-3">Externes Hosting</h3> angegebenen E-Mail-Adresse sind und mit dem Empfang des Newsletters einverstanden sind.
<p class="text-zinc-600 dark:text-zinc-400"> </p>
Diese Website wird extern gehostet. Die personenbezogenen Daten, die auf dieser Website erfasst werden, werden auf den Servern
des Hosters / der Hoster gespeichert. Hierbei kann es sich v. a. um IP-Adressen, Kontaktanfragen, Meta- und Kommunikationsdaten,
Vertragsdaten, Kontaktdaten, Namen, Websitezugriffe und sonstige Daten, die über eine Website generiert werden, handeln.
</p>
</div>
<div class="mb-8">
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">3. Allgemeine Hinweise und Pflichtinformationen</h2>
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-3">Datenschutz</h3>
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten
vertraulich und entsprechend den gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung.
</p>
</div>
<div class="mb-8">
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">4. Datenerfassung auf dieser Website</h2>
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-3">Cookies</h3>
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
Unsere Internetseiten verwenden so genannte „Cookies". Cookies sind kleine Datenpakete und richten auf Ihrem Endgerät keinen Schaden an.
Sie werden entweder vorübergehend für die Dauer einer Sitzung (Session-Cookies) oder dauerhaft (permanente Cookies) auf Ihrem Endgerät
gespeichert.
</p>
</div>
<div class="mb-8">
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-3">Server-Log-Dateien</h3>
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
Der Provider der Seiten erhebt und speichert automatisch Informationen in so genannten Server-Log-Dateien, die Ihr Browser
automatisch an uns übermittelt. Dies sind:
</p>
<ul class="list-disc list-inside text-zinc-600 dark:text-zinc-400 mb-4">
<li>Browsertyp und Browserversion</li>
<li>verwendetes Betriebssystem</li>
<li>Referrer URL</li>
<li>Hostname des zugreifenden Rechners</li>
<li>Uhrzeit der Serveranfrage</li>
<li>IP-Adresse</li>
</ul>
</div>
<div class="mb-8">
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">5. Analyse-Tools und Werbung</h2>
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-3">Google Analytics</h3>
<p class="text-zinc-600 dark:text-zinc-400">
Diese Website nutzt Funktionen des Webanalysedienstes Google Analytics. Anbieter ist die Google Ireland Limited („Google"),
Gordon House, Barrow Street, Dublin 4, Irland.
</p>
</div>
<div class="mb-8">
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">6. Newsletter</h2>
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-3">Newsletterdaten</h3>
<p class="text-zinc-600 dark:text-zinc-400">
Wenn Sie den auf der Website angebotenen Newsletter beziehen möchten, benötigen wir von Ihnen eine E-Mail-Adresse sowie
Informationen, welche uns die Überprüfung gestatten, dass Sie der Inhaber der angegebenen E-Mail-Adresse sind und mit dem
Empfang des Newsletters einverstanden sind.
</p>
</div>
<div class="mb-8">
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">7. Ihre Rechte</h2>
<p class="text-zinc-600 dark:text-zinc-400 mb-4">
Sie haben folgende Rechte:
</p>
<ul class="list-disc list-inside text-zinc-600 dark:text-zinc-400">
<li>Recht auf Auskunft über Ihre gespeicherten personenbezogenen Daten</li>
<li>Recht auf Berichtigung unrichtiger Daten</li>
<li>Recht auf Löschung Ihrer Daten</li>
<li>Recht auf Einschränkung der Datenverarbeitung</li>
<li>Recht auf Datenübertragbarkeit</li>
<li>Widerspruchsrecht gegen die Datenverarbeitung</li>
<li>Beschwerderecht bei einer Aufsichtsbehörde</li>
</ul>
</div>
<div>
<p class="text-sm text-zinc-500 dark:text-zinc-500">
Stand: Januar 2025
</p>
</div>
</div>
</div>
</div>
</section>
<livewire:web.footer />
</main>
<h2>7. Ihre Rechte</h2>
<p>Sie haben folgende Rechte:</p>
<ul>
<li>Recht auf Auskunft über Ihre gespeicherten personenbezogenen Daten</li>
<li>Recht auf Berichtigung unrichtiger Daten</li>
<li>Recht auf Löschung Ihrer Daten</li>
<li>Recht auf Einschränkung der Datenverarbeitung</li>
<li>Recht auf Datenübertragbarkeit</li>
<li>Widerspruchsrecht gegen die Datenverarbeitung</li>
<li>Beschwerderecht bei einer Aufsichtsbehörde</li>
</ul>
</div>
</x-web.static-page>
@endsection @endsection
@push('styles')
<style>
:root {
--color-primary: {{ $domainConfig['color_scheme']['primary'] ?? '#cf3628' }};
--color-secondary: {{ $domainConfig['color_scheme']['secondary'] ?? '#f0834a' }};
}
[x-cloak] { display: none !important; }
</style>
@endpush

View file

@ -1,419 +1,93 @@
@extends('web.layouts.web-master') @extends('web.layouts.web-master')
@section('title', 'FAQ - Häufig gestellte Fragen - Business Portal 24') @section('title', 'Häufig gestellte Fragen (FAQ)')
@section('meta_description', 'Antworten auf die wichtigsten Fragen rund um das Veröffentlichen von Pressemitteilungen, Account, Abrechnung und Newsroom.')
@php
// FAQ-Inhalte als Datenstruktur (DRY). Vor Go-Live ggf. mit dem Support
// abstimmen; bei Bedarf später in lang/*/faq.php auslagern.
$faqCategories = [
[
'title' => 'Erste Schritte',
'items' => [
['q' => 'Wie veröffentliche ich meine erste Pressemitteilung?', 'a' => 'Nach der Registrierung klicken Sie auf „Veröffentlichen" in der Hauptnavigation. Folgen Sie dem 5-Schritte-Wizard: Metadaten eingeben, Content erstellen, Medien hochladen, Kontaktdaten hinterlegen und Vorschau prüfen. Bei Fragen steht unser Support-Team zur Verfügung.'],
['q' => 'Muss ich mich registrieren, um Pressemitteilungen zu lesen?', 'a' => 'Nein, alle veröffentlichten Pressemitteilungen sind frei zugänglich. Eine Registrierung ist nur erforderlich, wenn Sie selbst Inhalte veröffentlichen oder einen Newsroom erstellen möchten.'],
['q' => 'Wie lange dauert die Freischaltung meiner Pressemitteilung?', 'a' => 'In der Regel werden Pressemitteilungen innerhalb weniger Stunden redaktionell geprüft und freigeschaltet. Höhere Tarife profitieren von einer beschleunigten Prüfung.'],
],
],
[
'title' => 'Account & Abrechnung',
'items' => [
['q' => 'Wie ändere ich meinen Tarif?', 'a' => 'In Ihrem Bereich unter „Buchungen & Add-ons" können Sie jederzeit upgraden oder downgraden. Upgrades gelten sofort, Downgrades zum nächsten Abrechnungszeitraum.'],
['q' => 'Welche Zahlungsmethoden werden akzeptiert?', 'a' => 'Wir akzeptieren Kreditkarten (Visa, Mastercard, American Express) sowie SEPA-Lastschrift. Die Abrechnung erfolgt sicher über unseren Zahlungsdienstleister; Bestandskunden können weiter per Rechnung zahlen.'],
['q' => 'Kann ich mein Konto löschen?', 'a' => 'Ja, Sie können Ihr Konto jederzeit in den Einstellungen löschen. Beachten Sie, dass bereits veröffentlichte Pressemitteilungen aus SEO-Gründen online bleiben, aber nicht mehr Ihrem Account zugeordnet sind.'],
],
],
[
'title' => 'Pressemitteilungen & Content',
'items' => [
['q' => 'Welche Dateiformate werden für Medien unterstützt?', 'a' => 'Bilder: JPG, PNG, WebP (max. 10 MB). Dokumente: PDF (max. 25 MB). Videos können über YouTube-/Vimeo-Einbettung hinzugefügt werden.'],
['q' => 'Kann ich eine Pressemitteilung nach Veröffentlichung bearbeiten?', 'a' => 'Inhaltliche Korrekturen und Updates sind über den jeweiligen Magic-Link möglich. Umfang und Konditionen richten sich nach dem gewählten Tarif.'],
['q' => 'Wie optimiere ich meine Pressemitteilung für SEO?', 'a' => 'Nutzen Sie aussagekräftige Headlines, integrieren Sie relevante Keywords natürlich, hinterlegen Sie Alt-Texte für Bilder und strukturieren Sie den Text mit Zwischenüberschriften.'],
],
],
[
'title' => 'Newsroom & Features',
'items' => [
['q' => 'Was ist ein Newsroom und wie erstelle ich einen?', 'a' => 'Ein Newsroom ist Ihre dedizierte Unternehmensseite, auf der alle Ihre Pressemitteilungen gebündelt werden. Je nach Tarif lässt er sich mit Logo, Farben und zusätzlichen Informationen individualisieren.'],
['q' => 'Wie funktionieren die Analytics?', 'a' => 'Sie erhalten Statistiken zu Aufrufen, Klicks und Reichweite Ihrer Meldungen. Die Daten werden laufend aktualisiert und lassen sich exportieren.'],
],
],
];
@endphp
@section('content') @section('content')
<x-web.static-page
<main class="min-h-screen flex flex-col bg-white dark:bg-zinc-950 transition-colors duration-200"> eyebrow="Hilfe"
<!-- Burger Menu Component --> title="Häufig gestellte Fragen"
<livewire:web.burger-menu /> lead="Finden Sie schnell Antworten auf die wichtigsten Fragen rund um Veröffentlichung, Account und Newsroom."
breadcrumb="FAQ"
<!-- Header Component --> >
<livewire:web.header /> <div class="max-w-[820px] space-y-10">
@foreach ($faqCategories as $category)
<!-- Hero Section --> <div>
<section class="relative overflow-hidden text-white py-16 animate-fade-in" <h2 class="font-serif text-[22px] font-semibold tracking-[-0.3px] text-ink m-0 mb-4">{{ $category['title'] }}</h2>
style="background: var(--gradient-hero);"> <div class="border border-bg-rule divide-y divide-bg-rule">
<div class="container mx-auto px-4 text-center"> @foreach ($category['items'] as $item)
<div class="flex justify-center mb-6"> <details class="group">
<svg class="h-16 w-16 animate-fade-in-up" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <summary class="flex items-center justify-between gap-4 cursor-pointer select-none list-none px-5 py-4 text-[14px] font-semibold text-ink hover:bg-bg-elev transition-colors [&::-webkit-details-marker]:hidden">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path> <span class="pr-4">{{ $item['q'] }}</span>
</svg> <svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true"
class="flex-shrink-0 text-ink-3 transition-transform duration-200 group-open:rotate-180">
<path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</summary>
<div class="px-5 pb-5 -mt-1 text-[13.5px] leading-[1.65] text-ink-2">
{{ $item['a'] }}
</div>
</details>
@endforeach
</div>
</div> </div>
<h1 class="text-4xl md:text-5xl font-bold mb-4 animate-fade-in-up animation-delay-200"> @endforeach
Häufig gestellte Fragen </div>
</h1>
<p class="text-xl text-white/90 max-w-2xl mx-auto animate-fade-in-up animation-delay-300"> {{-- Abschluss-CTA: Frage nicht gefunden? --}}
Finden Sie schnell Antworten auf die wichtigsten Fragen rund um Business Portal <div class="max-w-[820px] mt-12 border-t border-bg-rule pt-8">
</p> <h2 class="font-serif text-[22px] font-semibold tracking-[-0.3px] text-ink m-0">Frage nicht gefunden?</h2>
<p class="text-[13.5px] leading-[1.6] text-ink-2 mt-2 mb-5 max-w-[560px]">
Unser Support-Team hilft Ihnen gerne weiter – per E-Mail oder über das Kontaktformular.
</p>
<div class="flex flex-wrap gap-3">
<a href="{{ route('kontakt') }}"
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">
Kontakt aufnehmen
</a>
<a href="{{ route('hilfe') }}"
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-elev rounded-[2px] transition-colors">
Hilfe-Center besuchen
</a>
</div> </div>
<!-- Decorative Pattern --> </div>
<div class="absolute top-0 right-0 opacity-10"> </x-web.static-page>
<svg width="404" height="384" fill="none" viewBox="0 0 404 384">
<defs>
<pattern id="pattern-hero-faq" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<rect x="0" y="0" width="4" height="4" fill="currentColor"/>
</pattern>
</defs>
<rect width="404" height="384" fill="url(#pattern-hero-faq)"/>
</svg>
</div>
</section>
<!-- Search Section -->
<section class="py-8 bg-white dark:bg-zinc-950 border-b border-zinc-200 dark:border-zinc-800 transition-colors duration-200">
<div class="container mx-auto px-4 max-w-2xl">
<div class="relative">
<input
type="search"
placeholder="Suchen Sie nach Themen, z.B. 'Preise' oder 'Newsroom'..."
class="w-full px-4 py-3 pl-12 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 border border-zinc-300 dark:border-zinc-700 rounded-lg focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-colors duration-200"
/>
<svg class="absolute left-4 top-1/2 -translate-y-1/2 h-5 w-5 text-zinc-400 dark:text-zinc-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
</div>
</section>
<!-- FAQ Categories -->
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200">
<div class="container mx-auto px-4 max-w-4xl">
<!-- Category: Erste Schritte -->
<div class="mb-12">
<div class="flex items-center gap-3 mb-6">
<div class="w-10 h-10 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-lg flex items-center justify-center">
<svg class="h-5 w-5 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path>
</svg>
</div>
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100">
Erste Schritte
</h2>
</div>
<div class="space-y-4" x-data="{ open: null }">
<!-- Question 1 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 overflow-hidden transition-colors duration-200">
<button @click="open = open === 1 ? null : 1"
class="w-full p-6 flex items-center justify-between hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors">
<span class="font-semibold text-zinc-900 dark:text-zinc-100 text-left pr-4">
Wie veröffentliche ich meine erste Pressemitteilung?
</span>
<svg class="h-5 w-5 text-zinc-500 dark:text-zinc-400 flex-shrink-0 transition-transform duration-200"
:class="{ 'rotate-180': open === 1 }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show="open === 1" x-collapse x-cloak>
<div class="px-6 pb-6 text-zinc-600 dark:text-zinc-400 leading-relaxed">
Nach der Registrierung klicken Sie auf 'Veröffentlichen' in der Hauptnavigation. Folgen Sie dem intuitiven 5-Schritte-Wizard: Metadaten eingeben, Content erstellen, Medien hochladen, Kontaktdaten hinterlegen und Vorschau prüfen. Bei Fragen steht unser Support-Team jederzeit zur Verfügung.
</div>
</div>
</div>
<!-- Question 2 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 overflow-hidden transition-colors duration-200">
<button @click="open = open === 2 ? null : 2"
class="w-full p-6 flex items-center justify-between hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors">
<span class="font-semibold text-zinc-900 dark:text-zinc-100 text-left pr-4">
Muss ich mich registrieren, um Pressemitteilungen zu lesen?
</span>
<svg class="h-5 w-5 text-zinc-500 dark:text-zinc-400 flex-shrink-0 transition-transform duration-200"
:class="{ 'rotate-180': open === 2 }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show="open === 2" x-collapse x-cloak>
<div class="px-6 pb-6 text-zinc-600 dark:text-zinc-400 leading-relaxed">
Nein, alle veröffentlichten Pressemitteilungen sind frei zugänglich. Eine Registrierung ist nur erforderlich, wenn Sie selbst Inhalte veröffentlichen oder einen Newsroom erstellen möchten.
</div>
</div>
</div>
<!-- Question 3 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 overflow-hidden transition-colors duration-200">
<button @click="open = open === 3 ? null : 3"
class="w-full p-6 flex items-center justify-between hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors">
<span class="font-semibold text-zinc-900 dark:text-zinc-100 text-left pr-4">
Wie lange dauert die Freischaltung meiner Pressemitteilung?
</span>
<svg class="h-5 w-5 text-zinc-500 dark:text-zinc-400 flex-shrink-0 transition-transform duration-200"
:class="{ 'rotate-180': open === 3 }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show="open === 3" x-collapse x-cloak>
<div class="px-6 pb-6 text-zinc-600 dark:text-zinc-400 leading-relaxed">
In der Regel werden Pressemitteilungen innerhalb von 2-4 Stunden geprüft und freigeschaltet. Professional- und Enterprise-Kunden profitieren von einer beschleunigten Prüfung innerhalb von maximal 1 Stunde.
</div>
</div>
</div>
</div>
</div>
<!-- Category: Account & Abrechnung -->
<div class="mb-12">
<div class="flex items-center gap-3 mb-6">
<div class="w-10 h-10 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-lg flex items-center justify-center">
<svg class="h-5 w-5 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z"></path>
</svg>
</div>
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100">
Account & Abrechnung
</h2>
</div>
<div class="space-y-4" x-data="{ open: null }">
<!-- Question 1 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 overflow-hidden transition-colors duration-200">
<button @click="open = open === 4 ? null : 4"
class="w-full p-6 flex items-center justify-between hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors">
<span class="font-semibold text-zinc-900 dark:text-zinc-100 text-left pr-4">
Wie ändere ich meinen Tarif?
</span>
<svg class="h-5 w-5 text-zinc-500 dark:text-zinc-400 flex-shrink-0 transition-transform duration-200"
:class="{ 'rotate-180': open === 4 }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show="open === 4" x-collapse x-cloak>
<div class="px-6 pb-6 text-zinc-600 dark:text-zinc-400 leading-relaxed">
In Ihren Kontoeinstellungen unter 'Abonnement & Billing' können Sie jederzeit Ihren Tarif upgraden oder downgraden. Upgrades gelten sofort, Downgrades zum nächsten Abrechnungszeitraum.
</div>
</div>
</div>
<!-- Question 2 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 overflow-hidden transition-colors duration-200">
<button @click="open = open === 5 ? null : 5"
class="w-full p-6 flex items-center justify-between hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors">
<span class="font-semibold text-zinc-900 dark:text-zinc-100 text-left pr-4">
Welche Zahlungsmethoden werden akzeptiert?
</span>
<svg class="h-5 w-5 text-zinc-500 dark:text-zinc-400 flex-shrink-0 transition-transform duration-200"
:class="{ 'rotate-180': open === 5 }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show="open === 5" x-collapse x-cloak>
<div class="px-6 pb-6 text-zinc-600 dark:text-zinc-400 leading-relaxed">
Wir akzeptieren Kreditkarten (Visa, Mastercard, American Express), SEPA-Lastschrift und PayPal. Enterprise-Kunden können auch per Rechnung zahlen.
</div>
</div>
</div>
<!-- Question 3 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 overflow-hidden transition-colors duration-200">
<button @click="open = open === 6 ? null : 6"
class="w-full p-6 flex items-center justify-between hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors">
<span class="font-semibold text-zinc-900 dark:text-zinc-100 text-left pr-4">
Kann ich mein Konto löschen?
</span>
<svg class="h-5 w-5 text-zinc-500 dark:text-zinc-400 flex-shrink-0 transition-transform duration-200"
:class="{ 'rotate-180': open === 6 }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show="open === 6" x-collapse x-cloak>
<div class="px-6 pb-6 text-zinc-600 dark:text-zinc-400 leading-relaxed">
Ja, Sie können Ihr Konto jederzeit in den Einstellungen unter 'Account verwalten' löschen. Beachten Sie, dass bereits veröffentlichte Pressemitteilungen aus SEO-Gründen online bleiben, aber nicht mehr Ihrem Account zugeordnet sind.
</div>
</div>
</div>
</div>
</div>
<!-- Category: Pressemitteilungen & Content -->
<div class="mb-12">
<div class="flex items-center gap-3 mb-6">
<div class="w-10 h-10 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-lg flex items-center justify-center">
<svg class="h-5 w-5 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100">
Pressemitteilungen & Content
</h2>
</div>
<div class="space-y-4" x-data="{ open: null }">
<!-- Question 1 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 overflow-hidden transition-colors duration-200">
<button @click="open = open === 7 ? null : 7"
class="w-full p-6 flex items-center justify-between hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors">
<span class="font-semibold text-zinc-900 dark:text-zinc-100 text-left pr-4">
Welche Dateiformate werden für Medien unterstützt?
</span>
<svg class="h-5 w-5 text-zinc-500 dark:text-zinc-400 flex-shrink-0 transition-transform duration-200"
:class="{ 'rotate-180': open === 7 }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show="open === 7" x-collapse x-cloak>
<div class="px-6 pb-6 text-zinc-600 dark:text-zinc-400 leading-relaxed">
Bilder: JPG, PNG, WebP (max. 10 MB). Dokumente: PDF (max. 25 MB). Videos können über YouTube/Vimeo-Einbettung hinzugefügt werden.
</div>
</div>
</div>
<!-- Question 2 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 overflow-hidden transition-colors duration-200">
<button @click="open = open === 8 ? null : 8"
class="w-full p-6 flex items-center justify-between hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors">
<span class="font-semibold text-zinc-900 dark:text-zinc-100 text-left pr-4">
Kann ich eine Pressemitteilung nach Veröffentlichung bearbeiten?
</span>
<svg class="h-5 w-5 text-zinc-500 dark:text-zinc-400 flex-shrink-0 transition-transform duration-200"
:class="{ 'rotate-180': open === 8 }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show="open === 8" x-collapse x-cloak>
<div class="px-6 pb-6 text-zinc-600 dark:text-zinc-400 leading-relaxed">
Ja, Professional- und Enterprise-Kunden können Pressemitteilungen bis zu 7 Tage nach Veröffentlichung bearbeiten. Bei Free-Accounts ist eine nachträgliche Bearbeitung nicht möglich.
</div>
</div>
</div>
<!-- Question 3 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 overflow-hidden transition-colors duration-200">
<button @click="open = open === 9 ? null : 9"
class="w-full p-6 flex items-center justify-between hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors">
<span class="font-semibold text-zinc-900 dark:text-zinc-100 text-left pr-4">
Wie optimiere ich meine Pressemitteilung für SEO?
</span>
<svg class="h-5 w-5 text-zinc-500 dark:text-zinc-400 flex-shrink-0 transition-transform duration-200"
:class="{ 'rotate-180': open === 9 }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show="open === 9" x-collapse x-cloak>
<div class="px-6 pb-6 text-zinc-600 dark:text-zinc-400 leading-relaxed">
Nutzen Sie aussagekräftige Headlines (max. 70 Zeichen), integrieren Sie relevante Keywords natürlich, fügen Sie Alt-Texte für Bilder hinzu und strukturieren Sie den Text mit Zwischenüberschriften. Unser Editor zeigt Ihnen einen SEO-Score in Echtzeit.
</div>
</div>
</div>
</div>
</div>
<!-- Category: Newsroom & Features -->
<div class="mb-12">
<div class="flex items-center gap-3 mb-6">
<div class="w-10 h-10 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-lg flex items-center justify-center">
<svg class="h-5 w-5 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path>
</svg>
</div>
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100">
Newsroom & Features
</h2>
</div>
<div class="space-y-4" x-data="{ open: null }">
<!-- Question 1 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 overflow-hidden transition-colors duration-200">
<button @click="open = open === 10 ? null : 10"
class="w-full p-6 flex items-center justify-between hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors">
<span class="font-semibold text-zinc-900 dark:text-zinc-100 text-left pr-4">
Was ist ein Newsroom und wie erstelle ich einen?
</span>
<svg class="h-5 w-5 text-zinc-500 dark:text-zinc-400 flex-shrink-0 transition-transform duration-200"
:class="{ 'rotate-180': open === 10 }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show="open === 10" x-collapse x-cloak>
<div class="px-6 pb-6 text-zinc-600 dark:text-zinc-400 leading-relaxed">
Ein Newsroom ist Ihre dedizierte Unternehmensseite auf Business Portal, wo alle Ihre Pressemitteilungen gebündelt werden. Professional- und Enterprise-Kunden können ihren Newsroom mit Logo, Farben und zusätzlichen Informationen individualisieren.
</div>
</div>
</div>
<!-- Question 2 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 overflow-hidden transition-colors duration-200">
<button @click="open = open === 11 ? null : 11"
class="w-full p-6 flex items-center justify-between hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors">
<span class="font-semibold text-zinc-900 dark:text-zinc-100 text-left pr-4">
Wie funktionieren die Analytics?
</span>
<svg class="h-5 w-5 text-zinc-500 dark:text-zinc-400 flex-shrink-0 transition-transform duration-200"
:class="{ 'rotate-180': open === 11 }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
<div x-show="open === 11" x-collapse x-cloak>
<div class="px-6 pb-6 text-zinc-600 dark:text-zinc-400 leading-relaxed">
Professional-Kunden erhalten detaillierte Statistiken zu Views, Klicks, geografischer Verteilung und Referrern. Die Daten werden in Echtzeit aktualisiert und können als Report exportiert werden.
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Contact CTA -->
<section class="py-16 bg-zinc-50/50 dark:bg-zinc-900/50 transition-colors duration-200">
<div class="container mx-auto px-4 text-center">
<div class="max-w-2xl mx-auto">
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">
Frage nicht gefunden?
</h2>
<p class="text-zinc-600 dark:text-zinc-400 mb-8">
Unser Support-Team hilft Ihnen gerne weiter. Kontaktieren Sie uns per E-Mail oder Chat.
</p>
<div class="flex flex-wrap gap-4 justify-center">
<a href="/kontakt" class="inline-flex items-center justify-center px-6 py-3 text-sm font-medium text-white rounded-lg shadow-md hover:shadow-lg transition-all" style="background: var(--gradient-hero);">
Kontakt aufnehmen
</a>
<a href="#" class="inline-flex items-center justify-center px-6 py-3 text-sm font-medium text-zinc-700 dark:text-zinc-300 border border-zinc-300 dark:border-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-800 rounded-lg transition-all">
Hilfe-Center besuchen
</a>
</div>
</div>
</div>
</section>
<!-- Popular Topics -->
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200">
<div class="container mx-auto px-4 max-w-4xl">
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-8 text-center">
Beliebte Themen
</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-4 hover:shadow-lg transition-all cursor-pointer">
<a href="#" class="text-zinc-900 dark:text-zinc-100 hover:text-[var(--color-primary)] transition-colors">
Erste Schritte →
</a>
</div>
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-4 hover:shadow-lg transition-all cursor-pointer">
<a href="#" class="text-zinc-900 dark:text-zinc-100 hover:text-[var(--color-primary)] transition-colors">
Preise & Abrechnung →
</a>
</div>
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-4 hover:shadow-lg transition-all cursor-pointer">
<a href="#" class="text-zinc-900 dark:text-zinc-100 hover:text-[var(--color-primary)] transition-colors">
API-Dokumentation →
</a>
</div>
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-4 hover:shadow-lg transition-all cursor-pointer">
<a href="#" class="text-zinc-900 dark:text-zinc-100 hover:text-[var(--color-primary)] transition-colors">
SEO Best Practices →
</a>
</div>
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-4 hover:shadow-lg transition-all cursor-pointer">
<a href="#" class="text-zinc-900 dark:text-zinc-100 hover:text-[var(--color-primary)] transition-colors">
Medienformate →
</a>
</div>
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-4 hover:shadow-lg transition-all cursor-pointer">
<a href="#" class="text-zinc-900 dark:text-zinc-100 hover:text-[var(--color-primary)] transition-colors">
Datenschutz →
</a>
</div>
</div>
</div>
</section>
<!-- Footer Component -->
<livewire:web.footer />
</main>
@endsection @endsection
@push('styles')
<style>
/* Domain-spezifische Color-Variablen für Inline-Styles */
:root {
--color-primary: {{ $domainConfig['color_scheme']['primary'] ?? '#cf3628' }};
--color-secondary: {{ $domainConfig['color_scheme']['secondary'] ?? '#f0834a' }};
}
/* Alpine.js Cloak */
[x-cloak] {
display: none !important;
}
</style>
@endpush

View file

@ -1,256 +1,115 @@
@extends('web.layouts.web-master') @extends('web.layouts.web-master')
@section('title', 'Hilfe-Center - Business Portal 24') @section('title', 'Hilfe-Center')
@section('meta_description', 'Hilfe-Center: Antworten, Anleitungen und direkter Kontakt zum Support-Team.')
@php
// Hilfe-Themen mit Links auf vorhandene Ziele. „#" markiert Inhalte, die
// noch entstehen (Anleitungen/Tutorials) — vor Go-Live verlinken.
$helpTopics = [
[
'title' => 'Erste Schritte',
'links' => [
['label' => 'Account erstellen', 'href' => '#'],
['label' => 'Erste Pressemitteilung veröffentlichen', 'href' => route('veroeffentlichen')],
['label' => 'Newsroom einrichten', 'href' => route('newsrooms')],
['label' => 'Profil vervollständigen', 'href' => '#'],
],
],
[
'title' => 'Pressemitteilungen',
'links' => [
['label' => 'PM erstellen und formatieren', 'href' => '#'],
['label' => 'Medien hochladen', 'href' => '#'],
['label' => 'SEO-Optimierung', 'href' => '#'],
['label' => 'PM bearbeiten / löschen', 'href' => '#'],
],
],
[
'title' => 'Account & Abrechnung',
'links' => [
['label' => 'Tarif wechseln', 'href' => route('preise')],
['label' => 'Zahlungsmethoden', 'href' => route('preise')],
['label' => 'Rechnungen herunterladen', 'href' => '#'],
['label' => 'Account kündigen', 'href' => '#'],
],
],
[
'title' => 'Erweiterte Features',
'links' => [
['label' => 'API-Integration', 'href' => route('api')],
['label' => 'Analytics nutzen', 'href' => '#'],
['label' => 'Newsroom anpassen', 'href' => route('newsrooms')],
['label' => 'Team-Management', 'href' => '#'],
],
],
];
$quickLinks = [
['label' => 'FAQ', 'desc' => 'Häufig gestellte Fragen', 'href' => route('faq')],
['label' => 'Veröffentlichen', 'desc' => 'In wenigen Schritten zur Meldung', 'href' => route('veroeffentlichen')],
['label' => 'Kontakt', 'desc' => 'Direkter Draht zum Support', 'href' => route('kontakt')],
];
@endphp
@section('content') @section('content')
<x-web.static-page
<main class="min-h-screen flex flex-col bg-white dark:bg-zinc-950 transition-colors duration-200"> eyebrow="Hilfe"
<livewire:web.burger-menu /> title="Hilfe-Center"
<livewire:web.header /> lead="Finden Sie Antworten und Anleitungen – oder kontaktieren Sie unser Support-Team direkt."
breadcrumb="Hilfe"
<!-- Hero Section --> >
<section class="relative overflow-hidden text-white py-16 animate-fade-in" {{-- Schnellzugriff --}}
style="background: var(--gradient-hero);"> <div class="grid gap-px bg-bg-rule border border-bg-rule grid-cols-1 sm:grid-cols-3">
<div class="container mx-auto px-4 text-center"> @foreach ($quickLinks as $link)
<div class="flex justify-center mb-6"> <a href="{{ $link['href'] }}" class="group bg-bg p-6 hover:bg-bg-elev transition-colors">
<svg class="h-16 w-16 animate-fade-in-up" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <div class="flex items-center justify-between gap-2">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path> <span class="text-[15px] font-semibold text-ink group-hover:text-brand transition-colors">{{ $link['label'] }}</span>
</svg> <svg width="13" height="13" viewBox="0 0 12 12" fill="none" aria-hidden="true" class="text-ink-3 group-hover:text-brand transition-colors">
</div> <path d="M2 6h8M6 2l4 4-4 4" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" />
<h1 class="text-4xl md:text-5xl font-bold mb-4 animate-fade-in-up animation-delay-200"> </svg>
Hilfe-Center
</h1>
<p class="text-xl text-white/90 max-w-2xl mx-auto animate-fade-in-up animation-delay-300">
Wir helfen Ihnen gerne weiter – Finden Sie Antworten oder kontaktieren Sie unser Support-Team
</p>
</div>
</section>
<!-- Quick Links Section -->
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200">
<div class="container mx-auto px-4">
<div class="max-w-4xl mx-auto">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">
Schnellzugriff
</h2>
</div> </div>
<p class="text-[12.5px] text-ink-3 mt-1 mb-0">{{ $link['desc'] }}</p>
</a>
@endforeach
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6"> {{-- Hilfe-Themen --}}
<a href="/faq" class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all group"> <h2 class="font-serif text-[22px] font-semibold tracking-[-0.3px] text-ink m-0 mt-12 mb-4">Hilfe-Themen</h2>
<div class="w-12 h-12 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-lg flex items-center justify-center mb-4"> <div class="grid gap-px bg-bg-rule border border-bg-rule grid-cols-1 md:grid-cols-2">
<svg class="h-6 w-6 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24"> @foreach ($helpTopics as $topic)
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path> <div class="bg-bg p-6">
</svg> <h3 class="text-[14px] font-semibold text-ink m-0 mb-3">{{ $topic['title'] }}</h3>
</div> <ul class="list-none p-0 m-0 space-y-2">
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2 group-hover:text-[var(--color-primary)] transition-colors"> @foreach ($topic['links'] as $link)
FAQ <li>
</h3> <a href="{{ $link['href'] }}" class="inline-flex items-center gap-1.5 text-[13px] text-ink-2 hover:text-brand transition-colors">
<p class="text-sm text-zinc-600 dark:text-zinc-400"> <span class="text-ink-4" aria-hidden="true">›</span>
Häufig gestellte Fragen {{ $link['label'] }}
</p>
</a>
<a href="#" class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all group">
<div class="w-12 h-12 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-lg flex items-center justify-center mb-4">
<svg class="h-6 w-6 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2 group-hover:text-[var(--color-primary)] transition-colors">
Video-Tutorials
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Schritt-für-Schritt Anleitungen
</p>
</a>
<a href="/kontakt" class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all group">
<div class="w-12 h-12 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-lg flex items-center justify-center mb-4">
<svg class="h-6 w-6 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2 group-hover:text-[var(--color-primary)] transition-colors">
Kontakt
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Direkter Support
</p>
</a>
</div>
</div>
</div>
</section>
<!-- Help Topics Section -->
<section class="py-16 bg-zinc-50/50 dark:bg-zinc-900/50 transition-colors duration-200">
<div class="container mx-auto px-4">
<div class="max-w-4xl mx-auto">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">
Hilfe-Themen
</h2>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Topic 1 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all">
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-4">
Erste Schritte
</h3>
<ul class="space-y-2">
<li>
<a href="#" class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-[var(--color-primary)] transition-colors">
→ Account erstellen
</a>
</li>
<li>
<a href="#" class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-[var(--color-primary)] transition-colors">
→ Erste Pressemitteilung veröffentlichen
</a>
</li>
<li>
<a href="#" class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-[var(--color-primary)] transition-colors">
→ Newsroom einrichten
</a>
</li>
<li>
<a href="#" class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-[var(--color-primary)] transition-colors">
→ Profil vervollständigen
</a>
</li>
</ul>
</div>
<!-- Topic 2 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all">
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-4">
Pressemitteilungen
</h3>
<ul class="space-y-2">
<li>
<a href="#" class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-[var(--color-primary)] transition-colors">
→ PM erstellen und formatieren
</a>
</li>
<li>
<a href="#" class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-[var(--color-primary)] transition-colors">
→ Medien hochladen
</a>
</li>
<li>
<a href="#" class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-[var(--color-primary)] transition-colors">
→ SEO-Optimierung
</a>
</li>
<li>
<a href="#" class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-[var(--color-primary)] transition-colors">
→ PM bearbeiten/löschen
</a>
</li>
</ul>
</div>
<!-- Topic 3 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all">
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-4">
Account & Abrechnung
</h3>
<ul class="space-y-2">
<li>
<a href="#" class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-[var(--color-primary)] transition-colors">
→ Tarif wechseln
</a>
</li>
<li>
<a href="#" class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-[var(--color-primary)] transition-colors">
→ Zahlungsmethoden
</a>
</li>
<li>
<a href="#" class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-[var(--color-primary)] transition-colors">
→ Rechnungen herunterladen
</a>
</li>
<li>
<a href="#" class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-[var(--color-primary)] transition-colors">
→ Account kündigen
</a>
</li>
</ul>
</div>
<!-- Topic 4 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all">
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-4">
Erweiterte Features
</h3>
<ul class="space-y-2">
<li>
<a href="/api" class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-[var(--color-primary)] transition-colors">
→ API-Integration
</a>
</li>
<li>
<a href="#" class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-[var(--color-primary)] transition-colors">
→ Analytics nutzen
</a>
</li>
<li>
<a href="/newsrooms" class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-[var(--color-primary)] transition-colors">
→ Newsroom anpassen
</a>
</li>
<li>
<a href="#" class="text-sm text-zinc-600 dark:text-zinc-400 hover:text-[var(--color-primary)] transition-colors">
→ Team-Management
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</section>
<!-- Contact Support Section -->
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200">
<div class="container mx-auto px-4">
<div class="max-w-4xl mx-auto">
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-8 md:p-12 transition-colors duration-200">
<div class="text-center">
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">
Benötigen Sie weitere Hilfe?
</h2>
<p class="text-zinc-600 dark:text-zinc-400 mb-8">
Unser Support-Team steht Ihnen Mo-Fr von 9-18 Uhr zur Verfügung
</p>
<div class="flex flex-wrap gap-4 justify-center">
<a href="/kontakt" class="inline-flex items-center justify-center px-6 py-3 text-sm font-medium text-white rounded-lg shadow-md hover:shadow-lg transition-all" style="background: var(--gradient-hero);">
Support kontaktieren
</a> </a>
<a href="/faq" class="inline-flex items-center justify-center px-6 py-3 text-sm font-medium text-zinc-700 dark:text-zinc-300 border border-zinc-300 dark:border-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-800 rounded-lg transition-all"> </li>
FAQ durchsuchen @endforeach
</a> </ul>
</div>
</div>
</div>
</div> </div>
@endforeach
</div>
{{-- Support-CTA --}}
<div class="mt-12 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">Benötigen Sie weitere Hilfe?</h2>
<p class="text-[13px] text-ink-2 mt-1.5 mb-0">Unser Support-Team ist Mo–Fr von 9–18 Uhr für Sie da.</p>
</div> </div>
</section> <div class="flex flex-wrap gap-3 flex-shrink-0">
<a href="{{ route('kontakt') }}"
<livewire:web.footer /> 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">
</main> Support kontaktieren
</a>
<a href="{{ route('faq') }}"
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]">
FAQ durchsuchen
</a>
</div>
</div>
</x-web.static-page>
@endsection @endsection
@push('styles')
<style>
:root {
--color-primary: {{ $domainConfig['color_scheme']['primary'] ?? '#cf3628' }};
--color-secondary: {{ $domainConfig['color_scheme']['secondary'] ?? '#f0834a' }};
}
[x-cloak] { display: none !important; }
</style>
@endpush

View file

@ -1,138 +1,85 @@
@extends('web.layouts.web-master') @extends('web.layouts.web-master')
@section('title', 'Impressum - Business Portal 24') @section('title', 'Impressum')
@section('meta_description', 'Impressum und Anbieterkennzeichnung gemäß § 5 TMG.')
@section('content') @section('content')
<x-web.static-page
eyebrow="Rechtliches"
title="Impressum"
breadcrumb="Impressum"
>
{{-- Platzhalter-Angaben — vor Go-Live durch die echten Anbieterdaten ersetzen. --}}
<div class="pm-body max-w-[760px]">
<h2>Angaben gemäß § 5 TMG</h2>
<p>
Business Portal GmbH<br>
Musterstraße 123<br>
10115 Berlin<br>
Deutschland
</p>
<main class="min-h-screen flex flex-col bg-white dark:bg-zinc-950 transition-colors duration-200"> <h3>Kontakt</h3>
<livewire:web.burger-menu /> <p>
<livewire:web.header /> Telefon: +49 (0) 30 1234567-0<br>
E-Mail: info@businessportal.de
</p>
<!-- Hero Section --> <h3>Vertreten durch</h3>
<section class="relative overflow-hidden text-white py-16 animate-fade-in" style="background: var(--gradient-hero);"> <p>Geschäftsführer: Dr. Michael Weber</p>
<div class="container mx-auto px-4 text-center">
<h1 class="text-4xl md:text-5xl font-bold mb-4 animate-fade-in-up">
Impressum
</h1>
</div>
</section>
<!-- Content Section --> <h3>Registereintrag</h3>
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200"> <p>
<div class="container mx-auto px-4"> Eintragung im Handelsregister<br>
<div class="max-w-4xl mx-auto prose prose-zinc dark:prose-invert"> Registergericht: Amtsgericht Berlin-Charlottenburg<br>
<div Registernummer: HRB 123456 B
class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-8 md:p-12 transition-colors duration-200"> </p>
<h2 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-6">Angaben gemäß § 5 TMG</h2> <h3>Umsatzsteuer-ID</h3>
<p>
Umsatzsteuer-Identifikationsnummer gemäß § 27a UStG:<br>
DE123456789
</p>
<div class="mb-8"> <h3>Verantwortlich für den Inhalt nach § 55 Abs. 2 RStV</h3>
<p class="font-semibold text-zinc-900 dark:text-zinc-100">Business Portal GmbH</p> <p>
<p class="text-zinc-600 dark:text-zinc-400">Musterstraße 123</p> Lisa Müller<br>
<p class="text-zinc-600 dark:text-zinc-400">10115 Berlin</p> Musterstraße 123<br>
<p class="text-zinc-600 dark:text-zinc-400">Deutschland</p> 10115 Berlin
</div> </p>
<div class="mb-8"> <h3>Streitschlichtung</h3>
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-4">Kontakt</h3> <p>
<p class="text-zinc-600 dark:text-zinc-400">Telefon: +49 (0) 30 1234567-0</p> Die Europäische Kommission stellt eine Plattform zur Online-Streitbeilegung (OS) bereit:
<p class="text-zinc-600 dark:text-zinc-400">E-Mail: info@businessportal.de</p> <a href="https://ec.europa.eu/consumers/odr" target="_blank" rel="noopener">https://ec.europa.eu/consumers/odr</a>
</div> </p>
<p>
Wir sind nicht bereit oder verpflichtet, an Streitbeilegungsverfahren vor einer
Verbraucherschlichtungsstelle teilzunehmen.
</p>
<div class="mb-8"> <h3>Haftung für Inhalte</h3>
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-4">Vertreten durch</h3> <p>
<p class="text-zinc-600 dark:text-zinc-400">Geschäftsführer: Dr. Michael Weber</p> Als Diensteanbieter sind wir gemäß § 7 Abs. 1 TMG für eigene Inhalte auf diesen Seiten nach
</div> den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter
jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen
oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen.
</p>
<div class="mb-8"> <h3>Haftung für Links</h3>
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-4">Registereintrag</h3> <p>
<p class="text-zinc-600 dark:text-zinc-400">Eintragung im Handelsregister</p> Unser Angebot enthält Links zu externen Websites Dritter, auf deren Inhalte wir keinen Einfluss
<p class="text-zinc-600 dark:text-zinc-400">Registergericht: Amtsgericht Berlin-Charlottenburg haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte
</p> der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich.
<p class="text-zinc-600 dark:text-zinc-400">Registernummer: HRB 123456 B</p> </p>
</div>
<div class="mb-8">
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-4">Umsatzsteuer-ID</h3>
<p class="text-zinc-600 dark:text-zinc-400">Umsatzsteuer-Identifikationsnummer gemäß § 27a UStG:
</p>
<p class="text-zinc-600 dark:text-zinc-400">DE123456789</p>
</div>
<div class="mb-8">
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-4">Verantwortlich für den
Inhalt nach § 55 Abs. 2 RStV</h3>
<p class="text-zinc-600 dark:text-zinc-400">Lisa Müller</p>
<p class="text-zinc-600 dark:text-zinc-400">Musterstraße 123</p>
<p class="text-zinc-600 dark:text-zinc-400">10115 Berlin</p>
</div>
<div class="mb-8">
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-4">Streitschlichtung</h3>
<p class="text-zinc-600 dark:text-zinc-400">
Die Europäische Kommission stellt eine Plattform zur Online-Streitbeilegung (OS) bereit:
<a href="https://ec.europa.eu/consumers/odr"
class="text-[var(--color-primary)] hover:underline"
target="_blank">https://ec.europa.eu/consumers/odr</a>
</p>
<p class="text-zinc-600 dark:text-zinc-400 mt-4">
Wir sind nicht bereit oder verpflichtet, an Streitbeilegungsverfahren vor einer
Verbraucherschlichtungsstelle teilzunehmen.
</p>
</div>
<div class="mb-8">
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-4">Haftung für Inhalte</h3>
<p class="text-zinc-600 dark:text-zinc-400">
Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach
den allgemeinen Gesetzen verantwortlich.
Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte
oder gespeicherte fremde Informationen zu
überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen.
</p>
</div>
<div class="mb-8">
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-4">Haftung für Links</h3>
<p class="text-zinc-600 dark:text-zinc-400">
Unser Angebot enthält Links zu externen Websites Dritter, auf deren Inhalte wir keinen
Einfluss haben. Deshalb können wir für
diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten
ist stets der jeweilige Anbieter oder
Betreiber der Seiten verantwortlich.
</p>
</div>
<div>
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-4">Urheberrecht</h3>
<p class="text-zinc-600 dark:text-zinc-400">
Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem
deutschen Urheberrecht.
Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der
Grenzen des Urheberrechtes bedürfen
der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers.
</p>
</div>
</div>
</div>
</div>
</section>
<livewire:web.footer />
</main>
<h3>Urheberrecht</h3>
<p>
Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem
deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung
außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen
Autors bzw. Erstellers.
</p>
</div>
</x-web.static-page>
@endsection @endsection
@push('styles')
<style>
:root {
--color-primary: {{ $domainConfig['color_scheme']['primary'] ?? '#cf3628' }};
--color-secondary: {{ $domainConfig['color_scheme']['secondary'] ?? '#f0834a' }};
}
[x-cloak] {
display: none !important;
}
</style>
@endpush

View file

@ -58,47 +58,36 @@
{{-- Masthead --}} {{-- Masthead --}}
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 pt-8 lg:pt-9"> <section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 pt-8 lg:pt-9">
<div class="grid gap-8 lg:gap-12 lg:grid-cols-[1.5fr_1fr] lg:items-end mb-[18px]"> <div class="flex items-center justify-between gap-4 mb-4">
<div> <div class="eyebrow">Branche</div>
<div class="eyebrow mb-3">Branche</div> <a href="{{ route('web.home') }}" class="inline-flex items-center gap-1.5 text-[12px] font-semibold text-ink-3 hover:text-ink transition-colors whitespace-nowrap" aria-label="Zurück zu allen Meldungen">
<h1 class="font-serif text-[40px] sm:text-[52px] lg:text-[56px] font-semibold m-0 mb-4 leading-[1.02] tracking-[-1.2px] text-ink">{{ $catName }}</h1> <svg width="13" height="13" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M15 19l-7-7 7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
<p class="font-serif text-[16px] leading-[1.55] m-0 mb-[18px] max-w-[620px] text-ink-2">{{ $catDescription }}</p> Alle Meldungen
<div class="text-[11.5px] text-ink-3 flex items-center gap-2.5 flex-wrap"> </a>
<span class="w-1.5 h-1.5 rounded-full bg-brand pulse-dot"></span>
{{ $fmt($categoryStats['month'] ?? 0) }} Meldungen in den letzten 30 Tagen · {{ $fmt($categoryStats['today'] ?? 0) }} am {{ $referenceNow->translatedFormat('j. M Y') }}
</div>
</div>
<aside class="flex flex-col gap-2.5">
<a href="{{ route('veroeffentlichen') }}" class="w-full px-4 py-3 inline-flex items-center justify-center gap-2 text-[13px] font-semibold text-white bg-brand hover:bg-brand-deep transition-colors">
Veröffentlichen in {{ $catName }}
</a>
<div class="grid grid-cols-2 gap-2">
<a href="{{ route('newsrooms') }}" class="inline-flex items-center justify-center gap-1.5 px-3 py-2.5 text-[12px] font-semibold border border-bg-rule-strong bg-white hover:bg-bg-elev transition-colors">Newsrooms</a>
<a href="{{ route('web.home') }}" class="inline-flex items-center justify-center gap-1.5 px-3 py-2.5 text-[12px] font-semibold border border-bg-rule-strong bg-white hover:bg-bg-elev transition-colors">Alle Meldungen</a>
</div>
<div class="mt-1.5 pt-3.5 border-t border-bg-rule flex justify-between items-baseline text-[11px] text-ink-3">
<div>
<div class="eyebrow muted text-[9px] mb-1">Aktive Unternehmen</div>
<span class="font-mono text-[12px] text-ink-2">{{ $fmt($categoryStats['totalCompanies'] ?? 0) }} Newsrooms</span>
</div>
<span class="font-mono text-[11px] text-ink-3">{{ $fmt($categoryStats['total'] ?? 0) }} Meldungen gesamt</span>
</div>
</aside>
</div> </div>
<hr class="rule-strong">
</section>
@if ($subCategories->isNotEmpty()) {{-- Branchen-Profil --}}
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 mt-6 mb-2 flex flex-wrap items-center gap-2"> <div class="bg-bg-elev border border-bg-rule p-6 sm:p-8">
<span class="eyebrow muted text-[10px] mr-1.5">Sub-Themen</span> <h1 class="font-serif text-[36px] sm:text-[48px] lg:text-[52px] font-semibold m-0 leading-[1.02] tracking-[-1.2px] text-ink">{{ $catName }}</h1>
@foreach ($subCategories as $sub) <p class="font-serif text-[16px] leading-[1.55] m-0 mt-4 max-w-[680px] text-ink-2">{{ $catDescription }}</p>
<a href="{{ $sub['href'] }}" class="inline-flex items-baseline gap-[7px] px-3.5 py-2 text-[12.5px] font-medium border border-bg-rule-strong text-ink hover:bg-bg-elev transition-colors"> <div class="mt-4 text-[11.5px] text-ink-3 flex items-center gap-2.5 flex-wrap">
{{ $sub['name'] }} <span class="w-1.5 h-1.5 rounded-full bg-brand pulse-dot"></span>
<span class="font-mono text-[10.5px] text-ink-3 font-medium">{{ $fmt($sub['total']) }}</span> {{ $fmt($categoryStats['month'] ?? 0) }} Meldungen in den letzten 30 Tagen · {{ $fmt($categoryStats['today'] ?? 0) }} am {{ $referenceNow->translatedFormat('j. M Y') }}
</a> </div>
@endforeach
</section> @if ($subCategories->isNotEmpty())
@endif <div class="flex flex-wrap items-center gap-2 mt-5 pt-5 border-t border-bg-rule">
<span class="eyebrow muted text-[10px] mr-1.5">Sub-Themen</span>
@foreach ($subCategories as $sub)
<a href="{{ $sub['href'] }}" class="inline-flex items-baseline gap-[7px] px-3 py-1.5 text-[12px] font-medium border border-bg-rule-strong bg-bg text-ink hover:bg-white hover:border-brand transition-colors">
{{ $sub['name'] }}
<span class="font-mono text-[10.5px] text-ink-3 font-medium">{{ $fmt($sub['total']) }}</span>
</a>
@endforeach
</div>
@endif
</div>
</section>
{{-- Stat strip --}} {{-- Stat strip --}}
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 mt-6"> <section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 mt-6">

View file

@ -1,326 +1,88 @@
@extends('web.layouts.web-master') @extends('web.layouts.web-master')
@section('title', 'Kontakt - Business Portal 24') @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') @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>
<main class="min-h-screen flex flex-col bg-white dark:bg-zinc-950 transition-colors duration-200"> {{-- Besuch / Anfahrt --}}
<!-- Burger Menu Component --> <div class="grid gap-8 lg:grid-cols-[1.2fr_1fr] mt-12">
<livewire:web.burger-menu /> <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>
<!-- Header Component --> {{-- TODO: Kontaktformular reaktivieren, sobald ein POST-Handler
<livewire:web.header /> (Controller/Volt + Validierung + Mailversand) bereitsteht.
Bis dahin führt der direkte E-Mail-Weg ans Ziel. --}}
<!-- Hero Section --> <h3>Anfahrt</h3>
<section class="relative overflow-hidden text-white py-16 animate-fade-in" <p>
style="background: var(--gradient-hero);"> <strong>Öffentliche Verkehrsmittel:</strong> U-Bahn U4/U5 – Haltestelle Lehel; Tram 19 –
<div class="container mx-auto px-4 text-center"> Haltestelle Maxmonument.<br>
<h1 class="text-4xl md:text-5xl font-bold mb-4 animate-fade-in-up"> <strong>Parken:</strong> Parkhaus Maximilianstraße (5 Min. Fußweg).
Kontakt
</h1>
<p class="text-xl text-white/90 max-w-2xl mx-auto animate-fade-in-up animation-delay-200">
Wir sind für Sie da – per E-Mail, Telefon oder vor Ort in München
</p> </p>
</div> </div>
<!-- Decorative Pattern -->
<div class="absolute top-0 right-0 opacity-10">
<svg width="404" height="384" fill="none" viewBox="0 0 404 384">
<defs>
<pattern id="pattern-hero-kontakt" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<rect x="0" y="0" width="4" height="4" fill="currentColor"/>
</pattern>
</defs>
<rect width="404" height="384" fill="url(#pattern-hero-kontakt)"/>
</svg>
</div>
</section>
<!-- Contact Methods --> <aside class="border border-bg-rule bg-bg-elev p-6 h-max">
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200"> <div class="eyebrow muted mb-3">Hauptsitz</div>
<div class="container mx-auto px-4"> <p class="text-[13.5px] leading-[1.6] text-ink-2 m-0">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 max-w-6xl mx-auto mb-16"> {{ $brandLabel }}<br>
<!-- Email --> Maximilianstraße 35<br>
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 text-center hover:shadow-lg transition-all"> 80539 München<br>
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mx-auto mb-4"> Deutschland
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24"> </p>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path> <div class="mt-5 pt-5 border-t border-bg-rule">
</svg> <div class="eyebrow muted mb-2">Schnelle Hilfe</div>
</div> <p class="text-[12.5px] text-ink-3 m-0 mb-3">
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2"> Antworten auf die häufigsten Fragen finden Sie sofort online.
E-Mail </p>
</h3> <a href="{{ route('faq') }}"
<a href="mailto:info@businessportal.de" class="text-[var(--color-primary)] hover:text-[var(--color-secondary)] transition-colors font-medium block mb-1"> 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]">
info@businessportal.de Zur FAQ
</a> <svg width="11" height="11" viewBox="0 0 12 12" fill="none" aria-hidden="true">
<p class="text-sm text-zinc-600 dark:text-zinc-400"> <path d="M2 6h8M6 2l4 4-4 4" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" />
Antwort innerhalb von 24 Stunden </svg>
</p> </a>
</div>
<!-- Phone -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 text-center hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mx-auto mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Telefon
</h3>
<a href="tel:+498912345678" class="text-[var(--color-primary)] hover:text-[var(--color-secondary)] transition-colors font-medium block mb-1">
+49 89 1234 5678
</a>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Mo-Fr 9:00-18:00 Uhr
</p>
</div>
<!-- Address -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 text-center hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mx-auto mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Adresse
</h3>
<p class="text-zinc-900 dark:text-zinc-100 font-medium mb-1">
Maximilianstraße 35
</p>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
80539 München, Deutschland
</p>
</div>
<!-- Business Hours -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 text-center hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mx-auto mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Geschäftszeiten
</h3>
<p class="text-zinc-900 dark:text-zinc-100 font-medium mb-1">
Mo-Fr 9:00-18:00
</p>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Sa-So geschlossen
</p>
</div>
</div> </div>
</aside>
<!-- Contact Form & Map --> </div>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 max-w-6xl mx-auto"> </x-web.static-page>
<!-- Form -->
<div>
<div class="mb-8">
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">
Nachricht senden
</h2>
<p class="text-zinc-600 dark:text-zinc-400">
Haben Sie Fragen oder benötigen Sie Unterstützung? Füllen Sie das Formular aus und wir melden uns schnellstmöglich bei Ihnen.
</p>
</div>
<form class="space-y-6" method="POST" action="/kontakt">
@csrf
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="space-y-2">
<label for="vorname" class="block text-sm font-medium text-zinc-900 dark:text-zinc-100">
Vorname *
</label>
<input
id="vorname"
name="vorname"
type="text"
placeholder="Max"
required
class="w-full px-4 py-2 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 border border-zinc-300 dark:border-zinc-700 rounded-lg focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-colors duration-200"
/>
</div>
<div class="space-y-2">
<label for="nachname" class="block text-sm font-medium text-zinc-900 dark:text-zinc-100">
Nachname *
</label>
<input
id="nachname"
name="nachname"
type="text"
placeholder="Mustermann"
required
class="w-full px-4 py-2 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 border border-zinc-300 dark:border-zinc-700 rounded-lg focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-colors duration-200"
/>
</div>
</div>
<div class="space-y-2">
<label for="email" class="block text-sm font-medium text-zinc-900 dark:text-zinc-100">
E-Mail-Adresse *
</label>
<input
id="email"
name="email"
type="email"
placeholder="max.mustermann@beispiel.de"
required
class="w-full px-4 py-2 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 border border-zinc-300 dark:border-zinc-700 rounded-lg focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-colors duration-200"
/>
</div>
<div class="space-y-2">
<label for="unternehmen" class="block text-sm font-medium text-zinc-900 dark:text-zinc-100">
Unternehmen
</label>
<input
id="unternehmen"
name="unternehmen"
type="text"
placeholder="Firma GmbH"
class="w-full px-4 py-2 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 border border-zinc-300 dark:border-zinc-700 rounded-lg focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-colors duration-200"
/>
</div>
<div class="space-y-2">
<label for="telefon" class="block text-sm font-medium text-zinc-900 dark:text-zinc-100">
Telefon
</label>
<input
id="telefon"
name="telefon"
type="tel"
placeholder="+49 123 456789"
class="w-full px-4 py-2 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 border border-zinc-300 dark:border-zinc-700 rounded-lg focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-colors duration-200"
/>
</div>
<div class="space-y-2">
<label for="betreff" class="block text-sm font-medium text-zinc-900 dark:text-zinc-100">
Betreff *
</label>
<input
id="betreff"
name="betreff"
type="text"
placeholder="Wie können wir Ihnen helfen?"
required
class="w-full px-4 py-2 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 border border-zinc-300 dark:border-zinc-700 rounded-lg focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-colors duration-200"
/>
</div>
<div class="space-y-2">
<label for="nachricht" class="block text-sm font-medium text-zinc-900 dark:text-zinc-100">
Nachricht *
</label>
<textarea
id="nachricht"
name="nachricht"
placeholder="Ihre Nachricht an uns..."
rows="6"
required
class="w-full px-4 py-2 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 border border-zinc-300 dark:border-zinc-700 rounded-lg focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent transition-colors duration-200 resize-none"
></textarea>
</div>
<div class="text-sm text-zinc-600 dark:text-zinc-400">
* Pflichtfelder
</div>
<button
type="submit"
class="w-full inline-flex items-center justify-center px-6 py-3 text-sm font-medium text-white rounded-lg shadow-md hover:shadow-lg transition-all"
style="background: var(--gradient-hero);"
>
<svg class="h-4 w-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"></path>
</svg>
Nachricht senden
</button>
</form>
</div>
<!-- Map & Info -->
<div class="space-y-6">
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-8 transition-colors duration-200">
<h3 class="text-xl font-semibold text-zinc-900 dark:text-zinc-100 mb-6">
Besuchen Sie uns
</h3>
<div class="space-y-6">
<div>
<h4 class="font-medium text-zinc-900 dark:text-zinc-100 mb-2">Hauptsitz München</h4>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Maximilianstraße 35<br />
80539 München<br />
Deutschland
</p>
</div>
<div class="border-t border-zinc-200 dark:border-zinc-800 pt-6">
<h4 class="font-medium text-zinc-900 dark:text-zinc-100 mb-2">Anfahrt</h4>
<p class="text-sm text-zinc-600 dark:text-zinc-400 mb-4">
<strong class="text-zinc-900 dark:text-zinc-100">Öffentliche Verkehrsmittel:</strong><br />
U-Bahn U4/U5 – Haltestelle Lehel<br />
Tram 19 – Haltestelle Maxmonument
</p>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
<strong class="text-zinc-900 dark:text-zinc-100">Parken:</strong><br />
Parkhaus Maximilianstraße (5 Min. Fußweg)
</p>
</div>
</div>
</div>
<div class="h-80 bg-zinc-100 dark:bg-zinc-800 rounded-lg overflow-hidden">
<div class="w-full h-full bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 flex items-center justify-center">
<div class="text-center">
<svg class="h-12 w-12 text-[var(--color-primary)] mx-auto mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"></path>
</svg>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Interaktive Karte
</p>
</div>
</div>
</div>
<div class="bg-zinc-50/50 dark:bg-zinc-900/50 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 transition-colors duration-200">
<h4 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
Schnelle Hilfe benötigt?
</h4>
<p class="text-sm text-zinc-600 dark:text-zinc-400 mb-4">
Für dringende Anfragen oder technischen Support steht Ihnen unser Chat zur Verfügung.
</p>
<a href="#" class="inline-flex items-center justify-center w-full px-6 py-3 text-sm font-medium text-zinc-700 dark:text-zinc-300 border border-zinc-300 dark:border-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-800 rounded-lg transition-all">
Live-Chat starten
</a>
</div>
</div>
</div>
</div>
</section>
<!-- Footer Component -->
<livewire:web.footer />
</main>
@endsection @endsection
@push('styles')
<style>
/* Domain-spezifische Color-Variablen für Inline-Styles */
:root {
--color-primary: {{ $domainConfig['color_scheme']['primary'] ?? '#cf3628' }};
--color-secondary: {{ $domainConfig['color_scheme']['secondary'] ?? '#f0834a' }};
}
/* Alpine.js Cloak */
[x-cloak] {
display: none !important;
}
</style>
@endpush

View file

@ -0,0 +1,227 @@
@extends('web.layouts.web-master')
@php
use Illuminate\Support\Str;
\Carbon\Carbon::setLocale(app()->getLocale());
$brandConfig = config('domains.domains.'.config('app.theme').'.brand', []);
$brandName = $brandConfig['name'] ?? 'businessportal';
$brandAccent = $brandConfig['accent'] ?? '24';
$fmt = fn ($value) => number_format((int) $value, 0, ',', '.');
$palette = ['#0098A6', '#21A038', '#0018A8', '#1E1E1E', '#E20074', '#003781', '#C84A1E', '#5A6E2F'];
$logoUrl = $company->logoUrl();
$initial = mb_strtoupper(mb_substr((string) $company->name, 0, 1));
$color = $palette[crc32((string) $company->id) % count($palette)];
$boilerplate = filled($company->boilerplate)
? trim((string) Str::of(strip_tags((string) $company->boilerplate))->squish())
: null;
$websiteHost = filled($company->website) ? preg_replace('#^https?://(www\.)?#', '', rtrim((string) $company->website, '/')) : null;
$leadImage = $leadRelease?->images->first();
$leadImageUrl = $leadImage?->variantUrl('detail') ?? $leadImage?->variantUrl('card') ?? $leadImage?->url();
$leadCat = $leadRelease?->category?->translations->firstWhere('locale', app()->getLocale()) ?? $leadRelease?->category?->translations->first();
$leadLead = $leadRelease
? (filled($leadRelease->subtitle)
? $leadRelease->subtitle
: (string) Str::of(strip_tags((string) $leadRelease->text))->squish()->limit(220))
: null;
$leadWords = $leadRelease ? str_word_count(strip_tags((string) $leadRelease->text)) : 0;
$leadReadTime = max(1, (int) round($leadWords / 200));
@endphp
@section('title', $company->name.' – Newsroom · '.$brandName.$brandAccent)
@section('meta_description', Str::limit($boilerplate ?? ('Newsroom von '.$company->name.': alle redaktionell geprüften Pressemitteilungen gebündelt an einem Ort.'), 155))
@section('og_type', 'profile')
@section('hreflang')
<link rel="alternate" hreflang="de" href="{{ url('/de/newsroom/'.$company->slug) }}">
<link rel="alternate" hreflang="en" href="{{ url('/en/newsroom/'.$company->slug) }}">
<link rel="alternate" hreflang="x-default" href="{{ url('/de/newsroom/'.$company->slug) }}">
@endsection
@section('content')
<x-web.site-header />
<main class="bg-bg text-ink">
{{-- Breadcrumb --}}
<div class="border-b border-bg-rule">
<div class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 py-2.5 flex items-center gap-2 text-[11.5px] text-ink-3">
<a href="{{ route('web.home') }}" class="hover:text-ink transition-colors">Startseite</a>
<span class="text-ink-4" aria-hidden="true">/</span>
<a href="{{ route('newsrooms') }}" class="hover:text-ink transition-colors">Newsrooms</a>
<span class="text-ink-4" aria-hidden="true">/</span>
<span class="text-ink font-semibold truncate max-w-[55vw]">{{ $company->name }}</span>
</div>
</div>
{{-- Masthead --}}
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 pt-8 lg:pt-9">
<div class="flex items-center justify-between gap-4 mb-4">
<div class="eyebrow">Newsroom</div>
<a href="{{ route('newsrooms') }}" class="inline-flex items-center gap-1.5 text-[12px] font-semibold text-ink-3 hover:text-ink transition-colors whitespace-nowrap" aria-label="Zurück zu allen Newsrooms">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M15 19l-7-7 7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
Alle Newsrooms
</a>
</div>
{{-- Firmenprofil --}}
<div class="bg-bg-elev border border-bg-rule p-6 sm:p-8">
<div class="flex items-start gap-4 sm:gap-6">
@if ($logoUrl)
<img src="{{ $logoUrl }}" alt="{{ $company->name }}" class="w-16 h-16 sm:w-24 sm:h-24 object-contain bg-white border border-bg-rule flex-shrink-0">
@else
<div class="w-16 h-16 sm:w-24 sm:h-24 flex items-center justify-center text-white text-[30px] sm:text-[44px] font-bold font-serif flex-shrink-0" style="background: {{ $color }};">
{{ $initial }}
</div>
@endif
<div class="min-w-0 flex-1">
<h1 class="font-serif text-[28px] sm:text-[38px] lg:text-[42px] font-semibold m-0 leading-[1.05] tracking-[-1px] text-ink">{{ $company->name }}</h1>
<div class="mt-3 text-[12px] text-ink-3 flex items-center gap-2.5 flex-wrap">
@if ($websiteHost)
<a href="{{ $company->website }}" target="_blank" rel="nofollow noopener" class="inline-flex items-center gap-1.5 font-medium hover:text-ink transition-colors">
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true"><circle cx="6" cy="6" r="5" stroke="currentColor" stroke-width="1"/><path d="M1 6h10M6 1c2 1.5 2 8.5 0 10M6 1c-2 1.5-2 8.5 0 10" stroke="currentColor" stroke-width="1"/></svg>
{{ $websiteHost }}
</a>
<span class="text-ink-4" aria-hidden="true">·</span>
@endif
<span class="inline-flex items-center gap-1.5">
<span class="w-1.5 h-1.5 rounded-full bg-brand pulse-dot"></span>
{{ $fmt($newsroomStats['recent'] ?? 0) }} Meldungen in den letzten 30 Tagen
</span>
@if (! empty($newsroomStats['sinceYear']))
<span class="text-ink-4" aria-hidden="true">·</span>
<span>Newsroom seit {{ $newsroomStats['sinceYear'] }}</span>
@endif
</div>
</div>
</div>
@if ($boilerplate)
<p class="font-serif text-[15.5px] leading-[1.6] m-0 mt-5 pt-5 border-t border-bg-rule text-ink-2">{{ Str::limit($boilerplate, 360) }}</p>
@endif
@if ($categories->isNotEmpty())
<div class="flex flex-wrap items-center gap-2 mt-5 pt-5 border-t border-bg-rule">
<span class="eyebrow muted text-[10px] mr-1.5">Branchen</span>
@foreach ($categories as $cat)
<a href="{{ $cat['href'] }}" class="inline-flex items-baseline gap-[7px] px-3 py-1.5 text-[12px] font-medium border border-bg-rule-strong bg-bg text-ink hover:bg-white hover:border-brand transition-colors">
{{ $cat['name'] }}
<span class="font-mono text-[10.5px] text-ink-3 font-medium">{{ $fmt($cat['count']) }}</span>
</a>
@endforeach
</div>
@endif
</div>
</section>
{{-- Stat strip --}}
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 mt-6">
<div class="grid grid-cols-2 lg:grid-cols-4 border-y border-bg-rule">
<div class="px-6 py-5 border-r border-bg-rule">
<div class="eyebrow muted text-[10px] mb-2.5">Meldungen aktueller Tag</div>
<div class="font-serif text-[32px] sm:text-[36px] font-semibold leading-none tracking-[-0.6px] text-ink">{{ $fmt($newsroomStats['today'] ?? 0) }}</div>
<div class="text-[11.5px] text-ink-3 mt-2">Stand {{ $referenceNow->translatedFormat('j. M Y') }}</div>
</div>
<div class="px-6 py-5 lg:border-r border-bg-rule">
<div class="eyebrow muted text-[10px] mb-2.5">Letzte 30 Tage</div>
<div class="font-serif text-[32px] sm:text-[36px] font-semibold leading-none tracking-[-0.6px] text-ink">{{ $fmt($newsroomStats['recent'] ?? 0) }}</div>
<div class="text-[11.5px] text-ink-3 mt-2">veröffentlichte Meldungen</div>
</div>
<div class="px-6 py-5 border-r border-bg-rule border-t lg:border-t-0">
<div class="eyebrow muted text-[10px] mb-2.5">Im Archiv</div>
<div class="font-serif text-[32px] sm:text-[36px] font-semibold leading-none tracking-[-0.6px] text-ink">{{ $fmt($newsroomStats['total'] ?? 0) }}</div>
<div class="text-[11.5px] text-ink-3 mt-2">Meldungen gesamt</div>
</div>
<div class="px-6 py-5 border-t lg:border-t-0">
<div class="eyebrow muted text-[10px] mb-2.5">Aufrufe gesamt</div>
<div class="font-serif text-[32px] sm:text-[36px] font-semibold leading-none tracking-[-0.6px] text-ink">{{ $fmt($newsroomStats['totalHits'] ?? 0) }}</div>
<div class="text-[11.5px] text-ink-3 mt-2">über alle Meldungen</div>
</div>
</div>
</section>
@if ($leadRelease)
{{-- Top-Meldung --}}
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 mt-10">
<article>
<a href="{{ route('release.detail', ['slug' => $leadRelease->slug]) }}" class="block group">
<div class="relative overflow-hidden bg-hero-grad hatch-dark" style="aspect-ratio: 16 / 9;">
@if ($leadImageUrl)
<img src="{{ $leadImageUrl }}" alt="{{ $leadRelease->title }}" class="absolute inset-0 w-full h-full object-cover" loading="lazy">
@endif
<div class="absolute top-5 left-5 flex gap-2">
<span class="bp-tag">Aktuellste Meldung</span>
</div>
<div class="absolute left-0 right-0 bottom-0 px-6 sm:px-9 pb-8 pt-[70px] text-white" style="background:linear-gradient(180deg,transparent,rgba(0,0,0,0.92));">
@if ($leadCat)
<div class="eyebrow mb-3" style="color:#FF8B6F;">{{ $leadCat->name }}</div>
@endif
<h2 class="font-serif text-[26px] sm:text-[34px] font-semibold m-0 leading-[1.12] tracking-[-0.6px] max-w-[760px] group-hover:text-white">
{{ $leadRelease->title }}
</h2>
@if ($leadLead)
<p class="font-serif text-[14.5px] leading-[1.5] mt-3.5 max-w-[640px] text-white/85">{{ $leadLead }}</p>
@endif
<div class="mt-[18px] flex items-center gap-3.5 text-[12px] text-white/70 flex-wrap">
@if ($leadRelease->published_at)
<span class="font-mono">{{ $leadRelease->published_at->translatedFormat('d.m.Y · H:i') }}</span>
<span aria-hidden="true">·</span>
@endif
<span>{{ $leadReadTime }} Min. Lesezeit</span>
</div>
</div>
</div>
</a>
</article>
</section>
@endif
{{-- Meldungen + Sidebar --}}
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 mt-12 mb-16 grid gap-9 lg:grid-cols-[1.7fr_1fr]">
<div>
<header class="flex items-baseline justify-between mb-4 min-h-[34px] flex-wrap gap-3">
<h2 class="font-serif text-[28px] font-semibold m-0 tracking-[-0.3px] text-ink">
Alle Meldungen <span class="text-[14px] text-ink-3 font-normal ml-1.5">· {{ $fmt($newsroomStats['total'] ?? 0) }}</span>
</h2>
</header>
<hr class="rule-strong">
@forelse ($releases as $release)
<x-web.feed-item :release="$release" />
@empty
<p class="text-[13px] text-ink-3 py-6">Aktuell keine weiteren Meldungen in diesem Newsroom.</p>
@endforelse
<x-web.pagination :paginator="$releases" />
</div>
<aside class="flex flex-col gap-9">
<x-web.most-read :releases="$mostReadReleases ?? []" />
{{-- Eigenen Newsroom starten --}}
<section class="border border-bg-rule-strong bg-bg-elev p-6">
<div class="eyebrow mb-2">Für Unternehmen</div>
<h3 class="font-serif text-[20px] font-semibold m-0 mb-2 tracking-[-0.2px] leading-[1.2] text-ink">
Eigenen Newsroom starten
</h3>
<p class="text-[12.5px] leading-[1.5] m-0 mb-4 text-ink-2">
Bündeln Sie alle Ihre Pressemitteilungen unter einer eigenen Marken-URL – mit Logo, Branchen-Zuordnung und SEO-Vorteil.
</p>
<a href="{{ route('veroeffentlichen') }}"
class="w-full inline-flex items-center justify-center gap-2 px-[18px] py-2.5 text-[13px] font-semibold bg-white border border-bg-rule-strong text-ink rounded-[2px] cursor-pointer hover:border-brand hover:text-brand transition-colors">
Newsroom anlegen →
</a>
</section>
<x-web.publisher-cta />
</aside>
</section>
</main>
<x-web.site-footer />
@endsection

View file

@ -1,331 +1,184 @@
@extends('web.layouts.web-master') @extends('web.layouts.web-master')
@section('title', 'Newsrooms - Business Portal 24') @php
use Illuminate\Support\Carbon;
@section('content') \Carbon\Carbon::setLocale(app()->getLocale());
<main class="min-h-screen flex flex-col bg-white dark:bg-zinc-950 transition-colors duration-200"> $brandConfig = config('domains.domains.'.config('app.theme').'.brand', []);
<!-- Burger Menu Component --> $brandName = $brandConfig['name'] ?? 'businessportal';
<livewire:web.burger-menu /> $brandAccent = $brandConfig['accent'] ?? '24';
<!-- Header Component --> $palette = ['#0098A6', '#21A038', '#0018A8', '#1E1E1E', '#E20074', '#003781', '#C84A1E', '#5A6E2F'];
<livewire:web.header /> $fmt = fn ($value) => number_format((int) $value, 0, ',', '.');
@endphp
<!-- Hero Section --> @section('title', 'Newsrooms – '.$brandName.$brandAccent)
<section class="relative overflow-hidden text-white py-20 animate-fade-in" @section('meta_description', 'Alle aktiven Unternehmens-Newsrooms im Überblick – redaktionell geprüfte Pressemitteilungen je Unternehmen, gebündelt und dauerhaft auffindbar im DACH-Raum.')
style="background: var(--gradient-hero);">
<div class="container mx-auto px-4">
<div class="max-w-3xl mx-auto text-center">
<h1 class="text-4xl md:text-5xl font-bold mb-6 animate-fade-in-up">
Newsrooms
</h1>
<p class="text-xl text-white/90 leading-relaxed animate-fade-in-up animation-delay-200">
Ihr professioneller Unternehmens-Newsroom – Alle Pressemitteilungen zentral an einem Ort
</p>
</div>
</div>
<!-- Decorative Pattern -->
<div class="absolute top-0 right-0 opacity-10">
<svg width="404" height="384" fill="none" viewBox="0 0 404 384">
<defs>
<pattern id="pattern-hero-newsrooms" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<rect x="0" y="0" width="4" height="4" fill="currentColor"/>
</pattern>
</defs>
<rect width="404" height="384" fill="url(#pattern-hero-newsrooms)"/>
</svg>
</div>
</section>
<!-- What is a Newsroom Section -->
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200">
<div class="container mx-auto px-4">
<div class="max-w-4xl mx-auto">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">
Was ist ein Newsroom?
</h2>
<p class="text-lg text-zinc-600 dark:text-zinc-400">
Ihre digitale Pressezentrale für professionelle Unternehmenskommunikation
</p>
</div>
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-8 md:p-12 transition-colors duration-200">
<p class="text-lg text-zinc-900 dark:text-zinc-100 leading-relaxed mb-6">
Ein Newsroom ist Ihre dedizierte Unternehmensseite auf Business Portal, wo alle Ihre Pressemitteilungen gebündelt und professionell präsentiert werden. Journalisten, Partner und Interessenten finden hier alle relevanten Informationen zu Ihrem Unternehmen auf einen Blick.
</p>
<p class="text-lg text-zinc-900 dark:text-zinc-100 leading-relaxed">
Mit Ihrem individuellen Newsroom bauen Sie Vertrauen auf und schaffen eine zentrale Anlaufstelle für alle, die sich über Ihr Unternehmen informieren möchten.
</p>
</div>
</div>
</div>
</section>
<!-- Features Section -->
<section class="py-16 bg-zinc-50/50 dark:bg-zinc-900/50 transition-colors duration-200">
<div class="container mx-auto px-4">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">
Newsroom Features
</h2>
<p class="text-zinc-600 dark:text-zinc-400 max-w-2xl mx-auto">
Professionelle Features für Ihre Unternehmenskommunikation
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 max-w-6xl mx-auto">
<!-- Feature 1 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
Individuelles Branding
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Gestalten Sie Ihren Newsroom mit Ihrem Logo, Unternehmensfarben und individuellen Inhalten.
</p>
</div>
<!-- Feature 2 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
Zentrale Verwaltung
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Alle Pressemitteilungen chronologisch sortiert und nach Kategorien filterbar an einem Ort.
</p>
</div>
<!-- Feature 3 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
SEO-Optimiert
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Ihr Newsroom wird von Suchmaschinen indexiert und verbessert Ihre Online-Sichtbarkeit.
</p>
</div>
<!-- Feature 4 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
Analytics & Insights
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Detaillierte Statistiken zu Besuchern, Views und Engagement Ihrer Pressemitteilungen.
</p>
</div>
<!-- Feature 5 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
Medien-Kontakte
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Hinterlegen Sie Pressekontakte und ermöglichen Sie direkte Anfragen von Journalisten.
</p>
</div>
<!-- Feature 6 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
RSS-Feeds
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Automatische RSS-Feeds ermöglichen einfaches Abonnieren Ihrer Neuigkeiten.
</p>
</div>
</div>
</div>
</section>
<!-- Pricing Tiers Section -->
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200">
<div class="container mx-auto px-4">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">
Newsroom Pakete
</h2>
<p class="text-zinc-600 dark:text-zinc-400 max-w-2xl mx-auto">
Wählen Sie das passende Paket für Ihre Anforderungen
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-5xl mx-auto">
<!-- Basic Newsroom -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-8 hover:shadow-lg transition-all">
<h3 class="text-xl font-bold text-zinc-900 dark:text-zinc-100 mb-2">
Basic Newsroom
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400 mb-4">
Inklusive im Free-Tarif
</p>
<ul class="space-y-3 mb-6">
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-600 dark:text-zinc-400">Standard-Design</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-600 dark:text-zinc-400">Alle Pressemitteilungen</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-600 dark:text-zinc-400">RSS-Feed</span>
</li>
</ul>
</div>
<!-- Professional Newsroom -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border-2 border-[var(--color-primary)] p-8 hover:shadow-lg transition-all relative">
<div class="absolute -top-4 left-1/2 -translate-x-1/2 px-4 py-1 bg-gradient-to-r from-[var(--color-primary)] to-[var(--color-secondary)] text-white text-sm font-medium rounded-full">
Beliebt
</div>
<h3 class="text-xl font-bold text-zinc-900 dark:text-zinc-100 mb-2">
Professional Newsroom
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400 mb-4">
Professional-Tarif
</p>
<ul class="space-y-3 mb-6">
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-600 dark:text-zinc-400">Individuelles Branding</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-600 dark:text-zinc-400">Custom Domain</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-600 dark:text-zinc-400">Erweiterte Analytics</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-600 dark:text-zinc-400">Medien-Bibliothek</span>
</li>
</ul>
</div>
<!-- Enterprise Newsroom -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-8 hover:shadow-lg transition-all">
<h3 class="text-xl font-bold text-zinc-900 dark:text-zinc-100 mb-2">
Enterprise Newsroom
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400 mb-4">
Enterprise-Tarif
</p>
<ul class="space-y-3 mb-6">
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-600 dark:text-zinc-400">White Label Lösung</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-600 dark:text-zinc-400">API-Zugang</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-600 dark:text-zinc-400">Prioritäts-Support</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-600 dark:text-zinc-400">Individuelle Features</span>
</li>
</ul>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="py-16 text-white" style="background: var(--gradient-hero);">
<div class="container mx-auto px-4 text-center">
<div class="flex justify-center mb-6">
<svg class="h-16 w-16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"></path>
</svg>
</div>
<h2 class="text-3xl font-bold mb-4">
Starten Sie Ihren eigenen Newsroom
</h2>
<p class="text-xl text-white/90 mb-8 max-w-2xl mx-auto">
Erstellen Sie in wenigen Minuten Ihren professionellen Unternehmens-Newsroom
</p>
<a href="/register" class="inline-flex items-center justify-center px-8 py-4 text-sm font-medium bg-white text-[var(--color-primary)] hover:bg-zinc-100 rounded-lg shadow-md hover:shadow-lg transition-all">
Jetzt kostenlos starten
</a>
</div>
</section>
<!-- Footer Component -->
<livewire:web.footer />
</main>
@section('hreflang')
<link rel="alternate" hreflang="de" href="{{ url('/de/newsrooms') }}">
<link rel="alternate" hreflang="en" href="{{ url('/en/newsrooms') }}">
<link rel="alternate" hreflang="x-default" href="{{ url('/de/newsrooms') }}">
@endsection @endsection
@push('styles') @section('content')
<style> <x-web.site-header />
/* Domain-spezifische Color-Variablen für Inline-Styles */
:root {
--color-primary: {{ $domainConfig['color_scheme']['primary'] ?? '#cf3628' }};
--color-secondary: {{ $domainConfig['color_scheme']['secondary'] ?? '#f0834a' }};
}
/* Alpine.js Cloak */ <main class="bg-bg text-ink">
[x-cloak] { {{-- Breadcrumb --}}
display: none !important; <div class="border-b border-bg-rule">
} <div class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 py-2.5 flex items-center gap-2 text-[11.5px] text-ink-3">
</style> <a href="{{ route('web.home') }}" class="hover:text-ink transition-colors">{{ $brandName }}{{ $brandAccent }}</a>
@endpush <span class="text-ink-4" aria-hidden="true">›</span>
<span class="text-ink font-semibold">Newsrooms</span>
</div>
</div>
{{-- Masthead --}}
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 pt-8 lg:pt-10">
<div class="max-w-[680px]">
<div class="eyebrow mb-3">Unternehmens-Newsrooms</div>
<h1 class="font-serif text-[36px] sm:text-[46px] lg:text-[50px] font-semibold m-0 mb-4 leading-[1.05] tracking-[-1px] text-ink text-balance">
Newsrooms
</h1>
<p class="font-serif text-[16px] leading-[1.55] m-0 text-ink-2">
Alle aktiven Unternehmen mit ihren redaktionell geprüften Pressemitteilungen – gebündelt an einem Ort.
</p>
</div>
{{-- Stat strip --}}
<div class="grid grid-cols-2 lg:grid-cols-3 border-y border-bg-rule mt-8">
<div class="px-6 py-5 border-r border-bg-rule">
<div class="eyebrow muted text-[10px] mb-2.5">Aktive Newsrooms</div>
<div class="font-serif text-[32px] sm:text-[36px] font-semibold leading-none tracking-[-0.6px] text-ink">{{ $fmt($totalNewsrooms) }}</div>
<div class="text-[11.5px] text-ink-3 mt-2">mit veröffentlichten Meldungen</div>
</div>
<div class="px-6 py-5 lg:border-r border-bg-rule">
<div class="eyebrow muted text-[10px] mb-2.5">Aktiv (30 Tage)</div>
<div class="font-serif text-[32px] sm:text-[36px] font-semibold leading-none tracking-[-0.6px] text-ink">{{ $fmt($activeNewsroomsCount) }}</div>
<div class="text-[11.5px] text-ink-3 mt-2">Stand {{ $referenceNow->translatedFormat('j. M Y') }}</div>
</div>
<div class="px-6 py-5 border-t lg:border-t-0">
<div class="eyebrow muted text-[10px] mb-2.5">Meldungen im Archiv</div>
<div class="font-serif text-[32px] sm:text-[36px] font-semibold leading-none tracking-[-0.6px] text-ink">{{ $fmt($archiveTotal) }}</div>
<div class="text-[11.5px] text-ink-3 mt-2">redaktionell geprüft</div>
</div>
</div>
</section>
{{-- Suche + Verzeichnis --}}
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 mt-8 mb-16">
<form action="{{ route('newsrooms') }}" method="get" class="mb-7 max-w-[520px]">
<label class="sr-only" for="newsroom-search">Newsroom suchen</label>
<div class="flex items-center gap-3 px-4 py-3 border border-bg-rule-strong bg-bg-elev focus-within:border-brand transition-colors">
<svg width="18" height="18" viewBox="0 0 16 16" fill="none" class="flex-shrink-0 text-ink-3" aria-hidden="true">
<circle cx="7" cy="7" r="5" stroke="currentColor" stroke-width="1.5" />
<path d="M11 11l3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
</svg>
<input id="newsroom-search" type="search" name="q" value="{{ $term }}"
placeholder="Unternehmen suchen…"
autocomplete="off"
class="flex-1 bg-transparent border-0 p-0 text-[14px] text-ink placeholder:text-ink-3 focus:outline-none focus:ring-0 min-w-0">
<button type="submit" class="flex-shrink-0 px-3.5 py-1.5 text-[12.5px] font-semibold bg-brand text-white rounded-[2px] hover:bg-brand-deep transition-colors">
Suchen
</button>
</div>
</form>
<header class="flex items-baseline justify-between mb-1 flex-wrap gap-3">
<h2 class="font-serif text-[22px] font-semibold m-0 tracking-[-0.3px] text-ink">
{{ $fmt($newsrooms->total()) }}
{{ $newsrooms->total() === 1 ? 'Newsroom' : 'Newsrooms' }}
@if ($term !== '')
<span class="text-ink-3 font-normal">für „{{ $term }}"</span>
@endif
</h2>
@if ($term !== '')
<a href="{{ route('newsrooms') }}" class="text-[12.5px] text-brand font-semibold hover:text-brand-deep transition-colors">Filter zurücksetzen</a>
@endif
</header>
<hr class="rule-strong mb-6">
@if ($newsrooms->isNotEmpty())
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-px bg-bg-rule border border-bg-rule">
@foreach ($newsrooms as $company)
@php
$logoUrl = $company->logoUrl();
$initial = mb_strtoupper(mb_substr((string) $company->name, 0, 1));
$color = $palette[$loop->index % count($palette)];
$latest = $company->latest_published_at ? Carbon::parse($company->latest_published_at) : null;
$isRecentlyActive = (int) ($company->recent_count ?? 0) > 0;
@endphp
<a href="{{ route('newsroom', ['slug' => $company->slug]) }}"
class="group flex flex-col bg-bg p-5 hover:bg-bg-elev transition-colors">
<div class="flex items-start gap-3.5 mb-3.5">
@if ($logoUrl)
<img src="{{ $logoUrl }}" alt="{{ $company->name }}" class="w-12 h-12 object-contain bg-white border border-bg-rule flex-shrink-0" loading="lazy">
@else
<div class="w-12 h-12 flex items-center justify-center text-white text-[18px] font-bold font-serif flex-shrink-0" style="background: {{ $color }};">
{{ $initial }}
</div>
@endif
<div class="min-w-0 flex-1">
<h3 class="font-serif text-[16px] font-semibold leading-[1.25] text-ink group-hover:text-brand transition-colors truncate">{{ $company->name }}</h3>
@if ($latest)
<div class="text-[11px] text-ink-3 mt-1">Letzte Meldung {{ $latest->translatedFormat('j. M Y') }}</div>
@endif
</div>
</div>
<div class="mt-auto flex items-center justify-between pt-3 border-t border-bg-rule">
<span class="text-[12px] text-ink-2">
<span class="font-mono font-semibold text-ink">{{ $fmt($company->releases_count ?? 0) }}</span> Meldungen
</span>
@if ($isRecentlyActive)
<span class="inline-flex items-center gap-1.5 text-[10.5px] font-semibold text-ink-2 px-2 py-0.5 bg-brand/[0.06] border border-brand/20 rounded-[2px]">
<span class="w-1.5 h-1.5 rounded-full bg-brand"></span>
{{ $fmt($company->recent_count) }} / 30 Tage
</span>
@endif
</div>
</a>
@endforeach
</div>
<x-web.pagination :paginator="$newsrooms" />
@else
<div class="border border-bg-rule bg-bg-elev px-6 py-12 text-center">
<h3 class="font-serif text-[20px] font-semibold text-ink m-0 mb-2">Keine Newsrooms gefunden</h3>
<p class="text-[13px] text-ink-3 m-0 mb-5 max-w-md mx-auto">
@if ($term !== '')
Für „{{ $term }}" gibt es derzeit keinen passenden Newsroom. Versuchen Sie einen anderen Suchbegriff.
@else
Aktuell sind keine aktiven Newsrooms verfügbar.
@endif
</p>
@if ($term !== '')
<a href="{{ route('newsrooms') }}" class="inline-flex items-center gap-2 px-4 py-2.5 text-[13px] font-semibold border border-bg-rule-strong bg-white text-ink hover:bg-bg-elev transition-colors">
Alle Newsrooms anzeigen
</a>
@endif
</div>
@endif
</section>
{{-- Publisher CTA (breit) --}}
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 mb-16">
<div class="bg-topbar-grad text-ink-on-dark p-6 sm:p-9">
<div class="grid gap-9 lg:grid-cols-[1.4fr_1fr] lg:items-center">
<div>
<div class="eyebrow on-dark mb-2.5">Eigener Newsroom</div>
<h3 class="font-serif text-[24px] sm:text-[28px] font-semibold m-0 mb-2.5 leading-[1.15] text-white tracking-[-0.3px]">Bündeln Sie Ihre Pressemitteilungen im eigenen Newsroom.</h3>
<p class="text-[14px] leading-[1.55] m-0 max-w-[540px] text-white/80">Eigene Marken-URL · alle Meldungen zentral · SEO-Vorteil für Ihr Unternehmen · redaktionell geprüft.</p>
</div>
<div class="flex flex-col gap-2.5">
<a href="{{ route('veroeffentlichen') }}" class="w-full inline-flex items-center justify-center px-[18px] py-3.5 text-[14px] font-semibold bg-brand text-white hover:bg-brand-deep transition-colors">Pressemitteilung einreichen →</a>
<a href="{{ route('preise') }}" class="w-full inline-flex items-center justify-center px-[18px] py-3 text-[14px] font-semibold text-white border border-white/30 hover:bg-white/10 transition-colors">Tarife &amp; Pakete ansehen</a>
</div>
</div>
</div>
</section>
</main>
<x-web.site-footer />
@endsection

View file

@ -1,420 +1,276 @@
@extends('web.layouts.web-master') @extends('web.layouts.web-master')
@section('title', 'Preise & Leistungen - Business Portal 24') {{--
Öffentliche Preise-/Tarifseite (Editorial-Design).
Reihenfolge laut Vorgabe: 1) Abo-Tarife 2) Einzel-Pressemitteilung 3) Add-ons.
@section('content') Datenquellen (alles aus dem System, nichts hartkodiert):
- Abos: Plan::active() -> $plans
- Einzel-PM: config('billing.single_pm_price_cents') -> $singlePmPriceCents
- Add-ons: config('credits.*') -> $extraPm, $boost, $proofPdf, $creditPacks, $morePaths
<main class="min-h-screen flex flex-col bg-white dark:bg-zinc-950 transition-colors duration-200"> Inhalte/Texte: lang/de/pricing.php + lang/en/pricing.php (Schlüssel pricing.*).
<!-- Burger Menu Component -->
<livewire:web.burger-menu />
<!-- Header Component --> HINWEIS (bewusst teilweise mit Kommentaren): Die korrespondierende In-App-Buchungs-
<livewire:web.header /> seite (resources/views/livewire/customer/bookings.blade.php) wird gerade überarbeitet.
Buchungs-CTAs verlinken vorerst auf den Veröffentlichen-Funnel; die Deep-Links in den
Checkout/zur Registrierung mit Tarif-Vorauswahl folgen, sobald der Flow final ist.
--}}
<!-- Hero Section --> @section('title', __('pricing.meta_title'))
<section class="relative overflow-hidden text-white py-16 animate-fade-in" @section('meta_description', __('pricing.meta_description'))
style="background: var(--gradient-hero);">
<div class="container mx-auto px-4 text-center">
<h1 class="text-4xl md:text-5xl font-bold mb-4 animate-fade-in-up">
Preise & Leistungen
</h1>
<p class="text-xl text-white/90 max-w-2xl mx-auto animate-fade-in-up animation-delay-200">
Transparente Preise für jede Unternehmensgröße – von Start-ups bis Konzerne
</p>
</div>
<!-- Decorative Pattern -->
<div class="absolute top-0 right-0 opacity-10">
<svg width="404" height="384" fill="none" viewBox="0 0 404 384">
<defs>
<pattern id="pattern-hero-preise" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<rect x="0" y="0" width="4" height="4" fill="currentColor"/>
</pattern>
</defs>
<rect width="404" height="384" fill="url(#pattern-hero-preise)"/>
</svg>
</div>
</section>
<!-- Pricing Cards -->
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200">
<div class="container mx-auto px-4">
<div class="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-6xl mx-auto">
<!-- Free Plan -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-8 flex flex-col transition-all duration-300 hover:shadow-lg">
<div class="mb-6">
<h3 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-2">
Free
</h3>
<div class="flex items-baseline gap-2 mb-3">
<span class="text-4xl font-bold text-zinc-900 dark:text-zinc-100">
0€
</span>
<span class="text-zinc-600 dark:text-zinc-400">kostenlos</span>
</div>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Ideal für kleinere Unternehmen und Start-ups
</p>
</div>
<ul class="space-y-3 mb-8 flex-1">
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">1 Pressemitteilung pro Monat</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">Standard-Veröffentlichung</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">Basis-Statistiken</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">E-Mail-Support</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">Community-Forum Zugang</span>
</li>
</ul>
<a href="/register" class="inline-flex items-center justify-center px-6 py-3 text-sm font-medium text-zinc-700 dark:text-zinc-300 border border-zinc-300 dark:border-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-800 rounded-lg transition-all">
Jetzt starten
</a>
</div>
<!-- Professional Plan (Popular) -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border-2 border-[var(--color-primary)] p-8 flex flex-col relative shadow-lg transition-all duration-300 hover:shadow-xl">
<span class="absolute -top-3 left-1/2 -translate-x-1/2 inline-flex items-center px-4 py-1 text-xs font-medium text-white rounded-full" style="background: var(--gradient-hero);">
Beliebteste Wahl
</span>
<div class="mb-6">
<h3 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-2">
Professional
</h3>
<div class="flex items-baseline gap-2 mb-3">
<span class="text-4xl font-bold text-zinc-900 dark:text-zinc-100">
99€
</span>
<span class="text-zinc-600 dark:text-zinc-400">pro Monat</span>
</div>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Für wachsende Unternehmen mit regelmäßigem Kommunikationsbedarf
</p>
</div>
<ul class="space-y-3 mb-8 flex-1">
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">10 Pressemitteilungen pro Monat</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">Premium-Platzierung</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">Erweiterte Statistiken & Analytics</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">Medienkit-Hosting</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">Prioritäts-Support</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">Social Media Distribution</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">Eigener Newsroom</span>
</li>
</ul>
<a href="/register?plan=professional" class="inline-flex items-center justify-center px-6 py-3 text-sm font-medium text-white rounded-lg shadow-md hover:shadow-lg transition-all" style="background: var(--gradient-hero);">
Jetzt upgraden
</a>
</div>
<!-- Enterprise Plan -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-8 flex flex-col transition-all duration-300 hover:shadow-lg">
<div class="mb-6">
<h3 class="text-2xl font-bold text-zinc-900 dark:text-zinc-100 mb-2">
Enterprise
</h3>
<div class="flex items-baseline gap-2 mb-3">
<span class="text-4xl font-bold text-zinc-900 dark:text-zinc-100">
Individuell
</span>
</div>
<p class="text-sm text-zinc-600 dark:text-zinc-400 mb-3">
auf Anfrage
</p>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Maßgeschneiderte Lösungen für große Organisationen
</p>
</div>
<ul class="space-y-3 mb-8 flex-1">
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">Unbegrenzte Pressemitteilungen</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">Top-Platzierung garantiert</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">White-Label Newsroom</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">Dedizierter Account Manager</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">API-Zugang</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">Custom Integrationen</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">Individuelle SLAs</span>
</li>
<li class="flex items-start gap-2">
<svg class="h-5 w-5 text-[var(--color-primary)] flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
<span class="text-sm text-zinc-900 dark:text-zinc-100">Schulungen & Workshops</span>
</li>
</ul>
<a href="/kontakt" class="inline-flex items-center justify-center px-6 py-3 text-sm font-medium text-zinc-700 dark:text-zinc-300 border border-zinc-300 dark:border-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-800 rounded-lg transition-all">
Kontakt aufnehmen
</a>
</div>
</div>
</div>
</section>
<!-- Add-ons Section -->
<section class="py-16 bg-zinc-50/50 dark:bg-zinc-900/50 transition-colors duration-200">
<div class="container mx-auto px-4">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">
Zusätzliche Services
</h2>
<p class="text-zinc-600 dark:text-zinc-400 max-w-2xl mx-auto">
Maximieren Sie die Reichweite Ihrer Pressemitteilungen mit unseren Premium-Features
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 max-w-6xl mx-auto">
<!-- Featured Story -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 transition-all duration-300 hover:shadow-lg">
<div class="w-12 h-12 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-lg flex items-center justify-center mb-4">
<svg class="h-6 w-6 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Featured Story
</h3>
<div class="text-2xl font-bold text-[var(--color-primary)] mb-3">
199€
</div>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Ihre Meldung prominent auf der Startseite platziert für 24 Stunden
</p>
</div>
<!-- Newsletter Feature -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 transition-all duration-300 hover:shadow-lg">
<div class="w-12 h-12 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-lg flex items-center justify-center mb-4">
<svg class="h-6 w-6 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Newsletter Feature
</h3>
<div class="text-2xl font-bold text-[var(--color-primary)] mb-3">
149€
</div>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Exklusive Platzierung im wöchentlichen Newsletter an 50.000+ Abonnenten
</p>
</div>
<!-- Social Media Boost -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 transition-all duration-300 hover:shadow-lg">
<div class="w-12 h-12 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-lg flex items-center justify-center mb-4">
<svg class="h-6 w-6 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Social Media Boost
</h3>
<div class="text-2xl font-bold text-[var(--color-primary)] mb-3">
99€
</div>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Verstärkte Verbreitung über LinkedIn, Twitter und weitere Kanäle
</p>
</div>
<!-- Premium Analytics -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 transition-all duration-300 hover:shadow-lg">
<div class="w-12 h-12 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-lg flex items-center justify-center mb-4">
<svg class="h-6 w-6 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Premium Analytics
</h3>
<div class="text-2xl font-bold text-[var(--color-primary)] mb-3">
79€/Monat
</div>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Detaillierte Auswertungen mit Reichweite, Engagement und Conversion-Tracking
</p>
</div>
</div>
</div>
</section>
<!-- FAQ Section -->
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200">
<div class="container mx-auto px-4 max-w-3xl">
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-8 text-center">
Häufig gestellte Fragen
</h2>
<div class="space-y-6">
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 transition-colors duration-200">
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Kann ich meinen Plan jederzeit wechseln?
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Ja, Sie können jederzeit upgraden oder downgraden. Bei einem Upgrade wird anteilig berechnet, bei einem Downgrade gilt die Änderung ab dem nächsten Abrechnungszeitraum.
</p>
</div>
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 transition-colors duration-200">
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Gibt es eine Mindestvertragslaufzeit?
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Nein, alle unsere Pläne sind monatlich kündbar. Es gibt keine versteckten Kosten oder Mindestlaufzeiten.
</p>
</div>
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 transition-colors duration-200">
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Welche Zahlungsmethoden akzeptieren Sie?
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Wir akzeptieren alle gängigen Kreditkarten (Visa, Mastercard, American Express), SEPA-Lastschrift und PayPal. Für Enterprise-Kunden bieten wir auch Rechnungszahlung an.
</p>
</div>
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 transition-colors duration-200">
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Wie funktioniert die Reichweitenmessung?
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Alle Professional- und Enterprise-Kunden erhalten Zugang zu detaillierten Analytics: Views, Klicks, geografische Verteilung, Referrer und mehr. Die Daten werden in Echtzeit aktualisiert.
</p>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="py-16 text-white" style="background: var(--gradient-hero);">
<div class="container mx-auto px-4 text-center">
<h2 class="text-3xl font-bold mb-4">
Noch Fragen zu unseren Preisen?
</h2>
<p class="text-xl text-white/90 mb-8 max-w-2xl mx-auto">
Unser Team berät Sie gerne und findet die passende Lösung für Ihre Anforderungen
</p>
<div class="flex flex-wrap gap-4 justify-center">
<a href="/kontakt?type=beratung" class="inline-flex items-center justify-center px-6 py-3 text-sm font-medium bg-white text-[var(--color-primary)] hover:bg-zinc-100 rounded-lg shadow-md hover:shadow-lg transition-all">
Beratungsgespräch vereinbaren
</a>
<a href="/kontakt" class="inline-flex items-center justify-center px-6 py-3 text-sm font-medium bg-white/10 hover:bg-white/20 border border-white text-white rounded-lg transition-all">
Kontakt aufnehmen
</a>
</div>
</div>
</section>
<!-- Footer Component -->
<livewire:web.footer />
</main>
@section('hreflang')
<link rel="alternate" hreflang="de" href="{{ url('/de/preise') }}">
<link rel="alternate" hreflang="en" href="{{ url('/en/preise') }}">
<link rel="alternate" hreflang="x-default" href="{{ url('/de/preise') }}">
@endsection @endsection
@push('styles') @php
<style> // 1 Credit = 1 €. Preise sind ganzzahlige Euro -> ohne Nachkommastellen,
/* Domain-spezifische Color-Variablen für Inline-Styles */ // sonst mit zwei Stellen (deutsche Schreibweise).
:root { $euro = static fn (int $cents): string => number_format($cents / 100, $cents % 100 === 0 ? 0 : 2, ',', '.');
--color-primary: {{ $domainConfig['color_scheme']['primary'] ?? '#cf3628' }}; $popularPlan = 'business';
--color-secondary: {{ $domainConfig['color_scheme']['secondary'] ?? '#f0834a' }}; $submitHref = route('veroeffentlichen');
} @endphp
/* Alpine.js Cloak */ @section('content')
[x-cloak] { <x-web.site-header />
display: none !important;
} <main class="bg-bg text-ink">
</style> {{-- ============================================================
@endpush MASTHEAD
============================================================ --}}
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 pt-8 lg:pt-10">
<div class="eyebrow mb-3">{{ __('pricing.eyebrow') }}</div>
<h1 class="font-serif text-[36px] sm:text-[48px] lg:text-[52px] font-semibold m-0 leading-[1.02] tracking-[-1.2px] text-ink">
{{ __('pricing.headline') }}
</h1>
<p class="font-serif text-[16px] leading-[1.55] m-0 mt-4 max-w-[680px] text-ink-2">
{{ __('pricing.intro') }}
</p>
</section>
{{-- ============================================================
1) ABO-TARIFE (Daten: Plan::active())
============================================================ --}}
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 mt-10">
<header class="flex items-baseline justify-between mb-4 flex-wrap gap-3">
<div>
<div class="eyebrow muted mb-1">{{ __('pricing.plans.eyebrow') }}</div>
<h2 class="font-serif text-[28px] font-semibold m-0 tracking-[-0.3px] text-ink">{{ __('pricing.plans.title') }}</h2>
</div>
<p class="text-[12.5px] text-ink-3 m-0 max-w-[360px]">{{ __('pricing.plans.subtitle') }}</p>
</header>
<hr class="rule-strong">
@if ($plans->isNotEmpty())
<div class="grid gap-px bg-bg-rule border border-bg-rule grid-cols-1 sm:grid-cols-2 lg:grid-cols-4">
@foreach ($plans as $plan)
@php
$isPopular = $plan->slug === $popularPlan;
$hasMonthly = (int) $plan->monthly_price_cents > 0;
@endphp
<div class="relative flex flex-col p-6 bg-bg {{ $isPopular ? 'ring-1 ring-inset ring-brand' : '' }}">
@if ($isPopular)
<span class="absolute top-0 right-0 inline-flex items-center px-2.5 py-1 text-[9.5px] font-bold uppercase tracking-[0.14em] text-white bg-brand">
{{ __('pricing.plans.popular') }}
</span>
@endif
<div class="eyebrow muted mb-2">{{ $plan->name }}</div>
<div class="flex items-baseline gap-1.5 mb-1">
<span class="font-serif text-[34px] font-semibold leading-none tracking-[-0.6px] text-ink">{{ $euro((int) $plan->monthly_price_cents) }}&nbsp;€</span>
@if ($hasMonthly)
<span class="text-[12px] text-ink-3">{{ __('pricing.plans.per_month') }}</span>
@endif
</div>
@if ($hasMonthly && (int) $plan->yearly_price_cents > 0)
<div class="text-[11.5px] text-ink-3 mb-4">
{{ __('pricing.plans.yearly_hint', ['price' => $euro((int) $plan->yearly_price_cents)]) }}
</div>
@else
<div class="mb-4"></div>
@endif
<ul class="space-y-2 mb-6 flex-1 list-none p-0 m-0 text-[12.5px] text-ink-2">
<li class="flex items-baseline gap-2">
<span class="font-mono text-[12px] font-semibold text-ink">{{ $plan->press_release_quota }}</span>
<span>{{ __('pricing.plans.quota', ['count' => $plan->press_release_quota]) }}</span>
</li>
<li class="flex items-baseline gap-2">
@if ($plan->daily_limit !== null)
<span class="font-mono text-[12px] font-semibold text-ink">{{ $plan->daily_limit }}</span>
<span>{{ __('pricing.plans.daily_limit', ['count' => $plan->daily_limit]) }}</span>
@else
<span class="font-mono text-[12px] text-ink-3">∞</span>
<span class="text-ink-3">{{ __('pricing.plans.no_daily_limit') }}</span>
@endif
</li>
<li class="flex items-baseline gap-2 text-ink-3">
<span>{{ __('pricing.plans.included') }}</span>
</li>
</ul>
{{-- TODO: Deep-Link zu Checkout/Registrierung mit Tarif-Vorauswahl,
sobald der Buchungs-Flow (bookings.blade.php) final ist. --}}
<a href="{{ $submitHref }}"
class="inline-flex items-center justify-center gap-1.5 w-full px-4 py-2.5 text-[12.5px] font-semibold rounded-[2px] transition-colors cursor-pointer
{{ $isPopular ? 'bg-brand text-white hover:bg-brand-deep' : 'border border-bg-rule-strong text-ink hover:bg-bg-elev' }}">
{{ __('pricing.plans.cta') }}
<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>
@endforeach
</div>
<p class="text-[12px] text-ink-3 m-0 mt-4 max-w-[680px]">{{ __('pricing.plans.enterprise') }}</p>
@else
<p class="text-[13px] text-ink-3 m-0 mt-6">{{ __('pricing.plans.empty') }}</p>
@endif
</section>
{{-- ============================================================
2) EINZEL-PRESSEMITTEILUNG (Daten: config('billing'))
============================================================ --}}
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 mt-14">
<header class="mb-4">
<div class="eyebrow muted mb-1">{{ __('pricing.single.eyebrow') }}</div>
<h2 class="font-serif text-[28px] font-semibold m-0 tracking-[-0.3px] text-ink">{{ __('pricing.single.title') }}</h2>
</header>
<hr class="rule-strong">
<div class="bg-bg-elev border border-bg-rule p-6 sm:p-8 grid gap-6 md:grid-cols-[1fr_auto] md:items-center">
<p class="text-[13.5px] leading-[1.6] text-ink-2 m-0 max-w-[560px]">
{{ __('pricing.single.description') }}
</p>
<div class="flex items-center gap-6 md:flex-col md:items-end md:gap-3">
<div class="md:text-right">
<div class="font-serif text-[34px] font-semibold leading-none tracking-[-0.6px] text-ink">{{ $euro($singlePmPriceCents) }}&nbsp;€</div>
<div class="text-[11.5px] text-ink-3 mt-1">{{ __('pricing.single.price_suffix') }} · {{ __('pricing.single.net') }}</div>
</div>
<a href="{{ $submitHref }}"
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 cursor-pointer whitespace-nowrap">
{{ __('pricing.single.cta') }}
<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>
</div>
</section>
{{-- ============================================================
3) ADD-ONS & EINZELKOSTEN (Daten: config('credits'))
Spiegelt die In-App-Buchungsseite (bookings.blade.php), die noch
überarbeitet wird — daher Lineup/Preise hier als „teilweise final".
============================================================ --}}
<section class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 mt-14">
<header class="flex items-baseline justify-between mb-4 flex-wrap gap-3">
<div>
<div class="eyebrow muted mb-1">{{ __('pricing.addons.eyebrow') }}</div>
<h2 class="font-serif text-[28px] font-semibold m-0 tracking-[-0.3px] text-ink">{{ __('pricing.addons.title') }}</h2>
</div>
<p class="text-[12.5px] text-ink-3 m-0 max-w-[420px]">{{ __('pricing.addons.subtitle') }}</p>
</header>
<hr class="rule-strong">
<div class="grid gap-px bg-bg-rule border border-bg-rule grid-cols-1 md:grid-cols-2">
{{-- Extra-PM (tier-gestaffelt) --}}
<div class="bg-bg p-6">
<h3 class="text-[15px] font-semibold text-ink m-0">{{ __('pricing.addons.extra_pm.title') }}</h3>
<p class="text-[12.5px] leading-[1.5] text-ink-2 mt-1 mb-4">{{ __('pricing.addons.extra_pm.description') }}</p>
<table class="w-full text-[12.5px] border-collapse">
<thead>
<tr class="text-left text-ink-3 border-b border-bg-rule">
<th class="font-medium py-1.5">{{ __('pricing.addons.extra_pm.tier_label') }}</th>
<th class="font-medium py-1.5 text-right">{{ __('pricing.addons.extra_pm.price_label') }}</th>
</tr>
</thead>
<tbody>
@foreach ($extraPm as $row)
<tr class="border-b border-bg-rule last:border-b-0">
<td class="py-1.5 text-ink-2">{{ $row['tier'] }}</td>
<td class="py-1.5 text-right font-mono text-ink">{{ $row['credits'] }} {{ __('pricing.addons.credits_unit') }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
{{-- Boost-Platzierung (nach Dauer) --}}
<div class="bg-bg p-6">
<h3 class="text-[15px] font-semibold text-ink m-0">{{ __('pricing.addons.boost.title') }}</h3>
<p class="text-[12.5px] leading-[1.5] text-ink-2 mt-1 mb-4">{{ __('pricing.addons.boost.description') }}</p>
<ul class="list-none p-0 m-0 divide-y divide-bg-rule">
@foreach ($boost as $row)
<li class="flex items-baseline justify-between py-1.5 text-[12.5px]">
<span class="text-ink-2">{{ __('pricing.addons.boost.days', ['count' => $row['days']]) }}</span>
<span class="font-mono text-ink">{{ $row['credits'] }} {{ __('pricing.addons.credits_unit') }}</span>
</li>
@endforeach
</ul>
</div>
{{-- Veröffentlichungsnachweis-PDF --}}
<div class="bg-bg p-6">
<h3 class="text-[15px] font-semibold text-ink m-0">{{ __('pricing.addons.proof_pdf.title') }}</h3>
<p class="text-[12.5px] leading-[1.5] text-ink-2 mt-1 mb-4">{{ __('pricing.addons.proof_pdf.description') }}</p>
<div class="flex items-baseline gap-2">
<span class="font-serif text-[24px] font-semibold text-ink">{{ $proofPdf }}</span>
<span class="text-[12px] text-ink-3">{{ __('pricing.addons.credits_unit') }} · {{ __('pricing.addons.proof_pdf.unit') }}</span>
</div>
</div>
{{-- Credit-Pakete --}}
<div class="bg-bg p-6">
<h3 class="text-[15px] font-semibold text-ink m-0">{{ __('pricing.addons.packs.title') }}</h3>
<p class="text-[12.5px] leading-[1.5] text-ink-2 mt-1 mb-4">{{ __('pricing.addons.packs.description') }}</p>
<div class="grid grid-cols-2 gap-2">
@foreach ($creditPacks as $pack)
@php $bonus = (int) $pack['credits'] - intdiv((int) $pack['price_cents'], 100); @endphp
<div class="border border-bg-rule bg-bg-elev p-3">
<div class="text-[14px] font-semibold text-ink">{{ __('pricing.addons.packs.credits', ['count' => $pack['credits']]) }}</div>
<div class="text-[11.5px] text-ink-3">{{ $euro((int) $pack['price_cents']) }}&nbsp;€ {{ __('pricing.addons.packs.net') }}</div>
@if ($bonus > 0)
<span class="inline-block mt-1 text-[10px] font-semibold text-gain">{{ __('pricing.addons.packs.bonus', ['count' => $bonus]) }}</span>
@endif
</div>
@endforeach
</div>
</div>
</div>
{{-- Weitere Leistungen — TODO: hängt am Bookings-/Magic-Link-Rework,
Lineup und Preise final abstimmen, sobald die In-App-Seite steht. --}}
<div class="mt-px bg-bg border border-bg-rule border-t-0 p-6">
<div class="eyebrow muted mb-3">{{ __('pricing.addons.more.title') }}</div>
<div class="flex flex-wrap gap-x-8 gap-y-2 text-[12.5px]">
<span class="inline-flex items-baseline gap-2">
<span class="text-ink-2">{{ __('pricing.addons.more.correction') }}</span>
<span class="font-mono text-ink">{{ $morePaths['correction'] }} {{ __('pricing.addons.credits_unit') }}</span>
</span>
<span class="inline-flex items-baseline gap-2">
<span class="text-ink-2">{{ __('pricing.addons.more.update') }}</span>
<span class="font-mono text-ink">{{ $morePaths['update'] }} {{ __('pricing.addons.credits_unit') }}</span>
</span>
<span class="inline-flex items-baseline gap-2">
<span class="text-ink-2">{{ __('pricing.addons.more.depublish') }}</span>
<span class="font-mono text-ink">{{ $morePaths['depublish'] }} {{ __('pricing.addons.credits_unit') }}</span>
</span>
</div>
</div>
<p class="text-[11.5px] text-ink-3 m-0 mt-4 max-w-[680px]">{{ __('pricing.vat_note') }}</p>
</section>
{{-- Abschluss mit vorhandener Editorial-Komponente. --}}
<x-web.newsletter-strip />
</main>
<x-web.site-footer />
@endsection

View file

@ -40,6 +40,8 @@
<x-web.industry-index :industries="($industryIndex ?? collect())->isNotEmpty() ? $industryIndex->toArray() : null" /> <x-web.industry-index :industries="($industryIndex ?? collect())->isNotEmpty() ? $industryIndex->toArray() : null" />
<x-web.pricing-teaser />
<x-web.newsletter-strip /> <x-web.newsletter-strip />
<x-web.quality-summary :stats="$homeStats ?? []" /> <x-web.quality-summary :stats="$homeStats ?? []" />

View file

@ -1,412 +1,131 @@
@extends('web.layouts.web-master') @extends('web.layouts.web-master')
@section('title', 'Über Uns - Business Portal 24') @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') @section('content')
<x-web.static-page
<main class="min-h-screen flex flex-col bg-white dark:bg-zinc-950 transition-colors duration-200"> eyebrow="Über uns"
<!-- Burger Menu Component --> title="Über {{ $brandLabel }}"
<livewire:web.burger-menu /> lead="Wir verbinden Unternehmen mit Medien, Journalisten und Multiplikatoren im deutschsprachigen Raum – als Plattform für redaktionell geprüfte Unternehmenskommunikation."
breadcrumb="Über uns"
<!-- Header Component --> >
<livewire:web.header /> {{-- Kennzahlen --}}
<div class="grid gap-px bg-bg-rule border border-bg-rule grid-cols-2 lg:grid-cols-4">
<!-- Hero Section --> @foreach ($stats as $stat)
<section class="relative overflow-hidden text-white py-20 animate-fade-in" <div class="bg-bg p-6 text-center">
style="background: var(--gradient-hero);"> <div class="font-serif text-[30px] font-semibold tracking-[-0.6px] text-brand leading-none">{{ $stat['value'] }}</div>
<div class="container mx-auto px-4"> <div class="text-[12px] text-ink-3 mt-2">{{ $stat['label'] }}</div>
<div class="max-w-3xl mx-auto text-center">
<h1 class="text-4xl md:text-5xl font-bold mb-6 animate-fade-in-up">
Über Business Portal
</h1>
<p class="text-xl text-white/90 leading-relaxed animate-fade-in-up animation-delay-200">
Seit 2010 verbinden wir Unternehmen mit Medien, Journalisten und Multiplikatoren im deutschsprachigen Raum. Wir sind die führende Plattform für Unternehmenskommunikation und Pressearbeit im DACH-Raum.
</p>
</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>
<!-- Decorative Pattern --> <div class="pm-body">
<div class="absolute top-0 right-0 opacity-10"> <p>
<svg width="404" height="384" fill="none" viewBox="0 0 404 384"> Wir glauben daran, dass jedes Unternehmen – unabhängig von Größe oder Budget – die Möglichkeit
<defs> haben sollte, seine Geschichte zu erzählen und mit relevanten Zielgruppen zu kommunizieren.
<pattern id="pattern-hero-about" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<rect x="0" y="0" width="4" height="4" fill="currentColor"/>
</pattern>
</defs>
<rect width="404" height="384" fill="url(#pattern-hero-about)"/>
</svg>
</div>
</section>
<!-- Stats Section -->
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200">
<div class="container mx-auto px-4">
<div class="grid grid-cols-2 md:grid-cols-4 gap-8 max-w-4xl mx-auto">
<div class="text-center">
<div class="text-4xl font-bold bg-gradient-to-r from-[var(--color-primary)] to-[var(--color-secondary)] bg-clip-text text-transparent mb-2">
250.000+
</div>
<div class="text-sm text-zinc-600 dark:text-zinc-400">Veröffentlichte Meldungen</div>
</div>
<div class="text-center">
<div class="text-4xl font-bold bg-gradient-to-r from-[var(--color-primary)] to-[var(--color-secondary)] bg-clip-text text-transparent mb-2">
15.000+
</div>
<div class="text-sm text-zinc-600 dark:text-zinc-400">Registrierte Unternehmen</div>
</div>
<div class="text-center">
<div class="text-4xl font-bold bg-gradient-to-r from-[var(--color-primary)] to-[var(--color-secondary)] bg-clip-text text-transparent mb-2">
2,5 Mio.
</div>
<div class="text-sm text-zinc-600 dark:text-zinc-400">Monatliche Leser</div>
</div>
<div class="text-center">
<div class="text-4xl font-bold bg-gradient-to-r from-[var(--color-primary)] to-[var(--color-secondary)] bg-clip-text text-transparent mb-2">
40+
</div>
<div class="text-sm text-zinc-600 dark:text-zinc-400">Länder</div>
</div>
</div>
</div>
</section>
<!-- Mission Section -->
<section class="py-16 bg-zinc-50/50 dark:bg-zinc-900/50 transition-colors duration-200">
<div class="container mx-auto px-4">
<div class="max-w-4xl mx-auto">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">
Unsere Mission
</h2>
<p class="text-lg text-zinc-600 dark:text-zinc-400">
Professionelle Unternehmenskommunikation für alle zugänglich machen
</p>
</div>
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-8 md:p-12 transition-colors duration-200">
<p class="text-lg text-zinc-900 dark:text-zinc-100 leading-relaxed mb-6">
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 class="text-lg text-zinc-900 dark:text-zinc-100 leading-relaxed">
Business Portal demokratisiert professionelle PR-Arbeit durch innovative Technologie, faire Preismodelle und exzellenten Service. Wir schaffen Sichtbarkeit für wichtige Unternehmensnachrichten und verbinden Organisationen mit den Menschen, die ihre Botschaften lesen und teilen möchten.
</p>
</div>
</div>
</div>
</section>
<!-- Values Section -->
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200">
<div class="container mx-auto px-4">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">
Unsere Werte
</h2>
<p class="text-zinc-600 dark:text-zinc-400 max-w-2xl mx-auto">
Diese Prinzipien leiten uns in allem, was wir tun
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 max-w-6xl mx-auto">
<!-- Value 1 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 text-center hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mx-auto mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
Qualität vor Quantität
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Wir setzen auf redaktionelle Qualität und kuratieren Inhalte sorgfältig, um höchste Standards zu gewährleisten.
</p>
</div>
<!-- Value 2 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 text-center hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mx-auto mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
DACH-Expertise
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Spezialisiert auf den deutschsprachigen Raum mit tiefem Verständnis für regionale Besonderheiten.
</p>
</div>
<!-- Value 3 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 text-center hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mx-auto mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
Kundenfokus
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Ihre Zufriedenheit steht im Mittelpunkt. Wir bieten persönlichen Support und maßgeschneiderte Lösungen.
</p>
</div>
<!-- Value 4 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 text-center hover:shadow-lg transition-all">
<div class="w-16 h-16 bg-gradient-to-br from-[var(--color-primary)]/10 to-[var(--color-secondary)]/10 rounded-full flex items-center justify-center mx-auto mb-4">
<svg class="h-8 w-8 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-3">
Innovation & Technologie
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Kontinuierliche Weiterentwicklung unserer Plattform mit modernsten Technologien und Features.
</p>
</div>
</div>
</div>
</section>
<!-- Team Section -->
<section class="py-16 bg-zinc-50/50 dark:bg-zinc-900/50 transition-colors duration-200">
<div class="container mx-auto px-4">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">
Unser Team
</h2>
<p class="text-zinc-600 dark:text-zinc-400 max-w-2xl mx-auto">
Erfahrene Experten aus PR, Technologie und Medien
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 max-w-6xl mx-auto">
<!-- Team Member 1 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 text-center hover:shadow-lg transition-all">
<div class="w-24 h-24 bg-gradient-to-br from-[var(--color-primary)]/20 to-[var(--color-secondary)]/20 rounded-full flex items-center justify-center mx-auto mb-4">
<svg class="h-12 w-12 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-1">
Dr. Michael Weber
</h3>
<p class="text-sm text-[var(--color-primary)] mb-3">Gründer & CEO</p>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
15+ Jahre Erfahrung in PR und Unternehmenskommunikation
</p>
</div>
<!-- Team Member 2 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 text-center hover:shadow-lg transition-all">
<div class="w-24 h-24 bg-gradient-to-br from-[var(--color-primary)]/20 to-[var(--color-secondary)]/20 rounded-full flex items-center justify-center mx-auto mb-4">
<svg class="h-12 w-12 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-1">
Sarah Hoffmann
</h3>
<p class="text-sm text-[var(--color-primary)] mb-3">Chief Technology Officer</p>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Expertin für digitale Plattformen und Skalierung
</p>
</div>
<!-- Team Member 3 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 text-center hover:shadow-lg transition-all">
<div class="w-24 h-24 bg-gradient-to-br from-[var(--color-primary)]/20 to-[var(--color-secondary)]/20 rounded-full flex items-center justify-center mx-auto mb-4">
<svg class="h-12 w-12 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-1">
Thomas Schneider
</h3>
<p class="text-sm text-[var(--color-primary)] mb-3">Head of Customer Success</p>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Spezialist für Kundenzufriedenheit und Account Management
</p>
</div>
<!-- Team Member 4 -->
<div class="bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 p-6 text-center hover:shadow-lg transition-all">
<div class="w-24 h-24 bg-gradient-to-br from-[var(--color-primary)]/20 to-[var(--color-secondary)]/20 rounded-full flex items-center justify-center mx-auto mb-4">
<svg class="h-12 w-12 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path>
</svg>
</div>
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-1">
Lisa Müller
</h3>
<p class="text-sm text-[var(--color-primary)] mb-3">Head of Content & Quality</p>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Journalistin mit Schwerpunkt digitale Medien
</p>
</div>
</div>
</div>
</section>
<!-- Timeline Section -->
<section class="py-16 bg-white dark:bg-zinc-950 transition-colors duration-200">
<div class="container mx-auto px-4 max-w-4xl">
<div class="text-center mb-12">
<h2 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100 mb-4">
Unsere Geschichte
</h2>
</div>
<div class="space-y-8">
<!-- Milestone 1 -->
<div class="flex gap-6">
<div class="flex flex-col items-center">
<div class="w-12 h-12 rounded-full flex items-center justify-center text-white font-bold flex-shrink-0" style="background: var(--gradient-hero);">
10
</div>
<div class="w-0.5 h-16 bg-gradient-to-b from-[var(--color-primary)] to-[var(--color-secondary)] mt-2"></div>
</div>
<div class="pb-8">
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Gründung
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Start als kleines Start-up mit der Vision, PR zu demokratisieren
</p>
</div>
</div>
<!-- Milestone 2 -->
<div class="flex gap-6">
<div class="flex flex-col items-center">
<div class="w-12 h-12 rounded-full flex items-center justify-center text-white font-bold flex-shrink-0" style="background: var(--gradient-hero);">
13
</div>
<div class="w-0.5 h-16 bg-gradient-to-b from-[var(--color-primary)] to-[var(--color-secondary)] mt-2"></div>
</div>
<div class="pb-8">
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Expansion
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Erreichen von 1.000 registrierten Unternehmen
</p>
</div>
</div>
<!-- Milestone 3 -->
<div class="flex gap-6">
<div class="flex flex-col items-center">
<div class="w-12 h-12 rounded-full flex items-center justify-center text-white font-bold flex-shrink-0" style="background: var(--gradient-hero);">
16
</div>
<div class="w-0.5 h-16 bg-gradient-to-b from-[var(--color-primary)] to-[var(--color-secondary)] mt-2"></div>
</div>
<div class="pb-8">
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Wachstum
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Launch der Premium-Features und Enterprise-Lösungen
</p>
</div>
</div>
<!-- Milestone 4 -->
<div class="flex gap-6">
<div class="flex flex-col items-center">
<div class="w-12 h-12 rounded-full flex items-center justify-center text-white font-bold flex-shrink-0" style="background: var(--gradient-hero);">
19
</div>
<div class="w-0.5 h-16 bg-gradient-to-b from-[var(--color-primary)] to-[var(--color-secondary)] mt-2"></div>
</div>
<div class="pb-8">
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Innovation
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Einführung KI-gestützter Reichweiten-Analytics
</p>
</div>
</div>
<!-- Milestone 5 -->
<div class="flex gap-6">
<div class="flex flex-col items-center">
<div class="w-12 h-12 rounded-full flex items-center justify-center text-white font-bold flex-shrink-0" style="background: var(--gradient-hero);">
22
</div>
<div class="w-0.5 h-16 bg-gradient-to-b from-[var(--color-primary)] to-[var(--color-secondary)] mt-2"></div>
</div>
<div class="pb-8">
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Marktführer
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Über 10.000 aktive Unternehmenskunden im DACH-Raum
</p>
</div>
</div>
<!-- Milestone 6 -->
<div class="flex gap-6">
<div class="flex flex-col items-center">
<div class="w-12 h-12 rounded-full flex items-center justify-center text-white font-bold flex-shrink-0" style="background: var(--gradient-hero);">
25
</div>
</div>
<div class="pb-8">
<h3 class="font-semibold text-zinc-900 dark:text-zinc-100 mb-2">
Zukunft
</h3>
<p class="text-sm text-zinc-600 dark:text-zinc-400">
Internationalisierung und neue AI-Features
</p>
</div>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="py-16 text-white" style="background: var(--gradient-hero);">
<div class="container mx-auto px-4 text-center">
<div class="flex justify-center mb-6">
<svg class="h-16 w-16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"></path>
</svg>
</div>
<h2 class="text-3xl font-bold mb-4">
Werden Sie Teil unserer Success Story
</h2>
<p class="text-xl text-white/90 mb-8 max-w-2xl mx-auto">
Über 15.000 Unternehmen vertrauen bereits auf Business Portal
</p> </p>
<a href="/register" class="inline-flex items-center justify-center px-8 py-4 text-sm font-medium bg-white text-[var(--color-primary)] hover:bg-zinc-100 rounded-lg shadow-md hover:shadow-lg transition-all"> <p>
Jetzt kostenlos starten {{ $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> </a>
</div> </div>
</section> </div>
</x-web.static-page>
<!-- Footer Component -->
<livewire:web.footer />
</main>
@endsection @endsection
@push('styles')
<style>
/* Domain-spezifische Color-Variablen für Inline-Styles */
:root {
--color-primary: {{ $domainConfig['color_scheme']['primary'] ?? '#cf3628' }};
--color-secondary: {{ $domainConfig['color_scheme']['secondary'] ?? '#f0834a' }};
}
/* Alpine.js Cloak */
[x-cloak] {
display: none !important;
}
</style>
@endpush

View file

@ -2,10 +2,12 @@
use App\Enums\Portal; use App\Enums\Portal;
use App\Enums\PressReleaseStatus; use App\Enums\PressReleaseStatus;
use App\Enums\Tier;
use App\Http\Controllers\PressReleasePreviewController; use App\Http\Controllers\PressReleasePreviewController;
use App\Http\Middleware\SetEdition; use App\Http\Middleware\SetEdition;
use App\Models\Category; use App\Models\Category;
use App\Models\Company; use App\Models\Company;
use App\Models\Plan;
use App\Models\PressRelease; use App\Models\PressRelease;
use App\Scopes\PortalScope; use App\Scopes\PortalScope;
use App\Support\DomainAssetContext; use App\Support\DomainAssetContext;
@ -643,6 +645,47 @@ $veroeffentlichenPage = static function (string $edition) use ($applyWebDomainCo
]); ]);
}; };
// Preise-/Tarifseite je Ausgabe: Abos (Plan-Modell), Einzel-PM (config/billing)
// und Add-on-Einzelkosten (config/credits). Inhalte liegen in lang/*/pricing.php.
$preisePage = static function (string $edition) use ($applyWebDomainConfig) {
$domain = request()->getHost();
$domainKey = str_contains($domain, 'presseecho') ? 'presseecho' : 'businessportal24';
$applyWebDomainConfig($domainKey);
// Add-on-Einzelkosten aus der Credit-Ökonomie (1 Credit = 1 €).
$extraPm = collect(config('credits.extra_pm', []))
->map(static fn (int $credits, string $tier): array => [
'tier' => Tier::tryFrom($tier)?->label() ?? ucfirst($tier),
'credits' => $credits,
])
->values()
->all();
$boost = collect(config('credits.boost', []))
->map(static fn (int $credits, int|string $days): array => [
'days' => (int) $days,
'credits' => $credits,
])
->values()
->all();
return view('web.preise', [
'plans' => Plan::query()->active()->get(),
'singlePmPriceCents' => (int) config('billing.single_pm_price_cents'),
'extraPm' => $extraPm,
'boost' => $boost,
'proofPdf' => (int) config('credits.proof_pdf'),
'creditPacks' => config('credits.packs', []),
// TODO: Lineup/Preise hängen am Bookings-/Magic-Link-Rework — final abstimmen.
'morePaths' => [
'correction' => (int) config('credits.paths.correction'),
'update' => (int) config('credits.paths.update'),
'depublish' => (int) config('credits.depublish'),
],
]);
};
// Archiv-Suchseite je Ausgabe (interaktive Suche läuft in der Volt-Komponente). // Archiv-Suchseite je Ausgabe (interaktive Suche läuft in der Volt-Komponente).
$suchePage = static function (string $edition) use ($applyWebDomainConfig) { $suchePage = static function (string $edition) use ($applyWebDomainConfig) {
$domain = request()->getHost(); $domain = request()->getHost();
@ -676,6 +719,195 @@ $suchePage = static function (string $edition) use ($applyWebDomainConfig) {
]); ]);
}; };
// Newsrooms-Verzeichnis je Ausgabe: alle aktiven Unternehmen mit Meldungen.
$newsroomsIndex = static function (string $edition) use ($applyWebDomainConfig) {
$domain = request()->getHost();
$language = app()->getLocale();
[$domainKey, $portal] = match (true) {
str_contains($domain, 'presseecho') => ['presseecho', Portal::Presseecho],
default => ['businessportal24', Portal::Businessportal24],
};
$applyWebDomainConfig($domainKey);
$portalValues = [$portal->value, Portal::Both->value];
$referenceNow = EditorialClock::reference($portalValues, $language);
$recentSince = $referenceNow->copy()->subDays(30);
$term = trim((string) request('q', ''));
$published = static function (Builder $query) use ($portalValues, $language): void {
$query
->whereIn('portal', $portalValues)
->where('status', PressReleaseStatus::Published)
->where('language', $language)
->whereNotNull('published_at')
->where('published_at', '<=', now());
};
$activeCompanies = static fn (): Builder => Company::query()
->withoutGlobalScope(PortalScope::class)
->whereIn('portal', $portalValues)
->where('is_active', true)
->whereHas('pressReleases', fn (Builder $query) => $published($query));
$newsrooms = $activeCompanies()
->when($term !== '', fn (Builder $query) => $query->whereLike('name', '%'.$term.'%'))
->withCount([
'pressReleases as releases_count' => fn (Builder $query) => $published($query),
'pressReleases as recent_count' => function (Builder $query) use ($published, $recentSince): void {
$published($query);
$query->where('published_at', '>=', $recentSince);
},
])
->withMax(['pressReleases as latest_published_at' => fn (Builder $query) => $published($query)], 'published_at')
->orderByDesc('recent_count')
->orderByDesc('releases_count')
->orderBy('name')
->paginate(24)
->withQueryString();
$archiveTotal = PressRelease::query()
->withoutGlobalScope(PortalScope::class)
->tap(fn (Builder $query) => $published($query))
->count();
return view('web.newsrooms', [
'newsrooms' => $newsrooms,
'term' => $term,
'referenceNow' => $referenceNow,
'totalNewsrooms' => (clone $activeCompanies())->count(),
'activeNewsroomsCount' => $activeCompanies()
->whereHas('pressReleases', function (Builder $query) use ($published, $recentSince): void {
$published($query);
$query->where('published_at', '>=', $recentSince);
})
->count(),
'archiveTotal' => $archiveTotal,
]);
};
// Newsroom-Markenseite eines Unternehmens je Ausgabe: alle Meldungen der Firma.
$newsroomDetail = static function (string $edition, string $slug) use ($applyWebDomainConfig) {
$domain = request()->getHost();
$language = app()->getLocale();
[$domainKey, $portal] = match (true) {
str_contains($domain, 'presseecho') => ['presseecho', Portal::Presseecho],
default => ['businessportal24', Portal::Businessportal24],
};
$applyWebDomainConfig($domainKey);
$portalValues = [$portal->value, Portal::Both->value];
$company = Company::query()
->withoutGlobalScope(PortalScope::class)
->whereIn('portal', $portalValues)
->where('is_active', true)
->where('slug', $slug)
->with(['contacts'])
->first();
if (! $company) {
abort(404);
}
$base = static fn (): Builder => PressRelease::query()
->withoutGlobalScope(PortalScope::class)
->where('company_id', $company->id)
->whereIn('portal', $portalValues)
->where('status', PressReleaseStatus::Published)
->where('language', $language)
->whereNotNull('published_at')
->where('published_at', '<=', now());
// Keine öffentliche Newsroom-Seite ohne veröffentlichte Meldung.
if (! $base()->exists()) {
abort(404);
}
$latest = $base()->max('published_at');
$referenceNow = $latest ? Carbon::parse($latest) : now();
if ($referenceNow->gt(now())) {
$referenceNow = now();
}
$recentSince = $referenceNow->copy()->subDays(30);
$oldest = $base()->min('published_at');
$with = [
'company',
'category.translations' => fn ($query) => $query->where('locale', $language),
'images' => fn ($query) => $query->orderByDesc('is_preview')->orderBy('sort_order')->limit(1),
];
$leadRelease = $base()->with($with)->orderByDesc('published_at')->first();
$releases = $base()
->with($with)
->when($leadRelease, fn (Builder $query) => $query->whereKeyNot($leadRelease->getKey()))
->orderByDesc('published_at')
->paginate(10)
->withQueryString();
$mostReadReleases = $base()
->orderByDesc('hits')
->orderByDesc('published_at')
->limit(5)
->get(['id', 'slug', 'title', 'hits', 'portal', 'language']);
$companyFilter = static function (Builder $query) use ($company, $portalValues, $language): void {
$query
->withoutGlobalScope(PortalScope::class)
->where('company_id', $company->id)
->whereIn('portal', $portalValues)
->where('status', PressReleaseStatus::Published)
->where('language', $language)
->whereNotNull('published_at');
};
$categories = Category::query()
->whereIn('portal', $portalValues)
->whereHas('pressReleases', fn (Builder $query) => $companyFilter($query))
->with(['translations' => fn ($query) => $query->where('locale', $language)])
->withCount(['pressReleases as releases_count' => fn (Builder $query) => $companyFilter($query)])
->orderByDesc('releases_count')
->limit(8)
->get()
->map(function (Category $category): ?array {
$translation = $category->translations->first();
if (! $translation) {
return null;
}
return [
'name' => $translation->name,
'href' => $translation->slug ? route('kategorie', ['slug' => $translation->slug]) : route('web.home'),
'count' => (int) ($category->releases_count ?? 0),
];
})
->filter()
->values();
return view('web.newsroom', [
'company' => $company,
'referenceNow' => $referenceNow,
'leadRelease' => $leadRelease,
'releases' => $releases,
'mostReadReleases' => $mostReadReleases,
'categories' => $categories,
'newsroomStats' => [
'total' => $base()->count(),
'recent' => $base()->where('published_at', '>=', $recentSince)->count(),
'today' => $base()->whereDate('published_at', $referenceNow->toDateString())->count(),
'totalHits' => (int) $base()->sum('hits'),
'sinceYear' => $oldest ? (int) Carbon::parse($oldest)->format('Y') : null,
],
]);
};
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Bare Root: Publisher-Hub (pressekonto) oder Redirect auf die Default-Ausgabe. // Bare Root: Publisher-Hub (pressekonto) oder Redirect auf die Default-Ausgabe.
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -696,20 +928,91 @@ Route::get('/', function () use ($applyWebDomainConfig) {
// `category/x.html` nicht als Slug `x.html` in die Kategorie-Route läuft). // `category/x.html` nicht als Slug `x.html` in die Kategorie-Route läuft).
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
$htmlRedirect = static function (string $edition, string $path) { $htmlRedirect = static function (string $edition, string $path) {
$base = request()->getSchemeAndHttpHost();
$clean = trim((string) preg_replace('/\.html$/', '', $path), '/'); $clean = trim((string) preg_replace('/\.html$/', '', $path), '/');
$staticPages = [ // Account/Anmeldung lebt im Publisher-Hub (pressekonto), nicht am Portal.
'preise', 'faq', 'kontakt', 'ueber-uns', 'veroeffentlichen', // Die öffentlichen Spokes haben kein eigenes Login-System (Hub-and-Spoke).
'suche', 'newsrooms', 'api', 'team', 'partner', 'karriere', 'presse', $hubAliases = [
'hilfe', 'impressum', 'datenschutz', 'agb', 'cookies', 'registration' => '/register',
'login' => '/login',
]; ];
if (array_key_exists($clean, $hubAliases)) {
$hubUrl = rtrim((string) config('domains.domain_portal_url'), '/');
return redirect($hubUrl.$hubAliases[$clean], 301);
}
// Entfallene Rubriken-Übersicht -> Startseite der Ausgabe. // Entfallene Rubriken-Übersicht -> Startseite der Ausgabe.
if ($clean === 'kategorien') { if ($clean === 'kategorien') {
return redirect(request()->getSchemeAndHttpHost().'/'.$edition, 301); return redirect($base.'/'.$edition, 301);
} }
if (str_starts_with($clean, 'category/') || str_starts_with($clean, 'press-release/')) { // Ratgeber-Strecke der Altseite (/de/presse/*.html) -> konsolidierte FAQ.
// Hier steckt der SEO-Wert; alle Einzelseiten bündeln wir 301 auf /faq.
if ($clean === 'presse' || str_starts_with($clean, 'presse/')) {
return redirect($base.'/'.$edition.'/faq', 301);
}
// Alte Firmen-Pressemappe (presskit/{id}/{slug}) entspricht dem Newsroom.
// Feinmapping über die Legacy-ID: companies.(legacy_portal, legacy_id) ist
// unique-indiziert, ein Lookup liefert den heutigen Newsroom-Slug. Bei
// gültigem öffentlichem Newsroom 301 direkt dorthin (ein Hop), sonst sauber
// aufs Verzeichnis statt in einen 404.
if (preg_match('#^presskit/(\d+)#', $clean, $presskitMatch) === 1) {
$legacyPortal = str_contains(request()->getHost(), 'presseecho')
? Portal::Presseecho->value
: Portal::Businessportal24->value;
$company = Company::query()
->withoutGlobalScope(PortalScope::class)
->where('legacy_portal', $legacyPortal)
->where('legacy_id', (int) $presskitMatch[1])
->first();
$hasPublicNewsroom = $company
&& $company->is_active
&& $company->pressReleases()
->withoutGlobalScope(PortalScope::class)
->where('status', PressReleaseStatus::Published)
->whereNotNull('published_at')
->where('published_at', '<=', now())
->exists();
return redirect(
$hasPublicNewsroom
? $base.'/'.$edition.'/newsroom/'.$company->slug
: $base.'/'.$edition.'/newsrooms',
301
);
}
// Pressemappen-Pfade ohne numerische ID -> Newsrooms-Verzeichnis.
if ($clean === 'presskit' || str_starts_with($clean, 'presskit/')) {
return redirect($base.'/'.$edition.'/newsrooms', 301);
}
// Legacy-Slugs des Altsystems (meist englisch) -> neue deutsche Pfade.
$staticAliases = [
'pricelist' => 'preise',
'service' => 'veroeffentlichen',
'contact' => 'kontakt',
'imprint' => 'impressum',
'terms' => 'agb',
'privacypolicy' => 'datenschutz',
];
// Bereits saubere Zielpfade der neuen Struktur (Pfad bleibt erhalten).
$staticPages = [
'preise', 'faq', 'kontakt', 'ueber-uns', 'veroeffentlichen',
'suche', 'newsrooms', 'api', 'team', 'partner', 'karriere',
'hilfe', 'impressum', 'datenschutz', 'agb', 'cookies',
];
if (isset($staticAliases[$clean])) {
$target = $staticAliases[$clean];
} elseif (str_starts_with($clean, 'category/') || str_starts_with($clean, 'press-release/')) {
$target = $clean; $target = $clean;
} elseif ($clean === '' || str_contains($clean, '/')) { } elseif ($clean === '' || str_contains($clean, '/')) {
$target = $clean; $target = $clean;
@ -720,9 +1023,24 @@ $htmlRedirect = static function (string $edition, string $path) {
$target = 'press-release/'.$clean; $target = 'press-release/'.$clean;
} }
return redirect(request()->getSchemeAndHttpHost().rtrim('/'.$edition.'/'.$target, '/'), 301); return redirect(rtrim($base.'/'.$edition.'/'.$target, '/'), 301);
}; };
// ---------------------------------------------------------------------------
// Entfallene Sprach-/Regionsvarianten (de-ch, de-at) -> deutsche Ausgabe.
// Die echten Regionen-Übersichten (/region/{slug}) sind für einen späteren
// Schritt geplant; bis dahin verhindern diese 301 tote Bestands-Links.
// ---------------------------------------------------------------------------
$legacyRegions = ['de-ch', 'de-at'];
Route::get('{region}', function (string $region) {
return redirect(request()->getSchemeAndHttpHost().'/'.SetEdition::DEFAULT_EDITION, 301);
})->whereIn('region', $legacyRegions);
Route::get('{region}/{path}', function (string $region, string $path) {
return redirect(request()->getSchemeAndHttpHost().'/'.SetEdition::DEFAULT_EDITION, 301);
})->whereIn('region', $legacyRegions)->where('path', '.*');
Route::get('{edition}/{path}', function (string $edition, string $path) use ($htmlRedirect) { Route::get('{edition}/{path}', function (string $edition, string $path) use ($htmlRedirect) {
return $htmlRedirect($edition, $path); return $htmlRedirect($edition, $path);
})->where('path', '.*\.html')->whereIn('edition', SetEdition::EDITIONS); })->where('path', '.*\.html')->whereIn('edition', SetEdition::EDITIONS);
@ -735,7 +1053,7 @@ Route::get('{path}', function (string $path) use ($htmlRedirect) {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Öffentliche Inhalte je Ausgabe (Sprache): /de/... und /en/... // Öffentliche Inhalte je Ausgabe (Sprache): /de/... und /en/...
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
Route::prefix('{edition}')->whereIn('edition', SetEdition::EDITIONS)->group(function () use ($applyWebDomainConfig, $webHomeData, $categoryPage, $releaseDetailPage, $veroeffentlichenPage, $suchePage) { Route::prefix('{edition}')->whereIn('edition', SetEdition::EDITIONS)->group(function () use ($applyWebDomainConfig, $webHomeData, $categoryPage, $releaseDetailPage, $veroeffentlichenPage, $suchePage, $newsroomsIndex, $newsroomDetail, $preisePage) {
// Startseite je Ausgabe // Startseite je Ausgabe
Route::get('/', function (string $edition) use ($applyWebDomainConfig, $webHomeData) { Route::get('/', function (string $edition) use ($applyWebDomainConfig, $webHomeData) {
$domain = request()->getHost(); $domain = request()->getHost();
@ -760,14 +1078,17 @@ Route::prefix('{edition}')->whereIn('edition', SetEdition::EDITIONS)->group(func
// Detailseite einer Pressemitteilung (z.B. /de/press-release/ki-revolution) // Detailseite einer Pressemitteilung (z.B. /de/press-release/ki-revolution)
Route::get('press-release/{slug}', $releaseDetailPage)->name('release.detail'); Route::get('press-release/{slug}', $releaseDetailPage)->name('release.detail');
// Preise / Tarife (datengetrieben: Plan + config/billing + config/credits)
Route::get('preise', $preisePage)->name('preise');
// Statische Seiten // Statische Seiten
Route::view('preise', 'web.preise')->name('preise');
Route::view('faq', 'web.faq')->name('faq'); Route::view('faq', 'web.faq')->name('faq');
Route::view('kontakt', 'web.kontakt')->name('kontakt'); Route::view('kontakt', 'web.kontakt')->name('kontakt');
Route::view('ueber-uns', 'web.ueber-uns')->name('ueber-uns'); Route::view('ueber-uns', 'web.ueber-uns')->name('ueber-uns');
Route::get('veroeffentlichen', $veroeffentlichenPage)->name('veroeffentlichen'); Route::get('veroeffentlichen', $veroeffentlichenPage)->name('veroeffentlichen');
Route::get('suche', $suchePage)->name('suche'); Route::get('suche', $suchePage)->name('suche');
Route::view('newsrooms', 'web.newsrooms')->name('newsrooms'); Route::get('newsrooms', $newsroomsIndex)->name('newsrooms');
Route::get('newsroom/{slug}', $newsroomDetail)->name('newsroom');
Route::view('api', 'web.api')->name('api'); Route::view('api', 'web.api')->name('api');
Route::view('team', 'web.team')->name('team'); Route::view('team', 'web.team')->name('team');
Route::view('partner', 'web.partner')->name('partner'); Route::view('partner', 'web.partner')->name('partner');

View file

@ -0,0 +1,114 @@
<?php
use App\Enums\Portal;
use App\Models\Company;
use App\Models\PressRelease;
use Tests\TestCase;
/**
* Bestandsschutz für die URL-Struktur der Altseite: jede Alt-URL muss per 301
* sauber auf ihr neues Pendant zeigen, damit kein SEO-Wert verloren geht.
*
* @see docs/frontend/Struktur Frontend.md
*/
test('legacy static slugs of the old site redirect to the new german paths', function (string $legacy, string $target) {
/** @var TestCase $this */
$this->get('https://businessportal24.test/de/'.$legacy)
->assertStatus(301)
->assertRedirect('https://businessportal24.test/de/'.$target);
})->with([
'pricelist -> preise' => ['pricelist.html', 'preise'],
'service -> veroeffentlichen' => ['service.html', 'veroeffentlichen'],
'contact -> kontakt' => ['contact.html', 'kontakt'],
'imprint -> impressum' => ['imprint.html', 'impressum'],
'terms -> agb' => ['terms.html', 'agb'],
'privacypolicy -> datenschutz' => ['privacypolicy.html', 'datenschutz'],
]);
test('legacy account urls redirect to the publisher hub', function (string $legacy, string $hubPath) {
/** @var TestCase $this */
$hubUrl = rtrim((string) config('domains.domain_portal_url'), '/');
$this->get('https://businessportal24.test/de/'.$legacy)
->assertStatus(301)
->assertRedirect($hubUrl.$hubPath);
})->with([
'registration -> register' => ['registration.html', '/register'],
'login -> login' => ['login.html', '/login'],
]);
test('legacy press guide pages collapse into the faq', function (string $legacy) {
/** @var TestCase $this */
$this->get('https://businessportal24.test/de/'.$legacy)
->assertStatus(301)
->assertRedirect('https://businessportal24.test/de/faq');
})->with([
'overview' => ['presse.html'],
'pressemitteilung-schreiben' => ['presse/pressemitteilung-schreiben.html'],
'pressemitteilung-aufbau' => ['presse/pressemitteilung-aufbau.html'],
'presseausweis' => ['presse/presseausweis.html'],
]);
test('legacy presskit urls map to the new newsroom via the legacy id', function () {
/** @var TestCase $this */
$company = Company::factory()->businessportal24()->create([
'name' => 'Acme GmbH',
'slug' => 'acme-gmbh-neu',
'is_active' => true,
'legacy_portal' => Portal::Businessportal24->value,
'legacy_id' => 512,
]);
PressRelease::factory()
->published()
->forPortal(Portal::Businessportal24)
->for($company)
->create(['published_at' => now()->subDay()]);
// Alt-Slug ist egal – die Legacy-ID bestimmt das Ziel (heutiger Slug).
$this->get('https://businessportal24.test/de/presskit/512/irgendein-alt-slug.html')
->assertStatus(301)
->assertRedirect('https://businessportal24.test/de/newsroom/acme-gmbh-neu');
});
test('legacy presskit urls fall back to the directory without a public newsroom', function () {
/** @var TestCase $this */
// Unbekannte ID.
$this->get('https://businessportal24.test/de/presskit/99999/unbekannt.html')
->assertStatus(301)
->assertRedirect('https://businessportal24.test/de/newsrooms');
// Firma ohne veröffentlichte Meldung -> kein öffentlicher Newsroom.
Company::factory()->businessportal24()->create([
'is_active' => true,
'legacy_portal' => Portal::Businessportal24->value,
'legacy_id' => 777,
]);
$this->get('https://businessportal24.test/de/presskit/777/leer.html')
->assertStatus(301)
->assertRedirect('https://businessportal24.test/de/newsrooms');
});
test('dropped language/region variants redirect to the default edition', function (string $path) {
/** @var TestCase $this */
$this->get('https://businessportal24.test/'.$path)
->assertStatus(301)
->assertRedirect('https://businessportal24.test/de');
})->with([
'de-ch root' => ['de-ch'],
'de-at root' => ['de-at'],
'de-ch subpath' => ['de-ch/category/finanzen.html'],
'de-at subpath' => ['de-at/login.html'],
]);
test('legacy aliases also work without an edition prefix', function () {
/** @var TestCase $this */
$this->get('https://businessportal24.test/contact.html')
->assertStatus(301)
->assertRedirect('https://businessportal24.test/de/kontakt');
$this->get('https://businessportal24.test/imprint.html')
->assertStatus(301)
->assertRedirect('https://businessportal24.test/de/impressum');
});

View file

@ -0,0 +1,22 @@
<?php
use Tests\TestCase;
test('header and footer link to faq, hilfe and cookies and drop dead links', function () {
/** @var TestCase $this */
$response = $this->get('https://businessportal24.test/de');
$response->assertSuccessful()
// Neu verlinkt (FAQ im Header + Footer, Hilfe + Cookies im Footer).
->assertSee('/de/faq', false)
->assertSee('/de/hilfe', false)
->assertSee('/de/cookies', false)
// „Anmelden" führt jetzt in den Hub statt auf einen toten Anker.
->assertSee('/login', false)
->assertDontSee('href="#newsletter"', false)
->assertDontSee('href="#rss"', false)
->assertDontSee('href="#anmelden"', false)
// Nicht verlinkte Platzhalter-Punkte wurden entfernt.
->assertDontSee('Mediendaten')
->assertDontSee('Verifizierter Newsroom');
});

View file

@ -0,0 +1,116 @@
<?php
use App\Enums\Portal;
use App\Models\Category;
use App\Models\Company;
use App\Models\PressRelease;
use Illuminate\Support\Str;
use Tests\TestCase;
function makeNewsroom(string $name, Portal $portal = Portal::Businessportal24, array $attributes = []): Company
{
return Company::factory()
->state(['portal' => $portal->value])
->create(array_merge([
'name' => $name,
'slug' => Str::slug($name).'-'.fake()->unique()->numberBetween(1000, 9999),
'is_active' => true,
], $attributes));
}
function publishForCompany(Company $company, string $title, array $attributes = [], ?Category $category = null): PressRelease
{
$category ??= Category::factory()->create(['portal' => Portal::Both]);
return PressRelease::factory()
->published()
->forPortal(Portal::Businessportal24)
->for($category)
->for($company)
->create(array_merge([
'title' => $title,
'slug' => Str::slug($title).'-'.fake()->unique()->numberBetween(1000, 9999),
'language' => 'de',
'published_at' => now()->subDay(),
], $attributes));
}
test('the newsrooms index renders the editorial shell and lists active newsrooms', function () {
/** @var TestCase $this */
$company = makeNewsroom('Nordwind Energie AG');
publishForCompany($company, 'Nordwind nimmt neuen Windpark in Betrieb');
$this->get('https://businessportal24.test/de/newsrooms')
->assertSuccessful()
->assertSee('businessportal', false)
->assertSeeText('Newsrooms')
->assertSeeText('Nordwind Energie AG');
});
test('the newsrooms index filters by company name', function () {
/** @var TestCase $this */
$match = makeNewsroom('Solartec Industries GmbH');
publishForCompany($match, 'Solartec meldet Rekordquartal');
$other = makeNewsroom('Hafenlogistik Bremen AG');
publishForCompany($other, 'Hafenlogistik baut Terminal aus');
$this->get('https://businessportal24.test/de/newsrooms?q=Solartec')
->assertSuccessful()
->assertSeeText('Solartec Industries GmbH')
->assertDontSeeText('Hafenlogistik Bremen AG');
});
test('the newsrooms index excludes companies without published releases', function () {
/** @var TestCase $this */
makeNewsroom('Stilles Unternehmen AG');
$this->get('https://businessportal24.test/de/newsrooms')
->assertSuccessful()
->assertDontSeeText('Stilles Unternehmen AG');
});
test('the newsroom detail page renders company data and its releases', function () {
/** @var TestCase $this */
$company = makeNewsroom('Bavaria Maschinenbau AG', attributes: [
'boilerplate' => 'Bavaria Maschinenbau ist ein führender Anbieter von Industrielösungen.',
]);
publishForCompany($company, 'Bavaria präsentiert neue Produktionslinie');
$this->get('https://businessportal24.test/de/newsroom/'.$company->slug)
->assertSuccessful()
->assertSeeText('Bavaria Maschinenbau AG')
->assertSeeText('Bavaria präsentiert neue Produktionslinie')
->assertSeeText('Alle Meldungen');
});
test('the newsroom detail page returns 404 for an unknown slug', function () {
/** @var TestCase $this */
$this->get('https://businessportal24.test/de/newsroom/gibt-es-nicht')
->assertNotFound();
});
test('the newsroom detail page returns 404 when the company has no published releases', function () {
/** @var TestCase $this */
$company = makeNewsroom('Leeres Newsroom AG');
$this->get('https://businessportal24.test/de/newsroom/'.$company->slug)
->assertNotFound();
});
test('the newsrooms pages are available per edition and portal', function () {
/** @var TestCase $this */
$this->get('https://businessportal24.test/en/newsrooms')->assertSuccessful();
$this->get('https://presseecho.test/de/newsrooms')
->assertSuccessful()
->assertSee('presse', false);
});
test('legacy newsroom html urls redirect to the clean edition path', function () {
/** @var TestCase $this */
$this->get('https://businessportal24.test/de/newsrooms.html')
->assertRedirect('https://businessportal24.test/de/newsrooms');
$this->get('https://businessportal24.test/de/newsroom/acme.html')
->assertRedirect('https://businessportal24.test/de/newsroom/acme');
});

View file

@ -0,0 +1,57 @@
<?php
use App\Models\Plan;
use Database\Seeders\PlanSeeder;
use Tests\TestCase;
test('the pricing page renders the editorial shell with real plans, single pm and add-ons', function () {
/** @var TestCase $this */
$this->seed(PlanSeeder::class);
$this->get('https://businessportal24.test/de/preise')
->assertSuccessful()
// Editorial-Masthead (Inhalte aus lang/de/pricing.php)
->assertSeeText('Transparente Preise für jede Reichweite')
// 1) Abo-Tarife (echte Pläne aus dem System)
->assertSeeText('Abo-Tarife mit Monatskontingent')
->assertSeeText('Starter')
->assertSeeText('Business')
->assertSeeText('Pro')
->assertSeeText('Agency')
// 2) Einzel-Pressemitteilung (config/billing)
->assertSeeText('Einzel-Pressemitteilung')
->assertSeeText('pro Veröffentlichung')
// 3) Add-ons (config/credits)
->assertSeeText('Add-ons & Einzelkosten')
->assertSeeText('Extra-Pressemitteilung')
->assertSeeText('Boost-Platzierung')
->assertSeeText('Veröffentlichungsnachweis (PDF)')
->assertSeeText('Credit-Pakete')
->assertSeeText('7 Tage') // boost 7d aus config
->assertSeeText('10 Credits') // Credit-Paket p10 aus config
->assertSeeText('Depublizieren')
->assertSeeText('25 Credits'); // depublish aus config
});
test('the pricing page serves english content on the english edition', function () {
/** @var TestCase $this */
$this->seed(PlanSeeder::class);
$this->get('https://businessportal24.test/en/preise')
->assertSuccessful()
->assertSeeText('Transparent pricing for every reach')
->assertSeeText('Subscriptions with a monthly quota')
->assertSeeText('Single press release')
->assertSeeText('Add-ons & individual costs');
});
test('the pricing page still works and shows an empty hint without plans', function () {
/** @var TestCase $this */
expect(Plan::query()->count())->toBe(0);
$this->get('https://businessportal24.test/de/preise')
->assertSuccessful()
->assertSeeText('Tarife werden in Kürze veröffentlicht.')
// Add-ons sind config-basiert und unabhängig von Tarifen sichtbar.
->assertSeeText('Add-ons & Einzelkosten');
});

View file

@ -0,0 +1,54 @@
<?php
use App\Models\Plan;
use Database\Seeders\PlanSeeder;
use Tests\TestCase;
test('the homepage renders active plans from the system in the pricing teaser', function () {
/** @var TestCase $this */
$this->seed(PlanSeeder::class);
$this->get('https://businessportal24.test/de')
->assertSuccessful()
->assertSeeText('Tarife & Pakete')
->assertSeeText('Starter')
->assertSeeText('Business')
->assertSeeText('Pro')
->assertSeeText('Agency')
// Jahrespreis-Kommunikation und Live-Preis (Agency 199 €).
->assertSeeText('2 Monate gratis')
->assertSee('199')
->assertSeeText('Auswählen')
->assertSeeText('Beliebt');
});
test('the pricing teaser hides inactive plans', function () {
/** @var TestCase $this */
Plan::factory()->create(['name' => 'Sichtbarer Tarif', 'is_active' => true]);
Plan::factory()->inactive()->create(['name' => 'Versteckter Tarif']);
$this->get('https://businessportal24.test/de')
->assertSuccessful()
->assertSeeText('Sichtbarer Tarif')
->assertDontSeeText('Versteckter Tarif');
});
test('the pricing teaser is omitted when no plans exist but the page still works', function () {
/** @var TestCase $this */
expect(Plan::query()->count())->toBe(0);
$this->get('https://businessportal24.test/de')
->assertSuccessful()
->assertDontSeeText('Auswählen');
});
test('the header links to the pricing page on every portal page', function () {
/** @var TestCase $this */
$this->get('https://businessportal24.test/de')
->assertSuccessful()
->assertSee('/de/preise');
$this->get('https://presseecho.test/de')
->assertSuccessful()
->assertSee('/de/preise');
});

View file

@ -0,0 +1,45 @@
<?php
use Tests\TestCase;
dataset('static pages', [
'impressum' => ['de/impressum', 'Impressum'],
'datenschutz' => ['de/datenschutz', 'Datenschutzerklärung'],
'agb' => ['de/agb', 'Allgemeine Geschäftsbedingungen'],
'cookies' => ['de/cookies', 'Cookie-Richtlinien'],
'faq' => ['de/faq', 'Häufig gestellte Fragen'],
'hilfe' => ['de/hilfe', 'Hilfe-Center'],
'kontakt' => ['de/kontakt', 'Kontakt'],
'ueber-uns' => ['de/ueber-uns', 'Über uns'],
'api' => ['de/api', 'API & Integrationen'],
]);
test('static pages render in the editorial design', function (string $path, string $heading) {
/** @var TestCase $this */
$response = $this->get("https://businessportal24.test/{$path}");
$response->assertSuccessful()
->assertSeeText($heading)
// Editorial-Shell (Token aus den neuen Komponenten) statt altem Theme.
->assertSee('bg-bg', false)
// Altes Theme darf nicht mehr gerendert werden.
->assertDontSee('gradient-hero');
})->with('static pages');
test('the faq page lists questions and links to support', function () {
/** @var TestCase $this */
$this->get('https://businessportal24.test/de/faq')
->assertSuccessful()
->assertSeeText('Wie veröffentliche ich meine erste Pressemitteilung?')
->assertSeeText('Frage nicht gefunden?')
->assertSee(route('kontakt'), false);
});
test('the help center shows quick links and topics', function () {
/** @var TestCase $this */
$this->get('https://businessportal24.test/de/hilfe')
->assertSuccessful()
->assertSeeText('Hilfe-Themen')
->assertSee(route('faq'), false)
->assertSee(route('veroeffentlichen'), false);
});