19-05-2026 Rebrand Pressekonto, Hub-Flux UI und Legacy-Media-Migration
Umbenennung presseportale → pressekonto in Domains, Themes und Dokumentation. Design-Tokens, Portal-Shell, Customer-Dashboard, Auth- und Admin-PM-Views. Artisan-Befehl migrate:legacy-media mit Tests und Hub-Flux-Entwicklungsdocs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
092ee0e918
commit
0a3e52d603
112 changed files with 8464 additions and 1649 deletions
|
|
@ -6,18 +6,23 @@
|
|||
@endphp
|
||||
|
||||
@if($canCustomer)
|
||||
<div class="mb-6 rounded-xl border border-zinc-200 bg-zinc-50/80 px-4 py-3 shadow-sm ring-1 ring-zinc-950/5 dark:border-zinc-700 dark:bg-zinc-900/60 dark:ring-white/10">
|
||||
{{-- Hub-Stil-Banner: Hub-Soft-Hintergrund, Hub-Blau-Badge,
|
||||
dezente Buchpapier-Rule. Ersetzt das Zinc-Starter-Kit-Card. --}}
|
||||
<div class="mb-6 rounded-md border border-hub-soft-2 bg-hub-soft/50 px-4 py-3">
|
||||
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div class="min-w-0">
|
||||
<div class="flex items-center gap-2">
|
||||
<flux:badge color="zinc" size="sm">{{ __('User Backend') }}</flux:badge>
|
||||
<flux:text class="hidden text-xs text-zinc-500 dark:text-zinc-400 sm:block">
|
||||
<div class="flex items-center gap-2.5">
|
||||
<span class="inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-hub-soft text-hub text-[10.5px] font-bold tracking-[0.10em] uppercase">
|
||||
<span class="w-1.5 h-1.5 rounded-full bg-hub"></span>
|
||||
{{ __('User Backend') }}
|
||||
</span>
|
||||
<span class="hidden sm:inline-block text-[10.5px] font-semibold tracking-[0.16em] uppercase text-ink-3">
|
||||
{{ __('Firmenkontext') }}
|
||||
</flux:text>
|
||||
</span>
|
||||
</div>
|
||||
<flux:heading size="sm" class="mt-1 truncate">
|
||||
<h2 class="mt-1 text-[15px] font-semibold tracking-[-0.2px] truncate text-ink m-0">
|
||||
{{ $title ?? __('Mein Bereich') }}
|
||||
</flux:heading>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="w-full sm:w-auto">
|
||||
|
|
|
|||
|
|
@ -1,13 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="dark">
|
||||
{{--
|
||||
Hub × FluxUI Phase 1 — Portal-Shell im Hub-Design.
|
||||
class="dark" wurde entfernt; Light Mode ist Default, Dark kommt mit
|
||||
FluxUI Appearance-Switcher in Phase 5.
|
||||
--}}
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
<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">
|
||||
<body class="min-h-screen bg-bg text-ink antialiased">
|
||||
<flux:sidebar sticky stashable class="border-e border-bg-rule">
|
||||
<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 />
|
||||
|
||||
{{-- Brand-Block: Wortmarke + Hub-Eyebrow --}}
|
||||
<a href="{{ config('domains.domain_main_url') }}" class="block px-2 pt-1 pb-3 no-underline">
|
||||
<span class="text-[19px] font-bold tracking-[-0.4px] leading-none">
|
||||
<x-web.brand-mark brand="pressekonto" :serif="false" />
|
||||
</span>
|
||||
<div class="mt-1.5 text-[10px] font-semibold tracking-[0.18em] uppercase text-ink-3">
|
||||
Publisher · Hub
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@php
|
||||
|
|
@ -158,43 +170,42 @@
|
|||
@endauth
|
||||
|
||||
@if($impersonator)
|
||||
<div class="mt-3 rounded-lg border border-amber-200 bg-amber-50 p-3 text-sm text-amber-950 dark:border-amber-700/60 dark:bg-amber-950/40 dark:text-amber-100">
|
||||
<flux:text weight="semibold">{{ __('Testmodus aktiv') }}</flux:text>
|
||||
<flux:text class="mt-1 text-xs">
|
||||
{{ __('Angemeldet als :user. Admin: :admin.', ['user' => $user?->name, 'admin' => $impersonator->name]) }}
|
||||
</flux:text>
|
||||
|
||||
<form method="POST" action="{{ route('admin.impersonate.leave') }}" class="mt-3">
|
||||
@csrf
|
||||
<flux:button type="submit" size="sm" variant="primary" class="w-full">
|
||||
{{ __('Zurück zum Admin') }}
|
||||
</flux:button>
|
||||
</form>
|
||||
{{-- Testmodus-Block im Hub-Stil (statt Amber-Warnfarbe).
|
||||
Dunkles Hub-Blau-Panel mit Bernstein-Eyebrow, klare
|
||||
CTA „Zurück zum Admin" als helle Pille. --}}
|
||||
<div class="mt-3 relative overflow-hidden rounded-[5px] bg-hub p-4 text-ink-on-dark">
|
||||
<div class="absolute -top-6 -right-6 w-16 h-16 rounded-full bg-hub-3 opacity-50"></div>
|
||||
<div class="absolute -bottom-8 -left-8 w-20 h-20 rounded-full bg-hub-3 opacity-30"></div>
|
||||
<div class="relative">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<span class="w-1.5 h-1.5 rounded-full bg-accent animate-pulse"></span>
|
||||
<span class="text-[10.5px] font-bold tracking-[0.20em] uppercase text-accent-soft">
|
||||
{{ __('Testmodus aktiv') }}
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-[12px] leading-[1.5] text-ink-on-dark-2 m-0">
|
||||
{{ __('Angemeldet als') }}
|
||||
<strong class="text-white font-semibold">{{ $user?->name }}</strong>.<br/>
|
||||
{{ __('Admin:') }}
|
||||
<strong class="text-white font-semibold">{{ $impersonator->name }}</strong>
|
||||
</p>
|
||||
<form method="POST" action="{{ route('admin.impersonate.leave') }}" class="mt-3">
|
||||
@csrf
|
||||
<button
|
||||
type="submit"
|
||||
class="w-full px-3 py-2 bg-white text-hub text-[12px] font-semibold rounded-[3px] hover:bg-bg transition-colors flex items-center justify-center gap-1.5"
|
||||
>
|
||||
<svg width="11" height="11" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
||||
<path d="M9 3L3 9M3 9H8M3 9V4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
{{ __('Zurück zum Admin') }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<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
|
||||
|
|
@ -231,6 +242,22 @@
|
|||
|
||||
<flux:menu.separator />
|
||||
|
||||
{{-- Phase 5: Appearance-Switcher direkt im User-Menü.
|
||||
`$flux.appearance` ist FluxUIs Magic-Object, persistent
|
||||
über LocalStorage. Werte: 'light' | 'dark' | 'system'. --}}
|
||||
<div class="px-3 py-2">
|
||||
<div class="mb-1.5 text-[10px] font-semibold tracking-[0.16em] uppercase text-[color:var(--color-ink-3)]">
|
||||
{{ __('Erscheinung') }}
|
||||
</div>
|
||||
<flux:radio.group x-data variant="segmented" size="sm" x-model="$flux.appearance" class="w-full">
|
||||
<flux:radio value="light" icon="sun" :title="__('Hell')" />
|
||||
<flux:radio value="dark" icon="moon" :title="__('Dunkel')" />
|
||||
<flux:radio value="system" icon="computer-desktop" :title="__('System')" />
|
||||
</flux:radio.group>
|
||||
</div>
|
||||
|
||||
<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">
|
||||
|
|
@ -245,8 +272,10 @@
|
|||
<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 href="{{ config('domains.domain_main_url') }}" class="me-5 ml-2 flex items-baseline no-underline">
|
||||
<span class="text-[16px] font-bold tracking-[-0.3px] leading-none">
|
||||
<x-web.brand-mark brand="pressekonto" :serif="false" />
|
||||
</span>
|
||||
</a>
|
||||
<flux:spacer />
|
||||
|
||||
|
|
@ -284,6 +313,20 @@
|
|||
|
||||
<flux:menu.separator />
|
||||
|
||||
{{-- Phase 5: Appearance-Switcher (Mobile-Dropdown). --}}
|
||||
<div class="px-3 py-2">
|
||||
<div class="mb-1.5 text-[10px] font-semibold tracking-[0.16em] uppercase text-[color:var(--color-ink-3)]">
|
||||
{{ __('Erscheinung') }}
|
||||
</div>
|
||||
<flux:radio.group x-data variant="segmented" size="sm" x-model="$flux.appearance" class="w-full">
|
||||
<flux:radio value="light" icon="sun" :title="__('Hell')" />
|
||||
<flux:radio value="dark" icon="moon" :title="__('Dunkel')" />
|
||||
<flux:radio value="system" icon="computer-desktop" :title="__('System')" />
|
||||
</flux:radio.group>
|
||||
</div>
|
||||
|
||||
<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">
|
||||
|
|
|
|||
154
resources/views/components/layouts/auth/pressekonto.blade.php
Normal file
154
resources/views/components/layouts/auth/pressekonto.blade.php
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
@props([
|
||||
'title' => null,
|
||||
'eyebrow' => 'Publisher-Hub',
|
||||
'heading' => null,
|
||||
'topRightLabel' => null,
|
||||
'topRightLinkText' => null,
|
||||
'topRightLinkHref' => null,
|
||||
'showFromBanner' => true,
|
||||
])
|
||||
|
||||
@php
|
||||
$brand = config('domains.domains.pressekonto.brand', []);
|
||||
$from = request()->query('from');
|
||||
|
||||
$brandLabelMap = [
|
||||
'presseecho' => 'presseecho.de',
|
||||
'businessportal24' => 'businessportal24.com',
|
||||
];
|
||||
$fromBrandLabel = $brandLabelMap[$from] ?? null;
|
||||
|
||||
$pageTitle = $title ?? ($brand['meta_title'] ?? 'pressekonto – Publisher-Hub');
|
||||
|
||||
config([
|
||||
'app.theme' => 'pressekonto',
|
||||
'app.view_prefix' => 'web',
|
||||
]);
|
||||
$themeCssPath = \App\Helpers\ThemeHelper::getThemeCssPath();
|
||||
$assetsDir = config('domains.domains.pressekonto.assets_dir', 'build/web');
|
||||
\Illuminate\Support\Facades\Vite::useBuildDirectory($assetsDir);
|
||||
@endphp
|
||||
|
||||
<!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>{{ $pageTitle }}</title>
|
||||
|
||||
<link rel="icon" href="{{ asset(\App\Helpers\ThemeHelper::getFaviconPath()) }}" />
|
||||
|
||||
<link rel="preconnect" href="https://fonts.bunny.net" />
|
||||
<link rel="preconnect" href="https://fonts.bunny.net" crossorigin />
|
||||
<link href="https://fonts.bunny.net/css?family=inter-tight:400,500,600,700|source-serif-4:400,500,600,700|jetbrains-mono:400,500,600" rel="stylesheet" />
|
||||
|
||||
{{-- Nur CSS aus dem Web-Build laden. Alpine bringt @livewireScripts mit;
|
||||
würden wir hier zusätzlich resources/js/app.js mit Alpine.start()
|
||||
laden, gäbe es zwei Alpine-Instanzen und wire:submit, x-data,
|
||||
wire:model würden brechen (siehe Browser-Logs vor diesem Fix). --}}
|
||||
@vite([$themeCssPath], $assetsDir)
|
||||
@livewireStyles
|
||||
</head>
|
||||
|
||||
<body class="font-sans text-ink antialiased" style="background-color: #f6f4ef;">
|
||||
|
||||
<div class="relative min-h-screen flex flex-col overflow-hidden bg-bg">
|
||||
|
||||
{{-- Atmosphäre: subtiles Raster --}}
|
||||
<div class="auth-grid" aria-hidden="true"></div>
|
||||
|
||||
{{-- Atmosphäre: konzentrische Kreise um die Bildmitte --}}
|
||||
<svg class="absolute inset-0 w-full h-full pointer-events-none" preserveAspectRatio="xMidYMid slice" viewBox="0 0 1280 880" aria-hidden="true">
|
||||
<g opacity="0.09" stroke="#1A2540" fill="none" stroke-width="1">
|
||||
<circle cx="640" cy="470" r="160" />
|
||||
<circle cx="640" cy="470" r="260" />
|
||||
<circle cx="640" cy="470" r="380" />
|
||||
<circle cx="640" cy="470" r="510" />
|
||||
<circle cx="640" cy="470" r="660" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
{{-- 3px Hub-Blau-Streifen --}}
|
||||
<div class="relative h-[3px] bg-hub z-10"></div>
|
||||
|
||||
{{-- Header --}}
|
||||
<header class="relative z-10 px-6 sm:px-10 py-[22px] flex items-center justify-between gap-4">
|
||||
<a href="{{ route('home') }}" class="flex items-baseline gap-2.5 no-underline" wire:navigate>
|
||||
<span class="text-[19px] font-bold tracking-[-0.4px] leading-none">
|
||||
<x-web.brand-mark brand="pressekonto" :serif="false" />
|
||||
</span>
|
||||
<span class="hidden sm:inline-block w-px h-[14px] bg-bg-rule"></span>
|
||||
<span class="hidden sm:inline-block text-[9.5px] font-bold tracking-[0.22em] uppercase text-ink-3">
|
||||
{{ $brand['tagline_short'] ?? 'Publisher · Hub' }}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
@if ($topRightLinkText && $topRightLinkHref)
|
||||
<span class="text-[13px] text-ink-3">
|
||||
@if ($topRightLabel)
|
||||
{{ $topRightLabel }}
|
||||
@endif
|
||||
<a href="{{ $topRightLinkHref }}" class="link-hub" wire:navigate>{{ $topRightLinkText }}</a>
|
||||
</span>
|
||||
@endif
|
||||
</header>
|
||||
|
||||
{{-- Auth-Card --}}
|
||||
<main class="relative z-10 flex-1 flex items-center justify-center px-6 sm:px-10 py-5">
|
||||
<div class="w-full max-w-[440px]">
|
||||
|
||||
@if ($showFromBanner && $fromBrandLabel)
|
||||
<div class="from-banner mb-3.5">
|
||||
Sie kommen von <strong class="font-semibold text-ink">{{ $fromBrandLabel }}</strong>.
|
||||
Ihr Konto funktioniert für <strong class="font-semibold text-ink">beide Portale</strong> –
|
||||
presseecho.de und businessportal24.com.
|
||||
</div>
|
||||
@elseif ($showFromBanner)
|
||||
<div class="from-banner mb-3.5">
|
||||
Ihr Konto funktioniert auch für
|
||||
<strong class="font-semibold text-ink">presseecho.de</strong>
|
||||
und
|
||||
<strong class="font-semibold text-ink">businessportal24.com</strong>.
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="auth-card">
|
||||
@if ($eyebrow)
|
||||
<div class="eyebrow-hub mb-2.5">{{ $eyebrow }}</div>
|
||||
@endif
|
||||
|
||||
@if ($heading)
|
||||
<h1 class="text-[26px] font-bold tracking-[-0.5px] leading-[1.2] m-0 mb-7 text-ink">
|
||||
{{ $heading }}
|
||||
</h1>
|
||||
@endif
|
||||
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{{-- Micro-Footer --}}
|
||||
<footer class="relative z-10 px-6 sm:px-10 pt-[18px] pb-[26px] flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 text-[11.5px] text-ink-3">
|
||||
<span>
|
||||
SSL <span class="text-ink-4 mx-2">·</span>
|
||||
Daten in DE <span class="text-ink-4 mx-2">·</span>
|
||||
2-Faktor verfügbar
|
||||
</span>
|
||||
<span class="flex flex-wrap items-center gap-x-1 gap-y-1">
|
||||
<a href="{{ route('impressum') }}" class="text-ink-3 no-underline hover:text-ink">Impressum</a>
|
||||
<span class="text-ink-4 mx-2">·</span>
|
||||
<a href="{{ route('datenschutz') }}" class="text-ink-3 no-underline hover:text-ink">Datenschutz</a>
|
||||
<span class="text-ink-4 mx-2">·</span>
|
||||
<a href="{{ route('agb') }}" class="text-ink-3 no-underline hover:text-ink">AGB</a>
|
||||
<span class="text-ink-4 mx-2">·</span>
|
||||
<a href="{{ route('hilfe') }}" class="text-ink-3 no-underline hover:text-ink">Support</a>
|
||||
</span>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
@livewireScripts
|
||||
</body>
|
||||
</html>
|
||||
64
resources/views/components/portal/hint-card.blade.php
Normal file
64
resources/views/components/portal/hint-card.blade.php
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
@props([
|
||||
/**
|
||||
* Heroicon-Name (ohne flux:icon Prefix), z.B. user, archive-box, newspaper.
|
||||
* Wird unten via flux:icon gerendert.
|
||||
*/
|
||||
'icon' => 'information-circle',
|
||||
|
||||
/** Titel (fett, dunkel) */
|
||||
'title' => '',
|
||||
|
||||
/** Vollständigkeitswert in Prozent (0–100) für die Progress-Bar */
|
||||
'percent' => null,
|
||||
|
||||
/** Ziel-URL der Aktion (Pflicht für ein klickbares Hint) */
|
||||
'href' => null,
|
||||
|
||||
/** Optionaler Action-Text — wenn null wird `action`-Slot oder „Öffnen“ verwendet */
|
||||
'action' => null,
|
||||
|
||||
/** Wenn `true`, wird das Hint als Volt-`wire:navigate`-Link gerendert */
|
||||
'navigate' => true,
|
||||
])
|
||||
|
||||
@php
|
||||
$percent = $percent !== null ? max(0, min(100, (int) $percent)) : null;
|
||||
@endphp
|
||||
|
||||
<div class="hint-card">
|
||||
<span class="hint-ico">
|
||||
<flux:icon :name="$icon" class="size-[18px]" />
|
||||
</span>
|
||||
|
||||
<div class="min-w-0">
|
||||
<div class="flex items-baseline justify-between gap-3">
|
||||
<div class="text-[13px] font-semibold leading-tight text-[color:var(--color-ink)]">
|
||||
{{ $title }}
|
||||
</div>
|
||||
|
||||
@if ($percent !== null)
|
||||
<span class="stat-meta whitespace-nowrap flex-shrink-0 text-[10px]">{{ $percent }} %</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if ($percent !== null)
|
||||
<div class="hint-bar">
|
||||
<span style="width: {{ max(2, $percent) }}%;"></span>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<p class="text-[11.5px] leading-[1.5] mt-2 m-0 text-[color:var(--color-ink-3)]">
|
||||
{{ $slot }}
|
||||
</p>
|
||||
|
||||
@if ($href)
|
||||
<a
|
||||
href="{{ $href }}"
|
||||
@if ($navigate) wire:navigate @endif
|
||||
class="hint-action"
|
||||
>
|
||||
{{ $action ?? (isset($actionSlot) ? $actionSlot : __('Öffnen')) }} →
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
37
resources/views/components/portal/stat-card.blade.php
Normal file
37
resources/views/components/portal/stat-card.blade.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
@props([
|
||||
/**
|
||||
* Strip- und Label-Farbvariante.
|
||||
* Erlaubte Werte: primary | ok | warn | muted.
|
||||
* Mockup: dev/frontend/tailwind_v3/User Dashboard presseportale.html
|
||||
*/
|
||||
'variant' => 'muted',
|
||||
|
||||
/** Eyebrow-Label oben links (UPPERCASE, sperrgesetzt) */
|
||||
'label' => '',
|
||||
|
||||
/** Hauptzahl in JetBrains Mono */
|
||||
'value' => 0,
|
||||
])
|
||||
|
||||
@php
|
||||
$allowedVariants = ['primary', 'ok', 'warn', 'muted'];
|
||||
$variant = in_array($variant, $allowedVariants, true) ? $variant : 'muted';
|
||||
@endphp
|
||||
|
||||
<article {{ $attributes->class(['stat-card', "is-{$variant}"]) }}>
|
||||
<span class="stat-strip"></span>
|
||||
|
||||
<div class="flex items-baseline justify-between gap-3">
|
||||
<div class="stat-label">{{ $label }}</div>
|
||||
|
||||
@isset($meta)
|
||||
<span class="stat-meta">{{ $meta }}</span>
|
||||
@endisset
|
||||
</div>
|
||||
|
||||
<div class="stat-num">{{ $value }}</div>
|
||||
|
||||
@isset($trend)
|
||||
<div class="stat-trend">{{ $trend }}</div>
|
||||
@endisset
|
||||
</article>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
@props([
|
||||
'brand' => 'presseportale',
|
||||
'brand' => 'pressekonto',
|
||||
'variant' => 'auto',
|
||||
'serif' => true,
|
||||
])
|
||||
|
|
@ -9,47 +9,66 @@
|
|||
* Zentrale Brand-Wortmarke für alle drei Marken der Verlags-Familie.
|
||||
*
|
||||
* Schreibweise (verbindlich):
|
||||
* - presseecho → "presse" + "echo" (echo ist die Akzentfarbe)
|
||||
* - businessportal24 → "businessportal" + "24" (24 ist orange)
|
||||
* - presseportale → "presse" + "portale" (portale ist Bernstein)
|
||||
* - presseecho → "presse" + "echo" (echo grün)
|
||||
* - businessportal24 → "businessportal" + "24" (24 orange)
|
||||
* - pressekonto → "presse" + "konto" (konto bernstein)
|
||||
*
|
||||
* Keine TLD-Endung (".de", ".com") direkt am Markennamen. Diese gehören
|
||||
* – falls überhaupt – getrennt in den juristischen Bereich (Impressum, Kontakt).
|
||||
*
|
||||
* Schriftart:
|
||||
* - Standard `font-serif` (Source Serif 4) – passt zum Editorial-Charakter
|
||||
* von Presseecho und BusinessPortal24. Der Hub lädt Source Serif 4
|
||||
* ebenfalls mit, damit Markennennungen typografisch konsistent bleiben.
|
||||
* aller drei Portale.
|
||||
* - `:serif="false"` schaltet auf font-sans (Inter Tight) – etwa für die
|
||||
* Top-Utility-Bar, in der die Marken sehr klein erscheinen.
|
||||
*
|
||||
* Variant:
|
||||
* - `auto` → Akzentfarbe = Theme-Default (Orange / Grün / Bernstein)
|
||||
* - `on-dark` → hellere/wärmere Akzentfarbe (für dunkle Hub-Panels)
|
||||
* - `mono` → Akzent identisch zum Basis-Ton (z. B. wenn beides weiß sein soll)
|
||||
* - `auto` → Name + Akzent in den Marken-Standardfarben (auf hellem Grund)
|
||||
* - `on-dark` → Name in Weiß (Negativ), Akzent in der dunkel-tauglichen Variante
|
||||
* - `mono` → Name + Akzent erben vom Parent (z. B. wenn beides weiß sein soll)
|
||||
*
|
||||
* Logo-Farben (siehe Brand-Manual):
|
||||
* - businessportal: #232A33 (auf hell) / #FFFFFF (negativ)
|
||||
* - presse (Echo): #1B2417 (auf hell) / #FFFFFF (negativ)
|
||||
* - presse (Konto): #1A2540 (auf hell) / #FFFFFF (negativ)
|
||||
* - 24: #C84A1E immer
|
||||
* - echo: #345636 (auf hell) / #9BD5B2 (negativ)
|
||||
* - konto: #B07A3A immer
|
||||
*/
|
||||
$marks = [
|
||||
'presseecho' => [
|
||||
'name' => 'presse',
|
||||
'accent' => 'echo',
|
||||
'name_color_auto' => '#1B2417',
|
||||
'name_color_on_dark' => '#FFFFFF',
|
||||
'accent_color_auto' => '#345636',
|
||||
'accent_color_on_dark' => '#9BD5B2',
|
||||
],
|
||||
'businessportal24' => [
|
||||
'name' => 'businessportal',
|
||||
'accent' => '24',
|
||||
'name_color_auto' => '#232A33',
|
||||
'name_color_on_dark' => '#FFFFFF',
|
||||
'accent_color_auto' => '#C84A1E',
|
||||
'accent_color_on_dark' => '#C84A1E',
|
||||
],
|
||||
'presseportale' => [
|
||||
'pressekonto' => [
|
||||
'name' => 'presse',
|
||||
'accent' => 'portale',
|
||||
'accent' => 'konto',
|
||||
'name_color_auto' => '#1A2540',
|
||||
'name_color_on_dark' => '#FFFFFF',
|
||||
'accent_color_auto' => '#B07A3A',
|
||||
'accent_color_on_dark' => '#B07A3A',
|
||||
],
|
||||
];
|
||||
|
||||
$mark = $marks[$brand] ?? $marks['presseportale'];
|
||||
$mark = $marks[$brand] ?? $marks['pressekonto'];
|
||||
|
||||
$nameColor = match ($variant) {
|
||||
'on-dark' => $mark['name_color_on_dark'],
|
||||
'mono' => 'inherit',
|
||||
default => $mark['name_color_auto'],
|
||||
};
|
||||
|
||||
$accentColor = match ($variant) {
|
||||
'on-dark' => $mark['accent_color_on_dark'],
|
||||
|
|
@ -62,5 +81,6 @@
|
|||
$baseAttributes = $attributes->merge(['class' => $fontClass]);
|
||||
@endphp
|
||||
|
||||
<span {{ $baseAttributes }}>{{ $mark['name'] }}<span
|
||||
<span {{ $baseAttributes }}><span
|
||||
style="color: {{ $nameColor }};">{{ $mark['name'] }}</span><span
|
||||
style="color: {{ $accentColor }};">{{ $mark['accent'] }}</span></span>
|
||||
|
|
|
|||
|
|
@ -3,19 +3,19 @@
|
|||
])
|
||||
|
||||
@php
|
||||
$themeKey = config('app.theme', 'presseportale');
|
||||
$themeKey = config('app.theme', 'pressekonto');
|
||||
$brand = $brand ?? config('domains.domains.' . $themeKey . '.brand', []);
|
||||
$brandTagline = $brand['tagline_short'] ?? 'Publisher · Hub';
|
||||
$brandTaglineLong = $brand['tagline_long'] ?? 'Der gemeinsame Publisher-Bereich für presseecho und businessportal24.';
|
||||
$footerLegal = str_replace(':year', (string) now()->year, $brand['footer_legal'] ?? '© ' . now()->year . ' presseportale');
|
||||
$footerLegal = str_replace(':year', (string) now()->year, $brand['footer_legal'] ?? '© ' . now()->year . ' pressekonto');
|
||||
@endphp
|
||||
|
||||
<footer class="bg-hub-grad-2 text-ink-on-dark">
|
||||
<div class="max-w-layout mx-auto px-8 py-14 grid gap-10" style="grid-template-columns:1.5fr 1fr 1fr 1fr;">
|
||||
|
||||
<div>
|
||||
<div class="text-[24px] font-bold leading-none tracking-[-0.5px] text-white">
|
||||
<x-web.brand-mark brand="presseportale" :serif="false" />
|
||||
<div class="text-[24px] font-bold leading-none tracking-[-0.5px]">
|
||||
<x-web.brand-mark brand="pressekonto" variant="on-dark" :serif="false" />
|
||||
</div>
|
||||
<div class="eyebrow on-dark mt-2 text-[9.5px] tracking-[0.22em]">
|
||||
{{ $brandTagline }}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@
|
|||
])
|
||||
|
||||
@php
|
||||
$themeKey = config('app.theme', 'presseportale');
|
||||
$themeKey = config('app.theme', 'pressekonto');
|
||||
$brand =
|
||||
$brand ??
|
||||
config('domains.domains.' . $themeKey . '.brand', [
|
||||
'name' => 'presse',
|
||||
'accent' => 'portale',
|
||||
'accent' => 'konto',
|
||||
'tagline_short' => 'Publisher · Hub',
|
||||
]);
|
||||
$brandTagline = $brand['tagline_short'] ?? 'Publisher · Hub';
|
||||
|
|
@ -27,9 +27,9 @@
|
|||
<div class="max-w-layout mx-auto px-8 py-[18px] grid items-center gap-6" style="grid-template-columns:auto 1fr auto;">
|
||||
|
||||
<a href="{{ route('home') }}" class="flex items-baseline gap-2.5 cursor-pointer group"
|
||||
aria-label="presseportale Startseite">
|
||||
aria-label="pressekonto Startseite">
|
||||
<span class="text-[24px] font-bold tracking-[-0.5px] leading-none text-hub">
|
||||
<x-web.brand-mark brand="presseportale" :serif="false" />
|
||||
<x-web.brand-mark brand="pressekonto" :serif="false" />
|
||||
</span>
|
||||
<span class="hidden md:inline-block w-px h-[18px] bg-bg-rule"></span>
|
||||
<span class="eyebrow muted text-[9.5px] tracking-[0.22em]">{{ $brandTagline }}</span>
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@
|
|||
<div class="max-w-layout mx-auto px-8 py-12 grid gap-10 grid-cols-1 md:grid-cols-2 lg:grid-cols-[1.4fr_1fr_1fr_1fr]">
|
||||
<div>
|
||||
<a href="{{ route('home') }}" class="block cursor-pointer group" aria-label="{{ $brandName }}{{ $brandAccent }} Startseite">
|
||||
<div class="font-serif text-[24px] font-semibold leading-none tracking-[-0.5px] text-white group-hover:text-white/80 transition-colors">
|
||||
{{ $brandName }}@if ($brandAccent)<span class="text-brand">{{ $brandAccent }}</span>@endif
|
||||
<div class="text-[24px] font-semibold leading-none tracking-[-0.5px]">
|
||||
<x-web.brand-mark :brand="$themeKey" variant="on-dark" />
|
||||
</div>
|
||||
<div class="eyebrow mt-2 text-[9.5px] tracking-[0.18em] text-ink-on-dark-muted">
|
||||
{{ $brandTagline }}
|
||||
|
|
|
|||
|
|
@ -102,8 +102,8 @@
|
|||
@keydown.escape.window="searchOpen = false">
|
||||
<div class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 py-3 lg:py-[18px] flex items-center gap-3 sm:gap-4 lg:gap-6">
|
||||
<a href="{{ route('home') }}" class="block cursor-pointer group flex-shrink-0" aria-label="{{ $brandName }}{{ $brandAccent }} Startseite">
|
||||
<div class="font-serif text-[22px] sm:text-[24px] lg:text-[28px] font-semibold leading-none tracking-[-0.5px] text-ink group-hover:text-brand transition-colors">
|
||||
{{ $brandName }}@if ($brandAccent)<span class="text-brand">{{ $brandAccent }}</span>@endif
|
||||
<div class="text-[22px] sm:text-[24px] lg:text-[28px] font-semibold leading-none tracking-[-0.5px]">
|
||||
<x-web.brand-mark :brand="$themeKey" />
|
||||
</div>
|
||||
<div class="eyebrow muted mt-1 text-[9.5px] tracking-[0.18em] hidden sm:block">
|
||||
{{ $brandTagline }}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue