{{-- Buying a package. The first version put five cards in a four-column grid, so the fifth wrapped and sat alone; the consent box was at the BOTTOM, which left every button disabled on arrival — a page that looks broken before you have done anything wrong. And the prices ran across the card in one block, so nothing stood out to compare. Now: the consent comes first, because it is the condition for everything under it. Three columns, so five plans read as 3 + 2 rather than 4 + 1. Each card is one column of the same four rows — price, delivery, what you get, the button — so the eye can run down a row and compare like with like. --}}

{{ __('order.title') }}

{{ __('order.subtitle') }}

@if ($contract) {{-- Not an error and not a dead end: they have a contract, and the way to a bigger package is a plan change, which prorates and leaves their data where it is. A second checkout would build a second, empty cloud and bill for both. --}} {{ __('order.already_customer') }} {{ __('order.to_billing') }} @elseif ($plans === []) {{ __('order.no_catalogue') }} @else @error('plan'){{ $message }}@enderror {{-- `term` decides which of the two prices every card shows and what the forms post. Both figures are rendered, so switching is instant and costs no round trip — and the checkout is handed the same word the customer was looking at. --}}
{{-- ── The terms, first ────────────────────────────────────────── One declaration, and the terms behind it regulate the sale: price, VAT, delivery, cancellation, the fourteen-day withdrawal right and the express request to begin at once. The box used to carry that last one as a paragraph of its own, which read like a choice between "now" and "in fourteen days" — and there is no second option. The label is not the whole contract in small print: it says what is being accepted, links to it, and summarises underneath what a reader most needs to know before ticking. The server rule is the real gate (CheckoutController validates `accepted`), so with JavaScript off the field arrives empty and the checkout is refused with the sentence explaining why. --}} @error('terms_accepted') {{ $message }} @enderror {{-- ── Monthly or yearly ───────────────────────────────────────── Two words, not a dropdown: there are exactly two answers and both fit on the line. The saving is named on the switch itself, because "jährlich" alone gives nobody a reason to look. --}} {{-- The block form of the php directive, not the parenthesised short one: that short form does not survive a cast and a method call in one expression — it compiled to an unterminated PHP open tag and took the rest of the page with it. Neither form is written out here, and that is deliberate: Blade compiles DIRECTIVES inside comments too, so naming the short one in this very comment produced the same open tag a second time and the whole block vanished from the page without an error anywhere. A comment describes a directive; it never spells one. --}} @php $bestFreeMonths = (int) collect($plans)->max('free_months'); @endphp
@foreach (['monthly', 'yearly'] as $option) @endforeach
@if ($bestFreeMonths > 0) {{ trans_choice('order.free_months_hint', $bestFreeMonths, ['count' => $bestFreeMonths]) }} @endif
{{-- ── The packages ────────────────────────────────────────────── Three columns: five plans read as 3 + 2, and a fifth card alone on a row of four reads as a mistake. items-start, because the recommended one is allowed to be taller without dragging its neighbours' buttons down with it. --}}
@foreach ($plans as $i => $plan)
$plan['recommended'], 'border-line' => ! $plan['recommended'], ]) style="animation-delay: {{ 60 + $i * 40 }}ms"> {{-- Name, who it is for, and the one badge. --}}

{{ $plan['name'] }}

@if ($plan['recommended']) {{ __('order.recommended') }} @endif
@if ($plan['audience'])

{{ $plan['audience'] }}

@endif {{-- The price, gross and large. A customer quoted 58,80 € on the website must not meet 49 € on the page with the button on it; the net figure is underneath for the books. Both terms, one shown at a time. The headline figure stays "per month" in either — a yearly price shown as a single big number reads as five times dearer at a glance, and the amount actually taken is named on the line underneath. --}} @php $eur = fn (int $cents) => Number::currency($cents / 100, in: $plan['currency'], locale: app()->getLocale()); @endphp

{{ $eur($plan['gross']) }} {{ __('order.per_month') }}

{{ __('order.incl_vat', ['rate' => $vat]) }} · {{ __('order.net') }} {{ $eur($plan['net']) }}

{{ $eur($plan['yearly_per_month']) }} {{ __('order.per_month') }}

{{ __('order.yearly_total', ['total' => $eur($plan['yearly_gross'])]) }} · {{ __('order.incl_vat', ['rate' => $vat]) }} · {{ __('order.net') }} {{ $eur($plan['yearly_net']) }}

@if ($plan['free_months'] > 0) {{-- The saving, with the figure it is measured against: "2 Monate gratis" next to what twelve monthly payments would have cost. --}}

{{ trans_choice('order.free_months_hint', $plan['free_months'], ['count' => $plan['free_months']]) }} · {{ __('order.instead_of', ['amount' => $eur($plan['twelve_months_gross'])]) }}

@endif
@if ($setup > 0)

{{ __('order.setup', ['amount' => Number::currency($setup / 100, in: $plan['currency'], locale: app()->getLocale())]) }}

@endif {{-- Read from the estate, not written down: where a host has room this rolls out on its own. --}}
@foreach ([ __('order.storage') => $plan['quota_gb'] >= 1000 ? ($plan['quota_gb'] / 1000).' TB' : $plan['quota_gb'].' GB', __('order.traffic') => $plan['traffic_gb'] >= 1000 ? ($plan['traffic_gb'] / 1000).' TB' : $plan['traffic_gb'].' GB', __('order.seats') => __('order.up_to', ['count' => $plan['seats']]), ] as $label => $value)
{{ $label }}
{{ $value }}
@endforeach
{{-- A plain form post, not a Livewire action: the response is a redirect to another domain, and Livewire's XHR-and-swap cannot leave the site. --}}
@csrf {{-- The term the customer was looking at when they pressed. CheckoutController validates it against the two we sell and picks that term's Stripe Price, so nothing here can invent a third. --}} {{-- No order without the terms — so the button is not usable until they are accepted, and says why underneath rather than leaving somebody to guess at a dead button. The refusal on the server stands regardless: this is the visible half of one rule, not the rule itself. x-bind on a plain attribute, not @disabled on the component — R24#3: a Blade directive in a component tag's attribute list lands in the attribute bag and takes the view apart. --}} {{ __('order.buy') }}

{{ __('order.terms_first') }}

@endforeach

{{ __('order.terms') }}

@endif