<?php
/**
 * Threat Intelligence — Kommandozentrale.
 *
 * Wires the local Shieldforge_Threat_Intel / Shieldforge_Logger statistics
 * and the (optional) central Threat-Network feed into a single command
 * center: KPIs, activity timeline, attack-type/country breakdowns, a
 * geographic corridor (arc/chord) threat map, plain-language explanations,
 * and the existing participation/consent/registration controls.
 *
 * Degrades gracefully at every step: with the network off, or with no local
 * data yet, every section still renders with a friendly empty state.
 *
 * @package Brainwerk Security Suite
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/* ------------------------------------------------------------------
 * Existing sensor/participation state (unchanged wiring).
 * ------------------------------------------------------------------ */
$enabled    = Shieldforge_Sensor::is_enabled();
$registered = Shieldforge_Sensor::is_registered();
$reg        = Shieldforge_Sensor::registration();
$salt       = Shieldforge_Sensor::network_salt();
$stats      = Shieldforge_Sensor::stats();
$audit      = Shieldforge_Sensor::audit_log();
$epoch      = Shieldforge_Sensor::current_epoch();
$api_base   = Shieldforge_Sensor::api_base();
$token      = (string) Shieldforge_Settings::get( 'sensor_register_token', '' );
$notice     = Shieldforge_Sensor::take_notice();
$salt_fresh = ! empty( $salt['epoch'] ) && (string) $salt['epoch'] === (string) $epoch;

/* ------------------------------------------------------------------
 * Local statistics (always available).
 * ------------------------------------------------------------------ */
$now      = time();
$since24  = gmdate( 'Y-m-d H:i:s', $now - DAY_IN_SECONDS );
$since7d  = gmdate( 'Y-m-d H:i:s', $now - 7 * DAY_IN_SECONDS );

$snapshot24 = Shieldforge_Threat_Intel::compute_snapshot( $since24 );
$score      = Shieldforge_Threat_Intel::compute_threat_score( $snapshot24 );
$hourly     = Shieldforge_Threat_Intel::hourly_histogram( $now );
$top_ips    = Shieldforge_Logger::top_attacker_ips( 24, 6 );
$top_users  = Shieldforge_Threat_Intel::top_targeted_usernames( $since24, 6 );
$top_ccs    = Shieldforge_Threat_Intel::top_attacker_countries( $since24, 8 );
$attack_mix = Shieldforge_Threat_Intel::attack_type_breakdown( $since24 );

$top_slugs_local   = Shieldforge_Threat_Intel::top_attacked_slugs( $since7d, 8 );
$top_classes_local = Shieldforge_Threat_Intel::top_attack_classes( $since7d, 9 );
$top_tools_local   = Shieldforge_Threat_Intel::top_attacker_tools( $since7d, 11 );
$top_asns_local    = Shieldforge_Threat_Intel::top_attacker_asns( $since7d, 8 );
$hod_local         = Shieldforge_Threat_Intel::hour_of_day_local( $since24 );
$velocity_local    = Shieldforge_Threat_Intel::velocity_local();

$blocked_total = (int) $snapshot24['logins_blocked'] + (int) $snapshot24['lockouts'] + (int) $snapshot24['hardening_blocks'];

$score_badge = array(
    Shieldforge_Threat_Intel::LABEL_CALM     => array( 'good', __( 'NIEDRIG', 'brainwerk-security-suite' ) ),
    Shieldforge_Threat_Intel::LABEL_ELEVATED => array( 'warn', __( 'MITTEL', 'brainwerk-security-suite' ) ),
    Shieldforge_Threat_Intel::LABEL_HIGH     => array( 'serious', __( 'HOCH', 'brainwerk-security-suite' ) ),
    Shieldforge_Threat_Intel::LABEL_CRITICAL => array( 'critical', __( 'HOCH', 'brainwerk-security-suite' ) ),
);
$score_bcls  = isset( $score_badge[ $score['label'] ] ) ? $score_badge[ $score['label'] ][0] : 'good';
$score_blbl  = isset( $score_badge[ $score['label'] ] ) ? $score_badge[ $score['label'] ][1] : '—';

/* ------------------------------------------------------------------
 * Feed / network status (feed is verified locally the moment it's read —
 * class_exists guards keep this tab renderable even if intel classes
 * somehow failed to load).
 * ------------------------------------------------------------------ */
$feed_status = class_exists( 'Shieldforge_Intel_Client' ) ? Shieldforge_Intel_Client::status() : array(
    'has_feed' => false, 'verified' => false, 'feed_version' => 0, 'rules' => 0, 'indicators' => 0, 'generated_at' => '',
);
$feed_age = '';
if ( ! empty( $feed_status['generated_at'] ) ) {
    $ts = strtotime( $feed_status['generated_at'] );
    if ( $ts ) {
        $feed_age = sprintf( __( 'aktualisiert vor %s', 'brainwerk-security-suite' ), human_time_diff( $ts, $now ) );
    }
}

$network_connected = $enabled && $registered && $feed_status['has_feed'];

/* ------------------------------------------------------------------
 * Threat map: local corridors always available; network corridors only
 * when opted in + registered, fetched via the signed transport (cached).
 * ------------------------------------------------------------------ */
$map_view = ( isset( $_GET['sf_map_view'] ) && 'network' === $_GET['sf_map_view'] ) ? 'network' : 'local'; // phpcs:ignore WordPress.Security.NonceVerification
$local_corridors = Shieldforge_Threat_Intel::corridors_local( $since7d, 12 );

$network_map  = null;
$network_note = '';
if ( $enabled && $registered ) {
    $network_map = Shieldforge_Sensor::threatmap( '7d' );
    if ( null === $network_map ) {
        $network_note = __( 'Netz-Gesamtbild derzeit nicht erreichbar — es werden lokale Daten angezeigt.', 'brainwerk-security-suite' );
    }
} else {
    $network_note = __( 'Netz-Gesamtbild ist nur mit aktiver Teilnahme am Threat-Network verfügbar.', 'brainwerk-security-suite' );
}

/* ------------------------------------------------------------------
 * Network "state of WordPress" indicators (attacker ASNs, hour-of-day
 * pattern, attack velocity) — same cache/consent contract as threatmap().
 * ------------------------------------------------------------------ */
$network_stateofwp = ( $enabled && $registered ) ? Shieldforge_Sensor::stateofwp( '24h' ) : null;

/* ------------------------------------------------------------------
 * Network aggregates for the target/attack-class/tool panels — reuse the
 * already-fetched $network_map (threatmap, 7d) payload; hide the network
 * variant entirely when participation is off or no network data is present.
 * ------------------------------------------------------------------ */
$sf_normalize_top = function ( $rows, $key_field ) {
    $out = array();
    foreach ( (array) $rows as $row ) {
        if ( ! is_array( $row ) || empty( $row[ $key_field ] ) ) {
            continue;
        }
        $out[] = array(
            $key_field => (string) $row[ $key_field ],
            'hits'     => (int) ( $row['hits'] ?? $row['count'] ?? 0 ),
        );
    }
    return $out;
};

$top_slugs_network   = is_array( $network_map ) && ! empty( $network_map['top_plugins'] ) ? $sf_normalize_top( $network_map['top_plugins'], 'slug' ) : array();
$top_classes_network = is_array( $network_map ) && ! empty( $network_map['top_attack_classes'] ) ? $sf_normalize_top( $network_map['top_attack_classes'], 'class' ) : array();
$top_tools_network   = is_array( $network_map ) && ! empty( $network_map['top_tools'] ) ? $sf_normalize_top( $network_map['top_tools'], 'tool' ) : array();
$has_network_panels  = $enabled && $registered;

/* ------------------------------------------------------------------
 * Network normalisations for the ASN / hour-of-day / velocity panels.
 * top_asns comes from threatmap() (already fetched above); hour_of_day
 * and velocity come from the separate stateofwp() aggregate.
 * ------------------------------------------------------------------ */
$top_asns_network = array();
if ( is_array( $network_map ) && ! empty( $network_map['top_asns'] ) ) {
    foreach ( (array) $network_map['top_asns'] as $row ) {
        if ( ! is_array( $row ) || empty( $row['asn'] ) ) {
            continue;
        }
        $asn                 = (int) $row['asn'];
        $top_asns_network[] = array(
            'asn'   => $asn,
            'org'   => class_exists( 'Shieldforge_Asn' ) ? Shieldforge_Asn::org_for_asn( $asn ) : null,
            'count' => (int) ( $row['count'] ?? 0 ),
        );
    }
}

