First commit

This commit is contained in:
Kevin Adametz 2025-10-20 17:50:35 +02:00
commit 7cf3558ba7
12933 changed files with 1180047 additions and 0 deletions

66
resources/css/app.css Normal file
View file

@ -0,0 +1,66 @@
@import 'tailwindcss';
@import '../../vendor/livewire/flux/dist/flux.css';
@source '../views';
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../vendor/livewire/flux-pro/stubs/**/*.blade.php';
@source '../../vendor/livewire/flux/stubs/**/*.blade.php';
@custom-variant dark (&:where(.dark, .dark *));
@theme {
--font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
--color-zinc-50: #fafafa;
--color-zinc-100: #f5f5f5;
--color-zinc-200: #e5e5e5;
--color-zinc-300: #d4d4d4;
--color-zinc-400: #a3a3a3;
--color-zinc-500: #737373;
--color-zinc-600: #525252;
--color-zinc-700: #404040;
--color-zinc-800: #262626;
--color-zinc-900: #171717;
--color-zinc-950: #0a0a0a;
--color-accent: var(--color-neutral-800);
--color-accent-content: var(--color-neutral-800);
--color-accent-foreground: var(--color-white);
}
@layer theme {
.dark {
--color-accent: var(--color-white);
--color-accent-content: var(--color-white);
--color-accent-foreground: var(--color-neutral-800);
}
}
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
}
[data-flux-field]:not(ui-radio, ui-checkbox) {
@apply grid gap-2;
}
[data-flux-label] {
@apply !mb-0 !leading-tight;
}
input:focus[data-flux-control],
textarea:focus[data-flux-control],
select:focus[data-flux-control] {
@apply outline-hidden ring-2 ring-accent ring-offset-2 ring-offset-accent-foreground;
}
/* \[:where(&)\]:size-4 {
@apply size-4;
} */

67
resources/css/portal.css Normal file
View file

@ -0,0 +1,67 @@
@import "tailwindcss";
@import "../../vendor/livewire/flux/dist/flux.css";
@source '../views';
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../vendor/livewire/flux-pro/stubs/**/*.blade.php';
@source '../../vendor/livewire/flux/stubs/**/*.blade.php';
@custom-variant dark (&:where(.dark, .dark *));
@theme {
--font-sans: "Instrument Sans", ui-sans-serif, system-ui, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
"Noto Color Emoji";
--color-zinc-50: #fafafa;
--color-zinc-100: #f5f5f5;
--color-zinc-200: #e5e5e5;
--color-zinc-300: #d4d4d4;
--color-zinc-400: #a3a3a3;
--color-zinc-500: #737373;
--color-zinc-600: #525252;
--color-zinc-700: #404040;
--color-zinc-800: #262626;
--color-zinc-900: #171717;
--color-zinc-950: #0a0a0a;
--color-accent: var(--color-neutral-800);
--color-accent-content: var(--color-neutral-800);
--color-accent-foreground: var(--color-white);
}
@layer theme {
.dark {
--color-accent: var(--color-white);
--color-accent-content: var(--color-white);
--color-accent-foreground: var(--color-neutral-800);
}
}
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
}
[data-flux-field]:not(ui-radio, ui-checkbox) {
@apply grid gap-2;
}
[data-flux-label] {
@apply !mb-0 !leading-tight;
}
input:focus[data-flux-control],
textarea:focus[data-flux-control],
select:focus[data-flux-control] {
@apply outline-hidden ring-2 ring-accent ring-offset-2 ring-offset-accent-foreground;
}
/* \[:where(&)\]:size-4 {
@apply size-4;
} */

View file

@ -0,0 +1,437 @@
/* Shared styles for all web themes - no @apply directives */
*,
::before,
::after {
box-sizing: border-box;
border-width: 0;
border-style: solid;
border-color: hsl(var(--border));
}
body {
background-color: hsl(var(--background));
color: hsl(var(--foreground));
font-family: var(--font-primary, 'Inter'), system-ui, -apple-system, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
h1, h2, h3, h4, h5, h6 {
font-weight: 500;
letter-spacing: -0.025em;
font-family: var(--font-secondary, 'Inter'), var(--font-primary, 'Inter'), system-ui, -apple-system, sans-serif;
}
/* Typography scales */
.text-hero {
font-size: clamp(3rem, 4vw, 6rem);
line-height: 1.1;
font-weight: 300;
letter-spacing: -0.025em;
}
.text-section-title {
font-size: clamp(1.6rem, 3vw, 3rem);
font-weight: 300;
letter-spacing: -0.025em;
}
.text-large {
font-size: clamp(1.1rem, 2vw, 1.2rem);
line-height: 1.625;
}
/* Border utilities to override the global border-width: 0 */
.border-t {
border-top-width: 1px !important;
}
.border-b {
border-bottom-width: 1px !important;
}
.border-l {
border-left-width: 1px !important;
}
.border-r {
border-right-width: 1px !important;
}
.border {
border-width: 1px !important;
}
/* Button styles */
.btn-primary {
background-color: hsl(var(--primary));
color: hsl(var(--primary-foreground));
padding: 0.75rem 2rem;
border-radius: 0.5rem;
font-weight: 500;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
display: inline-block;
text-decoration: none;
}
.btn-primary:hover {
background-color: hsl(var(--secondary));
color: hsl(var(--secondary-foreground));
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
}
.btn-primary-accent {
background-color: hsl(var(--primary));
color: hsl(var(--primary-foreground));
border: 1px solid hsl(var(--border));
padding: 0.75rem 2rem;
border-radius: 0.5rem;
font-weight: 500;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
display: inline-block;
text-decoration: none;
}
.btn-primary-accent:hover {
background-color: hsl(var(--accent));
color: hsl(var(--accent-foreground));
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
}
.btn-secondary {
background-color: hsl(var(--secondary));
color: hsl(var(--secondary-foreground));
border: 1px solid hsl(var(--border));
padding: 0.75rem 2rem;
border-radius: 0.5rem;
font-weight: 500;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
display: inline-block;
text-decoration: none;
}
.btn-secondary:hover {
background-color: hsl(var(--primary));
color: hsl(var(--primary-foreground));
}
.btn-secondary-accent {
background-color: hsl(var(--secondary));
color: hsl(var(--secondary-foreground));
border: 1px solid hsl(var(--border));
padding: 0.75rem 2rem;
border-radius: 0.5rem;
font-weight: 500;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
display: inline-block;
text-decoration: none;
}
.btn-secondary-accent:hover {
background-color: hsl(var(--accent));
color: hsl(var(--accent-foreground));
}
.btn-accent {
background-color: hsl(var(--accent));
color: hsl(var(--accent-foreground));
padding: 0.75rem 2rem;
border-radius: 0.5rem;
font-weight: 500;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
display: inline-block;
text-decoration: none;
}
.btn-accent:hover {
background-color: hsl(var(--secondary));
color: hsl(var(--secondary-foreground));
box-shadow: var(--shadow-accent-glow);
}
/* Card styles */
.card-elevated {
background-color: hsl(var(--card));
border-radius: 1rem;
box-shadow: var(--shadow-card);
border: 1px solid hsl(var(--border) / 0.5);
}
/* Section styles */
.section-padding {
padding-top: 4rem;
padding-bottom: 4rem;
}
@media (min-width: 1024px) {
.section-padding {
padding-top: 6rem;
padding-bottom: 6rem;
}
}
.section-dark {
background-color: hsl(var(--dark-bg));
color: hsl(var(--dark-text));
}
.text-dark-muted {
color: hsl(var(--dark-muted));
}
/* Container styles */
.container-padding {
max-width: 80rem;
margin-left: auto;
margin-right: auto;
padding-left: 1rem;
padding-right: 1rem;
}
@media (min-width: 640px) {
.container-padding {
padding-left: 1.5rem;
padding-right: 1.5rem;
}
}
@media (min-width: 1024px) {
.container-padding {
padding-left: 2rem;
padding-right: 2rem;
}
}
.container-narrow {
max-width: 56rem;
margin-left: auto;
margin-right: auto;
padding-left: 1rem;
padding-right: 1rem;
}
@media (min-width: 640px) {
.container-narrow {
padding-left: 1.5rem;
padding-right: 1.5rem;
}
}
@media (min-width: 1024px) {
.container-narrow {
padding-left: 2rem;
padding-right: 2rem;
}
}
/* Spacing utilities */
.spacing-section > * + * {
margin-top: 2rem;
}
.spacing-content > * + * {
margin-top: 1.5rem;
}
.spacing-small > * + * {
margin-top: 1rem;
}
/* Additional utility classes for better consistency */
.text-muted-foreground {
color: hsl(var(--muted-foreground));
}
.bg-background {
background-color: hsl(var(--background));
}
.text-foreground {
color: hsl(var(--foreground));
}
.bg-card {
background-color: hsl(var(--card));
}
.text-card-foreground {
color: hsl(var(--card-foreground));
}
.border-border {
border-color: hsl(var(--border));
}
.text-secondary {
color: hsl(var(--secondary));
}
.bg-secondary {
background-color: hsl(var(--secondary));
}
.text-secondary-foreground {
color: hsl(var(--secondary-foreground));
}
.bg-primary {
background-color: hsl(var(--primary));
}
.text-primary-foreground {
color: hsl(var(--primary-foreground));
}
.bg-accent {
background-color: hsl(var(--accent));
}
.text-accent-foreground {
color: hsl(var(--accent-foreground));
}
.bg-muted {
background-color: hsl(var(--muted));
}
.bg-muted\/20 {
background-color: hsl(var(--muted) / 0.2);
}
.bg-secondary\/10 {
background-color: hsl(var(--secondary) / 0.1);
}
.bg-secondary\/20 {
background-color: hsl(var(--secondary) / 0.2);
}
.bg-card\/95 {
background-color: hsl(var(--card) / 0.95);
}
.border-border\/50 {
border-color: hsl(var(--border) / 0.5);
}
.border-border\/30 {
border-color: hsl(var(--border) / 0.3);
}
.text-dark-muted {
color: hsl(var(--dark-muted));
}
.border-dark-muted\/30 {
border-color: hsl(var(--dark-muted) / 0.3);
}
.text-dark-text {
color: hsl(var(--dark-text));
}
.bg-dark-bg {
background-color: hsl(var(--dark-bg));
}
.bg-hero-container {
background-color: hsl(var(--hero-container));
}
.shadow-elevated {
box-shadow: var(--shadow-elevated);
}
.shadow-card {
box-shadow: var(--shadow-card);
}
.shadow-accent-glow {
box-shadow: var(--shadow-accent-glow);
}
/* Theme-spezifische Farben für Tailwind-Kompatibilität */
.text-primary {
color: hsl(var(--primary));
}
.text-secondary {
color: hsl(var(--secondary));
}
.text-muted-foreground {
color: hsl(var(--muted-foreground));
}
.bg-primary {
background-color: hsl(var(--primary));
}
.bg-secondary {
background-color: hsl(var(--secondary));
}
.border-primary {
border-color: hsl(var(--primary));
}
.border-secondary {
border-color: hsl(var(--secondary));
}
/* Hover-Effekte für Navigation */
.hover-text-secondary:hover {
color: hsl(var(--secondary));
}
.hover-text-primary:hover {
color: hsl(var(--primary));
}
.hover-bg-primary:hover {
background-color: hsl(var(--primary));
}
.hover-bg-secondary:hover {
background-color: hsl(var(--secondary));
}
.hover-border-secondary:hover {
border-color: hsl(var(--secondary));
}
.hover-shadow-accent-glow:hover {
box-shadow: var(--shadow-accent-glow);
}
/* TopBar specific styles */
.topbar-normal {
background-color: hsl(var(--muted) / 0.2);
border-bottom: 1px solid hsl(var(--border) / 0.3);
}
/* Sticky Header Verhalten */
.header-sticky {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 50;
background-color: hsl(var(--background) / 0.8);
backdrop-filter: blur(8px);
border-bottom: 1px solid hsl(var(--border));
transition: all 0.3s ease-in-out;
}
.header-normal {
position: relative;
transition: all 0.3s ease-in-out;
}
.bg-muted\/20 {
background-color: hsl(var(--muted) / 0.2);
}
.border-border\/30 {
border-color: hsl(var(--border) / 0.3);
}

View file

@ -0,0 +1,55 @@
@import "tailwindcss";
/* B2A Domain Theme - Azur Blue & Liberty Red */
@layer base {
:root {
/* Base colors */
--background: 32 20% 97%; /* #f5f4f2 - Light Beige */
--foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
--card: 0 25% 96%; /* #hsl(0 25% 96%) - Off White */
--card-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
--popover: 0 25% 96%; /* #hsl(0 25% 96%)- Off White */
--popover-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
/* B2A Theme Colors */
--primary: 207 70% 26%; /* #123f6d - Azur Blue */
--primary-foreground: 30 25% 98%; /* #faf9f7 - Off White */
--secondary: 352 76% 48%; /* #ce1d2e - Liberty Red */
--secondary-foreground: 0 25% 96%; /* #hsl(0 25% 96%) - Off White */
/* Neutral colors */
--muted: 0 0% 92%; /* hsl(0 0% 92%) - Light Muted */
--muted-foreground: 199 50% 45%; /* #4a8bb5 - Muted Blue */
--accent: 210 20% 95%; /* hsl(201 20% 95%) - Light Accent */
--accent-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
/* Dark section colors */
--dark-bg: 207 70% 26%; /* #123f6d - Azur Blue */
--dark-text: 30 25% 98%; /* #faf9f7 - Off White */
--dark-muted: 30 20% 70%; /* #b8b0a7 - Dark Muted */
/* Interactive elements */
--destructive: 0 84.2% 60.2%; /* #ef4444 - Red */
--destructive-foreground: 210 40% 98%; /* #f8fafc - Light */
--border: 0 0% 80%; /* hsl(0 0% 80%) - Light Border */
--input: 0 0% 92%; /* hsl(0 0% 92%) - Input Background */
--ring: 20 14% 16%; /* #2a2a2a - Focus Ring */
--radius: 0.75rem;
/* Hero container background */
--hero-container: 0 0% 91%; /* #e8e8e8 - Light Gray */
/* Shadows */
--shadow-warm: 0 10px 30px -15px hsl(var(--foreground) / 0.1);
--shadow-card: 0 4px 20px -8px hsl(var(--foreground) / 0.08);
--shadow-elevated: 0 20px 40px -20px hsl(var(--foreground) / 0.15);
--shadow-accent-glow: 0 0 30px hsl(var(--secondary) / 0.3);
/* Font families */
--font-primary: 'Inter', system-ui, -apple-system, sans-serif;
--font-secondary: 'Merriweather', Georgia, serif;
}
}
@import "./shared-styles.css";

View file

@ -0,0 +1,68 @@
@import "tailwindcss";
/* B2IN Domain Theme - Anthracite & Dynamic Blue */
@layer base {
:root {
/* Base colors */
--background: 32 20% 97%; /* #f5f4f2 - Light Beige */
--foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
/* Card colors */
--card: 0 25% 96%; /* #hsl(0 25% 96%) - Off White */
--card-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
--popover: 0 25% 96%; /* #hsl(0 25% 96%)- Off White */
--popover-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
/* B2IN Theme Colors */
--primary: 209 32% 25%; /* #2b3f51 - Anthracite */
--primary-foreground: 0 25% 96%; /* #hsl(0 25% 96%) - Off White */
--secondary: 199 74% 49%; /* #20a0da - Dynamic Blue */
--secondary-foreground: 0 25% 96%; /* hsl(0 25% 96%) - Off White */
/* Neutral colors */
--muted: 0 0% 92%; /* hsl(0 0% 92%) - Light Muted */
--muted-foreground: 199 50% 45%; /* #4a8bb5 - Muted Blue */
--accent: 210 0% 94%; /* hsl(210 5.26% 92.55%) - Light Accent */
--accent-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
/* Dark section colors */
--dark-bg: 209 32% 25%; /* Matching primary */
--dark-text: 0 0% 100%; /* hsl(0 0% 100%) - Off White */
--dark-muted: 0 0% 80%; /* hsl(0 0% 80%) - Dark Muted */
/* Interactive elements */
--destructive: 0 84.2% 60.2%; /* #ef4444 - Red */
--destructive-foreground: 210 40% 98%; /* #f8fafc - Light */
--border: 0 0% 80%; /* hsl(0 0% 80%) - Light Border */
--input: 0 0% 92%; /* hsl(0 0% 92%) - Input Background */
--ring: 20 14% 16%; /* #2a2a2a - Focus Ring */
--radius: 0.75rem;
/* Hero container background */
--hero-container: 0 0% 91%; /* #e8e8e8 - Light Gray */
/* Consistent shadows */
--shadow-warm: 0 10px 30px -15px hsl(var(--foreground) / 0.1);
--shadow-card: 0 4px 20px -8px hsl(var(--foreground) / 0.08);
--shadow-elevated: 0 20px 40px -20px hsl(var(--foreground) / 0.15);
--shadow-accent-glow: 0 0 30px hsl(var(--secondary) / 0.3);
/* Transitions */
--transition-smooth: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
--transition-bounce: all 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
/* Font families */
--font-primary: 'Inter', system-ui, -apple-system, sans-serif;
--font-secondary: 'IBM Plex Sans', 'Inter', system-ui, -apple-system, sans-serif;
}
}
.text-section-title {
line-height: 0.95em;
}
@import "./shared-styles.css";

View file

@ -0,0 +1,63 @@
@import "tailwindcss";
@source '../../views/web/layout.blade.php';
@custom-variant dark (&:where(.dark, .dark *));
@theme {
--font-sans: "Instrument Sans", ui-sans-serif, system-ui, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
"Noto Color Emoji";
--color-zinc-50: #fafafa;
--color-zinc-100: #f5f5f5;
--color-zinc-200: #e5e5e5;
--color-zinc-300: #d4d4d4;
--color-zinc-400: #a3a3a3;
--color-zinc-500: #737373;
--color-zinc-600: #525252;
--color-zinc-700: #404040;
--color-zinc-800: #262626;
--color-zinc-900: #171717;
--color-zinc-950: #0a0a0a;
--color-accent: var(--color-neutral-800);
--color-accent-content: var(--color-neutral-800);
--color-accent-foreground: var(--color-white);
}
@layer theme {
.dark {
--color-accent: var(--color-white);
--color-accent-content: var(--color-white);
--color-accent-foreground: var(--color-neutral-800);
}
}
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
}
[data-flux-field]:not(ui-radio, ui-checkbox) {
@apply grid gap-2;
}
[data-flux-label] {
@apply !mb-0 !leading-tight;
}
input:focus[data-flux-control],
textarea:focus[data-flux-control],
select:focus[data-flux-control] {
@apply outline-hidden ring-2 ring-accent ring-offset-2 ring-offset-accent-foreground;
}
/* \[:where(&)\]:size-4 {
@apply size-4;
} */

