Interior-Feinschliff: Hero-Slideshow, Lektorat, Rechtstexte, Aufräumen und Korrekturen 08.10.

Startseite und Heroes
- Hero-Slideshow (11 Motive inkl. Febrü) mit Infokarte, Laufzeit-Linie, größeren Klickflächen,
  Goldrahmen und mobiler Karte unter dem Bild; Zeile über der Überschrift, neue Vertrauenspunkte
- Hero-Stil auf Marken, Über uns und Kontakt übertragen, Breadcrumb entfernt
- Gründer-Leiste, Vision-Box auf Ocker, Showroom-Display in Box mit „Größer ansehen“/Vollbild
- Akzentfarbe #a8741f, größere Serif-Überschriften in der Interior-Welt
- Marken: Bildpause mit Zitat; Vereine aktualisiert und verlinkt

Inhalte
- Lektorat aller angezeigten Texte, /about-Korrekturen, Rechtstexte (DDG, TDDDG, Hosting Hetzner)
- Ablauf Maßanfertigung überall einheitlich, Magazin-Beitrag neu, alte Beiträge offline,
  deutsches Datum/Lesezeit, FAQ Projektausstattung, Otterpohl
- Referenzen-Seite per CMS-Schalter ausblendbar

CMS und Technik
- Tote Sektionen, Felder, Seiten und Komponenten entfernt und archiviert (dev/2026-08-28/archiv-*)
- Entwurf /entwurf, Farb-Schalter und /welcome entfernt; Test-Routen nur noch lokal
- Seitenbaum-Beschreibungen geprüft, fehlende CMS-Felder ergänzt, Markenliste aus „Kernmarken“
- Admin-Bildvorschauen repariert, verwendete Bilder in die Mediathek übernommen
- Seeder für das Deployment siehe dev/2026-08-28/entwicklungsplan.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-10-08 14:00:15 +00:00
parent 4b07bbdcae
commit fcb10be120
406 changed files with 22549 additions and 3798 deletions

View file

@ -0,0 +1,123 @@
Im Hero auf der Home im Slider bitte noch diese beiden Bilder mit aufnehmen
an pos 4 = dev/2026-08-28/images/februe/Februe_Active-2-0_Bureo_300dpi_HighRes.jpg
an pos 8, bzw 9 =
dev/2026-08-28/images/februe/Februe_Elements-Soul_Grossraum_300dpi_HighRes.jpg
bei der Rubrik „Regional verbunden“ sind aktuell teilweise die falschen Vereine bzw. Bezeichnungen hinterlegt.
Bitte dort die tatsächlich von uns unterstützten Vereine einpflegen:
DSC Arminia Bielefeld
TC Bad Salzuflen
https://www.tcbadsalzuflen.de/
Tennisclub Hiddenhausen von 1973 e. V.
https://tc-hiddenhausen.de/
TC Blau Weiss Halle e. V.
https://www.tcbw-hallewestf.de/Home
Beim TC Hiddenhausen ist auf der aktuellen Seite offenbar schon das richtige Logo eingebaut, darunter steht aber fälschlicherweise „TC Hövelhof“. Das bitte entsprechend korrigieren.
Der aktuell aufgeführte TC Bad Waldliesborn-Horn gehört dort nicht hinein und sollte ersetzt werden.
Die Texte darunter bitte möglichst einheitlich und schlicht halten, z. B.:
TC Bad Salzuflen (logo dev/2026-08-28/sponsoren-logos/TCBadSalzuflen.png)
Tennisclub aus Bad Salzuflen – regional verwurzelt und engagiert im Vereinssport.
TC Hiddenhausen (LOGO dev/2026-08-28/sponsoren-logos/TCH_Logo.png)
Tennisclub aus Hiddenhausen – regional verwurzelt und engagiert im Vereinssport.
TC Blau Weiss Halle (logo dev/2026-08-28/sponsoren-logos/TCBWH_Logo.jpg)
Tennisclub aus Halle (Westfalen) – regional verwurzelt und engagiert im Vereinssport.
Inhlatliche korrekturen
Das sind keine neuen gestalterischen Wünsche, sondern im Wesentlichen inhaltliche Konsistenz und ein paar Texte, die noch aus einer früheren Richtung stammen.
1. Maßanfertigung / Aufmaß – bitte einmal durchgängig angleichen
Auf der CABINET-Seite ist der Ablauf unter „Ein Bild und ein grobes Maß reichen für den Anfang“ eigentlich schon genau richtig beschrieben. Den tatsächlichen Ablauf würde ich aber noch etwas genauer darstellen und bitte dann auch überall auf der Website entsprechend durchziehen:
Foto / Grundriss + grobe Maße → Beratung → Planung & Angebot → Angebotsannahme → Anzahlung → professionelles Aufmaß → Feinplanung / Fertigungsfreigabe → Bestellung / Fertigung
Der für mich wichtige Punkt ist:
Am Anfang reicht das grobe Maß. Am Ende entscheidet der Millimeter.
Der Kunde muss also nicht erst sein Haus millimetergenau vermessen, bevor er zu uns kommen kann. Mit Fotos, einem Grundriss und ungefähren Maßen können wir beraten, planen und bereits ein konkretes Angebot erstellen.
Wenn das Angebot angenommen und die Anzahlung erfolgt ist, übernehmen wir das professionelle Aufmaß vor Ort. Ab diesem Zeitpunkt zählt dann tatsächlich jeder Millimeter, weil dieses Maß die Grundlage für die endgültige Feinplanung, Fertigungsfreigabe und Bestellung bildet.
Das sollte bitte auf allen entsprechenden Seiten und auch in den FAQ einheitlich dargestellt werden.
Auf der CABINET-Seite würde ich bei „Aufmaß vor Ort“ statt „Grundlage jeder Planung“ eher schreiben:
Nach Angebotsannahme und Anzahlung erfolgt das professionelle Aufmaß bei Ihnen vor Ort. Es bildet die Grundlage für die finale Feinplanung und Fertigungsfreigabe.
In den FAQ bei „Wie läuft eine Beratung bei Ihnen ab?“ würde ich schreiben:
Am Anfang steht ein Gespräch – im Showroom, telefonisch oder auf Wunsch bei Ihnen vor Ort. Für eine erste Planung reichen uns in der Regel Fotos, ein Grundriss und grobe Maße. Damit können wir bereits Ideen entwickeln, die Planung konkretisieren und Ihnen ein entsprechendes Angebot erstellen.
Wenn Ihnen die Planung gefällt und Sie unser Angebot annehmen, erfolgt nach der Anzahlung das professionelle Aufmaß bei Ihnen vor Ort. Auf Grundlage dieser exakten Maße erstellen wir die Feinplanung und geben die Möbel anschließend zur Fertigung frei.
Und bei „Was kostet eine Maßanfertigung?“ bitte den Hinweis streichen, dass eine seriöse Zahl erst nach dem Aufmaß möglich sei.
Richtig ist:
Bereits auf Basis von Fotos, Grundriss und groben Maßen können wir eine konkrete Planung und ein entsprechendes Angebot erstellen. Das professionelle Aufmaß erfolgt nach Angebotsannahme und Anzahlung und dient anschließend der finalen Feinplanung und Fertigungsfreigabe.
Natürlich kann sich nach dem Aufmaß im Ausnahmefall noch etwas verändern, wenn sich vor Ort relevante Abweichungen ergeben. Der Kunde soll aber eindeutig verstehen: Für Beratung, Planung und Angebot reichen zunächst grobe Maße. Die millimetergenaue Vermessung übernehmen später wir.
2. Magazinartikel „Warum der Millimeter über den Raum entscheidet“
Hier würde ich den Text bitte komplett austauschen. Damit du da nicht noch einmal formulieren musst, kannst du folgenden Text direkt übernehmen:
Nach Maß statt von der Stange:
Warum am Ende der Millimeter zählt – und am Anfang grobe Maße reichen
Dachschrägen, Nischen, ungewöhnliche Höhen: Wo Standardmöbel an ihre Grenzen kommen, beginnt die Maßanfertigung. Und am Ende entscheiden tatsächlich wenige Millimeter darüber, ob eine Lösung wirklich perfekt in den Raum passt.
Am Anfang müssen Sie diese Millimeter aber noch gar nicht kennen.
Für eine erste Beratung, Planung und ein konkretes Angebot reichen uns in der Regel grobe Raummaße, ein Grundriss oder ein paar Fotos. Damit können wir bereits beurteilen, was sinnvoll machbar ist, erste Ideen entwickeln und Ihre individuelle Lösung planen.
Das exakte Aufmaß kommt später – und ist unsere Aufgabe, nicht Ihre.
Erst die Idee, dann der Millimeter
Niemand muss vor dem ersten Beratungstermin mit dem Lasermessgerät durch die Wohnung laufen.
Für die erste Planung reichen ungefähre Breiten, Höhen und Tiefen vollkommen aus. Gemeinsam entwickeln wir daraus die passende Lösung und klären Materialien, Ausstattung, Gestaltung und Budget.
Auf dieser Grundlage erhalten Sie von uns Ihre Planung und ein entsprechendes Angebot.
Wenn Sie sich für die Lösung entscheiden, das Angebot annehmen und die Anzahlung erfolgt ist, kommt der nächste Schritt: das professionelle Aufmaß bei Ihnen vor Ort.
Denn spätestens jetzt zählt tatsächlich jeder Millimeter.
Wände sind selten vollkommen gerade, Böden nicht immer eben und gerade in älteren Gebäuden können sich Höhen, Winkel und Anschlüsse über einen Raum deutlich verändern.
Diese Abweichungen nehmen wir exakt auf und berücksichtigen sie bei der finalen Feinplanung.
Der Ablauf ist damit bewusst einfach:
Grobe Maße reichen für Beratung und Angebot. Die exakten Maße übernehmen wir nach Auftragserteilung.
Anschließend erfolgt die Fertigungsfreigabe und Ihre individuelle Einrichtung geht in die Bestellung bzw. Fertigung.
Der Raum, den man sonst verschenkt
Der Vorteil einer Maßanfertigung liegt nicht nur in der Optik, sondern vor allem darin, den vorhandenen Raum bestmöglich zu nutzen.
Ein Schrank, der einer Dachschräge exakt folgt, nutzt Bereiche, die mit einem Standardmöbel häufig verloren gehen. Gleiches gilt für Nischen, schwierige Ecken, ungewöhnliche Raumhöhen oder individuelle Grundrisse.
So entsteht Stauraum dort, wo vorher keiner war – und eine Lösung, die sich selbstverständlich in den Raum einfügt.
Maßanfertigung dort, wo sie Sinn ergibt
Maßanfertigung ist nicht automatisch überall die beste Lösung.
Bei geraden Wänden, üblichen Raumhöhen und klassischen Anforderungen kann auch ein gutes Serienmöbel die vernünftigere Wahl sein.
Deshalb beginnt unsere Beratung nicht mit der Frage, wie möglichst viel Maßanfertigung eingesetzt werden kann, sondern damit, welche Lösung für den jeweiligen Raum tatsächlich die richtige ist.
Und wenn Maßanfertigung sinnvoll ist, sorgen wir dafür, dass am Ende genau das stimmt, was am Anfang noch gar nicht stimmen muss:
der letzte Millimeter.
3. Magazin – Immobilien-Hinweis entfernen
Unter dem Maßanfertigungsartikel und auch unter dem Küchenartikel steht aktuell noch:
„Entdecken Sie mehr über Immobilien-Investments und das B2in-Ökosystem.“
Das passt dort aus meiner Sicht überhaupt nicht mehr.
Bitte als allgemeinen Magazin-Baustein ersetzen durch:
Weitere Einblicke rund um Einrichtung, Planung und Projekte finden Sie im B2in Magazin.
4. Alte Magazinartikel
Die beiden Artikel
„Supply-Chain-Management für Entwickler“
„Local for Local“
würde ich aktuell erst einmal deaktivieren.
Die stammen inhaltlich noch deutlich aus einer früheren B2in-Richtung.
Beim Supply-Chain-Artikel sind Formulierungen wie garantierte Ankunft, Eskalation auf Managementebene, Millionenersparnis usw. deutlich härter als das, was wir heute zum Projektgeschäft kommunizieren.
Beim Local-for-Local-Artikel wird wiederum ein digitaler Marktplatzansatz beschrieben, den wir aktuell so ebenfalls nicht darstellen.
Bevor wir die beiden jetzt aufwendig umschreiben, bitte zunächst rausnehmen. Neue Magazinbeiträge können wir später sauber aus der heutigen Ausrichtung heraus entwickeln.
5. FAQ Projektgeschäft
Hier steckt ebenfalls noch einiges aus der alten Supply-Chain-Sprache drin, unter anderem „absolute Vertragssicherheit“, Überwachung von Lieferverträgen und sofortige Eskalation auf Managementebene.
Das würde ich bitte an unserer heutigen Positionierung ausrichten.
Unsere Formulierung dafür ist:
Vollständige Einrichtung für Objekte, Büros und Projektentwicklungen – koordiniert aus einer Hand, von der Küche bis zur letzten Blume. Mit einem zentralen deutschen Vertragspartner und einem eingespielten Herstellernetzwerk.
Die FAQ-Antwort bitte daraus ableiten. Der Schwerpunkt sollte auf Koordination, einem Ansprechpartner und dem eingespielten Netzwerk liegen und nicht auf Garantie- und Eskalationsformulierungen.
6. Otterpohl Logistik
Bei der Formulierung
„Das garantiert Ihnen absolute Planungssicherheit.“
würde ich ebenfalls etwas zurückgehen.
Bitte ändern in:
„Das erhöht die Planungssicherheit deutlich.“
Das sagt aus meiner Sicht genug und wir versprechen damit nicht etwas absolut, was letztlich niemand zu 100 % garantieren kann.
7. Magazin – Datum und Lesezeit
Kleine Sache, aber bitte ebenfalls einmal einheitlich eindeutschen.
Aktuell zum Beispiel:
August 26, 2026 · 5 min read
bitte:
26. August 2026 · 5 Min. Lesezeit
Das dann bitte bei allen Magazinartikeln entsprechend einheitlich.

View file