$hod_network      = array_fill( 0, 24, 0 );
$busiest_network  = null;
if ( is_array( $network_stateofwp ) && ! empty( $network_stateofwp['hour_of_day'] ) ) {
    foreach ( (array) $network_stateofwp['hour_of_day'] as $row ) {
        if ( ! is_array( $row ) || ! isset( $row['hour'] ) ) {
            continue;
        }
        $h = (int) $row['hour'];
        if ( $h >= 0 && $h < 24 ) {
            $hod_network[ $h ] = (int) ( $row['count'] ?? 0 );
        }
    }
    $busiest_network = isset( $network_stateofwp['busiest_hour'] )
        ? (int) $network_stateofwp['busiest_hour']
        : Shieldforge_Threat_Intel::peak_hour( $hod_network );
}

/** Normalise a free-form trend string (or fall back to deriving it from the counts). */
$sf_normalize_trend = function ( $trend_raw, $last, $prev ) {
    $t = strtolower( (string) $trend_raw );
    if ( in_array( $t, array( 'up', 'increasing', 'rising' ), true ) ) {
        return 'up';
    }
    if ( in_array( $t, array( 'down', 'decreasing', 'falling' ), true ) ) {
        return 'down';
    }
    if ( in_array( $t, array( 'flat', 'stable', 'steady' ), true ) ) {
        return 'flat';
    }
    return Shieldforge_Threat_Intel::velocity_trend( $last, $prev );
};

$velocity_network = array(
    'last_hour' => 0,
    'prev_hour' => 0,
    'trend'     => 'flat',
);
if ( is_array( $network_stateofwp ) && ! empty( $network_stateofwp['velocity'] ) && is_array( $network_stateofwp['velocity'] ) ) {
    $v                 = $network_stateofwp['velocity'];
    $velocity_network = array(
        'last_hour' => (int) ( $v['events_last_hour'] ?? 0 ),
        'prev_hour' => (int) ( $v['events_prev_hour'] ?? 0 ),
        'trend'     => $sf_normalize_trend( $v['trend'] ?? '', (int) ( $v['events_last_hour'] ?? 0 ), (int) ( $v['events_prev_hour'] ?? 0 ) ),
    );
}

$velocity_meta = array(
    'up'   => array( '▲', __( 'steigend', 'brainwerk-security-suite' ), 'var(--c-red)' ),
    'down' => array( '▼', __( 'fallend', 'brainwerk-security-suite' ), 'var(--c-green)' ),
    'flat' => array( '▬', __( 'stabil', 'brainwerk-security-suite' ), 'var(--muted)' ),
);

if ( 'network' === $map_view && is_array( $network_map ) && ! empty( $network_map['corridors'] ) ) {
    $active_corridors = array();
    foreach ( (array) $network_map['corridors'] as $c ) {
        if ( ! is_array( $c ) || empty( $c['attacker'] ) || empty( $c['victim'] ) ) {
            continue;
        }
        $active_corridors[] = array(
            'attacker'     => (string) $c['attacker'],
            'victim'       => (string) $c['victim'],
            'events'       => (int) ( $c['events'] ?? 0 ),
            'top_cve'      => isset( $c['top_cve'] ) ? (string) $c['top_cve'] : null,
            'top_endpoint' => isset( $c['top_endpoint'] ) ? (string) $c['top_endpoint'] : null,
            'exploited'    => ! empty( $c['exploited'] ),
        );
    }
    $active_view_label = __( 'Netz-Gesamtbild', 'brainwerk-security-suite' );
} else {
    $active_corridors  = $local_corridors;
    $active_view_label = __( 'Meine Site', 'brainwerk-security-suite' );
}

/* ------------------------------------------------------------------
 * Readable German labels for attack_class / tool_class keys (see
 * Shieldforge_Sensor_Privacy::classify_attack_class()/classify_tool_class()).
 * A shared hue cycle keeps every bar list visually consistent with the
 * existing "Angriffsarten" panel.
 * ------------------------------------------------------------------ */
$sf_hue_cycle = array( 'var(--c-blue)', 'var(--c-orange)', 'var(--c-aqua)', 'var(--c-yellow)', 'var(--c-magenta)', 'var(--c-green)', 'var(--c-violet)', 'var(--c-red)' );

$attack_class_labels = array(
    'sqli'             => __( 'SQL-Injection', 'brainwerk-security-suite' ),
    'xss'              => __( 'Cross-Site-Scripting (XSS)', 'brainwerk-security-suite' ),
    'lfi'              => __( 'Local File Inclusion (LFI)', 'brainwerk-security-suite' ),
    'rce'              => __( 'Remote Code Execution (RCE)', 'brainwerk-security-suite' ),
    'traversal'        => __( 'Path Traversal', 'brainwerk-security-suite' ),
    'auth_bypass'      => __( 'Auth-Bypass', 'brainwerk-security-suite' ),
    'ssrf'             => __( 'Server-Side Request Forgery (SSRF)', 'brainwerk-security-suite' ),
    'object_injection' => __( 'Object-Injection', 'brainwerk-security-suite' ),
    'file_upload'      => __( 'File-Upload-Exploit', 'brainwerk-security-suite' ),
);
$tool_class_labels = array(
    'wpscan'          => __( 'WPScan', 'brainwerk-security-suite' ),
    'sqlmap'          => __( 'sqlmap', 'brainwerk-security-suite' ),
    'nuclei'          => __( 'Nuclei', 'brainwerk-security-suite' ),
    'nikto'           => __( 'Nikto', 'brainwerk-security-suite' ),
    'curl'            => __( 'curl', 'brainwerk-security-suite' ),
    'wget'            => __( 'wget', 'brainwerk-security-suite' ),
    'python_requests' => __( 'python-requests', 'brainwerk-security-suite' ),
    'go_http'         => __( 'Go-http', 'brainwerk-security-suite' ),
    'libwww'          => __( 'libwww', 'brainwerk-security-suite' ),
    'headless_chrome' => __( 'Headless-Chrome', 'brainwerk-security-suite' ),
    'generic_bot'     => __( 'generischer Bot', 'brainwerk-security-suite' ),
    'other'           => __( 'sonstiges Werkzeug', 'brainwerk-security-suite' ),
);

/* ------------------------------------------------------------------
 * Network early-warning alerts (from stateofwp()). Hidden entirely when
 * participation is off; friendly empty state when on but no active alerts.
 * ------------------------------------------------------------------ */
$network_active = $enabled && $registered;
$alerts_active  = is_array( $network_stateofwp ) ? (int) ( $network_stateofwp['alerts_active'] ?? 0 ) : 0;
$top_alerts     = is_array( $network_stateofwp ) && ! empty( $network_stateofwp['top_alerts'] ) ? (array) $network_stateofwp['top_alerts'] : array();

$sf_alert_severity = function ( $alert ) {
    $sev = isset( $alert['severity'] ) ? (string) $alert['severity'] : 'elevated';
    return in_array( $sev, array( 'critical', 'high', 'elevated' ), true ) ? $sev : 'elevated';
};

$sf_alert_subject_label = function ( $alert ) use ( $attack_class_labels ) {
    $kind    = isset( $alert['kind'] ) ? (string) $alert['kind'] : '';
    $subject = isset( $alert['subject'] ) ? (string) $alert['subject'] : '';
    if ( 'attack_class' === $kind && isset( $attack_class_labels[ $subject ] ) ) {
        return $attack_class_labels[ $subject ];
    }
    return $subject;
};

$sf_alert_banner_text = function ( $alert ) use ( $sf_alert_subject_label ) {
    $kind    = isset( $alert['kind'] ) ? (string) $alert['kind'] : '';
    $subject = $sf_alert_subject_label( $alert );
    $events  = (int) ( $alert['window_events'] ?? 0 );
    $sites   = (int) ( $alert['sites'] ?? 0 );
    $ratio   = number_format_i18n( (float) ( $alert['ratio'] ?? 0 ), 1 );

    if ( 'cve' === $kind ) {
        return sprintf(
            /* translators: 1: CVE id, 2: events in the last hour, 3: number of sites, 4: ratio over baseline */
            __( '⚠ Frühwarnung: Aktive Ausnutzung von %1$s — %2$d Angriffe in der letzten Stunde über %3$d Sites (Faktor %4$s× über Normal). Jetzt aktualisieren.', 'brainwerk-security-suite' ),
            $subject, $events, $sites, $ratio
        );
    }
    if ( 'attack_class' === $kind ) {
        return sprintf(
            /* translators: 1: attack class label, 2: events in the last hour, 3: number of sites, 4: ratio over baseline */
            __( '⚠ Frühwarnung: Anstieg von %1$s-Angriffen — %2$d Angriffe in der letzten Stunde über %3$d Sites (Faktor %4$s× über Normal). Jetzt aktualisieren.', 'brainwerk-security-suite' ),
            $subject, $events, $sites, $ratio
        );
    }
    return sprintf(
        /* translators: 1: plugin/theme slug, 2: events in the last hour, 3: number of sites, 4: ratio over baseline */
        __( '⚠ Frühwarnung: Aktive Angriffswelle auf Plugin »%1$s« — %2$d Angriffe in der letzten Stunde über %3$d Sites (Faktor %4$s× über Normal). Jetzt aktualisieren.', 'brainwerk-security-suite' ),
        $subject, $events, $sites, $ratio
    );
};

/* ------------------------------------------------------------------
 * Immunisierungen panel: signed immun_rules from the feed, joined with
 * local hit-maturity counters. New "active" rules get a one-time banner
 * (shieldforge_immun_seen_active tracks which active rule_keys have
 * already been shown).
 * ------------------------------------------------------------------ */
$immun = class_exists( 'Shieldforge_Intel_Client' ) ? Shieldforge_Intel_Client::immun_status() : array(
    'rules' => array(), 'counters' => array(),
    'settings' => array( 'immunize_enabled' => false, 'block_enabled' => false, 'participation' => false ),
);

$immun_stage_labels = array(
    'shadow' => __( 'Schatten', 'brainwerk-security-suite' ),
    'canary' => __( 'Canary', 'brainwerk-security-suite' ),
    'active' => __( 'Aktiv', 'brainwerk-security-suite' ),
);
$immun_stage_badge = array(
    'shadow' => 'neutral',
    'canary' => 'warn',
    'active' => 'good',
);

$immun_new_active   = array();
$immun_seen_active  = (array) get_option( 'shieldforge_immun_seen_active', array() );
$immun_banner_rule  = null;
foreach ( (array) $immun['rules'] as $ir ) {
    if ( ! is_array( $ir ) || empty( $ir['key'] ) || 'active' !== ( $ir['stage'] ?? '' ) ) {
        continue;
    }
    $ir_key = (string) $ir['key'];
    if ( ! in_array( $ir_key, $immun_seen_active, true ) ) {
        $immun_new_active[] = $ir_key;
        if ( null === $immun_banner_rule ) {
            $immun_banner_rule = $ir;
        }
    }
}
if ( ! empty( $immun_new_active ) ) {
    update_option( 'shieldforge_immun_seen_active', array_values( array_unique( array_merge( $immun_seen_active, $immun_new_active ) ) ), false );
}

$panel_view = ( isset( $_GET['sf_panel_view'] ) && 'network' === $_GET['sf_panel_view'] ) ? 'network' : 'local'; // phpcs:ignore WordPress.Security.NonceVerification

if ( $notice ) :
    $cls = 'error' === $notice['type'] ? 'notice-error' : 'notice-success';
    ?>
    <div class="notice <?php echo esc_attr( $cls ); ?> is-dismissible"><p><?php echo esc_html( $notice['message'] ); ?></p></div>
    <?php