View file

@ -0,0 +1,58 @@
@import "tailwindcss";
/* Stileigentum Domain Theme - Style Blue & Style Sun */
@layer base {
:root {
/* Base colors */
--background: 32 20% 97%; /* #f5f4f2 - Light Beige */
--foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
--card: 38 40% 97%; /* #hsl(60 53.33% 88.24%) - Off White */
--card-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
--popover: 0 25% 96%; /* #hsl(0 25% 96%)- Off White */
--popover-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
/* Stileigentum Theme Colors */
--primary: 209 65% 20%; /* #123453 - Imperial Blue */
--primary-foreground: 0 25% 96%; /* #hsl(0 25% 96%) - Off White */
--secondary: 38 40% 66%; /* #c9ac84 - Sand Gold */
--secondary-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
/* Neutral colors */
--muted: 209 35% 94%; /* #f0f2f5 - Very Light Imperial Blue */
--muted-foreground: 209 10% 40%; /* hsl(208 9.09% 32.35%) - Muted Imperial Blue */
--accent: 38 40% 88%; /* hsl(38 40% 88%) - Very Light Sand Gold */
--accent-foreground: 209 10% 40%; /* hsl(204 4.35% 22.55%) - Darker Imperial Blue */
/* Dark section colors */
--dark-bg: 209 65% 20%; /* #123453 - Imperial Blue */
--dark-text: 0 0% 100%; /* hsl(0 0% 100%) - Off White */
--dark-muted: 30 20% 70%; /* #b8b0a7 - Dark Muted */
/* Interactive elements */
--destructive: 0 84.2% 60.2%; /* #ef4444 - Red */
--destructive-foreground: 210 40% 98%; /* #f8fafc - Light */
--border: 0 0% 80%; /* hsl(0 0% 80%) - Light Border */
--input: 0 0% 92%; /* hsl(0 0% 92%) - Input Background */
--radius: 0.75rem;
/* Hero container background */
--hero-container: 0 0% 91%; /* #e8e8e8 - Light Gray */
/* Shadows */
--shadow-warm: 0 10px 30px -15px hsl(var(--foreground) / 0.1);
--shadow-card: 0 4px 20px -8px hsl(var(--foreground) / 0.08);
--shadow-elevated: 0 20px 40px -20px hsl(var(--foreground) / 0.15);
--shadow-accent-glow: 0 0 30px hsl(var(--secondary) / 0.3);
/* Font families */
--font-primary: 'Inter', system-ui, -apple-system, sans-serif;
--font-secondary: 'EB Garamond', Georgia, serif;
}
}
.text-section-title {
line-height: 0.95em;
}
@import "./shared-styles.css";

View file

@ -0,0 +1,72 @@
@import "tailwindcss";
/* Style2own Domain Theme - Imperial Blue & Sand Gold */
@layer base {
:root {
/* Base colors */
--background: 32 20% 97%; /* #f5f4f2 - Light Beige */
--foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
--card: 30 25% 98%; /* #faf9f7 - Off White */
--card-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
--popover: 0 25% 96%; /* #hsl(0 25% 96%)- Off White */
--popover-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
/* Style2own Theme Colors */
--primary: 195 100% 34%; /* #007aab - Style Blue */
--primary-foreground: 30 25% 98%; /* #faf9f7 - Off White */
--secondary: 46 95% 56%; /* #fbaf22 - Style Sun */
--secondary-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
/* Neutral colors */
--muted: 0 0% 92%; /* hsl(0 0% 92%) - Light Muted */
--muted-foreground: 199 50% 45%; /* #4a8bb5 - Muted Blue */
--accent: 210 20% 95%; /* #f2f5f7 - Light Accent */
--accent-foreground: 20 14% 16%; /* #2a2a2a - Dark Gray */
/* Dark section colors */
--dark-bg: 195 100% 34%; /* #007aab - Style Blue */
--dark-text: 30 25% 98%; /* #faf9f7 - Off White */
--dark-muted: 30 20% 70%; /* #b8b0a7 - Dark Muted */
/* Interactive elements */
--destructive: 0 84.2% 60.2%; /* #ef4444 - Red */
--destructive-foreground: 210 40% 98%; /* #f8fafc - Light */
--border: 32 20% 90%; /* #e6e0d8 - Light Border */
--border: 0 0% 80%; /* hsl(0 0% 80%) - Light Border */
--input: 0 0% 92%; /* hsl(0 0% 92%) - Input Background */
--radius: 0.75rem;
/* Hero container background */
--hero-container: 0 0% 91%; /* #e8e8e8 - Light Gray */
/* Shadows */
--shadow-warm: 0 10px 30px -15px hsl(var(--foreground) / 0.1);
--shadow-card: 0 4px 20px -8px hsl(var(--foreground) / 0.08);
--shadow-elevated: 0 20px 40px -20px hsl(var(--foreground) / 0.15);
--shadow-accent-glow: 0 0 30px hsl(var(--secondary) / 0.3);
/* Font families */
--font-primary: 'Inter', system-ui, -apple-system, sans-serif;
--font-secondary: 'Ephesis', cursive;
}
}
/* Font size adjustments for Ephesis font - 30% larger */
.text-hero {
font-size: clamp(3.6rem, 4.2vw, 7.8rem) !important;
}
.text-section-title {
font-size: clamp(2.1rem, 3.9vw, 3.9rem) !important;
line-height: 0.85em;
}
.text-xl {
font-size: clamp(1.3rem, 2.2vw, 2.2rem) !important;
}
@import "./shared-styles.css";

0
resources/js/admin.js Normal file
View file

1
resources/js/app.js Normal file
View file

@ -0,0 +1 @@
// App JS ohne Alpine-Initialisierung. Alpine wird von Livewire verwaltet.

View file

@ -0,0 +1,6 @@
<?php
return [
'Willkommen bei :domain' => 'Willkommen bei :domain',
'Sprache' => 'Sprache',
];

View file

@ -0,0 +1,6 @@
<?php
return [
'Willkommen bei :domain' => 'Welcome to :domain',
'Sprache' => 'Language',
];

View file

@ -0,0 +1,6 @@
<?php
return [
'Willkommen bei :domain' => 'Bienvenido a :domain',
'Sprache' => 'Idioma',
];

View file

@ -0,0 +1,6 @@
<?php
return [
'Willkommen bei :domain' => 'Bienvenue chez :domain',
'Sprache' => 'Langue',
];

View file

@ -0,0 +1,18 @@
<x-layouts.app title="Dashboard">
<div class="flex h-full w-full flex-1 flex-col gap-4 rounded-xl">
<div class="grid auto-rows-min gap-4 md:grid-cols-3">
<div class="relative aspect-video overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700 p-4">
<livewire:notifications />
</div>
<div class="relative aspect-video overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700">
<x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />
</div>
<div class="relative aspect-video overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700">
<x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />
</div>
</div>
<div class="relative h-full flex-1 overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-700">
<x-placeholder-pattern class="absolute inset-0 size-full stroke-gray-900/20 dark:stroke-neutral-100/20" />
</div>
</div>
</x-layouts.app>

View file

@ -0,0 +1,14 @@
@props([
'on',
])
<div
x-data="{ shown: false, timeout: null }"
x-init="@this.on('{{ $on }}', () => { clearTimeout(timeout); shown = true; timeout = setTimeout(() => { shown = false }, 2000); })"
x-show.transition.out.opacity.duration.1500ms="shown"
x-transition:leave.opacity.duration.1500ms
style="display: none"
{{ $attributes->merge(['class' => 'text-sm']) }}
>
{{ $slot->isEmpty() ? __('Saved.') : $slot }}
</div>

View file

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 42" {{ $attributes }}>
<path
fill="currentColor"
fill-rule="evenodd"
clip-rule="evenodd"
d="M17.2 5.633 8.6.855 0 5.633v26.51l16.2 9 16.2-9v-8.442l7.6-4.223V9.856l-8.6-4.777-8.6 4.777V18.3l-5.6 3.111V5.633ZM38 18.301l-5.6 3.11v-6.157l5.6-3.11V18.3Zm-1.06-7.856-5.54 3.078-5.54-3.079 5.54-3.078 5.54 3.079ZM24.8 18.3v-6.157l5.6 3.111v6.158L24.8 18.3Zm-1 1.732 5.54 3.078-13.14 7.302-5.54-3.078 13.14-7.3v-.002Zm-16.2 7.89 7.6 4.222V38.3L2 30.966V7.92l5.6 3.111v16.892ZM8.6 9.3 3.06 6.222 8.6 3.143l5.54 3.08L8.6 9.3Zm21.8 15.51-13.2 7.334V38.3l13.2-7.334v-6.156ZM9.6 11.034l5.6-3.11v14.6l-5.6 3.11v-14.6Z"
/>
</svg>

After

Width:  |  Height:  |  Size: 714 B

View file

@ -0,0 +1,6 @@
<div class="flex aspect-square size-8 items-center justify-center rounded-md bg-accent-content text-accent-foreground">
<x-app-logo-icon class="size-5 fill-current text-white dark:text-black" />
</div>
<div class="ms-1 grid flex-1 text-start text-sm">
<span class="mb-0.5 truncate leading-none font-semibold">B2IN</span>
</div>

View file

@ -0,0 +1,9 @@
@props([
'title',
'description',
])
<div class="flex w-full flex-col text-center">
<flux:heading size="xl">{{ $title }}</flux:heading>
<flux:subheading>{{ $description }}</flux:subheading>
</div>

View file

@ -0,0 +1,9 @@
@props([
'status',
])
@if ($status)
<div {{ $attributes->merge(['class' => 'font-medium text-sm text-green-600']) }}>
{{ $status }}
</div>
@endif

View file

@ -0,0 +1,5 @@
<x-layouts.app.sidebar :title="$title ?? null">
<flux:main>
{{ $slot }}
</flux:main>
</x-layouts.app.sidebar>

View file

@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
<head>
@include('partials.head')
</head>
<body class="min-h-screen bg-white dark:bg-zinc-800">
<flux:header container class="border-b border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900">
<flux:sidebar.toggle class="lg:hidden" icon="bars-2" inset="left" />
<a href="{{ route('dashboard') }}" class="ms-2 me-5 flex items-center space-x-2 rtl:space-x-reverse lg:ms-0" wire:navigate>
<x-app-logo />
</a>
<flux:navbar class="-mb-px max-lg:hidden">
<flux:navbar.item icon="layout-grid" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>
{{ __('Dashboard') }}
</flux:navbar.item>
</flux:navbar>
<flux:spacer />
<flux:navbar class="me-1.5 space-x-0.5 rtl:space-x-reverse py-0!">
<flux:tooltip :content="__('Search')" position="bottom">
<flux:navbar.item class="!h-10 [&>div>svg]:size-5" icon="magnifying-glass" href="#" :label="__('Search')" />
</flux:tooltip>
<flux:tooltip :content="__('Repository')" position="bottom">
<flux:navbar.item
class="h-10 max-lg:hidden [&>div>svg]:size-5"
icon="folder-git-2"
href="https://github.com/laravel/livewire-starter-kit"
target="_blank"
:label="__('Repository')"
/>
</flux:tooltip>
<flux:tooltip :content="__('Documentation')" position="bottom">
<flux:navbar.item
class="h-10 max-lg:hidden [&>div>svg]:size-5"
icon="book-open-text"
href="https://laravel.com/docs/starter-kits#livewire"
target="_blank"
label="Documentation"
/>
</flux:tooltip>
</flux:navbar>
<!-- Desktop User Menu -->
<flux:dropdown position="top" align="end">
<flux:profile
class="cursor-pointer"
:initials="auth()->user()->initials()"
/>
<flux:menu>
<flux:menu.radio.group>
<div class="p-0 text-sm font-normal">
<div class="flex items-center gap-2 px-1 py-1.5 text-start text-sm">
<span class="relative flex h-8 w-8 shrink-0 overflow-hidden rounded-lg">
<span
class="flex h-full w-full items-center justify-center rounded-lg bg-neutral-200 text-black dark:bg-neutral-700 dark:text-white"
>
{{ auth()->user()->initials() }}
</span>
</span>
<div class="grid flex-1 text-start text-sm leading-tight">
<span class="truncate font-semibold">{{ auth()->user()->name }}</span>
<span class="truncate text-xs">{{ auth()->user()->email }}</span>
</div>
</div>
</div>
</flux:menu.radio.group>
<flux:menu.separator />
<flux:menu.radio.group>
<flux:menu.item :href="route('settings.profile')" icon="cog" wire:navigate>{{ __('Settings') }}</flux:menu.item>
</flux:menu.radio.group>
<flux:menu.separator />
<form method="POST" action="{{ route('logout') }}" class="w-full">
@csrf
<flux:menu.item as="button" type="submit" icon="arrow-right-start-on-rectangle" class="w-full">
{{ __('Log Out') }}
</flux:menu.item>
</form>
</flux:menu>
</flux:dropdown>
</flux:header>
<!-- Mobile Menu -->
<flux:sidebar stashable sticky class="lg:hidden border-e border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900">
<flux:sidebar.toggle class="lg:hidden" icon="x-mark" />
<a href="{{ route('dashboard') }}" class="ms-1 flex items-center space-x-2 rtl:space-x-reverse" wire:navigate>
<x-app-logo />
</a>
<flux:navlist variant="outline">
<flux:navlist.group :heading="__('Platform')">
<flux:navlist.item icon="layout-grid" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>
{{ __('Dashboard') }}
</flux:navlist.item>
</flux:navlist.group>
</flux:navlist>
<flux:spacer />
<flux:navlist variant="outline">
<flux:navlist.item icon="folder-git-2" href="https://github.com/laravel/livewire-starter-kit" target="_blank">
{{ __('Repository') }}
</flux:navlist.item>
<flux:navlist.item icon="book-open-text" href="https://laravel.com/docs/starter-kits#livewire" target="_blank">
{{ __('Documentation') }}
</flux:navlist.item>
</flux:navlist>
</flux:sidebar>
{{ $slot }}
@fluxScripts
</body>
</html>

View file

@ -0,0 +1,166 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
<head>
@include('partials.head')
</head>
<body class="min-h-screen bg-white dark:bg-zinc-800">
<flux:sidebar sticky stashable class="border-e border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900">
<flux:sidebar.toggle class="lg:hidden" icon="x-mark" />
<a href="{{ config('domains.domain_main_url') }}" class="me-5 flex items-center space-x-2 rtl:space-x-reverse">
<x-app-logo />
</a>
<flux:navlist variant="outline">
<flux:navlist.group :heading="__('Trader')" class="grid mb-4">
<flux:navlist.item icon="home" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
</flux:navlist.group>
<flux:navlist.group :heading="__('Customer')" class="grid mb-4">
<flux:navlist.item icon="home" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
</flux:navlist.group>
<flux:navlist.group :heading="__('Admin')" class="grid mb-4">
<flux:navlist.item icon="user-group" :href="route('admin.users')" :current="request()->routeIs('admin.users')" wire:navigate>{{ __('Users') }}</flux:navlist.item>
<flux:navlist.item icon="user-group" :href="route('admin.users.table')" :current="request()->routeIs('admin.users.table')" wire:navigate>{{ __('Users Table') }}</flux:navlist.item>
<flux:navlist.group expandable expanded="false" heading="Favorites" class="hidden lg:grid">
<flux:navlist.item icon="user-group" :href="route('admin.users')" :current="request()->routeIs('admin.users')" wire:navigate>{{ __('Users') }}</flux:navlist.item>
<flux:navlist.item icon="user-group" :href="route('admin.users.table')" :current="request()->routeIs('admin.users.table')" wire:navigate>{{ __('Users Table') }}</flux:navlist.item>
</flux:navlist.group>
</flux:navlist.group>
<flux:navlist.group :heading="__('CMS')" class="grid mb-4">
<flux:navlist.item icon="home" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
</flux:navlist.group>
<flux:navlist.group :heading="__('Superadmin')" class="grid mb-4">
<flux:navlist.item icon="home" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
</flux:navlist.group>
</flux:navlist>
<flux:spacer />
<flux:navlist variant="outline">
<flux:navlist.group :heading="__('Resources')">
<flux:navlist.item icon="pencil" href="https://tailwindcss.com/docs/installation/using-vite" target="_blank">
{{ __('Tailwind CSS') }}
</flux:navlist.item>
<flux:navlist.item icon="shield-check" href="https://heroicons.com" target="_blank">
{{ __('Hero Icons') }}
</flux:navlist.item>
<flux:navlist.item icon="bolt" href="https://fluxui.dev/docs/installation" target="_blank">
{{ __('Flux UI') }}
</flux:navlist.item>
<flux:navlist.item icon="folder-git-2" href="https://github.com/laravel/livewire-starter-kit" target="_blank">
{{ __('Repository') }}
</flux:navlist.item>
<flux:navlist.item icon="book-open-text" href="https://laravel.com/docs/starter-kits" target="_blank">
{{ __('Documentation') }}
</flux:navlist.item>
</flux:navlist.group>
</flux:navlist>
<!-- Desktop User Menu -->
<flux:dropdown position="bottom" align="start">
<flux:profile
:name="auth()->user()->name"
:initials="auth()->user()->initials()"
icon-trailing="chevrons-up-down"
/>
<flux:menu class="w-[220px]">
<flux:menu.radio.group>
<div class="p-0 text-sm font-normal">
<div class="flex items-center gap-2 px-1 py-1.5 text-start text-sm">
<span class="relative flex h-8 w-8 shrink-0 overflow-hidden rounded-lg">
<span
class="flex h-full w-full items-center justify-center rounded-lg bg-neutral-200 text-black dark:bg-neutral-700 dark:text-white"
>
{{ auth()->user()->initials() }}
</span>
</span>
<div class="grid flex-1 text-start text-sm leading-tight">
<span class="truncate font-semibold">{{ auth()->user()->name }}</span>
<span class="truncate text-xs">{{ auth()->user()->email }}</span>
</div>
</div>
</div>
</flux:menu.radio.group>
<flux:menu.separator />
<flux:menu.radio.group>
<flux:menu.item :href="route('settings.profile')" icon="cog" wire:navigate>{{ __('Settings') }}</flux:menu.item>
</flux:menu.radio.group>
<flux:menu.separator />
<form method="POST" action="{{ route('logout') }}" class="w-full">
@csrf
<flux:menu.item as="button" type="submit" icon="arrow-right-start-on-rectangle" class="w-full">
{{ __('Log Out') }}
</flux:menu.item>
</form>
</flux:menu>
</flux:dropdown>
</flux:sidebar>
<!-- Mobile User Menu -->
<flux:header class="lg:hidden">
<flux:sidebar.toggle class="lg:hidden" icon="bars-2" inset="left" />
<a href="{{ config('domains.domain_main_url') }}" class="me-5 ml-2 flex items-center space-x-2 rtl:space-x-reverse">
<x-app-logo />
</a>
<flux:spacer />
<flux:dropdown position="top" align="end">
<flux:profile
:initials="auth()->user()->initials()"
icon-trailing="chevron-down"
/>
<flux:menu>
<flux:menu.radio.group>
<div class="p-0 text-sm font-normal">
<div class="flex items-center gap-2 px-1 py-1.5 text-start text-sm">
<span class="relative flex h-8 w-8 shrink-0 overflow-hidden rounded-lg">
<span
class="flex h-full w-full items-center justify-center rounded-lg bg-neutral-200 text-black dark:bg-neutral-700 dark:text-white"
>
{{ auth()->user()->initials() }}
</span>
</span>
<div class="grid flex-1 text-start text-sm leading-tight">
<span class="truncate font-semibold">{{ auth()->user()->name }}</span>
<span class="truncate text-xs">{{ auth()->user()->email }}</span>
</div>
</div>
</div>
</flux:menu.radio.group>
<flux:menu.separator />
<flux:menu.radio.group>
<flux:menu.item :href="route('settings.profile')" icon="cog" wire:navigate>{{ __('Settings') }}</flux:menu.item>
</flux:menu.radio.group>
<flux:menu.separator />
<form method="POST" action="{{ route('logout') }}" class="w-full">
@csrf
<flux:menu.item as="button" type="submit" icon="arrow-right-start-on-rectangle" class="w-full">
{{ __('Log Out') }}
</flux:menu.item>
</form>
</flux:menu>
</flux:dropdown>
</flux:header>
{{ $slot }}
@fluxScripts
</body>
</html>

