feat: Enhance UI components with improved styles and responsiveness across various views

This commit is contained in:
2026-04-22 10:56:39 -04:00
parent 8baf7d6c7d
commit 71b031ca64
14 changed files with 108 additions and 103 deletions

View File

@@ -24,7 +24,9 @@ Alpine.store('notifications', {
},
addNotification(notification) {
notification = notification[0];
// Livewire dispatches pass args as an array; unwrap if needed.
if (Array.isArray(notification)) notification = notification[0];
if (!notification || typeof notification !== 'object') return;
notification.show = false;
notification.id = Date.now() + Math.floor(Math.random() * 1000);
notification.type = notification.type || 'success';

View File

@@ -1,6 +1,6 @@
<div class="bg-background-secondary/50 bg-background-secondary/50 backdrop-blur-md grid w-full max-w-6xl mx-auto overflow-hidden text-color-base rounded-2xl shadow-2xl md:grid-cols-2" style="margin: 50px auto;">
<div class="hidden md:flex flex-col justify-between p-10 animated-gradient bg-gradient-to-br from-primary to-secondary">
<div>
<div class="bg-background-secondary/50 bg-background-secondary/50 backdrop-blur-md grid w-full max-w-6xl mx-auto overflow-hidden text-color-base rounded-2xl shadow-floating md:grid-cols-2 relative" style="margin: 50px auto;">
<div class="hidden md:flex flex-col justify-between p-10 animated-gradient bg-gradient-to-br from-primary to-secondary relative overflow-hidden noise-overlay">
<div class="relative z-10">
<div class="mt-8 text-white">
<h2 class="text-4xl font-extrabold leading-tight tracking-tight">
Manage Your Billing with Ease
@@ -11,7 +11,7 @@
</p>
</div>
</div>
<p class="text-sm text-white/70">© {{ date('Y') }} {{ config('app.name') }} | All rights reserved.</p>
<p class="text-sm text-white/70 relative z-10">© {{ date('Y') }} {{ config('app.name') }} | All rights reserved.</p>
</div>
<div class="p-8 sm:p-12 form-fade-in">

View File

@@ -1,5 +1,5 @@
<div class="bg-background-secondary/50 bg-background-secondary/50 backdrop-blur-md grid w-full max-w-6xl mx-auto overflow-hidden text-color-base rounded-2xl shadow-2xl md:grid-cols-2">
<div class="hidden md:flex flex-col justify-between p-10 animated-gradient bg-gradient-to-br from-primary to-secondary">
<div class="bg-background-secondary/50 bg-background-secondary/50 backdrop-blur-md grid w-full max-w-6xl mx-auto overflow-hidden text-color-base rounded-2xl shadow-floating md:grid-cols-2">
<div class="hidden md:flex flex-col justify-between p-10 animated-gradient bg-gradient-to-br from-primary to-secondary relative overflow-hidden noise-overlay">
<div>
<div class="mt-8 text-white">
<h2 class="text-4xl font-extrabold leading-tight tracking-tight">

View File

@@ -10,7 +10,7 @@
<div class="space-y-4">
@foreach (Auth::user()->sessions->filter(fn ($session) => !$session->impersonating()) as $session)
<div class="flex flex-col sm:flex-row items-start sm:items-center justify-between py-4 border-b border-neutral-700 last:border-b-0">
<div class="flex flex-col sm:flex-row items-start sm:items-center justify-between py-4 border-b border-neutral last:border-b-0">
<div>
<p class="text-lg font-semibold text-color-base mb-1">{{ $session->ip_address }}</p>
<p class="text-sm text-color-muted">{{ $session->formatted_device }} - {{ $session->last_activity->diffForHumans() }}</p>
@@ -65,7 +65,7 @@
<x-modal :title="__('account.two_factor_authentication_enable')" open="true">
<p class="text-color-base mb-4">{{ __('account.two_factor_authentication_enable_description') }}</p>
<div class="flex flex-col items-center mt-4 mb-6">
<img src="{{ $twoFactorData['image'] }}" alt="QR code" class="w-64 h-64 border border-neutral-700 rounded-lg p-2 bg-background-tertiary" />
<img src="{{ $twoFactorData['image'] }}" alt="QR code" class="w-64 h-64 border border-neutral rounded-lg p-2 bg-background-tertiary" />
<p class="text-color-muted mt-4 text-sm text-center font-mono break-all">
{{ __('account.two_factor_authentication_secret') }}<br />
<span class="text-color-base text-base font-bold">{{ $twoFactorData['secret'] }}</span>

View File

@@ -6,6 +6,7 @@
'trend' => null,
'icon' => null,
'href' => null,
'tone' => 'primary', // primary | success | warning | info | error | secondary
])
@php
$trendClass = match($trend) {
@@ -19,10 +20,26 @@
'down' => 'ri-arrow-down-line',
default => null,
};
$toneBg = match($tone) {
'success' => 'bg-success/10 group-hover:bg-success/20',
'warning' => 'bg-warning/10 group-hover:bg-warning/20',
'info' => 'bg-info/10 group-hover:bg-info/20',
'error' => 'bg-error/10 group-hover:bg-error/20',
'secondary' => 'bg-secondary/10 group-hover:bg-secondary/20',
default => 'bg-primary/10 group-hover:bg-primary/20',
};
$toneText = match($tone) {
'success' => 'text-success',
'warning' => 'text-warning',
'info' => 'text-info',
'error' => 'text-error',
'secondary' => 'text-secondary',
default => 'text-primary',
};
$tag = $href ? 'a' : 'div';
@endphp
<{{ $tag }} @if($href) href="{{ $href }}" wire:navigate @endif
{{ $attributes->merge(['class' => 'card-glass card-glass-hover block p-5 group']) }}>
{{ $attributes->merge(['class' => 'card-glass card-glass-hover hover-lift block p-5 group']) }}>
<div class="flex items-start justify-between gap-3">
<div class="min-w-0 flex-1">
<p class="text-xs font-semibold tracking-wider uppercase text-base/60">{{ $label }}</p>
@@ -38,7 +55,7 @@
@endif
</div>
@if($icon)
<div class="size-10 rounded-lg bg-primary/10 text-primary flex items-center justify-center shrink-0 group-hover:bg-primary/20 transition-colors">
<div class="size-10 rounded-lg {{ $toneBg }} {{ $toneText }} flex items-center justify-center shrink-0 transition-colors">
<x-dynamic-component :component="$icon" class="size-5" />
</div>
@endif