@ -0,0 +1,47 @@
# Archiv: tote Inhalte und Seiten (06.10.2026)
Beim Aufräumen am 06.10.2026 (Nachtrag 22) wurde alles entfernt, was keine erreichbare Seite mehr
anzeigt. Hier liegen die Kopien. Nichts in diesem Ordner wird von der Anwendung geladen.
## Was hier liegt
| Datei / Ordner | Inhalt |
|---|---|
| `lang-de-sektionen.php`, `lang-en-sektionen.php` | Die 48 Sektionen, die aus `resources/lang/{de,en}/b2in.php` (`themes.b2in.*`) entfernt wurden |
| `cms-content-lokal-vollstaendig.json` | Kompletter Export aller CMS-Einträge (`cms_contents`, beide Sprachen) der lokalen Datenbank **vor** dem Aufräumen |
| `cms-content-geloescht-lokal.json` | Nur die 48 lokal gelöschten CMS-Einträge |
| `code/` | Gelöschte oder bereinigte Dateien im Originalzustand, Pfade wie im Projekt: alte Seiten-Views, Livewire-Komponenten, `NetzwerkPageCmsSeeder` samt Test, `config/content.php` (als `config-content.php`), `config/cms_section_map.php` und `routes/web.php` vorher, sowie die Blades mit auskommentierten Blöcken (Social Media im Kontaktformular, „Mehr laden“ im Magazin, „Artikel teilen“) |
Auf dem Server schreibt `UnusedCmsContentCleanupSeeder` vor dem Löschen eine eigene Sicherung nach
`storage/app/private/cms-archiv/cms-content-geloescht-{Zeitstempel}.json`.
## Was entfernt wurde
- **Seiten**, die nur noch umleiten oder nie verlinkt waren: Netzwerk, Partner, Ecosystem, Interior,
Service, Portfolio, die alte Immobilien-Seite samt Projektseite, `b2in`, `home2`, `about_bak`,
`welcome_bak`. Die 301-Umleitungen bleiben.
- **Dev-Archivseiten** `/dev/immobilien-v1`, `/dev/interior-v1`, `/dev/partner-v1` mit ihren Routen.
- **19 Livewire-Sektionen**, die nur diese Seiten nutzten (BenefitsSection, BrokerSection, CardSection,
CommitmentSection, DarkStatsSection, DigitalCore, EcosystemHero, EcosystemStats, EndCustomerSection,
FinalCommitment, HeroImage, HeroTiles, LeadershipTeam, PartnerBenefits, PartnerHero, PartnerProcess,
Portfolio, SpotlightsSection, SupplierSection).
- **48 CMS-Sektionen** (Gruppe `netzwerk` bis auf den Abschluss der Über-uns-Seite, die Immobilien-Blöcke
der alten Seite, `home.synergie_section`, `home.ecosystem_core`, `home.brand_worlds`,
`home.integriertes_modell_b2in`, `about.leadership_team`).
- **Ungenutzte Felder** in aktiven Sektionen: `stats` (Abschluss Über uns), `social_media` (Kontakt),
`load_more` (Magazin-Übersichten), `share_article` (Magazin-Beitrag).
- **`config/content.php`** komplett – wurde nur vom `CmsContentSeeder` gelesen und dort vollständig von
den Lang-Dateien überdeckt.
Die Projektdaten von Azizi Creek Views 4 (früher `immobilien_projects` in den Lang-Dateien) stehen jetzt
direkt im `CmsProjectSeeder`.
Nicht angefasst: die Themes b2a, Stileigentum und Style2own (eigene Domains, eigene Views) samt der
Komponenten, die nur sie nutzen (`content-section`, `ecosystem-core`, `brand-worlds`).
## Etwas zurückholen
- Eine CMS-Sektion: Eintrag aus `cms-content-lokal-vollstaendig.json` mit Gruppe, Schlüssel und `value`
wieder anlegen und die Zeile in `config/cms_section_map.php` (alter Stand in `code/`) ergänzen.
- Eine Seite: View und Komponenten aus `code/` zurückkopieren, Route wieder eintragen, Sektionen wie oben.
- Oder per Git: der Stand vor dem Aufräumen ist der Commit vor Nachtrag 22.

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,29 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class BenefitsSection extends Component
{
public $content = [];
public $layout = 'left'; // Standard-Layout
public $bg = 'bg-background';
public $section = 'card_section';
public function mount($layout = 'left', $bg = 'bg-background', $section = 'card_section')
{
$this->layout = $layout;
$this->bg = $bg;
$this->section = $section;
$this->content = cms_theme_section($this->section);
}
public function render()
{
return view('livewire.web.components.sections.benefits-section');
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class BrokerSection extends Component
{
public $content = [];
public function mount()
{
$this->content = cms_theme_section('broker_section');
}
public function render()
{
return view('livewire.web.components.sections.broker-section');
}
}

View file

@ -0,0 +1,29 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class CardSection extends Component
{
public $content = [];
public $layout = 'left'; // Standard-Layout
public $bg = 'bg-background';
public $section = 'card_section';
public function mount($layout = 'left', $bg = 'bg-background', $section = 'card_section')
{
$this->layout = $layout;
$this->bg = $bg;
$this->section = $section;
$this->content = cms_theme_section($this->section);
}
public function render()
{
return view('livewire.web.components.sections.card-section');
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class CommitmentSection extends Component
{
public $content = [];
public function mount()
{
$this->content = cms_theme_section('commitment_section');
}
public function render()
{
return view('livewire.web.components.sections.commitment-section');
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class DarkStatsSection extends Component
{
public $content = [];
public function mount()
{
$this->content = cms_theme_section('dark_stats_section');
}
public function render()
{
return view('livewire.web.components.sections.dark-stats-section');
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class DigitalCore extends Component
{
public $content = [];
public function mount()
{
$this->content = cms_theme_section('digital_core');
}
public function render()
{
return view('livewire.web.components.sections.digital-core');
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class EcosystemHero extends Component
{
public $content = [];
public function mount()
{
$this->content = cms_theme_section('ecosystem_hero');
}
public function render()
{
return view('livewire.web.components.sections.ecosystem-hero');
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class EcosystemStats extends Component
{
public $content = [];
public function mount()
{
$this->content = cms_theme_section('ecosystem_stats');
}
public function render()
{
return view('livewire.web.components.sections.ecosystem-stats');
}
}

View file

@ -0,0 +1,26 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class EndCustomerSection extends Component
{
public $content = [];
public $bg = '';
public $section = '';
public function mount($bg = 'bg-accent', $section = 'end_customer_section')
{
$this->section = $section;
$this->bg = $bg;
$this->content = cms_theme_section('end_customer_section');
}
public function render()
{
return view('livewire.web.components.sections.end-customer-section');
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class FinalCommitment extends Component
{
public $content = [];
public function mount()
{
$this->content = cms_theme_section('final_commitment');
}
public function render()
{
return view('livewire.web.components.sections.final-commitment');
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class HeroImage extends Component
{
public $content = [];
public function mount()
{
$this->content = cms_theme_section('hero_image');
}
public function render()
{
return view('livewire.web.components.sections.hero-image');
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class HeroTiles extends Component
{
public $content = [];
public function mount()
{
$this->content = cms_theme_section('hero_tiles');
}
public function render()
{
return view('livewire.web.components.sections.hero-tiles');
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class LeadershipTeam extends Component
{
public $content = [];
public function mount()
{
$this->content = cms_theme_section('leadership_team');
}
public function render()
{
return view('livewire.web.components.sections.leadership-team');
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class PartnerBenefits extends Component
{
public $content = [];
public function mount()
{
$this->content = cms_theme_section('partner_benefits');
}
public function render()
{
return view('livewire.web.components.sections.partner-benefits');
}
}

View file

@ -0,0 +1,48 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class PartnerHero extends Component
{
public $partnerTypes = [
[
'title' => 'Makler',
'description' => 'Lifetime-Vergütung',
'icon' => 'trending-up',
],
[
'title' => 'Lieferanten',
'description' => 'Globale Märkte',
'icon' => 'globe',
],
[
'title' => 'Partnership',
'description' => 'Faire Konditionen',
'icon' => 'handshake',
],
[
'title' => 'Erfolg',
'description' => 'Nachhaltiges Wachstum',
'icon' => 'award',
],
];
public $section = 'partner_hero';
public $content = [];
public function mount($section = 'partner_hero')
{
$this->section = $section;
$this->content = cms_theme_section($this->section);
}
public function render()
{
return view('livewire.web.components.sections.partner-hero', [
'partnerTypes' => $this->partnerTypes,
]);
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class PartnerProcess extends Component
{
public $content = [];
public function mount()
{
$this->content = cms_theme_section('partner_process');
}
public function render()
{
return view('livewire.web.components.sections.partner-process');
}
}

View file

@ -0,0 +1,74 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class Portfolio extends Component
{
public string $activeFilter = 'alle';
public ?array $selectedProject = null;
public bool $showModal = false;
public $content = [];
public $theme = '';
public $filters = [];
public function mount()
{
$filters = [
'alle' => 'Alle',
'villen' => 'Villen',
'penthouse' => 'Penthouse',
'loft' => 'Loft',
];
$this->filters = $filters;
$this->activeFilter = 'alle';
$this->theme = config('app.theme', 'b2in');
$portfolio = cms_theme_section('portfolio', $this->theme);
if (! is_array($portfolio)) {
$portfolio = [];
}
$this->content = $portfolio;
$this->filters = $portfolio['filters'] ?? $filters;
}
public function filterBy(string $category): void
{
$this->activeFilter = $category;
}
public function openModal(array $project): void
{
$this->selectedProject = $project;
$this->showModal = true;
}
public function closeModal(): void
{
$this->showModal = false;
$this->selectedProject = null;
}
public function getFilteredProjects(): array
{
$projects = $this->content['projects'] ?? [];
if ($this->activeFilter === 'alle') {
return $projects;
}
return array_filter($projects, function ($project) {
return strtolower($project['category']) === strtolower($this->activeFilter);
});
}
public function render()
{
return view('livewire.web.components.sections.portfolio');
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class SpotlightsSection extends Component
{
public $content = [];
public function mount()
{
$this->content = cms_theme_section('spotlights_section');
}
public function render()
{
return view('livewire.web.components.sections.spotlights-section');
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace App\Livewire\Web\Components\Sections;
use Livewire\Component;
class SupplierSection extends Component
{
public $content = [];
public function mount()
{
$this->content = cms_theme_section('supplier_section');
}
public function render()
{
return view('livewire.web.components.sections.supplier-section');
}
}

View file

@ -0,0 +1,211 @@
<?php
namespace App\Livewire\Web\Components\Ui;
use Acme\ContactForm\ContactFormService;
use Acme\ContactForm\SpamDetector;
use App\Models\CmsBrand;
use Illuminate\Validation\Rule;
use Livewire\Component;
class ContactForm extends Component
{
public string $firstName = '';
public string $lastName = '';
public string $company = '';
public string $email = '';
public string $phone = '';
public string $subject = '';
public string $message = '';
public bool $privacy = false;
public bool $success = false;
/** @var string Hidden honeypot field */
public string $website = '';
public ?int $formLoadedAt = null;
/** @var array<string, mixed> */
public array $content = [];
/** Farbwelt der Seite (`interior` | `immobilien`). */
public string $world = 'interior';
public function mount(string $world = 'interior'): void
{
$this->world = $world === 'immobilien' ? 'immobilien' : 'interior';
$this->content = $this->loadContent();
$this->formLoadedAt = time();
}
/**
* Inhalte der Welt. Die Immobilien-Welt liegt als Overlay über der Interior-Sektion:
* `contact_form_immobilien` trägt nur, was abweicht (Einstieg, Betreffe) – Adresse,
* Beschriftungen und Social Media erbt sie von `contact_form`.
*
* @return array<string, mixed>
*/
private function loadContent(): array
{
$base = cms_theme_section('contact_form');
$base = is_array($base) ? $base : [];
if ($this->world !== 'immobilien') {
return $base;
}
$overlay = cms_theme_section('contact_form_immobilien');
if (! is_array($overlay)) {
return $base;
}
return array_replace_recursive($base, $overlay);
}
/**
* Betreffe in Gruppen: Interior (mit den gepflegten Kernmarken vorneweg), Immobilien, B2in.
* Die Welt der Seite bestimmt die Reihenfolge – ihre Gruppe steht oben.
*
* Ohne `subject_groups` (aeltere CMS-Staende) faellt das Formular auf die flache Liste zurueck.
*
* @return array<string, array{label: string, subjects: array<string, string>}>
*/
public function getSubjectGroupsProperty(): array
{
$groups = $this->content['form']['subject_groups'] ?? null;
if (! is_array($groups) || $groups === []) {
$flat = $this->content['form']['subjects'] ?? [];
unset($flat['']);
return $flat === [] ? [] : ['all' => ['label' => '', 'subjects' => $flat]];
}
$brands = [];
foreach (CmsBrand::forFrontend() as $slug => $brand) {
$brands[$slug] = (string) ($brand['name'] ?? $slug);
}
$out = [];
foreach ($groups as $key => $group) {
$subjects = is_array($group['subjects'] ?? null) ? $group['subjects'] : [];
if ($key === 'interior') {
$subjects = $brands + $subjects;
}
$out[$key] = [
'label' => (string) ($group['label'] ?? ''),
'subjects' => $subjects,
];
}
$first = $this->world === 'immobilien' ? 'immobilien' : 'interior';
if (isset($out[$first])) {
$out = [$first => $out[$first]] + $out;
}
return $out;
}
/**
* Alle waehlbaren Betreffe als flache Liste (Schluessel → Beschriftung).
*
* @return array<string, string>
*/
public function getSubjectsProperty(): array
{
$flat = [];
foreach ($this->getSubjectGroupsProperty() as $group) {
$flat += $group['subjects'];
}
return $flat;
}
public function getSubjectPlaceholderProperty(): string
{
return (string) ($this->content['form']['subjects'][''] ?? $this->content['form']['subject_placeholder'] ?? __('ui.contact_form.subject_placeholder'));
}
/** @return array<int, array<string, mixed>> */
public function getContactInfoProperty(): array
{
return $this->content['contact_info'] ?? [];
}
/** @return array<int, array<string, mixed>> */
public function getSocialMediaProperty(): array
{
return $this->content['social_media']['platforms'] ?? [];
}
public function submit(ContactFormService $service): void
{
$this->validate([
'firstName' => ['required', 'string', 'max:255'],
'lastName' => ['required', 'string', 'max:255'],
'email' => ['required', 'email:rfc', 'max:255'],
'subject' => ['required', 'string', Rule::in(array_keys($this->subjects))],
'message' => ['required', 'string', 'max:2000'],
'company' => ['nullable', 'string', 'max:255'],
'phone' => ['nullable', 'string', 'max:255'],
'privacy' => ['accepted'],
'website' => ['nullable', 'string', 'max:0'],
]);
$spamDetector = SpamDetector::fromConfig();
$payload = [
'first_name' => $this->firstName,
'last_name' => $this->lastName,
'email' => $this->email,
'subject' => $this->subject,
'message' => $this->message,
'company' => $this->company,
'phone' => $this->phone,
'website' => $this->website,
'ip' => request()->ip(),
'user_agent' => request()->userAgent(),
'is_spam' => false,
];
$payload['is_spam'] = $spamDetector->detect($payload, $this->formLoadedAt);
$subjectLabel = $this->getSubjectsProperty()[$this->subject] ?? $this->subject;
$prefix = $this->world === 'immobilien' ? 'Kontaktanfrage B2in Immobilien' : 'Kontaktanfrage B2in';
$subjectLine = $subjectLabel
? $prefix.': '.$subjectLabel
: __('contact-form::contact-form.default_subject');
$service->handle($payload, $subjectLine, 'contact-form');
$this->success = true;
$this->firstName = '';
$this->lastName = '';
$this->company = '';
$this->email = '';
$this->phone = '';
$this->subject = '';
$this->message = '';
$this->privacy = false;
$this->website = '';
$this->formLoadedAt = time();
}
public function render(): \Illuminate\View\View
{
return view('livewire.web.components.ui.contact-form');
}
}

View file

@ -0,0 +1,123 @@
<?php
declare(strict_types=1);
/**
* Theme-Section-Schlüssel (wie in b2in.themes.{theme}.*) → [CMS-Gruppe, CMS-Key].
*
* Wird von cms_theme_section() und CmsContentSeeder verwendet.
*/
return [
'lang_keys' => [
'card_section' => 'partner_card_section',
],
'sections' => [
'announcement_bar' => ['global', 'announcement_bar'],
'announcement_bar_immobilien' => ['global', 'announcement_bar_immobilien'],
'header' => ['global', 'header'],
'hero_slider' => ['home', 'hero_slider'],
'footer' => ['global', 'footer'],
'cta_section' => ['global', 'cta_section'],
'cta_section_immobilien' => ['global', 'cta_section_immobilien'],
'appointment_widget' => ['global', 'appointment_widget'],
'cta_section_portfolio' => ['global', 'cta_section_portfolio'],
'hero' => ['home', 'hero'],
'audience_switch' => ['home', 'audience_switch'],
'core_brands' => ['home', 'core_brands'],
'origin_section' => ['home', 'origin_section'],
'marken_hero' => ['marken', 'hero'],
'marken_network' => ['marken', 'network'],
'marken_growth' => ['marken', 'growth'],
'marken_cta' => ['marken', 'cta'],
'brand_craft' => ['marken', 'craft'],
'referenzen_hero' => ['referenzen', 'hero'],
'reference_projects' => ['referenzen', 'projects'],
'display_feed' => ['referenzen', 'display_feed'],
'sponsoring' => ['home', 'sponsoring'],
'immobilien_teaser' => ['home', 'immobilien_teaser'],
'founder_bar' => ['home', 'founder_bar'],
'synergie_section' => ['home', 'synergie_section'],
'ecosystem_core' => ['home', 'ecosystem_core'],
'vision_section' => ['home', 'vision_section'],
'brand_worlds' => ['home', 'brand_worlds'],
'integriertes_modell_b2in' => ['home', 'integriertes_modell_b2in'],
'immobilien_hero' => ['immobilien', 'hero'],
'immobilien_hero_v2' => ['immobilien', 'hero_v2'],
'immobilien_projects' => ['immobilien', 'projects_meta'],
'immobilien_moebel_vorteil' => ['immobilien', 'moebel_vorteil'],
'immobilien_trust' => ['immobilien', 'trust'],
'immobilien_warum_dubai' => ['immobilien', 'warum_dubai'],
'immobilien_image_break' => ['immobilien', 'image_break'],
'immobilien_kaufprozess' => ['immobilien', 'kaufprozess'],
'immobilien_bruecke' => ['immobilien', 'bruecke'],
'immobilien_mindset' => ['immobilien', 'mindset'],
'portfolio' => ['immobilien', 'portfolio'],
'netzwerk_hero' => ['netzwerk', 'hero'],
'netzwerk_image_break' => ['netzwerk', 'image_break'],
'netzwerk_teasers' => ['netzwerk', 'teasers'],
'netzwerk_cta' => ['netzwerk', 'cta'],
'netzwerk_cabinet_partner' => ['netzwerk', 'cabinet_partner'],
'netzwerk_immobilien_hint' => ['netzwerk', 'immobilien_hint'],
'interior_hero' => ['netzwerk', 'interior_hero'],
'interior_concept' => ['netzwerk', 'interior_concept'],
'interior_brands' => ['netzwerk', 'interior_brands'],
'interior_zielgruppen' => ['netzwerk', 'interior_zielgruppen'],
'interior_process' => ['netzwerk', 'interior_process'],
'interior_trust' => ['netzwerk', 'interior_trust'],
'faq' => ['faq', 'faq'],
'faq_immobilien' => ['faq', 'faq_immobilien'],
// Immobilien-Welt: eigene Navigation, eigenes Magazin, eigene Ueber-uns-Seite
'header_immobilien' => ['global', 'header_immobilien'],
'magazin_list_immobilien' => ['immobilien', 'magazin_list'],
'immobilien_about_hero' => ['immobilien', 'about_hero'],
'immobilien_our_story' => ['immobilien', 'our_story'],
'immobilien_about_image_break' => ['immobilien', 'about_image_break'],
'immobilien_our_values' => ['immobilien', 'our_values'],
'contact_form' => ['contact', 'contact_form'],
'contact_form_immobilien' => ['contact', 'contact_form_immobilien'],
'about_hero' => ['about', 'hero'],
'our_story' => ['about', 'our_story'],
'about_image_break' => ['about', 'image_break'],
'our_values' => ['about', 'our_values'],
'leadership_team' => ['about', 'leadership_team'],
'broker_section' => ['netzwerk', 'broker_section'],
'commitment_section' => ['netzwerk', 'commitment_section'],
'dark_stats_section' => ['netzwerk', 'dark_stats_section'],
'ecosystem_hero' => ['netzwerk', 'ecosystem_hero'],
'ecosystem_stats' => ['netzwerk', 'ecosystem_stats'],
'ecosystem_start' => ['netzwerk', 'ecosystem_start'],
'ecosystem_hub' => ['netzwerk', 'ecosystem_hub'],
'ecosystem_result' => ['netzwerk', 'ecosystem_result'],
'end_customer_section' => ['netzwerk', 'end_customer_section'],
'final_commitment' => ['netzwerk', 'final_commitment'],
'digital_core' => ['netzwerk', 'digital_core'],
'supply_chain_intro' => ['netzwerk', 'supply_chain_intro'],
'partner_hero' => ['netzwerk', 'partner_hero'],
'partner_benefits' => ['netzwerk', 'partner_benefits'],
'partner_cta' => ['netzwerk', 'partner_cta'],
'partner_card_section' => ['netzwerk', 'partner_card_section'],
'card_section' => ['netzwerk', 'partner_card_section'],
'partner_benefits_developer' => ['netzwerk', 'partner_benefits_developer'],
'partner_benefits_retailer' => ['netzwerk', 'partner_benefits_retailer'],
'partner_benefits_supplier' => ['netzwerk', 'partner_benefits_supplier'],
'partner_benefits_broker' => ['netzwerk', 'partner_benefits_broker'],
'partner_process' => ['netzwerk', 'partner_process'],
'supplier_section' => ['netzwerk', 'supplier_section'],
'magazin_detail' => ['magazin', 'detail'],
'magazin_list' => ['magazin', 'list'],
],
];

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,90 @@
<?php
namespace Database\Seeders;
use FluxCms\Core\Models\CmsContent;
use FluxCms\Core\Services\CmsContentService;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Lang;
class NetzwerkPageCmsSeeder extends Seeder
{
/**
* Füllt nur fehlende Netzwerk-Seitenblöcke (CABINET-Premiumpartner, Immobilien-Hinweis) aus den Lang-Dateien.
* Bestehende CMS-Einträge werden nicht überschrieben.
*
* @var array<string, array{0: string, 1: string}>
*/
protected array $sections = [
'netzwerk_cabinet_partner' => ['netzwerk', 'cabinet_partner'],
'netzwerk_immobilien_hint' => ['netzwerk', 'immobilien_hint'],
];
public function run(): void
{
/** @var array<string, mixed> $langDe */
$langDe = Lang::get('b2in.themes.b2in', [], 'de');
/** @var array<string, mixed> $langEn */
$langEn = Lang::get('b2in.themes.b2in', [], 'en');
if (! is_array($langDe)) {
$this->command?->warn('NetzwerkPageCmsSeeder: b2in.themes.b2in (de) fehlt.');
return;
}
if (! is_array($langEn)) {
$langEn = [];
}
$created = 0;
foreach ($this->sections as $sectionKey => [$group, $key]) {
if (CmsContent::query()->where('group', $group)->where('key', $key)->exists()) {
$this->command?->info("CMS {$group}.{$key} existiert bereits – übersprungen.");
continue;
}
$sectionDataDe = $langDe[$sectionKey] ?? null;
if ($sectionDataDe === null) {
$this->command?->warn("Lang-Block {$sectionKey} fehlt – übersprungen.");
continue;
}
$sectionDataEn = $langEn[$sectionKey] ?? $sectionDataDe;
CmsContent::query()->create([
'group' => $group,
'key' => $key,
'type' => $this->detectType($sectionDataDe),
'value' => [
'de' => $sectionDataDe,
'en' => $sectionDataEn,
],
'order' => 0,
]);
$created++;
$this->command?->info("CMS {$group}.{$key} angelegt.");
}
if ($created > 0) {
app(CmsContentService::class)->clearCache();
}
}
private function detectType(mixed $data): string
{
if (is_array($data)) {
return 'json';
}
if (is_string($data) && preg_match('/<[^>]+>/', $data)) {
return 'html';
}
return 'text';
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,146 @@
<section class="section-padding {{ $bg }}" id="{{ $content['id'] }}">
<div class="container-padding">
@if(isset($content['title']))
<div class="text-center mb-16">
<h2 class="text-section-title text-foreground mb-6">
{{ $content['title'] }}
</h2>
<p class="text-large text-muted-foreground max-w-3xl mx-auto">
{{ $content['subtitle'] }}
</p>
</div>
@endif
<div class="grid lg:grid-cols-12 gap-16">
@if ($layout === 'right')
{{-- Layout Right: Bild zuerst, dann Text --}}
{{-- Bild --}}
<div class="space-y-8 col-span-8 lg:col-span-4 order-2 lg:order-1">
<div class="relative h-full">
<div class="sticky top-8">
<div class="relative rounded-3xl overflow-hidden shadow-elevated slide-right delay-300">
@if(isset($content['image']))
<img src="{{ theme_image_url($content['image']) }}"
alt="{{ $content['image_alt'] ?? 'Benefits Image' }}"
class="w-full h-[400px] md:h-[500px] lg:h-[600px] object-cover" />
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
@endif
</div>
<div class="bg-secondary/5 rounded-xl p-6 mt-6">
<div class="text-center">
<div class="text-3xl font-bold text-secondary mb-2">{{ $content['highlight']['value'] }}</div>
<p class="text-sm text-muted-foreground">
{{ $content['highlight']['text'] }}
</p>
</div>
</div>
</div>
</div>
</div>
{{-- Text --}}
<div class="space-y-8 col-span-8 order-1 lg:order-2">
<div class="text-center lg:text-left slide-left delay-400">
<div
class="inline-flex items-center gap-2 bg-secondary/10 text-secondary px-4 py-2 rounded-full text-md font-medium mb-6">
@svg('heroicon-o-'.$content['tag_icon'], 'w-4 h-4')
{{ $content['tag'] }}
</div>
<h3 class="text-3xl font-light text-foreground mb-6">
{!! $content['tag_title'] !!}
</h3>
</div>
<div class="space-y-6">
@foreach ($content['features'] as $index => $feature)
<div class="card-elevated p-6 rounded-xl slide-left delay-{{ 500 + ($index * 100) }}">
<div class="flex gap-4">
<div
class="flex-shrink-0 w-12 h-12 rounded-xl bg-secondary/10 flex items-center justify-center">
@if (isset($feature['icon']))
@svg('heroicon-o-'.$feature['icon'], 'w-6 h-6 text-secondary')
@endif
</div>
<div>
<h4 class="text-lg font-semibold text-foreground mb-2">
{{ $feature['title'] }}
</h4>
<p class="text-muted-foreground">
{{ $feature['description'] }}
</p>
</div>
</div>
</div>
@endforeach
</div>
</div>
@else
{{-- Layout Left (Standard): Text zuerst, dann Bild --}}
{{-- Text --}}
<div class="space-y-8 col-span-8 order-1 lg:order-1">
<div class="text-center lg:text-left slide-right delay-300">
<div
class="inline-flex items-center gap-2 bg-secondary/10 text-secondary px-4 py-2 rounded-full text-md font-medium mb-6">
@svg('heroicon-o-'.$content['tag_icon'], 'w-4 h-4')
{{ $content['tag'] }}
</div>
<h3 class="text-3xl font-light text-foreground mb-6">
{!! $content['tag_title'] !!}
</h3>
</div>
<div class="space-y-6">
@foreach ($content['features'] as $index => $feature)
<div class="card-elevated p-6 rounded-xl slide-right delay-{{ 400 + ($index * 100) }}">
<div class="flex gap-4">
<div
class="flex-shrink-0 w-12 h-12 rounded-xl bg-secondary/10 flex items-center justify-center">
@if (isset($feature['icon']))
@svg('heroicon-o-'.$feature['icon'], 'w-6 h-6 text-secondary')
@endif
</div>
<div>
<h4 class="text-lg font-semibold text-foreground mb-2">
{{ $feature['title'] }}
</h4>
<p class="text-muted-foreground">
{{ $feature['description'] }}
</p>
</div>
</div>
</div>
@endforeach
</div>
</div>
{{-- Bild --}}
<div class="space-y-8 col-span-8 lg:col-span-4 order-2 lg:order-2">
<div class="relative h-full">
<div class="sticky top-8">
<div class="relative rounded-3xl overflow-hidden shadow-elevated slide-left delay-300">
@if(isset($content['image']))
<img src="{{ theme_image_url($content['image']) }}"
alt="{{ $content['image_alt'] ?? 'Benefits Image' }}"
class="w-full h-[400px] md:h-[500px] lg:h-[600px] object-cover" />
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
@endif
</div>
<div class="bg-secondary/5 rounded-xl p-6 mt-6">
<div class="text-center">
<div class="text-3xl font-bold text-secondary mb-2">{{ $content['highlight']['value'] }}</div>
<p class="text-sm text-muted-foreground">
{{ $content['highlight']['text'] }}
</p>
</div>
</div>
</div>
</div>
</div>
@endif
</div>
</div>
</section>

View file

@ -0,0 +1,101 @@
<section class="section-padding bg-background">
<div class="container-padding">
<div class="grid lg:grid-cols-2 gap-16 items-center">
<div class="relative order-2 lg:order-1">
<div class="card-elevated rounded-3xl p-12">
<div class="text-center mb-8">
<div class="w-20 h-20 mx-auto rounded-full bg-gradient-to-br from-secondary to-secondary/60 flex items-center justify-center mb-6">
<svg class="w-10 h-10 text-secondary" 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"/>
</svg>
</div>
<h3 class="text-2xl font-semibold text-foreground mb-4">
{{ $content['card_title'] }}
</h3>
</div>
<div class="space-y-6">
<div class="bg-accent/30 rounded-xl p-6">
<div class="flex justify-between items-center mb-2">
<span class="text-sm text-muted-foreground">Erstverkauf</span>
<span class="text-lg font-semibold text-secondary">{{ $content['compensation']['initial_sale'] }}</span>
</div>
<div class="w-full bg-accent/50 rounded-full h-2">
<div class="bg-secondary h-2 rounded-full w-[35%]"></div>
</div>
</div>
<div class="bg-accent/30 rounded-xl p-6">
<div class="flex justify-between items-center mb-2">
<span class="text-sm text-muted-foreground">Folgegeschäfte</span>
<span class="text-lg font-semibold text-secondary">{{ $content['compensation']['follow_up'] }}</span>
</div>
<div class="w-full bg-accent/50 rounded-full h-2">
<div class="bg-secondary h-2 rounded-full w-[15%]"></div>
</div>
</div>
<div class="text-center pt-4">
<p class="text-sm text-muted-foreground">
{{ $content['compensation_text'] }}
</p>
</div>
</div>
</div>
</div>
<div class="space-y-8 order-1 lg:order-2">
<div>
<div class="inline-flex items-center gap-2 bg-secondary/10 text-secondary px-4 py-2 rounded-full text-sm font-medium mb-6">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"/>
</svg>
Für Makler
</div>
<h2 class="text-section-title mb-6">
{!! $content['title'] !!}
</h2>
<p class="text-large text-muted-foreground leading-relaxed">
{{ $content['subtitle'] }}
</p>
</div>
<div class="space-y-6">
@foreach($content['benefits'] as $benefit)
<div class="flex gap-4">
<div class="flex-shrink-0 w-12 h-12 rounded-xl bg-secondary/10 flex items-center justify-center">
@if($benefit['icon'] === 'trending-up')
<svg class="w-6 h-6 text-secondary" 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"/>
</svg>
@elseif($benefit['icon'] === 'clock')
<svg class="w-6 h-6 text-secondary" 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"/>
</svg>
@elseif($benefit['icon'] === 'target')
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 18.657A8 8 0 016.343 7.343S7 9 9 10c0-2 1.657-2.657 1.657-2.657A8 8 0 0118.657 17.657zM12 12l1 1"/>
</svg>
@else
<svg class="w-6 h-6 text-secondary" 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"/>
</svg>
@endif
</div>
<div>
<h3 class="text-lg font-semibold text-foreground mb-2">
{{ $benefit['title'] }}
</h3>
<p class="text-muted-foreground">
{{ $benefit['description'] }}
</p>
</div>
</div>
@endforeach
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,69 @@
<section class="section-padding {{ $bg }}">
<div class="container-padding">
{{-- Section Title --}}
<div class="text-center mb-16 slide-up delay-300">
<h2 class="text-section-title">{!! $content['title'] !!}</h2>
<p class="text-large text-muted-foreground mt-4 max-w-3xl mx-auto">
{!! $content['subtitle'] !!}
</p>
</div>
{{-- Brand Cards --}}
<div class="grid md:grid-cols-2 gap-8">
@foreach ($content['cards'] as $index => $card)
<div class="card-elevated overflow-hidden group hover:shadow-elevated transition-all duration-300 flex flex-col slide-up delay-{{ $index * 200 }}">
@if(isset($card['image']))
<div class="relative">
<img src="{{ theme_image_url($card['image']) }}" alt="{{ $card['title'] }}"
class="w-full h-64 object-cover group-hover:scale-105 transition-transform duration-500" />
</div>
@endif
@if(isset($card['icon']))
<div class="relative pt-12 pb-8">
<div class="mx-auto w-20 h-20 icon-secondary-linear glow-soft group-hover:glow-medium rounded-2xl flex items-center justify-center transition-colors duration-300">
@svg('heroicon-o-'.$card['icon'], 'w-10 h-10 text-secondary-foreground')
</div>
</div>
@endif
<div class="p-6 spacing-small flex flex-col justify-between flex-grow">
<div class="mb-4">
@if (isset($card['logo']))
<img src="{{ asset($card['logo']) }}" alt="{{ $card['title'] }}"
class="{{ $card['logo_width'] }} h-18 object-contain" />
@endif
@if(isset($card['title']))
<h3 class="text-xl font-medium text-center">{{ $card['title'] }}</h3>
@endif
@if(isset($card['description']))
<p class="text-muted-foreground leading-relaxed mt-2 text-center">
{{ $card['description'] }}
</p>
@endif
</div>
@if(isset($card['button']))
<div class="flex flex-col sm:flex-row gap-4 slide-right delay-300 mx-auto pt-4">
<a href="{{ $card['button'] }}" class="btn-primary-accent">
{{ $card['button_text'] }}
</a>
</div>
@endif
@if(isset($card['link']))
<a href="{{ $card['link'] }}"
class="inline-flex items-center gap-2 text-secondary font-medium hover:gap-3 transition-all duration-300">
{{ __('ui.learn_more') }}
<svg class="w-4 h-4" 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>
</a>
@endif
</div>
</div>
@endforeach
</div>
</div>
</section>

View file

@ -0,0 +1,40 @@
<section class="section-padding text-center">
<div class="container-padding">
<div class="text-center mb-16 slide-up delay-300">
<h2 class="text-section-title text-foreground mb-6">
{!! $content['title'] !!}
</h2>
<p class="text-large text-muted-foreground max-w-2xl mx-auto">
{{ $content['subtitle'] }}
</p>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
@foreach($content['testimonials'] as $index => $testimonial)
<div class="card-elevated rounded-2xl p-8 text-left space-y-6 slide-up delay-{{ $index * 200 }}">
<div class="flex items-center gap-4">
<img src="{{ theme_image_url($testimonial['image']) }}" alt="{{ $testimonial['author'] }}" class="w-16 h-16 rounded-full object-cover">
<div>
<h4 class="font-bold text-foreground">{{ $testimonial['author'] }}</h4>
<p class="text-sm text-muted-foreground">{{ $testimonial['author_title'] }}</p>
</div>
</div>
<div class="flex">
@for ($i = 0; $i < 5; $i++)
<svg class="w-5 h-5 {{ $i < $testimonial['rating'] ? 'text-secondary' : 'text-muted/20' }}" fill="currentColor" viewBox="0 0 20 20">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/>
</svg>
@endfor
</div>
<blockquote class="text-muted-foreground italic leading-relaxed">
"{{ $testimonial['quote'] }}"
</blockquote>
</div>
@endforeach
</div>
</div>
</section>

View file

@ -0,0 +1,47 @@
<section class="section-padding">
<div class="container-padding">
<div class="grid lg:grid-cols-2 gap-16 items-center">
<div class="space-y-12">
<div class="grid grid-cols-2 gap-8">
@foreach($content['stats'] as $stat)
<div>
<div class="text-6xl font-light text-foreground mb-2">{{ $stat['number'] }}</div>
<p class="text-muted-foreground text-sm">{{ $stat['text'] }}</p>
</div>
@endforeach
</div>
<div class="space-y-6">
<h3 class="text-section-title">
{!! $content['title'] !!}
</h3>
<p class="text-muted-foreground leading-relaxed">
{{ $content['description'] }}
</p>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 pt-8">
@foreach($content['features'] as $feature)
<div class="flex items-center gap-3">
<div class="w-8 h-8 bg-secondary rounded-full flex items-center justify-center">
<span class="text-primary text-sm">✓</span>
</div>
<div>
<p class="text-foreground font-medium text-sm">{{ $feature['title'] }}</p>
<p class="text-muted-foreground text-xs">{{ $feature['subtitle'] }}</p>
</div>
</div>
@endforeach
</div>
</div>
</div>
<div class="relative">
<div class="card-elevated bg-muted p-0 overflow-hidden rounded-3xl">
<img src="{{ theme_image_url($content['image']) }}" alt="{{ $content['image_alt'] }}"
class="w-full h-96 object-cover" />
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,40 @@
<section class="section-padding bg-background">
<div class="container-padding">
<div class="text-center mb-16 slide-up delay-300">
<h2 class="text-section-title mb-6">
{!! $content['title'] !!}
</h2>
<p class="text-large text-muted-foreground max-w-3xl mx-auto">
{{ $content['subtitle'] }}
</p>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
@foreach($content['features'] as $index => $feature)
<div class="group h-full {{ $index === 4 ? 'md:col-span-2 lg:col-span-1 lg:col-start-2' : '' }}">
<div class="card-elevated p-8 overflow-hidden group hover:shadow-elevated transition-all duration-300 flex flex-col h-full slide-up delay-{{ $index * 200 }}">
<div class="text-center space-y-6">
<div class="mx-auto w-16 h-16 icon-secondary-linear glow-soft group-hover:glow-medium rounded-2xl flex items-center justify-center transition-colors duration-300">
@if($feature['icon'])
@svg('heroicon-o-'.$feature['icon'], 'w-8 h-8 text-secondary-foreground')
@endif
</div>
<h3 class="text-xl font-semibold text-foreground">
{{ $feature['title'] }}
</h3>
<div class="w-12 h-px bg-secondary mx-auto"></div>
<p class="text-muted-foreground leading-relaxed">
{{ $feature['description'] }}
</p>
</div>
<div class="absolute bottom-0 left-0 right-0 h-1 bg-gradient-to-r from-secondary/20 via-secondary to-secondary/20 transform scale-x-0 group-hover:scale-x-100 transition-transform duration-300"></div>
</div>
</div>
@endforeach
</div>
</div>
</section>

View file

@ -0,0 +1,79 @@
<section class="section-padding flex items-center relative border-b border-border/30">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 bg-hero-container rounded-[20px] w-[95%]">
<div class="grid lg:grid-cols-2 gap-16 items-center">
<div class="space-y-8">
<h1 class="text-hero">
{!! $content['title'] !!}
</h1>
<p class="text-large text-muted-foreground leading-relaxed">
{{ $content['subtitle'] }}
</p>
<div class="grid grid-cols-2 gap-6">
@foreach ($content['features'] as $feature)
<div class="flex items-center gap-3">
<div class="w-12 h-12 rounded-full bg-secondary/10 flex items-center justify-center">
@if ($feature['icon'] === 'users')
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197m13.5-9a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z" />
</svg>
@elseif($feature['icon'] === 'building-2')
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
</svg>
@elseif($feature['icon'] === 'network')
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.367 2.684 3 3 0 00-5.367-2.684z" />
</svg>
@else
<svg class="w-6 h-6 text-secondary" 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" />
</svg>
@endif
</div>
<div>
<p class="font-semibold text-foreground">{{ $feature['title'] }}</p>
<p class="text-sm text-muted-foreground">{{ $feature['description'] }}</p>
</div>
</div>
@endforeach
</div>
</div>
<div class="relative">
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
<img src="{{ theme_image_url($content['image']) }}"
alt="{{ $content['image_alt'] }}"
class="w-full h-[600px] object-cover" />
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
</div>
{{-- Floating info card --}}
<div
class="absolute bottom-6 left-6 bg-card/95 backdrop-blur-sm rounded-xl p-4 shadow-lg border border-border/50">
<div class="text-center">
<div
class="w-24 h-24 mx-auto rounded-full bg-secondary flex items-center justify-center mb-4">
<svg class="w-12 h-12 text-white" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z" />
</svg>
</div>
<h3 class="text-xl font-semibold text-foreground">{{ $content['hub']['title'] }}</h3>
<p class="text-sm text-muted-foreground">{{ $content['hub']['subtitle'] }}</p>
</div>
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,27 @@
<section class="section-padding bg-background">
<div class="container-padding">
<div class="text-center mb-16 slide-up delay-300">
<h2 class="text-section-title">{!! $content['title'] !!}</h2>
<p class="text-large text-muted-foreground mt-4 max-w-3xl mx-auto">
{!! $content['subtitle'] !!}
</p>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-8">
@foreach ($content['stats'] as $index => $stat)
<div class="card-elevated p-8 text-center overflow-hidden group hover:shadow-elevated transition-all duration-300 flex flex-col slide-up delay-{{ $index * 200 }}">
<h2 class="text-4xl lg:text-5xl font-bold text-secondary mb-4">
{{ $stat['number'] }}
</h2>
<h3 class="text-xl lg:text-2xl font-semibold text-foreground mb-3">
{{ $stat['label'] }}
</h3>
<p class="text-md text-muted-foreground leading-relaxed">
{{ $stat['description'] }}
</p>
</div>
@endforeach
</div>
</div>
</section>

View file

@ -0,0 +1,83 @@
<section class="section-padding {{ $bg }}">
<div class="container-padding">
<div class="grid lg:grid-cols-2 gap-16 items-center">
<div class="space-y-8">
<div>
<div class="inline-flex items-center gap-2 bg-secondary/10 text-secondary px-4 py-2 rounded-full text-sm font-medium mb-6">
<svg class="w-4 h-4" 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"/>
</svg>
{{ $content['tag'] }}
</div>
<h2 class="text-section-title mb-6">
{!! $content['title'] !!}
</h2>
<p class="text-large text-muted-foreground leading-relaxed">
{{ $content['subtitle'] }}
</p>
</div>
<div class="space-y-6">
@foreach($content['benefits'] as $benefit)
<div class="flex gap-4">
<div class="flex-shrink-0 w-12 h-12 rounded-xl bg-secondary/10 flex items-center justify-center">
@if($benefit['icon'] === 'credit-card')
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"/>
</svg>
@elseif($benefit['icon'] === 'star')
<svg class="w-6 h-6 text-secondary" 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"/>
</svg>
@elseif($benefit['icon'] === 'home')
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
</svg>
@else
<svg class="w-6 h-6 text-secondary" 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"/>
</svg>
@endif
</div>
<div>
<h3 class="text-lg font-semibold text-foreground mb-2">
{{ $benefit['title'] }}
</h3>
<p class="text-muted-foreground">
{{ $benefit['description'] }}
</p>
</div>
</div>
@endforeach
</div>
</div>
<div class="relative">
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
<img src="{{ theme_image_url($content['image']) }}"
alt="{{ $content['image_alt'] }}"
class="w-full h-[600px] object-cover" />
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
</div>
{{-- Floating info card --}}
<div
class="absolute bottom-6 left-6 bg-card/95 backdrop-blur-sm rounded-xl p-4 shadow-lg border border-border/50">
<div class="text-center">
<div
class="w-24 h-24 mx-auto rounded-full bg-secondary flex items-center justify-center mb-4">
<svg class="w-12 h-12 text-white" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z" />
</svg>
</div>
<h3 class="text-xl font-semibold text-foreground">{{ $content['card_title'] }}</h3>
<p class="text-sm text-muted-foreground">{{ $content['card_title'] }}</p>
</div>
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,16 @@
<section class="section-padding text-center">
<div class="container-narrow">
<h2 class="text-section-title text-foreground leading-tight mb-8">
{!! $content['title'] !!}
</h2>
<div class="flex justify-center mb-8">
<div class="w-16 h-px bg-secondary"></div>
</div>
<p class="text-large text-muted-foreground">
{{ $content['author'] }} <br />
<span class="text-sm">{{ $content['author_title'] }}</span>
</p>
</div>
</section>

View file

@ -0,0 +1,49 @@
<section class="section-padding relative">
<div class="container-padding">
{{-- Header Content --}}
<div class="text-center mb-12 max-w-4xl mx-auto">
<h1 class="text-hero mb-6">
{!! $content['title'] !!}
</h1>
<p class="text-large text-muted-foreground mt-4 max-w-3xl mx-auto">
{!! $content['subtitle'] !!}
</p>
</div>
{{-- CTA Buttons --}}
@if(isset($content['cta1_text']) && isset($content['cta2_text']))
<div class="flex flex-col sm:flex-row gap-4 justify-center mb-16">
<a href="{{ $content['cta1_link'] }}" class="btn-primary-accent">
{{ $content['cta1_text'] }}
</a>
<a href="{{ $content['cta2_link'] }}" class="btn-secondary-accent">
{{ $content['cta2_text'] }}
</a>
</div>
@endif
{{-- Full Width Hero Image --}}
<div class="relative w-full">
<div class="relative rounded-2xl overflow-hidden shadow-elevated">
<img src="{{ theme_image_url($content['hero_image'] ?? $content['tiles'][0]['image']) }}"
alt="{{ $content['hero_image_alt'] ?? $content['tiles'][0]['alt'] ?? '' }}"
class="w-full h-64 md:h-80 lg:h-96 object-cover" />
<div class="absolute inset-0 bg-gradient-to-t from-black/30 via-black/10 to-transparent"></div>
{{-- Optional overlay content --}}
@if(isset($content['stats']) && count($content['stats']) > 0)
<div class="absolute bottom-0 left-0 right-0 p-8">
<div class="flex items-center justify-center space-x-8 text-white/90 text-sm">
@foreach ($content['stats'] as $stat)
<span class="font-medium">{{ $stat }}</span>
@if (!$loop->last)
<span class="opacity-60">•</span>
@endif
@endforeach
</div>
</div>
@endif
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,84 @@
<section class="section-padding flex items-center relative border-b border-border/30">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 bg-hero-container rounded-[20px] w-[95%]">
<div class="grid lg:grid-cols-2 gap-12 lg:gap-16 items-center">
{{-- Left Content --}}
<div class="space-y-8">
<div class="space-y-6">
<h1 class="text-hero">
{!! $content['title'] !!}
</h1>
<p class="text-lg text-muted-foreground max-w-md leading-relaxed">
{!! $content['subtitle'] !!}
</p>
</div>
<div class="flex flex-col sm:flex-row gap-4">
<a href="{{ $content['cta1_link'] }}" class="btn-primary-accent">
{{ $content['cta1_text'] }}
</a>
<a href="{{ $content['cta2_link'] }}" class="btn-secondary-accent">
{{ $content['cta2_text'] }}
</a>
</div>
<div class="flex items-center space-x-8 text-sm text-muted-foreground">
@foreach ($content['stats'] as $stat)
<span>{{ $stat }}</span>
@if (!$loop->last)
<span>•</span>
@endif
@endforeach
</div>
</div>
{{-- Right Image Tiles --}}
<div class="relative">
<div class="flex justify-end gap-8 sm:-mt-44 sm:justify-start sm:pl-20 lg:mt-0 lg:pl-0">
{{-- First Column --}}
<div class="ml-auto w-44 flex-none space-y-8 pt-32 sm:ml-0 sm:pt-80 lg:order-last lg:pt-36 xl:order-0 xl:pt-80">
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
<img src="{{ theme_image_url($content['tiles'][0]['image']) }}"
alt="{{ $content['tiles'][0]['alt'] ?? '' }}"
class="aspect-2/3 w-full object-cover" />
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
</div>
</div>
{{-- Second Column --}}
<div class="mr-auto w-44 flex-none space-y-8 sm:mr-0 sm:pt-52 lg:pt-36">
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
<img src="{{ theme_image_url($content['tiles'][1]['image']) }}"
alt="{{ $content['tiles'][1]['alt'] ?? '' }}"
class="aspect-2/3 w-full object-cover" />
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
</div>
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
<img src="{{ theme_image_url($content['tiles'][2]['image']) }}"
alt="{{ $content['tiles'][2]['alt'] ?? '' }}"
class="aspect-2/3 w-full object-cover" />
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
</div>
</div>
{{-- Third Column --}}
<div class="w-44 flex-none space-y-8 pt-32 sm:pt-0">
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
<img src="{{ theme_image_url($content['tiles'][3]['image']) }}"
alt="{{ $content['tiles'][3]['alt'] ?? '' }}"
class="aspect-2/3 w-full object-cover" />
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
</div>
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
<img src="{{ theme_image_url($content['tiles'][4]['image']) }}"
alt="{{ $content['tiles'][4]['alt'] ?? '' }}"
class="aspect-2/3 w-full object-cover" />
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,49 @@
<section class="section-padding bg-accent">
<div class="container-padding">
<div class="text-center mb-16">
<h2 class="text-section-title mb-6">
{!! $content['title'] !!}
</h2>
<p class="text-large text-muted-foreground max-w-2xl mx-auto">
{{ $content['subtitle'] }}
</p>
</div>
<div class="grid md:grid-cols-3 gap-8">
@foreach($content['team'] as $member)
<div class="group">
<div class="card-elevated rounded-3xl overflow-hidden hover:scale-105 transition-all duration-300">
<div class="relative">
<img
src="{{ theme_image_url($member['image']) }}"
alt="{{ $member['name'] }} - {{ $member['position'] }}"
class="w-full h-80 object-cover"
/>
<div class="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent"></div>
</div>
<div class="p-6 space-y-4">
<div>
<h3 class="text-xl font-semibold text-foreground mb-1">
{{ $member['name'] }}
</h3>
<p class="text-secondary font-medium text-sm">
{{ $member['position'] }}
</p>
</div>
<p class="text-muted-foreground text-sm leading-relaxed">
{{ $member['expertise'] }}
</p>
<div class="flex items-center gap-2 pt-2">
<div class="w-8 h-px bg-secondary"></div>
<span class="text-xs text-secondary font-medium">{{ $content['team_tag'] }}</span>
</div>
</div>
</div>
</div>
@endforeach
</div>
</div>
</section>

View file

@ -0,0 +1,116 @@
<div>
<!-- Back Navigation -->
<div class="pt-4 pb-4 border-b border-border/30 ">
<div class="container-narrow ">
<a href="{{ $listUrl }}" class="inline-flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors">
<svg class="w-4 h-4" 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"/>
</svg>
{{ $content['back_to_magazine'] }}
</a>
</div>
</div>
<!-- Article Header -->
<article class="pb-16 pt-16">
<div class="container-narrow">
<header class="text-center mb-12 slide-up delay-200">
<h1 class="text-section-title mb-6 leading-tight">
{!! $article['title'] !!}
</h1>
<p class="text-large text-muted-foreground mb-8 max-w-3xl mx-auto">
{{ $article['subtitle'] }}
</p>
<div class="flex items-center justify-center gap-6 text-sm text-muted-foreground">
<div class="flex items-center gap-2">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
</svg>
<span>{{ $article['date'] }}</span>
</div>
<div class="flex items-center gap-2">
<svg class="w-4 h-4" 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"/>
</svg>
<span>{{ $article['readTime'] }}</span>
</div>
</div>
</header>
<!-- Featured Image -->
<div class="mb-12 overflow-hidden rounded-lg shadow-md slide-up delay-200">
<x-web-picture
src="{{ theme_image_url($article['image']) }}"
alt="{{ $article['title'] }}"
class="w-full h-64 md:h-96 object-cover"
/>
</div>
<div class="grid md:grid-cols-4 gap-12">
<!-- Main Content -->
<div class="md:col-span-4">
<div class="prose prose-lg max-w-none">
<p class="text-lg text-muted-foreground leading-relaxed mb-8 slide-up delay-200">
{{ $article['content']['intro'] }}
</p>
@foreach($article['content']['sections'] as $index => $section)
<section class="mb-10 bg-light-muted shadow-md p-6 rounded-lg slide-up delay-400" id="section-{{ $index }}">
<h2 class="text-2xl font-medium text-foreground mb-4">
{{ $index + 1 }}. {{ $section['title'] }}
</h2>
<p class="text-muted-foreground leading-relaxed">
{{ $section['content'] }}
</p>
</section>
@endforeach
</div>
</div>
<!-- Sidebar -->
{{-- <div class="md:col-span-1">
<div class="sticky top-24">
<div class="card-elevated rounded-lg p-2 slide-left delay-400">
<h3 class="font-medium text-foreground mb-4 text-center font-2xl py-2">{{ $content['share_article'] }}</h3>
<div class="space-y-3">
<button class="btn-secondary-accent w-full">
<div class="flex items-center justify-center gap-2">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
</svg>
<span class="font-medium text-sm">LinkedIn</span>
</div>
</button>
<button class="btn-secondary-accent w-full">
<div class="flex items-center justify-center gap-2">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
</svg>
<span class="font-medium text-sm">Facebook</span>
</div>
</button>
</div>
</div>
</div>
</div> --}}
</div>
</div>
</article>
<!-- Bottom CTA -->
<section class="bg-secondary text-secondary-foreground section-padding">
<div class="container-narrow text-center">
<div class="max-w-2xl mx-auto">
<h2 class="text-3xl font-light mb-6 text-white">
{!! $content['cta_title'] !!}
</h2>
<a href="{{ $listUrl }}" class="btn-primary-accent">
{{ $content['cta_button'] }}
</a>
</div>
</div>
</section>
</div>

View file

@ -0,0 +1,74 @@
<section id="magazin" class="section-padding">
<div class="container-padding">
<div class="text-center mb-16">
<h1 class="text-hero mb-6">
{!! $content['title'] !!}
</h1>
<p class="text-large text-muted-foreground mt-4 max-w-3xl mx-auto">
{{ $content['subtitle'] }}
</p>
</div>
<div class="space-y-8">
@foreach($this->posts as $post)
<article class="group">
<div class="card-elevated rounded-3xl overflow-hidden h-full transition-all duration-300">
<div class="flex flex-col lg:flex-row">
<div class="relative lg:w-3/4 aspect-[2/1] lg:aspect-[2/1]">
<x-web-picture
src="{{ theme_image_url($post['image']) }}"
alt="{{ $post['title'] }}"
class="w-full h-full object-cover"
/>
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
</div>
<div class="lg:w-2/3 p-6 lg:p-8 flex flex-col justify-between">
<div class="space-y-4">
<div class="flex items-center gap-4 text-sm text-muted-foreground">
<time>{{ $post['date'] }}</time>
<span class="w-1 h-1 bg-muted-foreground rounded-full"></span>
<span>{{ $post['readTime'] }}</span>
</div>
<h3 class="text-xl lg:text-2xl font-semibold text-foreground leading-tight group-hover:text-secondary transition-colors duration-200">
<a href="{{ route('magazin.detail', ['slug' => $post['slug']]) }}" class="stretched-link">
{!! $post['title'] !!}
</a>
</h3>
<p class="text-muted-foreground leading-relaxed text-base lg:text-lg">
{{ $post['excerpt'] }}
</p>
</div>
<div class="flex items-center justify-between mt-6">
<div class="flex items-center text-secondary font-medium group-hover:text-secondary-dark transition-colors duration-200">
<a href="{{ route('magazin.detail', ['slug' => $post['slug']]) }}" class="text-sm">{{ $content['read_more'] }}</a>
<svg class="w-4 h-4 ml-2 transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3" />
</svg>
</div>
<div class="w-10 h-10 bg-primary rounded-full flex items-center justify-center group-hover:bg-secondary transition-colors duration-200">
<a href="{{ route('magazin.detail', ['slug' => $post['slug']]) }}" aria-label="{{ __('ui.read_article', ['title' => $post['title']]) }}">
<svg class="w-4 h-4 text-white transform group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3" />
</svg>
</a>
</div>
</div>
</div>
</div>
</div>
</article>
@endforeach
</div>
{{-- <div class="text-center mt-16">
<a href="/magazin?page=2" class="btn-primary-accent">
{{ $content['load_more'] }}
</a>
</div> --}}
</div>
</section>

View file

@ -0,0 +1,154 @@
<section class="section-padding">
<div class="container-padding">
<div class="text-center mb-16">
<h2 class="text-section-title text-foreground mb-6">
{{ $content['title'] }}
</h2>
<p class="text-large text-muted-foreground max-w-3xl mx-auto">
{{ $content['subtitle'] }}
</p>
</div>
<div class="grid lg:grid-cols-2 gap-16">
{{-- Für Makler --}}
<div class="space-y-8">
<div class="text-center lg:text-left">
<div
class="inline-flex items-center gap-2 bg-secondary/10 text-secondary px-4 py-2 rounded-full text-sm font-medium mb-6">
<svg class="w-4 h-4" 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>
{{ $content['broker']['tag'] }}
</div>
<h3 class="text-3xl font-light text-foreground mb-6">
{!! $content['broker']['title'] !!}
</h3>
</div>
<div class="space-y-6">
@foreach ($content['broker']['benefits'] as $index => $benefit)
<div class="card-elevated p-6 rounded-xl">
<div class="flex gap-4">
<div
class="flex-shrink-0 w-12 h-12 rounded-xl bg-secondary/10 flex items-center justify-center">
@if ($benefit['icon'] === 'trending-up')
<svg class="w-6 h-6 text-secondary" 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>
@elseif($benefit['icon'] === 'target')
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
@else
<svg class="w-6 h-6 text-secondary" 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>
@endif
</div>
<div>
<h4 class="text-lg font-semibold text-foreground mb-2">
{{ $benefit['title'] }}
</h4>
<p class="text-muted-foreground">
{{ $benefit['description'] }}
</p>
</div>
</div>
</div>
@endforeach
</div>
<div class="bg-secondary/5 rounded-xl p-6">
<div class="text-center">
<div class="text-3xl font-bold text-secondary mb-2">{{ $content['broker']['highlight']['value'] }}</div>
<p class="text-sm text-muted-foreground">
{{ $content['broker']['highlight']['text'] }}
</p>
</div>
</div>
</div>
{{-- Für Lieferanten --}}
<div class="space-y-8">
<div class="text-center lg:text-left">
<div class="inline-flex items-center gap-2 bg-secondary/10 text-secondary px-4 py-2 rounded-full text-sm font-medium mb-6">
<svg class="w-4 h-4" 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>
{{ $content['supplier']['tag'] }}
</div>
<h3 class="text-3xl font-light text-foreground mb-6">
{!! $content['supplier']['title'] !!}
</h3>
</div>
<div class="space-y-6">
@foreach ($content['supplier']['benefits'] as $index => $benefit)
<div class="card-elevated p-6 rounded-xl">
<div class="flex gap-4">
<div
class="flex-shrink-0 w-12 h-12 rounded-xl bg-accent/20 flex items-center justify-center">
@if ($benefit['icon'] === 'globe')
<svg class="w-6 h-6 text-accent-foreground" 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>
@elseif($benefit['icon'] === 'handshake')
<svg class="w-6 h-6 text-accent-foreground" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.367 2.684 3 3 0 00-5.367-2.684z">
</path>
</svg>
@else
<svg class="w-6 h-6 text-accent-foreground" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z">
</path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
</svg>
@endif
</div>
<div>
<h4 class="text-lg font-semibold text-foreground mb-2">
{{ $benefit['title'] }}
</h4>
<p class="text-muted-foreground">
{{ $benefit['description'] }}
</p>
</div>
</div>
</div>
@endforeach
</div>
<div class="relative">
<div class="card-elevated p-0 overflow-hidden rounded-xl">
<img src="{{ theme_image_url($content['supplier']['highlight']['image']) }}" alt="{{ $content['supplier']['highlight']['alt'] }}"
class="w-full h-48 object-cover" />
<div class="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent flex items-end">
<div class="p-6 text-white">
<div class="text-2xl font-bold mb-1">{{ $content['supplier']['highlight']['value'] }}</div>
<p class="text-sm opacity-90">{{ $content['supplier']['highlight']['text'] }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,61 @@
<section class="section-padding flex items-center relative border-b border-border/30">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 bg-hero-container rounded-[20px] w-[95%]">
<div class="grid lg:grid-cols-2 gap-16 items-center">
<div class="space-y-8">
<div class="slide-right delay-300">
<h1 class="text-hero mb-6">
{!! $content['title'] !!}
</h1>
<p class="text-lg text-muted-foreground max-w-md leading-relaxed">
{{ $content['subtitle'] }}
</p>
</div>
@if(isset($content['partner_types']))
<div class="grid grid-cols-2 gap-6 mt-8 border-t border-border/50 pt-8">
@foreach ($content['partner_types'] as $index => $partner)
<div class="flex gap-4 slide-up delay-{{ $index * 200 }}">
<div class="flex-shrink-0 w-12 h-12 rounded-full bg-secondary/10 flex items-center justify-center">
@svg('heroicon-o-'.$partner['icon'], 'w-6 h-6 text-secondary')
</div>
<div>
<p class="font-semibold text-foreground">{{ $partner['title'] }}</p>
<p class="text-sm text-muted-foreground">{{ $partner['description'] }}</p>
</div>
</div>
@endforeach
</div>
@endif
@if(isset($content['stats']))
<div class="flex flex-wrap items-center gap-6 pt-10 border-t border-border/80 slide-right delay-300">
@foreach ($content['stats'] as $stat)
<div class="flex items-center gap-2 text-md text-muted-foreground">
@svg('heroicon-o-check-circle', 'w-6 h-6 text-secondary')
<span>{{ $stat }}</span>
</div>
@endforeach
</div>
@endif
</div>
<div class="relative">
<div class="relative rounded-3xl overflow-hidden shadow-elevated slide-left delay-300">
<img src="{{ theme_image_url($content['image']) }}"
alt="{{ $content['image_alt'] }}"
class="w-full h-[600px] object-cover" />
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
</div>
{{-- Floating info card --}}
<div
class="absolute bottom-6 left-6 bg-card/95 backdrop-blur-sm rounded-xl p-4 shadow-lg border border-border/50 slide-left delay-400">
<div class="text-xl font-medium text-muted-foreground">{!! $content['hub']['title'] !!}</div>
<div class="text-lg font-medium font-secondary">{!! $content['hub']['subtitle'] !!}</div>
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,49 @@
<section class="section-padding bg-accent">
<div class="container-padding">
<div class="text-center mb-16 slide-up delay-300">
<h2 class="text-section-title text-foreground mb-6">
{!! $content['title'] !!}
</h2>
<p class="text-large text-muted-foreground max-w-3xl mx-auto">
{{ $content['subtitle'] }}
</p>
</div>
<div class="grid md:grid-cols-3 gap-8 mb-16">
@foreach ($content['steps'] as $index => $step)
<div class="card-elevated p-0 overflow-hidden group hover:shadow-elevated transition-all duration-300 slide-up delay-{{ $index * 200 }}">
@if(isset($step['icon']))
<div class="relative pt-12 pb-8">
<div class="mx-auto w-20 h-20 icon-secondary-linear glow-soft group-hover:glow-medium rounded-2xl flex items-center justify-center transition-colors duration-300">
@svg('heroicon-o-'.$step['icon'], 'w-10 h-10 text-secondary-foreground')
</div>
</div>
@endif
<div class="p-8">
<div class="flex items-center gap-3 mb-4">
<div class="w-10 h-10 rounded-lg bg-secondary/10 flex items-center justify-center">
<span class="text-lg font-bold text-secondary">{{ $index + 1 }}</span>
</div>
<h3 class="text-2xl font-medium text-foreground">
{{ $step['title'] }}
</h3>
</div>
<p class="text-muted-foreground leading-relaxed mb-6">
{{ $step['description'] }}
</p>
@if ($index === count($content['steps']) - 1)
<a href="{{ $content['cta']['button_link'] }}">
<button class="btn-secondary-accent w-full cursor-pointer">
{{ $content['cta']['button_text'] }}
</button>
</a>
@endif
</div>
</div>
@endforeach
</div>
</div>
</section>

View file

@ -0,0 +1,299 @@
<section class="section-padding">
<div class="container-padding">
<!-- Header -->
<div class="text-center mb-16">
<h2 class="text-hero mb-6">
{!! $content['title'] !!}
</h2>
<p class="text-large text-muted-foreground max-w-2xl mx-auto">
{!! $content['subtitle'] !!}
</p>
</div>
<!-- Filter Navigation -->
<div class="flex flex-wrap justify-center gap-3 mb-12">
@foreach($this->filters as $filterKey => $filterLabel)
<button
wire:click="filterBy('{{ $filterKey }}')"
class="{{ $activeFilter === $filterKey
? 'btn-primary-accent'
: 'btn-secondary-accent' }}"
>
{{ $filterLabel }}
</button>
@endforeach
</div>
<!-- Portfolio Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"
x-data
x-init="$nextTick(() => {
// Smooth animation for grid changes
$el.style.opacity = '0';
setTimeout(() => { $el.style.opacity = '1'; }, 100);
})">
@foreach($this->getFilteredProjects() as $index => $project)
<div class="group card-elevated rounded-3xl overflow-hidden h-full hover:scale-[1.02] transition-all duration-300"
x-data="{ loaded: false }"
x-init="setTimeout(() => loaded = true, {{ $index * 100 }})"
x-show="loaded"
x-transition:enter="transition ease-out duration-700"
x-transition:enter-start="opacity-0 transform translate-y-8"
x-transition:enter-end="opacity-100 transform translate-y-0">
<!-- Image Container -->
<div class="relative aspect-[4/3] overflow-hidden cursor-pointer"
wire:click="openModal({{ json_encode($project) }})">
<img src="{{ theme_image_url($project['image']) }}"
alt="{{ $project['title'] }}"
class="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110">
<!-- Overlay -->
<div class="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
<!-- View Button -->
<div class="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-all duration-300">
<button class="btn-primary-accent">
<div class="flex items-center justify-center">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>
</svg>
<span class="font-medium"> {{ __('ui.view') }}</span>
</div>
</button>
</div>
<!-- Category Badge -->
<div class="absolute top-4 left-4">
<span class="bg-primary text-white px-3 py-1 rounded-full text-xs font-medium">
{{ $project['category'] }}
</span>
</div>
</div>
<!-- Content -->
<div class="p-6 lg:p-8 flex flex-col justify-between">
<div class="space-y-4">
<h3 class="text-2xl lg:text-3xl font-semibold text-foreground leading-tight group-hover:text-secondary transition-colors duration-200">
{{ $project['title'] }}
</h3>
<p class="text-muted-foreground leading-relaxed text-base line-clamp-2">
{{ $project['description'] }}
</p>
<!-- Features -->
<div class="flex flex-wrap gap-2">
@foreach($project['features'] as $feature)
<span class="text-xs bg-muted text-muted-foreground px-2 py-1 rounded">
{{ $feature }}
</span>
@endforeach
</div>
</div>
<!-- Location and Price -->
<div class="flex items-center justify-between mt-6">
<div class="flex items-center text-sm text-muted-foreground gap-4">
@if(isset($project['location']) && $project['location'] != '')
<div class="flex items-center gap-1">
<svg class="w-4 h-4" 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>
{{ $project['location'] }}
</div>
@endif
@if(isset($project['price']) && $project['price'] != '')
<span class="w-1 h-1 bg-muted-foreground rounded-full"></span>
<span class="font-medium text-secondary">{{ $project['price'] }}</span>
@endif
</div>
</div>
</div>
</div>
@endforeach
</div>
@if(empty($this->getFilteredProjects()))
<div class="text-center py-16">
<div class="w-24 h-24 mx-auto mb-4 bg-muted rounded-full flex items-center justify-center">
<svg class="w-12 h-12 text-muted-foreground" 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="text-lg font-medium text-foreground mb-2">{{ __('ui.portfolio.no_projects') }}</h3>
<p class="text-muted-foreground">{{ __('ui.portfolio.try_other_filter') }}</p>
</div>
@endif
</div>
<!-- Modal -->
<div x-data="{ show: @entangle('showModal').live }"
x-show="show"
x-cloak
class="fixed inset-0 z-50 overflow-y-auto"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
@click="$wire.closeModal()">
<!-- Backdrop -->
<div class="fixed inset-0 bg-black/70 backdrop-blur-sm"></div>
<!-- Modal Content -->
<div class="relative min-h-screen flex items-center justify-center p-4">
<div class="relative card-elevated rounded-3xl max-w-4xl w-full max-h-[90vh] overflow-hidden"
x-show="show"
x-transition:enter="transition ease-out duration-300 transform"
x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-200 transform"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.stop>
@if($selectedProject)
<!-- Close Button -->
<button @click="$wire.closeModal()"
class="absolute top-4 right-4 z-20 bg-secondary text-white rounded-full p-2 hover:bg-secondary/80 transition-colors duration-200">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
<!-- Scrollable Content Area -->
<div class="h-full max-h-[90vh] overflow-y-auto">
<!-- Image -->
<div class="aspect-[16/10] relative overflow-hidden rounded-t-2xl">
<img src="{{ theme_image_url($selectedProject['image']) }}"
alt="{{ $selectedProject['title'] }}"
class="w-full h-full object-cover">
<!-- Category Badge -->
<div class="absolute top-6 left-6">
<span class="bg-primary text-white px-4 py-2 rounded-full text-sm font-medium">
{{ $selectedProject['category'] }}
</span>
</div>
</div>
<!-- Content -->
<div class="p-8">
<div class="flex flex-col lg:flex-row lg:items-start lg:justify-between gap-6">
<div class="flex-1">
<h2 class="text-section-title mb-4">
{{ $selectedProject['title'] }}
</h2>
<p class="text-muted-foreground mb-6 leading-relaxed text-base lg:text-lg">
{{ $selectedProject['description'] }}
</p>
<!-- Features -->
<div class="mb-6">
<h4 class="font-semibold text-foreground mb-3">{{ __('ui.portfolio.amenities') }}</h4>
<div class="flex flex-wrap gap-2">
@foreach($selectedProject['features'] as $feature)
<span class="bg-muted text-muted-foreground px-3 py-1 rounded-full text-sm">
{{ $feature }}
</span>
@endforeach
</div>
</div>
</div>
<!-- Details Sidebar -->
<div class="lg:w-80 card-elevated rounded-lg p-6">
<h4 class="font-semibold text-foreground mb-4">{{ __('ui.portfolio.project_details') }}</h4>
<div class="space-y-4">
@if(isset($selectedProject['location']) && $selectedProject['location'] != '')
<div class="flex items-start gap-3">
<svg class="w-5 h-5 text-muted-foreground mt-0.5" 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>
<span class="text-sm text-muted-foreground">{{ __('ui.portfolio.location') }}</span>
<div class="font-medium text-foreground">{{ $selectedProject['location'] }}</div>
</div>
</div>
@endif
@if(isset($selectedProject['price']) && $selectedProject['price'] != '')
<div class="flex items-start gap-3">
<svg class="w-5 h-5 text-muted-foreground mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1"></path>
</svg>
<div>
<span class="text-sm text-muted-foreground">{{ __('ui.portfolio.price') }}</span>
<div class="font-bold text-lg text-secondary">{{ $selectedProject['price'] }}</div>
</div>
</div>
@endif
@if(isset($selectedProject['size']) && $selectedProject['size'] != '')
<div class="flex items-start gap-3">
<svg class="w-5 h-5 text-muted-foreground mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4a1 1 0 011-1h4m0 0V4m0-1h6m0 1v3M4 8h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V8z"></path>
</svg>
<div>
<span class="text-sm text-muted-foreground">{{ __('ui.portfolio.size') }}</span>
<div class="font-medium text-foreground">{{ $selectedProject['size'] }}</div>
</div>
</div>
@endif
</div>
<!-- CTA Button -->
<button class="btn-primary-accent w-full mt-6">
{{ __('ui.contact') }}
</button>
</div>
</div>
</div>
</div>
@endif
</div>
</div>
</div>
</section>
@push('styles')
<style>
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* Custom scrollbar for modal */
.overflow-y-auto::-webkit-scrollbar {
width: 6px;
}
.overflow-y-auto::-webkit-scrollbar-track {
background: transparent;
margin: 1rem 0;
}
.overflow-y-auto::-webkit-scrollbar-thumb {
background: hsl(var(--muted-foreground) / 0.3);
border-radius: 3px;
}
.overflow-y-auto::-webkit-scrollbar-thumb:hover {
background: hsl(var(--muted-foreground) / 0.5);
}
</style>
@endpush

View file

@ -0,0 +1,52 @@
<section class="section-padding bg-muted/20">
<div class="container-padding">
{{-- Section Title --}}
<div class="text-center mb-16">
<h2 class="text-section-title">{{ $content['title'] }}</h2>
<p class="text-large text-muted-foreground mt-4 max-w-2xl mx-auto">
{{ $content['subtitle'] }}
</p>
</div>
{{-- Spotlights Grid --}}
<div class="grid md:grid-cols-3 gap-8 lg:gap-12">
@foreach ($content['spotlights'] as $index => $spotlight)
<div class="text-center space-y-6 group">
<div
class="mx-auto w-20 h-20 bg-secondary/10 rounded-2xl flex items-center justify-center group-hover:bg-secondary/20 transition-colors duration-300">
@if ($spotlight['icon'] === 'map-pin')
<svg class="w-10 h-10 text-secondary" 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>
@elseif($spotlight['icon'] === 'star')
<svg class="w-10 h-10 text-secondary" 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>
@else
<svg class="w-10 h-10 text-secondary" 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>
@endif
</div>
<div class="space-y-4">
<h3 class="text-xl font-medium">{{ $spotlight['title'] }}</h3>
<p class="text-muted-foreground leading-relaxed">
{{ $spotlight['description'] }}
</p>
</div>
</div>
@endforeach
</div>
</div>
</section>

View file

@ -0,0 +1,90 @@
<section class="section-padding bg-accent">
<div class="container-padding">
<div class="grid lg:grid-cols-2 gap-16 items-center">
<div class="space-y-8">
<div>
<div class="inline-flex items-center gap-2 bg-secondary/10 text-secondary px-4 py-2 rounded-full text-sm font-medium mb-6">
<svg class="w-4 h-4" 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"/>
</svg>
{{ $content['tag'] }}
</div>
<h2 class="text-section-title mb-6">
{!! $content['title'] !!}
</h2>
<p class="text-large text-muted-foreground leading-relaxed">
{{ $content['subtitle'] }}
</p>
</div>
<div class="space-y-6">
@foreach($content['benefits'] as $benefit)
<div class="flex gap-4">
<div class="flex-shrink-0 w-12 h-12 rounded-xl bg-secondary/10 flex items-center justify-center">
@if($benefit['icon'] === 'store')
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"/>
</svg>
@elseif($benefit['icon'] === 'settings')
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
@elseif($benefit['icon'] === 'check-circle')
<svg class="w-6 h-6 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
@else
<svg class="w-6 h-6 text-secondary" 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"/>
</svg>
@endif
</div>
<div>
<h3 class="text-lg font-semibold text-foreground mb-2">
{{ $benefit['title'] }}
</h3>
<p class="text-muted-foreground">
{{ $benefit['description'] }}
</p>
</div>
</div>
@endforeach
</div>
</div>
<div class="relative">
<div class="card-elevated rounded-3xl p-8">
<div class="space-y-8">
<div class="text-center">
<div class="w-20 h-20 mx-auto rounded-full bg-gradient-to-br from-secondary/20 to-secondary/5 flex items-center justify-center mb-6">
<svg class="w-10 h-10 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"/>
</svg>
</div>
<h3 class="text-2xl font-semibold text-foreground mb-4">
{{ $content['dashboard']['title'] }}
</h3>
</div>
<div class="space-y-4">
@foreach($content['dashboard']['stats'] as $stat)
<div class="bg-accent/30 rounded-xl p-4">
<div class="flex items-center justify-between mb-2">
<span class="text-sm font-medium text-foreground">{{ $stat['label'] }}</span>
<span class="text-xs text-secondary">{{ $stat['value'] }}</span>
</div>
<div class="w-full bg-accent/50 rounded-full h-2">
<div class="bg-secondary h-2 rounded-full" style="width: {{ $stat['value'] }}"></div>
</div>
</div>
@endforeach
</div>
</div>
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,267 @@
<div>
<!-- Hero Section with Contact Form -->
<section id="kontakt" class="py-10 flex items-center relative overflow-hidden">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 bg-[hsl(var(--hero-container))] rounded-[20px] w-[95%]">
<div class="grid lg:grid-cols-2 gap-12 items-center">
<!-- Left Side - Hero Text -->
<div class="">
<h1 class="text-hero mb-6 tracking-wide">
{!! $content['hero']['title'] ?? 'Send us a<br /><span class="text-secondary font-medium">message.</span>' !!}
</h1>
<p class="text-large text-muted-foreground mb-8 max-w-md">
{{ $content['hero']['subtitle'] ?? 'Wir freuen uns auf Ihre Nachricht und werden uns schnellstmöglich bei Ihnen melden.' }}
</p>
</div>
<!-- Right Side - Contact Form -->
<div class="card-elevated p-8 ">
@if ($success)
<div class="flex flex-col items-center text-center py-8 gap-5">
<div class="flex items-center justify-center w-20 h-20 rounded-full bg-green-100">
<svg class="w-10 h-10 text-green-600" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
</div>
<div>
<p class="text-2xl font-semibold text-foreground">{{ __('ui.contact_form.success_title') }}</p>
<p class="text-muted-foreground mt-2 max-w-sm mx-auto">
{{ $content['form']['success_message'] ?? __('ui.contact_form.success_message') }}
</p>
</div>
</div>
@else
<form wire:submit="submit" class="space-y-6">
<div class="grid md:grid-cols-2 gap-4">
<div>
<label for="firstName" class="text-foreground mb-2 block text-sm font-medium">
{{ $content['form']['labels']['first_name'] ?? __('ui.contact_form.first_name') }}
</label>
<input
wire:model="firstName"
id="firstName"
type="text"
class="form-field"
required
/>
@error('firstName') <span class="text-red-500 text-xs">{{ $message }}</span> @enderror
</div>
<div>
<label for="lastName" class="text-foreground mb-2 block text-sm font-medium">
{{ $content['form']['labels']['last_name'] ?? __('ui.contact_form.last_name') }}
</label>
<input
wire:model="lastName"
id="lastName"
type="text"
class="form-field"
required
/>
@error('lastName') <span class="text-red-500 text-xs">{{ $message }}</span> @enderror
</div>
</div>
<div>
<label for="company" class="text-foreground mb-2 block text-sm font-medium">
{{ $content['form']['labels']['company'] ?? __('ui.contact_form.company') }}
</label>
<input
wire:model="company"
id="company"
type="text"
class="form-field"
/>
@error('company') <span class="text-red-500 text-xs">{{ $message }}</span> @enderror
</div>
<div class="grid md:grid-cols-2 gap-4">
<div>
<label for="email" class="text-foreground mb-2 block text-sm font-medium">
{{ $content['form']['labels']['email'] ?? __('ui.contact_form.email') }}
</label>
<input
wire:model="email"
id="email"
type="email"
class="form-field"
required
/>
@error('email') <span class="text-red-500 text-xs">{{ $message }}</span> @enderror
</div>
<div>
<label for="phone" class="text-foreground mb-2 block text-sm font-medium">
{{ $content['form']['labels']['phone'] ?? __('ui.contact_form.phone') }}
</label>
<input
wire:model="phone"
id="phone"
type="tel"
class="form-field"
/>
@error('phone') <span class="text-red-500 text-xs">{{ $message }}</span> @enderror
</div>
</div>
<div>
<label for="subject" class="text-foreground mb-2 block text-sm font-medium">
{{ $content['form']['labels']['subject'] ?? __('ui.contact_form.subject') }}
</label>
<div>
<select
wire:model="subject"
id="subject" name="subject"
class="form-field form-select">
<option value="">{{ $this->subjectPlaceholder }}</option>
@foreach($this->subjectGroups as $groupKey => $group)
@if ($group['label'] !== '')
<optgroup label="{{ $group['label'] }}">
@endif
@foreach($group['subjects'] as $value => $label)
<option value="{{ $value }}">{{ $label }}</option>
@endforeach
@if ($group['label'] !== '')
</optgroup>
@endif
@endforeach
</select>
</div>
@error('subject') <span class="text-red-500 text-xs">{{ $message }}</span> @enderror
</div>
<div>
<label for="message" class="text-foreground mb-2 block text-sm font-medium">
{{ $content['form']['labels']['message'] ?? __('ui.contact_form.message') }}
</label>
<textarea
wire:model="message"
id="message"
rows="5"
class="form-field resize-none"
placeholder="{{ $content['form']['placeholders']['message'] ?? __('ui.contact_form.message_placeholder') }}"
required
></textarea>
@error('message') <span class="text-red-500 text-xs">{{ $message }}</span> @enderror
</div>
{{-- Honeypot --}}
<div class="opacity-0 absolute top-0 left-0 h-0 w-0 -z-10 overflow-hidden" aria-hidden="true">
<label for="website">Website</label>
<input type="text" id="website" name="website" wire:model="website" tabindex="-1" autocomplete="off">
</div>
<div x-data="{ on: $wire.entangle('privacy') }">
<label class="flex items-start gap-3 cursor-pointer">
<input
x-model="on"
id="privacy"
type="checkbox"
class="sr-only"
/>
<span
role="switch"
:aria-checked="on.toString()"
:class="on ? 'bg-green-500' : 'bg-muted'"
class="relative mt-0.5 w-11 h-6 shrink-0 rounded-full transition-colors duration-200"
>
<span
:class="on ? 'translate-x-5' : 'translate-x-0'"
class="absolute top-0.5 left-0.5 h-5 w-5 rounded-full bg-white shadow-sm transition-transform duration-200 pointer-events-none"
></span>
</span>
<span class="text-sm text-muted-foreground">
{{ __('ui.contact_form.privacy_prefix') }}
<a href="{{ route('privacy') }}" target="_blank" class="text-secondary underline underline-offset-2 hover:no-underline">Datenschutzerklärung</a>
{{ __('ui.contact_form.privacy_suffix') }}
</span>
</label>
@error('privacy') <span class="text-red-500 text-xs mt-1 block">{{ $message }}</span> @enderror
</div>
<button
type="submit"
class="w-full btn-primary flex items-center justify-center"
wire:loading.attr="disabled"
>
<div class="flex items-center justify-center">
<span wire:loading.remove>{{ $content['form']['button_text'] ?? __('ui.contact_form.send') }}</span>
<span wire:loading>{{ $content['form']['button_loading'] ?? __('ui.contact_form.sending') }}</span>
<svg wire:loading.remove class="ml-2 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"/>
</svg>
</div>
</button>
<p class="text-sm text-muted-foreground">{{ __('ui.required_fields') }}</p>
</form>
@endif
</div>
</div>
</div>
</section>
<!-- Contact Information Cards -->
<section class="section-padding">
<div class="container-padding">
<div class="grid md:grid-cols-3 gap-8">
@foreach($this->contactInfo as $index => $info)
<div class="card-elevated p-8 rounded-xl text-center slide-up delay-{{ $index * 200 }}">
<div class="w-12 h-12 bg-secondary/20 rounded-full flex items-center justify-center mx-auto mb-4">
@if($info['icon'] === 'map-pin')
<svg class="w-6 h-6 text-secondary" 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 stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
@elseif($info['icon'] === 'mail')
<svg class="w-6 h-6 text-secondary" 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"/>
</svg>
@else
<svg class="w-6 h-6 text-secondary" 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"/>
</svg>
@endif
</div>
<h3 class="text-xl mb-2 text-foreground">{{ $info['title'] }}</h3>
<div class="text-muted-foreground text-base">
@foreach($info['info'] as $line)
<p>{{ $line }}</p>
@endforeach
</div>
</div>
@endforeach
</div>
</div>
</section>
<!-- Social Media Section -->
{{-- <section class="section-padding bg-accent">
<div class="container-padding">
<div class="grid lg:grid-cols-2 gap-12 items-center">
<div class="slide-right delay-200">
<h2 class="text-section-title mb-6">
{!! $content['social_media']['title'] ?? 'Follow for<br /><span class="text-secondary font-medium">exclusives</span>' !!}
</h2>
<p class="text-muted-foreground mb-8 max-w-md">
{{ $content['social_media']['subtitle'] ?? 'Bleiben Sie auf dem Laufenden mit exklusiven Angeboten und News.' }}
</p>
</div>
<div class="space-y-4">
@foreach($this->socialMedia as $index => $social)
<div class="flex items-center justify-between p-4 border border-border rounded-lg hover:bg-muted/50 transition-colors slide-left delay-{{ $index * 200 }} cursor-pointer">
<div>
<h3 class="text-xl text-foreground">{{ $social['name'] }}</h3>
<p class="text-sm text-muted-foreground">{{ $social['handle'] }}</p>
</div>
<svg class="w-4 h-4 text-muted-foreground" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"/>
</svg>
</div>
@endforeach
</div>
</div>
</div>
</section>
--}}
</div>

View file

@ -0,0 +1,32 @@
@extends('web.layouts.web-master')
@section('title', 'Über B2IN - Unser Team & Geschichte')
@section('content')
<div class="bg-background">
<livewire:web.components.ui.header />
<main class="variante-glass-flow">
<livewire:web.components.sections.about-hero />
<livewire:web.components.sections.founder-bar />
<livewire:web.components.sections.our-story />
<livewire:web.components.sections.leadership-team />
<livewire:web.components.sections.our-values />
<livewire:web.components.sections.partner-c-t-a />
</main>
<livewire:web.components.ui.footer />
</div>
@endsection
@push('styles')
<style>
[x-cloak] {
display: none !important;
}
</style>
@endpush
@push('scripts')
{{-- Alpine.js wird zentral im Layout geladen --}}
@endpush

View file

@ -0,0 +1,33 @@
@extends('web.layouts.web-master')
@section('title', 'B2IN - Connecting Design and Property')
@section('content')
<div class="bg-background">
<livewire:web.components.ui.header />
<main>
<livewire:web.components.sections.hero />
<livewire:web.components.sections.founder-bar />
<livewire:web.components.sections.content-section section="synergie_section" layout="left" />
<livewire:web.components.sections.vision-section bg="bg-accent" />
<livewire:web.components.sections.ecosystem-core />
<livewire:web.components.sections.c-t-a-section />
</main>
<livewire:web.components.ui.footer />
</div>
@endsection
@push('styles')
<style>
[x-cloak] {
display: none !important;
}
</style>
@endpush
@push('scripts')
{{-- Alpine.js wird zentral im Layout geladen --}}
@endpush

View file

@ -0,0 +1,134 @@
@extends('web.layouts.web-master')
@section('title', 'Internationale Immobilien - B2in')
@section('content')
<div class="bg-background">
<livewire:web.components.ui.header />
<main class="variante-glass-flow">
<livewire:web.components.sections.partner-hero section="immobilien_hero" />
<livewire:web.components.sections.founder-bar />
{{-- Aktuelle Projekte --}}
@php
$projects = cms_theme_section('immobilien_projects');
$moebelVorteil = cms_theme_section('immobilien_moebel_vorteil');
@endphp
@if (!empty($projects))
<section class="section-padding">
<div class="container-padding">
<div class="text-center mb-12 slide-up delay-300">
<h2 class="text-section-title">{!! $projects['title'] ?? '' !!}</h2>
@if (isset($projects['subtitle']))
<p class="text-large text-muted-foreground mt-4 max-w-2xl mx-auto">
{{ $projects['subtitle'] }}
</p>
@endif
</div>
<div class="grid md:grid-cols-1 lg:grid-cols-2 gap-8 slide-up delay-400">
@foreach ($projects['projects'] ?? [] as $project)
<div class="card-elevated rounded-2xl overflow-hidden">
@if (isset($project['image']))
<div class="relative h-56 overflow-hidden">
<img src="{{ theme_image_url($project['image']) }}"
alt="{{ $project['title'] }}"
class="w-full h-full object-cover" />
@if (isset($project['status']))
<div class="absolute top-4 left-4">
<span class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-xs font-semibold bg-secondary text-white">
{{ $project['status'] }}
@if (isset($project['launch_date']))
<span class="opacity-80">({{ $project['launch_date'] }})</span>
@endif
</span>
</div>
@endif
</div>
@endif
<div class="p-6 lg:p-8">
<div class="mb-4">
<h3 class="text-xl font-semibold text-foreground">{{ $project['title'] }}</h3>
@if (isset($project['location']))
<p class="text-sm text-muted-foreground mt-1">{{ $project['location'] }}</p>
@endif
</div>
@if (isset($project['price_from']))
<p class="text-lg font-medium text-secondary mb-4">{{ $project['price_from'] }}</p>
@endif
@if (isset($project['highlights']))
<ul class="space-y-2 mb-6">
@foreach ($project['highlights'] as $highlight)
<li class="flex items-start gap-2 text-sm text-muted-foreground">
<svg class="w-4 h-4 text-secondary mt-0.5 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
{{ $highlight }}
</li>
@endforeach
</ul>
@endif
<a href="{{ isset($project['slug']) ? route('immobilien.show', $project['slug']) : ($projects['cta_link'] ?? '/contact') }}"
class="inline-flex items-center gap-2 btn-primary-accent">
{{ isset($project['slug']) ? 'Exposé ansehen' : ($projects['cta_text'] ?? 'Anfragen') }}
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3" />
</svg>
</a>
</div>
</div>
@endforeach
</div>
</div>
</section>
@endif
{{-- Möbel-Vorteil Banner --}}
@if (!empty($moebelVorteil))
<section class="section-padding bg-secondary/5">
<div class="container-padding">
<div class="max-w-3xl mx-auto text-center slide-up delay-300">
<h2 class="text-section-title">{!! $moebelVorteil['title'] ?? '' !!}</h2>
<p class="text-large text-muted-foreground mt-4">
{{ $moebelVorteil['text'] ?? '' }}
</p>
@if (isset($moebelVorteil['button_text']))
<div class="mt-8">
<a href="{{ $moebelVorteil['button_link'] ?? '/partner' }}"
class="btn-secondary-accent">
{{ $moebelVorteil['button_text'] }}
</a>
</div>
@endif
</div>
</div>
</section>
@endif
{{-- Trust & Kontakt --}}
<livewire:web.components.sections.content-section section="immobilien_trust" layout="right" />
<livewire:web.components.sections.c-t-a-section />
</main>
<livewire:web.components.ui.footer />
</div>
@endsection
@push('styles')
<style>
[x-cloak] {
display: none !important;
}
</style>
@endpush
@push('scripts')
{{-- Alpine.js wird zentral im Layout geladen --}}
@endpush

View file

@ -0,0 +1,160 @@
@extends('web.layouts.web-master')
@section('title', 'Einrichtungsnetzwerk - B2in Interior')
@section('content')
<div class="bg-background">
<livewire:web.components.ui.header />
<main class="variante-glass-flow">
<livewire:web.components.sections.partner-hero section="interior_hero" />
<livewire:web.components.sections.founder-bar />
{{-- Local-for-Local Konzept --}}
<livewire:web.components.sections.content-section section="interior_concept" layout="left" />
{{-- Zwei Marken --}}
@php
$brands = cms_theme_section('interior_brands');
$zielgruppen = cms_theme_section('interior_zielgruppen');
$process = cms_theme_section('interior_process');
@endphp
@if (!empty($brands))
<section class="section-padding bg-accent">
<div class="container-padding">
<div class="text-center mb-12 slide-up delay-300">
<h2 class="text-section-title">{!! $brands['title'] ?? '' !!}</h2>
@if (isset($brands['subtitle']))
<p class="text-large text-muted-foreground mt-4 max-w-2xl mx-auto">
{{ $brands['subtitle'] }}
</p>
@endif
</div>
<div class="grid md:grid-cols-2 gap-8 max-w-4xl mx-auto slide-up delay-400">
@foreach ($brands['brands'] ?? [] as $brand)
<div class="card-elevated rounded-2xl overflow-hidden">
<div class="p-8 lg:p-10">
@if (isset($brand['logo']))
<div class="mb-6">
<img src="{{ asset($brand['logo']) }}"
alt="{{ $brand['name'] }}"
class="{{ $brand['logo_width'] ?? 'w-32' }}" />
</div>
@endif
<p class="text-xs font-semibold uppercase tracking-wider text-secondary mb-3">
{{ $brand['tagline'] ?? '' }}
</p>
<p class="text-muted-foreground leading-relaxed">
{{ $brand['description'] ?? '' }}
</p>
@if (isset($brand['audience']))
<p class="text-sm font-medium text-foreground mt-4">
{{ $brand['audience'] }}
</p>
@endif
@if (isset($brand['link']))
<div class="mt-6">
<a href="{{ $brand['link'] }}"
target="_blank" rel="noopener"
class="inline-flex items-center gap-2 text-sm font-medium text-secondary hover:text-secondary/80 transition-colors">
{{ $brand['name'] }} entdecken
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
</svg>
</a>
</div>
@endif
</div>
</div>
@endforeach
</div>
</div>
</section>
@endif
{{-- Für wen? Zielgruppen --}}
@if (!empty($zielgruppen))
<section class="section-padding">
<div class="container-padding">
<div class="text-center mb-12 slide-up delay-300">
<h2 class="text-section-title">{!! $zielgruppen['title'] ?? '' !!}</h2>
</div>
<div class="grid md:grid-cols-3 gap-8 max-w-5xl mx-auto slide-up delay-400">
@foreach ($zielgruppen['groups'] ?? [] as $group)
<div class="text-center p-6">
<div class="inline-flex items-center justify-center w-14 h-14 rounded-full bg-secondary/10 text-secondary mb-5">
<svg class="w-7 h-7" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
@switch($group['icon'] ?? '')
@case('home')
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
@break
@case('building-office-2')
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 21h19.5m-18-18v18m10.5-18v18m6-13.5V21M6.75 6.75h.75m-.75 3h.75m-.75 3h.75m3-6h.75m-.75 3h.75m-.75 3h.75M6.75 21v-3.375c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21M3 3h12m-.75 4.5H21m-3.75 3.75h.008v.008h-.008v-.008zm0 3h.008v.008h-.008v-.008zm0 3h.008v.008h-.008v-.008z" />
@break
@case('clipboard-document-check')
<path stroke-linecap="round" stroke-linejoin="round" d="M11.35 3.836c-.065.21-.1.433-.1.664 0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75 2.25 2.25 0 00-.1-.664m-5.8 0A2.251 2.251 0 0113.5 2.25H15c1.012 0 1.867.668 2.15 1.586m-5.8 0c-.376.023-.75.05-1.124.08C9.095 4.01 8.25 4.973 8.25 6.108V8.25m8.9-4.414c.376.023.75.05 1.124.08 1.131.094 1.976 1.057 1.976 2.192V16.5A2.25 2.25 0 0118 18.75h-2.25m-7.5-10.5H4.875c-.621 0-1.125.504-1.125 1.125v11.25c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V18.75m-7.5-10.5h6.375c.621 0 1.125.504 1.125 1.125v9.375m-8.25-3l1.5 1.5 3-3.75" />
@break
@endswitch
</svg>
</div>
<h3 class="text-lg font-semibold text-foreground mb-3">{{ $group['title'] ?? '' }}</h3>
<p class="text-sm text-muted-foreground leading-relaxed">{{ $group['description'] ?? '' }}</p>
</div>
@endforeach
</div>
</div>
</section>
@endif
{{-- So funktioniert es - Prozess --}}
@if (!empty($process))
<section class="section-padding bg-accent">
<div class="container-padding">
<div class="text-center mb-12 slide-up delay-300">
<h2 class="text-section-title">{!! $process['title'] ?? '' !!}</h2>
</div>
<div class="max-w-3xl mx-auto slide-up delay-400">
<div class="space-y-8">
@foreach ($process['steps'] ?? [] as $step)
<div class="flex gap-6 items-start">
<div class="shrink-0 w-14 h-14 rounded-full bg-secondary text-white flex items-center justify-center text-lg font-bold">
{{ $step['number'] ?? '' }}
</div>
<div class="pt-2">
<h3 class="text-lg font-semibold text-foreground mb-2">{{ $step['title'] ?? '' }}</h3>
<p class="text-muted-foreground leading-relaxed">{{ $step['description'] ?? '' }}</p>
</div>
</div>
@endforeach
</div>
</div>
</div>
</section>
@endif
{{-- Trust / Marcel Scheibe --}}
<livewire:web.components.sections.content-section section="interior_trust" layout="right" />
{{-- CTA --}}
<livewire:web.components.sections.c-t-a-section />
</main>
<livewire:web.components.ui.footer />
</div>
@endsection
@push('styles')
<style>
[x-cloak] {
display: none !important;
}
</style>
@endpush
@push('scripts')
{{-- Alpine.js wird zentral im Layout geladen --}}
@endpush

View file

@ -0,0 +1,38 @@
@extends('web.layouts.web-master')
@section('title', 'Für Entwickler & Partner - B2in')
@section('content')
<div class="bg-background">
<livewire:web.components.ui.header />
<main class="variante-glass-flow">
<livewire:web.components.sections.partner-hero />
<livewire:web.components.sections.founder-bar />
<livewire:web.components.sections.content-section section="supply_chain_intro" layout="left" bg="bg-accent" />
<livewire:web.components.sections.card-section section="partner_card_section" />
<livewire:web.components.sections.benefits-section section="partner_benefits_developer" />
<livewire:web.components.sections.benefits-section section="partner_benefits_retailer" layout="right" bg="bg-accent" />
<livewire:web.components.sections.benefits-section section="partner_benefits_supplier" />
<livewire:web.components.sections.benefits-section section="partner_benefits_broker" layout="right" bg="bg-accent" />
<livewire:web.components.sections.partner-process />
<livewire:web.components.sections.commitment-section />
<livewire:web.components.sections.partner-c-t-a />
</main>
<livewire:web.components.ui.footer />
</div>
@endsection
@push('styles')
<style>
[x-cloak] {
display: none !important;
}
</style>
@endpush
@push('scripts')
{{-- Alpine.js wird zentral im Layout geladen --}}
@endpush

View file

@ -0,0 +1,36 @@
@extends('web.layouts.web-master')
@section('title', 'B2in Ecosystem - Intelligentes Netzwerk')
@section('content')
<div class="bg-background">
<livewire:web.components.ui.header />
<main class="variante-glass-flow">
<livewire:web.components.sections.partner-hero section="ecosystem_hero" />
<livewire:web.components.sections.ecosystem-stats />
<livewire:web.components.sections.content-section layout="right" bg="bg-accent"
section="ecosystem_start" />
<livewire:web.components.sections.content-section layout="left" bg=""
section="ecosystem_hub" />
<livewire:web.components.sections.content-section layout="right" bg="bg-accent"
section="ecosystem_result" />
<livewire:web.components.sections.digital-core />
<livewire:web.components.sections.partner-c-t-a />
</main>
<livewire:web.components.ui.footer />
</div>
@endsection
@push('styles')
<style>
[x-cloak] {
display: none !important;
}
</style>
@endpush
@push('scripts')
{{-- Alpine.js wird zentral im Layout geladen --}}
@endpush

View file

@ -0,0 +1,70 @@
@extends('web.layouts.web-master')
@section('title', 'Home - ' . config('app.name'))
@section('content')
<div class="min-h-screen bg-background">
<livewire:web.components.ui.header />
<main>
<section class="section-padding">
<div class="container-padding">
<div class="text-center mb-16">
<h1 class="text-section-title">Willkommen bei {{ config('app.name') }}</h1>
<p class="text-large text-muted-foreground mt-4 max-w-2xl mx-auto">
Dies ist die Home-Seite mit dem {{ ucfirst(config('app.theme')) }} Theme.
</p>
</div>
<div class="max-w-4xl mx-auto">
<div class="bg-card/95 backdrop-blur-sm rounded-xl p-8 shadow-lg border border-border/50 spacing-content">
<h2 class="text-2xl font-medium mb-6 text-primary">Features</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="space-y-4">
<div class="flex items-center space-x-3">
<div class="w-2 h-2 bg-secondary rounded-full"></div>
<span class="text-muted-foreground">Responsive Design</span>
</div>
<div class="flex items-center space-x-3">
<div class="w-2 h-2 bg-secondary rounded-full"></div>
<span class="text-muted-foreground">Mehrere Themes</span>
</div>
</div>
<div class="space-y-4">
<div class="flex items-center space-x-3">
<div class="w-2 h-2 bg-secondary rounded-full"></div>
<span class="text-muted-foreground">Dark Mode Unterstützung</span>
</div>
<div class="flex items-center space-x-3">
<div class="w-2 h-2 bg-secondary rounded-full"></div>
<span class="text-muted-foreground">Adaptive Farbschemata</span>
</div>
</div>
</div>
<div class="text-center mt-8">
<a href="{{ url('/welcome') }}" class="btn-primary-accent">
Zur Willkommensseite
</a>
</div>
</div>
</div>
</div>
</section>
</main>
<livewire:web.components.ui.footer />
</div>
@endsection
@push('styles')
<style>
[x-cloak] {
display: none !important;
}
</style>
@endpush
@push('scripts')
{{-- Alpine.js wird zentral im Layout geladen --}}
@endpush

View file

@ -0,0 +1,363 @@
@extends('web.layouts.web-master')
@section('title', ($project['title'] ?? 'Exposé') . ' - B2in Immobilien')
@section('meta_description', ($project['investment_case']['text'] ?? 'Exklusives Off-Market-Immobilienprojekt in Dubai – jetzt Exposé ansehen.'))
@section('content')
<div class="bg-background">
<livewire:web.components.ui.header />
<main class="variante-glass-flow">
{{-- 1. Hero --}}
<section class="relative h-[50vh] min-h-[400px] overflow-hidden">
<x-web-picture
src="{{ theme_image_url($project['image'] ?? '') }}"
alt="{{ $project['title'] ?? '' }}"
class="absolute inset-0 w-full h-full object-cover"
loading="" />
<div class="absolute inset-0 bg-gradient-to-t from-black/70 via-black/30 to-transparent"></div>
<div class="absolute bottom-0 left-0 right-0 p-8 lg:p-12">
<div class="container-padding">
@if (isset($project['status']))
<span class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-xs font-semibold bg-secondary text-white mb-4">
{{ $project['status'] }}
@if (isset($project['launch_date']))
<span class="opacity-80">({{ $project['launch_date'] }})</span>
@endif
</span>
@endif
<h1 class="text-3xl lg:text-4xl font-bold text-white">{{ $project['title'] ?? '' }}</h1>
@if (isset($project['location']))
<p class="text-lg text-white/80 mt-2">{{ $project['location'] }}</p>
@endif
@if (isset($project['price_from']))
<p class="text-xl font-semibold text-white mt-3">{{ $project['price_from'] }}</p>
@endif
</div>
</div>
</section>
{{-- 2. Quick Facts --}}
{{-- Editierbar über CMS je Projekt --}}
@if (!empty($project['quick_facts']))
<section class=" bg-accent">
<div class="container-padding">
<div class="grid grid-cols-2 lg:grid-cols-4 gap-6">
@foreach ($project['quick_facts'] as $fact)
<div class="text-center p-4">
<div class="inline-flex items-center justify-center w-12 h-12 rounded-full bg-secondary/10 text-secondary mb-3">
@if (isset($fact['icon']))
<svg class="w-6 h-6" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
@switch($fact['icon'])
@case('home-modern')
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 21v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21m0 0h4.5V3.545M12.75 21h7.5V10.75M2.25 21h1.5m18 0h-18M2.25 9l4.5-1.636M18.75 3l-1.5.545m0 6.205l3 1m1.5.5l-1.5-.5M6.75 7.364V3h-3v18m3-13.636l10.5-3.819" />
@break
@case('squares-2x2')
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6A2.25 2.25 0 016 3.75h2.25A2.25 2.25 0 0110.5 6v2.25a2.25 2.25 0 01-2.25 2.25H6a2.25 2.25 0 01-2.25-2.25V6zM3.75 15.75A2.25 2.25 0 016 13.5h2.25a2.25 2.25 0 012.25 2.25V18a2.25 2.25 0 01-2.25 2.25H6A2.25 2.25 0 013.75 18v-2.25zM13.5 6a2.25 2.25 0 012.25-2.25H18A2.25 2.25 0 0120.25 6v2.25A2.25 2.25 0 0118 10.5h-2.25a2.25 2.25 0 01-2.25-2.25V6zM13.5 15.75a2.25 2.25 0 012.25-2.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-2.25A2.25 2.25 0 0113.5 18v-2.25z" />
@break
@case('building-office-2')
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 21h19.5m-18-18v18m10.5-18v18m6-13.5V21M6.75 6.75h.75m-.75 3h.75m-.75 3h.75m3-6h.75m-.75 3h.75m-.75 3h.75M6.75 21v-3.375c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21M3 3h12m-.75 4.5H21m-3.75 3.75h.008v.008h-.008v-.008zm0 3h.008v.008h-.008v-.008zm0 3h.008v.008h-.008v-.008z" />
@break
@case('user')
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z" />
@break
@endswitch
</svg>
@endif
</div>
<p class="text-xs text-muted-foreground uppercase tracking-wider mb-1">{{ $fact['label'] ?? '' }}</p>
<p class="text-sm font-semibold text-foreground">{{ $fact['value'] ?? '' }}</p>
</div>
@endforeach
</div>
</div>
</section>
@endif
{{-- 3. Investment Case --}}
@if (!empty($project['investment_case']))
<section class="section-padding">
<div class="container-padding">
<div class="max-w-3xl mx-auto">
<h2 class="text-section-title text-left">{{ $project['investment_case']['title'] ?? '' }}</h2>
<p class="text-large text-muted-foreground mt-6 leading-relaxed">
{{ $project['investment_case']['text'] ?? '' }}
</p>
@if (!empty($project['investment_case']['views']))
<div class="mt-8">
<p class="text-sm font-semibold text-foreground mb-3">Verfügbare Views:</p>
<div class="flex flex-wrap gap-2">
@foreach ($project['investment_case']['views'] as $view)
<span class="inline-flex items-center px-3 py-1.5 rounded-full text-xs font-medium bg-secondary/10 text-secondary">
{{ $view }}
</span>
@endforeach
</div>
</div>
@endif
@if (!empty($project['highlights']))
<ul class="mt-8 space-y-3">
@foreach ($project['highlights'] as $highlight)
<li class="flex items-start gap-3 text-muted-foreground">
<svg class="w-5 h-5 text-secondary mt-0.5 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
{{ $highlight }}
</li>
@endforeach
</ul>
@endif
</div>
</div>
</section>
@endif
{{-- 4. Bildergalerie --}}
@if (!empty($project['gallery']))
<div x-data="{ lightbox: false, current: 0 }">
<section class="section-padding bg-accent">
<div class="container-padding">
<h2 class="text-section-title text-center mb-8">Galerie</h2>
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-3 gap-4">
@foreach ($project['gallery'] as $index => $image)
<div class="relative aspect-[4/3] rounded-xl overflow-hidden cursor-pointer group"
@click="lightbox = true; current = {{ $index }}">
<x-web-picture
src="{{ theme_image_url($image) }}"
alt="{{ $project['title'] ?? '' }} – Bild {{ $index + 1 }}"
class="w-full h-full object-cover transition-transform duration-300 group-hover:scale-105" />
<div class="absolute inset-0 bg-black/0 group-hover:bg-black/20 transition-colors duration-300"></div>
</div>
@endforeach
</div>
</div>
</section>
{{-- Lightbox (via x-teleport ins body, umgeht alle Eltern-Constraints) --}}
<template x-teleport="body">
<div x-show="lightbox" x-cloak
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
class="fixed inset-0 z-50 isolate bg-black/90"
@keydown.escape.window="lightbox = false"
@keydown.arrow-right.window="current = (current + 1) % {{ count($project['gallery']) }}"
@keydown.arrow-left.window="current = (current - 1 + {{ count($project['gallery']) }}) % {{ count($project['gallery']) }}">
{{-- Bildbereich (eigene Ebene, dahinter) --}}
<div class="absolute inset-0 flex items-center justify-center p-4 z-0">
@foreach ($project['gallery'] as $index => $image)
<x-web-picture x-show="current === {{ $index }}"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100"
src="{{ theme_image_url($image) }}"
alt="{{ $project['title'] ?? '' }} – Bild {{ $index + 1 }}"
class="max-h-[85vh] max-w-[90vw] object-contain rounded-lg"
loading="" />
@endforeach
</div>
{{-- Close Button (oben rechts mit Abstand) --}}
<button @click="lightbox = false"
class="cursor-pointer absolute top-6 left-auto right-6 z-10 flex items-center justify-center w-12 h-12 rounded-full bg-white/10 hover:bg-white/20 text-white/90 hover:text-white border border-white/20 transition-all">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
{{-- Previous (links, vertikal mittig) --}}
<button @click="current = (current - 1 + {{ count($project['gallery']) }}) % {{ count($project['gallery']) }}"
class="cursor-pointer absolute left-6 top-1/2 -translate-y-1/2 z-10 flex items-center justify-center w-14 h-14 rounded-full bg-white/10 hover:bg-white/20 text-white/90 hover:text-white border border-white/20 transition-all">
<svg class="w-7 h-7" 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" />
</svg>
</button>
{{-- Next (rechts, vertikal mittig) --}}
<button @click="current = (current + 1) % {{ count($project['gallery']) }}"
class="cursor-pointer absolute left-auto right-6 top-1/2 -translate-y-1/2 z-10 flex items-center justify-center w-14 h-14 rounded-full bg-white/10 hover:bg-white/20 text-white/90 hover:text-white border border-white/20 transition-all">
<svg class="w-7 h-7" 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" />
</svg>
</button>
{{-- Counter --}}
<div class="absolute bottom-4 left-1/2 -translate-x-1/2 z-10 text-white/60 text-sm">
<span x-text="current + 1"></span> / {{ count($project['gallery']) }}
</div>
</div>
</template>
</div>
@endif
{{-- 5. Trust-Block: Investorenschutz (pro Projekt im CMS, siehe investor_trust) --}}
@php
$trust = $project['investor_trust'] ?? [];
$trustColumns = $trust['columns'] ?? [];
@endphp
@if (! empty($trust['title']) || count($trustColumns) > 0)
<section class="section-padding">
<div class="container-padding">
<div class="max-w-4xl mx-auto">
@if (! empty($trust['title']) || ! empty($trust['intro']))
<div class="text-center mb-10">
@if (! empty($trust['title']))
<h2 class="text-section-title">{{ $trust['title'] }}</h2>
@endif
@if (! empty($trust['intro']))
<p class="text-large text-muted-foreground mt-4 max-w-2xl mx-auto">
{{ $trust['intro'] }}
</p>
@endif
</div>
@endif
@if (count($trustColumns) > 0)
<div class="grid md:grid-cols-3 gap-6 mb-10">
@foreach ($trustColumns as $col)
<div class="card-elevated rounded-2xl p-6 text-center">
<div class="inline-flex items-center justify-center w-14 h-14 rounded-full bg-secondary/10 text-secondary mb-5">
@if (! empty($col['icon']))
@svg($col['icon'], 'w-7 h-7')
@endif
</div>
<h3 class="text-base font-semibold text-foreground mb-3">{{ $col['title'] ?? '' }}</h3>
<p class="text-sm text-muted-foreground leading-relaxed">
{{ $col['text'] ?? '' }}
</p>
</div>
@endforeach
</div>
@endif
@if (! empty($trust['cta_url']) && ! empty($trust['cta_label']))
<div class="text-center">
<a href="{{ $trust['cta_url'] }}" class="btn-secondary-accent transition-colors duration-200">
<span class="flex items-center justify-center gap-2">
@svg('heroicon-o-book-open', 'w-4 h-4')
<span>{{ $trust['cta_label'] }}</span>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3" />
</svg>
</span>
</a>
</div>
@endif
</div>
</div>
</section>
@endif
{{-- 6. Location & Map --}}
@if (!empty($project['location_info']))
<section class="section-padding bg-accent">
<div class="container-padding">
<div class="max-w-3xl mx-auto">
<h2 class="text-section-title text-left">{{ $project['location_info']['title'] ?? '' }}</h2>
@if (!empty($project['location_info']['points']))
<ul class="mt-8 space-y-4">
@foreach ($project['location_info']['points'] as $point)
<li class="flex items-start gap-3 text-muted-foreground">
<svg class="w-5 h-5 text-secondary mt-0.5 shrink-0 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 10.5a3 3 0 11-6 0 3 3 0 016 0z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.5 10.5c0 7.142-7.5 11.25-7.5 11.25S4.5 17.642 4.5 10.5a7.5 7.5 0 1115 0z" />
</svg>
{{ $point }}
</li>
@endforeach
</ul>
@endif
@if (isset($project['location_info']['map_url']))
<div class="mt-8 text-center">
<a href="{{ $project['location_info']['map_url'] }}"
target="_blank" rel="noopener"
class="inline-flex items-center gap-2 btn-secondary-accent">
<svg class="w-4 h-4 inline-block mr-2 mb-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" />
</svg>
Auf Google Maps ansehen
</a>
</div>
@endif
</div>
</div>
</section>
@endif
{{-- Möbel-Vorteil / Synergie (pro Projekt: furniture_benefit; Fallback: Theme-Config) --}}
@php
$moebelVorteil = $project['furniture_benefit'] ?? [];
if (empty($moebelVorteil) || (empty($moebelVorteil['title'] ?? null) && empty($moebelVorteil['text'] ?? null))) {
$moebelVorteil = cms_theme_section('immobilien_moebel_vorteil');
}
@endphp
@if (! empty($moebelVorteil))
<section class="section-padding bg-secondary/5">
<div class="container-padding">
<div class="max-w-3xl mx-auto text-center">
<h2 class="text-section-title">{!! $moebelVorteil['title'] ?? '' !!}</h2>
<p class="text-large text-muted-foreground mt-4">
{{ $moebelVorteil['text'] ?? '' }}
</p>
@if (! empty($moebelVorteil['button_text'] ?? null))
<div class="mt-8">
<a href="{{ $moebelVorteil['button_link'] ?? '/partner' }}"
class="btn-secondary-accent">
{{ $moebelVorteil['button_text'] }}
</a>
</div>
@endif
</div>
</div>
</section>
@endif
{{-- 7. Lead-Generierung / Kontakt --}}
@if (!empty($project['contact']))
<section class="section-padding bg-accent">
<div class="container-padding">
<div class="max-w-2xl mx-auto text-center">
<h2 class="text-section-title">{{ $project['contact']['title'] ?? '' }}</h2>
@if (isset($project['contact']['subtitle']))
<p class="text-large text-muted-foreground mt-3">{{ $project['contact']['subtitle'] }}</p>
@endif
<div class="mt-8 card-elevated rounded-2xl p-8 text-left">
<livewire:web.components.sections.immobilien-contact-form
:projectSlug="$project['slug'] ?? ''"
:projectTitle="$project['title'] ?? ''"
:interestOptions="$project['contact']['options'] ?? []"
/>
</div>
</div>
</div>
</section>
@endif
</main>
<livewire:web.components.ui.footer />
</div>
@endsection
@push('styles')
<style>
[x-cloak] {
display: none !important;
}
</style>
@endpush

View file

@ -0,0 +1,314 @@
@extends('web.layouts.web-master')
@section('title', 'Immobilien Dubai - B2in')
@section('meta_description', 'Exklusive Off-Market-Immobilien in Dubai. Persönliche Beratung, steuerfreie Renditen & Turnkey-Einrichtung aus einer Hand.')
@section('content')
<div class="bg-background">
<livewire:web.components.ui.header />
<main class="variante-glass-flow">
@php
$heroV2 = cms_theme_section('immobilien_hero_v2');
$warumDubai = cms_theme_section('immobilien_warum_dubai');
$kaufprozess = cms_theme_section('immobilien_kaufprozess');
$bruecke = cms_theme_section('immobilien_bruecke');
$mindset = cms_theme_section('immobilien_mindset');
$projects = cms_theme_section('immobilien_projects');
$moebelVorteil = cms_theme_section('immobilien_moebel_vorteil');
@endphp
{{-- Sektion 1: Hero --}}
@if (!empty($heroV2))
<section class="relative min-h-[70vh] flex items-center overflow-hidden">
<x-web-picture
src="{{ theme_image_url($heroV2['image'] ?? '') }}"
alt="{{ $heroV2['image_alt'] ?? 'Immobilien Investment Dubai' }}"
class="absolute inset-0 w-full h-full object-cover"
loading="" />
<div class="absolute inset-0 bg-gradient-to-r from-black/80 via-black/60 to-black/30"></div>
<div class="relative z-10 container-padding py-24 lg:py-32">
<div class="max-w-3xl slide-right delay-300">
<h1 class="text-4xl lg:text-5xl xl:text-6xl font-bold text-white leading-tight">
{!! $heroV2['title'] !!}
</h1>
<p class="text-lg lg:text-xl text-white/80 mt-6 max-w-2xl leading-relaxed">
{{ $heroV2['subtitle'] ?? '' }}
</p>
@if (isset($heroV2['cta_text']))
<div class="mt-10">
<a href="{{ $heroV2['cta_link'] ?? '#projekte' }}"
class="btn-primary-accent px-8 py-4 text-lg">
{{ $heroV2['cta_text'] }}
</a>
</div>
@endif
</div>
</div>
</section>
@endif
<livewire:web.components.sections.founder-bar />
{{-- Sektion 2: Warum Dubai? --}}
@if (!empty($warumDubai))
<section class="section-padding">
<div class="container-padding">
<div class="max-w-3xl mx-auto text-center mb-12 slide-up delay-300">
<h2 class="text-section-title">{!! $warumDubai['title'] !!}</h2>
@if (isset($warumDubai['intro']))
<p class="text-large text-muted-foreground mt-4 leading-relaxed">
{{ $warumDubai['intro'] }}
</p>
@endif
</div>
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-6 max-w-5xl mx-auto">
@foreach ($warumDubai['facts'] ?? [] as $index => $fact)
<div class="card-elevated rounded-2xl p-6 lg:p-8 text-center slide-up delay-{{ 300 + $index * 100 }}">
<div class="inline-flex items-center justify-center w-14 h-14 rounded-full bg-secondary/10 text-secondary mb-5">
@svg('heroicon-o-' . ($fact['icon'] ?? 'check'), 'w-7 h-7')
</div>
<h3 class="text-lg font-semibold text-foreground mb-2">{{ $fact['title'] ?? '' }}</h3>
<p class="text-sm text-muted-foreground leading-relaxed">{{ $fact['description'] ?? '' }}</p>
</div>
@endforeach
</div>
</div>
</section>
@endif
<livewire:web.components.sections.image-break section="immobilien_image_break" />
{{-- Sektion 3: Kaufprozess --}}
@if (!empty($kaufprozess))
<section class="section-padding bg-accent">
<div class="container-padding">
<div class="max-w-3xl mx-auto text-center mb-12 slide-up delay-300">
<h2 class="text-section-title">{!! $kaufprozess['title'] !!}</h2>
@if (isset($kaufprozess['intro']))
<p class="text-large text-muted-foreground mt-4 leading-relaxed">
{{ $kaufprozess['intro'] }}
</p>
@endif
</div>
<div class="max-w-4xl mx-auto">
<div class="grid md:grid-cols-2 gap-6">
@foreach ($kaufprozess['steps'] ?? [] as $index => $step)
<div class="relative card-elevated rounded-2xl p-6 lg:p-8 slide-up delay-{{ 300 + $index * 100 }}">
<div class="flex gap-5 items-start">
<div class="shrink-0 w-12 h-12 rounded-full bg-secondary text-white flex items-center justify-center text-lg font-bold">
{{ $step['number'] ?? '' }}
</div>
<div>
<h3 class="text-lg font-semibold text-foreground mb-2">{{ $step['title'] ?? '' }}</h3>
<p class="text-sm text-muted-foreground leading-relaxed">{{ $step['description'] ?? '' }}</p>
</div>
</div>
</div>
@endforeach
</div>
</div>
</div>
</section>
@endif
{{-- Sektion 4: Die Brücke – Marcels Pitch --}}
@if (!empty($bruecke))
<section class="section-padding">
<div class="container-padding">
<div class="grid lg:grid-cols-2 gap-12 lg:gap-16 items-center">
<div class="relative lg:order-1">
<div class="card-elevated rounded-3xl overflow-hidden slide-left delay-400">
<x-web-picture
src="{{ theme_image_url($bruecke['image'] ?? '') }}"
alt="{{ $bruecke['image_alt'] ?? 'Marcel Scheibe – Ihre Brücke nach Dubai' }}"
class="w-full h-[500px] object-cover" />
@if (isset($bruecke['image_caption']))
<div class="absolute bottom-6 left-6 bg-card/95 backdrop-blur-sm rounded-xl p-4 shadow-lg border border-border/50 slide-left delay-500">
{{ $bruecke['image_caption'] }}
</div>
@endif
</div>
</div>
<div class="spacing-section lg:order-2">
<div class="spacing-content slide-right delay-300">
<h2 class="text-section-title">{!! $bruecke['title'] !!}</h2>
<div class="spacing-small text-large text-muted-foreground leading-relaxed">
@foreach ($bruecke['paragraphs'] ?? [] as $paragraph)
<p>{!! $paragraph !!}</p>
@endforeach
</div>
@if (isset($bruecke['advantage_title']))
<div class="mt-8 p-6 rounded-2xl bg-secondary/5 border border-secondary/20">
<h3 class="text-lg font-semibold text-foreground mb-2">{{ $bruecke['advantage_title'] }}</h3>
<p class="text-muted-foreground leading-relaxed">{{ $bruecke['advantage_text'] ?? '' }}</p>
</div>
@endif
@if (isset($bruecke['cta_text']))
<div class="mt-8">
<a href="{{ $bruecke['cta_link'] ?? '/contact' }}"
class="btn-primary-accent px-6 py-3">
{{ $bruecke['cta_text'] }}
</a>
</div>
@endif
</div>
</div>
</div>
</div>
</section>
@endif
{{-- Aktuelle Projekte --}}
@if (!empty($projects))
<section id="projekte" class="section-padding bg-accent">
<div class="container-padding">
<div class="text-center mb-12 slide-up delay-300">
<h2 class="text-section-title">{!! $projects['title'] ?? '' !!}</h2>
@if (isset($projects['subtitle']))
<p class="text-large text-muted-foreground mt-4 max-w-2xl mx-auto">
{{ $projects['subtitle'] }}
</p>
@endif
</div>
@php
$projectCount = count($projects['projects'] ?? []);
@endphp
<div class="grid md:grid-cols-1 lg:grid-cols-2 gap-8 slide-up delay-400">
@foreach ($projects['projects'] ?? [] as $project)
<div class="card-elevated rounded-2xl overflow-hidden {{ $projectCount === 1 ? 'lg:col-span-2 lg:max-w-[calc((100%-2rem)/2)] lg:mx-auto' : '' }}">
@if (isset($project['image']))
<div class="relative h-56 overflow-hidden">
<x-web-picture
src="{{ theme_image_url($project['image']) }}"
alt="{{ $project['title'] }}"
class="w-full h-full object-cover" />
@if (isset($project['status']))
<div class="absolute top-4 left-4">
<span class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-xs font-semibold bg-secondary text-white">
{{ $project['status'] }}
@if (isset($project['launch_date']))
<span class="opacity-80">({{ $project['launch_date'] }})</span>
@endif
</span>
</div>
@endif
</div>
@endif
<div class="p-6 lg:p-8">
<div class="mb-4">
<h3 class="text-xl font-semibold text-foreground">{{ $project['title'] }}</h3>
@if (isset($project['location']))
<p class="text-sm text-muted-foreground mt-1">{{ $project['location'] }}</p>
@endif
</div>
@if (isset($project['price_from']))
<p class="text-lg font-medium text-secondary mb-4">{{ $project['price_from'] }}</p>
@endif
@if (isset($project['highlights']))
<ul class="space-y-2 mb-6">
@foreach ($project['highlights'] as $highlight)
<li class="flex items-start gap-2 text-sm text-muted-foreground">
<svg class="w-4 h-4 text-secondary mt-0.5 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
{{ $highlight }}
</li>
@endforeach
</ul>
@endif
<a href="{{ isset($project['slug']) ? route('immobilien.show', $project['slug']) : ($projects['cta_link'] ?? '/contact') }}"
class="inline-flex items-center gap-2 whitespace-nowrap btn-primary-accent">
<span>{{ isset($project['slug']) ? 'Exposé ansehen' : ($projects['cta_text'] ?? 'Anfragen') }}</span>
<svg class="w-4 h-4 shrink-0 inline-block ml-2 mb-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3" />
</svg>
</a>
</div>
</div>
@endforeach
</div>
</div>
</section>
@endif
{{-- Sektion 5: Mindset-Check --}}
@if (!empty($mindset))
<section class="section-padding">
<div class="container-padding">
<div class="max-w-4xl mx-auto">
<div class="rounded-2xl border-2 border-secondary/20 bg-secondary/5 p-8 lg:p-12 slide-up delay-300">
<h2 class="text-section-title text-center">{!! $mindset['title'] !!}</h2>
<div class="mt-8 space-y-6 text-large leading-relaxed">
@if (isset($mindset['text_positive']))
<p class="text-foreground">{!! $mindset['text_positive'] !!}</p>
@endif
@if (isset($mindset['text_negative']))
<p class="text-muted-foreground">{{ $mindset['text_negative'] }}</p>
@endif
@if (isset($mindset['closing']))
<p class="text-foreground pt-4 border-t border-secondary/20">{!! $mindset['closing'] !!}</p>
@endif
</div>
@if (isset($mindset['cta_text']))
<div class="mt-8 text-center">
<a href="{{ $mindset['cta_link'] ?? '/contact' }}"
class="btn-primary-accent px-8 py-4 text-lg">
{{ $mindset['cta_text'] }}
</a>
</div>
@endif
</div>
</div>
</div>
</section>
@endif
{{-- Möbel-Vorteil Banner (Teaser) --}}
@if (!empty($moebelVorteil))
<section class="section-padding bg-accent">
<div class="container-padding">
<div class="max-w-3xl mx-auto text-center slide-up delay-300">
<h2 class="text-section-title">{!! $moebelVorteil['title'] ?? '' !!}</h2>
<p class="text-large text-muted-foreground mt-4">
{{ $moebelVorteil['text'] ?? '' }}
</p>
@if (isset($moebelVorteil['button_text']))
<div class="mt-8">
<a href="{{ $moebelVorteil['button_link'] ?? '/netzwerk' }}"
class="btn-secondary-accent">
{{ $moebelVorteil['button_text'] }}
</a>
</div>
@endif
</div>
</div>
</section>
@endif
<livewire:web.components.sections.c-t-a-section />
</main>
<livewire:web.components.ui.footer />
</div>
@endsection
@push('styles')
<style>
[x-cloak] {
display: none !important;
}
</style>
@endpush

View file

@ -0,0 +1,160 @@
@extends('web.layouts.web-master')
@section('title', 'Einrichtungsnetzwerk - B2in Interior')
@section('content')
<div class="bg-background">
<livewire:web.components.ui.header />
<main class="variante-glass-flow">
<livewire:web.components.sections.partner-hero section="interior_hero" />
<livewire:web.components.sections.founder-bar />
{{-- Local-for-Local Konzept --}}
<livewire:web.components.sections.content-section section="interior_concept" layout="left" />
{{-- Zwei Marken --}}
@php
$brands = cms_theme_section('interior_brands');
$zielgruppen = cms_theme_section('interior_zielgruppen');
$process = cms_theme_section('interior_process');
@endphp
@if (!empty($brands))
<section class="section-padding bg-accent">
<div class="container-padding">
<div class="text-center mb-12 slide-up delay-300">
<h2 class="text-section-title">{!! $brands['title'] ?? '' !!}</h2>
@if (isset($brands['subtitle']))
<p class="text-large text-muted-foreground mt-4 max-w-2xl mx-auto">
{{ $brands['subtitle'] }}
</p>
@endif
</div>
<div class="grid md:grid-cols-2 gap-8 max-w-4xl mx-auto slide-up delay-400">
@foreach ($brands['brands'] ?? [] as $brand)
<div class="card-elevated rounded-2xl overflow-hidden">
<div class="p-8 lg:p-10">
@if (isset($brand['logo']))
<div class="mb-6">
<img src="{{ asset($brand['logo']) }}"
alt="{{ $brand['name'] }}"
class="{{ $brand['logo_width'] ?? 'w-32' }}" />
</div>
@endif
<p class="text-xs font-semibold uppercase tracking-wider text-secondary mb-3">
{{ $brand['tagline'] ?? '' }}
</p>
<p class="text-muted-foreground leading-relaxed">
{{ $brand['description'] ?? '' }}
</p>
@if (isset($brand['audience']))
<p class="text-sm font-medium text-foreground mt-4">
{{ $brand['audience'] }}
</p>
@endif
@if (isset($brand['link']))
<div class="mt-6">
<a href="{{ $brand['link'] }}"
target="_blank" rel="noopener"
class="inline-flex items-center gap-2 text-sm font-medium text-secondary hover:text-secondary/80 transition-colors">
{{ $brand['name'] }} entdecken
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
</svg>
</a>
</div>
@endif
</div>
</div>
@endforeach
</div>
</div>
</section>
@endif
{{-- Für wen? Zielgruppen --}}
@if (!empty($zielgruppen))
<section class="section-padding">
<div class="container-padding">
<div class="text-center mb-12 slide-up delay-300">
<h2 class="text-section-title">{!! $zielgruppen['title'] ?? '' !!}</h2>
</div>
<div class="grid md:grid-cols-3 gap-8 max-w-5xl mx-auto slide-up delay-400">
@foreach ($zielgruppen['groups'] ?? [] as $group)
<div class="text-center p-6">
<div class="inline-flex items-center justify-center w-14 h-14 rounded-full bg-secondary/10 text-secondary mb-5">
<svg class="w-7 h-7" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
@switch($group['icon'] ?? '')
@case('home')
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
@break
@case('building-office-2')
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 21h19.5m-18-18v18m10.5-18v18m6-13.5V21M6.75 6.75h.75m-.75 3h.75m-.75 3h.75m3-6h.75m-.75 3h.75m-.75 3h.75M6.75 21v-3.375c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21M3 3h12m-.75 4.5H21m-3.75 3.75h.008v.008h-.008v-.008zm0 3h.008v.008h-.008v-.008zm0 3h.008v.008h-.008v-.008z" />
@break
@case('clipboard-document-check')
<path stroke-linecap="round" stroke-linejoin="round" d="M11.35 3.836c-.065.21-.1.433-.1.664 0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75 2.25 2.25 0 00-.1-.664m-5.8 0A2.251 2.251 0 0113.5 2.25H15c1.012 0 1.867.668 2.15 1.586m-5.8 0c-.376.023-.75.05-1.124.08C9.095 4.01 8.25 4.973 8.25 6.108V8.25m8.9-4.414c.376.023.75.05 1.124.08 1.131.094 1.976 1.057 1.976 2.192V16.5A2.25 2.25 0 0118 18.75h-2.25m-7.5-10.5H4.875c-.621 0-1.125.504-1.125 1.125v11.25c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V18.75m-7.5-10.5h6.375c.621 0 1.125.504 1.125 1.125v9.375m-8.25-3l1.5 1.5 3-3.75" />
@break
@endswitch
</svg>
</div>
<h3 class="text-lg font-semibold text-foreground mb-3">{{ $group['title'] ?? '' }}</h3>
<p class="text-sm text-muted-foreground leading-relaxed">{{ $group['description'] ?? '' }}</p>
</div>
@endforeach
</div>
</div>
</section>
@endif
{{-- So funktioniert es - Prozess --}}
@if (!empty($process))
<section class="section-padding bg-accent">
<div class="container-padding">
<div class="text-center mb-12 slide-up delay-300">
<h2 class="text-section-title">{!! $process['title'] ?? '' !!}</h2>
</div>
<div class="max-w-3xl mx-auto slide-up delay-400">
<div class="space-y-8">
@foreach ($process['steps'] ?? [] as $step)
<div class="flex gap-6 items-start">
<div class="shrink-0 w-14 h-14 rounded-full bg-secondary text-white flex items-center justify-center text-lg font-bold">
{{ $step['number'] ?? '' }}
</div>
<div class="pt-2">
<h3 class="text-lg font-semibold text-foreground mb-2">{{ $step['title'] ?? '' }}</h3>
<p class="text-muted-foreground leading-relaxed">{{ $step['description'] ?? '' }}</p>
</div>
</div>
@endforeach
</div>
</div>
</div>
</section>
@endif
{{-- Trust / Marcel Scheibe --}}
<livewire:web.components.sections.content-section section="interior_trust" layout="right" />
{{-- CTA --}}
<livewire:web.components.sections.c-t-a-section />
</main>
<livewire:web.components.ui.footer />
</div>
@endsection
@push('styles')
<style>
[x-cloak] {
display: none !important;
}
</style>
@endpush
@push('scripts')
{{-- Alpine.js wird zentral im Layout geladen --}}
@endpush

View file

@ -0,0 +1,183 @@
@extends('web.layouts.web-master')
@section('title', 'Netzwerk – regionale Fachexperten und starke Marken | B2in Interior')
@section('meta_description', 'Das B2in-Netzwerk: Europäisches Einrichtungsnetzwerk, Fachhändler-Partnerschaften & Marken-Kooperationen – in Entwicklung.')
@section('content')
<div class="bg-background">
<livewire:web.components.ui.header />
<main class="variante-glass-flow">
@php
$hero = cms_theme_section('netzwerk_hero');
$teasers = cms_theme_section('netzwerk_teasers');
$cta = cms_theme_section('netzwerk_cta');
$cabinet = cms_theme_section('netzwerk_cabinet_partner');
$immobilienHint = cms_theme_section('netzwerk_immobilien_hint');
@endphp
{{-- Hero --}}
@if (!empty($hero))
<section class="section-padding flex items-center relative border-b border-border/30">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 bg-hero-container rounded-[20px] w-[95%]">
<div class="grid lg:grid-cols-2 gap-16 items-center">
<div class="space-y-8">
<div class="slide-right delay-300">
<h1 class="text-hero mb-6">
{!! $hero['title'] !!}
</h1>
<p class="text-lg text-muted-foreground max-w-md leading-relaxed">
{{ $hero['subtitle'] ?? '' }}
</p>
</div>
</div>
<div class="relative">
<div class="relative rounded-3xl overflow-hidden shadow-elevated slide-left delay-300">
<x-web-picture
src="{{ theme_image_url($hero['image'] ?? '') }}"
alt="{{ $hero['image_alt'] ?? 'B2in Netzwerk – regionale Fachexperten' }}"
class="w-full h-[500px] object-cover"
loading="" />
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
</div>
</div>
</div>
</div>
</section>
@endif
<livewire:web.components.sections.founder-bar />
{{-- Teaser-Kacheln --}}
@if (!empty($teasers))
<section class="section-padding">
<div class="container-padding">
<div class="text-center mb-12 slide-up delay-300">
<h2 class="text-section-title">{!! $teasers['title'] !!}</h2>
</div>
<div class="grid md:grid-cols-3 gap-8 max-w-5xl mx-auto">
@foreach ($teasers['cards'] ?? [] as $index => $card)
<div class="card-elevated rounded-2xl p-8 text-center slide-up delay-{{ 300 + $index * 100 }}">
<div class="inline-flex items-center justify-center w-16 h-16 rounded-full bg-secondary/10 text-secondary mb-6">
@svg('heroicon-o-' . ($card['icon'] ?? 'squares-2x2'), 'w-8 h-8')
</div>
<h3 class="text-lg font-semibold text-foreground mb-3">{{ $card['title'] ?? '' }}</h3>
<p class="text-sm text-muted-foreground leading-relaxed mb-6">{{ $card['description'] ?? '' }}</p>
@if (isset($card['status']))
<span class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-xs font-semibold bg-secondary/10 text-secondary">
<span class="w-1.5 h-1.5 rounded-full bg-secondary animate-pulse"></span>
{{ $card['status'] }}
</span>
@endif
</div>
@endforeach
</div>
</div>
</section>
@endif
<livewire:web.components.sections.image-break section="netzwerk_image_break" />
{{-- CABINET Premiumpartner --}}
@if (! empty($cabinet))
<section class="section-padding">
<div class="container-padding">
<div class="max-w-6xl mx-auto">
<div class="grid lg:grid-cols-2 gap-12 items-center">
<div class="space-y-6 slide-right delay-300">
@if (! empty($cabinet['badge'] ?? null))
<div class="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-secondary/10 text-secondary text-sm font-semibold">
<span class="w-2 h-2 rounded-full bg-secondary"></span>
{{ $cabinet['badge'] }}
</div>
@endif
@if (! empty($cabinet['title'] ?? null))
<h2 class="text-section-title">
{!! $cabinet['title'] !!}
</h2>
@endif
@if (! empty($cabinet['lead'] ?? null))
<p class="text-lg font-medium text-foreground">{{ $cabinet['lead'] }}</p>
@endif
@foreach ($cabinet['paragraphs'] ?? [] as $paragraph)
<p class="text-muted-foreground leading-relaxed">{{ $paragraph }}</p>
@endforeach
</div>
<div class="relative slide-left delay-300">
<div class="card-elevated rounded-3xl overflow-hidden p-10 flex items-center justify-center bg-white min-h-[300px]">
<img
src="{{ theme_image_url($cabinet['image'] ?? 'b2in/cabinet_logo.png') }}"
alt="{{ $cabinet['image_alt'] ?? 'CABINET' }}"
class="max-w-xs w-full object-contain"
/>
</div>
</div>
</div>
</div>
</div>
</section>
@endif
{{-- Immobilien-Vorteil Hinweis --}}
@if (! empty($immobilienHint))
<section class="section-padding bg-accent">
<div class="container-padding">
<div class="max-w-3xl mx-auto text-center slide-up delay-300">
<div class="inline-flex items-center justify-center w-14 h-14 rounded-full bg-secondary/10 text-secondary mb-6">
@svg('heroicon-o-building-office-2', 'w-7 h-7')
</div>
@if (! empty($immobilienHint['title'] ?? null))
<h2 class="text-section-title">{!! $immobilienHint['title'] !!}</h2>
@endif
@if (! empty($immobilienHint['description'] ?? null))
<p class="text-large text-muted-foreground mt-4 leading-relaxed">
{{ $immobilienHint['description'] }}
</p>
@endif
@if (! empty($immobilienHint['button_text'] ?? null))
<div class="mt-8">
<a href="{{ url($immobilienHint['button_link'] ?? '/immobilien') }}" class="btn-primary-accent px-8 py-4 text-lg">
{{ $immobilienHint['button_text'] }}
</a>
</div>
@endif
</div>
</div>
</section>
@endif
{{-- CTA --}}
@if (!empty($cta))
<section class="section-padding">
<div class="container-padding">
<div class="max-w-3xl mx-auto text-center slide-up delay-300">
<h2 class="text-section-title">{!! $cta['title'] !!}</h2>
<p class="text-large text-muted-foreground mt-4 leading-relaxed">
{{ $cta['text'] ?? '' }}
</p>
@if (isset($cta['button_text']))
<div class="mt-8">
<a href="{{ $cta['button_link'] ?? '/contact' }}"
class="btn-primary-accent px-8 py-4 text-lg">
{{ $cta['button_text'] }}
</a>
</div>
@endif
</div>
</div>
</section>
@endif
</main>
<livewire:web.components.ui.footer />
</div>
@endsection
@push('styles')
<style>
[x-cloak] {
display: none !important;
}
</style>
@endpush

View file

@ -0,0 +1,38 @@
@extends('web.layouts.web-master')
@section('title', 'Für Entwickler & Partner - B2in')
@section('content')
<div class="bg-background">
<livewire:web.components.ui.header />
<main class="variante-glass-flow">
<livewire:web.components.sections.partner-hero />
<livewire:web.components.sections.founder-bar />
<livewire:web.components.sections.content-section section="supply_chain_intro" layout="left" bg="bg-accent" />
<livewire:web.components.sections.card-section section="partner_card_section" />
<livewire:web.components.sections.benefits-section section="partner_benefits_developer" />
<livewire:web.components.sections.benefits-section section="partner_benefits_retailer" layout="right" bg="bg-accent" />
<livewire:web.components.sections.benefits-section section="partner_benefits_supplier" />
<livewire:web.components.sections.benefits-section section="partner_benefits_broker" layout="right" bg="bg-accent" />
<livewire:web.components.sections.partner-process />
<livewire:web.components.sections.commitment-section />
<livewire:web.components.sections.partner-c-t-a />
</main>
<livewire:web.components.ui.footer />
</div>
@endsection
@push('styles')
<style>
[x-cloak] {
display: none !important;
}
</style>
@endpush
@push('scripts')
{{-- Alpine.js wird zentral im Layout geladen --}}
@endpush

View file

@ -0,0 +1,30 @@
@extends('web.layouts.web-master')
@section('title', 'B2in Magazin - Insights & Trends')
@section('content')
<div class="bg-background">
<livewire:web.components.ui.header />
<main class="variante-glass-flow">
<livewire:web.components.sections.portfolio />
<livewire:web.components.sections.c-t-a-section section="cta_section_portfolio" />
</main>
<livewire:web.components.ui.footer />
</div>
@endsection
@push('styles')
<style>
[x-cloak] {
display: none !important;
}
</style>
@endpush
@push('scripts')
{{-- Alpine.js wird zentral im Layout geladen --}}
@endpush

View file

@ -0,0 +1,32 @@
@extends('web.layouts.web-master')
@section('title', 'Stileigentum - Premium Immobilien & Zeitlose Eleganz')
@section('content')
<div class="bg-background">
<livewire:web.components.ui.header />
<main class="variante-glass-flow">
<livewire:web.components.sections.hero-image />
<livewire:web.components.sections.content-section layout="left" bg="bg-white" section="content_section_left" />
<livewire:web.components.sections.content-section layout="right" bg="bg-accent" section="content_section_right" />
<livewire:web.components.sections.ecosystem-stats />
<livewire:web.components.sections.c-t-a-section />
</main>
<livewire:web.components.ui.footer />
</div>
@endsection
@push('styles')
<style>
[x-cloak] {
display: none !important;
}
</style>
@endpush
@push('scripts')
{{-- Alpine.js wird zentral im Layout geladen --}}
@endpush

View file

@ -0,0 +1,40 @@
@extends('web.layouts.web-master')
@section('title', 'Willkommen - ' . config('app.name'))
@section('content')
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900 dark:text-gray-100">
<h1 class="text-2xl font-bold mb-4">Willkommensseite</h1>
<p class="mb-4">Dies ist die Willkommensseite mit dem {{ ucfirst(config('app.theme')) }} Theme.</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mt-8">
<div class="bg-accent-50 dark:bg-accent-900 p-6 rounded-lg shadow-sm">
<h3 class="text-xl font-semibold mb-3 text-accent-800 dark:text-accent-200">Über das Theme</h3>
<p>Diese Seite demonstriert die verschiedenen Stile des {{ ucfirst(config('app.theme')) }}-Themes.</p>
<p class="mt-2">Jede Landingpage hat ihr eigenes Theme mit individuellen Farben und Schriften.</p>
</div>
<div class="bg-primary-50 dark:bg-primary-900 p-6 rounded-lg shadow-sm">
<h3 class="text-xl font-semibold mb-3 text-primary-800 dark:text-primary-200">Domainspezifisches Styling</h3>
<p>Die Styles werden basierend auf der Domain automatisch geladen:</p>
<ul class="list-disc pl-5 mt-2 space-y-1">
<li>b2in.local - Hauptstil</li>
<li>landing1.local - Landingpage 1</li>
<li>landing2.local - Landingpage 2</li>
</ul>
</div>
</div>
<div class="mt-8">
<a href="{{ url('/') }}" class="button">
Zurück zur Startseite
</a>
</div>
</div>
</div>
</div>
</div>
@endsection

View file

@ -0,0 +1,284 @@
<?php
use App\Livewire\Cabinet\QuickStatus;
use App\Models\CmsProject;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Livewire\Volt\Volt;
// Gemeinsame Web-Routes für alle Pages)
// Jede Landing-Page hat das gleiche Gerüst, aber unterschiedliches Styling
// Hauptseite - lädt automatisch das richtige Theme basierend auf der Domain
Route::get('/', function () {
$theme = config('app.theme', 'b2in');
// Use theme-specific view if it exists (e.g., web.b2a, web.stileigentum)
// The view name for b2in theme is 'web.b2in' and not 'web.home'
if ($theme === 'b2in') {
return view('web.home');
}
if (view()->exists('web.'.$theme)) {
return view('web.'.$theme);
}
// Fallback to the default home view
return view('web.home');
})->name('home');
// Entwurf der Startseite in der Farbwelt vom 24.09.2026 (Nachtrag 19) – nur zur Abstimmung,
// mit B2IN_HOME_DRAFT=false verschwindet die Seite (404).
Route::get('/entwurf', function () {
abort_unless(config('app.theme', 'b2in') === 'b2in' && config('app.home_draft'), 404);
app()->instance('b2in.palette', 'greige');
return view('web.home-draft');
})->name('home.draft');
// Willkommensseite
Route::get('/welcome', function () {
return view('web.welcome');
})->name('welcome');
// Weitere gemeinsame Webseiten hier...
Route::get('/about', function () {
return view('web.about');
})->name('about');
Route::get('/ecosystem', function () {
return redirect('/partner', 301);
})->name('ecosystem');
$loadAziziContent = fn (): array => json_decode(
file_get_contents(resource_path('lang/de/immobilien-azizi.json')),
true,
512,
JSON_THROW_ON_ERROR,
);
$isAziziSourcePreview = function (Request $request): bool {
if (! $request->query->has('dev')) {
return false;
}
return ! in_array(strtolower((string) $request->query('dev')), ['0', 'false', 'off', 'no'], true);
};
Route::get('/immobilien', function (Request $request) use ($isAziziSourcePreview, $loadAziziContent) {
$content = $loadAziziContent();
$dev = $isAziziSourcePreview($request);
$devQuery = $dev;
$overviewRouteName = 'immobilien';
$detailRouteName = 'immobilien.show';
return view('web.dev.immobilien-azizi', compact('content', 'dev', 'devQuery', 'overviewRouteName', 'detailRouteName'));
})->name('immobilien');
// Immobilien-Welt: eigenes Magazin, eigene Über-uns-Seite und eigene FAQ. Muessen vor der
// Projekt-Detailroute stehen, sonst wuerde diese die Pfade als Projekt-Slug lesen.
Route::get('/immobilien/magazin', function () {
return view('web.magazin', ['world' => 'immobilien']);
})->name('immobilien.magazin');
Route::get('/immobilien/ueber-b2in', function () {
return view('web.immobilien-about');
})->name('immobilien.about');
Route::get('/immobilien/faq', function () {
return view('web.faq', ['section' => 'faq_immobilien']);
})->name('immobilien.faq');
Route::get('/immobilien/kontakt', function () {
return view('web.contact', ['world' => 'immobilien']);
})->name('immobilien.contact');
Route::get('/immobilien/{slug}', function (Request $request, string $slug) use ($isAziziSourcePreview, $loadAziziContent) {
$content = $loadAziziContent();
$dev = $isAziziSourcePreview($request);
$devQuery = $dev;
$overviewRouteName = 'immobilien';
$project = collect($content['projects'] ?? [])->firstWhere('slug', $slug);
abort_unless($project, 404);
return view('web.dev.immobilien-azizi-show', compact('content', 'project', 'dev', 'devQuery', 'overviewRouteName'));
})->name('immobilien.show');
// Die Netzwerk-Seite geht im Abschnitt "Mehr als Marken: unser Netzwerk" auf /marken auf.
// Alte Links und Rankings laufen per 301 dorthin; die View bleibt als Archiv liegen.
Route::get('/netzwerk', function () {
return redirect('/marken', 301);
})->name('netzwerk');
Route::get('/interior', function () {
return redirect('/marken', 301);
})->name('interior');
/*Route::get('/immobilien/{slug}', function (string $slug) {
$cmsProject = CmsProject::query()->published()->where('slug', $slug)->first();
if ($cmsProject) {
$project = $cmsProject->toFrontendArray();
return view('web.immobilien-show', compact('project'));
}
$theme = config('app.theme', 'b2in');
$immobilienProjects = cms_theme_section('immobilien_projects', $theme);
$project = is_array($immobilienProjects) ? data_get($immobilienProjects, "projects.{$slug}") : null;
abort_unless($project, 404);
return view('web.immobilien-show', compact('project'));
})->name('immobilien.show');
*/
Route::get('/partner', function () {
return redirect('/marken', 301);
})->name('partner');
Route::get('/magazin', function () {
return view('web.magazin');
})->name('magazin');
// Alte numerische Magazin-URLs (/magazin/1 … /magazin/5) dauerhaft auf den Slug umleiten.
// Muss vor der Slug-Route stehen, sonst wuerde diese die Ziffern selbst schlucken.
Route::get('/magazin/{id}', function (string $id) {
$slug = \App\Models\CmsArticle::slugForLegacyId($id);
abort_unless($slug !== null, 404);
return redirect()->route('magazin.detail', ['slug' => $slug], 301);
})->whereNumber('id')->name('magazin.detail.legacy');
Route::get('/magazin/{slug}', function (string $slug) {
// Die Detailseite rendert in der Welt ihres Beitrags (Dubai-Themen bleiben blau). Die Welt
// muss vor dem Rendern feststehen, weil Kopf- und Fusszeile sie in mount() festhalten.
$article = \App\Models\CmsArticle::forFrontend()[$slug] ?? null;
abort_unless($article !== null, 404);
b2in_world_set($article['world'] ?? 'interior');
return view('web.magazin-detail', compact('slug'));
})->name('magazin.detail');
// Kernmarken: Uebersichtsseite und Detailseite je Marke.
Route::get('/marken', function () {
return view('web.marken');
})->name('marken');
Route::get('/marken/{slug}', function (string $slug) {
$brands = \App\Models\CmsBrand::forFrontend();
abort_unless(isset($brands[$slug]), 404);
$brand = $brands[$slug];
$brandTitle = $brand['name'].' – '.$brand['tagline'].' | B2in Interior';
$brandDescription = trim(strip_tags((string) $brand['teaser']));
return view('web.marken-show', compact('slug', 'brandTitle', 'brandDescription'));
})->name('marken.show');
// Referenzen: realisierte Projekte aus den Markengalerien plus der Showroom-Feed.
Route::get('/referenzen', function () {
return view('web.referenzen');
})->name('referenzen');
// Schreibgeschuetzte Einbettung eines Displays (nur veroeffentlichte Playlists, kein Token).
Route::get('/embed/display/{display}', [\App\Http\Controllers\DisplayEmbedController::class, 'show'])
->name('display.embed');
Route::get('/contact', function () {
return view('web.contact');
})->name('contact');
// Verwaiste Seiten: ihre Content-Sektionen (hero_image, content_section_left/right, portfolio)
// existieren in keiner Lang-Datei mehr und die Seiten liefern seitdem 500. Sie werden wie die
// anderen stillgelegten Seiten dauerhaft umgeleitet; die Views bleiben als Archiv liegen.
Route::get('/service', function () {
return redirect('/marken', 301);
})->name('service');
Route::get('/portfolio', function () {
return redirect('/immobilien', 301);
})->name('portfolio');
Route::get('/faq', function () {
return view('web.faq');
})->name('faq');
// Rechtliche Seiten
Route::get('/impressum', function () {
return view('web.impressum');
})->name('impressum');
Route::get('/privacy', function () {
return view('web.privacy');
})->name('privacy');
Route::get('/terms', function () {
return view('web.terms');
})->name('terms');
Route::get('/cookie-policy', function () {
return view('web.cookie-policy');
})->name('cookie-policy');
// Theme Demo Route
Route::get('/theme-demo', function () {
return view('web.theme-demo');
})->name('theme-demo');
// Dev: Sitemap & Archiv-Versionen
Route::prefix('dev')->group(function () use ($loadAziziContent) {
Route::get('/sitemap', fn () => view('web.dev.sitemap'))->name('dev.sitemap');
Route::get('/immobilien-v1', fn () => view('web.dev.immobilien-v1'))->name('dev.immobilien-v1');
Route::get('/immobilien-azizi', function () use ($loadAziziContent) {
$content = $loadAziziContent();
$dev = true;
$devQuery = false;
$overviewRouteName = 'dev.immobilien-azizi';
$detailRouteName = 'dev.immobilien-azizi.show';
return view('web.dev.immobilien-azizi', compact('content', 'dev', 'devQuery', 'overviewRouteName', 'detailRouteName'));
})->name('dev.immobilien-azizi');
Route::get('/immobilien-azizi/{slug}', function (string $slug) use ($loadAziziContent) {
$content = $loadAziziContent();
$project = collect($content['projects'] ?? [])->firstWhere('slug', $slug);
abort_unless($project, 404);
$dev = true;
$devQuery = false;
$overviewRouteName = 'dev.immobilien-azizi';
return view('web.dev.immobilien-azizi-show', compact('content', 'project', 'dev', 'devQuery', 'overviewRouteName'));
})->name('dev.immobilien-azizi.show');
Route::get('/interior-v1', fn () => view('web.dev.interior-v1'))->name('dev.interior-v1');
Route::get('/partner-v1', fn () => view('web.dev.partner-v1'))->name('dev.partner-v1');
});
// Pfad-basierte Theme-Routen für lokale Entwicklung wurden entfernt
// Die Themensauswahl wird nun über den ThemeServiceProvider gesteuert (Domain oder ?theme=... GET-Parameter)
Route::get('/partner/invitation/expired/{token}', function (string $token) {
$invitation = \App\Models\PartnerInvitation::with('role')->where('token', $token)->firstOrFail();
return view('partner.invitation-expired', compact('invitation'));
})->name('partner.invitation.expired');
Route::get('/partner/invitation/used/{token}', function (string $token) {
$invitation = \App\Models\PartnerInvitation::with('role')->where('token', $token)->firstOrFail();
return view('partner.invitation-used', compact('invitation'));
})->name('partner.invitation.used');
Volt::route('/partner/invitation/{token}', 'partner.invitation-accept')
->name('partner.invitation.accept');
Volt::route('/partner/create-account', 'partner.create-account')
->name('partner.create.account');
// Öffentliche Registrierung per QR-/Code (Landing, code-check)
Volt::route('/reg/{role}', 'reg.landing')
->name('registration.landing');
Volt::route('/registration/thank-you', 'reg.thank-you')
->name('registration.thank-you');
// Partner Setup Wizard & Daten
Route::middleware('auth')->group(function () {
Volt::route('/partner/setup', 'partner.setup-wizard')
->name('partner.setup.wizard');
});
// Cabinet Quick-Status – key-geschützte Mini-App für schnellen Statuswechsel
Route::get('/info/status', QuickStatus::class)->name('cabinet.quick-status');
// Authentifizierungs-Routen werden in domains.php eingebunden
// require __DIR__ . '/auth.php';

View file

@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
use FluxCms\Core\Models\CmsContent;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
test('netzwerk page lang blocks exist for de', function () {
$cabinet = trans('b2in.themes.b2in.netzwerk_cabinet_partner', [], 'de');
$hint = trans('b2in.themes.b2in.netzwerk_immobilien_hint', [], 'de');
expect($cabinet)->toBeArray()
->toHaveKey('badge')
->and($cabinet['paragraphs'])->toBeArray();
expect($hint)->toBeArray()
->toHaveKey('title')
->toHaveKey('button_text');
});
test('netzwerk page cms seeder creates rows only once', function () {
$this->seed(\Database\Seeders\NetzwerkPageCmsSeeder::class);
expect(CmsContent::where('group', 'netzwerk')->where('key', 'cabinet_partner')->exists())->toBeTrue()
->and(CmsContent::where('group', 'netzwerk')->where('key', 'immobilien_hint')->exists())->toBeTrue();
$count = CmsContent::count();
$this->seed(\Database\Seeders\NetzwerkPageCmsSeeder::class);
expect(CmsContent::count())->toBe($count);
});
test('cms_theme_section returns cabinet content from database after netzwerk page seed', function () {
$this->seed(\Database\Seeders\NetzwerkPageCmsSeeder::class);
app()->setLocale('de');
$cabinet = cms_theme_section('netzwerk_cabinet_partner');
expect($cabinet)->toBeArray()
->and($cabinet['badge'])->toBe('Premiumpartner');
});

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,25 @@
# Archiv: Aufräumen 07.10.2026
Dateien, die nichts mehr lädt oder anzeigt. Pfade unter `code/` wie im Projekt. Nichts in diesem Ordner
wird von der Anwendung geladen.
| Datei / Ordner | Was es war |
|---|---|
| `resources/views/livewire/web/components/sections_bak/` | 20 Sicherungskopien alter Sektionen (`*.blade_bak.php`, Stand April 2026) |
| `resources/views/livewire/partner/setup-wizard_bak.blade.php` | Sicherungskopie des Partner-Einrichtungsassistenten |
| `app/Livewire/Web/Components/AboutHero.php` | doppelte, ungenutzte Klasse – im Einsatz ist `Sections/AboutHero` |
| `resources/views/web/layouts/admin-master.blade.php`, `header.blade.php`, `footer.blade.php` | alte Layout-Teile (Tailwind-UI-Vorlage mit Platzhalter-Logo) |
| `resources/views/layouts/web-master.blade.php`, `admin-master.blade.php`, `resources/views/partials/admin-head.blade.php` | zweite, ungenutzte Fassung der Layouts – im Einsatz sind `web/layouts/web-master` und die Flux-Layouts |
| `resources/views/components/placeholder-pattern.blade.php`, `components/layouts/app/header.blade.php`, `components/layouts/auth/simple.blade.php`, `components/layouts/auth/split.blade.php` | Varianten aus der Starter-Vorlage, nirgends eingebunden (im Einsatz: `app/sidebar`, `auth/card`) |
| `public/img/assets/b2in/* Kopie*` | Bildkopien (hero-room, partner-hero, b2a) |
| `public/img/assets/b2in/._*` | macOS-Metadaten (AppleDouble), keine Bilder |
| `public/img/assets/b2in/integriertes-model.*` | Bild der entfernten Sektion „Integriertes Modell“ |
| `public/img/map/dubai-map.*` | Dubai-Karte der früheren Immobilien-Seite (5 MB) |
| `resources/views/web/welcome.blade.php` | Demo-Seite `/welcome` („Dies ist die Willkommensseite …“), Route entfernt |
| `public/img/assets/b2a/`, `stileigentum/`, `style2own/` | 118 Bilder (14,5 MB) der drei ruhenden Domains, die keine Vorlage mehr verwendet – ihre Texte lagen in `config/content.php` (Archiv vom 06.10.). Die Domains selbst mit Views, Komponenten und den noch genutzten Bildern bleiben. |
Außerdem entfernt: der auskommentierte TopBar-Aufruf in `web/layouts/web-master.blade.php` (die
Komponente selbst bleibt, das Registrierungs-Layout `web-master-slot` nutzt sie) und drei leere Ordner
unter `resources/views/components/web/components/`.
Zurückholen: Datei an den ursprünglichen Pfad zurückkopieren.

View file

@ -0,0 +1,13 @@
<?php
namespace App\Livewire\Web\Components;
use Livewire\Component;
class AboutHero extends Component
{
public function render()
{
return view('livewire.web.components.sections.about-hero');
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Some files were not shown because too many files have changed in this diff Show more