View file

@ -0,0 +1,3 @@
<x-layouts.auth.simple :title="$title ?? null">
{{ $slot }}
</x-layouts.auth.simple>

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
<head>
@include('partials.head')
</head>
<body class="min-h-screen bg-neutral-100 antialiased dark:bg-linear-to-b dark:from-neutral-950 dark:to-neutral-900">
<div class="bg-muted flex min-h-svh flex-col items-center justify-center gap-6 p-6 md:p-10">
<div class="flex w-full max-w-md flex-col gap-6">
<a href="{{ route('home') }}" class="flex flex-col items-center gap-2 font-medium" wire:navigate>
<span class="flex h-9 w-9 items-center justify-center rounded-md">
<x-app-logo-icon class="size-9 fill-current text-black dark:text-white" />
</span>
<span class="sr-only">{{ config('app.name', 'Laravel') }}</span>
</a>
<div class="flex flex-col gap-6">
<div class="rounded-xl border bg-white dark:bg-stone-950 dark:border-stone-800 text-stone-800 shadow-xs">
<div class="px-10 py-8">{{ $slot }}</div>
</div>
</div>
</div>
</div>
@fluxScripts
</body>
</html>

View file

@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
<head>
@include('partials.head')
</head>
<body class="min-h-screen bg-white antialiased dark:bg-linear-to-b dark:from-neutral-950 dark:to-neutral-900">
<div class="bg-background flex min-h-svh flex-col items-center justify-center gap-6 p-6 md:p-10">
<div class="flex w-full max-w-sm flex-col gap-2">
<a href="{{ route('home') }}" class="flex flex-col items-center gap-2 font-medium" wire:navigate>
<span class="flex h-9 w-9 mb-1 items-center justify-center rounded-md">
<x-app-logo-icon class="size-9 fill-current text-black dark:text-white" />
</span>
<span class="sr-only">{{ config('app.name', 'Laravel') }}</span>
</a>
<div class="flex flex-col gap-6">
{{ $slot }}
</div>
</div>
</div>
@livewireScripts
@fluxScripts
<script src="{{ asset('vendor/livewire/livewire.js') }}"></script>
<!-- Debug: Script-Status -->
<script>
console.log('Body Scripts geladen');
console.log('Livewire JS:', {{ file_exists(public_path('vendor/livewire/livewire.js')) ? 'true' : 'false' }});
if (typeof Livewire !== 'undefined') {
console.log('Livewire verfügbar:', true);
} else {
console.log('Livewire verfügbar:', false);
}
</script>
</body>
</html>

View file

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
<head>
@include('partials.head')
</head>
<body class="min-h-screen bg-white antialiased dark:bg-linear-to-b dark:from-neutral-950 dark:to-neutral-900">
<div class="relative grid h-dvh flex-col items-center justify-center px-8 sm:px-0 lg:max-w-none lg:grid-cols-2 lg:px-0">
<div class="bg-muted relative hidden h-full flex-col p-10 text-white lg:flex dark:border-e dark:border-neutral-800">
<div class="absolute inset-0 bg-neutral-900"></div>
<a href="{{ route('home') }}" class="relative z-20 flex items-center text-lg font-medium" wire:navigate>
<span class="flex h-10 w-10 items-center justify-center rounded-md">
<x-app-logo-icon class="me-2 h-7 fill-current text-white" />
</span>
{{ config('app.name', 'Laravel') }}
</a>
@php
[$message, $author] = str(Illuminate\Foundation\Inspiring::quotes()->random())->explode('-');
@endphp
<div class="relative z-20 mt-auto">
<blockquote class="space-y-2">
<flux:heading size="lg">&ldquo;{{ trim($message) }}&rdquo;</flux:heading>
<footer><flux:heading>{{ trim($author) }}</flux:heading></footer>
</blockquote>
</div>
</div>
<div class="w-full lg:p-8">
<div class="mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]">
<a href="{{ route('home') }}" class="z-20 flex flex-col items-center gap-2 font-medium lg:hidden" wire:navigate>
<span class="flex h-9 w-9 items-center justify-center rounded-md">
<x-app-logo-icon class="size-9 fill-current text-black dark:text-white" />
</span>
<span class="sr-only">{{ config('app.name', 'Laravel') }}</span>
</a>
{{ $slot }}
</div>
</div>
</div>
@fluxScripts
</body>
</html>

View file

@ -0,0 +1,12 @@
@props([
'id' => uniqid(),
])
<svg {{ $attributes }} fill="none">
<defs>
<pattern id="pattern-{{ $id }}" x="0" y="0" width="8" height="8" patternUnits="userSpaceOnUse">
<path d="M-1 5L5 -1M3 9L8.5 3.5" stroke-width="0.5"></path>
</pattern>
</defs>
<rect stroke="none" fill="url(#pattern-{{ $id }})" width="100%" height="100%"></rect>
</svg>

View file

@ -0,0 +1,20 @@
<div class="flex items-start max-md:flex-col">
<div class="me-10 w-full pb-4 md:w-[220px]">
<flux:navlist>
<flux:navlist.item :href="route('settings.profile')" wire:navigate>{{ __('Profile') }}</flux:navlist.item>
<flux:navlist.item :href="route('settings.password')" wire:navigate>{{ __('Password') }}</flux:navlist.item>
<flux:navlist.item :href="route('settings.appearance')" wire:navigate>{{ __('Appearance') }}</flux:navlist.item>
</flux:navlist>
</div>
<flux:separator class="md:hidden" />
<div class="flex-1 self-stretch max-md:pt-6">
<flux:heading>{{ $heading ?? '' }}</flux:heading>
<flux:subheading>{{ $subheading ?? '' }}</flux:subheading>
<div class="mt-5 w-full max-w-lg">
{{ $slot }}
</div>
</div>
</div>

View file

@ -0,0 +1,51 @@
@props([
'expandable' => false,
'expanded' => true,
'heading' => null,
])
<?php if ($expandable && $heading): ?>
<ui-disclosure
{{ $attributes->class('group/disclosure') }}
@if ($expanded === true) open @endif
data-flux-navlist-group
>
<button
type="button"
class="group/disclosure-button mb-[2px] flex h-10 w-full items-center rounded-lg text-zinc-500 hover:bg-zinc-800/5 hover:text-zinc-800 lg:h-8 dark:text-white/80 dark:hover:bg-white/[7%] dark:hover:text-white"
>
<div class="ps-3 pe-4">
<flux:icon.chevron-down class="hidden size-3! group-data-open/disclosure-button:block" />
<flux:icon.chevron-right class="block size-3! group-data-open/disclosure-button:hidden" />
</div>
<span class="text-sm font-medium leading-none">{{ $heading }}</span>
</button>
<div class="relative hidden space-y-[2px] ps-7 data-open:block" @if ($expanded === true) data-open @endif>
<div class="absolute inset-y-[3px] start-0 ms-4 w-px bg-zinc-200 dark:bg-white/30"></div>
{{ $slot }}
</div>
</ui-disclosure>
<?php elseif ($heading): ?>
<div {{ $attributes->class('block space-y-[2px]') }}>
<div class="px-1 py-2">
<div class="text-xs leading-none text-zinc-400">{{ $heading }}</div>
</div>
<div>
{{ $slot }}
</div>
</div>
<?php else: ?>
<div {{ $attributes->class('block space-y-[2px]') }}>
{{ $slot }}
</div>
<?php endif; ?>

View file

@ -0,0 +1,149 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>@yield('title', $domainName ?? 'Admin - ' . config('app.name'))</title>
<!-- Favicon -->
<link rel="icon" href="{{ asset('img/favicons/admin-favicon.ico') }}">
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=instrument-sans:400,500,600,700" rel="stylesheet" />
<!-- Styles -->
@vite(['resources/css/admin.css', 'resources/js/app.js'])
<!-- Additional Styles -->
@stack('styles')
</head>
<body class="antialiased bg-gray-50 dark:bg-gray-900">
<div class="min-h-screen flex">
<!-- Sidebar Navigation -->
<aside class="w-64 bg-white dark:bg-gray-800 shadow-md hidden md:block">
<div class="p-6">
<a href="{{ route('admin.home') }}" class="text-xl font-bold text-gray-900 dark:text-white">
{{ $domainName ?? config('app.name') . ' Admin' }}
</a>
</div>
<nav class="mt-10 px-6">
<a href="{{ route('admin.dashboard') }}" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-100 dark:hover:bg-gray-700 {{ request()->routeIs('admin.dashboard') ? 'bg-gray-100 dark:bg-gray-700' : '' }}">
Dashboard
</a>
<a href="{{ route('admin.settings.profile') }}" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-100 dark:hover:bg-gray-700 {{ request()->routeIs('admin.settings.profile') ? 'bg-gray-100 dark:bg-gray-700' : '' }}">
Profil
</a>
<!-- Weitere Navigationspunkte hier -->
</nav>
</aside>
<div class="flex-1 flex flex-col">
<!-- Top Navigation -->
<header class="bg-white dark:bg-gray-800 shadow-sm">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex items-center md:hidden">
<!-- Mobile menu button -->
<button type="button" class="text-gray-500 hover:text-gray-600 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500" id="mobile-menu-button">
<span class="sr-only">Menu öffnen</span>
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
<div class="flex items-center">
@if(app()->environment('local'))
<!-- Domain-Informationsanzeige (nur in local) -->
<div class="mr-4 text-xs px-2 py-1 rounded bg-indigo-100 text-indigo-800 dark:bg-indigo-900 dark:text-indigo-200">
{{ Request::getHost() }}
@if(config('domains.dev_settings.simulate_domain'))
<span class="inline-flex items-center ml-1 px-1.5 py-0.5 rounded-full text-xs bg-yellow-100 text-yellow-800">
Simuliert
</span>
@endif
</div>
@endif
<!-- User Dropdown -->
<div class="ml-3 relative">
<div>
<button type="button" class="flex text-sm rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" id="user-menu-button">
<span class="sr-only">Benutzermenü öffnen</span>
<div class="h-8 w-8 rounded-full bg-gray-200 flex items-center justify-center">
<span class="text-xs font-medium">{{ Auth::user()->name[0] ?? 'U' }}</span>
</div>
</button>
</div>
<!-- Dropdown menu -->
<div class="hidden origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg py-1 bg-white dark:bg-gray-700 ring-1 ring-black ring-opacity-5 focus:outline-none" role="menu" id="user-menu">
<a href="{{ route('admin.settings.profile') }}" class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600" role="menuitem">Profil</a>
<a href="{{ route('admin.settings.appearance') }}" class="block px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600" role="menuitem">Einstellungen</a>
<form method="POST" action="{{ route('logout') }}">
@csrf
<button type="submit" class="block w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600" role="menuitem">Abmelden</button>
</form>
</div>
</div>
</div>
</div>
</div>
</header>
<!-- Mobile menu (off-canvas) -->
<div class="md:hidden hidden" id="mobile-menu">
<div class="px-2 pt-2 pb-3 space-y-1 bg-white dark:bg-gray-800 shadow-lg">
<a href="{{ route('admin.dashboard') }}" class="block px-3 py-2 rounded-md text-base font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700">Dashboard</a>
<a href="{{ route('admin.settings.profile') }}" class="block px-3 py-2 rounded-md text-base font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700">Profil</a>
<!-- Weitere mobile Navigationspunkte hier -->
</div>
</div>
<!-- Page Content -->
<main class="flex-1 py-10">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
@yield('content')
</div>
</main>
</div>
</div>
<!-- Scripts -->
<script>
// Toggle user dropdown
const userMenuButton = document.getElementById('user-menu-button');
const userMenu = document.getElementById('user-menu');
if (userMenuButton && userMenu) {
userMenuButton.addEventListener('click', function() {
userMenu.classList.toggle('hidden');
});
// Close the dropdown when clicked outside
document.addEventListener('click', function(event) {
if (!userMenuButton.contains(event.target) && !userMenu.contains(event.target)) {
userMenu.classList.add('hidden');
}
});
}
// Mobile menu toggle
const mobileMenuButton = document.getElementById('mobile-menu-button');
const mobileMenu = document.getElementById('mobile-menu');
if (mobileMenuButton && mobileMenu) {
mobileMenuButton.addEventListener('click', function() {
mobileMenu.classList.toggle('hidden');
});
}
</script>
<!-- Additional Scripts -->
@stack('scripts')
</body>
</html>

View file

@ -0,0 +1,165 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>@yield('title', $domainName ?? config('app.name', 'Laravel'))</title>
<!-- Domain-spezifisches Favicon -->
<link rel="icon" href="{{ asset('img/favicons/' . $theme . '-favicon.ico') }}">
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
@if($theme === 'landing1')
<link href="https://fonts.bunny.net/css?family=inter:400,500,600,700" rel="stylesheet" />
@elseif($theme === 'landing2')
<link href="https://fonts.bunny.net/css?family=poppins:400,500,600,700" rel="stylesheet" />
@else
<link href="https://fonts.bunny.net/css?family=instrument-sans:400,500,600,700" rel="stylesheet" />
@endif
<!-- Dynamisches CSS basierend auf Domain-Konfiguration -->
@if($theme === 'landing1')
@vite('resources/css/web/theme-landing1.css')
@elseif($theme === 'landing2')
@vite('resources/css/web/theme-landing2.css')
@else
@vite('resources/css/web/theme-main.css')
@endif
@vite('resources/js/app.js')
<!-- Additional Styles -->
@stack('styles')
<!-- Domain-spezifische Inline-Styles -->
{{-- @if(isset($domainConfig['color_scheme']))
<style>
:root {
@if(isset($domainConfig['color_scheme']['primary']))
--primary-color: {{ $domainConfig['color_scheme']['primary'] }};
@endif
@if(isset($domainConfig['color_scheme']['accent']))
--accent-color: {{ $domainConfig['color_scheme']['accent'] }};
@endif
}
</style>
@endif --}}
</head>
<body class="antialiased">
<div class="min-h-screen bg-gray-100 dark:bg-gray-900 flex flex-col">
<!-- Header -->
<header class="bg-white dark:bg-gray-800 shadow">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex items-center">
<a href="{{ url('/') }}" class="text-xl font-bold text-primary-800 dark:text-primary-200">
{{ $domainName ?? config('app.name', 'Laravel') }}
</a>
<nav class="ml-10 space-x-4">
<a href="{{ url('/') }}" class="text-primary-600 hover:text-primary-900 dark:text-primary-300 dark:hover:text-primary-100">Home</a>
<a href="{{ url('/welcome') }}" class="text-primary-600 hover:text-primary-900 dark:text-primary-300 dark:hover:text-primary-100">Welcome</a>
<a href="https://portal.b2in.test" class="text-primary-600 hover:text-primary-900 dark:text-primary-300 dark:hover:text-primary-100">Portal</a>
<!-- Weitere Navigationspunkte hier -->
</nav>
</div>
<div class="flex items-center">
<!-- Theme-Switcher -->
<button id="theme-toggle" type="button" class="text-accent-600 dark:text-accent-400 hover:text-accent-800 dark:hover:text-accent-200 rounded-lg text-sm p-2.5">
<svg id="theme-toggle-dark-icon" class="hidden w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"></path></svg>
<svg id="theme-toggle-light-icon" class="hidden w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>
</button>
@if(app()->environment('local'))
<!-- Domain-Simulationsanzeige (nur in local) -->
<div class="ml-4 text-xs px-2 py-1 rounded bg-accent-100 text-accent-800 dark:bg-accent-800 dark:text-accent-100">
{{ $theme }} / {{ Request::getHost() }}
@if(config('domains.dev_settings.simulate_domain'))
<span class="inline-flex items-center ml-1 px-1.5 py-0.5 rounded-full text-xs bg-yellow-100 text-yellow-800">
Simuliert
</span>
@endif
</div>
@endif
</div>
</div>
</div>
</header>
<!-- Page Content -->
<main class="flex-grow py-10">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
@yield('content')
</div>
</main>
<!-- Footer -->
<footer class="bg-white dark:bg-gray-800 shadow py-6">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between">
<div>
<p class="text-gray-500 dark:text-gray-400">
&copy; {{ date('Y') }} {{ $domainName ?? config('app.name', 'Laravel') }}. Alle Rechte vorbehalten.
</p>
</div>
<div>
<!-- Footer-Links -->
<div class="flex space-x-4">
<a href="#" class="text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300">Impressum</a>
<a href="#" class="text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300">Datenschutz</a>
</div>
</div>
</div>
</div>
</footer>
</div>
<!-- Dark Mode Toggle Script -->
<script>
const themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon');
const themeToggleLightIcon = document.getElementById('theme-toggle-light-icon');
// Set initial icon state
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
themeToggleLightIcon.classList.remove('hidden');
document.documentElement.classList.add('dark');
} else {
themeToggleDarkIcon.classList.remove('hidden');
document.documentElement.classList.remove('dark');
}
// Toggle theme
document.getElementById('theme-toggle').addEventListener('click', function() {
themeToggleDarkIcon.classList.toggle('hidden');
themeToggleLightIcon.classList.toggle('hidden');
if (localStorage.getItem('color-theme')) {
if (localStorage.getItem('color-theme') === 'light') {
document.documentElement.classList.add('dark');
localStorage.setItem('color-theme', 'dark');
} else {
document.documentElement.classList.remove('dark');
localStorage.setItem('color-theme', 'light');
}
} else {
if (document.documentElement.classList.contains('dark')) {
document.documentElement.classList.remove('dark');
localStorage.setItem('color-theme', 'light');
} else {
document.documentElement.classList.add('dark');
localStorage.setItem('color-theme', 'dark');
}
}
});
</script>
<!-- Additional Scripts -->
@stack('scripts')
</body>
</html>