View File

@@ -107,60 +107,30 @@
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 lg:gap-6 mb-6">
@endif
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 border border-neutral/50 rounded-xl p-6 shadow-lg transform transition-all duration-300 hover:scale-[1.02] hover:shadow-xl animate-fade-in-up"
style="animation-delay: 0.1s;">
<div class="flex items-center justify-between">
<div>
<div class="bg-primary/10 text-primary p-2 rounded-full inline-flex mb-3">
<x-ri-archive-stack-fill class="size-5" />
</div>
<h3 class="text-sm font-medium text-color-muted mb-1">{{ __('dashboard.active_services') }}</h3>
<p class="text-2xl font-bold text-color-base">{{ Auth::user()->services()->where('status',
'active')->count() }}</p>
</div>
<a href="{{ route('services') }}"
class="text-primary hover:text-blue-700 transition-colors duration-300">
<x-ri-arrow-right-line class="size-5" />
</a>
</div>
</div>
<x-card.stat
:label="__('dashboard.active_services')"
:value="Auth::user()->services()->where('status', 'active')->count()"
icon="ri-archive-stack-fill"
:href="route('services')"
tone="primary"
data-tilt />
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 border border-neutral/50 rounded-xl p-6 shadow-lg transform transition-all duration-300 hover:scale-[1.02] hover:shadow-xl animate-fade-in-up"
style="animation-delay: 0.2s;">
<div class="flex items-center justify-between">
<div>
<div class="bg-orange-500/10 text-orange-500 p-2 rounded-full inline-flex mb-3">
<x-ri-receipt-fill class="size-5" />
</div>
<h3 class="text-sm font-medium text-color-muted mb-1">{{ __('dashboard.unpaid_invoices') }}</h3>
<p class="text-2xl font-bold text-color-base">{{ Auth::user()->invoices()->where('status',
'pending')->count() }}</p>
</div>
<a href="{{ route('invoices') }}"
class="text-orange-500 hover:text-orange-700 transition-colors duration-300">
<x-ri-arrow-right-line class="size-5" />
</a>
</div>
</div>
<x-card.stat
:label="__('dashboard.unpaid_invoices')"
:value="Auth::user()->invoices()->where('status', 'pending')->count()"
icon="ri-receipt-fill"
:href="route('invoices')"
tone="warning"
data-tilt />
@if(!config('settings.tickets_disabled', false))
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 border border-neutral/50 rounded-xl p-6 shadow-lg transform transition-all duration-300 hover:scale-[1.02] hover:shadow-xl animate-fade-in-up"
style="animation-delay: 0.3s;">
<div class="flex items-center justify-between">
<div>
<div class="bg-green-500/10 text-green-500 p-2 rounded-full inline-flex mb-3">
<x-ri-customer-service-fill class="size-5" />
</div>
<h3 class="text-sm font-medium text-color-muted mb-1">{{ __('dashboard.open_tickets') }}</h3>
<p class="text-2xl font-bold text-color-base">{{ Auth::user()->tickets()->where('status', '!=',
'closed')->count() }}</p>
</div>
<a href="{{ route('tickets') }}"
class="text-green-500 hover:text-green-700 transition-colors duration-300">
<x-ri-arrow-right-line class="size-5" />
</a>
</div>
</div>
<x-card.stat
:label="__('dashboard.open_tickets')"
:value="Auth::user()->tickets()->where('status', '!=', 'closed')->count()"
icon="ri-customer-service-fill"
:href="route('tickets')"
tone="info"
data-tilt />
@endif
</div>
@@ -202,13 +172,13 @@
style="animation-delay: 0.6s;">
<div class="flex items-center justify-between mb-6 border-b border-dashed border-neutral/50 pb-4">
<div class="flex items-center gap-4">
<div class="bg-orange-500/10 text-orange-500 p-3 rounded-full flex-shrink-0 shadow-md">
<div class="bg-warning/10 text-warning p-3 rounded-full flex-shrink-0 shadow-md">
<x-ri-receipt-fill class="size-6" />
</div>
<h2 class="text-2xl font-bold text-color-base">{{ __('dashboard.unpaid_invoices') }}</h2>
</div>
<span
class="bg-orange-500 text-white text-lg font-bold rounded-full size-10 flex items-center justify-center shadow-lg transform transition-transform duration-300 hover:scale-110">
class="bg-warning text-white tnum text-lg font-bold rounded-full size-10 flex items-center justify-center shadow-lg transform transition-transform duration-300 hover:scale-110">
{{ Auth::user()->invoices()->where('status', 'pending')->count() }}
</span>
</div>
@@ -308,13 +278,13 @@
style="animation-delay: 0.7s;">
<div class="flex items-center justify-between mb-6 border-b border-dashed border-neutral/50 pb-4">
<div class="flex items-center gap-3">
<div class="bg-green-500/10 text-green-500 p-2 rounded-full flex-shrink-0">
<div class="bg-info/10 text-info p-2 rounded-full flex-shrink-0">
<x-ri-customer-service-fill class="size-5" />
</div>
<h2 class="text-xl font-bold text-color-base">{{ __('dashboard.open_tickets') }}</h2>
</div>
<a href="{{ route('tickets.create') }}" wire:navigate
class="bg-green-500/10 text-green-500 p-1.5 rounded-lg hover:bg-green-500 hover:text-white transition-colors">
class="bg-info/10 text-info p-1.5 rounded-lg hover:bg-info hover:text-white transition-colors">
<x-ri-add-line class="size-5" />
</a>
</div>

