CluPilotCloud/resources/views/landing.blade.php

830 lines
53 KiB
PHP

{{--
The public front page.
Rebuilt, not recoloured the first attempt kept the old page's skeleton
(eight numbered sections, a split hero, a comparison matrix) and only
changed the palette, which is why it still read as the old site.
What the page does now, in order: show the product, say what is in it, say
how it arrives, show the evidence, answer the obvious objection, quote the
price, take the questions, and ask for the call.
--}}
<x-layouts.site
title="CluPilot Cloud — Ihre firmeneigene Cloud, betrieben und belegbar"
description="Eigene isolierte Cloud-Instanz für Kanzleien, Praxen und KMU. Serverstandort EU, tägliche verschlüsselte Sicherung mit monatlichem Wiederherstellungstest, AV-Vertrag inklusive, Betreuung auf Deutsch."
>
{{-- ════ Hero ═══════════════════════════════════════════════════════════
Centred and quiet, with the product directly underneath. The old hero
described the product beside a table of facts; a visitor had to read two
columns before seeing anything. --}}
<section class="relative overflow-hidden">
{{-- One warm bloom behind the headline, drawn as a blurred shape rather
than a radial-gradient so the colour comes from the token instead of a
literal rgba() nobody would think to update. --}}
<div class="pointer-events-none absolute -top-56 left-1/2 size-[720px] -translate-x-1/2 rounded-pill bg-accent opacity-[0.09] blur-3xl" aria-hidden="true"></div>
<div class="relative mx-auto max-w-[1120px] px-5 pt-36 text-center sm:px-6 lg:pt-44">
<a href="#security" class="lbl inline-flex items-center gap-2 rounded-pill border border-line bg-surface px-3.5 py-2 shadow-xs transition-colors hover:border-accent-border">
<span class="relative flex size-1.5">
<span class="absolute inline-flex size-full animate-ping rounded-pill bg-success-bright opacity-60"></span>
<span class="relative inline-flex size-1.5 rounded-pill bg-success-bright"></span>
</span>
Serverstandort EU · täglich gesichert · monatlich getestet
</a>
<h1 class="mx-auto mt-8 max-w-[15ch] text-[clamp(2.6rem,6.2vw,4.6rem)] font-bold leading-[1.02] tracking-[-0.04em] text-ink">
Ihre firmeneigene Cloud.
</h1>
<p class="mx-auto mt-6 max-w-[54ch] text-lg leading-relaxed text-muted">
Eine eigene, isolierte Instanz — eingerichtet, täglich gesichert und laufend überwacht.
Was wir tun, können Sie nachweisen: mit Protokoll, Prüfbericht und AV-Vertrag.
</p>
{{-- Straight to the sign-in, not to a booking page behind auth. The
difference matters: /order redirects an anonymous visitor to the
login anyway, but through a middleware redirect that leaves them on
a page they never asked for. Buying happens in the panel, where
everything already works — the website's job is to get them there.
Every path on this page used to end in "anfragen" instead: a
mailto: link and an afternoon of somebody's time per customer, for
a product whose whole point is that the machine does the work. --}}
<div class="mt-9 flex flex-wrap justify-center gap-3">
<x-ui.button href="{{ route('login') }}" variant="ink" size="lg">Jetzt buchen</x-ui.button>
<x-ui.button href="#pricing" variant="secondary" size="lg">Preise ansehen</x-ui.button>
</div>
<p class="mt-4 text-sm text-muted">Fixer Preis pro Firma · keine Abrechnung pro Kopf</p>
</div>
{{-- The product itself, cropped by the section below it. Built from the
same tokens as the real console, because it is a picture of the real
console — a mock in a different design language would be a promise the
first sign-in breaks. --}}
<div class="relative mx-auto mt-16 max-w-[1120px] px-5 sm:px-6">
<div class="overflow-hidden rounded-xl border border-line bg-surface shadow-md">
<div class="flex items-center gap-2 border-b border-line bg-surface-2 px-4 py-3">
<span class="size-2.5 rounded-pill bg-line-strong"></span>
<span class="size-2.5 rounded-pill bg-line-strong"></span>
<span class="size-2.5 rounded-pill bg-line-strong"></span>
<span class="mx-auto flex items-center gap-1.5 rounded-pill border border-line bg-surface px-3 py-1 font-mono text-xs text-muted">
<x-ui.icon name="lock" class="size-3" />cloud.kanzlei-berger.at
</span>
</div>
<div class="flex">
<aside class="hidden w-52 shrink-0 bg-plate p-3 sm:block">
<div class="flex items-center gap-2 px-2 py-2">
<span class="grid size-6 place-items-center rounded-sm bg-accent text-[11px] font-bold text-white">B</span>
<span class="text-sm font-semibold text-white">Kanzlei Berger</span>
</div>
<div class="mt-4 space-y-0.5">
@foreach ([['gauge', 'Übersicht', true], ['cloud', 'Dateien', false], ['users', 'Benutzer', false], ['shield-check', 'Sicherungen', false], ['receipt', 'Rechnungen', false]] as [$icon, $label, $active])
<span @class([
'flex items-center gap-2.5 rounded px-2.5 py-2 text-sm',
'bg-plate-2 text-white' => $active,
'text-plate-muted' => ! $active,
])>
<x-ui.icon name="{{ $icon }}" class="size-4" />{{ $label }}
</span>
@endforeach
</div>
</aside>
<div class="min-w-0 flex-1 p-5 sm:p-7">
<div class="flex flex-wrap items-center gap-3">
<h2 class="text-lg font-bold tracking-[-0.02em] text-ink">Übersicht</h2>
<span class="inline-flex items-center gap-1.5 rounded-pill border border-success-border bg-success-bg px-2.5 py-1 text-xs font-medium text-success">
<span class="size-1.5 rounded-pill bg-success-bright"></span>Alle Dienste aktiv
</span>
<span class="ml-auto font-mono text-xs text-muted">EU</span>
</div>
<div class="mt-5 grid gap-3 sm:grid-cols-3">
@foreach ([
['Speicher', '235', 'von 500 GB', 47],
['Benutzer', '8', 'von 25 Plätzen', 32],
['Verfügbarkeit', '99,98', '% letzte 30 Tage', 100],
] as [$label, $value, $sub, $fill])
<div class="rounded-lg border border-line bg-surface-2 p-4">
<p class="lbl">{{ $label }}</p>
<p class="mt-2 text-xl font-bold tabular-nums tracking-[-0.03em] text-ink">{{ $value }}</p>
<p class="text-xs text-muted">{{ $sub }}</p>
<div class="mt-3 h-1 overflow-hidden rounded-pill bg-surface-hover">
<span class="block h-full rounded-pill bg-accent" style="width: {{ $fill }}%"></span>
</div>
</div>
@endforeach
</div>
<div class="mt-4 rounded-lg border border-line">
<p class="lbl border-b border-line px-4 py-3">Heute erledigt</p>
@foreach ([
['Sicherung verschlüsselt & geprüft', '03:12'],
['Sicherheitsupdates eingespielt', '04:05'],
['8 Benutzer synchronisiert', '07:30'],
] as [$done, $when])
<div class="flex items-center gap-2.5 border-b border-line px-4 py-2.5 text-sm last:border-0">
<x-ui.icon name="check" class="size-4 shrink-0 text-success" />
<span class="truncate text-body">{{ $done }}</span>
<time class="ml-auto font-mono text-xs tabular-nums text-muted">{{ $when }}</time>
</div>
@endforeach
</div>
</div>
</div>
</div>
</div>
</section>
{{-- ════ The quiet number line ══════════════════════════════════════════ --}}
<section class="mx-auto mt-16 max-w-[1120px] px-5 sm:px-6 lg:mt-24">
<div class="flex flex-wrap items-center justify-between gap-x-10 gap-y-6 border-y border-line py-7">
@foreach ([
['99,95', '99.95', 2, '% Verfügbarkeit'],
['365', '365', 0, 'Sicherungen pro Jahr'],
['12', '12', 0, 'Wiederherstellungstests'],
['0', '0', 0, 'Termine bis zum Start'],
['0', '0', 0, 'Datenverluste'],
] as [$shown, $target, $decimals, $label])
<div class="flex items-baseline gap-2.5">
<b class="text-lg font-bold tabular-nums tracking-[-0.02em] text-ink" data-count="{{ $target }}" data-decimals="{{ $decimals }}">{{ $shown }}</b>
<span class="text-sm text-muted">{{ $label }}</span>
</div>
@endforeach
</div>
</section>
{{-- ════ What is in it — one asymmetric grid ════════════════════════════
Six equal cards in two rows was the old page's answer to every section.
Tiles of different weight let the important thing be bigger than the rest,
which is the whole point of having a layout. --}}
<section id="product" class="mx-auto max-w-[1120px] px-5 py-24 sm:px-6 lg:py-32">
<div class="rv max-w-[46ch]">
<p class="lbl !text-accent-text">Was enthalten ist</p>
<h2 class="mt-3 text-[clamp(2rem,4vw,3.1rem)] font-bold leading-[1.06] tracking-[-0.035em] text-ink">
Für Ihr Team ist es firmeneigene Software. Wir betreiben sie nur.
</h2>
</div>
<div class="mt-12 grid gap-4 lg:grid-cols-3">
<div class="rv flex flex-col justify-between rounded-xl border border-line bg-surface p-7 shadow-xs lg:col-span-2 lg:row-span-2 lg:p-9">
<div>
<x-ui.icon name="globe" class="size-6 text-accent-text" />
<h3 class="mt-5 max-w-[18ch] text-xl font-bold tracking-[-0.025em] text-ink">Ihre Adresse, Ihr Logo, Ihre Ordnerstruktur.</h3>
<p class="mt-3 max-w-[52ch] text-sm leading-relaxed text-muted">
Eigene Domain, eigenes Erscheinungsbild, und eine Ablage, die nach Branchenvorlage
schon steht, bevor die erste Datei hochgeladen wird.
</p>
</div>
<div class="mt-8 grid gap-2 sm:grid-cols-2">
@foreach ([
['cloud', 'Dateien &amp; Synchronisation'],
['file-text', 'Office im Browser'],
['calendar', 'Kalender, Kontakte, Aufgaben'],
['users', 'Videokonferenz &amp; Chat'],
['external-link', 'Freigabelinks mit Ablauf'],
['rotate-ccw', 'Versionierung &amp; Papierkorb'],
] as [$icon, $feature])
<div class="flex items-center gap-2.5 rounded-lg bg-surface-2 px-3.5 py-3 text-sm text-body">
<x-ui.icon name="{{ $icon }}" class="size-4 shrink-0 text-muted" />{!! $feature !!}
</div>
@endforeach
</div>
</div>
<div class="rv d1 rounded-xl border border-line bg-plate p-7 text-plate-text shadow-xs">
<x-ui.icon name="shield-check" class="size-6 text-accent" />
<h3 class="mt-5 text-lg font-bold tracking-[-0.02em] text-white">Getrennt von allen anderen.</h3>
<p class="mt-3 text-sm leading-relaxed text-plate-muted">
Eine eigene virtuelle Maschine je Kunde. Keine geteilte Datenbank, kein gemeinsamer Speicher.
</p>
<dl class="mt-6 space-y-2.5 border-t border-plate-rule pt-5 font-mono text-xs">
@foreach (['Instanz' => 'dediziert', 'Standort' => 'EU', 'Transfer' => 'kein Drittland'] as $k => $v)
<div class="flex justify-between"><dt class="text-plate-muted">{{ $k }}</dt><dd class="text-white">{{ $v }}</dd></div>
@endforeach
</dl>
</div>
<div class="rv d2 rounded-xl border border-accent-border bg-accent-subtle p-7 shadow-xs">
<x-ui.icon name="tag" class="size-6 text-accent-text" />
<h3 class="mt-5 text-lg font-bold tracking-[-0.02em] text-ink">Ein Preis. Für die Firma.</h3>
<p class="mt-3 text-sm leading-relaxed text-body">
Kein Aufpreis für die vierzehnte Kollegin. Wächst das Team, bleibt die Rechnung gleich.
</p>
</div>
<div class="rv rounded-xl border border-line bg-surface p-7 shadow-xs lg:col-span-2">
<div class="flex flex-wrap items-baseline gap-x-3 gap-y-1">
<x-ui.icon name="plus" class="size-5 text-accent-text" />
<h3 class="text-lg font-bold tracking-[-0.02em] text-ink">Zubuchbare Module</h3>
<span class="text-sm text-muted">jederzeit, ohne Umzug</span>
</div>
<div class="mt-5 grid gap-3 sm:grid-cols-3">
@foreach ([
['Vaultwarden', 'Team-Passwörter', true],
['Paperless-ngx', 'Dokumentenarchiv', true],
['Digitale Signatur', 'in Vorbereitung', false],
] as [$module, $what, $ready])
<div class="rounded-lg border border-line bg-surface-2 px-4 py-3.5">
<b class="block text-sm font-semibold text-ink">{{ $module }}</b>
<span class="text-xs {{ $ready ? 'text-muted' : 'text-warning' }}">{{ $what }}</span>
</div>
@endforeach
</div>
</div>
<div class="rv d1 flex flex-col rounded-xl border border-line bg-surface p-7 shadow-xs">
<x-ui.icon name="life-buoy" class="size-6 text-accent-text" />
<h3 class="mt-5 text-lg font-bold tracking-[-0.02em] text-ink">Jemand, den Sie anrufen.</h3>
<p class="mt-3 flex-1 text-sm leading-relaxed text-muted">
Auf Deutsch, mit Antwort am selben Werktag. Kein Callcenter, keine Warteschleife.
</p>
</div>
</div>
{{-- The industries, dense. Six cards saying almost the same thing was
repetition; what a visitor actually looks for is their own trade. --}}
<div class="rv mt-4 overflow-hidden rounded-xl border border-line bg-surface shadow-xs">
<div class="flex flex-wrap items-baseline gap-x-3 gap-y-1 border-b border-line px-7 py-5">
<h3 class="text-lg font-bold tracking-[-0.02em] text-ink">Ordnerstruktur nach Branchenvorlage</h3>
<span class="text-sm text-muted">ab dem ersten Tag, änderbar</span>
</div>
<div class="grid sm:grid-cols-2">
@foreach ([
['Steuerberatung', 'Mandanten / Jahresabschluss / Belege'],
['Rechtsanwälte', 'Akten / Schriftsätze / Fristen'],
['Ärzte &amp; Therapeuten', 'Verwaltung / Befunde / Abrechnung'],
['Architektur &amp; Planung', 'Projekte / Pläne / Freigaben'],
['Handwerk &amp; Bau', 'Baustellen / Aufmaß / Abnahme'],
['Immobilienverwaltung', 'Objekte / Verträge / Abrechnung'],
] as $i => [$trade, $template])
<div class="flex flex-wrap items-baseline gap-x-4 gap-y-1 border-b border-line px-7 py-4 sm:odd:border-r">
<b class="text-sm font-semibold text-ink">{!! $trade !!}</b>
<span class="font-mono text-xs text-muted">{{ $template }}</span>
</div>
@endforeach
</div>
</div>
</section>
{{-- ════ The dark hinge how it arrives ════════════════════════════════ --}}
<section id="process" class="bg-plate py-24 text-plate-text lg:py-32">
<div class="mx-auto max-w-[1120px] px-5 sm:px-6">
{{-- No clock anywhere in this section any more.
"In 20 Minuten betriebsbereit", a log with minute marks down the
side, "betriebsbereit in unter 20 Minuten" three promises about
a duration nobody controls. A provisioning run waits on a
hypervisor, on a certificate authority and on DNS propagating;
when it is done it is done, and a customer who once waited
forty minutes has been told something untrue by their supplier.
What replaces it is the thing that IS promised and IS kept: the
order of the steps, and a message when it is ready. Nobody has to
sit and watch. --}}
<div class="rv max-w-[46ch]">
<p class="lbl !text-accent">Ohne Termin, ohne Warten</p>
<h2 class="mt-3 text-[clamp(2rem,4vw,3.1rem)] font-bold leading-[1.06] tracking-[-0.035em] text-white">
Nur der erste Schritt ist Ihrer.
</h2>
</div>
<div class="mt-14 grid gap-12 lg:grid-cols-[.85fr_1.15fr] lg:gap-16">
<ol class="rv space-y-8">
@foreach ([
['Sie', 'Paket wählen', 'Ein Formular online. Unmittelbar danach beginnt die Instanz von selbst zu entstehen — Sie müssen nichts weiter tun und auf nichts warten.'],
['Wir', 'Einrichtung', 'Benutzer und Rechte, Ordnerstruktur, Ihr Logo, Ihre Domain. Auf Wunsch übernehmen wir Bestandsdaten aus Dropbox, OneDrive oder vom alten Server — mit schriftlichem Übernahmeprotokoll.'],
['Gemeinsam', 'Einschulung', '45 Minuten für Ihr Team per Videokonferenz, Kurzanleitung als PDF mit Ihren eigenen Screenshots.'],
] as $i => [$who, $what, $body])
<li class="relative pl-14">
<span class="absolute left-0 top-0 grid size-10 place-items-center rounded-pill border border-plate-rule bg-plate-2 font-mono text-sm font-medium text-accent">{{ $i + 1 }}</span>
@if ($i < 2)
<span class="absolute bottom-[-2rem] left-5 top-12 w-px bg-plate-rule"></span>
@endif
<span class="lbl !text-plate-muted">{{ $who }}</span>
<h3 class="mt-1 text-lg font-bold tracking-[-0.02em] text-white">{{ $what }}</h3>
<p class="mt-2 max-w-[46ch] text-sm leading-relaxed text-plate-muted">{{ $body }}</p>
</li>
@endforeach
</ol>
{{-- self-start: a grid cell stretches by default, and the empty
dark space under the last line reads as a panel that failed to
load rather than as breathing room. --}}
<div id="deploy-log" class="self-start overflow-hidden rounded-xl border border-plate-rule bg-plate-2">
<div class="flex items-center justify-between border-b border-plate-rule px-5 py-3.5">
<span class="lbl !text-plate-muted">Bereitstellungsprotokoll</span>
<span class="rounded-sm bg-plate px-2 py-0.5 font-mono text-xs text-plate-muted">Beispiel</span>
</div>
{{-- The steps in order, ticked as they pass. The column that
held minute marks now holds a number: WHAT happens and in
which order is a promise that can be kept. --}}
@foreach ([
'Instanz erstellt und gestartet',
'Verschlüsselung und Firewall aktiv',
'Domain verbunden, Zertifikat ausgestellt',
'Erste Sicherung angelegt und geprüft',
'Logo und Farben hinterlegt',
] as $i => $what)
<div class="logline flex items-center gap-4 border-b border-plate-rule px-5 py-3.5 text-sm">
<span class="grid size-5 shrink-0 place-items-center rounded-pill bg-success-bright/15">
<x-ui.icon name="check" class="size-3 text-success-bright" />
</span>
<span class="min-w-0 flex-1 truncate text-plate-text">{{ $what }}</span>
<span class="shrink-0 font-mono text-xs text-plate-muted">{{ $i + 1 }}/5</span>
</div>
@endforeach
<div class="flex items-start gap-2.5 px-5 py-4">
<x-ui.icon name="mail" class="mt-0.5 size-4 shrink-0 text-accent" />
<p class="text-sm leading-relaxed text-white">
Fertig. Sie bekommen eine E-Mail mit Adresse und Zugangsdaten,
<span class="text-plate-muted">sobald Ihre Cloud bereit ist Sie müssen nicht danebensitzen.</span>
</p>
</div>
</div>
</div>
</div>
</section>
{{-- ════ Evidence ═══════════════════════════════════════════════════════
A three-column table was the old page's version of this. What a visitor
needs from it is the pairing — measure, rhythm, and the piece of paper
they can hand to somebody — so the pairing is what the row shows. --}}
<section id="security" class="mx-auto max-w-[1120px] px-5 py-24 sm:px-6 lg:py-32">
<div class="rv max-w-[46ch]">
<p class="lbl !text-accent-text">Sicherheit &amp; Nachweis</p>
<h2 class="mt-3 text-[clamp(2rem,4vw,3.1rem)] font-bold leading-[1.06] tracking-[-0.035em] text-ink">
Jede Maßnahme hat einen Nachweis.
</h2>
<p class="mt-5 text-md leading-relaxed text-muted">
Sie bekommen sie schriftlich — für Ihre eigene Dokumentation, Ihre Prüfung, Ihre Versicherung.
</p>
</div>
<div class="rv mt-12 overflow-hidden rounded-xl border border-line bg-surface shadow-xs">
@foreach ([
['shield', 'Eigene isolierte Instanz', 'Eine virtuelle Maschine je Kunde, strikt getrennt von allen anderen.', 'dauerhaft', 'Instanzkennung im Kundenbereich'],
['database', 'Verschlüsselte Sicherung', 'Clientseitig verschlüsselt, getrennt vom Produktivsystem gelagert.', 'täglich', 'Sicherungsprotokoll mit Zeitstempel'],
['rotate-ccw', 'Wiederherstellungstest', 'Eine Sicherung wird tatsächlich zurückgespielt nicht nur geprüft.', 'monatlich', 'Testbericht mit Ergebnis'],
['refresh', 'Sicherheitsupdates', 'Betriebssystem und Anwendung, eingespielt außerhalb Ihrer Arbeitszeit.', 'laufend', 'Wartungsprotokoll'],
['activity', 'Überwachung', 'Erreichbarkeit, Speicher und Dienste Alarm, bevor Sie es merken.', 'rund um die Uhr', 'Verfügbarkeitsbericht'],
['globe', 'Serverstandort EU', 'Kein Transfer in Drittländer, keine Abhängigkeit von US-Anbietern.', 'vertraglich', 'AV-Vertrag &amp; TOM-Dokumentation'],
] as [$icon, $measure, $detail, $rhythm, $proof])
<div class="grid items-start gap-x-6 gap-y-3 border-b border-line p-6 last:border-0 hover:bg-surface-2 lg:grid-cols-[1.6fr_.5fr_1fr] lg:p-7">
<div class="flex gap-4">
<x-ui.icon name="{{ $icon }}" class="mt-0.5 size-5 shrink-0 text-accent-text" />
<div>
<b class="block font-semibold text-ink">{{ $measure }}</b>
<span class="mt-1 block max-w-[46ch] text-sm leading-relaxed text-muted">{{ $detail }}</span>
</div>
</div>
<div class="pl-9 lg:pl-0">
<span class="inline-block rounded-pill bg-surface-2 px-3 py-1 font-mono text-xs text-body">{{ $rhythm }}</span>
</div>
<div class="flex items-center gap-2 pl-9 text-sm text-body lg:pl-0">
<x-ui.icon name="file-text" class="size-4 shrink-0 text-muted" />{!! $proof !!}
</div>
</div>
@endforeach
</div>
{{-- The other half of "Sicherheit", and the half somebody looks for after
they have already clicked something. It was only in the footer, in the
mail footers and under the sign-in form — none of which is where a
person goes when they think "is this really them?". They go to the
section called Sicherheit. --}}
<a href="{{ route('security') }}" class="rv mt-6 flex flex-wrap items-center gap-x-3 gap-y-1 rounded-xl border border-line bg-surface px-6 py-5 shadow-xs transition-colors hover:border-accent-border">
<x-ui.icon name="shield-check" class="size-5 shrink-0 text-accent-text" />
<b class="font-semibold text-ink">Echte Adressen erkennen</b>
<span class="text-sm text-muted">Welche Domains uns gehören — und was zu tun ist, wenn Sie Ihr Passwort woanders eingegeben haben.</span>
<x-ui.icon name="external-link" class="ml-auto size-4 shrink-0 text-muted" />
</a>
</section>
{{-- ════ The objection ══════════════════════════════════════════════════ --}}
<section class="border-y border-line bg-surface-2 py-24 lg:py-32">
<div class="mx-auto max-w-[1120px] px-5 sm:px-6">
<div class="rv max-w-[46ch]">
<p class="lbl !text-accent-text">Der ehrliche Vergleich</p>
<h2 class="mt-3 text-[clamp(2rem,4vw,3.1rem)] font-bold leading-[1.06] tracking-[-0.035em] text-ink">
Warum nicht einfach …?
</h2>
<p class="mt-5 text-md leading-relaxed text-muted">
Berechtigte Frage — samt der Punkte, die gegen uns sprechen.
</p>
</div>
<div class="mt-12 grid items-start gap-4 lg:grid-cols-3">
@foreach ([
['Bei der US-Cloud bleiben', 'Dropbox, OneDrive & Co.', false, [
[true, 'Bequem und sofort verfügbar'],
[false, 'Daten bei US-Konzernen Drittlandtransfer als Dauerthema Ihrer Dokumentation'],
[false, 'Preis pro Kopf: Jeder neue Mitarbeiter erhöht die Rechnung'],
[false, 'Support über ein Ticketsystem in Übersee'],
]],
['Einen eigenen Server', 'Selbst betreiben', false, [
[true, 'Volle Kontrolle über alles'],
[false, 'Updates, Sicherung und Ausfälle sind Ihr Problem auch am Wochenende'],
[false, 'Braucht dauerhaft echtes IT-Wissen im Haus'],
[false, 'Ein vergessenes Update kann sehr teuer werden'],
]],
['CluPilot Cloud', 'Ihre Cloud, von uns betrieben', true, [
[true, 'Eigene isolierte Instanz, Standort EU, AV-Vertrag inklusive'],
[true, 'Fixer Firmenpreis, unabhängig von der Kopfzahl'],
[true, 'Betrieb, Sicherung und Überwachung nachweislich durch uns'],
{{-- With the figure, and only while there is one. An
installation that charges no setup fee must not carry a
card admitting to a cost it does not have. --}}
...($setup ? [[false, 'Einrichtung kostet einmalig '.$setup['gross'].' wir richten wirklich ein, statt nur freizuschalten']] : []),
]],
] as $i => [$option, $subtitle, $ours, $points])
<div @class([
'rv rounded-xl border p-7',
'd'.$i,
'border-ink bg-surface shadow-md lg:-mt-4 lg:pb-9 lg:pt-9' => $ours,
'border-line bg-surface/60' => ! $ours,
])>
<div class="flex items-center gap-2.5">
<h3 class="text-md font-bold tracking-[-0.02em] text-ink">{{ $option }}</h3>
@if ($ours)
<span class="rounded-pill bg-accent-active px-2 py-0.5 font-mono text-[10px] font-medium uppercase tracking-[0.07em] text-on-accent">Wir</span>
@endif
</div>
<span class="lbl mt-1 block">{{ $subtitle }}</span>
<ul class="mt-6 space-y-3.5">
@foreach ($points as [$good, $point])
<li class="flex gap-2.5 text-sm leading-relaxed {{ $ours ? 'text-body' : 'text-muted' }}">
<x-ui.icon name="{{ $good ? 'check' : 'x' }}" class="mt-0.5 size-4 shrink-0 {{ $good ? 'text-success' : 'text-danger' }}" />
{{ $point }}
</li>
@endforeach
</ul>
</div>
@endforeach
</div>
</div>
</section>
{{-- ════ Price ══════════════════════════════════════════════════════════
Cards, with the matrix folded away underneath. The matrix was the first
thing a visitor met on the old page: twelve rows of ticks before a single
price was legible. --}}
{{-- Wider than the rest of the page, and only here. Four packages side by
side in 1120px left each card 202px of text — narrow enough that
"Bereitstellung in 2-3 Werktagen" broke over two lines and every card
looked crammed against its neighbours. The reading columns elsewhere are
narrow on purpose; a price sheet is four columns that must be comparable
at a glance, which is a different problem. --}}
<section id="pricing" class="mx-auto max-w-[1240px] px-5 py-24 sm:px-6 lg:py-32">
<div class="rv mx-auto max-w-[46ch] text-center">
<p class="lbl !text-accent-text">Preise</p>
<h2 class="mt-3 text-[clamp(2rem,4vw,3.1rem)] font-bold leading-[1.06] tracking-[-0.035em] text-ink">
Ein fixer Preis pro Firma.
</h2>
<p class="mt-5 text-md leading-relaxed text-muted">
Alle Preise inklusive {{ $vat['label'] }} % Umsatzsteuer. Keine Staffelung nach Benutzern,
keine Nachverrechnung bei Zuwachs.
</p>
{{-- Said once, here, rather than as a footnote per card: a consumer must
never be quoted a figure that grows at checkout, and a business
needs to know the net one is on the invoice. --}}
<p class="mt-2 text-sm text-muted">
Als Unternehmen ziehen Sie die Umsatzsteuer über die Rechnung wieder ab — den Nettobetrag
finden Sie unter jedem Preis.
</p>
</div>
@if (empty($plans))
{{-- The catalogue could not be read. Showing a number we might not
honour would be worse than showing none. --}}
<div class="rv mx-auto mt-12 max-w-[640px] rounded-xl border border-line bg-surface p-10 text-center shadow-xs">
<h3 class="text-lg font-bold text-ink">Preise derzeit auf Anfrage</h3>
<p class="mx-auto mt-3 max-w-[52ch] text-sm leading-relaxed text-muted">
Die Paketübersicht steht gerade nicht zur Verfügung. Wir nennen Ihnen die aktuellen Konditionen gerne direkt.
</p>
<x-ui.button href="#contact" variant="ink" size="lg" class="mt-7">Preise anfragen</x-ui.button>
{{-- Still "anfragen" here, and only here: with no catalogue there is
nothing to put in a checkout. --}}
</div>
@else
@php
// Written out rather than interpolated: Tailwind builds its
// stylesheet by reading these files as text, so a class name
// assembled at render time is a class name that was never compiled.
$planColumns = ['lg:grid-cols-1', 'lg:grid-cols-2', 'lg:grid-cols-3', 'lg:grid-cols-4'][min(count($plans), 4) - 1];
@endphp
{{-- Stretched, not items-start: the cards carry different numbers of
features, and four "anfragen" buttons at four different heights is
the first thing the eye picks up on a price sheet. --}}
<div class="mt-14 grid gap-5 sm:grid-cols-2 lg:gap-6 {{ $planColumns }}">
@foreach ($plans as $i => $plan)
<div @class([
'rv flex flex-col rounded-xl border p-7',
'd'.($i % 3),
'border-ink bg-surface shadow-md lg:-mt-5 lg:pb-9 lg:pt-9' => $plan['recommended'],
'border-line bg-surface shadow-xs' => ! $plan['recommended'],
])>
<div class="flex items-center gap-2">
<h3 class="text-md font-bold tracking-[-0.02em] text-ink">{{ $plan['name'] }}</h3>
@if ($plan['recommended'])
<span class="rounded-pill bg-accent-active px-2 py-0.5 font-mono text-[10px] font-medium uppercase tracking-[0.07em] text-on-accent">Empfohlen</span>
@endif
</div>
{{-- A plan can exist before its copy is written — the empty
string renders nothing rather than an empty paragraph
with margin above it and nothing in it. --}}
@if ($plan['audience'])
<p class="mt-1 text-sm text-muted">{{ $plan['audience'] }}</p>
@endif
<p class="mt-6 flex items-baseline gap-1.5">
<span class="text-[2.4rem] font-bold leading-none tabular-nums tracking-[-0.04em] text-ink">{{ $plan['price'] }}</span>
<span class="text-sm text-muted">/Monat</span>
</p>
{{-- The net figure under the gross one, not instead of it.
A private customer pays what is written large; a
business needs the other number for its books, and
printing only one of the two was wrong for one of the
two readers whichever we picked. --}}
<p class="mt-1.5 text-xs text-muted">
inkl. {{ $vat['label'] }} % MwSt. · netto {{ $plan['price_net'] }}
</p>
{{-- Named, or not mentioned. "zzgl. einmaliger Einrichtung"
without a figure told a visitor only that there is a
cost — the worst of both. Zero on the Finance page
removes the line entirely. --}}
@if ($setup)
<p class="mt-1 text-xs text-muted">
zzgl. Einrichtung einmalig {{ $setup['gross'] }}
</p>
@endif
{{-- Read from the estate, not written down: where a host has
room this rolls out on its own, and where none has, a
machine has to be bought first. Saying "sofort" in that
second case is a promise the buyer catches us breaking
on day one. --}}
<x-ui.delivery :state="$plan['delivery']" class="mt-4" />
<dl class="mt-6 space-y-2 border-y border-line py-5 text-sm">
@foreach ([
'Speicher' => $plan['storage'],
'Datenvolumen' => $plan['traffic'],
'Benutzer' => 'bis '.$plan['seats'],
] as $term => $value)
<div class="flex justify-between gap-4">
<dt class="text-muted">{{ $term }}</dt>
<dd class="font-mono tabular-nums text-ink">{{ $value }}</dd>
</div>
@endforeach
</dl>
{{-- Six, then a pointer to the table. A card listing eleven
features is a table with worse alignment. --}}
<ul class="mt-5 flex-1 space-y-2.5 text-sm">
@foreach (array_slice($plan['features'], 0, 6) as $feature)
<li class="flex gap-2.5 text-body">
<x-ui.icon name="check" class="mt-0.5 size-4 shrink-0 text-success" />{{ $feature }}
</li>
@endforeach
@if (count($plan['features']) > 6)
<li class="pl-[26px] text-muted">und {{ count($plan['features']) - 6 }} weitere Merkmale</li>
@endif
</ul>
{{-- To the sign-in, not to an inbox. Booking happens in the
panel: the account has to exist and its address has to
be confirmed before money moves, because that address is
where the finished cloud's credentials are sent. --}}
<x-ui.button href="{{ route('login') }}" :variant="$plan['recommended'] ? 'ink' : 'secondary'" class="mt-7 w-full">
{{ $plan['name'] }} buchen
</x-ui.button>
</div>
@endforeach
</div>
{{-- The baseline, said once and said first. Four of these were rows of
ticks running straight down every column of the table below, and
the same promises were repeated in a prose line under it a
visitor read the comparison twice to learn the two places where it
compared nothing. The address is shown as the address, not as the
phrase "eigene Subdomain": what is worth knowing about it is its
shape. --}}
<div class="rv mt-12 overflow-hidden rounded-xl border border-line bg-surface shadow-xs">
<div class="flex flex-wrap items-baseline gap-x-3 gap-y-1 border-b border-line px-7 py-5">
<h3 class="text-lg font-bold tracking-[-0.02em] text-ink">In jedem Paket enthalten</h3>
<span class="text-sm text-muted">ohne Aufpreis, ab dem ersten Tag</span>
</div>
<div class="grid sm:grid-cols-2">
@foreach ($baseline as $item)
<div class="flex gap-3.5 border-b border-line px-7 py-5 sm:odd:border-r">
<x-ui.icon name="{{ $item['icon'] }}" class="mt-0.5 size-4 text-accent-text" />
<div class="min-w-0">
<b class="block text-sm font-semibold text-ink">{{ $item['label'] }}</b>
<span @class([
'mt-1 block text-xs leading-relaxed text-muted',
'font-mono' => $item['mono'] ?? false,
])>{{ $item['detail'] }}</span>
</div>
</div>
@endforeach
</div>
</div>
{{-- Only what differs, and three answers instead of two. A dash used to
mean both "you cannot have this" and "you can have this for nine
euros", which is how a page that sells five modules came to mention
none of them. --}}
@if (! empty($comparison))
<details class="faq rv group mt-4 overflow-hidden rounded-xl border border-line bg-surface shadow-xs">
<summary class="flex min-h-14 items-center gap-4 px-6 py-4 text-sm font-medium text-ink transition-colors hover:bg-surface-hover">
Was die Pakete unterscheidet
<x-ui.icon name="chevron-down" class="ml-auto size-4 shrink-0 text-muted transition-transform duration-200 group-open:rotate-180" />
</summary>
{{-- The table keeps its own scroll. Four columns of prose cells
do not fit a phone, and a page that scrolls sideways as a
whole loses its header and its margins with it. --}}
<div class="overflow-x-auto border-t border-line">
<table class="w-full min-w-[720px] border-collapse text-left text-sm">
<caption class="sr-only">Was die Pakete unterscheidet</caption>
<thead>
<tr class="border-b border-line">
<th scope="col" class="px-6 py-4"><span class="sr-only">Merkmal</span></th>
@foreach ($plans as $plan)
<th scope="col" class="px-6 py-4 font-semibold text-ink">{{ $plan['name'] }}</th>
@endforeach
</tr>
</thead>
<tbody>
@foreach ($comparison as $row)
<tr class="border-b border-line last:border-0">
<th scope="row" class="px-6 py-3.5 font-medium text-muted">{{ $row['label'] }}</th>
@foreach ($plans as $plan)
@php($cell = $row['cells'][$plan['key']] ?? ['state' => 'absent'])
<td class="px-6 py-3.5 align-top">
@switch($cell['state'])
@case('included')
<span class="inline-flex items-center gap-2 text-body">
<x-ui.icon name="check" class="size-4 text-success" />inklusive
</span>
@break
@case('optional')
<span class="inline-flex items-center gap-1.5 rounded-pill border border-accent-border bg-accent-subtle px-2.5 py-1 text-xs font-medium text-accent-text">
<x-ui.icon name="plus" class="size-3.5" />optional · {{ $cell['price'] }}
</span>
@break
@case('level')
<span class="block font-medium text-ink">{{ $cell['text'] }}</span>
@if ($cell['note'])
<span class="mt-0.5 block text-xs text-muted">{{ $cell['note'] }}</span>
@endif
@break
@default
<span class="text-faint" aria-label="nicht enthalten"></span>
@endswitch
</td>
@endforeach
</tr>
@endforeach
</tbody>
</table>
</div>
<p class="border-t border-line px-6 py-4 text-xs leading-relaxed text-muted">
„optional“ heißt: in diesem Paket nicht enthalten, aber jederzeit zubuchbar brutto pro Monat, monatlich kündbar.
„—“ heißt: in diesem Paket nicht verfügbar.
</p>
</details>
@endif
{{-- What costs extra, with the price it costs. The modules were on sale
the whole time and the page named none of them; the owner's
complaint was simply that nothing on it said so. --}}
@if (! empty($addons))
<div class="rv d1 mt-4 overflow-hidden rounded-xl border border-line bg-surface shadow-xs">
<div class="flex flex-wrap items-baseline gap-x-3 gap-y-1 border-b border-line px-7 py-5">
<h3 class="text-lg font-bold tracking-[-0.02em] text-ink">Optional dazubuchbar</h3>
<span class="text-sm text-muted">zu jedem Paket, monatlich kündbar</span>
</div>
<div class="grid gap-3 p-6 sm:grid-cols-2 lg:grid-cols-3">
@foreach ($addons as $addon)
<div class="flex flex-col rounded-lg border border-line bg-surface-2 px-4 py-3.5">
<b class="text-sm font-semibold text-ink">{{ $addon['name'] }}</b>
<span class="mt-1.5 flex-1 text-xs leading-relaxed text-muted">{{ $addon['body'] }}</span>
<span class="mt-3.5 flex items-baseline gap-1.5 font-mono text-sm tabular-nums text-ink">
+{{ $addon['price'] }}<span class="text-xs text-muted">/Monat</span>
</span>
</div>
@endforeach
</div>
</div>
@endif
@endif
</section>
{{-- ════ Questions ══════════════════════════════════════════════════════ --}}
<section id="faq" class="border-t border-line bg-surface-2 py-24 lg:py-32">
<div class="mx-auto grid max-w-[1120px] gap-12 px-5 sm:px-6 lg:grid-cols-[.75fr_1.25fr] lg:gap-20">
<div class="rv lg:sticky lg:top-28 lg:self-start">
<p class="lbl !text-accent-text">Häufige Fragen</p>
<h2 class="mt-3 text-[clamp(2rem,4vw,3.1rem)] font-bold leading-[1.06] tracking-[-0.035em] text-ink">
Klare Antworten.
</h2>
<p class="mt-5 max-w-[36ch] text-md leading-relaxed text-muted">
Steht Ihre Frage nicht dabei, schreiben Sie uns — wir antworten am selben Werktag.
</p>
<a href="mailto:office&#64;clupilot.com" class="mt-5 inline-flex items-center gap-2 text-sm font-medium text-accent-text underline-offset-4 hover:underline">
<x-ui.icon name="mail" class="size-4" />office&#64;clupilot.com
</a>
</div>
<div class="faq rv d1 divide-y divide-line border-y border-line">
@foreach ([
['Was passiert mit unseren Daten, wenn wir kündigen?', 'Sie erhalten vor Vertragsende einen vollständigen Export in offenen Standardformaten. Ihre Cloud basiert auf Open-Source-Software Sie sind nie eingesperrt. Nach der Übergabe löschen wir Instanz und Sicherungen und bestätigen das schriftlich.'],
['Ersetzt das Microsoft 365?', 'Es ersetzt den Dateiteil. Viele Kunden behalten Microsoft für E-Mail und nutzen die Cloud als zentrale, sichere Ablage statt OneDrive oder Dropbox zum fixen Firmenpreis statt pro Benutzer.'],
['Wie lange dauert die Einrichtung?', 'Die Instanz entsteht unmittelbar nach der Bestellung von selbst; Sie bekommen eine E-Mail, sobald sie bereit ist. Eine Dauer nennen wir bewusst nicht sie hängt an Dingen, die wir nicht allein in der Hand haben. Die vollständige Einrichtung Benutzer und Rechte, Ordnerstruktur nach Branchenvorlage, Ihr Logo, Ihre Domain und die Einschulung ist in drei bis sieben Werktagen abgeschlossen. Die Übernahme Ihrer Bestandsdaten aus Dropbox, OneDrive oder vom alten Server bieten wir gesondert an, inklusive schriftlichem Übernahmeprotokoll.'],
['Was, wenn jemand versehentlich Dateien löscht?', 'Papierkorb und Versionierung fangen den Alltag ab. Darüber hinaus gibt es tägliche Sicherungen mit 30 Tagen Aufbewahrung: Ein Anruf genügt, wir stellen den gewünschten Stand wieder her.'],
['Brauchen wir eigene IT-Kenntnisse?', 'Nein. Bedienen kann es jeder, der mit Ordnern und Dateien umgeht dafür gibt es die Einschulung. Alles Technische übernehmen wir dauerhaft.'],
['Mit wem spreche ich bei Fragen?', 'Direkt mit uns, per E-Mail oder Telefon, auf Deutsch, mit Antwort am selben Werktag. Kein Callcenter, keine Warteschleife.'],
['Wo genau stehen die Server?', 'In Rechenzentren innerhalb der EU. Es findet kein Transfer in Drittländer statt. Den Standort Ihrer Instanz halten wir im AV-Vertrag fest.'],
] as [$question, $answer])
<details class="group">
<summary class="flex min-h-16 items-center gap-4 py-4 text-md font-medium text-ink">
{{ $question }}
<x-ui.icon name="plus" class="ml-auto size-4 shrink-0 text-muted transition-transform duration-200 group-open:rotate-45" />
</summary>
<p class="max-w-[68ch] pb-5 text-sm leading-relaxed text-muted">{{ $answer }}</p>
</details>
@endforeach
</div>
</div>
</section>
{{-- ════ Close ══════════════════════════════════════════════════════════
The one large accent area. Orange appears in few places on this page, and
this is allowed to be all of it. --}}
<section id="contact" class="bg-accent-active">
<div class="mx-auto max-w-[1120px] px-5 py-24 text-center sm:px-6 lg:py-32">
{{-- The old headline asked who you call when a folder is missing on a
Monday morning. It promised the wrong thing: what happens inside a
customer's own Nextcloud is their own house the recycle bin and
the version history are right there, and a provider presenting
itself as the first call for somebody else's user error is offering
a service it does not run.
What is actually sold is the opposite: the part they would have to
do themselves and would rather not. The comparison section already
says it in the operator's own words "Updates, Sicherung und
Ausfälle sind Ihr Problem, auch am Wochenende" so the closing
question asks exactly that. --}}
<p class="lbl !text-white/70">Loslegen</p>
<h2 class="mx-auto mt-4 max-w-[22ch] text-[clamp(2rem,4.4vw,3.4rem)] font-bold leading-[1.06] tracking-[-0.035em] text-white">
Wer kümmert sich um Updates, Sicherung und Ausfälle?
</h2>
{{-- The old version promised "danach wissen Sie … wie Ihre Daten sicher
umziehen". We do not know where a visitor's data is, what shape it
is in, or whether it can be moved at all — that is a promise made
before seeing the thing it is about. What is said here instead is
what we actually control: the cloud itself is built by the machine,
and a migration is looked at first and quoted afterwards. --}}
<p class="mx-auto mt-6 max-w-[54ch] text-md leading-relaxed text-white/85">
Bei uns: wir — nachweislich, mit Protokoll. Konto anlegen, Paket wählen, bezahlen:
Ihre Cloud entsteht automatisch, ohne Termin und ohne Wartezeit auf eine Antwort.
</p>
<div class="mt-9 flex flex-wrap justify-center gap-3">
<a href="{{ route('login') }}" class="inline-flex min-h-[46px] items-center justify-center gap-2 rounded-[10px] bg-white px-[22px] text-[15px] font-semibold leading-none text-accent-active transition hover:bg-accent-subtle">
Jetzt buchen
</a>
<a href="mailto:office&#64;clupilot.com" class="inline-flex min-h-[46px] items-center justify-center gap-2 rounded-[10px] border border-white/40 px-[22px] text-[15px] font-semibold leading-none text-white transition hover:bg-white/10">
<x-ui.icon name="mail" class="size-4" />Frage stellen
</a>
</div>
{{-- Named, because it is the one thing this page cannot promise and the
one thing a visitor with an existing system will ask about. --}}
<p class="mx-auto mt-6 max-w-[60ch] text-sm leading-relaxed text-white/70">
Daten aus einem bestehenden System übernehmen? Das hängt davon ab, woher sie kommen —
schreiben Sie uns kurz, was Sie einsetzen. Wir sehen es uns an und sagen Ihnen ehrlich,
ob und wie es geht, bevor irgendetwas kostet.
</p>
<dl class="mx-auto mt-14 grid max-w-[760px] grid-cols-2 gap-y-8 border-t border-white/20 pt-10 sm:grid-cols-4">
@foreach ([
'Antwortzeit' => 'selber Werktag',
'Sprache' => 'Deutsch',
'Sitz' => 'Österreich',
'Gespräch' => 'unverbindlich',
] as $term => $value)
<div>
<dt class="lbl !text-white/60">{{ $term }}</dt>
<dd class="mt-1.5 font-semibold text-white">{{ $value }}</dd>
</div>
@endforeach
</dl>
</div>
</section>
</x-layouts.site>