View file

@ -0,0 +1,57 @@
<?php
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
use Livewire\Attributes\Layout;
use Livewire\Volt\Component;
new #[Layout('components.layouts.auth')] class extends Component {
public string $password = '';
/**
* Confirm the current user's password.
*/
public function confirmPassword(): void
{
$this->validate([
'password' => ['required', 'string'],
]);
if (! Auth::guard('web')->validate([
'email' => Auth::user()->email,
'password' => $this->password,
])) {
throw ValidationException::withMessages([
'password' => __('auth.password'),
]);
}
session(['auth.password_confirmed_at' => time()]);
$this->redirectIntended(default: route('dashboard', absolute: false), navigate: true);
}
}; ?>
<div class="flex flex-col gap-6">
<x-auth-header
:title="__('Confirm password')"
:description="__('This is a secure area of the application. Please confirm your password before continuing.')"
/>
<!-- Session Status -->
<x-auth-session-status class="text-center" :status="session('status')" />
<form wire:submit="confirmPassword" class="flex flex-col gap-6">
<!-- Password -->
<flux:input
wire:model="password"
:label="__('Password')"
type="password"
required
autocomplete="new-password"
:placeholder="__('Password')"
/>
<flux:button variant="primary" type="submit" class="w-full">{{ __('Confirm') }}</flux:button>
</form>
</div>

View file

@ -0,0 +1,49 @@
<?php
use Illuminate\Support\Facades\Password;
use Livewire\Attributes\Layout;
use Livewire\Volt\Component;
new #[Layout('components.layouts.auth')] class extends Component {
public string $email = '';
/**
* Send a password reset link to the provided email address.
*/
public function sendPasswordResetLink(): void
{
$this->validate([
'email' => ['required', 'string', 'email'],
]);
Password::sendResetLink($this->only('email'));
session()->flash('status', __('A reset link will be sent if the account exists.'));
}
}; ?>
<div class="flex flex-col gap-6">
<x-auth-header :title="__('Forgot password')" :description="__('Enter your email to receive a password reset link')" />
<!-- Session Status -->
<x-auth-session-status class="text-center" :status="session('status')" />
<form wire:submit="sendPasswordResetLink" class="flex flex-col gap-6">
<!-- Email Address -->
<flux:input
wire:model="email"
:label="__('Email Address')"
type="email"
required
autofocus
placeholder="email@example.com"
/>
<flux:button variant="primary" type="submit" class="w-full">{{ __('Email password reset link') }}</flux:button>
</form>
<div class="space-x-1 text-center text-sm text-zinc-400">
{{ __('Or, return to') }}
<flux:link :href="route('login')" wire:navigate>{{ __('log in') }}</flux:link>
</div>
</div>

View file

@ -0,0 +1,153 @@
<?php
use Illuminate\Auth\Events\Lockout;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Validate;
use Livewire\Volt\Component;
new #[Layout('components.layouts.auth')] class extends Component {
#[Validate('required|string|email')]
public string $email = '';
#[Validate('required|string')]
public string $password = '';
public bool $remember = false;
/**
* Handle an incoming authentication request.
*/
public function login(): void
{
$this->validate();
$this->ensureIsNotRateLimited();
if (! Auth::attempt(['email' => $this->email, 'password' => $this->password], $this->remember)) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'email' => __('auth.failed'),
]);
}
RateLimiter::clear($this->throttleKey());
Session::regenerate();
$this->redirectIntended(default: route('dashboard', absolute: false), navigate: true);
}
/**
* Ensure the authentication request is not rate limited.
*/
protected function ensureIsNotRateLimited(): void
{
if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
return;
}
event(new Lockout(request()));
$seconds = RateLimiter::availableIn($this->throttleKey());
throw ValidationException::withMessages([
'email' => __('auth.throttle', [
'seconds' => $seconds,
'minutes' => ceil($seconds / 60),
]),
]);
}
/**
* Get the authentication rate limiting throttle key.
*/
protected function throttleKey(): string
{
return Str::transliterate(Str::lower($this->email).'|'.request()->ip());
}
}; ?>
<div class="flex flex-col gap-6 p-8 bg-white rounded-lg shadow-lg">
<div class="text-center">
<h1 class="text-2xl font-bold text-gray-900">Log in to your account</h1>
<p class="text-gray-600 mt-2">Enter your email and password below to log in</p>
</div>
<!-- Session Status -->
@if (session('status'))
<div class="text-center text-sm text-green-600">
{{ session('status') }}
</div>
@endif
<form wire:submit="login" class="flex flex-col gap-6">
<!-- Email Address -->
<div>
<label for="email" class="block text-sm font-medium text-gray-700">Email address</label>
<input
wire:model="email"
id="email"
type="email"
required
autofocus
autocomplete="email"
placeholder="email@example.com"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
/>
@error('email')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
</div>
<!-- Password -->
<div class="relative">
<label for="password" class="block text-sm font-medium text-gray-700">Password</label>
<input
wire:model="password"
id="password"
type="password"
required
autocomplete="current-password"
placeholder="Password"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
/>
@error('password')
<p class="mt-1 text-sm text-red-600">{{ $message }}</p>
@enderror
@if (Route::has('password.request'))
<a href="{{ route('password.request') }}" class="absolute right-0 top-0 text-sm text-blue-600 hover:text-blue-500">
Forgot your password?
</a>
@endif
</div>
<!-- Remember Me -->
<div class="flex items-center">
<input
wire:model="remember"
id="remember"
type="checkbox"
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
/>
<label for="remember" class="ml-2 block text-sm text-gray-900">Remember me</label>
</div>
<button type="submit" class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
Log in
</button>
</form>
@if (Route::has('register'))
<div class="text-center text-sm text-gray-600">
Don't have an account?
<a href="{{ route('register') }}" class="text-blue-600 hover:text-blue-500">Sign up</a>
</div>
@endif
</div>

View file

@ -0,0 +1,126 @@
<?php
use Illuminate\Auth\Events\Lockout;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Validate;
use Livewire\Volt\Component;
new #[Layout('components.layouts.auth')] class extends Component {
#[Validate('required|string|email')]
public string $email = '';
#[Validate('required|string')]
public string $password = '';
public bool $remember = false;
/**
* Handle an incoming authentication request.
*/
public function login(): void
{
$this->validate();
$this->ensureIsNotRateLimited();
if (! Auth::attempt(['email' => $this->email, 'password' => $this->password], $this->remember)) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'email' => __('auth.failed'),
]);
}
RateLimiter::clear($this->throttleKey());
Session::regenerate();
$this->redirectIntended(default: route('dashboard', absolute: false), navigate: true);
}
/**
* Ensure the authentication request is not rate limited.
*/
protected function ensureIsNotRateLimited(): void
{
if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
return;
}
event(new Lockout(request()));
$seconds = RateLimiter::availableIn($this->throttleKey());
throw ValidationException::withMessages([
'email' => __('auth.throttle', [
'seconds' => $seconds,
'minutes' => ceil($seconds / 60),
]),
]);
}
/**
* Get the authentication rate limiting throttle key.
*/
protected function throttleKey(): string
{
return Str::transliterate(Str::lower($this->email).'|'.request()->ip());
}
}; ?>
<div class="flex flex-col gap-6">
<x-auth-header :title="__('Log in to your account')" :description="__('Enter your email and password below to log in')" />
<!-- Session Status -->
<x-auth-session-status class="text-center" :status="session('status')" />
<form wire:submit="login" class="flex flex-col gap-6">
<!-- Email Address -->
<flux:input
wire:model="email"
:label="__('Email address')"
type="email"
required
autofocus
autocomplete="email"
placeholder="email@example.com"
/>
<!-- Password -->
<div class="relative">
<flux:input
wire:model="password"
:label="__('Password')"
type="password"
required
autocomplete="current-password"
:placeholder="__('Password')"
/>
@if (Route::has('password.request'))
<flux:link class="absolute right-0 top-0 text-sm" :href="route('password.request')" wire:navigate>
{{ __('Forgot your password?') }}
</flux:link>
@endif
</div>
<!-- Remember Me -->
<flux:checkbox wire:model="remember" :label="__('Remember me')" />
<div class="flex items-center justify-end">
<flux:button variant="primary" type="submit" class="w-full">{{ __('Log in') }}</flux:button>
</div>
</form>
@if (Route::has('register'))
<div class="space-x-1 text-center text-sm text-zinc-600 dark:text-zinc-400">
{{ __('Don\'t have an account?') }}
<flux:link :href="route('register')" wire:navigate>{{ __('Sign up') }}</flux:link>
</div>
@endif
</div>

View file

@ -0,0 +1,97 @@
<?php
use App\Models\User;
use Illuminate\Auth\Events\Registered;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules;
use Livewire\Attributes\Layout;
use Livewire\Volt\Component;
new #[Layout('components.layouts.auth')] class extends Component {
public string $name = '';
public string $email = '';
public string $password = '';
public string $password_confirmation = '';
/**
* Handle an incoming registration request.
*/
public function register(): void
{
$validated = $this->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:' . User::class],
'password' => ['required', 'string', 'confirmed', Rules\Password::defaults()],
]);
$validated['password'] = Hash::make($validated['password']);
event(new Registered(($user = User::create($validated))));
Auth::login($user);
$this->redirectIntended(route('dashboard', absolute: false), navigate: true);
}
}; ?>
<div class="flex flex-col gap-6">
<x-auth-header :title="__('Create an account')" :description="__('Enter your details below to create your account')" />
<!-- Session Status -->
<x-auth-session-status class="text-center" :status="session('status')" />
<form wire:submit="register" class="flex flex-col gap-6">
<!-- Name -->
<flux:input
wire:model="name"
:label="__('Name')"
type="text"
required
autofocus
autocomplete="name"
:placeholder="__('Full name')"
/>
<!-- Email Address -->
<flux:input
wire:model="email"
:label="__('Email address')"
type="email"
required
autocomplete="email"
placeholder="email@example.com"
/>
<!-- Password -->
<flux:input
wire:model="password"
:label="__('Password')"
type="password"
required
autocomplete="new-password"
:placeholder="__('Password')"
/>
<!-- Confirm Password -->
<flux:input
wire:model="password_confirmation"
:label="__('Confirm password')"
type="password"
required
autocomplete="new-password"
:placeholder="__('Confirm password')"
/>
<div class="flex items-center justify-end">
<flux:button type="submit" variant="primary" class="w-full">
{{ __('Create account') }}
</flux:button>
</div>
</form>
<div class="space-x-1 text-center text-sm text-zinc-600 dark:text-zinc-400">
{{ __('Already have an account?') }}
<flux:link :href="route('login')" wire:navigate>{{ __('Log in') }}</flux:link>
</div>
</div>

View file

@ -0,0 +1,113 @@
<?php
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Locked;
use Livewire\Volt\Component;
new #[Layout('components.layouts.auth')] class extends Component {
#[Locked]
public string $token = '';
public string $email = '';
public string $password = '';
public string $password_confirmation = '';
/**
* Mount the component.
*/
public function mount(string $token): void
{
$this->token = $token;
$this->email = request()->string('email');
}
/**
* Reset the password for the given user.
*/
public function resetPassword(): void
{
$this->validate([
'token' => ['required'],
'email' => ['required', 'string', 'email'],
'password' => ['required', 'string', 'confirmed', Rules\Password::defaults()],
]);
// Here we will attempt to reset the user's password. If it is successful we
// will update the password on an actual user model and persist it to the
// database. Otherwise we will parse the error and return the response.
$status = Password::reset(
$this->only('email', 'password', 'password_confirmation', 'token'),
function ($user) {
$user->forceFill([
'password' => Hash::make($this->password),
'remember_token' => Str::random(60),
])->save();
event(new PasswordReset($user));
}
);
// If the password was successfully reset, we will redirect the user back to
// the application's home authenticated view. If there is an error we can
// redirect them back to where they came from with their error message.
if ($status != Password::PasswordReset) {
$this->addError('email', __($status));
return;
}
Session::flash('status', __($status));
$this->redirectRoute('login', navigate: true);
}
}; ?>
<div class="flex flex-col gap-6">
<x-auth-header :title="__('Reset password')" :description="__('Please enter your new password below')" />
<!-- Session Status -->
<x-auth-session-status class="text-center" :status="session('status')" />
<form wire:submit="resetPassword" class="flex flex-col gap-6">
<!-- Email Address -->
<flux:input
wire:model="email"
:label="__('Email')"
type="email"
required
autocomplete="email"
/>
<!-- Password -->
<flux:input
wire:model="password"
:label="__('Password')"
type="password"
required
autocomplete="new-password"
:placeholder="__('Password')"
/>
<!-- Confirm Password -->
<flux:input
wire:model="password_confirmation"
:label="__('Confirm password')"
type="password"
required
autocomplete="new-password"
:placeholder="__('Confirm password')"
/>
<div class="flex items-center justify-end">
<flux:button type="submit" variant="primary" class="w-full">
{{ __('Reset password') }}
</flux:button>
</div>
</form>
</div>

View file

@ -0,0 +1,57 @@
<?php
use App\Livewire\Actions\Logout;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use Livewire\Attributes\Layout;
use Livewire\Volt\Component;
new #[Layout('components.layouts.auth')] class extends Component {
/**
* Send an email verification notification to the user.
*/
public function sendVerification(): void
{
if (Auth::user()->hasVerifiedEmail()) {
$this->redirectIntended(default: route('dashboard', absolute: false), navigate: true);
return;
}
Auth::user()->sendEmailVerificationNotification();
Session::flash('status', 'verification-link-sent');
}
/**
* Log the current user out of the application.
*/
public function logout(Logout $logout): void
{
$logout();
$this->redirect('/', navigate: true);
}
}; ?>
<div class="mt-4 flex flex-col gap-6">
<flux:text class="text-center">
{{ __('Please verify your email address by clicking on the link we just emailed to you.') }}
</flux:text>
@if (session('status') == 'verification-link-sent')
<flux:text class="text-center font-medium !dark:text-green-400 !text-green-600">
{{ __('A new verification link has been sent to the email address you provided during registration.') }}
</flux:text>
@endif
<div class="flex flex-col items-center justify-between space-y-3">
<flux:button wire:click="sendVerification" variant="primary" class="w-full">
{{ __('Resend verification email') }}
</flux:button>
<flux:link class="text-sm cursor-pointer" wire:click="logout">
{{ __('Log out') }}
</flux:link>
</div>
</div>

View file

@ -0,0 +1,11 @@
<?php
use Livewire\Volt\Component;
new class extends Component {
public bool $notifications = false;
}; ?>
<div>
<flux:switch wire:model.live="notifications" label="Enable notifications" />
</div>

View file