View File

@@ -11,6 +11,8 @@
SECTION 1 — HERO (full viewport, always visible)
═══════════════════════════════════════════════════════════════ --}}
<section class="relative flex items-center overflow-hidden" style="min-height: calc(100dvh - var(--nav-h, 4rem));">
<!-- Depth grid overlay -->
<div class="absolute inset-0 grid-bg opacity-40 pointer-events-none"></div>
<!-- Parallax ambient blobs -->
<div class="absolute inset-0 pointer-events-none overflow-hidden">
<div class="absolute -top-40 -right-40 w-[500px] h-[500px] bg-primary/20 rounded-full blur-[120px] animate-pulse"

View File

@@ -40,18 +40,18 @@
@forelse ($invoices as $invoice)
<a href="{{ route('invoices.show', $invoice) }}" wire:navigate class="block">
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 hover:bg-secondary/25 border border-neutral/50 p-6 rounded-xl shadow-lg
transition-all duration-300 hover:scale-[1.01] hover:shadow-xl hover:border-primary/50
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 hover:bg-secondary/25 border border-neutral/50 p-6 rounded-xl shadow-lg hover-lift
transition-all duration-300 hover:shadow-xl hover:border-primary/50
flex flex-col md:flex-row items-start md:items-center justify-between gap-4">
<div class="flex items-start md:items-center gap-4 flex-grow">
<div class="bg-blue-500/10 p-3 rounded-full flex-shrink-0 shadow-sm">
<x-ri-bill-line class="size-6 text-blue-500" />
<div class="bg-primary/10 p-3 rounded-full flex-shrink-0 shadow-sm">
<x-ri-bill-line class="size-6 text-primary" />
</div>
<div class="flex flex-col">
<span class="text-xl font-bold text-color-base leading-tight">{{ __('Invoice') }} #{{ $invoice->number }}</span>
<p class="text-color-muted text-sm mt-1">
{{ __('Total') }}: <span class="font-bold text-primary">{{ $invoice->formattedTotal }}</span>
{{ __('Total') }}: <span class="font-bold tnum text-primary">{{ $invoice->formattedTotal }}</span>
<span class="mx-2 text-color-muted/50">•</span>
{{ __('invoices.invoice_date') }}: {{ $invoice->created_at->format('d M Y') }}
</p>
@@ -86,8 +86,8 @@
</a>
@empty
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 rounded-xl shadow-lg p-8 lg:p-12 border border-neutral/50 text-center group">
<div class="bg-blue-500/10 rounded-full p-6 w-fit mx-auto mb-6 transition-transform duration-300 group-hover:scale-110 empty-state-float">
<x-ri-file-list-3-line class="size-12 text-blue-500" />
<div class="bg-primary/10 rounded-full p-6 w-fit mx-auto mb-6 transition-transform duration-300 group-hover:scale-110 empty-state-float">
<x-ri-file-list-3-line class="size-12 text-primary" />
</div>
<h3 class="text-2xl font-bold text-color-base mb-3">No invoices yet</h3>
<p class="text-color-muted mb-6 max-w-md mx-auto">Your invoices will appear here once you make a purchase. Browse our products to get started.</p>

