diff --git a/app/Http/Controllers/Admin/SupportTicketController.php b/app/Http/Controllers/Admin/SupportTicketController.php
new file mode 100644
index 0000000..99484af
--- /dev/null
+++ b/app/Http/Controllers/Admin/SupportTicketController.php
@@ -0,0 +1,59 @@
+with('assignee')
+ ->when($request->filled('status'), fn ($q) => $q->where('status', $request->string('status')))
+ ->latest()
+ ->paginate(50)
+ ->withQueryString();
+
+ return view('admin.support.index', compact('tickets'));
+ }
+
+ public function show(SupportTicket $ticket)
+ {
+ $ticket->load(['user', 'assignee']);
+ if (auth()->user()) {
+ auth()->user()->unreadNotifications()->get()
+ ->filter(fn ($notification) => (int) ($notification->data['support_ticket_id'] ?? 0) === $ticket->id)
+ ->each->markAsRead();
+ }
+
+ return view('admin.support.show', [
+ 'ticket' => $ticket,
+ 'admins' => User::query()->where('is_admin', true)->orderBy('name')->get(['id', 'name', 'email']),
+ ]);
+ }
+
+ public function update(Request $request, SupportTicket $ticket): RedirectResponse
+ {
+ $data = $request->validate([
+ 'status' => ['required', 'in:new,open,waiting,resolved,closed'],
+ 'priority' => ['required', 'in:low,normal,high,urgent'],
+ 'assigned_to' => ['nullable', 'integer', 'exists:users,id'],
+ ]);
+
+ if ($data['assigned_to'] ?? null) {
+ abort_unless(User::whereKey($data['assigned_to'])->where('is_admin', true)->exists(), 422);
+ }
+
+ $data['resolved_at'] = in_array($data['status'], ['resolved', 'closed'], true)
+ ? ($ticket->resolved_at ?? now())
+ : null;
+ $ticket->update($data);
+
+ return back()->with('status', 'Support ticket updated.');
+ }
+}
diff --git a/app/Http/Controllers/Support/SupportController.php b/app/Http/Controllers/Support/SupportController.php
new file mode 100644
index 0000000..13e9bec
--- /dev/null
+++ b/app/Http/Controllers/Support/SupportController.php
@@ -0,0 +1,92 @@
+ [
+ 'technical' => 'Technical support',
+ 'licensing' => 'Licence & activation',
+ 'billing' => 'Billing & subscription',
+ 'feature' => 'Feature request',
+ 'privacy' => 'Privacy / data request',
+ 'general' => 'General enquiry',
+ ],
+ ]);
+ }
+
+ public function store(Request $request): RedirectResponse
+ {
+ // Honeypot: bots tend to fill hidden fields. Return success without retaining spam.
+ if (filled($request->input('company_website'))) {
+ return back()->with('status', 'Your support request has been received.');
+ }
+
+ $data = $request->validate([
+ 'name' => ['required', 'string', 'max:120'],
+ 'email' => ['required', 'email:rfc', 'max:254'],
+ 'category' => ['required', 'in:technical,licensing,billing,feature,privacy,general'],
+ 'subject' => ['required', 'string', 'max:180'],
+ 'message' => ['required', 'string', 'min:10', 'max:10000'],
+ 'privacy_notice' => ['accepted'],
+ ]);
+
+ $ticket = SupportTicket::create([
+ 'user_id' => $request->user()?->id,
+ 'reference' => $this->reference(),
+ 'name' => $data['name'],
+ 'email' => strtolower($data['email']),
+ 'category' => $data['category'],
+ 'subject' => $data['subject'],
+ 'message' => $data['message'],
+ 'privacy_notice_accepted_at' => now(),
+ ]);
+
+ $this->notifyTeam($ticket);
+
+ Mail::raw(
+ "We received your Rsync Studio support request.\n\nReference: {$ticket->reference}\nSubject: {$ticket->subject}\n\nWe will reply to this email address. Please keep the reference in any follow-up.",
+ fn ($mail) => $mail->to($ticket->email)->subject("Rsync Studio support request {$ticket->reference}")
+ );
+
+ return redirect()->route('support')->with('status', "Support request {$ticket->reference} received. A confirmation has been emailed to you.");
+ }
+
+ private function notifyTeam(SupportTicket $ticket): void
+ {
+ if (config('rsync-studio.support.notify_admin_users', true)) {
+ User::query()->where('is_admin', true)->get()->each->notify(new NewSupportTicket($ticket));
+ }
+
+ $emails = collect(config('rsync-studio.support.alert_emails', []))
+ ->filter(fn ($email) => filter_var($email, FILTER_VALIDATE_EMAIL))
+ ->unique()
+ ->values();
+
+ if ($emails->isNotEmpty()) {
+ Notification::route('mail', $emails->all())->notify(new NewSupportTicket($ticket));
+ }
+ }
+
+ private function reference(): string
+ {
+ do {
+ $reference = 'RS-'.now()->format('ymd').'-'.Str::upper(Str::random(6));
+ } while (SupportTicket::where('reference', $reference)->exists());
+
+ return $reference;
+ }
+}
diff --git a/app/Models/SupportTicket.php b/app/Models/SupportTicket.php
new file mode 100644
index 0000000..f12c556
--- /dev/null
+++ b/app/Models/SupportTicket.php
@@ -0,0 +1,39 @@
+ 'datetime',
+ 'resolved_at' => 'datetime',
+ ];
+ }
+
+ public function user(): BelongsTo { return $this->belongsTo(User::class); }
+ public function assignee(): BelongsTo { return $this->belongsTo(User::class, 'assigned_to'); }
+
+ public function prunable(): Builder
+ {
+ $days = max(30, (int) config('rsync-studio.privacy.support_retention_days', 730));
+
+ return static::query()
+ ->whereNotNull('resolved_at')
+ ->where('resolved_at', '<=', now()->subDays($days));
+ }
+}
diff --git a/app/Notifications/NewSupportTicket.php b/app/Notifications/NewSupportTicket.php
new file mode 100644
index 0000000..6f76b82
--- /dev/null
+++ b/app/Notifications/NewSupportTicket.php
@@ -0,0 +1,43 @@
+subject("New Rsync Studio support request {$this->ticket->reference}")
+ ->greeting('New support request')
+ ->line("{$this->ticket->name} <{$this->ticket->email}>")
+ ->line("Category: {$this->ticket->category}")
+ ->line("Subject: {$this->ticket->subject}")
+ ->line($this->ticket->message)
+ ->action('Open support ticket', route('admin.support.show', $this->ticket));
+ }
+
+ public function toArray(object $notifiable): array
+ {
+ return [
+ 'support_ticket_id' => $this->ticket->id,
+ 'reference' => $this->ticket->reference,
+ 'subject' => $this->ticket->subject,
+ 'email' => $this->ticket->email,
+ ];
+ }
+}
diff --git a/config/rsync-studio.php b/config/rsync-studio.php
index 9a2b2b8..54c5b73 100644
--- a/config/rsync-studio.php
+++ b/config/rsync-studio.php
@@ -10,6 +10,22 @@ return [
'purchase_url' => env('RSYNC_STUDIO_PURCHASE_URL'),
'portal_url' => env('RSYNC_STUDIO_PORTAL_URL'),
'support_url' => env('RSYNC_STUDIO_SUPPORT_URL'),
+
+ 'legal' => [
+ 'controller_name' => env('RSYNC_STUDIO_LEGAL_NAME', 'Rsync Studio'),
+ 'privacy_email' => env('RSYNC_STUDIO_PRIVACY_EMAIL', env('MAIL_FROM_ADDRESS')),
+ 'support_email' => env('RSYNC_STUDIO_SUPPORT_EMAIL', env('MAIL_FROM_ADDRESS')),
+ 'country' => env('RSYNC_STUDIO_LEGAL_COUNTRY', 'United Kingdom'),
+ ],
+ 'privacy' => [
+ 'policy_version' => env('RSYNC_STUDIO_PRIVACY_VERSION', '2026-09-09'),
+ 'cookie_version' => env('RSYNC_STUDIO_COOKIE_VERSION', '1'),
+ 'support_retention_days' => (int) env('RSYNC_STUDIO_SUPPORT_RETENTION_DAYS', 730),
+ ],
+ 'support' => [
+ 'alert_emails' => array_values(array_filter(array_map('trim', explode(',', (string) env('RSYNC_STUDIO_SUPPORT_ALERT_EMAILS', ''))))),
+ 'notify_admin_users' => filter_var(env('RSYNC_STUDIO_SUPPORT_NOTIFY_ADMINS', true), FILTER_VALIDATE_BOOL),
+ ],
'paddle' => [
'api_key' => env('PADDLE_API_KEY'),
'client_side_token' => env('PADDLE_CLIENT_SIDE_TOKEN'),
diff --git a/database/database.sqlite b/database/database.sqlite
index 3f4a46a..234116b 100644
Binary files a/database/database.sqlite and b/database/database.sqlite differ
diff --git a/database/migrations/2026_09_09_160000_create_support_tickets_and_notifications.php b/database/migrations/2026_09_09_160000_create_support_tickets_and_notifications.php
new file mode 100644
index 0000000..a6223e3
--- /dev/null
+++ b/database/migrations/2026_09_09_160000_create_support_tickets_and_notifications.php
@@ -0,0 +1,47 @@
+id();
+ $table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
+ $table->foreignId('assigned_to')->nullable()->constrained('users')->nullOnDelete();
+ $table->string('reference', 24)->unique();
+ $table->string('name', 120);
+ $table->string('email', 254)->index();
+ $table->string('category', 40)->default('general');
+ $table->string('subject', 180);
+ $table->text('message');
+ $table->string('status', 20)->default('new')->index();
+ $table->string('priority', 20)->default('normal');
+ $table->timestamp('privacy_notice_accepted_at');
+ $table->timestamp('resolved_at')->nullable()->index();
+ $table->timestamps();
+ });
+ }
+
+ if (! Schema::hasTable('notifications')) {
+ Schema::create('notifications', function (Blueprint $table): void {
+ $table->uuid('id')->primary();
+ $table->string('type');
+ $table->morphs('notifiable');
+ $table->text('data');
+ $table->timestamp('read_at')->nullable();
+ $table->timestamps();
+ });
+ }
+ }
+
+ public function down(): void
+ {
+ Schema::dropIfExists('support_tickets');
+ Schema::dropIfExists('notifications');
+ }
+};
diff --git a/resources/views/admin/index.blade.php b/resources/views/admin/index.blade.php
index 8df543f..b0e4829 100644
--- a/resources/views/admin/index.blade.php
+++ b/resources/views/admin/index.blade.php
@@ -1 +1,6 @@
-@extends('layouts.app') @section('content')
Licensing administration
{{ $licenseCount }}Licences
{{ $activeCount }}Not revoked
{{ $activationCount }}Active installations
{{ $userCount }}Portal users
Manage licences@endsection
+@extends('layouts.app')
+@section('content')
+
+{{ $licenseCount }}Licences
{{ $activeCount }}Not revoked
{{ $activationCount }}Active installations
{{ $userCount }}Portal users
+
+@endsection
diff --git a/resources/views/admin/support/index.blade.php b/resources/views/admin/support/index.blade.php
new file mode 100644
index 0000000..db55a42
--- /dev/null
+++ b/resources/views/admin/support/index.blade.php
@@ -0,0 +1,24 @@
+@extends('layouts.app', ['title' => 'Support Inbox — Rsync Studio'])
+@section('content')
+
+
+
+{{ $tickets->links() }}
+@endsection
diff --git a/resources/views/admin/support/show.blade.php b/resources/views/admin/support/show.blade.php
new file mode 100644
index 0000000..4248c64
--- /dev/null
+++ b/resources/views/admin/support/show.blade.php
@@ -0,0 +1,14 @@
+@extends('layouts.app', ['title' => $ticket->reference.' — Support'])
+@section('content')
+← Support inbox
+{{ ucfirst($ticket->status) }}
+
+
Request
{{ ucfirst($ticket->category) }}{{ $ticket->created_at->format('j M Y H:i') }}
{!! nl2br(e($ticket->message)) !!}
Reply by email
+
+
+@endsection
diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php
index eaeb291..f7b16ec 100644
--- a/resources/views/layouts/app.blade.php
+++ b/resources/views/layouts/app.blade.php
@@ -70,7 +70,7 @@
.brand img{width:34px;height:34px;border-radius:9px;box-shadow:0 5px 14px rgba(37,99,235,.25)}
.nav-links{display:flex;align-items:center;gap:22px}
.nav-links a{color:#cbd5e1;text-decoration:none;font-weight:650;font-size:14px;transition:color .16s ease}
- .nav-links a:hover{color:#fff}
+ .nav-links a:hover{color:#fff}.nav-alert-count{display:inline-flex;min-width:18px;height:18px;align-items:center;justify-content:center;margin-left:5px;padding:0 5px;border-radius:99px;background:#ef4444;color:#fff;font-size:10px;font-weight:900;vertical-align:1px}
.nav-account{margin-left:auto;display:flex;align-items:center;gap:12px;min-width:0}
.nav-email{color:#cbd5e1;font-size:13px;max-width:230px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nav-auth-link{color:#e2e8f0;text-decoration:none;font-weight:650;font-size:14px}
@@ -135,7 +135,7 @@
.portal-header{display:flex;align-items:flex-end;justify-content:space-between;gap:24px;margin-bottom:26px}.licence-list{display:grid;gap:16px}.licence-card{background:#fff;border:1px solid var(--line);border-radius:18px;box-shadow:var(--shadow-sm);overflow:hidden}.licence-card-featured{border-color:#c6d7fb}.licence-main{padding:24px 26px}.licence-title-row{display:flex;align-items:flex-start;justify-content:space-between;gap:20px}.licence-title-row h2{font-size:22px;margin:10px 0 2px;letter-spacing:-.015em}.licence-key{margin:0}.badge-row{display:flex;gap:7px;flex-wrap:wrap}.status-badge,.plan-badge,.billing-badge{display:inline-flex;align-items:center;border-radius:999px;padding:4px 9px;font-size:12px;font-weight:800}.status-active{background:var(--green-soft);color:var(--green)}.status-inactive{background:var(--red-soft);color:var(--red)}.plan-badge{background:var(--blue-soft);color:var(--blue-dark)}.billing-badge{background:#f2f4f7;color:#475467}.licence-stats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;margin:24px 0 12px;padding-top:20px;border-top:1px solid var(--line)}.licence-stats>div{display:flex;flex-direction:column;gap:3px}.stat-label{font-size:12px;color:var(--muted);font-weight:700;text-transform:uppercase;letter-spacing:.04em}.licence-stats strong{font-size:15px}.activation-meter{height:7px;background:#eef2f6;border-radius:99px;overflow:hidden}.activation-meter span{display:block;height:100%;background:var(--blue);border-radius:99px}.upgrade-strip,.subscription-warning{margin-top:20px;border-radius:12px;padding:15px 16px;display:flex;align-items:center;justify-content:space-between;gap:16px}.upgrade-strip{background:#f5f8ff;border:1px solid #dbe7ff}.upgrade-strip div{display:flex;flex-direction:column;gap:2px}.upgrade-strip span{color:#475467;font-size:14px}.subscription-warning{background:#fff7ed;border:1px solid #fed7aa}.subscription-warning p{margin:3px 0 0;color:#9a3412;font-size:13px;max-width:720px}.empty-state{background:#fff;border:1px dashed #cbd5e1;border-radius:16px;padding:44px;text-align:center}.empty-state h2{margin-top:0}.history-panel{margin-top:26px;background:#fff;border:1px solid var(--line);border-radius:14px;overflow:hidden}.history-panel summary{cursor:pointer;padding:16px 20px;font-weight:800}.history-panel summary span{display:inline-flex;margin-left:6px;min-width:22px;height:22px;align-items:center;justify-content:center;border-radius:99px;background:#f2f4f7;color:#475467;font-size:12px}.history-list{border-top:1px solid var(--line)}.history-row{display:grid;grid-template-columns:1fr auto auto;align-items:center;gap:18px;padding:14px 20px;border-bottom:1px solid var(--line)}.history-row:last-child{border-bottom:0}.history-row>div:first-child{display:flex;flex-direction:column}.history-row span{font-size:13px;color:var(--muted)}.history-status{font-size:13px;color:var(--muted)}.history-row a{font-weight:700;color:var(--blue);text-decoration:none}.back-link{display:inline-block;margin-bottom:20px;color:#475467;text-decoration:none;font-weight:700}.licence-detail-head{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;margin-bottom:24px}.licence-detail-head h1{font-size:32px}.detail-grid{display:grid;grid-template-columns:minmax(0,1.65fr) minmax(280px,.7fr);gap:18px}.panel{margin:0}.panel h2{margin:0;font-size:20px}.panel-heading{display:flex;justify-content:space-between;gap:18px;align-items:flex-start;padding-bottom:18px;border-bottom:1px solid var(--line)}.panel-heading p{margin:4px 0 0;color:var(--muted)}.activation-count{font-weight:800;background:var(--blue-soft);color:var(--blue-dark);padding:6px 10px;border-radius:999px}.device-row{display:grid;grid-template-columns:42px 1fr auto;gap:14px;align-items:center;padding:17px 0;border-bottom:1px solid var(--line)}.device-row:last-child{border-bottom:0}.device-icon{width:42px;height:42px;display:flex;align-items:center;justify-content:center;background:#f2f4f7;border-radius:10px;font-size:20px}.device-copy{display:flex;flex-direction:column;min-width:0}.device-copy span,.device-copy small{color:var(--muted)}.device-copy small{margin-top:2px}.empty-inline{padding:26px 0 4px;color:var(--muted)}.subscription-panel form+form{margin-top:10px}.subscription-facts{margin:18px 0 22px}.subscription-facts>div{display:flex;justify-content:space-between;gap:16px;padding:11px 0;border-bottom:1px solid var(--line)}.subscription-facts dt{color:var(--muted)}.subscription-facts dd{margin:0;font-weight:700;text-align:right}
- .site-footer{background:#0b1220;color:#94a3b8;border-top:1px solid rgba(255,255,255,.06)}.footer-shell{max-width:1220px;margin:0 auto;padding:34px 24px;display:flex;align-items:center;justify-content:space-between;gap:28px}.footer-brand{display:flex;align-items:center;gap:10px;color:#e2e8f0;font-weight:800}.footer-brand img{width:28px;height:28px;border-radius:7px}.footer-links{display:flex;gap:20px;flex-wrap:wrap}.footer-links a{color:#cbd5e1;text-decoration:none;font-size:13px;font-weight:650}.footer-links a:hover{color:#fff}.footer-copy{font-size:12px;margin-top:5px}
+ .site-footer{background:#0b1220;color:#94a3b8;border-top:1px solid rgba(255,255,255,.06)}.footer-shell{max-width:1220px;margin:0 auto;padding:34px 24px;display:flex;align-items:center;justify-content:space-between;gap:28px}.footer-brand{display:flex;align-items:center;gap:10px;color:#e2e8f0;font-weight:800}.footer-brand img{width:28px;height:28px;border-radius:7px}.footer-links{display:flex;gap:20px;flex-wrap:wrap}.footer-links a{color:#cbd5e1;text-decoration:none;font-size:13px;font-weight:650}.footer-links a:hover{color:#fff}.footer-cookie-link{background:none!important;border:0!important;padding:0!important;color:#cbd5e1!important;font-size:13px!important;font-weight:650!important;box-shadow:none!important}.footer-cookie-link:hover{color:#fff!important}.footer-copy{font-size:12px;margin-top:5px}
@media(max-width:980px){
.hero-grid{grid-template-columns:1fr;gap:48px}.app-window{max-width:720px;transform:none}.feature-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.workflow-grid{grid-template-columns:repeat(2,1fr)}.security-panel{grid-template-columns:1fr;gap:28px}.nav-email{display:none}
@@ -146,6 +146,24 @@
}
@media(max-width:480px){.launch-hero h1{font-size:42px}.hero-actions{flex-direction:column}.hero-actions .btn{width:100%}.app-body{grid-template-columns:1fr}.app-sidebar{display:none}.window-title{display:none}.launch-kicker{font-size:11px}.feature-card{padding:22px}}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*{transition:none!important}}
+
+
+ /* Launch polish + GDPR/support UI */
+ .launch-hero{background:linear-gradient(135deg,#07111f 0%,#0b1d36 54%,#0c2b55 100%);padding:78px 24px 82px}
+ .launch-hero:after{content:"";position:absolute;right:-10%;bottom:-36%;width:58%;height:80%;background:radial-gradient(ellipse at center,rgba(37,99,235,.45),rgba(14,165,233,.14) 42%,transparent 68%);filter:blur(18px);pointer-events:none}
+ .app-window{background:#1c1c1e;border-color:rgba(255,255,255,.14);box-shadow:0 34px 70px rgba(0,0,0,.42)}
+ .window-bar{background:#252527;border-bottom-color:#353539;color:#d4d4d8}.app-body{background:#1c1c1e}.app-sidebar{background:#252526;border-right:1px solid #39393d}.mini-brand{color:#f4f4f5}.side-item{color:#b7b7bd}.side-item.active{background:#1677ea;color:white}.app-content{background:#1c1c1e;color:#f4f4f5}.mock-job{background:#242426;border-color:#37373b;box-shadow:none}.mock-job p,.app-statusbar{color:#9f9fa6}.app-toolbar{color:#f4f4f5}.mock-progress{background:#34343a}
+ .launch-section{position:relative}.feature-card{border:1px solid rgba(148,163,184,.18);box-shadow:0 14px 34px rgba(15,23,42,.06);transition:transform .18s ease,box-shadow .18s ease}.feature-card:hover{transform:translateY(-3px);box-shadow:0 20px 42px rgba(15,23,42,.10)}
+ .feature-card:nth-child(1){background:linear-gradient(135deg,#eef7ff,#dceeff)}.feature-card:nth-child(2){background:linear-gradient(135deg,#effdf5,#d9f8e7)}.feature-card:nth-child(3){background:linear-gradient(135deg,#fff9ed,#ffedc9)}.feature-card:nth-child(4){background:linear-gradient(135deg,#f8f1ff,#eadcff)}.feature-card:nth-child(5){background:linear-gradient(135deg,#fff1f4,#ffdce4)}.feature-card:nth-child(6){background:linear-gradient(135deg,#eafffb,#ccf7ef)}
+ .feature-card:nth-child(1) .feature-icon{background:#d7ebff;color:#1474e5}.feature-card:nth-child(2) .feature-icon{background:#c9f3dc;color:#079455}.feature-card:nth-child(3) .feature-icon{background:#ffe2aa;color:#e87500}.feature-card:nth-child(4) .feature-icon{background:#dfc9ff;color:#7c3aed}.feature-card:nth-child(5) .feature-icon{background:#ffc8d4;color:#e11d48}.feature-card:nth-child(6) .feature-icon{background:#bff2e9;color:#0891b2}
+ input,select,textarea{width:100%;padding:11px 12px;border:1px solid #cbd5e1;border-radius:9px;margin:6px 0 14px;background:#fff;color:var(--text);font:inherit}textarea{resize:vertical;min-height:150px}select{appearance:auto}.field-error{color:var(--red);font-size:13px;margin:-8px 0 12px}.form-help{font-size:12px;color:var(--muted);margin:-8px 0 14px}.honeypot{position:absolute!important;left:-10000px!important;width:1px!important;height:1px!important;overflow:hidden!important}
+ .support-hero{padding:8px 0 28px}.support-hero h1{font-size:44px;line-height:1.05;letter-spacing:-.04em;margin:8px 0 12px}.support-layout{display:grid;grid-template-columns:minmax(0,1.5fr) minmax(280px,.7fr);gap:22px;align-items:start}.support-form-card{background:#fff;border:1px solid var(--line);border-radius:20px;padding:28px;box-shadow:var(--shadow-md)}.panel-heading-simple{display:flex;align-items:flex-start;justify-content:space-between;gap:20px;padding-bottom:20px;border-bottom:1px solid var(--line);margin-bottom:22px}.panel-heading-simple h2{margin:0 0 4px;font-size:23px}.panel-heading-simple p{margin:0;color:var(--muted)}.response-badge{background:var(--blue-soft);color:var(--blue-dark);padding:6px 10px;border-radius:999px;font-size:12px;font-weight:800}.form-grid.two{display:grid;grid-template-columns:1fr 1fr;gap:16px}.consent-check{display:flex;align-items:flex-start;gap:10px;font-weight:500;color:#475467;margin:2px 0 20px}.consent-check input{width:18px;height:18px;margin:2px 0 0;flex:0 0 auto}.consent-check a{color:var(--blue);font-weight:700}.support-actions{display:flex;gap:12px;flex-wrap:wrap}.support-side{display:grid;gap:14px}.support-info-card{padding:22px;border-radius:18px;border:1px solid rgba(15,23,42,.08);box-shadow:var(--shadow-sm)}.support-info-card.blue{background:linear-gradient(135deg,#eff6ff,#dbeafe)}.support-info-card.green{background:linear-gradient(135deg,#ecfdf3,#d1fadf)}.support-info-card.violet{background:linear-gradient(135deg,#f5f3ff,#ede9fe)}.support-info-card h3{margin:12px 0 6px}.support-info-card p{margin:0;color:#475467}.support-info-icon{width:40px;height:40px;border-radius:11px;background:rgba(255,255,255,.75);display:flex;align-items:center;justify-content:center;font-size:20px;font-weight:900;color:var(--blue)}
+ .legal-page{max-width:840px;margin:0 auto;background:#fff;border:1px solid var(--line);border-radius:20px;padding:42px 46px;box-shadow:var(--shadow-sm)}.legal-head{padding-bottom:24px;border-bottom:1px solid var(--line);margin-bottom:26px}.legal-head h1{font-size:42px;line-height:1.05;letter-spacing:-.04em;margin:8px 0}.legal-head p{margin:0;color:var(--muted)}.legal-intro{font-size:18px;line-height:1.65;color:#344054;background:linear-gradient(135deg,#eff6ff,#f8fafc);border:1px solid #dbeafe;border-radius:14px;padding:18px 20px;margin-bottom:30px}.legal-page section{padding:4px 0 16px}.legal-page h2{font-size:21px;margin:16px 0 8px}.legal-page p{color:#475467;line-height:1.72}.legal-page a,.link-button{color:var(--blue);font-weight:700}.link-button{padding:0;background:none;border:0;box-shadow:none;text-decoration:underline;display:inline}.link-button:hover{background:none;color:var(--blue-dark)}.legal-table,.cookie-table{display:grid;gap:10px}.legal-table>div,.cookie-table>div{display:grid;grid-template-columns:150px 1fr;gap:18px;padding:14px 0;border-bottom:1px solid var(--line)}.legal-table span,.cookie-table span{color:#475467}
+ .cookie-banner{position:fixed;z-index:1000;left:20px;right:20px;bottom:20px;max-width:980px;margin:auto;background:rgba(12,20,36,.98);color:#fff;border:1px solid rgba(255,255,255,.14);border-radius:18px;padding:20px 22px;box-shadow:0 24px 80px rgba(0,0,0,.38);backdrop-filter:blur(18px);display:none}.cookie-banner.is-open{display:block}.cookie-banner-grid{display:grid;grid-template-columns:1fr auto;gap:24px;align-items:center}.cookie-banner h2{margin:0 0 5px;font-size:18px}.cookie-banner p{margin:0;color:#cbd5e1;font-size:13px;line-height:1.55}.cookie-banner a{color:#bfdbfe}.cookie-actions{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}.cookie-actions button{padding:9px 12px}.cookie-actions .btn-secondary{background:transparent;color:#fff;border-color:rgba(255,255,255,.25)}
+ .cookie-modal-backdrop{position:fixed;z-index:1100;inset:0;background:rgba(2,6,23,.64);display:none;align-items:center;justify-content:center;padding:20px}.cookie-modal-backdrop.is-open{display:flex}.cookie-modal{width:min(620px,100%);max-height:90vh;overflow:auto;background:#fff;border-radius:20px;box-shadow:0 34px 90px rgba(0,0,0,.35)}.cookie-modal-head{padding:24px 26px 18px;border-bottom:1px solid var(--line);display:flex;justify-content:space-between;gap:18px}.cookie-modal-head h2{margin:0;font-size:24px}.cookie-close{background:#f2f4f7;color:#344054;width:36px;height:36px;padding:0;border-radius:50%}.cookie-close:hover{background:#e4e7ec}.cookie-modal-body{padding:8px 26px 4px}.cookie-option{display:grid;grid-template-columns:1fr auto;gap:18px;padding:17px 0;border-bottom:1px solid var(--line)}.cookie-option h3{margin:0 0 4px;font-size:16px}.cookie-option p{margin:0;color:var(--muted);font-size:13px}.cookie-switch{width:46px!important;height:24px!important;margin:2px 0!important;accent-color:var(--blue)}.cookie-modal-actions{padding:20px 26px 24px;display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap}.cookie-required{font-size:12px;font-weight:800;color:var(--green);padding-top:4px}
+ .admin-ticket-list{display:grid;gap:10px}.admin-ticket-row{display:grid;grid-template-columns:minmax(0,1fr) auto auto auto;gap:18px;align-items:center;padding:16px 18px;background:#fff;border:1px solid var(--line);border-radius:14px;text-decoration:none;box-shadow:var(--shadow-sm)}.admin-ticket-row:hover{border-color:#b8cdf6}.admin-ticket-row>div:first-child{display:flex;flex-direction:column;min-width:0}.admin-ticket-row small{color:var(--muted)}.ticket-ref{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--blue);font-weight:850}.ticket-category,.ticket-status{padding:5px 8px;border-radius:999px;font-size:12px;font-weight:800;background:#f2f4f7;color:#475467}.status-new{background:#eff6ff;color:#1d4ed8}.status-open{background:#ecfdf3;color:#067647}.status-waiting{background:#fff7ed;color:#9a3412}.status-resolved,.status-closed{background:#f2f4f7;color:#475467}.admin-ticket-row time{color:var(--muted);font-size:12px}.filter-bar{display:flex;align-items:center;gap:10px;margin-bottom:18px}.filter-bar select{width:auto;margin:0}.ticket-detail-head{display:flex;justify-content:space-between;align-items:flex-start;gap:20px;margin-bottom:22px}.ticket-detail-head h1{font-size:34px;line-height:1.12;letter-spacing:-.03em;margin:6px 0}.ticket-detail-head p{margin:0;color:var(--muted)}.ticket-message .ticket-meta{display:flex;gap:12px;color:var(--muted);font-size:13px;margin:8px 0 20px}.message-body{white-space:normal;background:#f8fafc;border:1px solid var(--line);border-radius:12px;padding:18px;line-height:1.7;margin-bottom:18px}
+ @media(max-width:800px){.support-layout{grid-template-columns:1fr}.form-grid.two{grid-template-columns:1fr}.legal-page{padding:28px 22px}.legal-table>div,.cookie-table>div{grid-template-columns:1fr;gap:4px}.cookie-banner-grid{grid-template-columns:1fr}.cookie-actions{justify-content:flex-start}.admin-ticket-row{grid-template-columns:1fr auto}.admin-ticket-row .ticket-category,.admin-ticket-row time{display:none}.ticket-detail-head{flex-direction:column}}
+
@stack('head')
@@ -160,9 +178,14 @@
Product
Pricing
Support
+ Privacy
@auth
@if(auth()->user()->hasVerifiedEmail())My licences@endif
- @if(auth()->user()->is_admin)Admin@endif
+ @if(auth()->user()->is_admin)
+ @php($supportUnread = auth()->user()->unreadNotifications()->where('type', \App\Notifications\NewSupportTicket::class)->count())
+ Admin
+ Support@if($supportUnread){{ $supportUnread }}@endif
+ @endif
@endauth
+
+
+
+
+
+
Your privacy choices
+
We use necessary cookies for security, sign-in and licence services. Optional cookies stay off unless you choose them. Read our Cookie Policy.
+
+
+
+
+
+
+
+
+
+
+
+ Privacy controls
Cookie settings
+
+
Necessary
Required for security, authentication, sessions and remembering this choice.
Always on
+
+
+
+
+
+
+
+
+
+