From bfab08029b2042ae8dd9f21ea1359a035664c05c Mon Sep 17 00:00:00 2001 From: Clemens Creutzburg Date: Sat, 4 Apr 2026 15:09:56 +0200 Subject: [PATCH] Startseite angepasst --- .../Central/Controllers/LandingController.php | 35 +- saas-app/public/index.php | 397 ++++++++---- saas-app/resources/views/auth/login.blade.php | 260 ++------ .../resources/views/dashboard/index.blade.php | 74 ++- .../resources/views/layouts/app.blade.php | 601 +++++++++++++----- .../resources/views/support/index.blade.php | 201 +++--- .../resources/views/tenants/roles.blade.php | 199 +++--- saas-app/resources/views/welcome.blade.php | 440 ++++++++----- 8 files changed, 1306 insertions(+), 901 deletions(-) diff --git a/saas-app/app/Modules/Central/Controllers/LandingController.php b/saas-app/app/Modules/Central/Controllers/LandingController.php index 695122a..2b9b0af 100644 --- a/saas-app/app/Modules/Central/Controllers/LandingController.php +++ b/saas-app/app/Modules/Central/Controllers/LandingController.php @@ -4,25 +4,36 @@ declare(strict_types=1); namespace App\Modules\Central\Controllers; -use App\Modules\Identity\Services\AuthService; -use App\Modules\Tenants\Services\TenantService; - class LandingController { - public function __construct( - private readonly TenantService $tenantService, - private readonly AuthService $authService - ) { - } - public function index(): array { return [ 'view' => 'welcome', 'data' => [ - 'title' => 'Kaffeeliste SaaS', - 'tenantOverview' => $this->tenantService->adminOverview(), - 'centralLoginPreview' => $this->authService->centralLoginPreview(), + 'title' => 'Die Kaffeeliste', + 'landingColumns' => [ + [ + 'eyebrow' => 'Für Mitglieder', + 'title' => 'Schnell im Alltag', + 'copy' => 'Anmelden, Überblick sehen und direkt weitermachen.', + ], + [ + 'eyebrow' => 'Für Verantwortliche', + 'title' => 'Einfach verwalten', + 'copy' => 'Mitglieder, Bereiche und Abläufe an einem Ort.', + ], + [ + 'eyebrow' => 'Für Teams', + 'title' => 'Klar für alle', + 'copy' => 'Eine gemeinsame Kaffeeliste mit verständlicher Oberfläche.', + ], + ], + 'landingPreview' => [ + ['label' => 'Schneller Überblick', 'value' => 'Direkt sichtbar'], + ['label' => 'Für Mitglieder', 'value' => 'Einfach nutzbar'], + ['label' => 'Für Verantwortliche', 'value' => 'Klar verwaltet'], + ], ], ]; } diff --git a/saas-app/public/index.php b/saas-app/public/index.php index 4198ad4..1d3d227 100644 --- a/saas-app/public/index.php +++ b/saas-app/public/index.php @@ -71,7 +71,6 @@ if ($page === 'logout' && $requestMethod === 'POST') { app_redirect('/'); } -$marketing = app_marketing_messages(); $flash = app_flash(); $auth = app_auth_user(); $pdo = null; @@ -223,7 +222,31 @@ if ($auth !== null && isset($restrictedPages[$page]) && !$restrictedPages[$page] $canManageTenant = app_can_manage_tenant($auth); $tenantNavItems = app_tenant_navigation_items($auth, $tenantLicense); +$guestNavItems = [ + ['key' => 'home', 'href' => '/', 'label' => 'Start'], + ['key' => 'login', 'href' => '/login/', 'label' => 'Anmeldung'], + ['key' => 'tenants', 'href' => '/admin/login/', 'label' => 'Admin'], +]; +$primaryNavItems = $auth === null ? $guestNavItems : $tenantNavItems; +$currentNavLabel = 'Start'; +foreach ($primaryNavItems as $item) { + if ($page === (string) ($item['key'] ?? '')) { + $currentNavLabel = (string) ($item['label'] ?? $currentNavLabel); + break; + } +} $themeCss = app_tenant_theme_root_css($tenantSettings); +$isMarketingHome = $page === 'home' && $auth === null; +$landingColumns = [ + ['eyebrow' => 'Für Mitglieder', 'title' => 'Schnell starten', 'copy' => 'Einloggen und direkt weiter.'], + ['eyebrow' => 'Für Verantwortliche', 'title' => 'Alles im Blick', 'copy' => 'Bereiche, Hinweise und Verwaltung an einem Ort.'], + ['eyebrow' => 'Für Standorte', 'title' => 'Gemeinsam organisiert', 'copy' => 'Ein klarer Ablauf für Teams und Bereiche.'], +]; +$landingPreview = [ + ['label' => 'Start', 'value' => 'Klar'], + ['label' => 'Team', 'value' => 'Gemeinsam'], + ['label' => 'Zugang', 'value' => 'Direkt'], +]; ?> @@ -237,104 +260,248 @@ $themeCss = app_tenant_theme_root_css($tenantSettings); body{margin:0;min-height:100vh;font-family:"Aptos","Segoe UI",sans-serif;color:var(--ink);background:linear-gradient(180deg,#f9f6ef 0%,var(--bg) 100%)} a{color:inherit;text-decoration:none} h1,h2,h3{font-family:Georgia,serif;letter-spacing:-.02em} - .button,button{display:inline-flex;align-items:center;justify-content:center;padding:10px 14px;border-radius:999px;border:1px solid transparent;background:var(--brand);color:#fff;font:inherit;font-weight:700;cursor:pointer} + .button,button{display:inline-flex;align-items:center;justify-content:center;padding:10px 14px;border-radius:12px;border:1px solid transparent;background:var(--brand);color:#fff;font:inherit;font-weight:700;cursor:pointer} .button.secondary,.button--ghost{background:#fff;color:var(--brand);border-color:rgba(var(--brand-rgb),.18)} - .page-shell{width:min(1460px,calc(100vw - 32px));margin:20px auto 40px;display:grid;grid-template-columns:minmax(280px,300px) minmax(0,1fr);gap:20px;align-items:start} - .sidebar,.hero,.card,.alert{border:1px solid var(--line);border-radius:var(--radius);background:var(--card);box-shadow:var(--shadow)} - .sidebar{position:sticky;top:20px;display:grid;gap:16px;padding:18px;background:rgba(255,251,244,.96)} - .sidebar__brand{display:grid;gap:6px;padding-bottom:14px;border-bottom:1px solid rgba(37,24,15,.1)} + .page-shell{width:min(1320px,calc(100vw - 32px));margin:18px auto 34px;display:grid;gap:16px} + .site-header{position:sticky;top:18px;z-index:20} + .site-header__inner{display:flex;align-items:center;justify-content:space-between;gap:18px;padding:16px 18px;border:1px solid var(--line);border-radius:24px;background:rgba(255,255,255,.94);box-shadow:var(--shadow)} + .site-brand{display:flex;align-items:center;gap:14px;min-width:0} + .site-brand__mark{width:44px;height:44px;border-radius:16px;display:grid;place-items:center;background:linear-gradient(135deg,var(--brand) 0%,var(--brand-strong) 100%);color:#fff;font-weight:800;box-shadow:0 14px 28px rgba(var(--brand-rgb),.18)} + .site-brand__title{margin:0;font-size:1.1rem;color:var(--ink)} + .site-brand__subtitle{margin:2px 0 0;color:var(--muted);font-size:.92rem} + .site-nav,.site-actions,.actions,.context{display:flex;flex-wrap:wrap;gap:10px;align-items:center} + .site-nav__link{display:inline-flex;align-items:center;justify-content:center;padding:10px 14px;border-radius:999px;border:1px solid transparent;background:transparent;color:var(--muted);font-weight:700} + .site-nav__link:hover{text-decoration:none;color:var(--brand);background:rgba(255,255,255,.82);border-color:rgba(var(--brand-rgb),.14)} + .site-nav__link.active{background:rgba(var(--brand-rgb),.10);color:var(--brand);border-color:rgba(var(--brand-rgb),.18)} + .site-mobile{display:none;position:relative} + .site-mobile[open]{z-index:20} + .site-toggle{display:flex;align-items:center;justify-content:space-between;gap:12px;cursor:pointer;list-style:none;padding:12px 14px;border-radius:16px;border:1px solid rgba(var(--brand-rgb),.12);background:#fff;color:var(--brand);font-weight:700} + .site-toggle::-webkit-details-marker{display:none} + .site-toggle::after{content:"";width:11px;height:11px;border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(45deg);transition:transform .2s ease} + .site-mobile[open] .site-toggle::after{transform:rotate(225deg)} + .site-panel{position:absolute;right:0;top:calc(100% + 12px);width:min(320px,calc(100vw - 32px));padding:14px;border-radius:18px;border:1px solid var(--line);background:#fffdf9;box-shadow:var(--shadow)} + .site-stack{display:grid;gap:10px} + .site-stack .site-nav__link{justify-content:flex-start;background:rgba(255,255,255,.78);border-color:rgba(37,24,15,.08);color:var(--ink)} + .site-footer-actions{display:flex;justify-content:flex-end;margin-top:12px} + .hero,.card,.alert{border:1px solid var(--line);border-radius:var(--radius);background:var(--card);box-shadow:var(--shadow)} .sidebar__eyebrow,.eyebrow{display:inline-block;color:var(--accent);text-transform:uppercase;letter-spacing:.14em;font-size:.8rem;font-weight:800} .sidebar__eyebrow{margin:0} - .sidebar__title{margin:0;font-size:1.55rem;line-height:1.05} + .sidebar__title{margin:0;font-size:1.32rem;line-height:1.04} .sidebar__subtitle,.muted,p{color:var(--muted)} - .sidebar__meta,.actions,.context{display:flex;flex-wrap:wrap;gap:10px;align-items:center} - .sidebar__section{display:inline-block;color:var(--accent);text-transform:uppercase;letter-spacing:.14em;font-size:.76rem;font-weight:800} - .sidebar__nav,.sidebar__stack,.stack{display:grid;gap:10px} - .sidebar__link{display:flex;align-items:center;justify-content:space-between;padding:12px 14px;border-radius:16px;border:1px solid rgba(var(--brand-rgb),.12);background:#fff;color:var(--brand);font-weight:700} - .sidebar__link.active{background:var(--brand);color:#fff} - .sidebar__footer{display:grid;gap:12px;padding-top:14px;border-top:1px solid rgba(37,24,15,.1)} - .sidebar__mobile{display:none} - .sidebar__mobile[open]{z-index:20} - .sidebar__toggle{display:flex;align-items:center;justify-content:space-between;gap:12px;cursor:pointer;list-style:none;padding:12px 14px;border-radius:16px;border:1px solid rgba(var(--brand-rgb),.12);background:#fff;color:var(--brand);font-weight:700} - .sidebar__toggle::-webkit-details-marker{display:none} - .sidebar__toggle::after{content:"";width:11px;height:11px;border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(45deg);transition:transform .2s ease} - .sidebar__mobile[open] .sidebar__toggle::after{transform:rotate(225deg)} - .sidebar__panel{margin-top:12px;padding:14px;border-radius:18px;border:1px solid var(--line);background:#fffdf9;box-shadow:var(--shadow)} - .content{min-width:0;display:grid;gap:18px} - .hero,.card{padding:24px} - .hero{margin-bottom:0;background:linear-gradient(180deg,#fffdf8 0%,#f9f4ea 100%)} + .content{min-width:0;display:grid;gap:16px} + .hero,.card{padding:20px} + .hero{margin-bottom:0;background:rgba(255,255,255,.9)} .grid{display:grid;gap:18px}.grid-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-4{grid-template-columns:repeat(4,minmax(0,1fr))} - h1{font-size:clamp(2rem,4vw,3.2rem);margin:0 0 12px}h2{font-size:1.35rem;margin:0 0 12px}h3{font-size:1.05rem;margin:0 0 10px}p{margin:0;line-height:1.6} - .metric{padding:18px;border:1px solid var(--line);border-radius:16px;background:#fff}.metric strong{display:block;font-size:1.8rem;margin-bottom:8px} + h1{font-size:clamp(1.9rem,4vw,2.8rem);margin:0 0 10px}h2{font-size:1.2rem;margin:0 0 10px}h3{font-size:1rem;margin:0 0 8px}p{margin:0;line-height:1.55} + .metric{padding:18px;border:1px solid var(--line);border-radius:16px;background:#fff}.metric strong{display:block;font-size:1.55rem;margin-bottom:6px} .list{margin:14px 0 0;padding-left:18px;color:var(--muted);line-height:1.7} .alert{padding:16px 18px;margin-bottom:0}.alert-success{background:rgba(var(--brand-rgb),.08)}.alert-warning{background:rgba(var(--accent-rgb),.1)}.alert-error{background:rgba(154,31,31,.1)}.alert-info{background:rgba(var(--brand-rgb),.08)} .badge{display:inline-flex;align-items:center;padding:7px 12px;border-radius:999px;font-size:.86rem;font-weight:700} .badge-neutral{background:rgba(var(--brand-rgb),.08);color:var(--brand)}.badge-success{background:rgba(var(--brand-rgb),.12);color:var(--brand)}.badge-warning{background:rgba(var(--accent-rgb),.14);color:#8c6500} - .table{overflow-x:auto}.table table{width:100%;border-collapse:collapse;min-width:720px}.table th,.table td{padding:13px 10px;border-bottom:1px solid var(--line);text-align:left;vertical-align:top}.table th{font-size:.85rem;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)} + .table{overflow-x:auto}.table table{width:100%;border-collapse:collapse;min-width:720px}.table th,.table td{padding:12px 10px;border-bottom:1px solid var(--line);text-align:left;vertical-align:top}.table th{font-size:.78rem;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)} form.grid{grid-template-columns:repeat(2,minmax(0,1fr))}label{display:flex;flex-direction:column;gap:8px;font-weight:700}input,select,textarea{width:100%;padding:12px 14px;border-radius:14px;border:1px solid rgba(37,24,15,.15);font:inherit;background:#fff;color:var(--ink)}textarea{min-height:120px} .footer{margin-top:0;text-align:center;color:var(--muted);font-size:.92rem} - @media(max-width:960px){.page-shell{grid-template-columns:1fr;width:min(100vw - 20px,1460px)}.sidebar{position:static}.sidebar__desktop{display:none}.sidebar__mobile{display:block}.grid-2,.grid-3,.grid-4,form.grid{grid-template-columns:1fr}.table table{min-width:0}} - @media(min-width:961px){.sidebar__mobile{display:none}} + .section-mini{display:grid;gap:10px} + .section-mini__title{margin:0;font-size:1rem;color:var(--ink)} + .section-mini__copy{margin:0;color:var(--muted)} + body.landing-preview{background:radial-gradient(circle at top center,rgba(88,122,255,.22),transparent 28%),radial-gradient(circle at 20% 20%,rgba(42,72,170,.18),transparent 24%),linear-gradient(180deg,#05070d 0%,#0a0f1a 52%,#0d1320 100%);color:#f4f7ff} + body.landing-preview h1,body.landing-preview h2,body.landing-preview h3{font-family:"Inter Tight","Aptos","Segoe UI",sans-serif;letter-spacing:-.04em} + .marketing-shell{min-height:100vh;padding:0 0 92px;display:grid;gap:12px} + .marketing-main{width:min(1240px,calc(100vw - 48px));margin:0 auto} + .marketing-bar{position:sticky;top:0;z-index:20;display:flex;align-items:center;justify-content:space-between;gap:14px;height:88px;min-height:88px;width:100%;margin:0 0 20px;padding:0 18px;border:0;border-bottom:1px solid rgba(137,154,188,.18);border-radius:0;background:rgba(8,10,18,.82);box-shadow:none;backdrop-filter:blur(16px)} + .marketing-brand{display:flex;align-items:center;gap:8px;flex:0 0 auto} + .marketing-brand__mark{width:40px;height:40px;border-radius:10px;display:grid;place-items:center;background:linear-gradient(135deg,#587aff 0%,#243a91 100%);color:#fff;font-size:1rem;font-weight:800;box-shadow:none} + .marketing-brand__title{margin:0;font-size:1.08rem;line-height:1;color:#f4f7ff} + .marketing-brand__copy{display:none} + .marketing-nav,.marketing-actions,.landing-actions{display:flex;flex-wrap:wrap;gap:12px;align-items:center} + .marketing-nav{gap:6px} + .marketing-nav a{display:inline-flex;align-items:center;justify-content:center;min-height:36px;padding:0 .3rem;border-radius:6px;border:1px solid transparent;font-size:1rem;font-weight:600;color:rgba(231,238,255,.8)} + .marketing-nav a:hover{text-decoration:none;color:#f4f7ff;background:rgba(255,255,255,.06);border-color:rgba(201,214,255,.12)} + .marketing-actions .button{min-height:38px;padding:.42rem .8rem;border-radius:8px;font-size:.94rem} + .marketing-actions .button.secondary,.marketing-mobile__footer .button.secondary{background:transparent;color:#f4f7ff;border-color:rgba(201,214,255,.16);box-shadow:none} + .marketing-mobile{display:none;position:relative} + .marketing-mobile[open]{z-index:40} + .marketing-mobile__toggle{display:inline-flex;align-items:center;justify-content:center;gap:10px;list-style:none;cursor:pointer;min-width:38px;min-height:38px;padding:.24rem .46rem;border-radius:8px;border:1px solid rgba(201,214,255,.14);background:rgba(255,255,255,.04);color:#f4f7ff} + .marketing-mobile__toggle::-webkit-details-marker{display:none} + .marketing-mobile__toggle::before{content:"";width:16px;height:10px;border-top:2px solid currentColor;border-bottom:2px solid currentColor;box-shadow:inset 0 -4px 0 0 currentColor} + .marketing-mobile__panel{position:absolute;right:0;top:calc(100% + 10px);width:min(280px,calc(100vw - 24px));padding:14px;border-radius:16px;border:1px solid rgba(163,183,255,.14);background:rgba(8,10,18,.96);box-shadow:0 18px 36px rgba(1,5,13,.45)} + .marketing-mobile__stack{display:grid;gap:8px} + .marketing-mobile__stack .marketing-nav__link{justify-content:flex-start;padding:.55rem .7rem;background:rgba(255,255,255,.04);border-color:rgba(201,214,255,.1)} + .marketing-mobile__footer{margin-top:12px;display:flex;justify-content:flex-end} + .landing-hero{width:min(1240px,calc(100vw - 48px));margin:0 auto;padding-top:12px;display:grid;grid-template-columns:minmax(0,1.08fr) minmax(280px,.92fr);gap:40px;align-items:start} + .landing-copy__eyebrow{margin:0 0 10px;text-transform:uppercase;letter-spacing:.16em;font-size:.78rem;font-weight:700;color:#8aa0d0} + .landing-copy h1{margin:0;font-size:clamp(3.2rem,7vw,6.4rem);line-height:.9;letter-spacing:-.06em;color:#f4f7ff} + .landing-copy p{margin:14px 0 0;color:rgba(219,228,248,.72);font-size:1.05rem;max-width:30rem;line-height:1.65} + .landing-actions{margin-top:24px} + .landing-visual,.landing-callout{border:1px solid rgba(163,183,255,.12);border-radius:20px;background:rgba(14,20,34,.86);box-shadow:0 16px 40px rgba(2,5,12,.34)} + .landing-visual{padding:20px;display:grid;gap:12px} + .landing-visual__top{display:flex;align-items:center;justify-content:space-between;gap:12px;padding-bottom:12px;border-bottom:1px solid rgba(163,183,255,.12)} + .landing-visual__title{margin:0;font-size:1.1rem;color:#f4f7ff} + .landing-visual__stack{display:grid;gap:12px} + .landing-visual__row{display:flex;justify-content:space-between;gap:12px;align-items:center;padding:12px 14px;border-radius:16px;background:rgba(255,255,255,.04);color:rgba(216,225,246,.72);font-weight:600} + .landing-visual__row strong{color:#f4f7ff} + .landing-columns{width:min(1240px,calc(100vw - 48px));margin:0 auto;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0;border-top:1px solid rgba(163,183,255,.12);border-bottom:1px solid rgba(163,183,255,.12)} + .landing-column{padding:24px 18px} + .landing-column + .landing-column{border-left:1px solid rgba(163,183,255,.12)} + .landing-column__eyebrow{margin:0 0 10px;color:#8aa0d0;font-size:.78rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase} + .landing-column h2{margin:0 0 10px;font-size:1.45rem;color:#f4f7ff} + .landing-column p{margin:0;max-width:22rem;color:rgba(219,228,248,.72)} + .landing-callout{width:min(1240px,calc(100vw - 48px));margin:0 auto;padding:24px 26px} + .landing-callout__eyebrow{margin:0 0 8px;color:#8aa0d0;font-size:.78rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase} + .landing-callout h2{margin:0 0 10px;font-size:2rem;color:#f4f7ff} + .landing-callout p{margin:0;max-width:36rem;color:rgba(217,226,246,.8)} + .landing-cta{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:16px;padding-top:20px;margin-top:22px;border-top:1px solid rgba(163,183,255,.12)} + .landing-cta__copy{display:grid;gap:6px} + .landing-cta__copy strong{font-size:1.05rem;color:#f4f7ff} + .landing-cta__copy span{color:rgba(217,226,246,.72)} + .marketing-footer{position:fixed;left:0;right:0;bottom:0;z-index:25;margin-top:0;padding:10px 24px;border-top:1px solid rgba(137,154,188,.14);background:rgba(8,10,18,.88);backdrop-filter:blur(18px);color:rgba(209,217,235,.68);font-size:.92rem} + .marketing-footer__inner{display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;width:min(1240px,calc(100% - 48px));margin:0 auto} + @media(max-width:960px){.marketing-main,.landing-hero,.landing-columns,.landing-callout{width:calc(100vw - 24px)}.marketing-bar{height:72px;min-height:72px;margin:0 0 16px;padding:0 12px}.marketing-nav,.marketing-actions{display:none}.marketing-mobile{display:block}.landing-hero,.landing-columns{grid-template-columns:1fr}.landing-hero{gap:24px;padding-top:0}.landing-column{padding:20px 0}.landing-column + .landing-column{border-left:0;border-top:1px solid rgba(163,183,255,.12)}.landing-callout{padding:20px}.marketing-shell{padding:0 0 88px}.marketing-footer{padding:10px 12px}.marketing-footer__inner{width:100%}} + @media(max-width:960px){.page-shell{width:min(100vw - 20px,1460px)}.site-header__inner{align-items:flex-start;padding:14px 16px}.site-nav{display:none}.site-mobile{display:block}.grid-2,.grid-3,.grid-4,form.grid{grid-template-columns:1fr}.table table{min-width:0}} + @media(min-width:961px){.site-mobile{display:none}} - -
- + + + +
+ Anmelden +
+ +
+ +
+ + +
+
+ + + +
+ + +
+
+

Die Kaffeeliste

+

Kaffee im Team. Klar organisiert.

+

Für Mitglieder, Verantwortliche und Standorte.

+ +
+ + +
+ +
+ +
+

+

+

+
+ +
+ +
+

Einfach im Alltag

+

Ein gemeinsamer Ort für die Kaffeeliste.

+

Weniger suchen. Weniger erklären. Klar durch den Tag.

+
+
+ Bereit für den Start? + Direkt zur Anmeldung. +
+ Anmelden +
+
+ +
+ +
+
+ +
+
@@ -387,13 +554,13 @@ $themeCss = app_tenant_theme_root_css($tenantSettings);
-
Zentrale Anmeldung
+
Anmeldung

Anmeldung

-

Zuerst wird der passende Bereich ermittelt. Falls mehrere Zuordnungen vorhanden sind, wählst du den richtigen Tenant aus und gibst danach dein Passwort ein.

+

Mit deiner E-Mail weiter.

- - - + + +
@@ -408,7 +575,7 @@ $themeCss = app_tenant_theme_root_css($tenantSettings);
Schritt 2
-

Passenden Tenant wählen

+

Bereich waehlen

@@ -424,7 +591,7 @@ $themeCss = app_tenant_theme_root_css($tenantSettings);
Schritt 2

Passwort eingeben

-

Der Tenant wurde erkannt:

+

@@ -444,11 +611,11 @@ $themeCss = app_tenant_theme_root_css($tenantSettings);
-
Hilfe beim Einstieg
-

Wenn die Anmeldung nicht sofort klappt

+
Hilfe
+

Wenn es nicht direkt klappt

  • Prüfe zuerst, ob du die richtige berufliche E-Mail-Adresse verwendest.
  • -
  • Wenn du in mehreren Bereichen arbeitest, wirst du automatisch zur passenden Auswahl geführt.
  • +
  • Wenn du in mehreren Bereichen arbeitest, waehle den passenden aus.
  • Falls kein Zugang gefunden wird, brauchst du meist nur eine Einladung oder den Kontakt zur verantwortlichen Person.
@@ -495,13 +662,12 @@ $themeCss = app_tenant_theme_root_css($tenantSettings);
-
Tenant-Dashboard
-

Übersicht

-

Kontostand, Buchungen, Einzahlungen und die letzten Aktivitäten stehen direkt für diesen Tenant bereit.

+
Uebersicht
+

+

Alles Wichtige auf einen Blick.

- Zur zentralen Verwaltung - Mitglieder im Menü + Zur Verwaltung
@@ -519,18 +685,18 @@ $themeCss = app_tenant_theme_root_css($tenantSettings);
-
Bereiche im Menü
-

Funktionen werden über das Menü geöffnet

-
    -
  • Hinweise, Support und Umfragen erscheinen als feste Hauptbereiche im Tenant-Menü.
  • -
  • Mitglieder, Rollen, Buchungen und Zahlungen werden nur für passende Rollen eingeblendet.
  • -
  • Einstellungen und Exporte erscheinen nur, wenn das Lizenzmodell diese Funktionen freischaltet.
  • -
+
Heute
+

Schnell weiter

+
+

Mitglieder, Buchungen und weitere Bereiche oeffnest du direkt ueber das Menue.

+
-
Lizenzlogik
-

Nur passende Funktionen sichtbar

-

Die Oberfläche blendet Bereiche nicht als tote Kacheln ein. Was im Menü erscheint, hängt von Rolle und Lizenz des Tenants ab.

+
Status
+

Alles im Blick

+
+

Die wichtigsten Zahlen und die letzten Buchungen stehen hier zuerst.

+
@@ -563,18 +729,18 @@ $themeCss = app_tenant_theme_root_css($tenantSettings);
-
Mitgliedersicht
+
Dein Bereich

Dein Bereich

  • Hier siehst du deinen Kontostand, letzte Buchungen und aktuelle Hinweise.
  • -
  • Tenant-weite Buchungen und Mitgliederverwaltung bleiben bei den verantwortlichen Admins.
  • +
  • Weitere Bereiche findest du direkt im Menue.
  • Wenn dir etwas fehlt, wende dich an den Betreiber deines Bereichs.
-
Nächster Schritt
-

Womit du direkt weiterkommst

-

Weitere Bereiche wechselst du direkt über das Menü. Sichtbar wird dort nur, was für deine Rolle freigegeben ist.

+
Naechster Schritt
+

Direkt weiter

+

Nutze das Menue fuer den naechsten Bereich.

@@ -850,8 +1016,9 @@ $themeCss = app_tenant_theme_root_css($tenantSettings);
Die angeforderte Seite konnte nicht gefunden werden.
- +
+ diff --git a/saas-app/resources/views/auth/login.blade.php b/saas-app/resources/views/auth/login.blade.php index a9baf2f..7ba60c2 100644 --- a/saas-app/resources/views/auth/login.blade.php +++ b/saas-app/resources/views/auth/login.blade.php @@ -1,81 +1,22 @@ @extends('layouts.app') -@section('page_title', 'Die Kaffeeliste - Zentrale Anmeldung') +@section('page_title', 'Die Kaffeeliste - Anmeldung') @php $preview = $loginPreview ?? [ 'single' => [ 'email' => 'mia@berlin.example', - 'message' => 'Direkte Weiterleitung in den zugeordneten Tenant.', + 'message' => 'Direkt weiter.', 'matches' => [['name' => 'Werk Berlin', 'domain' => 'berlin.kaffeeliste.de', 'login_mode' => 'oidc-first']], ], 'multiple' => [ 'email' => 'leitung@kaffeeliste.example', - 'message' => 'Tenant-Auswahl vor Passwort oder SSO.', + 'message' => 'Auswahl vor dem Einstieg.', 'matches' => [ ['name' => 'Werk Berlin', 'domain' => 'berlin.kaffeeliste.de', 'login_mode' => 'oidc-first'], ['name' => 'Werk Koeln', 'domain' => 'koeln.kaffeeliste.de', 'login_mode' => 'oidc-first'], - ['name' => 'Shared Services', 'domain' => 'shared.kaffeeliste.de', 'login_mode' => 'central-routing'], ], ], - 'unknown' => [ - 'email' => 'extern@example.org', - 'message' => 'Rueckfuehrung auf Tenant-Admin oder Einladungspfad.', - 'matches' => [], - ], - ]; - $identityPolicy = $identityPolicy ?? [ - 'local_login_required' => true, - 'external_login_mode' => 'ADFS/OIDC', - 'supported_modes' => ['password', 'adfs_oidc'], - 'email_mapping' => 'E-Mail-Mapping als primaerer Abgleich zwischen externer Identitaet und internem Benutzer', - 'fallback' => 'Bei Dubletten oder unklaren Zuordnungen wird ein Admin-Klaerfall erzeugt.', - 'recovery' => 'Lokale Anmeldung bleibt immer verfuegbar, auch wenn externe Provider ausfallen.', - 'clarification' => 'Der Erstlogin soll bestehende Konten wiederverwenden und nicht stillschweigend neue Duplikate anlegen.', - 'admin_clarification' => [ - 'title' => 'Admin-Klaerfall', - 'description' => 'Wenn eine E-Mail-Adresse nicht eindeutig zugeordnet werden kann, wird der Fall an die zuständigen Admins eskaliert.', - 'steps' => ['Identitaet pruefen', 'Tenant zuordnen', 'Konto bestaetigen oder neu anlegen'], - ], - ]; - $roleMatrix = $roleMatrix ?? [ - 'roles' => [ - ['key' => 'platform_admin', 'summary' => 'Globaler Zugriff auf Plattform, Tenants und Betriebssteuerung.'], - ['key' => 'tenant_admin', 'summary' => 'Vollzugriff im eigenen Tenant inklusive Rollen- und Inhaltsverwaltung.'], - ['key' => 'finance_admin', 'summary' => 'Operative Buchungsrolle fuer Einzahlungen, Storno und Finanzreports.'], - ['key' => 'support_contact', 'summary' => 'Bearbeitung und Abschluss von Supportvorgaengen.'], - ['key' => 'survey_manager', 'summary' => 'Pflege, Freigabe und Auswertung von Surveys.'], - ['key' => 'member', 'summary' => 'Mitglied mit Zugriff auf eigenes Profil und freigegebene Inhalte.'], - ], - 'rules' => [ - 'Tenant-Admin hat Vollzugriff im eigenen Tenant.', - 'Spezialrollen erhalten nur die fuer ihr Modul noetigen Rechte.', - 'Einzahlungen duerfen nur von Verantwortlichen storniert werden.', - 'Stricheintraege duerfen nur von Verantwortlichen geloescht werden.', - ], - ]; - $providers = $providers ?? [ - 'password' => [ - 'label' => 'Lokale Systemanmeldung', - 'type' => 'password', - 'required' => true, - 'description' => 'Pflichtweg fuer lokale Konten und Fallback bei externen Ausfaellen.', - ], - 'adfs_oidc' => [ - 'label' => 'ADFS / OIDC', - 'type' => 'oidc', - 'required' => false, - 'description' => 'Zusatzoption fuer angebundene Identitaetsprovider.', - ], - ]; - $oidcProviders = $oidcProviders ?? [ - [ - 'provider_key' => 'adfs-oidc-default', - 'driver' => 'oidc', - 'client_id' => 'tenant-client-id', - 'redirect_uri' => '/auth/oidc/adfs-oidc-default/callback', - 'scopes' => ['openid', 'profile', 'email'], - ], ]; @endphp @@ -83,53 +24,37 @@
-

Mitglieder-Login

-

Eine zentrale Anmeldung, die Mitglieder automatisch in den richtigen Tenant bringt.

+

Anmeldung

+

Einfach einsteigen.

- Statt verschiedene Tenant-URLs zu kennen, starten Mitglieder zentral mit ihrer E-Mail-Adresse. Die Plattform - erkennt Einzel- oder Mehrfachzuordnungen und fuehrt danach passend weiter: direkt in den Tenant, in eine - Tenant-Auswahl oder in einen klaren Kontaktpfad. + E-Mail eingeben, kurz pruefen, weitermachen.

-
- E-Mail first - Tenant-Erkennung - Lokaler Login Pflicht - ADFS/OIDC zusaetzlich - Mehrfachzuordnung unterstuetzt + Direkt + Klar + Wenig Schritte
-
+
-

Zentraler Einstieg

-

Mit E-Mail und Passwort anmelden

-

- Die E-Mail-Adresse steuert zuerst die Tenant-Erkennung. Der Passwort- oder SSO-Schritt kommt danach im richtigen Kontext. -

+

Zugang

+

Anmelden

@@ -140,86 +65,60 @@
- + Passwort vergessen?
-
- Zielbild: Eine zentrale Anmeldung fuer Mitglieder, ohne dass zuerst Tenant-Keys oder Subdomains bekannt sein muessen. -
-

Was danach passiert

-

Automatische Weiterleitung oder Tenant-Auswahl.

+

Ablauf

+

So geht es weiter

-

Genau ein Treffer

-

Die Plattform leitet direkt in den Tenant weiter und zeigt dort Passwort- oder SSO-Login an.

+

1. E-Mail

+

Die Anmeldung startet mit der Adresse.

-

Mehrere Treffer

-

Vor dem eigentlichen Login erscheint eine Tenant-Auswahl mit Namen, Domain und Login-Modell.

+

2. Pruefen

+

Der passende Zugang wird zugeordnet.

-

Kein Treffer

-

Statt Sackgasse gibt es einen klaren Rueckweg zu Tenant-Admin, Einladung oder Support.

+

3. Weiter

+

Dann folgt der eigentliche Login.

-
- @foreach ($providers as $providerKey => $provider) -
-
{{ strtoupper(substr((string) $providerKey, 0, 1)) }}
-
-

{{ $provider['label'] ?? $providerKey }}

-

{{ $provider['description'] ?? '' }}

-
- - {{ !empty($provider['required']) ? 'Pflicht' : 'Optional' }} - -
- @endforeach -
-
- {{ $identityPolicy['admin_clarification']['title'] ?? 'Admin-Klaerfall' }} -

{{ $identityPolicy['admin_clarification']['description'] ?? $identityPolicy['fallback'] ?? '' }}

-
    - @foreach (($identityPolicy['admin_clarification']['steps'] ?? []) as $step) -
  • - {{ $step }}
  • - @endforeach -
-
-

Preview: Einzelzuordnung

+

Ein Treffer

{{ $preview['single']['email'] }}

{{ $preview['single']['message'] }}

-
+
@foreach ($preview['single']['matches'] as $tenant)

{{ $tenant['name'] }}

{{ $tenant['domain'] }}

- Auto-Weiterleitung + Direkt
@endforeach
-

Preview: Mehrfachzuordnung

+

Mehrere Treffer

{{ $preview['multiple']['email'] }}

{{ $preview['multiple']['message'] }}

-
+
@foreach ($preview['multiple']['matches'] as $tenant)

{{ $tenant['name'] }}

-

{{ $tenant['domain'] }} - {{ $tenant['login_mode'] }}

+

{{ $tenant['domain'] }}

Auswahl
@@ -228,94 +127,13 @@
-

Preview: Unbekannte Mail

-

{{ $preview['unknown']['email'] }}

-

{{ $preview['unknown']['message'] }}

-
- Keine Sackgasse fuer Mitglieder - Die Anwendung kann stattdessen Tenant-Kontakt, Einladung oder den zentralen Supportpfad anzeigen. +

Kein Treffer

+

Sauberer Rueckweg

+

Wenn keine Zuordnung passt, geht es klar weiter statt im Leeren zu enden.

+
+ Kontakt oder Einladung + Die Anmeldung zeigt dann den naechsten klaren Schritt.
- -
-
-

Identity-Policy

-

Lokale Anmeldung plus ADFS/OIDC

-
-
-

Pflicht

-

{{ $identityPolicy['local_login_required'] ? 'Lokale Anmeldung bleibt immer verfuegbar.' : 'Lokale Anmeldung ist optional.' }}

-
-
-

Zusaetzliche Option

-

{{ $identityPolicy['external_login_mode'] ?? 'ADFS/OIDC' }}

-
-
-

Abgleich

-

{{ $identityPolicy['email_mapping'] ?? '' }}

-
-
-

Klärfall

-

{{ $identityPolicy['fallback'] ?? '' }}

-
-
-

Admin-Klaerfall

-

{{ $identityPolicy['admin_clarification']['description'] ?? '' }}

-
-
-
- -
-

Rollenmodell

-

Vorgeschlagene Rechtebasis

-
- @foreach ($roleMatrix['roles'] ?? [] as $role) -
-
{{ strtoupper(substr((string) ($role['key'] ?? ''), 0, 1)) }}
-
-

{{ $role['key'] ?? '' }}

-

{{ $role['summary'] ?? '' }}

-
-
- @endforeach -
-
-
- -
-
-

Provider-Details

-

Konfigurierte ADFS/OIDC-Verbindungen

-
- @foreach ($oidcProviders as $provider) -
-

{{ $provider['provider_key'] ?? 'provider' }}

-

Driver: {{ $provider['driver'] ?? 'oidc' }} | Client-ID: {{ $provider['client_id'] ?? '-' }}

-

Redirect: {{ $provider['redirect_uri'] ?? '-' }}

-

Scopes: {{ implode(', ', $provider['scopes'] ?? []) }}

-
- @endforeach -
-
- -
-

Mindestregel

-

Lokale Anmeldung bleibt immer verfuegbar.

-
- Selbst wenn ein externer Provider ausfaellt, bleibt der lokale Weg aktiv. So kann der Tenant weiterarbeiten und der Admin-Klaerfall bleibt handhabbar. -
-
-
- -
-

Regeln fuer Rollen und Abgrenzung

-
    - @foreach ($roleMatrix['rules'] ?? [] as $rule) -
  • - Regel {{ $rule }} -
  • - @endforeach -
-
@endsection diff --git a/saas-app/resources/views/dashboard/index.blade.php b/saas-app/resources/views/dashboard/index.blade.php index f59a896..09eb602 100644 --- a/saas-app/resources/views/dashboard/index.blade.php +++ b/saas-app/resources/views/dashboard/index.blade.php @@ -3,42 +3,56 @@ @section('page_title', 'Die Kaffeeliste - Übersicht') @section('content') -
-
-

Übersicht

-

Dein Bereich

-

- Das Dashboard zeigt den aktuellen Kontostand, die Nutzung im Monat und die letzten Buchungen. - Die Werte sind hier bewusst als fachliche Anker platziert und können später direkt aus dem Ledger gespeist werden. -

-
-
- Letzte Synchronisation: heute - Tenant: Demo-Workspace - Saldo aktiv +
+
+
+

Uebersicht

+

Dein Bereich

+

+ Die wichtigsten Werte auf einen Blick. +

+
+
+ Heute + Aktiv + Bereit +
+ +

Kontostand

7,50 EUR
-

Positiver Puffer für den laufenden Monat.

+

Aktueller Stand.

-

Striche diesen Monat

+

Striche

5
-

Verbrauch seit Monatsbeginn.

+

Diesen Monat.

-

Einzahlungen diesen Monat

+

Einzahlungen

1
-

Alle gebuchten Zahlungen im aktuellen Zeitraum.

+

Diesen Monat.

Letzte Buchung

Heute
-

Aktuelle Aktivität im Mandantenbereich.

+

Aktuelle Aktivitaet.

@@ -46,10 +60,10 @@
-

Aktivität

+

Aktivitaet

Letzte Buchungen

- Live feed + Live
@@ -86,24 +100,24 @@
-

Arbeitsbereich

-

Die Navigation läuft vollständig über das Menü. Im Inhalt bleiben nur die fachlichen Schwerpunkte.

+

Bereiche

+

Im Menue liegen die zentralen Arbeitsbereiche.

-

Mitglieder und Rollen

-

Im Menü sichtbar, wenn die angemeldete Rolle den Bereich verwalten darf.

+

Mitglieder

+

Verwaltung im Hintergrund.

-

Buchungen und Zahlungen

-

Nur für Finanzrollen freigeschaltet und dadurch nicht für jede Anmeldung sichtbar.

+

Buchungen

+

Striche und Zahlungen zusammen.

-

Exporte und Zusatzfunktionen

-

Werden im Menü nur angezeigt, wenn das Lizenzmodell sie für den Tenant enthält.

+

Exporte

+

Nur wenn freigeschaltet.

- Der alte Funktionskern bleibt sichtbar: Saldo, Striche, Einzahlungen und letzte Aktionen bilden die produktive Achse. + Die wichtigsten Zahlen sind hier, der Rest bleibt im Menue.
diff --git a/saas-app/resources/views/layouts/app.blade.php b/saas-app/resources/views/layouts/app.blade.php index 35235ed..cec9193 100644 --- a/saas-app/resources/views/layouts/app.blade.php +++ b/saas-app/resources/views/layouts/app.blade.php @@ -20,10 +20,28 @@ $layoutNavItems = function_exists('app_tenant_navigation_items') ? app_tenant_navigation_items($layoutAuth, $layoutLicense) : []; + $layoutGuestItems = [ + ['href' => '/', 'label' => 'Start'], + ['href' => '/login/', 'label' => 'Anmeldung'], + ['href' => '/admin/login/', 'label' => 'Admin'], + ]; + $layoutPrimaryNavItems = $layoutNavItems !== [] ? $layoutNavItems : $layoutGuestItems; + $layoutCurrentLabel = 'Start'; + foreach ($layoutPrimaryNavItems as $item) { + $itemHref = rtrim((string) ($item['href'] ?? '/'), '/'); + $itemHref = $itemHref === '' ? '/' : $itemHref; + if ($layoutPath === $itemHref) { + $layoutCurrentLabel = (string) ($item['label'] ?? $layoutCurrentLabel); + break; + } + } $layoutThemeCss = function_exists('app_tenant_theme_root_css') ? app_tenant_theme_root_css($layoutThemeSettings) : ''; @endphp + @php + $resolvedLayoutMode = trim((string) $__env->yieldContent('layout_mode', 'app')); + @endphp + @yield('page_styles') -
- - -
-
-
-
-

Die Kaffeeliste

-

- @if (is_array($layoutAuth)) - Ruhige Tenant-Oberfläche mit klarer Navigation und ohne doppelte Statusinfos. - @else - Anmeldung, Tenant-Zugriff und Verwaltung bleiben in einer ruhigen gemeinsamen Struktur. - @endif -

- @if (!is_array($layoutAuth)) -
- Mandantenfähig - Mobil tauglich -
- @endif -
Menü
@if (is_array($layoutAuth))
-
+
+ -
+
@yield('content')
-
+ @endif diff --git a/saas-app/resources/views/support/index.blade.php b/saas-app/resources/views/support/index.blade.php index 5a51c8b..aab38e6 100644 --- a/saas-app/resources/views/support/index.blade.php +++ b/saas-app/resources/views/support/index.blade.php @@ -46,82 +46,61 @@ width:min(1460px,calc(100vw - 32px)); margin:20px auto 40px; display:grid; - grid-template-columns:minmax(280px,300px) minmax(0,1fr); gap:20px; - align-items:start; } - .sidebar,.hero,.card,.alert{ + .site-header{position:sticky;top:20px;z-index:20} + .site-header__inner{ + display:flex; + align-items:center; + justify-content:space-between; + gap:18px; + padding:16px 18px; + border:1px solid var(--line); + border-radius:24px; + background:rgba(255,251,244,.96); + box-shadow:var(--shadow); + } + .site-brand{display:flex;align-items:center;gap:14px;min-width:0} + .site-brand__mark{ + width:44px; + height:44px; + border-radius:16px; + display:grid; + place-items:center; + background:linear-gradient(135deg,var(--brand) 0%,var(--brand-strong) 100%); + color:#fff; + font-weight:800; + box-shadow:0 14px 28px rgba(var(--brand-rgb),.18); + } + .site-brand__title{margin:0;font-family:Georgia,serif;font-size:1.1rem;letter-spacing:-.02em} + .site-brand__subtitle{margin:2px 0 0;color:var(--muted);font-size:.92rem} + .site-nav,.site-actions,.actions,.context{display:flex;flex-wrap:wrap;gap:10px;align-items:center} + .site-nav__link{ + display:inline-flex; + align-items:center; + justify-content:center; + padding:10px 14px; + border-radius:999px; + border:1px solid transparent; + color:var(--muted); + font-weight:700; + } + .site-nav__link:hover{text-decoration:none;color:var(--brand);background:rgba(255,255,255,.82);border-color:rgba(var(--brand-rgb),.14)} + .site-nav__link.active{background:rgba(var(--brand-rgb),.10);color:var(--brand);border-color:rgba(var(--brand-rgb),.18)} + .hero,.card,.alert{ border:1px solid var(--line); border-radius:var(--radius); background:var(--card); box-shadow:var(--shadow); } - .sidebar{ - position:sticky; - top:20px; - display:grid; - gap:16px; - padding:18px; - background:rgba(255,251,244,.96); - } - .sidebar__brand{ - display:grid; - gap:6px; - padding-bottom:14px; - border-bottom:1px solid rgba(37,24,15,.1); - } - .sidebar__eyebrow{ - margin:0; - color:var(--accent); - text-transform:uppercase; - letter-spacing:.16em; - font-size:.78rem; - font-weight:800; - } - .sidebar__title,.hero__title,.card h2,.card h3{ + .hero__title,.card h2,.card h3{ font-family:Georgia,serif; letter-spacing:-.02em; } - .sidebar__title{ - margin:0; - font-size:1.55rem; - line-height:1.05; - } - .sidebar__subtitle,.muted,p{color:var(--muted)} - .sidebar__meta,.actions,.context{display:flex;flex-wrap:wrap;gap:10px;align-items:center} - .sidebar__section{ - display:inline-block; - color:var(--accent); - text-transform:uppercase; - letter-spacing:.14em; - font-size:.76rem; - font-weight:800; - } - .sidebar__nav{display:grid;gap:10px} - .sidebar__link{ - display:flex; - align-items:center; - justify-content:space-between; - padding:12px 14px; - border-radius:16px; - border:1px solid rgba(var(--brand-rgb),.12); - background:#fff; - color:var(--brand); - font-weight:700; - } - .sidebar__link.active{ - background:var(--brand); - color:#fff; - } - .sidebar__footer{ - display:grid; - gap:12px; - padding-top:14px; - border-top:1px solid rgba(37,24,15,.1); - } - .sidebar__mobile{display:none} - .sidebar__mobile[open]{z-index:20} - .sidebar__toggle{ + .muted,p{color:var(--muted)} + .site-mobile{display:none;position:relative} + .site-mobile[open]{z-index:20} + .site-toggle{ display:flex; align-items:center; justify-content:space-between; @@ -135,8 +114,8 @@ color:var(--brand); font-weight:700; } - .sidebar__toggle::-webkit-details-marker{display:none} - .sidebar__toggle::after{ + .site-toggle::-webkit-details-marker{display:none} + .site-toggle::after{ content:""; width:11px; height:11px; @@ -145,16 +124,21 @@ transform:rotate(45deg); transition:transform .2s ease; } - .sidebar__mobile[open] .sidebar__toggle::after{transform:rotate(225deg)} - .sidebar__panel{ - margin-top:12px; + .site-mobile[open] .site-toggle::after{transform:rotate(225deg)} + .site-panel{ + position:absolute; + right:0; + top:calc(100% + 12px); + width:min(320px,calc(100vw - 32px)); padding:14px; border-radius:18px; border:1px solid var(--line); background:#fffdf9; box-shadow:var(--shadow); } - .sidebar__stack{display:grid;gap:10px} + .site-stack{display:grid;gap:10px} + .site-stack .site-nav__link{justify-content:flex-start;background:rgba(255,255,255,.78);border-color:rgba(37,24,15,.08);color:var(--ink)} + .site-footer-actions{display:flex;justify-content:flex-end;margin-top:12px} .content{min-width:0;display:grid;gap:18px} .hero{ padding:24px; @@ -253,59 +237,56 @@ .mono{font-family:Consolas,monospace} .footer{margin-top:18px;text-align:center;color:var(--muted);font-size:.92rem} @media(max-width:1040px){ - .page-shell{grid-template-columns:1fr;width:min(100vw - 20px,1460px)} - .sidebar{position:static} - .sidebar__desktop{display:none} - .sidebar__mobile{display:block} + .page-shell{width:min(100vw - 20px,1460px)} + .site-header__inner{align-items:flex-start;padding:14px 16px} + .site-nav{display:none} + .site-mobile{display:block} .split,.grid--2,.grid--3,.grid--4{grid-template-columns:1fr} table{min-width:0} } @media(min-width:1041px){ - .sidebar__mobile{display:none} + .site-mobile{display:none} }
- +
@@ -351,7 +332,7 @@
+
@endsection