View File

@@ -1,7 +1,7 @@
<div class="space-y-4">
@foreach ($invoices as $invoice)
<a href="{{ route('invoices.show', $invoice) }}" wire:navigate>
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 border border-neutral/50 p-4 rounded-lg mb-4">
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 border border-neutral/50 p-4 rounded-lg mb-4 hover-lift">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-3">
<div class="bg-secondary/10 p-2 rounded-full">
@@ -11,7 +11,7 @@
<span class="text-base/50 font-semibold">
<x-ri-circle-fill class="size-1 text-base/20" />
</span>
<span class="text-base text-sm">{{ $invoice->formattedTotal }}</span>
<span class="text-base text-sm tnum">{{ $invoice->formattedTotal }}</span>
</div>
<div class="size-5 rounded-full p-0.5
@if ($invoice->status == 'paid') text-success bg-success/20

View File

@@ -8,8 +8,11 @@
<div class="p-6 lg:p-8">
<div class="flex items-start justify-between mb-6">
<div class="flex items-center gap-2">
<div class="size-2 bg-green-500 rounded-full animate-pulse"></div>
<span class="text-xs font-medium text-green-600 uppercase tracking-wide">Available</span>
<span class="relative flex size-2.5">
<span class="absolute inline-flex h-full w-full rounded-full bg-success opacity-60 animate-ping"></span>
<span class="relative inline-flex size-2.5 rounded-full bg-success"></span>
</span>
<span class="text-xs font-medium text-success uppercase tracking-wide">Available</span>
</div>
</div>
@@ -269,12 +272,12 @@
&& auth()->check() && empty(auth()->user()->tfa_secret)
)
{{-- TFA Required --}}
<div class="p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-xl">
<div class="flex items-center gap-2 text-red-600 dark:text-red-400">
<div class="p-4 bg-error/10 border border-error/30 rounded-xl">
<div class="flex items-center gap-2 text-error">
<x-ri-error-warning-fill class="size-5" />
<span class="font-medium">Two-Factor Authentication Required</span>
</div>
<p class="text-sm text-red-500 dark:text-red-300 mt-1">
<p class="text-sm text-error/80 mt-1">
You must enable two-factor authentication to order this product.
</p>
</div>
@@ -286,24 +289,24 @@
&& !auth()->check()
)
{{-- Login Required --}}
<div class="p-4 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-xl">
<div class="flex items-center gap-2 text-blue-600 dark:text-blue-400">
<div class="p-4 bg-info/10 border border-info/30 rounded-xl">
<div class="flex items-center gap-2 text-info">
<x-ri-information-fill class="size-5" />
<span class="font-medium">Login and Two-Factor Authentication Required</span>
</div>
<p class="text-sm text-blue-500 dark:text-blue-300 mt-1">
<p class="text-sm text-info/80 mt-1">
You must be logged in to order this product and enable two-factor authentication.
</p>
</div>
@else
{{-- Currently Unavailable --}}
<div class="p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-xl">
<div class="flex items-center gap-2 text-red-600 dark:text-red-400">
<div class="p-4 bg-error/10 border border-error/30 rounded-xl">
<div class="flex items-center gap-2 text-error">
<x-ri-error-warning-fill class="size-5" />
<span class="font-medium">Currently Unavailable</span>
</div>
<p class="text-sm text-red-500 dark:text-red-300 mt-1">
<p class="text-sm text-error/80 mt-1">
This product is currently out of stock or not available for purchase.
</p>
</div>