@ -0,0 +1,189 @@
<?php
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Livewire\Volt\Component;
use Livewire\WithPagination; // Wichtig für Paginierung
new class extends Component {
use WithPagination;
// Optional: Such- und Filter-Properties
public string $search = '';
public string $statusFilter = '';
public string $roleFilter = '';
// Optional: Sortierung
public string $sortField = 'name';
public string $sortDirection = 'asc';
/**
* Mount the component.
*/
public function mount(): void
{
// Standardwerte für Sortierung setzen
$this->sortField = 'name';
$this->sortDirection = 'asc';
}
public function sortBy(string $field): void
{
if ($this->sortField === $field) {
$this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc';
} else {
$this->sortDirection = 'asc';
}
$this->sortField = $field;
}
// Die Hauptmethode, um Daten zu laden
public function users()
{
return User::query()
->when($this->search, fn($query, $search) =>
$query->where('name', 'like', '%' . $search . '%')
->orWhere('email', 'like', '%' . $search . '%')
)
->when($this->statusFilter, fn($query, $status) =>
$query->where('status', $status)
)
->when($this->roleFilter, fn($query, $role) =>
$query->where('role', $role) // oder 'role_id' wenn du IDs verwendest
)
->orderBy($this->sortField, $this->sortDirection)
->paginate(10); // 10 Einträge pro Seite
}
// Optional: Lifecycle hook für das Zurücksetzen der Paginierung bei Suche/Filterung
public function updatedSearch() { $this->resetPage(); }
public function updatedStatusFilter() { $this->resetPage(); }
public function updatedRoleFilter() { $this->resetPage(); }
// Wird für die Paginierung mit Tailwind benötigt (Standard in Livewire 3)
// Wenn FluxUI Bootstrap-basierte Paginierung braucht, musst du das anpassen
// public function paginationView()
// {
// return 'vendor.livewire.tailwind'; // oder 'livewire::bootstrap'
// }
// Wenn du mit Relationen arbeitest (z.B. user->role->name)
// public function with(): array
// {
// return [
// 'users' => User::with(['role', 'group']) // Eager loading
// // ... deine Query-Logik von oben ...
// ->paginate(10),
// ];
// }
}; ?>
<div>
{{-- Filter und Suchleiste (Beispiel, FluxUI Klassen anpassen) --}}
<div class="mb-4 grid grid-cols-1 md:grid-cols-3 gap-4 p-4 bg-gray-100 rounded">
<div>
<label for="search" class="block text-sm font-medium text-gray-700">Suche</label>
<input wire:model.live.debounce.300ms="search" id="search" type="text" placeholder="Name oder E-Mail..."
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
</div>
<div>
<label for="statusFilter" class="block text-sm font-medium text-gray-700">Status</label>
<select wire:model.live="statusFilter" id="statusFilter"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
<option value="">Alle</option>
<option value="active">Aktiv</option>
<option value="inactive">Inaktiv</option>
<option value="pending">Ausstehend</option>
</select>
</div>
<div>
<label for="roleFilter" class="block text-sm font-medium text-gray-700">Rolle</label>
<input wire:model.live.debounce.300ms="roleFilter" id="roleFilter" type="text" placeholder="Rolle..."
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
</div>
</div>
{{-- Tabelle (FluxUI Klassen anpassen!) --}}
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200 shadow">
<thead class="bg-gray-50"> {{-- FluxUI Klasse für Thead --}}
<tr>
<th scope="col" wire:click="sortBy('name')"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer">
Name @if($sortField === 'name')<span>{{ $sortDirection === 'asc' ? '▲' : '▼' }}</span>@endif
</th>
<th scope="col" wire:click="sortBy('email')"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer">
E-Mail @if($sortField === 'email')<span>{{ $sortDirection === 'asc' ? '▲' : '▼' }}</span>@endif
</th>
<th scope="col" wire:click="sortBy('status')"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer">
Status @if($sortField === 'status')<span>{{ $sortDirection === 'asc' ? '▲' : '▼' }}</span>@endif
</th>
<th scope="col" wire:click="sortBy('role')"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer">
Rolle @if($sortField === 'role')<span>{{ $sortDirection === 'asc' ? '▲' : '▼' }}</span>@endif
</th>
<th scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Gruppe
</th>
<th scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-700 uppercase tracking-wider">
Rechte
</th>
<th scope="col" class="relative px-6 py-3">
<span class="sr-only">Aktionen</span>
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200"> {{-- FluxUI Klasse für Tbody --}}
@forelse ($this->users() as $user)
<tr wire:key="{{ $user->id }}">
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{{ $user->name }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ $user->email }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full
{{ $user->status === 'active' ? 'bg-green-100 text-green-800' : ($user->status === 'inactive' ? 'bg-red-100 text-red-800' : 'bg-yellow-100 text-yellow-800') }}">
{{ ucfirst($user->status) }}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{{ $user->role }} {{-- Oder $user->role->name, wenn es eine Relation ist --}}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{{ $user->group }} {{-- Oder $user->group->name --}}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{{-- Darstellung der Rechte. Wenn es eine Many-to-Many Relation ist: --}}
{{-- @foreach($user->permissions as $permission)
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800">
{{ $permission->name }}
</span>
@endforeach --}}
{{-- Oder wenn es ein JSON-Feld ist, musst du es parsen und anzeigen --}}
Einfache Rechte-Anzeige (Todo)
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<a href="#" class="text-indigo-600 hover:text-indigo-900">Bearbeiten</a> {{-- FluxUI Button-Klassen --}}
<button wire:click="$dispatch('openModal', { component: 'admin.delete-user-modal', arguments: { userId: {{ $user->id }} }})"
class="text-red-600 hover:text-red-900 ml-2">Löschen</button> {{-- FluxUI Button-Klassen --}}
</td>
</tr>
@empty
<tr>
<td colspan="7" class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 text-center">
Keine Benutzer gefunden.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
<div class="mt-4">
{{ $this->users()->links() }} {{-- Stellt sicher, dass die Paginierungs-Views für dein UI-Kit konfiguriert sind --}}
</div>
</div>

View file

@ -0,0 +1,144 @@
<?php
use App\Models\User;
use Livewire\Volt\Component;
use Livewire\WithPagination; // Wichtig für Paginierung
new class extends Component {
use WithPagination;
// Optional: Such- und Filter-Properties
public string $search = '';
public string $statusFilter = '';
public string $roleFilter = '';
// Optional: Sortierung
public $sortBy = 'name';
public $sortDirection = 'asc';
/**
* Mount the component.
*/
public function mount(): void
{
// Standardwerte für Sortierung setzen
$this->sortBy = 'name';
$this->sortDirection = 'asc';
}
public function sort($column) {
if ($this->sortBy === $column) {
$this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc';
} else {
$this->sortBy = $column;
$this->sortDirection = 'asc';
}
}
/*public function orders()
{
return \App\Models\Order::query()
->tap(fn ($query) => $this->sortBy ? $query->orderBy($this->sortBy, $this->sortDirection) : $query)
->paginate(5);
}*/
// Die Hauptmethode, um Daten zu laden
#[\Livewire\Attributes\Computed]
public function users()
{
return User::query()
->when($this->search, fn($query, $search) =>
$query->where('name', 'like', '%' . $search . '%')
->orWhere('email', 'like', '%' . $search . '%')
)
->when($this->statusFilter, fn($query, $status) =>
$query->where('status', $status)
)
->when($this->roleFilter, fn($query, $role) =>
$query->where('role', $role) // oder 'role_id' wenn du IDs verwendest
)
->orderBy($this->sortBy, $this->sortDirection)
->paginate(10); // 10 Einträge pro Seite
}
// Optional: Lifecycle hook für das Zurücksetzen der Paginierung bei Suche/Filterung
public function updatedSearch() { $this->resetPage(); }
public function updatedStatusFilter() { $this->resetPage(); }
public function updatedRoleFilter() { $this->resetPage(); }
// Wird für die Paginierung mit Tailwind benötigt (Standard in Livewire 3)
// Wenn FluxUI Bootstrap-basierte Paginierung braucht, musst du das anpassen
// public function paginationView()
// {
// return 'vendor.livewire.tailwind'; // oder 'livewire::bootstrap'
// }
// Wenn du mit Relationen arbeitest (z.B. user->role->name)
// public function with(): array
// {
// return [
// 'users' => User::with(['role', 'group']) // Eager loading
// // ... deine Query-Logik von oben ...
// ->paginate(10),
// ];
// }
}; ?>
<flux:table :paginate="$this->users">
<flux:table.columns>
<flux:table.column>Customer</flux:table.column>
<flux:table.column sortable :sorted="$sortBy === 'date'" :direction="$sortDirection" wire:click="sort('date')">Date</flux:table.column>
<flux:table.column sortable :sorted="$sortBy === 'status'" :direction="$sortDirection" wire:click="sort('status')">Status</flux:table.column>
<flux:table.column sortable :sorted="$sortBy === 'amount'" :direction="$sortDirection" wire:click="sort('amount')">Amount</flux:table.column>
</flux:table.columns>
<flux:table.rows>
@foreach ($this->users as $user)
<flux:table.row :key="$user->id">
<flux:table.cell class="flex items-center gap-3">
<flux:avatar size="xs" src="{{ $user->avatar }}" />
{{ $user->name }}
</flux:table.cell>
<flux:table.cell class="whitespace-nowrap">{{ $user->email }}</flux:table.cell>
<flux:table.cell>
<flux:badge size="sm" color="lime" inset="top bottom">RTest</flux:badge>
</flux:table.cell>
<flux:table.cell variant="strong">{{ $user->role }}</flux:table.cell>
<flux:table.cell>
<flux:dropdown>
<flux:button variant="ghost" size="sm" icon="ellipsis-horizontal" inset="top bottom"></flux:button>
<flux:menu>
<flux:menu.item icon="plus">New post</flux:menu.item>
<flux:menu.separator />
<flux:menu.submenu heading="Sort by">
<flux:menu.radio.group>
<flux:menu.radio checked>Name</flux:menu.radio>
<flux:menu.radio>Date</flux:menu.radio>
<flux:menu.radio>Popularity</flux:menu.radio>
</flux:menu.radio.group>
</flux:menu.submenu>
<flux:menu.submenu heading="Filter">
<flux:menu.checkbox checked>Draft</flux:menu.checkbox>
<flux:menu.checkbox checked>Published</flux:menu.checkbox>
<flux:menu.checkbox>Archived</flux:menu.checkbox>
</flux:menu.submenu>
<flux:menu.separator />
<flux:menu.item variant="danger" icon="trash">Delete</flux:menu.item>
</flux:menu>
</flux:dropdown>
</flux:table.cell>
</flux:table.row>
@endforeach
</flux:table.rows>
</flux:table>

View file

@ -0,0 +1,19 @@
<?php
use Livewire\Volt\Component;
new class extends Component {
//
}; ?>
<section class="w-full">
@include('partials.settings-heading')
<x-settings.layout :heading="__('Appearance')" :subheading=" __('Update the appearance settings for your account')">
<flux:radio.group x-data variant="segmented" x-model="$flux.appearance">
<flux:radio value="light" icon="sun">{{ __('Light') }}</flux:radio>
<flux:radio value="dark" icon="moon">{{ __('Dark') }}</flux:radio>
<flux:radio value="system" icon="computer-desktop">{{ __('System') }}</flux:radio>
</flux:radio.group>
</x-settings.layout>
</section>

View file

@ -0,0 +1,58 @@
<?php
use App\Livewire\Actions\Logout;
use Illuminate\Support\Facades\Auth;
use Livewire\Volt\Component;
new class extends Component {
public string $password = '';
/**
* Delete the currently authenticated user.
*/
public function deleteUser(Logout $logout): void
{
$this->validate([
'password' => ['required', 'string', 'current_password'],
]);
tap(Auth::user(), $logout(...))->delete();
$this->redirect('/', navigate: true);
}
}; ?>
<section class="mt-10 space-y-6">
<div class="relative mb-5">
<flux:heading>{{ __('Delete account') }}</flux:heading>
<flux:subheading>{{ __('Delete your account and all of its resources') }}</flux:subheading>
</div>
<flux:modal.trigger name="confirm-user-deletion">
<flux:button variant="danger" x-data="" x-on:click.prevent="$dispatch('open-modal', 'confirm-user-deletion')">
{{ __('Delete account') }}
</flux:button>
</flux:modal.trigger>
<flux:modal name="confirm-user-deletion" :show="$errors->isNotEmpty()" focusable class="max-w-lg">
<form wire:submit="deleteUser" class="space-y-6">
<div>
<flux:heading size="lg">{{ __('Are you sure you want to delete your account?') }}</flux:heading>
<flux:subheading>
{{ __('Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.') }}
</flux:subheading>
</div>
<flux:input wire:model="password" :label="__('Password')" type="password" />
<div class="flex justify-end space-x-2 rtl:space-x-reverse">
<flux:modal.close>
<flux:button variant="filled">{{ __('Cancel') }}</flux:button>
</flux:modal.close>
<flux:button variant="danger" type="submit">{{ __('Delete account') }}</flux:button>
</div>
</form>
</flux:modal>
</section>

View file

@ -0,0 +1,78 @@
<?php
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules\Password;
use Illuminate\Validation\ValidationException;
use Livewire\Volt\Component;
new class extends Component {
public string $current_password = '';
public string $password = '';
public string $password_confirmation = '';
/**
* Update the password for the currently authenticated user.
*/
public function updatePassword(): void
{
try {
$validated = $this->validate([
'current_password' => ['required', 'string', 'current_password'],
'password' => ['required', 'string', Password::defaults(), 'confirmed'],
]);
} catch (ValidationException $e) {
$this->reset('current_password', 'password', 'password_confirmation');
throw $e;
}
Auth::user()->update([
'password' => Hash::make($validated['password']),
]);
$this->reset('current_password', 'password', 'password_confirmation');
$this->dispatch('password-updated');
}
}; ?>
<section class="w-full">
@include('partials.settings-heading')
<x-settings.layout :heading="__('Update password')" :subheading="__('Ensure your account is using a long, random password to stay secure')">
<form wire:submit="updatePassword" class="mt-6 space-y-6">
<flux:input
wire:model="current_password"
:label="__('Current password')"
type="password"
required
autocomplete="current-password"
/>
<flux:input
wire:model="password"
:label="__('New password')"
type="password"
required
autocomplete="new-password"
/>
<flux:input
wire:model="password_confirmation"
:label="__('Confirm Password')"
type="password"
required
autocomplete="new-password"
/>
<div class="flex items-center gap-4">
<div class="flex items-center justify-end">
<flux:button variant="primary" type="submit" class="w-full">{{ __('Save') }}</flux:button>
</div>
<x-action-message class="me-3" on="password-updated">
{{ __('Saved.') }}
</x-action-message>
</div>
</form>
</x-settings.layout>
</section>

View file

@ -0,0 +1,114 @@
<?php
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use Illuminate\Validation\Rule;
use Livewire\Volt\Component;
new class extends Component {
public string $name = '';
public string $email = '';
/**
* Mount the component.
*/
public function mount(): void
{
$this->name = Auth::user()->name;
$this->email = Auth::user()->email;
}
/**
* Update the profile information for the currently authenticated user.
*/
public function updateProfileInformation(): void
{
$user = Auth::user();
$validated = $this->validate([
'name' => ['required', 'string', 'max:255'],
'email' => [
'required',
'string',
'lowercase',
'email',
'max:255',
Rule::unique(User::class)->ignore($user->id)
],
]);
$user->fill($validated);
if ($user->isDirty('email')) {
$user->email_verified_at = null;
}
$user->save();
$this->dispatch('profile-updated', name: $user->name);
}
/**
* Send an email verification notification to the current user.
*/
public function resendVerificationNotification(): void
{
$user = Auth::user();
if ($user->hasVerifiedEmail()) {
$this->redirectIntended(default: route('dashboard', absolute: false));
return;
}
$user->sendEmailVerificationNotification();
Session::flash('status', 'verification-link-sent');
}
}; ?>
<section class="w-full">
@include('partials.settings-heading')
<x-settings.layout :heading="__('Profile')" :subheading="__('Update your name and email address')">
<form wire:submit="updateProfileInformation" class="my-6 w-full space-y-6">
<flux:input wire:model="name" :label="__('Name')" type="text" required autofocus autocomplete="name" />
<div>
<flux:input wire:model="email" :label="__('Email')" type="email" required autocomplete="email" />
@if (auth()->user() instanceof \Illuminate\Contracts\Auth\MustVerifyEmail &&! auth()->user()->hasVerifiedEmail())
<div>
<flux:text class="mt-4">
{{ __('Your email address is unverified.') }}
<flux:link class="text-sm cursor-pointer" wire:click.prevent="resendVerificationNotification">
{{ __('Click here to re-send the verification email.') }}
</flux:link>
</flux:text>
@if (session('status') === 'verification-link-sent')
<flux:text class="mt-2 font-medium !dark:text-green-400 !text-green-600">
{{ __('A new verification link has been sent to your email address.') }}
</flux:text>
@endif
</div>
@endif
</div>
<div class="flex items-center gap-4">
<div class="flex items-center justify-end">
<flux:button variant="primary" type="submit" class="w-full">{{ __('Save') }}</flux:button>
</div>
<x-action-message class="me-3" on="profile-updated">
{{ __('Saved.') }}
</x-action-message>
</div>
</form>
<livewire:settings.delete-user-form />
</x-settings.layout>
</section>

View file

@ -0,0 +1,20 @@
<div class="text-center mb-16">
<h2 class="text-section-title mb-8">Button-Demo</h2>
<div class="flex flex-wrap justify-center gap-4">
<button class="btn-primary">Primary Button</button>
<button class="btn-secondary">Secondary Button</button>
<button class="btn-accent">Accent Button</button>
</div>
<div class="mt-8">
<p class="text-sm text-muted-foreground mb-4">Hover-Effekte:</p>
<div class="flex flex-wrap justify-center gap-4">
<button class="btn-primary-accent">
Primary Accent (Hover)
</button>
<button class="btn-secondary-accent">
Secondary Accent (Hover)
</button>
</div>
</div>
</div>

View file

@ -0,0 +1,20 @@
<div class="text-center mb-16">
<h2 class="text-section-title mb-8">Farb-Demo</h2>
<div class="grid md:grid-cols-3 gap-6">
<div class="card-elevated p-6">
<div class="w-full h-20 bg-primary rounded-lg mb-4"></div>
<h3 class="font-medium">Primary</h3>
<p class="text-sm text-muted-foreground">{{ \App\Helpers\ThemeHelper::getPrimaryColor() }}</p>
</div>
<div class="card-elevated p-6">
<div class="w-full h-20 bg-secondary rounded-lg mb-4"></div>
<h3 class="font-medium">Secondary</h3>
<p class="text-sm text-muted-foreground">{{ \App\Helpers\ThemeHelper::getSecondaryColor() }}</p>
</div>
<div class="card-elevated p-6">
<div class="w-full h-20 bg-accent rounded-lg mb-4"></div>
<h3 class="font-medium">Accent</h3>
<p class="text-sm text-muted-foreground">Neutral</p>
</div>
</div>
</div>

View file