endif;
?>
<div class="sf-intel-command">

    <!-- ============ Header ============ -->
    <div class="sf-ic-card sf-ic-header">
        <div>
            <h1><?php esc_html_e( 'Threat Intelligence — Kommandozentrale', 'brainwerk-security-suite' ); ?></h1>
            <p class="sf-ic-sub"><?php esc_html_e( 'Brainwerk Security Suite · Privacy-first · EU-gehostet', 'brainwerk-security-suite' ); ?></p>
        </div>
        <div class="sf-ic-header-right">
            <?php if ( $feed_age ) : ?>
                <span class="sf-ic-updated"><?php echo esc_html( $feed_age ); ?></span>
            <?php endif; ?>
            <span class="sf-ic-chip <?php echo $network_connected ? 'on' : 'off'; ?>">
                <span class="dot"></span>
                <?php echo $network_connected
                    ? esc_html__( 'Netzwerk verbunden', 'brainwerk-security-suite' )
                    : esc_html__( 'Netzwerk getrennt', 'brainwerk-security-suite' ); ?>
            </span>
        </div>
    </div>

    <!-- ============ Early-warning banner ============ -->
    <?php if ( $network_active && $alerts_active > 0 && ! empty( $top_alerts ) ) :
        $sf_primary_alert = $top_alerts[0];
        $sf_alert_sev      = $sf_alert_severity( $sf_primary_alert );
        $sf_alert_extra    = $alerts_active - 1;
        ?>
        <div class="sf-ic-alert <?php echo esc_attr( $sf_alert_sev ); ?>">
            <div class="sf-ic-alert-body">
                <?php echo esc_html( $sf_alert_banner_text( $sf_primary_alert ) ); ?>
                <?php if ( $sf_alert_extra > 0 ) : ?>
                    <span class="sf-ic-alert-more"><?php printf( esc_html__( '+%d weitere Frühwarnungen', 'brainwerk-security-suite' ), (int) $sf_alert_extra ); ?></span>
                <?php endif; ?>
            </div>
        </div>
    <?php endif; ?>

    <!-- ============ KPI tiles ============ -->
    <div class="sf-ic-kpis">
        <div class="sf-ic-kpi">
            <div class="sf-ic-kpi-label"><?php esc_html_e( 'Angriffe (24h)', 'brainwerk-security-suite' ); ?></div>
            <div class="sf-ic-kpi-value"><?php echo esc_html( number_format_i18n( (int) $snapshot24['total_high_severity'] + (int) $snapshot24['probing_404s'] ) ); ?></div>
        </div>
        <div class="sf-ic-kpi">
            <div class="sf-ic-kpi-label"><?php esc_html_e( 'Blockiert', 'brainwerk-security-suite' ); ?></div>
            <div class="sf-ic-kpi-value"><?php echo esc_html( number_format_i18n( $blocked_total ) ); ?></div>
        </div>
        <div class="sf-ic-kpi">
            <div class="sf-ic-kpi-label"><?php esc_html_e( 'Eindeutige Angreifer', 'brainwerk-security-suite' ); ?></div>
            <div class="sf-ic-kpi-value"><?php echo esc_html( number_format_i18n( (int) $snapshot24['distinct_ips'] ) ); ?></div>
        </div>
        <div class="sf-ic-kpi">
            <div class="sf-ic-kpi-label"><?php esc_html_e( 'Bedrohungs-Score', 'brainwerk-security-suite' ); ?></div>
            <div class="sf-ic-kpi-value"><?php echo (int) $score['score']; ?><span style="font-size:13px;color:var(--muted);">/100</span></div>
            <span class="sf-ic-kpi-badge <?php echo esc_attr( $score_bcls ); ?>"><?php echo esc_html( $score_blbl ); ?></span>
        </div>
        <div class="sf-ic-kpi">
            <div class="sf-ic-kpi-label"><?php esc_html_e( 'Feed-Indikatoren aktiv', 'brainwerk-security-suite' ); ?></div>
            <div class="sf-ic-kpi-value"><?php echo esc_html( number_format_i18n( (int) $feed_status['indicators'] ) ); ?></div>
        </div>
    </div>

    <!-- ============ Activity timeline + network status ============ -->
    <div class="sf-ic-row">
        <div class="sf-ic-card">
            <h2><?php esc_html_e( 'Angriffs-Aktivität', 'brainwerk-security-suite' ); ?></h2>
            <p class="sf-ic-sub"><?php esc_html_e( '24 Stunden, stündlich (WARN und höher)', 'brainwerk-security-suite' ); ?></p>
            <?php if ( array_sum( $hourly ) > 0 ) : ?>
                <?php echo Shieldforge_Threat_Intel::render_hourly_svg( $hourly ); // phpcs:ignore WordPress.Security.EscapeOutput ?>
            <?php else : ?>
                <p class="sf-ic-empty"><?php esc_html_e( 'Noch keine Daten — der Sensor sammelt.', 'brainwerk-security-suite' ); ?></p>
            <?php endif; ?>
        </div>
        <div class="sf-ic-card">
            <h2><?php esc_html_e( 'Threat-Netzwerk', 'brainwerk-security-suite' ); ?></h2>
            <ul class="sf-ic-status-list">
                <li><span class="k"><?php esc_html_e( 'Teilnahme', 'brainwerk-security-suite' ); ?></span>
                    <span class="v"><?php echo $enabled ? esc_html__( 'Aktiv', 'brainwerk-security-suite' ) : esc_html__( 'Aus', 'brainwerk-security-suite' ); ?></span></li>
                <li><span class="k"><?php esc_html_e( 'Feed-Version', 'brainwerk-security-suite' ); ?></span>
                    <span class="v"><?php echo $feed_status['feed_version'] ? (int) $feed_status['feed_version'] : '—'; ?></span></li>
                <li><span class="k"><?php esc_html_e( 'Aktualisiert', 'brainwerk-security-suite' ); ?></span>
                    <span class="v"><?php echo $feed_age ? esc_html( $feed_age ) : '—'; ?></span></li>
                <li><span class="k"><?php esc_html_e( 'Virtual-Patch-Regeln', 'brainwerk-security-suite' ); ?></span>
                    <span class="v"><?php echo esc_html( number_format_i18n( (int) $feed_status['rules'] ) ); ?></span></li>
                <li><span class="k"><?php esc_html_e( 'Sensoren im Netz', 'brainwerk-security-suite' ); ?></span>
                    <span class="v"><?php
                        $sensor_count = is_array( $network_map ) && isset( $network_map['active_sensors'] ) ? (int) $network_map['active_sensors'] : null;
                        echo null !== $sensor_count ? esc_html( number_format_i18n( $sensor_count ) ) : '—';
                    ?></span></li>
                <li><span class="k"><?php esc_html_e( 'Ed25519-Signatur verifiziert', 'brainwerk-security-suite' ); ?></span>
                    <span class="v"><?php echo $feed_status['verified'] ? '✓ ' . esc_html__( 'ja', 'brainwerk-security-suite' ) : esc_html__( 'nein', 'brainwerk-security-suite' ); ?></span></li>
            </ul>
        </div>
    </div>

    <!-- ============ Frühwarnungen (Netz) ============ -->
    <?php if ( $network_active ) : ?>
        <div class="sf-ic-card">
            <h2><?php esc_html_e( 'Frühwarnungen (Netz)', 'brainwerk-security-suite' ); ?></h2>
            <p class="sf-ic-sub"><?php esc_html_e( 'Netzweite Angriffswellen mit auffälliger Rate gegenüber dem Normalwert', 'brainwerk-security-suite' ); ?></p>
            <?php if ( ! empty( $top_alerts ) ) : ?>
                <ul class="sf-ic-alert-list">
                    <?php foreach ( $top_alerts as $alert ) :
                        $sev     = $sf_alert_severity( $alert );
                        $subject = $sf_alert_subject_label( $alert );
                        $events  = (int) ( $alert['window_events'] ?? 0 );
                        $ratio   = number_format_i18n( (float) ( $alert['ratio'] ?? 0 ), 1 );
                        $sites   = (int) ( $alert['sites'] ?? 0 );
                        ?>
                        <li class="sf-ic-alert-row">
                            <span class="sf-ic-alert-chip <?php echo esc_attr( $sev ); ?>"><?php echo esc_html( strtoupper( $sev ) ); ?></span>
                            <span class="subject"><?php echo esc_html( $subject ); ?></span>
                            <span class="meta">
                                <?php printf(
                                    /* translators: 1: events in the last hour, 2: ratio over baseline, 3: number of sites */
                                    esc_html__( '%1$d× / Faktor %2$s× / %3$d Sites', 'brainwerk-security-suite' ),
                                    esc_html( $events ), esc_html( $ratio ), esc_html( $sites )
                                ); ?>
                            </span>
                        </li>
                    <?php endforeach; ?>
                </ul>
            <?php else : ?>
                <p class="sf-ic-empty"><?php esc_html_e( 'Keine aktiven Frühwarnungen — alles ruhig.', 'brainwerk-security-suite' ); ?></p>
            <?php endif; ?>
        </div>
    <?php endif; ?>

    <!-- ============ Attack types / top IPs / top usernames ============ -->
    <div class="sf-ic-cols">
        <div class="sf-ic-card">
            <h2><?php esc_html_e( 'Angriffsarten', 'brainwerk-security-suite' ); ?></h2>
            <?php
            $mix_labels = array(
                'bruteforce' => array( __( 'Brute-Force', 'brainwerk-security-suite' ), 'var(--c-red)' ),
                'honeypot'   => array( __( 'Honeypot', 'brainwerk-security-suite' ), 'var(--c-magenta)' ),
                'probing'    => array( __( 'Probing', 'brainwerk-security-suite' ), 'var(--c-yellow)' ),
                'waf'        => array( __( 'WAF', 'brainwerk-security-suite' ), 'var(--c-blue)' ),
                'malware'    => array( __( 'Malware', 'brainwerk-security-suite' ), 'var(--c-orange)' ),
                'anomaly'    => array( __( 'Anomalie', 'brainwerk-security-suite' ), 'var(--c-violet)' ),
            );
            $mix_max = max( 1, max( $attack_mix ) );
            ?>
            <?php if ( array_sum( $attack_mix ) > 0 ) : ?>
                <div class="sf-ic-bars">
                    <?php foreach ( $mix_labels as $key => $meta ) :
                        $val = (int) $attack_mix[ $key ];
                        $pct = max( 2, ( $val / $mix_max ) * 100 );
                        ?>
                        <div class="sf-ic-bar-row">
                            <span class="lbl"><?php echo esc_html( $meta[0] ); ?></span>
                            <span class="sf-ic-bar-track"><span class="sf-ic-bar-fill" style="width:<?php echo esc_attr( $pct ); ?>%;background:<?php echo esc_attr( $meta[1] ); ?>"></span></span>
                            <span class="n"><?php echo esc_html( number_format_i18n( $val ) ); ?></span>
                        </div>
                    <?php endforeach; ?>
                </div>
            <?php else : ?>
                <p class="sf-ic-empty"><?php esc_html_e( 'Noch keine Daten — der Sensor sammelt.', 'brainwerk-security-suite' ); ?></p>
            <?php endif; ?>
        </div>

        <div class="sf-ic-card">
            <h2><?php esc_html_e( 'Top-Angreifer-IPs', 'brainwerk-security-suite' ); ?></h2>
            <?php if ( ! empty( $top_ips ) ) : ?>
                <?php $ip_max = max( 1, max( array_map( function ( $r ) { return (int) $r->hits; }, $top_ips ) ) ); ?>
                <div class="sf-ic-bars">
                    <?php foreach ( $top_ips as $row ) : $pct = max( 2, ( (int) $row->hits / $ip_max ) * 100 ); ?>
                        <div class="sf-ic-bar-row">
                            <span class="lbl"><code><?php echo esc_html( $row->ip ); ?></code></span>
                            <span class="sf-ic-bar-track"><span class="sf-ic-bar-fill" style="width:<?php echo esc_attr( $pct ); ?>%;background:var(--c-blue)"></span></span>
                            <span class="n"><?php echo (int) $row->hits; ?></span>
                        </div>
                    <?php endforeach; ?>
                </div>
            <?php else : ?>
                <p class="sf-ic-empty"><?php esc_html_e( 'Noch keine Daten — der Sensor sammelt.', 'brainwerk-security-suite' ); ?></p>
            <?php endif; ?>
        </div>

        <div class="sf-ic-card">
            <h2><?php esc_html_e( 'Angegriffene Benutzernamen', 'brainwerk-security-suite' ); ?></h2>
            <?php if ( ! empty( $top_users ) ) : ?>
                <?php $u_max = max( 1, max( array_map( function ( $r ) { return (int) $r->hits; }, $top_users ) ) ); ?>
                <div class="sf-ic-bars">
                    <?php foreach ( $top_users as $row ) : $pct = max( 2, ( (int) $row->hits / $u_max ) * 100 ); ?>
                        <div class="sf-ic-bar-row">
                            <span class="lbl"><?php echo esc_html( $row->username ); ?></span>
                            <span class="sf-ic-bar-track"><span class="sf-ic-bar-fill" style="width:<?php echo esc_attr( $pct ); ?>%;background:var(--c-aqua)"></span></span>
                            <span class="n"><?php echo (int) $row->hits; ?></span>
                        </div>
                    <?php endforeach; ?>
                </div>
            <?php else : ?>
                <p class="sf-ic-empty"><?php esc_html_e( 'Noch keine Daten — der Sensor sammelt.', 'brainwerk-security-suite' ); ?></p>
            <?php endif; ?>
        </div>
    </div>

    <!-- ============ Herkunft der Angriffe ============ -->
    <div class="sf-ic-card">
        <h2><?php esc_html_e( 'Herkunft der Angriffe', 'brainwerk-security-suite' ); ?></h2>
        <p class="sf-ic-sub"><?php esc_html_e( 'Angreifer-Länder, 24h, lokal aufgelöst (keine externen Abfragen)', 'brainwerk-security-suite' ); ?></p>
        <?php if ( ! empty( $top_ccs ) ) : ?>
            <?php $cc_max = max( 1, max( array_column( $top_ccs, 'hits' ) ) ); ?>
            <div class="sf-ic-bars">
                <?php foreach ( $top_ccs as $row ) : $pct = max( 2, ( $row['hits'] / $cc_max ) * 100 ); ?>
                    <div class="sf-ic-bar-row">
                        <span class="lbl"><?php echo esc_html( $row['flag'] . ' ' . $row['name'] ); ?></span>
                        <span class="sf-ic-bar-track"><span class="sf-ic-bar-fill" style="width:<?php echo esc_attr( $pct ); ?>%;background:var(--c-green)"></span></span>
                        <span class="n"><?php echo (int) $row['hits']; ?></span>
                    </div>
                <?php endforeach; ?>
            </div>
        <?php else : ?>
            <p class="sf-ic-empty"><?php esc_html_e( 'Noch keine Daten — der Sensor sammelt.', 'brainwerk-security-suite' ); ?></p>
        <?php endif; ?>
    </div>

    <!-- ============ Ziele / Angriffsklassen / Werkzeuge ============ -->
    <?php if ( $has_network_panels ) : ?>
        <div class="sf-ic-map-toggle">
            <a href="<?php echo esc_url( add_query_arg( 'sf_panel_view', 'local' ) ); ?>" class="<?php echo 'local' === $panel_view ? 'active' : ''; ?>"><?php esc_html_e( 'Meine Site', 'brainwerk-security-suite' ); ?></a>
            <a href="<?php echo esc_url( add_query_arg( 'sf_panel_view', 'network' ) ); ?>" class="<?php echo 'network' === $panel_view ? 'active' : ''; ?>"><?php esc_html_e( 'Netz-Gesamtbild', 'brainwerk-security-suite' ); ?></a>
        </div>
    <?php endif; ?>

    <?php
    $show_network_panels = $has_network_panels && 'network' === $panel_view;
    $top_slugs           = $show_network_panels ? $top_slugs_network : $top_slugs_local;
    $top_classes         = $show_network_panels ? $top_classes_network : $top_classes_local;
    $top_tools           = $show_network_panels ? $top_tools_network : $top_tools_local;
    $top_asns            = $show_network_panels ? $top_asns_network : $top_asns_local;
    $hod                 = $show_network_panels ? $hod_network : $hod_local;
    $hod_has_data        = $show_network_panels ? ( is_array( $network_stateofwp ) && ! empty( $network_stateofwp['hour_of_day'] ) ) : ( array_sum( $hod_local ) > 0 );
    $busiest_hour        = $show_network_panels ? $busiest_network : Shieldforge_Threat_Intel::peak_hour( $hod_local );
    $velocity            = $show_network_panels ? $velocity_network : $velocity_local;
    $velocity_has_data   = $show_network_panels ? ( is_array( $network_stateofwp ) && ! empty( $network_stateofwp['velocity'] ) ) : true;
    $vm                  = isset( $velocity_meta[ $velocity['trend'] ] ) ? $velocity_meta[ $velocity['trend'] ] : $velocity_meta['flat'];
    ?>

    <div class="sf-ic-cols">
        <div class="sf-ic-card">
            <h2><?php esc_html_e( 'Meistangegriffene Plugins/Themes', 'brainwerk-security-suite' ); ?></h2>
            <p class="sf-ic-sub"><?php echo $show_network_panels
                ? esc_html__( '7 Tage, Netz-Gesamtbild', 'brainwerk-security-suite' )
                : esc_html__( '7 Tage, lokal erkannt', 'brainwerk-security-suite' ); ?></p>
            <?php if ( $show_network_panels && '' !== $network_note && empty( $top_slugs ) ) : ?>
                <p class="sf-ic-empty"><?php echo esc_html( $network_note ); ?></p>
            <?php elseif ( ! empty( $top_slugs ) ) : ?>
                <?php $slug_max = max( 1, max( array_column( $top_slugs, 'hits' ) ) ); ?>
                <div class="sf-ic-bars">
                    <?php foreach ( $top_slugs as $i => $row ) : $pct = max( 2, ( $row['hits'] / $slug_max ) * 100 ); ?>
                        <div class="sf-ic-bar-row">
                            <span class="lbl"><code><?php echo esc_html( $row['slug'] ); ?></code></span>
                            <span class="sf-ic-bar-track"><span class="sf-ic-bar-fill" style="width:<?php echo esc_attr( $pct ); ?>%;background:<?php echo esc_attr( $sf_hue_cycle[ $i % count( $sf_hue_cycle ) ] ); ?>"></span></span>
                            <span class="n"><?php echo (int) $row['hits']; ?></span>
                        </div>
                    <?php endforeach; ?>
                </div>
            <?php else : ?>
                <p class="sf-ic-empty"><?php esc_html_e( 'Noch keine Daten — der Sensor sammelt.', 'brainwerk-security-suite' ); ?></p>
            <?php endif; ?>
        </div>

        <div class="sf-ic-card">
            <h2><?php esc_html_e( 'Angriffsklassen', 'brainwerk-security-suite' ); ?></h2>
            <p class="sf-ic-sub"><?php echo $show_network_panels
                ? esc_html__( '7 Tage, Netz-Gesamtbild', 'brainwerk-security-suite' )
                : esc_html__( '7 Tage, lokal erkannt', 'brainwerk-security-suite' ); ?></p>
            <?php if ( $show_network_panels && '' !== $network_note && empty( $top_classes ) ) : ?>
                <p class="sf-ic-empty"><?php echo esc_html( $network_note ); ?></p>
            <?php elseif ( ! empty( $top_classes ) ) : ?>
                <?php $class_max = max( 1, max( array_column( $top_classes, 'hits' ) ) ); ?>
                <div class="sf-ic-bars">
                    <?php foreach ( $top_classes as $i => $row ) : $pct = max( 2, ( $row['hits'] / $class_max ) * 100 ); ?>
                        <div class="sf-ic-bar-row">
                            <span class="lbl"><?php echo esc_html( $attack_class_labels[ $row['class'] ] ?? $row['class'] ); ?></span>
                            <span class="sf-ic-bar-track"><span class="sf-ic-bar-fill" style="width:<?php echo esc_attr( $pct ); ?>%;background:<?php echo esc_attr( $sf_hue_cycle[ $i % count( $sf_hue_cycle ) ] ); ?>"></span></span>
                            <span class="n"><?php echo (int) $row['hits']; ?></span>
                        </div>
                    <?php endforeach; ?>
                </div>
            <?php else : ?>
                <p class="sf-ic-empty"><?php esc_html_e( 'Noch keine Daten — der Sensor sammelt.', 'brainwerk-security-suite' ); ?></p>
            <?php endif; ?>
        </div>

        <div class="sf-ic-card">
            <h2><?php esc_html_e( 'Angreifer-Werkzeuge', 'brainwerk-security-suite' ); ?></h2>
            <p class="sf-ic-sub"><?php echo $show_network_panels
                ? esc_html__( '7 Tage, Netz-Gesamtbild', 'brainwerk-security-suite' )
                : esc_html__( '7 Tage, lokal erkannt (User-Agent)', 'brainwerk-security-suite' ); ?></p>
            <?php if ( $show_network_panels && '' !== $network_note && empty( $top_tools ) ) : ?>
                <p class="sf-ic-empty"><?php echo esc_html( $network_note ); ?></p>
            <?php elseif ( ! empty( $top_tools ) ) : ?>
                <?php $tool_max = max( 1, max( array_column( $top_tools, 'hits' ) ) ); ?>
                <div class="sf-ic-bars">
                    <?php foreach ( $top_tools as $i => $row ) : $pct = max( 2, ( $row['hits'] / $tool_max ) * 100 ); ?>
                        <div class="sf-ic-bar-row">
                            <span class="lbl"><?php echo esc_html( $tool_class_labels[ $row['tool'] ] ?? $row['tool'] ); ?></span>
                            <span class="sf-ic-bar-track"><span class="sf-ic-bar-fill" style="width:<?php echo esc_attr( $pct ); ?>%;background:<?php echo esc_attr( $sf_hue_cycle[ $i % count( $sf_hue_cycle ) ] ); ?>"></span></span>
                            <span class="n"><?php echo (int) $row['hits']; ?></span>
                        </div>
                    <?php endforeach; ?>
                </div>
            <?php else : ?>
                <p class="sf-ic-empty"><?php esc_html_e( 'Noch keine Daten — der Sensor sammelt.', 'brainwerk-security-suite' ); ?></p>
            <?php endif; ?>
        </div>
    </div>

    <!-- ============ Angreifer-Netze / Tageszeit-Muster / Angriffs-Tempo ============ -->
    <div class="sf-ic-cols">
        <div class="sf-ic-card">
            <h2><?php esc_html_e( 'Angreifer-Netze (Provider)', 'brainwerk-security-suite' ); ?></h2>
            <p class="sf-ic-sub"><?php echo $show_network_panels
                ? esc_html__( '7 Tage, Netz-Gesamtbild', 'brainwerk-security-suite' )
                : esc_html__( '7 Tage, lokal aufgelöst (keine externen Abfragen)', 'brainwerk-security-suite' ); ?></p>
            <?php if ( $show_network_panels && '' !== $network_note && empty( $top_asns ) ) : ?>
                <p class="sf-ic-empty"><?php echo esc_html( $network_note ); ?></p>
            <?php elseif ( ! empty( $top_asns ) ) : ?>
                <?php $asn_max = max( 1, max( array_column( $top_asns, 'count' ) ) ); ?>
                <div class="sf-ic-bars">
                    <?php foreach ( $top_asns as $i => $row ) :
                        $pct   = max( 2, ( $row['count'] / $asn_max ) * 100 );
                        $label = ! empty( $row['org'] ) ? $row['org'] . ' · AS' . $row['asn'] : 'AS' . $row['asn'];
                        ?>
                        <div class="sf-ic-bar-row">
                            <span class="lbl"><?php echo esc_html( $label ); ?></span>
                            <span class="sf-ic-bar-track"><span class="sf-ic-bar-fill" style="width:<?php echo esc_attr( $pct ); ?>%;background:<?php echo esc_attr( $sf_hue_cycle[ $i % count( $sf_hue_cycle ) ] ); ?>"></span></span>
                            <span class="n"><?php echo (int) $row['count']; ?></span>
                        </div>
                    <?php endforeach; ?>
                </div>
            <?php else : ?>
                <p class="sf-ic-empty"><?php esc_html_e( 'Noch keine Daten — der Sensor sammelt.', 'brainwerk-security-suite' ); ?></p>
            <?php endif; ?>
        </div>

        <div class="sf-ic-card">
            <h2><?php esc_html_e( 'Tageszeit-Muster', 'brainwerk-security-suite' ); ?></h2>
            <p class="sf-ic-sub"><?php echo $show_network_panels
                ? esc_html__( '24 Stunden, Netz-Gesamtbild (UTC)', 'brainwerk-security-suite' )
                : esc_html__( '24 Stunden, lokal (UTC)', 'brainwerk-security-suite' ); ?></p>
            <?php if ( $show_network_panels && '' !== $network_note && ! $hod_has_data ) : ?>
                <p class="sf-ic-empty"><?php echo esc_html( $network_note ); ?></p>
            <?php elseif ( $hod_has_data ) : ?>
                <?php echo Shieldforge_Threat_Intel::render_hourly_svg( $hod ); // phpcs:ignore WordPress.Security.EscapeOutput ?>
                <?php if ( null !== $busiest_hour ) : ?>
                    <p class="sf-ic-sub"><?php printf( esc_html__( 'Spitze um %02d:00 UTC', 'brainwerk-security-suite' ), esc_html( $busiest_hour ) ); ?></p>
                <?php endif; ?>
            <?php else : ?>
                <p class="sf-ic-empty"><?php esc_html_e( 'Noch keine Daten — der Sensor sammelt.', 'brainwerk-security-suite' ); ?></p>
            <?php endif; ?>
        </div>

        <div class="sf-ic-card">
            <h2><?php esc_html_e( 'Angriffs-Tempo', 'brainwerk-security-suite' ); ?></h2>
            <p class="sf-ic-sub"><?php echo $show_network_panels
                ? esc_html__( 'Netz-Gesamtbild, letzte Stunde vs. vorherige', 'brainwerk-security-suite' )
                : esc_html__( 'Meine Site, letzte Stunde vs. vorherige', 'brainwerk-security-suite' ); ?></p>
            <?php if ( $show_network_panels && '' !== $network_note && ! $velocity_has_data ) : ?>
                <p class="sf-ic-empty"><?php echo esc_html( $network_note ); ?></p>
            <?php else : ?>
                <div style="display:flex;align-items:baseline;gap:10px;margin-top:6px;">
                    <span style="font-size:28px;line-height:1;color:<?php echo esc_attr( $vm[2] ); ?>"><?php echo esc_html( $vm[0] ); ?></span>
                    <span style="font-size:15px;font-weight:600;color:<?php echo esc_attr( $vm[2] ); ?>"><?php echo esc_html( $vm[1] ); ?></span>
                </div>
                <p class="sf-ic-sub" style="margin-top:6px;">
                    <?php printf(
                        /* translators: 1: events in the last hour, 2: events in the previous hour */
                        esc_html__( '%1$d letzte Stunde · %2$d Stunde davor', 'brainwerk-security-suite' ),
                        (int) $velocity['last_hour'],
                        (int) $velocity['prev_hour']
                    ); ?>
                </p>
            <?php endif; ?>
        </div>
    </div>

    <!-- ============ Threat map: Angriffs-Korridore ============ -->
    <div class="sf-ic-card">
        <h2><?php esc_html_e( 'Angriffs-Korridore', 'brainwerk-security-suite' ); ?></h2>
        <p class="sf-ic-sub"><?php esc_html_e( 'Herkunfts- zu Ziel-Länder, letzte 7 Tage. Keine Kartenkacheln — ein datenbasiertes Chord-Diagramm.', 'brainwerk-security-suite' ); ?></p>

        <div class="sf-ic-map-toggle">
            <a href="<?php echo esc_url( add_query_arg( 'sf_map_view', 'local' ) ); ?>" class="<?php echo 'local' === $map_view ? 'active' : ''; ?>"><?php esc_html_e( 'Meine Site', 'brainwerk-security-suite' ); ?></a>
            <a href="<?php echo esc_url( add_query_arg( 'sf_map_view', 'network' ) ); ?>" class="<?php echo 'network' === $map_view ? 'active' : ''; ?>"><?php esc_html_e( 'Netz-Gesamtbild', 'brainwerk-security-suite' ); ?></a>
        </div>

        <?php if ( 'network' === $map_view && $network_note ) : ?>
            <p class="sf-ic-empty"><?php echo esc_html( $network_note ); ?></p>
        <?php endif; ?>

        <?php if ( ! empty( $active_corridors ) ) : ?>
            <?php echo Shieldforge_Threat_Intel::render_corridor_svg( $active_corridors ); // phpcs:ignore WordPress.Security.EscapeOutput ?>

            <table class="sf-ic-table">
                <thead>
                    <tr>
                        <th><?php esc_html_e( 'Herkunft → Ziel', 'brainwerk-security-suite' ); ?></th>
                        <th><?php esc_html_e( 'Ereignisse', 'brainwerk-security-suite' ); ?></th>
                        <th><?php esc_html_e( 'Top-CVE', 'brainwerk-security-suite' ); ?></th>
                        <th><?php esc_html_e( 'Top-Endpunktklasse', 'brainwerk-security-suite' ); ?></th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach ( $active_corridors as $c ) : ?>
                        <tr>
                            <td>
                                <?php
                                echo esc_html(
                                    Shieldforge_Geo::flag_emoji( $c['attacker'] ) . ' ' . Shieldforge_Geo::country_name( $c['attacker'] )
                                    . ' → ' .
                                    Shieldforge_Geo::flag_emoji( $c['victim'] ) . ' ' . Shieldforge_Geo::country_name( $c['victim'] )
                                );
                                ?>
                            </td>
                            <td><?php echo (int) $c['events']; ?></td>
                            <td><?php echo ! empty( $c['top_cve'] ) ? '<span class="sf-ic-cve-tag">' . esc_html( $c['top_cve'] ) . '</span>' : '—'; ?></td>
                            <td><?php echo ! empty( $c['top_endpoint'] ) ? esc_html( $c['top_endpoint'] ) : '—'; ?></td>
                        </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
        <?php else : ?>
            <p class="sf-ic-empty"><?php esc_html_e( 'Noch keine Daten — der Sensor sammelt.', 'brainwerk-security-suite' ); ?></p>
        <?php endif; ?>
    </div>

    <!-- ============ Angriffsarten — kurz erklärt ============ -->
    <div class="sf-ic-card">
        <h2><?php esc_html_e( 'Angriffsarten — kurz erklärt', 'brainwerk-security-suite' ); ?></h2>
        <div class="sf-ic-explain-grid">
            <div class="sf-ic-explain">
                <h4><?php esc_html_e( 'Brute-Force', 'brainwerk-security-suite' ); ?></h4>
                <p><?php esc_html_e( 'Automatisiertes Durchprobieren von Passwörtern gegen den Login.', 'brainwerk-security-suite' ); ?></p>
                <p class="protect"><?php esc_html_e( 'Schutz: Sperren nach Fehlversuchen, 2FA.', 'brainwerk-security-suite' ); ?></p>
            </div>
            <div class="sf-ic-explain">
                <h4><?php esc_html_e( 'Honeypot', 'brainwerk-security-suite' ); ?></h4>
                <p><?php esc_html_e( 'Ein unsichtbares Köder-Feld — nur Bots füllen es aus.', 'brainwerk-security-suite' ); ?></p>
                <p class="protect"><?php esc_html_e( 'Schutz: Einreichung wird stumm verworfen.', 'brainwerk-security-suite' ); ?></p>
            </div>
            <div class="sf-ic-explain">
                <h4><?php esc_html_e( 'Probing/404', 'brainwerk-security-suite' ); ?></h4>
                <p><?php esc_html_e( 'Scanner suchen nach bekannten Pfaden und Sicherheitslücken.', 'brainwerk-security-suite' ); ?></p>
                <p class="protect"><?php esc_html_e( 'Schutz: Muster-Erkennung, Rate-Limiting.', 'brainwerk-security-suite' ); ?></p>
            </div>
            <div class="sf-ic-explain">
                <h4><?php esc_html_e( 'WAF-Block', 'brainwerk-security-suite' ); ?></h4>
                <p><?php esc_html_e( 'Eine Anfrage passte zu einer bekannten Angriffssignatur und wurde geblockt.', 'brainwerk-security-suite' ); ?></p>
                <p class="protect"><?php esc_html_e( 'Schutz: Signierte Virtual-Patch-Regeln aus dem Netzwerk.', 'brainwerk-security-suite' ); ?></p>
            </div>
            <div class="sf-ic-explain">
                <h4><?php esc_html_e( 'Malware-Fund', 'brainwerk-security-suite' ); ?></h4>
                <p><?php esc_html_e( 'Verdächtiger Code-Fund im Dateisystem — möglicher Kompromittierungshinweis.', 'brainwerk-security-suite' ); ?></p>
                <p class="protect"><?php esc_html_e( 'Schutz: Datei-Integritätsscan, Scanner-Tab prüfen.', 'brainwerk-security-suite' ); ?></p>
            </div>
            <div class="sf-ic-explain">
                <h4><?php esc_html_e( 'Anomalie', 'brainwerk-security-suite' ); ?></h4>
                <p><?php esc_html_e( 'Ein Login weicht stark vom gewohnten Verhalten des Kontos ab.', 'brainwerk-security-suite' ); ?></p>
                <p class="protect"><?php esc_html_e( 'Schutz: Statistische Verhaltensanalyse, Benachrichtigung.', 'brainwerk-security-suite' ); ?></p>
            </div>
        </div>
    </div>

    <!-- ============ Immunisierungen ============ -->
    <div class="sf-ic-card">
        <h2><?php esc_html_e( 'Immunisierungen', 'brainwerk-security-suite' ); ?></h2>
        <p class="sf-ic-sub"><?php esc_html_e( 'Netzweit reifende Schutzregeln — vom stillen Mitlesen bis zur aktiven Blockade.', 'brainwerk-security-suite' ); ?></p>

        <?php if ( $immun_banner_rule ) : ?>
            <div class="sf-ic-alert good sf-ic-immun-banner">
                <div class="sf-ic-alert-body">
                    <?php
                    printf(
                        /* translators: %s: plain-language explanation of the newly active immun rule */
                        esc_html__( '✓ Neue Immunisierung aktiv: %s', 'brainwerk-security-suite' ),
                        esc_html( isset( $immun_banner_rule['explanation'] ) ? (string) $immun_banner_rule['explanation'] : (string) $immun_banner_rule['key'] )
                    );
                    ?>
                </div>
            </div>
        <?php endif; ?>

        <?php if ( ! $immun['settings']['immunize_enabled'] ) : ?>
            <p class="sf-ic-empty"><?php esc_html_e( 'Netz-Immunisierungen sind deaktiviert (Einstellung „intel_immunize“).', 'brainwerk-security-suite' ); ?></p>
        <?php elseif ( ! $immun['settings']['participation'] ) : ?>
            <p class="sf-ic-empty"><?php esc_html_e( 'Nur mit aktiver Teilnahme am Threat-Network verfügbar — siehe „Teilnahme & Datenschutz“ unten.', 'brainwerk-security-suite' ); ?></p>
        <?php elseif ( empty( $immun['rules'] ) ) : ?>
            <p class="sf-ic-empty"><?php esc_html_e( 'Derzeit keine Netz-Immunisierungen aktiv.', 'brainwerk-security-suite' ); ?></p>
        <?php else : ?>
            <table class="sf-ic-table sf-ic-immun-table">
                <thead>
                    <tr>
                        <th><?php esc_html_e( 'Stufe', 'brainwerk-security-suite' ); ?></th>
                        <th><?php esc_html_e( 'Warum bin ich davon geschützt?', 'brainwerk-security-suite' ); ?></th>
                        <th><?php esc_html_e( 'Ziel / Muster', 'brainwerk-security-suite' ); ?></th>
                        <th><?php esc_html_e( 'Reife (lokal)', 'brainwerk-security-suite' ); ?></th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach ( (array) $immun['rules'] as $ir ) :
                        if ( ! is_array( $ir ) || empty( $ir['key'] ) ) {
                            continue;
                        }
                        $ir_key    = (string) $ir['key'];
                        $ir_stage  = isset( $immun_stage_labels[ $ir['stage'] ?? '' ] ) ? (string) $ir['stage'] : 'shadow';
                        $ir_counts = isset( $immun['counters'][ $ir_key ] ) && is_array( $immun['counters'][ $ir_key ] ) ? $immun['counters'][ $ir_key ] : array();
                        ?>
                        <tr>
                            <td><span class="sf-ic-immun-badge <?php echo esc_attr( $immun_stage_badge[ $ir_stage ] ); ?>"><?php echo esc_html( $immun_stage_labels[ $ir_stage ] ); ?></span></td>
                            <td><?php echo esc_html( isset( $ir['explanation'] ) ? (string) $ir['explanation'] : '—' ); ?></td>
                            <td>
                                <code class="sf-ic-immun-mono">
                                    <?php echo esc_html( isset( $ir['target'] ) ? (string) $ir['target'] : '—' ); ?>:
                                    <?php echo esc_html( isset( $ir['pattern'] ) ? (string) $ir['pattern'] : '' ); ?>
                                </code>
                            </td>
                            <td class="sf-ic-immun-counts">
                                <?php
                                printf(
                                    /* translators: 1: shadow hit count, 2: canary hit count, 3: false-positive-suspected count */
                                    esc_html__( 'Schatten-Treffer: %1$d · Canary-Treffer: %2$d · FP-Verdacht: %3$d', 'brainwerk-security-suite' ),
                                    (int) ( $ir_counts['shadow'] ?? 0 ),
                                    (int) ( $ir_counts['canary'] ?? 0 ),
                                    (int) ( $ir_counts['fp'] ?? 0 )
                                );
                                ?>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
        <?php endif; ?>
    </div>

    <!-- ============ Teilnahme & Datenschutz ============ -->
    <div class="shieldforge-card">
        <h2><?php esc_html_e( 'Teilnahme & Datenschutz', 'brainwerk-security-suite' ); ?></h2>

        <table class="form-table" role="presentation">
            <tr>
                <th scope="row"><?php esc_html_e( 'Participation', 'brainwerk-security-suite' ); ?></th>
                <td>
                    <?php if ( $enabled ) : ?>
                        <span class="sf-pill sf-pill-ok"><?php esc_html_e( 'Opted in', 'brainwerk-security-suite' ); ?></span>
                    <?php else : ?>
                        <span class="sf-pill"><?php esc_html_e( 'Off', 'brainwerk-security-suite' ); ?></span>
                    <?php endif; ?>
                </td>
            </tr>
            <tr>
                <th scope="row"><?php esc_html_e( 'Registration', 'brainwerk-security-suite' ); ?></th>
                <td>
                    <?php if ( $registered ) : ?>
                        <span class="sf-pill sf-pill-ok"><?php esc_html_e( 'Registered', 'brainwerk-security-suite' ); ?></span>
                        <code><?php echo esc_html( $reg['site_id'] ); ?></code>
                    <?php else : ?>
                        <span class="sf-pill sf-pill-warn"><?php esc_html_e( 'Not registered', 'brainwerk-security-suite' ); ?></span>
                    <?php endif; ?>
                </td>
            </tr>
            <tr>
                <th scope="row"><?php esc_html_e( 'Correlation salt', 'brainwerk-security-suite' ); ?></th>
                <td>
                    <?php if ( $salt_fresh ) : ?>
                        <span class="sf-pill sf-pill-ok"><?php esc_html_e( 'Current', 'brainwerk-security-suite' ); ?></span>
                        <?php printf( esc_html__( 'epoch %s', 'brainwerk-security-suite' ), '<code>' . esc_html( $epoch ) . '</code>' ); // phpcs:ignore WordPress.Security.EscapeOutput ?>
                    <?php elseif ( $registered ) : ?>
                        <span class="sf-pill sf-pill-warn"><?php esc_html_e( 'Stale — refresh below', 'brainwerk-security-suite' ); ?></span>
                    <?php else : ?>
                        <span class="sf-pill"><?php esc_html_e( 'Local placeholder (no cross-site correlation until registered)', 'brainwerk-security-suite' ); ?></span>
                    <?php endif; ?>
                </td>
            </tr>
            <tr>
                <th scope="row"><?php esc_html_e( 'Queue', 'brainwerk-security-suite' ); ?></th>
                <td>
                    <?php
                    printf(
                        esc_html__( '%1$d pending · %2$d sent total · %3$d dropped', 'brainwerk-security-suite' ),
                        (int) $stats['pending'], (int) $stats['queued_total'], (int) $stats['dropped_total']
                    );
                    ?>
                </td>
            </tr>
        </table>

        <?php if ( $registered ) : ?>
            <form method="post" style="display:inline-block;margin-right:8px">
                <?php wp_nonce_field( Shieldforge_Sensor::ACTION_NONCE ); ?>
                <input type="hidden" name="shieldforge_action" value="sensor_send_now">
                <button class="button"><?php esc_html_e( 'Send queued now', 'brainwerk-security-suite' ); ?></button>
            </form>
            <form method="post" style="display:inline-block;margin-right:8px">
                <?php wp_nonce_field( Shieldforge_Sensor::ACTION_NONCE ); ?>
                <input type="hidden" name="shieldforge_action" value="sensor_fetch_salt">
                <button class="button"><?php esc_html_e( 'Refresh salt', 'brainwerk-security-suite' ); ?></button>
            </form>
            <form method="post" style="display:inline-block" onsubmit="return confirm('<?php echo esc_js( __( 'Unregister this site? No further data will be sent.', 'brainwerk-security-suite' ) ); ?>');">
                <?php wp_nonce_field( Shieldforge_Sensor::ACTION_NONCE ); ?>
                <input type="hidden" name="shieldforge_action" value="sensor_unregister">
                <button class="button button-link-delete"><?php esc_html_e( 'Unregister', 'brainwerk-security-suite' ); ?></button>
            </form>
        <?php endif; ?>

        <form method="post" class="shieldforge-form" style="margin-top:14px">
            <?php wp_nonce_field( Shieldforge_Admin::NONCE ); ?>
            <input type="hidden" name="shieldforge_action" value="save_settings">
            <input type="hidden" name="shieldforge_tab_keys[]" value="sf_site_cc_autodetect">
            <table class="form-table" role="presentation">
                <tr>
                    <th scope="row"><?php esc_html_e( 'Serverstandort-Ländercode', 'brainwerk-security-suite' ); ?></th>
                    <td>
                        <input type="text" class="small-text" style="text-transform:uppercase" maxlength="2"
                               name="shieldforge[sf_site_cc_override]"
                               value="<?php echo esc_attr( Shieldforge_Settings::get( Shieldforge_Geo::SITE_CC_OVERRIDE, '' ) ); ?>"
                               placeholder="AT">
                        <p class="description"><?php esc_html_e( 'Manuelle Vorgabe (2-stelliger Ländercode) für die "Ziel"-Achse der Angriffs-Korridore. Hat Vorrang vor der automatischen Erkennung. Leer lassen zum Deaktivieren.', 'brainwerk-security-suite' ); ?></p>
                    </td>
                </tr>
                <tr>
                    <th scope="row"><?php esc_html_e( 'Automatische Erkennung', 'brainwerk-security-suite' ); ?></th>
                    <td>
                        <label class="shieldforge-toggle">
                            <input type="checkbox" name="shieldforge[sf_site_cc_autodetect]" value="1"
                                   <?php checked( Shieldforge_Settings::get( Shieldforge_Geo::SITE_CC_AUTODETECT, false ) ); ?>>
                            <span><?php esc_html_e( 'Serverstandort automatisch erkennen (einmaliger Abruf der eigenen Server-IP über api.ipify.org)', 'brainwerk-security-suite' ); ?></span>
                        </label>
                        <p class="description"><?php esc_html_e( 'Standardmäßig aus — ohne Ländercode-Vorgabe und ohne automatische Erkennung macht das Plugin keinen ausgehenden Aufruf und zeigt den Serverstandort als "Unbekannt".', 'brainwerk-security-suite' ); ?></p>
                    </td>
                </tr>
            </table>
            <p><button type="submit" class="button"><?php esc_html_e( 'Save', 'brainwerk-security-suite' ); ?></button></p>
        </form>
    </div>

    <form method="post" class="shieldforge-form">
        <?php wp_nonce_field( Shieldforge_Admin::NONCE ); ?>
        <input type="hidden" name="shieldforge_action" value="save_settings">
        <input type="hidden" name="shieldforge_tab_keys[]" value="sensor_enabled">
        <input type="hidden" name="shieldforge_tab_keys[]" value="sensor_share_with_feed">

        <div class="shieldforge-card">
            <h2><?php esc_html_e( 'Participation (opt-in)', 'brainwerk-security-suite' ); ?></h2>
            <label class="shieldforge-toggle">
                <input type="checkbox" name="shieldforge[sensor_enabled]" value="1" <?php checked( $enabled ); ?>>
                <span><?php esc_html_e( 'Contribute privacy-preserving threat telemetry to the network', 'brainwerk-security-suite' ); ?></span>
            </label>
            <p class="description">
                <?php esc_html_e( 'When on, attack indicators (never raw IPs or personal data) are queued and sent to the EU-hosted central network so every participating site is protected by what the others see. Default off.', 'brainwerk-security-suite' ); ?>
            </p>
            <label class="shieldforge-toggle">
                <input type="checkbox" name="shieldforge[sensor_share_with_feed]" value="1" <?php checked( Shieldforge_Settings::get( 'sensor_share_with_feed' ) ); ?>>
                <span><?php esc_html_e( 'Also allow my indicators in the shared redistribution feed', 'brainwerk-security-suite' ); ?></span>
            </label>
        </div>

        <div class="shieldforge-card">
            <h2><?php esc_html_e( 'Connection', 'brainwerk-security-suite' ); ?></h2>
            <table class="form-table" role="presentation">
                <tr>
                    <th scope="row"><?php esc_html_e( 'API endpoint', 'brainwerk-security-suite' ); ?></th>
                    <td>
                        <input type="url" class="regular-text" name="shieldforge[sensor_api_base]"
                               value="<?php echo esc_attr( $api_base ); ?>" placeholder="https://shieldforge-intel.brainwerk.at">
                        <p class="description"><?php esc_html_e( 'EU-hosted central network. Change only if you run your own instance.', 'brainwerk-security-suite' ); ?></p>
                    </td>
                </tr>
                <tr>
                    <th scope="row"><?php esc_html_e( 'Register token', 'brainwerk-security-suite' ); ?></th>
                    <td>
                        <input type="text" class="regular-text" name="shieldforge[sensor_register_token]"
                               value="<?php echo esc_attr( $token ); ?>" autocomplete="off">
                        <p class="description"><?php esc_html_e( 'One-time bootstrap token from the network operator. Needed once to register this site.', 'brainwerk-security-suite' ); ?></p>
                    </td>
                </tr>
            </table>
        </div>

        <p>
            <button type="submit" class="button button-primary"><?php esc_html_e( 'Save', 'brainwerk-security-suite' ); ?></button>
        </p>
    </form>

    <?php if ( ! $registered ) : ?>
        <div class="shieldforge-card">
            <h2><?php esc_html_e( 'Register this site', 'brainwerk-security-suite' ); ?></h2>
            <p class="description"><?php esc_html_e( 'Save the API endpoint + register token above first, then register. Registration exchanges the token for a pseudonymous site identity and secret.', 'brainwerk-security-suite' ); ?></p>
            <form method="post">
                <?php wp_nonce_field( Shieldforge_Sensor::ACTION_NONCE ); ?>
                <input type="hidden" name="shieldforge_action" value="sensor_register">
                <button class="button button-primary" <?php disabled( '' === $token ); ?>><?php esc_html_e( 'Register now', 'brainwerk-security-suite' ); ?></button>
            </form>
        </div>
    <?php endif; ?>

    <div class="shieldforge-card">
        <h2><?php esc_html_e( 'Transparency — what gets sent', 'brainwerk-security-suite' ); ?></h2>
        <p class="description"><?php esc_html_e( 'The most recent items queued for the network. Only the fields listed leave your site; identifiers are salted hashes, never raw values.', 'brainwerk-security-suite' ); ?></p>
        <?php if ( empty( $audit ) ) : ?>
            <p><em><?php esc_html_e( 'Nothing queued yet.', 'brainwerk-security-suite' ); ?></em></p>
        <?php else : ?>
            <table class="widefat striped">
                <thead><tr>
                    <th><?php esc_html_e( 'When (UTC)', 'brainwerk-security-suite' ); ?></th>
                    <th><?php esc_html_e( 'Category', 'brainwerk-security-suite' ); ?></th>
                    <th><?php esc_html_e( 'Fields sent', 'brainwerk-security-suite' ); ?></th>
                    <th><?php esc_html_e( 'IP indicator', 'brainwerk-security-suite' ); ?></th>
                </tr></thead>
                <tbody>
                <?php foreach ( $audit as $row ) : ?>
                    <tr>
                        <td><?php echo esc_html( isset( $row['ts'] ) ? $row['ts'] : '' ); ?></td>
                        <td><?php echo esc_html( isset( $row['category'] ) ? $row['category'] : '' ); ?></td>
                        <td><code><?php echo esc_html( ! empty( $row['fields'] ) ? implode( ', ', (array) $row['fields'] ) : '—' ); ?></code></td>
                        <td><code><?php echo esc_html( ! empty( $row['ip_indicator'] ) ? $row['ip_indicator'] : '—' ); ?></code></td>
                    </tr>
                <?php endforeach; ?>
                </tbody>
            </table>
        <?php endif; ?>
    </div>

</div>