View File

@@ -9,11 +9,15 @@
@endif
<div class="flex flex-col gap-8">
@if ($product->stock === 0)
<span class="text-xs font-semibold px-3 py-1 rounded-full bg-red-800 text-red-100 w-fit">
<span class="text-xs font-semibold px-3 py-1 rounded-full bg-error/15 text-error border border-error/30 w-fit">
{{ __('product.out_of_stock', ['product' => $product->name]) }}
</span>
@elseif($product->stock > 0)
<span class="text-xs font-semibold px-3 py-1 rounded-full bg-green-800 text-green-100 w-fit">
<span class="inline-flex items-center gap-1.5 text-xs font-semibold px-3 py-1 rounded-full bg-success/15 text-success border border-success/30 w-fit">
<span class="relative flex size-2">
<span class="absolute inline-flex h-full w-full rounded-full bg-success opacity-60 animate-ping"></span>
<span class="relative inline-flex size-2 rounded-full bg-success"></span>
</span>
{{ __('product.in_stock') }}
</span>
@endif

View File

@@ -37,7 +37,7 @@
<div class="bg-success/10 border border-success/50 rounded-xl p-4 text-center status-card-hover">
<div class="flex items-center justify-center mb-2">
<x-ri-checkbox-circle-fill class="size-6 text-success mr-2" />
<span class="text-2xl font-bold text-success">{{ $services->where('status', 'active')->count() }}</span>
<span class="text-2xl font-bold tnum text-success">{{ $services->where('status', 'active')->count() }}</span>
</div>
<p class="text-sm font-medium text-success">{{ __('Active') }}</p>
</div>
@@ -45,23 +45,23 @@
<div class="bg-warning/10 border border-warning/50 rounded-xl p-4 text-center status-card-hover">
<div class="flex items-center justify-center mb-2">
<x-ri-error-warning-fill class="size-6 text-warning mr-2" />
<span class="text-2xl font-bold text-warning">{{ $services->where('status', 'pending')->count() }}</span>
<span class="text-2xl font-bold tnum text-warning">{{ $services->where('status', 'pending')->count() }}</span>
</div>
<p class="text-sm font-medium text-warning">{{ __('Pending') }}</p>
</div>
<div class="bg-error/10 border border-error/50 rounded-xl p-4 text-center status-card-hover">
<div class="flex items-center justify-center mb-2">
<x-ri-forbid-fill class="size-6 text-red-500 mr-2" />
<span class="text-2xl font-bold text-red-500">{{ $services->where('status', 'suspended')->count() }}</span>
<x-ri-forbid-fill class="size-6 text-error mr-2" />
<span class="text-2xl font-bold tnum text-error">{{ $services->where('status', 'suspended')->count() }}</span>
</div>
<p class="text-sm font-medium text-red-500">{{ __('Suspended') }}</p>
<p class="text-sm font-medium text-error">{{ __('Suspended') }}</p>
</div>
<div class="bg-inactive/10 border border-inactive/50 rounded-xl p-4 text-center status-card-hover">
<div class="flex items-center justify-center mb-2">
<x-ri-close-circle-fill class="size-6 text-inactive mr-2" />
<span class="text-2xl font-bold text-inactive">{{ $services->where('status', 'cancelled')->count() }}</span>
<span class="text-2xl font-bold tnum text-inactive">{{ $services->where('status', 'cancelled')->count() }}</span>
</div>
<p class="text-sm font-medium text-inactive">{{ __('Cancelled') }}</p>
</div>
@@ -86,8 +86,8 @@
@forelse ($services as $service)
<a href="{{ route('services.show', $service) }}" wire:navigate class="block">
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 hover:bg-secondary/25 border border-neutral/50 p-6 rounded-xl shadow-lg
transition-all duration-300 hover:scale-[1.02] hover:shadow-xl hover:border-primary/50
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 hover:bg-secondary/25 border border-neutral/50 p-6 rounded-xl shadow-lg hover-lift
transition-all duration-300 hover:shadow-xl hover:border-primary/50
flex flex-col md:flex-row items-start md:items-center justify-between gap-4">
<div class="flex items-start md:items-center gap-4 flex-grow">
@@ -140,7 +140,7 @@
<div class="flex items-center gap-3 flex-shrink-0 mt-3 md:mt-0">
<div class="text-sm font-semibold px-3 py-1 rounded-full flex items-center gap-1.5 transition-all duration-200
@if ($service->status == 'active') text-success bg-success/20 status-pulse
@elseif($service->status == 'suspended') text-red-500 bg-red-500/20
@elseif($service->status == 'suspended') text-error bg-error/20
@elseif($service->status == 'cancelled') text-inactive bg-inactive/20
@else text-warning bg-warning/20
@endif">