@ -0,0 +1,14 @@
<div class="text-center mb-16">
<h2 class="text-section-title mb-8">{{ $title }}</h2>
@if ($description)
<p class="text-muted-foreground mb-8 max-w-2xl mx-auto">{{ $description }}</p>
@endif
<div class="card-elevated p-8">
@if ($component)
<livewire:web.components.{{ $component }} />
@else
{{ $slot }}
@endif
</div>
</div>

View file

@ -0,0 +1,19 @@
<div class="text-center mb-16">
<h2 class="text-section-title mb-8">Logo-Demo</h2>
<div class="grid md:grid-cols-2 gap-8">
<div class="card-elevated p-8">
<h3 class="text-lg font-medium mb-4">Positives Logo</h3>
<div class="flex justify-center">
<img src="{{ asset(\App\Helpers\ThemeHelper::getLogoPath('positive')) }}"
alt="{{ $domainName ?? 'B2IN' }} Logo" class="h-16 w-auto" />
</div>
</div>
<div class="card-elevated p-8 bg-dark-bg">
<h3 class="text-lg font-medium mb-4 text-dark-text">Negatives Logo</h3>
<div class="flex justify-center">
<img src="{{ asset(\App\Helpers\ThemeHelper::getLogoPath('negative')) }}"
alt="{{ $domainName ?? 'B2IN' }} Logo" class="h-16 w-auto" />
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,40 @@
<div class="text-center mb-16">
<h1 class="text-hero mb-8">
Theme Demo für <span class="text-secondary">{{ $domainName ?? 'B2IN' }}</span>
</h1>
<div class="card-elevated p-8 max-w-4xl mx-auto">
<div class="grid md:grid-cols-2 gap-8 text-left">
<div>
<h3 class="text-xl font-medium mb-4">Aktuelle Domain-Konfiguration</h3>
<div class="space-y-2 text-sm">
<p><strong>Domain:</strong> {{ $domainName ?? 'Nicht erkannt' }}</p>
<p><strong>Theme:</strong> {{ $theme ?? 'b2in' }}</p>
<p><strong>View Prefix:</strong> {{ $viewPrefix ?? 'b2in' }}</p>
<p><strong>URL:</strong> {{ $domainUrl ?? config('app.url') }}</p>
</div>
</div>
<div>
<h3 class="text-xl font-medium mb-4">Theme-Details</h3>
<div class="space-y-2 text-sm">
@php
$domainConfig = \App\Helpers\ThemeHelper::getDomainConfig();
@endphp
<p><strong>Primärfarbe:</strong>
<span class="inline-block w-4 h-4 rounded-full mr-2"
style="background-color: {{ \App\Helpers\ThemeHelper::getPrimaryColor() }}"></span>
{{ \App\Helpers\ThemeHelper::getPrimaryColor() }}
</p>
<p><strong>Sekundärfarbe:</strong>
<span class="inline-block w-4 h-4 rounded-full mr-2"
style="background-color: {{ \App\Helpers\ThemeHelper::getSecondaryColor() }}"></span>
{{ \App\Helpers\ThemeHelper::getSecondaryColor() }}
</p>
<p><strong>Primärschrift:</strong> {{ \App\Helpers\ThemeHelper::getPrimaryFont() }}</p>
<p><strong>Sekundärschrift:</strong> {{ \App\Helpers\ThemeHelper::getSecondaryFont() }}</p>
</div>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,35 @@
<div class="text-center">
<h2 class="text-section-title mb-8">Domain-Switching</h2>
<div class="card-elevated p-8 max-w-4xl mx-auto">
<p class="text-muted-foreground mb-6">Testen Sie das Theme-Switching mit verschiedenen Domains:</p>
<!-- Domain-basierte Links -->
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
@foreach ($domains as $domain)
<a href="{{ $domain['url'] }}/theme-demo" class="btn-secondary text-center">{{ $domain['domain_name'] }} Theme</a>
@endforeach
</div>
{{-- <div class="border-t pt-6">
<p class="text-muted-foreground mb-4">Oder testen Sie das Theme-Switching über URL-Parameter:</p>
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<a href="/theme-demo?theme=b2in" class="btn-accent text-center">B2IN (URL)</a>
<a href="/theme-demo?theme=b2a" class="btn-accent text-center">B2A (URL)</a>
<a href="/theme-demo?theme=stileigentum" class="btn-accent text-center">Stileigentum (URL)</a>
<a href="/theme-demo?theme=style2own" class="btn-accent text-center">Style2own (URL)</a>
</div>
<div class="border-t pt-6">
<p class="text-muted-foreground mb-4">Für lokale Entwicklung ohne Domain-Setup (Pfad-basiert):</p>
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-4">
<a href="/b2in/theme-demo" class="btn-primary text-center">B2IN (Pfad)</a>
<a href="/b2a/theme-demo" class="btn-primary text-center">B2A (Pfad)</a>
<a href="/stileigentum/theme-demo" class="btn-primary text-center">Stileigentum (Pfad)</a>
<a href="/style2own/theme-demo" class="btn-primary text-center">Style2own (Pfad)</a>
</div>
</div>
--}}
</div>
</div>
</div>

View file

@ -0,0 +1,37 @@
<section class="section-padding 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-16 items-center">
<div class="space-y-8">
<h1 class="text-hero">
{!! $content['title'] !!}
</h1>
<blockquote class="text-large text-muted-foreground italic leading-relaxed border-l-4 border-secondary pl-6">
{{ $content['quote'] }}
</blockquote>
<div class="flex items-center gap-4">
<div class="w-16 h-px bg-secondary"></div>
<div>
<p class="font-semibold text-foreground">{{ $content['founder_name'] }}</p>
<p class="text-sm text-muted-foreground">{{ $content['founder_title'] }}</p>
</div>
</div>
</div>
<div class="relative">
<div class="card-elevated rounded-3xl overflow-hidden">
<img
src="{{ asset('img/assets/' . $content['image']) }}"
alt="{{ $content['image_alt'] }}"
class="w-full h-96 lg:h-[500px] object-cover"
/>
</div>
<div class="absolute -bottom-6 -right-6 bg-secondary text-secondary-foreground p-6 rounded-2xl">
<div class="text-3xl font-bold">{{ $content['year'] }}</div>
<p class="text-sm opacity-90">{{ $content['year_text'] }}</p>
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,39 @@
<section class="section-padding {{ $bg }}">
<div class="container-padding">
{{-- Section Title --}}
<div class="text-center mb-16">
<h2 class="text-section-title">{{ $title }}</h2>
<p class="text-large text-muted-foreground mt-4 max-w-2xl mx-auto">
{{ $subtitle }}
</p>
</div>
{{-- Brand Cards --}}
<div class="grid md:grid-cols-3 gap-8">
@foreach ($worlds as $world)
<div class="card-elevated overflow-hidden group hover:shadow-elevated transition-all duration-300">
<div class="relative">
<img src="{{ asset('img/assets/' . $world['image']) }}" alt="{{ $world['title'] }}"
class="w-full h-64 object-cover group-hover:scale-105 transition-transform duration-500" />
</div>
<div class="p-6 spacing-small">
<h3 class="text-xl font-medium">{{ $world['title'] }}</h3>
<p class="text-muted-foreground leading-relaxed">
{{ $world['description'] }}
</p>
<a href="{{ $world['link'] }}"
class="inline-flex items-center gap-2 text-secondary font-medium hover:gap-3 transition-all duration-300">
Mehr erfahren
<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>
</div>
</div>
@endforeach
</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,22 @@
<section class="{{ $bg }} text-secondary-foreground section-padding">
<div class="container-narrow text-center">
<div class="spacing-section">
<h2 class="text-section-title text-white">
{!! $content['title'] !!}
</h2>
<p class="text-large text-secondary-foreground max-w-2xl mx-auto leading-relaxed">
{{ $content['subtitle'] }}
</p>
<div class="pt-4">
<a
href="{{ $content['button_link'] }}"
class="btn-primary-accent px-8 py-4 text-lg"
>
{{ $content['button_text'] }}
</a>
</div>
</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">
<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 $testimonial)
<div class="card-elevated rounded-2xl p-8 text-left space-y-6">
<div class="flex items-center gap-4">
<img src="{{ asset('img/assets/' . $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,59 @@
<section class="section-padding {{ $bg }}">
<div class="container-padding">
<div class="grid lg:grid-cols-2 gap-12 lg:gap-16 items-center">
@if($layout === 'right')
{{-- Layout Right: Image zuerst, dann Content --}}
{{-- Image --}}
<div class="relative lg:order-1">
<div class="card-elevated rounded-3xl overflow-hidden">
<img
src="{{ asset('img/assets/' . $content['image']) }}"
alt="{{ $content['image_alt'] }}"
class="w-full h-[500px] object-cover"
/>
<div class="absolute bottom-6 left-6 bg-card/95 backdrop-blur-sm rounded-xl p-4 shadow-lg border border-border/50">{{ $content['image_caption'] }}</div>
</div>
</div>
{{-- Content --}}
<div class="spacing-section lg:order-2">
<div class="spacing-content">
<h2 class="text-section-title">{{ $content['title'] }}</h2>
<div class="spacing-small text-large text-muted-foreground leading-relaxed">
@foreach($content['paragraphs'] as $paragraph)
<p>{{ $paragraph }}</p>
@endforeach
</div>
</div>
</div>
@else
{{-- Layout Left (Standard): Content zuerst, dann Image --}}
{{-- Content --}}
<div class="spacing-section">
<div class="spacing-content">
<h2 class="text-section-title">{{ $content['title'] }}</h2>
<div class="spacing-small text-large text-muted-foreground leading-relaxed">
@foreach($content['paragraphs'] as $paragraph)
<p>{{ $paragraph }}</p>
@endforeach
</div>
</div>
</div>
{{-- Image --}}
<div class="relative">
<div class="card-elevated rounded-3xl overflow-hidden">
<img
src="{{ asset('img/assets/' . $content['image']) }}"
alt="{{ $content['image_alt'] }}"
class="w-full h-[500px] object-cover"
/>
<div class="absolute bottom-6 left-6 bg-card/95 backdrop-blur-sm rounded-xl p-4 shadow-lg border border-border/50">{{ $content['image_caption'] }}</div>
</div>
</div>
@endif
</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="{{ asset('img/assets/' . $content['image']) }}" alt="{{ $content['image_alt'] }}"
class="w-full h-96 object-cover" />
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,58 @@
<section class="section-padding bg-background">
<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-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 {{ $index === 4 ? 'md:col-span-2 lg:col-span-1 lg:col-start-2' : '' }}">
<div class="card-elevated p-8 rounded-3xl h-full hover:scale-105 transition-all duration-300 relative overflow-hidden">
<div class="text-center space-y-6">
<div class="w-16 h-16 mx-auto rounded-xl bg-secondary/10 flex items-center justify-center mb-6">
@if($feature['icon'] === 'cloud')
<svg class="w-8 h-8 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"/>
</svg>
@elseif($feature['icon'] === 'shield')
<svg class="w-8 h-8 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>
@elseif($feature['icon'] === 'layers')
<svg class="w-8 h-8 text-secondary" 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"/>
</svg>
@elseif($feature['icon'] === 'database')
<svg class="w-8 h-8 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4"/>
</svg>
@else
<svg class="w-8 h-8 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z"/>
</svg>
@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,55 @@
{{-- Hero Icons Helper Function --}}
@php
function renderHeroIcon($iconName, $style = 'outline') {
$iconPath = public_path("heroicons/optimized/24/{$style}/{$iconName}.svg");
$fallbackPath = public_path("heroicons/optimized/24/outline/sparkles.svg");
if (file_exists($iconPath)) {
$svg = file_get_contents($iconPath);
// Add classes for styling
return str_replace('<svg', '<svg class="w-10 h-10 text-secondary"', $svg);
} elseif (file_exists($fallbackPath)) {
$svg = file_get_contents($fallbackPath);
return str_replace('<svg', '<svg class="w-10 h-10 text-secondary"', $svg);
}
// Ultimate fallback - simple star icon
return '<svg class="w-10 h-10 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.563.563 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z"/>
</svg>';
}
@endphp
<section class="section-padding {{ $bg }}">
<div class="container-padding">
{{-- Section Title --}}
<div class="text-center mb-16">
<h2 class="text-section-title">{{ $content['title'] }}</h2>
@if(isset($content['subtitle']))
<p class="text-large text-muted-foreground mt-4 max-w-2xl mx-auto">
{{ $content['subtitle'] }}
</p>
@endif
</div>
{{-- Pillars Grid --}}
<div class="grid md:grid-cols-3 gap-8 lg:gap-12">
@foreach($content['pillars'] as $index => $pillar)
<div class="card-elevated rounded-2xl p-8 text-center">
<div class="text-center spacing-content 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">
{!! renderHeroIcon($pillar['icon'], $pillar['icon_style'] ?? 'outline') !!}
</div>
<div class="spacing-small">
<h3 class="text-xl font-medium">{{ $pillar['title'] }}</h3>
<p class="text-muted-foreground leading-relaxed">
{{ $pillar['description'] }}
</p>
</div>
</div>
</div>
@endforeach
</div>
</div>
</section>

View file

