@if ($supported)
@if ($check['key'] === 'fail2ban')
@can('manage-network')
@endcan
@endif
@if ($check['key'] === 'ssh_password' && $check['featureOn'])
{{-- Safe auto-flow: generate+install a key, verify, switch the panel credential, THEN disable. --}}
@can('manage-fleet')
{{ __('servers.ssh_key_provision_action') }}
@endcan
@else
@can('manage-network')
{{-- Disabled while the post-apply re-read runs — prevents re-opening the
modal against the stale pre-toggle state ("2-3 Versuche"-Effekt). --}}
{{ $check['featureOn'] ? __('common.disable') : __('common.enable') }}
@endcan
@endif
@endif
@endforeach
{{-- Firewall + fail2ban: only the tools actually installed, side-by-side on lg --}}
@php
$fw = $firewall ?? [];
$fwTool = $fw['tool'] ?? 'ufw';
$fwToolLabel = $fwTool === 'firewalld' ? 'firewalld' : 'UFW';
$fwSupported = $fw['supported'] ?? false;
$fwInstalled = $fw['installed'] ?? false;
$fwActive = $fw['active'] ?? false;
$fwManageable = $fw['manageable'] ?? false;
$fwReadOnly = $fw['readOnly'] ?? false;
$fwReadError = $fw['readError'] ?? false;
$fwRules = $fw['rules'] ?? [];
$fwDefaults = $fw['defaults'] ?? [];
$actTone = ['ALLOW' => 'online', 'LIMIT' => 'warning', 'DENY' => 'offline', 'REJECT' => 'offline'];
$f2b = $fail2ban ?? [];
$f2bSupported = $f2b['supported'] ?? false;
$f2bReadError = $f2b['readError'] ?? false;
$f2bInstalled = $f2b['installed'] ?? false;
$f2bActive = $f2b['active'] ?? false;
$f2bJails = $f2b['jails'] ?? [];
$f2bIgnore = $f2b['ignoreip'] ?? [];
$f2bBanned = array_sum(array_map(fn ($j) => $j['currentlyBanned'] ?? 0, $f2bJails));
// Show a panel when its tool is actually installed (active or inactive), OR
// when the privileged read FAILED (readError) — a failed probe must stay
// visible so the operator can tell it apart from a genuinely-absent tool
// (both report installed=false). When truly absent, the Sicherheit checklist
// row carries the "Aktivieren" install path — so the redundant "nicht
// installiert" box is gone.
$showFw = $fwSupported && ($fwInstalled || $fwReadError);
$showF2b = $f2bSupported && ($f2bInstalled || $f2bReadError);
$panelCount = ($showFw ? 1 : 0) + ($showF2b ? 1 : 0);
// A single installed tool would otherwise sit in a capped, left-aligned box
// beside a large void. Instead the lone panel spans the full content width and
// splits its OWN body into two columns on lg — a rich, deliberate card rather
// than a fragment. Two tools keep the side-by-side grid.
$lone = $panelCount === 1;
@endphp
@if ($panelCount > 0)
{{-- Two tools → side-by-side; a lone tool spans full width and lays its body out
internally in two columns (see $lone), so neither case leaves dead space. --}}
$panelCount === 2,
])>
@if ($showFw)
{{-- Firewall-Regeln --}}
{{-- Adding rules to an INACTIVE firewall would suggest they take effect — gate on active. --}}
@if ($fwManageable && $fwActive)
@can('manage-network')
{{ __('servers.firewall_add_rule') }}
@endcan
@endif
@if ($fwReadError)
{{ __('servers.firewall_read_error') }}
@elseif (! $fwActive)
{{-- Inactive firewall (ufw OR firewalld): rules are not enforced, so showing the
rules table would mislead — compact hint + Aktivieren instead. --}}
@forelse ($fwRules as $rule)
{{-- $ruleTone, NOT $tone: the page-level $tone is a closure used by the
gauges/Volumes panel; reusing the name here would clobber it. --}}
@php $ruleTone = $actTone[$rule['action'] ?? 'ALLOW'] ?? 'online'; @endphp
@else
{{-- Lone fail2ban: status summary + "Gesperrte IPs ansehen" in the left
column, the whitelist (ignoreip) management in the right. Two-tool
case keeps the single stacked column. --}}
$lone])>
{{-- Compact summary; the full jail/banned-IP list (which can grow very
long) lives in a scrollable modal, opened via the button below. --}}