View File

@@ -1,7 +1,7 @@
<div class="space-y-4">
@foreach ($services as $service)
<a href="{{ route('services.show', $service) }}" wire:navigate>
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 border border-neutral p-4 rounded-lg mb-4">
<div class="bg-gradient-to-br from-background-secondary/50 to-background-secondary/30 border border-neutral p-4 rounded-lg mb-4 hover-lift">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-3">
<div class="bg-secondary/10 p-2 rounded-full">

View File

@@ -12,15 +12,22 @@
<div class="bg-background-secondary/50 border border-neutral p-6 rounded-xl shadow-lg mb-6">
<div class="flex flex-col gap-5 max-h-[60vh] overflow-y-auto pr-4 custom-scrollbar" wire:poll.5s>
@foreach ($ticket->messages()->with('user')->get() as $index => $message)
@php
$isMine = $message->user_id === auth()->id();
$isStaff = ! $isMine && ($message->user->role_id ?? null);
@endphp
<div
class="bg-background/10 border border-neutral/20 p-4 rounded-lg
w-full max-w-[80%] {{ $message->user_id === auth()->id() ? 'ml-auto bg-primary/10 border-primary/20' : 'mr-auto' }}
transition-all duration-200">
class="p-4 rounded-lg w-full max-w-[80%] transition-all duration-200
{{ $isMine ? 'ml-auto bg-primary/15 border border-primary/25' : 'mr-auto glass-panel' }}
{{ $isStaff ? 'border-l-2 border-l-secondary' : '' }}">
<div class="flex items-center justify-between mb-2">
<div>
<div class="flex items-center gap-2">
<h3 class="font-semibold text-color-base text-lg">{{ $message->user->name }}</h3>
<p class="text-sm text-neutral-400">{{ $message->created_at->diffForHumans() }}</p>
@if($isStaff)
<span class="text-[10px] uppercase tracking-wider font-bold px-1.5 py-0.5 rounded bg-secondary/15 text-secondary">{{ __('Staff') }}</span>
@endif
</div>
<p class="text-sm text-neutral-400">{{ $message->created_at->diffForHumans() }}</p>
</div>
<div class="mt-2 prose dark:prose-invert max-w-none text-color-base">
{!! Str::markdown(nl2br(e($message->message)), ['allow_unsafe_links' => false]) !!}