@ -0,0 +1,79 @@
<section class="section-padding 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-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="{{ asset('img/assets/' . $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,28 @@
<section class="section-padding bg-background">
<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-3xl mx-auto">
{{ $content['subtitle'] }}
</p>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-8">
@foreach ($content['stats'] as $stat)
<div class="card-elevated rounded-2xl p-8 text-center">
<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="{{ asset('img/assets/' . $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,67 @@
<div x-data="{ openIndex: null }">
<section class="section-padding {{ $bg }}">
<div class="container-padding">
{{-- Section Title --}}
<div class="text-center mb-16">
<h2 class="text-hero mb-6">
{!! $content['title'] !!}
</h2>
@if(!empty($content['subtitle']))
<p class="text-large text-muted-foreground max-w-2xl mx-auto">
{!! $content['subtitle'] !!}
</p>
@endif
</div>
{{-- FAQ Container --}}
<div class="max-w-4xl mx-auto">
@if(!empty($content['questions']))
<div class="space-y-4">
@foreach($content['questions'] as $index => $faq)
<div class="card-elevated rounded-xl overflow-hidden">
<dt>
<button
@click="openIndex = openIndex === {{ $index }} ? null : {{ $index }}"
class="flex w-full items-center justify-between p-6 text-left hover:bg-muted/30 transition-colors duration-200"
:aria-expanded="openIndex === {{ $index }}"
>
<span class="text-lg font-medium text-foreground pr-6">
{{ $faq['question'] }}
</span>
<span class="flex-shrink-0 ml-6 flex h-8 w-8 items-center justify-center rounded-full bg-secondary/10 transition-all duration-200"
:class="openIndex === {{ $index }} ? 'bg-secondary text-white' : 'text-secondary hover:bg-secondary/20'">
<svg class="w-5 h-5 transition-transform duration-200"
:class="openIndex === {{ $index }} ? 'rotate-180' : ''"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</span>
</button>
</dt>
<dd x-show="openIndex === {{ $index }}"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0 transform -translate-y-2"
x-transition:enter-end="opacity-100 transform translate-y-0"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100 transform translate-y-0"
x-transition:leave-end="opacity-0 transform -translate-y-2"
class="px-6 pb-6">
<div class="border-t border-border pt-4">
<p class="text-muted-foreground leading-relaxed">
{{ $faq['answer'] }}
</p>
</div>
</dd>
</div>
@endforeach
</div>
@else
{{-- Fallback wenn keine FAQ-Daten vorhanden --}}
<div class="text-center py-12">
<p class="text-muted-foreground">Keine FAQ-Inhalte verfügbar.</p>
</div>
@endif
</div>
</div>
</section>
</div>

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="{{ asset('img/assets/' . ($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,139 @@
<div x-data="heroSlider()" x-init="init()">
<section class="relative mb-10">
<!-- Slider Container -->
<div class="absolute inset-0 overflow-hidden">
@if(!empty($content['slides']))
@foreach($content['slides'] as $index => $slide)
<div
class="absolute inset-0 transition-opacity duration-1000 ease-in-out"
:class="currentSlide === {{ $index }} ? 'opacity-100' : 'opacity-0'"
>
<img
src="{{ asset('img/assets/' . $slide['image']) }}"
alt="{{ $slide['image_alt'] }}"
class="size-full object-cover"
/>
<div class="absolute inset-0 bg-gray-900 opacity-20"></div>
</div>
@endforeach
@endif
</div>
<!-- Content -->
<div class="relative mx-auto flex max-w-3xl flex-col items-center px-6 py-32 text-center sm:py-64 lg:px-0">
<h1 class="text-hero text-white">
{!! $content['title'] !!}
</h1>
<p class="mt-4 text-xl text-white">{!! $content['subtitle'] !!}</p>
<a href="{{ $content['cta1_link'] }}" class="mt-8 inline-block btn-secondary-accent">{{ $content['cta1_text'] }}</a>
</div>
<!-- Navigation Dots -->
@if(!empty($content['slides']) && count($content['slides']) > 1)
<div class="absolute bottom-8 left-1/2 transform -translate-x-1/2">
<div class="flex space-x-3">
@foreach($content['slides'] as $index => $slide)
<button
@click="setSlide({{ $index }})"
class="w-3 h-3 rounded-full border-2 border-white/50 transition-all duration-300"
:class="currentSlide === {{ $index }} ? 'bg-white border-white' : 'bg-transparent hover:border-white/80'"
aria-label="Slide {{ $index + 1 }} anzeigen"
></button>
@endforeach
</div>
</div>
@endif
<!-- Arrow Navigation (Optional) -->
@if(!empty($content['slides']) && count($content['slides']) > 1)
<button
@click="previousSlide()"
class="absolute left-6 top-1/2 transform -translate-y-1/2 text-white/70 hover:text-white transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-white/50 rounded-full p-2"
aria-label="Vorheriges Bild"
>
<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="M15 19l-7-7 7-7"></path>
</svg>
</button>
<button
@click="nextSlide()"
class="absolute right-6 top-1/2 transform -translate-y-1/2 text-white/70 hover:text-white transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-white/50 rounded-full p-2"
aria-label="Nächstes Bild"
>
<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="M9 5l7 7-7 7"></path>
</svg>
</button>
@endif
</section>
</div>
<script>
function heroSlider() {
return {
currentSlide: 0,
totalSlides: {{ !empty($content['slides']) ? count($content['slides']) : 0 }},
autoplayInterval: null,
autoplayTimeout: null,
init() {
if (this.totalSlides > 1) {
this.startAutoplay();
}
},
// Automatischer Wechsel (nur für Intervall)
autoNextSlide() {
this.currentSlide = (this.currentSlide + 1) % this.totalSlides;
},
// Manuelle Navigation
nextSlide() {
this.currentSlide = (this.currentSlide + 1) % this.totalSlides;
this.resetAutoplay();
},
previousSlide() {
this.currentSlide = (this.currentSlide - 1 + this.totalSlides) % this.totalSlides;
this.resetAutoplay();
},
setSlide(index) {
this.currentSlide = index;
this.resetAutoplay();
},
startAutoplay() {
// Zuerst alle bestehenden Timer löschen
this.stopAutoplay();
this.autoplayInterval = setInterval(() => {
this.autoNextSlide();
}, 5000); // Wechsel alle 5 Sekunden
},
stopAutoplay() {
if (this.autoplayInterval) {
clearInterval(this.autoplayInterval);
this.autoplayInterval = null;
}
if (this.autoplayTimeout) {
clearTimeout(this.autoplayTimeout);
this.autoplayTimeout = null;
}
},
resetAutoplay() {
// Alle Timer stoppen
this.stopAutoplay();
// Nach 5 Sekunden Pause wieder starten
this.autoplayTimeout = setTimeout(() => {
this.startAutoplay();
}, 1000);
}
}
}
</script>

View file

@ -0,0 +1,84 @@
<section class="section-padding flex items-center relative">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 card-elevated 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="{{ asset('img/assets/' . $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="{{ asset('img/assets/' . $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="{{ asset('img/assets/' . $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="{{ asset('img/assets/' . $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="{{ asset('img/assets/' . $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,53 @@
<section class="section-padding flex items-center relative">
<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 --}}
<div class="relative">
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
<img src="{{ asset('img/assets/' . $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-sm text-muted-foreground">{{ $content['card_title'] }}</div>
<div class="text-2xl font-medium">{!! $content['card_text'] !!}
</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="{{ asset('img/assets/' . $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,113 @@
<div>
<!-- Back Navigation -->
<div class="pt-20 pb-4">
<div class="container-narrow">
<a href="/magazin" 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">
<div class="container-narrow">
<header class="text-center mb-12">
<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">
<img
src="{{ asset('img/assets/' . $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-3">
<div class="prose prose-lg max-w-none">
<p class="text-large text-muted-foreground leading-relaxed mb-8">
{{ $article['content']['intro'] }}
</p>
@foreach($article['content']['sections'] as $index => $section)
<section class="mb-10" 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-6">
<h3 class="font-medium text-foreground mb-4">{{ $content['share_article'] }}</h3>
<div class="space-y-3">
<button class="btn-secondary-accent w-full">
<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">LinkedIn</span>
</button>
<button class="btn-secondary-accent w-full">
<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>
</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="/magazin" class="btn-primary-accent">
{{ $content['cta_button'] }}
</a>
</div>
</div>
</section>
</div>

View file

@ -0,0 +1,74 @@
<section class="section-padding">
<div class="container-padding">
<div class="text-center mb-16">
<h2 class="text-hero mb-6">
{!! $content['title'] !!}
</h2>
<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 hover:scale-[1.02] transition-all duration-300">
<div class="flex flex-col md:flex-row">
<div class="relative md:w-3/4 aspect-[2/1] md:aspect-[2/1]">
<img
src="{{ asset('img/assets/' . $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="/magazin/{{ $post['id'] }}" 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="/magazin/{{ $post['id'] }}" 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">
<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="/magazin/{{ $post['id'] }}">
<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">
<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,33 @@
<section class="section-padding">
<div class="container-padding text-center">
<h2 class="text-section-title text-foreground mb-12">
{!! $content['title'] !!}
</h2>
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
@foreach($content['timeline'] as $index => $item)
<div class="group {{ $index === 4 ? 'md:col-span-2 lg:col-span-1 lg:col-start-2' : '' }}">
<div class="card-elevated p-8 rounded-3xl h-full hover:scale-105 transition-all duration-300 relative overflow-hidden">
<div class="text-center space-y-6">
<div class="w-12 h-12 mx-auto bg-secondary/20 rounded-full flex items-center justify-center">
<div class="w-6 h-6 bg-secondary rounded-full"></div>
</div>
<h3 class="text-xl font-semibold text-foreground">{{ $item['title'] }}</h3>
<p class="text-muted-foreground text-sm leading-relaxed">
{{ $item['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>
<p class="text-large text-muted-foreground leading-relaxed max-w-3xl mx-auto mt-12">
{{ $content['summary'] }}
</p>
</div>
</section>

View file

@ -0,0 +1,59 @@
{{-- Hero Icons Helper Function --}}
@php
function renderHeroIcon($iconName, $style = 'outline') {
$iconPath = public_path("heroicons/optimized/24/{$style}/{$iconName}.svg");
$fallbackPath = public_path("heroicons/optimized/24/outline/sparkles.svg");
if (file_exists($iconPath)) {
$svg = file_get_contents($iconPath);
// Add classes for styling
return str_replace('<svg', '<svg class="w-10 h-10 text-secondary"', $svg);
} elseif (file_exists($fallbackPath)) {
$svg = file_get_contents($fallbackPath);
return str_replace('<svg', '<svg class="w-10 h-10 text-secondary"', $svg);
}
// Ultimate fallback - simple star icon
return '<svg class="w-10 h-10 text-secondary" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.563.563 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z"/>
</svg>';
}
@endphp
<section class="section-padding">
<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-2 lg:grid-cols-3 gap-8">
@foreach($content['values'] as $index => $value)
<div class="group {{ $index === 4 ? 'md:col-span-2 lg:col-span-1 lg:col-start-2' : '' }}">
<div class="card-elevated p-8 rounded-3xl h-full hover:scale-105 transition-all duration-300 relative overflow-hidden">
<div class="text-center space-y-6">
<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">
{!! renderHeroIcon($value['icon'], $value['icon_style'] ?? 'outline') !!}
</div>
<h3 class="text-2xl font-semibold text-foreground">
{{ $value['title'] }}
</h3>
<div class="w-12 h-px bg-secondary mx-auto"></div>
<p class="text-muted-foreground leading-relaxed">
{{ $value['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,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="{{ asset('img/assets/' . $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,33 @@
<section class="{{ $bg }} text-secondary-foreground section-padding">
<div class="container-narrow text-center">
<div class="spacing-section">
<h2 class="text-section-title text-white">
{!! $content['title'] !!}
</h2>
<p class="text-large text-secondary-foreground max-w-2xl mx-auto leading-relaxed">
{{ $content['subtitle'] }}
</p>
<div class="grid md:grid-cols-3 gap-8 py-8">
@foreach($content['stats'] as $stat)
<div class="text-center space-y-3">
<div class="text-4xl font-light text-secondary-foreground">{{ $stat['number'] }}</div>
<p class="text-secondary-foreground text-sm">{{ $stat['label'] }}</p>
</div>
@endforeach
</div>
<div class="spacing-content">
<a href="{{ $content['button_link'] }}" class="btn-primary-accent">
{{ $content['button_text'] }}
</a>
<p class="text-secondary-foreground text-sm">
{{ $content['small_text'] }}
</p>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,81 @@
<section class="section-padding flex items-center relative overflow-hidden">
<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-lg text-muted-foreground max-w-md leading-relaxed">
{{ $content['subtitle'] }}
</p>
<div class="grid grid-cols-2 gap-6">
@foreach ($content['partner_types'] as $partner)
<div class="flex items-center gap-3">
<div class="w-12 h-12 rounded-full bg-secondary/10 flex items-center justify-center">
@if ($partner['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($partner['icon'] === 'globe')
<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.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" />
</svg>
@elseif($partner['icon'] === 'handshake')
<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="M7 12l3-3 3 3 4-4M8 21l4-4 4 4M3 4h18M4 4h16v12a1 1 0 01-1 1H5a1 1 0 01-1-1V4z" />
</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>
<p class="font-semibold text-foreground">{{ $partner['title'] }}</p>
<p class="text-sm text-muted-foreground">{{ $partner['description'] }}</p>
</div>
</div>
@endforeach
</div>
</div>
<div class="relative">
<div class="relative rounded-3xl overflow-hidden shadow-elevated">
<img src="{{ asset('img/assets/' . $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,91 @@
<section class="section-padding bg-accent">
<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 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">
<div class="relative overflow-hidden">
<img src="{{ asset('img/assets/' . $step['image']) }}" alt="{{ $step['title'] }}"
class="w-full h-64 object-cover group-hover:scale-105 transition-transform duration-300" />
<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>
{{-- Step Number Badge --}}
<div
class="absolute top-4 left-4 w-12 h-12 rounded-full bg-secondary text-white flex items-center justify-center font-bold text-lg">
{{ $step['step'] }}
</div>
</div>
<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">
@if ($step['icon'] === 'file-text')
<svg class="w-5 h-5 text-secondary" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z">
</path>
</svg>
@elseif($step['icon'] === 'search')
<svg class="w-5 h-5 text-secondary" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
</svg>
@else
<svg class="w-5 h-5 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"></path>
</svg>
@endif
</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="/contact">
<button class="btn-secondary-accent w-full">
Jetzt starten
</button>
</a>
@endif
</div>
</div>
@endforeach
</div>
{{-- CTA Section --}}
<div class="text-center">
<div class="card-elevated p-12 rounded-3xl bg-gradient-to-br from-secondary/10 to-secondary/5">
<h3 class="text-3xl font-light text-foreground mb-6">
{!! $content['cta']['title'] !!}
</h3>
<p class="text-large text-muted-foreground mb-8 max-w-2xl mx-auto">
{{ $content['cta']['subtitle'] }}
</p>
<a href="{{ $content['cta']['button_link'] }}">
<button class="btn-primary-accent">
{{ $content['cta']['button_text'] }}
</button>
</a>
</div>
</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="{{ asset('img/assets/' . $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"> Ansehen</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">Keine Projekte gefunden</h3>
<p class="text-muted-foreground">Versuchen Sie einen anderen 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="{{ asset('img/assets/' . $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">Ausstattung</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">Projektdetails</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">Standort</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">Preis</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">Größe</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">
Kontakt aufnehmen
</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,30 @@
<section class="section-padding {{ $bg }}">
<div class="container-padding">
<div class="grid lg:grid-cols-2 gap-12 lg:gap-16 items-center">
{{-- Content --}}
<div class="spacing-section">
<div class="spacing-content">
<h2 class="text-section-title">{{ $content['title'] }}</h2>
<div class="spacing-small text-large text-muted-foreground leading-relaxed">
@foreach($content['paragraphs'] as $paragraph)
<p>{{ $paragraph }}</p>
@endforeach
</div>
</div>
</div>
{{-- Image --}}
<div class="relative">
<div class="card-elevated rounded-3xl overflow-hidden">
<img
src="{{ asset('img/assets/' . $content['image']) }}"
alt="{{ $content['image_alt'] }}"
class="w-full h-[500px] object-cover"
/>
<div class="absolute bottom-6 left-6 bg-card/95 backdrop-blur-sm rounded-xl p-4 shadow-lg border border-border/50">{{ $content['image_caption'] }}</div>
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,39 @@
<section class="min-h-screen 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-16 items-center">
<div class="space-y-8">
<h1 class="text-5xl lg:text-6xl font-light text-foreground">
Über <span class="text-secondary">B2In</span>
</h1>
<blockquote class="text-xl lg:text-2xl text-muted-foreground italic leading-relaxed border-l-4 border-secondary pl-6">
"Unsere Vision ist es, Unternehmen durch innovative Konnektivitätslösungen zu verbinden
und nachhaltiges Wachstum in der digitalen Welt zu ermöglichen. Bei B2In schaffen wir
nicht nur Verbindungen wir bauen Brücken in die Zukunft."
</blockquote>
<div class="flex items-center gap-4">
<div class="w-16 h-px bg-secondary"></div>
<div>
<p class="font-semibold text-foreground">Marcel Scheibe</p>
<p class="text-sm text-muted-foreground">Gründer & CEO, B2In</p>
</div>
</div>
</div>
<div class="relative">
<div class="card-elevated rounded-3xl overflow-hidden">
<img
src="{{ asset('img/assets/marcel-scheibe.jpg') }}"
alt="Marcel Scheibe, Gründer und CEO von B2In"
class="w-full h-96 lg:h-[500px] object-cover"
/>
</div>
<div class="absolute -bottom-6 -right-6 bg-secondary text-secondary-foreground p-6 rounded-2xl">
<div class="text-3xl font-bold">2019</div>
<p class="text-sm opacity-90">Gründungsjahr</p>
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,103 @@
<section class="py-20 px-4 bg-background">
<div class="max-w-7xl mx-auto">
<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-primary to-primary/60 flex items-center justify-center mb-6">
<svg class="w-10 h-10 text-white" 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">
Lifetime-Vergütung
</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-primary">3.5%</span>
</div>
<div class="w-full bg-accent/50 rounded-full h-2">
<div class="bg-primary 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-primary">1.5%</span>
</div>
<div class="w-full bg-accent/50 rounded-full h-2">
<div class="bg-primary h-2 rounded-full w-[15%]"></div>
</div>
</div>
<div class="text-center pt-4">
<p class="text-sm text-muted-foreground">
Kontinuierliche Erträge über die gesamte Kundenbeziehung
</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-primary/10 text-primary 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-4xl lg:text-5xl font-light text-foreground mb-6">
Lifetime <span class="text-primary">Vergütung</span> für Makler
</h2>
<p class="text-xl text-muted-foreground leading-relaxed">
Profitieren Sie von einem revolutionären Vergütungsmodell, das über
den einmaligen Verkauf hinausgeht. Bauen Sie langfristige Kundenbeziehungen
auf und generieren Sie kontinuierliche Erträge.
</p>
</div>
<div class="space-y-6">
@foreach($this->benefits as $benefit)
<div class="flex gap-4">
<div class="flex-shrink-0 w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center">
@if($benefit['icon'] === 'trending-up')
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"/>
</svg>
@elseif($benefit['icon'] === 'clock')
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
@elseif($benefit['icon'] === 'target')
<svg class="w-6 h-6 text-primary" 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-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"/>
</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,20 @@
<section class="py-16 px-4 text-center">
<div class="max-w-4xl mx-auto">
<div class="mb-8">
<div
class="inline-flex items-center gap-2 bg-primary text-primary-foreground px-4 py-2 rounded-full text-sm font-medium mb-6">
4.9 Rating
</div>
</div>
<h2 class="text-section-title text-foreground mb-6">
Committed to excellence, ensuring <br />
<span class="text-secondary">enduring comfort</span> and creating lasting <br />
memories
</h2>
<p class="text-muted-foreground text-lg">
Robert Wilson
</p>
</div>
</section>

View file

@ -0,0 +1,72 @@
<section class="section-dark py-20 px-4">
<div class="max-w-7xl mx-auto">
<div class="grid lg:grid-cols-2 gap-16 items-center">
<div class="space-y-12">
<div class="grid grid-cols-2 gap-8">
<div>
<div class="text-6xl font-light text-dark-text mb-2">17+</div>
<p class="text-dark-muted text-sm">Years of Experience</p>
</div>
<div>
<div class="text-6xl font-light text-dark-text mb-2">2M</div>
<p class="text-dark-muted text-sm">Happy Guests</p>
</div>
</div>
<div class="space-y-6">
<h3 class="text-3xl font-light text-dark-text">
Economically Sound and Well-<br />
<span class="text-secondary">Friendly Service</span> for<br />
Families and Their<br />
Precious Belongings
</h3>
<p class="text-dark-muted leading-relaxed">
We understand that every family is unique, which is why we offer personalized
services tailored to meet your specific needs. From luxury amenities to
budget-friendly options, we ensure every guest feels valued and comfortable.
</p>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 pt-8">
<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-dark-text font-medium text-sm">Top Consultation</p>
<p class="text-dark-muted text-xs">Expert guidance</p>
</div>
</div>
<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-dark-text font-medium text-sm">Finest Meal</p>
<p class="text-dark-muted text-xs">Gourmet dining</p>
</div>
</div>
<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-dark-text font-medium text-sm">Easy Tax Reduction</p>
<p class="text-dark-muted text-xs">Cost-effective</p>
</div>
</div>
</div>
</div>
</div>
<div class="relative">
<div class="card-elevated bg-dark-muted p-0 overflow-hidden rounded-3xl">
<img src="{{ asset('img/assets/accommodation-2.jpg') }}" alt="Luxury interior design"
class="w-full h-96 object-cover" />
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,59 @@
<section class="py-20 px-4 bg-background">
<div class="max-w-7xl mx-auto">
<div class="text-center mb-16">
<h2 class="text-4xl lg:text-5xl font-light text-foreground mb-6">
Digitales <span class="text-primary">Herzstück</span>
</h2>
<p class="text-xl text-muted-foreground max-w-3xl mx-auto">
Modernste Technologie-Infrastruktur, die alle Ecosystem-Teilnehmer
nahtlos miteinander verbindet und außergewöhnliche Nutzererfahrungen ermöglicht.
</p>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
@foreach($this->features as $index => $feature)
<div class="group {{ $index === 4 ? 'md:col-span-2 lg:col-span-1 lg:col-start-2' : '' }}">
<div class="card-elevated p-8 rounded-3xl h-full hover:scale-105 transition-all duration-300 relative overflow-hidden">
<div class="text-center space-y-6">
<div class="w-16 h-16 mx-auto rounded-xl bg-primary/10 flex items-center justify-center mb-6">
@if($feature['icon'] === 'cloud')
<svg class="w-8 h-8 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"/>
</svg>
@elseif($feature['icon'] === 'shield')
<svg class="w-8 h-8 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
</svg>
@elseif($feature['icon'] === 'layers')
<svg class="w-8 h-8 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"/>
</svg>
@elseif($feature['icon'] === 'database')
<svg class="w-8 h-8 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4"/>
</svg>
@else
<svg class="w-8 h-8 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z"/>
</svg>
@endif
</div>
<h3 class="text-xl font-semibold text-foreground">
{{ $feature['title'] }}
</h3>
<div class="w-12 h-px bg-primary 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-primary/20 via-primary to-primary/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,126 @@
<section class="min-h-screen 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-16 items-center">
<div class="space-y-8">
<h1 class="text-5xl lg:text-7xl font-light text-foreground">
B2In <span class="text-primary">Ecosystem</span>
</h1>
<p class="text-xl lg:text-2xl text-muted-foreground leading-relaxed">
Ein intelligentes Netzwerk, das Endkunden, Makler, Lieferanten und
Technologie nahtlos miteinander verbindet. Jeder Teilnehmer profitiert
vom gesamten System und schafft gemeinsam außergewöhnliche Immobilienerlebnisse.
</p>
<div class="grid grid-cols-2 gap-6">
@foreach ($this->features as $feature)
<div class="flex items-center gap-3">
<div class="w-12 h-12 rounded-full bg-primary/10 flex items-center justify-center">
@if ($feature['icon'] === 'users')
<svg class="w-6 h-6 text-primary" 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-primary" 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-primary" 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-primary" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13 10V3L4 14h7v7l9-11h-7z" />
</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="card-elevated rounded-3xl p-12 bg-background/80 backdrop-blur-sm">
<div class="space-y-8">
<!-- Central Hub -->
<div class="text-center">
<div
class="w-24 h-24 mx-auto rounded-full bg-primary 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="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>
</div>
<h3 class="text-xl font-semibold text-foreground">B2In Portal</h3>
<p class="text-sm text-muted-foreground">Zentrale Plattform</p>
</div>
<!-- Connection Points -->
<div class="grid grid-cols-2 gap-8">
<div class="text-center">
<div
class="w-16 h-16 mx-auto rounded-full bg-accent flex items-center justify-center mb-3">
<svg class="w-8 h-8 text-accent-foreground" 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>
</div>
<p class="font-medium text-sm">Endkunden</p>
</div>
<div class="text-center">
<div
class="w-16 h-16 mx-auto rounded-full bg-accent flex items-center justify-center mb-3">
<svg class="w-8 h-8 text-accent-foreground" 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>
</div>
<p class="font-medium text-sm">Makler</p>
</div>
<div class="text-center">
<div
class="w-16 h-16 mx-auto rounded-full bg-accent flex items-center justify-center mb-3">
<svg class="w-8 h-8 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" />
</svg>
</div>
<p class="font-medium text-sm">Lieferanten</p>
</div>
<div class="text-center">
<div
class="w-16 h-16 mx-auto rounded-full bg-accent flex items-center justify-center mb-3">
<svg class="w-8 h-8 text-accent-foreground" 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>
</div>
<p class="font-medium text-sm">B2A</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,29 @@
<section class="py-20 px-4 bg-background">
<div class="max-w-7xl mx-auto">
<div class="text-center mb-16">
<h2 class="text-4xl lg:text-5xl font-light text-foreground mb-6">
Unser <span class="text-primary">Ecosystem</span> in Zahlen
</h2>
<p class="text-xl text-muted-foreground max-w-3xl mx-auto">
Zahlen, die die Stärke und das Vertrauen in unser vernetztes
Geschäftsmodell widerspiegeln.
</p>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-4 gap-8">
@foreach ($this->stats as $stat)
<div class="card-elevated rounded-2xl p-8 text-center">
<div class="text-4xl lg:text-5xl font-bold text-primary mb-4">
{{ $stat['number'] }}
</div>
<h3 class="text-lg font-semibold text-foreground mb-3">
{{ $stat['label'] }}
</h3>
<p class="text-sm text-muted-foreground leading-relaxed">
{{ $stat['description'] }}
</p>
</div>
@endforeach
</div>
</div>
</section>

View file

@ -0,0 +1,83 @@
<section class="py-20 px-4 bg-accent/30">
<div class="max-w-7xl mx-auto">
<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-primary/10 text-primary 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>
Für Endkunden
</div>
<h2 class="text-4xl lg:text-5xl font-light text-foreground mb-6">
Exklusive <span class="text-primary">Erlebnisse</span> für Sie
</h2>
<p class="text-xl text-muted-foreground leading-relaxed">
Mit Ihrer persönlichen Login-Karte erhalten Sie Zugang zu einer
einzigartigen Erlebniswelt, die speziell auf Ihre Wohnwünsche
und Lebensstil abgestimmt ist. Entdecken Sie kuratierte Immobilien
und Services, die sonst nicht verfügbar sind.
</p>
</div>
<div class="space-y-6">
@foreach($this->benefits as $benefit)
<div class="flex gap-4">
<div class="flex-shrink-0 w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center">
@if($benefit['icon'] === 'credit-card')
<svg class="w-6 h-6 text-primary" 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-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"/>
</svg>
@elseif($benefit['icon'] === 'home')
<svg class="w-6 h-6 text-primary" 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-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
</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 overflow-hidden">
<div class="bg-gradient-to-br from-primary/20 to-primary/5 p-12 h-96 flex flex-col justify-center items-center text-center">
<div class="w-24 h-24 rounded-full bg-primary/20 backdrop-blur-sm flex items-center justify-center mb-6">
<svg class="w-12 h-12 text-primary" 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>
</div>
<h3 class="text-2xl font-semibold text-foreground mb-4">
Login-Karte
</h3>
<p class="text-muted-foreground mb-6">
Ihr Schlüssel zu exklusiven Immobilienerlebnissen
</p>
<div class="bg-background/80 backdrop-blur-sm rounded-xl p-4 w-full max-w-xs">
<div class="text-sm text-muted-foreground mb-2">Mitgliedsnummer</div>
<div class="font-mono text-lg">B2IN-2024-VIP</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,20 @@
<section class="section-dark py-20 px-4 text-center">
<div class="max-w-4xl mx-auto">
<h2 class="text-5xl md:text-6xl font-light text-dark-text leading-tight mb-8">
Were committed to <br />
your <span class="text-secondary">comfort</span> and <br />
<span class="text-secondary">satisfaction</span> for <br />
unforgettable <br />
experiences
</h2>
<div class="flex justify-center mb-8">
<div class="w-16 h-px bg-secondary"></div>
</div>
<p class="text-dark-muted text-lg">
Robert Wilson <br />
<span class="text-sm">General Manager</span>
</p>
</div>
</section>

View file

@ -0,0 +1,50 @@
<section class="py-20 px-4 bg-background">
<div class="max-w-7xl mx-auto">
<div class="text-center mb-16">
<h2 class="text-4xl lg:text-5xl font-light text-foreground mb-6">
Das <span class="text-secondary">Führungsteam</span>
</h2>
<p class="text-muted-foreground text-lg max-w-2xl mx-auto">
Unser erfahrenes Team bringt jahrzehntelange Expertise in den Bereichen
Technologie, Operations und Geschäftsentwicklung mit.
</p>
</div>
<div class="grid md:grid-cols-3 gap-8">
@foreach($this->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="{{ asset('img/assets/' . $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">B2IN TEAM</span>
</div>
</div>
</div>
</div>
@endforeach
</div>
</div>
</section>

View file

@ -0,0 +1,116 @@
<div>
<!-- Back Navigation -->
<div class="pt-20 pb-4">
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<a href="/magazin" 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>
Zurück zum Magazin
</a>
</div>
</div>
<!-- Article Header -->
<article class="pb-16">
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<header class="text-center mb-12">
<h1 class="text-4xl md:text-5xl font-light text-foreground mb-6 leading-tight">
{{ $article['title'] }}
</h1>
<p class="text-xl 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">
<img
src="{{ asset('images/' . $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-3">
<div class="prose prose-lg max-w-none">
<p class="text-lg text-muted-foreground leading-relaxed mb-8">
{{ $article['content']['intro'] }}
</p>
@foreach($article['content']['sections'] as $index => $section)
<section class="mb-10" 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-6">
<h3 class="font-medium text-foreground mb-4">Artikel teilen</h3>
<div class="space-y-3">
<button class="w-full bg-[#0077B5] hover:bg-[#0095e5] text-white rounded-lg py-3 px-4 flex items-center justify-center gap-3 transition-colors duration-200">
<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">LinkedIn</span>
</button>
<button class="w-full bg-[#3b5998] hover:bg-[#5077cc] text-white rounded-lg py-3 px-4 flex items-center justify-center gap-3 transition-colors duration-200">
<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>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</article>
<!-- Bottom CTA -->
<section class="bg-secondary text-secondary-foreground section-padding">
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<div class="max-w-2xl mx-auto">
<h2 class="text-3xl font-light mb-6 text-[hsl(var(--dark-text))]">
Entdecken Sie mehr über
<span class="text-primary font-medium">Luxus</span> und
<span class="text-primary font-medium">Komfort</span>
für unvergessliche Erlebnisse.
</h2>
<a href="/magazin" class="btn-accent px-8 py-3 rounded-lg">
Weitere Artikel entdecken
</a>
</div>
</div>
</section>
</div>

View file

@ -0,0 +1,75 @@
<section class="py-20 px-4">
<div class="max-w-7xl mx-auto">
<div class="text-center mb-16">
<h2 class="text-4xl lg:text-5xl font-light text-foreground mb-6">
B2In <span class="text-secondary">Magazin</span>
</h2>
<p class="text-muted-foreground text-lg max-w-2xl mx-auto">
Entdecken Sie die neuesten Trends, Insights und Geschichten aus der Welt
der Business-Konnektivität und Innovation.
</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 hover:scale-[1.02] transition-all duration-300">
<div class="flex flex-col md:flex-row">
<div class="relative md:w-3/4 aspect-[2/1] md:aspect-[2/1]">
<img
src="{{ asset('images/' . $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="/magazin/{{ $post['id'] }}" 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="/magazin/{{ $post['id'] }}" class="text-sm">Weiterlesen</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">
<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="/magazin/{{ $post['id'] }}">
<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">
<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 px-8 py-4 rounded-2xl">
Weitere Artikel laden
</a>
</div>
</div>
</section>

View file

@ -0,0 +1,28 @@
<section class="section-dark section-padding">
<div class="container-narrow text-center">
<h2 class="text-section-title text-[hsl(var(--dark-text))] mb-12">
Unsere <span class="text-secondary">Geschichte</span>
</h2>
<div class="grid md:grid-cols-3 gap-8 mb-16">
@foreach($this->timeline as $item)
<div class="spacing-small">
<div class="w-12 h-12 mx-auto bg-secondary/20 rounded-full flex items-center justify-center">
<div class="w-6 h-6 bg-secondary rounded-full"></div>
</div>
<h3 class="text-xl font-semibold text-[hsl(var(--dark-text))]">{{ $item['title'] }}</h3>
<p class="text-dark-muted text-sm leading-relaxed">
{{ $item['description'] }}
</p>
</div>
@endforeach
</div>
<p class="text-large text-dark-muted leading-relaxed max-w-3xl mx-auto">
Was als Vision begann, traditionelle Geschäftsprozesse zu revolutionieren, ist heute eine
bewährte Plattform für digitale Innovation. B2In schließt die Lücke zwischen
traditionellen Unternehmen und modernen, digitalen Lösungen durch maßgeschneiderte
Konnektivitätsservices, die Effizienz steigern und nachhaltiges Wachstum fördern.
</p>
</div>
</section>

View file

@ -0,0 +1,37 @@
<section class="py-20 px-4">
<div class="max-w-7xl mx-auto">
<div class="text-center mb-16">
<h2 class="text-4xl lg:text-5xl font-light text-foreground mb-6">
Unsere <span class="text-secondary">Werte</span>
</h2>
<p class="text-muted-foreground text-lg max-w-2xl mx-auto">
Diese fünf Grundpfeiler leiten unser tägliches Handeln und definieren,
wer wir als Unternehmen sind und wofür wir stehen.
</p>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
@foreach($this->values as $index => $value)
<div class="group {{ $index === 4 ? 'md:col-span-2 lg:col-span-1 lg:col-start-2' : '' }}">
<div class="card-elevated p-8 rounded-3xl h-full hover:scale-105 transition-all duration-300 relative overflow-hidden">
<div class="text-center space-y-6">
<div class="text-5xl mb-4">{{ $value['icon'] }}</div>
<h3 class="text-2xl font-semibold text-foreground">
{{ $value['title'] }}
</h3>
<div class="w-12 h-px bg-secondary mx-auto"></div>
<p class="text-muted-foreground leading-relaxed">
{{ $value['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,156 @@
<section class="py-16 px-4">
<div class="max-w-7xl mx-auto">
<div class="text-center mb-16">
<h2 class="text-section-title text-foreground mb-6">
Warum Partner werden?
</h2>
<p class="text-muted-foreground text-lg max-w-3xl mx-auto">
Entdecken Sie die Vorteile einer Partnerschaft mit B2In und
wie Sie von unserem innovativen Ecosystem profitieren können.
</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-primary/10 text-primary 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>
Für Makler
</div>
<h3 class="text-3xl font-light text-foreground mb-6">
Revolutionäres <span class="text-primary">Provisionsmodell</span>
</h3>
</div>
<div class="space-y-6">
@foreach ($this->brokerBenefits 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-primary/10 flex items-center justify-center">
@if ($benefit['icon'] === 'trending-up')
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"></path>
</svg>
@elseif($benefit['icon'] === 'target')
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
@else
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z">
</path>
</svg>
@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-primary/5 rounded-xl p-6">
<div class="text-center">
<div class="text-3xl font-bold text-primary mb-2">3.5% - </div>
<p class="text-sm text-muted-foreground">
Erstprovision bis Lifetime-Vergütung
</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-accent/50 text-accent-foreground 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>
Für Lieferanten
</div>
<h3 class="text-3xl font-light text-foreground mb-6">
Globale <span class="text-primary">Marktchancen</span>
</h3>
</div>
<div class="space-y-6">
@foreach ($this->supplierBenefits 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="{{ asset('img/assets/accommodation-1.jpg') }}" alt="Partner success visualization"
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">500+</div>
<p class="text-sm opacity-90">Erfolgreiche Partner</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,36 @@
<section class="section-dark section-padding">
<div class="container-narrow text-center">
<div class="spacing-section">
<h2 class="text-5xl lg:text-6xl font-light text-[hsl(var(--dark-text))] leading-tight">
Wachsen Sie <br />
<span class="text-secondary">mit uns</span>
</h2>
<div class="w-16 h-px bg-secondary mx-auto"></div>
<p class="text-large text-dark-muted leading-relaxed max-w-2xl mx-auto">
Werden Sie Teil des B2In-Partnernetzwerks und erschließen Sie neue
Geschäftsmöglichkeiten durch innovative Konnektivitätslösungen.
</p>
<div class="grid md:grid-cols-3 gap-8 py-8">
@foreach($this->stats as $stat)
<div class="text-center space-y-3">
<div class="text-4xl font-light text-secondary">{{ $stat['number'] }}</div>
<p class="text-dark-muted text-sm">{{ $stat['label'] }}</p>
</div>
@endforeach
</div>
<div class="spacing-content">
<a href="/contact" class="btn-accent px-12 py-6 rounded-2xl text-lg">
Werden Sie B2In Partner
</a>
<p class="text-dark-muted text-sm">
Entdecken Sie die Vorteile einer strategischen Partnerschaft mit B2In
</p>
</div>
</div>
</div>
</section>

View file

@ -0,0 +1,131 @@
<section class="min-h-screen flex items-center relative overflow-hidden">
<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">
Wachsen Sie mit uns.<br />
Werden Sie <span class="text-secondary">B2In Partner</span>.
</h1>
<p class="text-lg text-muted-foreground max-w-md leading-relaxed">
Werden Sie Teil des B2In Ecosystems und profitieren Sie von innovativen
Geschäftsmodellen, die nachhaltiges Wachstum und langfristigen Erfolg ermöglichen.
Gemeinsam gestalten wir die Zukunft der Immobilienbranche.
</p>
<div class="grid grid-cols-2 gap-6">
@foreach ($this->partnerTypes as $partner)
<div class="flex items-center gap-3">
<div class="w-12 h-12 rounded-full bg-primary/10 flex items-center justify-center">
@if ($partner['icon'] === 'trending-up')
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
</svg>
@elseif($partner['icon'] === 'globe')
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
@elseif($partner['icon'] === 'handshake')
<svg class="w-6 h-6 text-primary" 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>
@else
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z" />
</svg>
@endif
</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>
</div>
<div class="relative">
<div class="card-elevated rounded-3xl p-12 bg-background/80 backdrop-blur-sm">
<div class="space-y-8">
<!-- Central Partnership Hub -->
<div class="text-center">
<div
class="w-24 h-24 mx-auto rounded-full bg-primary 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">Partner Network</h3>
<p class="text-sm text-muted-foreground">Werden Sie Teil unseres Ecosystems</p>
</div>
<!-- Partner Types -->
<div class="grid grid-cols-2 gap-8">
<div class="text-center">
<div
class="w-16 h-16 mx-auto rounded-full bg-accent flex items-center justify-center mb-3">
<svg class="w-8 h-8 text-accent-foreground" 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>
<p class="font-medium text-sm">Makler</p>
<p class="text-xs text-muted-foreground">Lifetime-Modell</p>
</div>
<div class="text-center">
<div
class="w-16 h-16 mx-auto rounded-full bg-accent flex items-center justify-center mb-3">
<svg class="w-8 h-8 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" />
</svg>
</div>
<p class="font-medium text-sm">Lieferanten</p>
<p class="text-xs text-muted-foreground">Global Markets</p>
</div>
<div class="text-center">
<div
class="w-16 h-16 mx-auto rounded-full bg-accent flex items-center justify-center mb-3">
<svg class="w-8 h-8 text-accent-foreground" 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>
</div>
<p class="font-medium text-sm">Erfolg</p>
<p class="text-xs text-muted-foreground">Messbare Ziele</p>
</div>
<div class="text-center">
<div
class="w-16 h-16 mx-auto rounded-full bg-accent flex items-center justify-center mb-3">
<svg class="w-8 h-8 text-accent-foreground" 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>
</div>
<p class="font-medium text-sm">Qualität</p>
<p class="text-xs text-muted-foreground">Premium Standards</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>

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