<?php
require_once __DIR__ . '/db/auth.php';
require_once __DIR__ . '/db/config.php';

function index_scan_normalize_rarity(?string $rarity): string
{
    return strtoupper(trim((string) $rarity));
}

function index_scan_rarity_class(?string $rarity): string
{
    return match (index_scan_normalize_rarity($rarity)) {
        'L' => 'scan-rarity-L',
        'E' => 'scan-rarity-E',
        'R' => 'scan-rarity-R',
        'U' => 'scan-rarity-U',
        'C' => 'scan-rarity-C',
        default => 'scan-rarity-none',
    };
}

function index_scan_rarity_label(?string $rarity): string
{
    return match (index_scan_normalize_rarity($rarity)) {
        'L' => 'Légendaire',
        'E' => 'Épique',
        'R' => 'Rare',
        'U' => 'Peu commun',
        'C' => 'Commun',
        default => 'Non définie',
    };
}

function index_itemcustom_display_value($value): string
{
    if ($value === null || $value === '') {
        return '0';
    }

    if (is_numeric($value)) {
        $formatted = number_format((float) $value, 2, '.', '');
        $formatted = rtrim(rtrim($formatted, '0'), '.');
        return $formatted === '' ? '0' : $formatted;
    }

    return trim((string) $value) !== '' ? trim((string) $value) : '0';
}

function index_itemcustom_stat_preview(?string $sign, $value, ?string $unit): string
{
    $prefix = $sign === '-' ? '-' : ($sign === '+' ? '+' : '');
    $displayValue = index_itemcustom_display_value($value);
    $displayUnit = trim((string) ($unit ?? ''));

    return trim($prefix . $displayValue . ($displayUnit !== '' ? ' ' . $displayUnit : ''));
}

function index_vanilla_description_html(?string $description): string
{
    $description = trim((string) $description);
    if ($description === '') {
        return '<span class="vanilla-db-muted">Aucune description.</span>';
    }

    if ($description !== strip_tags($description)) {
        return $description;
    }

    return nl2br(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'));
}


function index_vanilla_uex_normalize_whitespace(string $value): string
{
    return trim((string) preg_replace('/\s+/u', ' ', html_entity_decode(strip_tags($value), ENT_QUOTES | ENT_HTML5, 'UTF-8')));
}

function index_vanilla_uex_normalize_search_text(string $value): string
{
    $value = function_exists('mb_strtolower')
        ? mb_strtolower($value, 'UTF-8')
        : strtolower($value);

    $value = preg_replace('/[^[:alnum:]]+/u', ' ', $value);
    return trim((string) preg_replace('/\s+/u', ' ', $value));
}

function index_vanilla_uex_normalize_compact_search_text(string $value): string
{
    $value = function_exists('mb_strtolower')
        ? mb_strtolower($value, 'UTF-8')
        : strtolower($value);

    return trim((string) preg_replace('/[^[:alnum:]]+/u', '', $value));
}

function index_vanilla_uex_tokenize_search_text(string $value): array
{
    $normalizedValue = index_vanilla_uex_normalize_search_text($value);
    if ($normalizedValue === '') {
        return [];
    }

    $tokens = array_values(array_filter(explode(' ', $normalizedValue), static function (string $token): bool {
        return preg_match('/\d/u', $token) || strlen($token) >= 2;
    }));

    return array_values(array_unique($tokens));
}

function index_vanilla_uex_extract_wts_subject(string $title): string
{
    $normalizedTitle = index_vanilla_uex_normalize_search_text($title);
    if ($normalizedTitle === '') {
        return '';
    }

    if (!preg_match('/\bwts\b/u', $normalizedTitle, $matches, PREG_OFFSET_CAPTURE)) {
        return '';
    }

    $matchText = (string) ($matches[0][0] ?? 'wts');
    $matchOffset = (int) ($matches[0][1] ?? 0);
    $subject = trim(substr($normalizedTitle, $matchOffset + strlen($matchText)));

    while ($subject !== '') {
        $updated = trim((string) preg_replace('/^(?:wts|wtb|lts|ltb|sell|selling|trade|trading|for|offer|offering|looking|lf|want|wanted)\b[\s\-:]*/u', '', $subject));
        if ($updated === $subject) {
            break;
        }

        $subject = $updated;
    }

    $subject = trim((string) preg_replace('/^(?:[a-z]{1,4}\s+)?\d+(?:\s+\d+)*(?:\s*[\-:])\s*/u', '', $subject));
    return $subject;
}

function index_vanilla_uex_title_has_wts_marker(string $title): bool
{
    return index_vanilla_uex_extract_wts_subject($title) !== '';
}

function index_vanilla_uex_title_match_score(string $title, string $queryName): int
{
    $normalizedTitle = index_vanilla_uex_extract_wts_subject($title);
    $normalizedQuery = index_vanilla_uex_normalize_search_text($queryName);
    $compactTitle = index_vanilla_uex_normalize_compact_search_text($normalizedTitle);
    $compactQuery = index_vanilla_uex_normalize_compact_search_text($normalizedQuery);

    if ($normalizedTitle === '' || $normalizedQuery === '' || $compactTitle === '' || $compactQuery === '') {
        return 0;
    }

    if ($normalizedTitle === $normalizedQuery || $compactTitle === $compactQuery) {
        return 3;
    }

    if (strpos($normalizedTitle, $normalizedQuery) !== false || strpos($compactTitle, $compactQuery) !== false) {
        return 2;
    }

    $queryTokens = index_vanilla_uex_tokenize_search_text($normalizedQuery);
    if ($queryTokens === []) {
        return 0;
    }

    foreach ($queryTokens as $token) {
        if (strpos($normalizedTitle, $token) === false) {
            return 0;
        }
    }

    return 1;
}

function index_vanilla_uex_title_matches_query(string $title, string $queryName): bool
{
    return index_vanilla_uex_title_match_score($title, $queryName) > 0;
}

function index_vanilla_uex_extract_price_value(string $rawPrice): ?int
{
    $rawPrice = trim($rawPrice);
    if ($rawPrice === '') {
        return null;
    }

    if (!preg_match('/([0-9][0-9\s,\.]*)((?:\s*[KMB])?)\s*(?:A?UEC)\b/i', $rawPrice, $matches)) {
        return null;
    }

    $numberPart = preg_replace('/\s+/', '', (string) ($matches[1] ?? ''));
    $suffix = strtoupper(trim((string) ($matches[2] ?? '')));

    if ($numberPart === '') {
        return null;
    }

    if ($suffix !== '') {
        if (substr_count($numberPart, ',') === 1 && strpos($numberPart, '.') === false) {
            $numberPart = str_replace(',', '.', $numberPart);
        } else {
            $numberPart = str_replace(',', '', $numberPart);
        }
    } else {
        if (strpos($numberPart, ',') !== false && strpos($numberPart, '.') !== false) {
            if (strrpos($numberPart, ',') > strrpos($numberPart, '.')) {
                $numberPart = str_replace('.', '', $numberPart);
                $numberPart = str_replace(',', '.', $numberPart);
            } else {
                $numberPart = str_replace(',', '', $numberPart);
            }
        } else {
            $numberPart = str_replace(',', '', $numberPart);
        }
    }

    if (!is_numeric($numberPart)) {
        return null;
    }

    $value = (float) $numberPart;
    $multiplier = match ($suffix) {
        'K' => 1000,
        'M' => 1000000,
        'B' => 1000000000,
        default => 1,
    };

    return (int) round($value * $multiplier);
}

function index_vanilla_uex_parse_estimate_from_html(string $html, string $queryName, int $sampleLimit = 10): array
{
    $candidates = [];
    $chunks = preg_split('/<div\s+class="search-row\b[^>]*>/i', $html) ?: [];

    foreach ($chunks as $chunk) {
        if (!preg_match('/<a\b[^>]*class="text-bold"[^>]*>(.*?)<\/a>/is', $chunk, $titleMatches)) {
            continue;
        }

        $title = index_vanilla_uex_normalize_whitespace((string) ($titleMatches[1] ?? ''));
        if ($title === '' || !index_vanilla_uex_title_has_wts_marker($title)) {
            continue;
        }

        $matchScore = index_vanilla_uex_title_match_score($title, $queryName);
        if ($matchScore <= 0) {
            continue;
        }

        if (!preg_match('/<h4\b[^>]*>(.*?)<\/h4>/is', $chunk, $priceMatches)) {
            continue;
        }

        $priceValue = index_vanilla_uex_extract_price_value(index_vanilla_uex_normalize_whitespace((string) ($priceMatches[1] ?? '')));
        if ($priceValue === null) {
            continue;
        }

        $candidates[] = [
            'price' => $priceValue,
            'score' => $matchScore,
        ];
    }

    if ($candidates === []) {
        return [
            'has_estimate' => false,
            'average' => null,
            'formatted' => '—',
            'sample_count' => 0,
        ];
    }

    $bestScore = max(array_column($candidates, 'score'));
    $minimumAcceptedScore = $bestScore >= 3 ? 2 : $bestScore;
    $values = [];

    foreach ($candidates as $candidate) {
        if (($candidate['score'] ?? 0) < $minimumAcceptedScore) {
            continue;
        }

        $values[] = (int) $candidate['price'];
        if (count($values) >= $sampleLimit) {
            break;
        }
    }

    if ($values === []) {
        return [
            'has_estimate' => false,
            'average' => null,
            'formatted' => '—',
            'sample_count' => 0,
        ];
    }

    $average = (int) round(array_sum($values) / count($values));

    return [
        'has_estimate' => true,
        'average' => $average,
        'formatted' => '~' . number_format($average, 0, ',', ' ') . ' UEC',
        'sample_count' => count($values),
    ];
}

function index_vanilla_uex_create_handle(string $url, string $userAgent, int $connectTimeout, int $timeout)
{
    $handle = curl_init();
    curl_setopt_array($handle, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_CONNECTTIMEOUT => $connectTimeout,
        CURLOPT_TIMEOUT => $timeout,
        CURLOPT_USERAGENT => $userAgent,
        CURLOPT_ENCODING => '',
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2,
        CURLOPT_HTTPHEADER => [
            'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            'Accept-Language: fr-FR,fr;q=0.9,en;q=0.8',
            'Cache-Control: no-cache',
        ],
    ]);

    return $handle;
}

function index_vanilla_uex_fetch_single_body(string $url, string $userAgent, int $connectTimeout = 8, int $timeout = 18): ?string
{
    $handle = index_vanilla_uex_create_handle($url, $userAgent, $connectTimeout, $timeout);
    $body = curl_exec($handle);
    $error = curl_error($handle);
    $httpCode = (int) curl_getinfo($handle, CURLINFO_RESPONSE_CODE);
    curl_close($handle);

    if (!is_string($body) || $error !== '' || $httpCode < 200 || $httpCode >= 300 || trim($body) === '') {
        return null;
    }

    return $body;
}

function index_vanilla_uex_fetch_estimates(array $names, int $sampleLimit = 10): array
{
    $results = [];
    $uniqueNames = [];

    foreach ($names as $name) {
        $name = trim((string) $name);
        if ($name === '' || isset($uniqueNames[$name])) {
            continue;
        }

        $uniqueNames[$name] = $name;
    }

    if ($uniqueNames === []) {
        return $results;
    }

    $userAgent = 'Mozilla/5.0 (compatible; FlatLogicVanillaDb/1.0; +https://uexcorp.space/)';
    $batchSize = 4;

    foreach (array_chunk(array_values($uniqueNames), $batchSize) as $nameBatch) {
        $multiHandle = curl_multi_init();
        $handles = [];

        foreach ($nameBatch as $name) {
            $url = 'https://uexcorp.space/search?q=' . rawurlencode($name);
            $handle = index_vanilla_uex_create_handle($url, $userAgent, 6, 12);
            curl_multi_add_handle($multiHandle, $handle);
            $handles[$name] = [
                'handle' => $handle,
                'url' => $url,
            ];
        }

        $running = null;
        do {
            $status = curl_multi_exec($multiHandle, $running);
            if ($running) {
                curl_multi_select($multiHandle, 1.0);
            }
        } while ($running && $status === CURLM_OK);

        foreach ($handles as $name => $payload) {
            $handle = $payload['handle'];
            $url = $payload['url'];
            $error = curl_error($handle);
            $httpCode = (int) curl_getinfo($handle, CURLINFO_RESPONSE_CODE);
            $body = (string) curl_multi_getcontent($handle);

            curl_multi_remove_handle($multiHandle, $handle);
            curl_close($handle);

            if ($error !== '' || $httpCode < 200 || $httpCode >= 300 || trim($body) === '') {
                $body = index_vanilla_uex_fetch_single_body($url, $userAgent) ?? '';
            }

            if (trim($body) === '') {
                $results[$name] = [
                    'has_estimate' => false,
                    'average' => null,
                    'formatted' => 'Indisponible',
                    'sample_count' => 0,
                    'error' => true,
                ];
                continue;
            }

            $results[$name] = index_vanilla_uex_parse_estimate_from_html($body, $name, $sampleLimit);
            $results[$name]['error'] = false;
        }

        curl_multi_close($multiHandle);
    }

    return $results;
}

auth_start_session();
auth_bootstrap();

$session_cl_auth_user = isset($_SESSION['user']) ? (string) $_SESSION['user'] : '';
$session_cl_auth_right = isset($_SESSION['role']) ? (string) $_SESSION['role'] : '';
$is_authenticated = $session_cl_auth_user !== '';
$has_member_access = $is_authenticated && in_array($session_cl_auth_right, ['member', 'admin'], true);
$has_vanilla_db_access = $is_authenticated && in_array($session_cl_auth_right, ['member', 'moderator', 'admin'], true);

if (isset($_GET['ajax']) && (string) $_GET['ajax'] === 'vanilla-price-estimates') {
    header('Content-Type: application/json; charset=UTF-8');

    if (!$has_vanilla_db_access) {
        http_response_code(403);
        echo json_encode([
            'ok' => false,
            'message' => 'Accès refusé.',
            'estimates' => new stdClass(),
        ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        exit;
    }

    $requestedNames = $_GET['names'] ?? [];
    if (!is_array($requestedNames)) {
        $requestedNames = [$requestedNames];
    }

    $requestedNames = array_slice(array_values(array_filter(array_map('strval', $requestedNames), static fn ($name): bool => trim($name) !== '')), 0, 10);
    $estimates = index_vanilla_uex_fetch_estimates($requestedNames, 10);

    echo json_encode([
        'ok' => true,
        'estimates' => $estimates,
    ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

$scan_reference_rows = [];
$scan_reference_max_occurrence = 0;
$scan_reference_error = null;
$ship_preset_rows = [];
$ship_preset_manufacturers = [];
$ship_preset_error = null;
$item_custom_public_rows = [];
$item_custom_public_types = [];
$item_custom_public_error = null;
$vanilla_db_rows = [];
$vanilla_db_error = null;
$vanilla_db_search = '';
$vanilla_db_per_page = 10;
$vanilla_db_total_rows = 0;
$vanilla_db_total_pages = 1;
$vanilla_db_current_page = 1;
$vanilla_db_result_start = 0;
$vanilla_db_result_end = 0;
$vanilla_db_base_query = ['open_modal' => 'vanilla-db'];
$vanilla_db_reset_url = 'index.php?open_modal=vanilla-db';
$should_open_vanilla_db_modal = false;

try {
    $db = db();
    $stmt_scan_reference = $db->query(
        "SELECT o.cl_scobjs_id, o.cl_scobjs_name, o.cl_scobjs_rarity, m.cl_scmining_scan_value, m.cl_scmining_max_occurrence,
                m.cl_scmining_can_manual, m.cl_scmining_can_land, m.cl_scmining_can_space
         FROM tbl_scmining m
         INNER JOIN tbl_scobjs o ON o.cl_scobjs_id = m.cl_scmining_obj_id
         ORDER BY
            CASE UPPER(COALESCE(o.cl_scobjs_rarity, ''))
                WHEN 'L' THEN 1
                WHEN 'E' THEN 2
                WHEN 'R' THEN 3
                WHEN 'U' THEN 4
                WHEN 'C' THEN 5
                ELSE 6
            END,
            o.cl_scobjs_name ASC"
    );

    foreach ($stmt_scan_reference->fetchAll() as $row) {
        $occurrence_count = max(1, (int) ($row['cl_scmining_max_occurrence'] ?? 1));
        $scan_value = (int) ($row['cl_scmining_scan_value'] ?? 0);
        $recovery_modes = [];

        if (!empty($row['cl_scmining_can_manual'])) {
            $recovery_modes[] = 'Manuel';
        }
        if (!empty($row['cl_scmining_can_land'])) {
            $recovery_modes[] = 'Terrestre';
        }
        if (!empty($row['cl_scmining_can_space'])) {
            $recovery_modes[] = 'Spatial';
        }

        $scan_steps = [];
        for ($i = 1; $i <= $occurrence_count; $i++) {
            $scan_steps[] = $scan_value * $i;
        }

        $scan_reference_rows[] = [
            'id' => (string) ($row['cl_scobjs_id'] ?? ''),
            'name' => (string) ($row['cl_scobjs_name'] ?? ''),
            'rarity' => index_scan_normalize_rarity($row['cl_scobjs_rarity'] ?? ''),
            'rarity_label' => index_scan_rarity_label($row['cl_scobjs_rarity'] ?? ''),
            'rarity_class' => index_scan_rarity_class($row['cl_scobjs_rarity'] ?? ''),
            'recovery_modes' => $recovery_modes,
            'scan_steps' => $scan_steps,
            'max_occurrence' => $occurrence_count,
        ];

        $scan_reference_max_occurrence = max($scan_reference_max_occurrence, $occurrence_count);
    }
} catch (Throwable $e) {
    $scan_reference_error = 'Impossible de charger le tableau des signatures de scan pour le moment.';
}

if ($has_member_access) {
    try {
        if (!isset($db) || !($db instanceof PDO)) {
            $db = db();
        }

        $stmt_ship_presets = $db->query(
        "SELECT cl_scpreset_id, cl_scpreset_name, cl_scpreset_manufacturer, cl_scpreset_description, cl_scpreset_link, cl_scpreset_creator
         FROM tbl_scpreset
         ORDER BY cl_scpreset_manufacturer ASC, cl_scpreset_name ASC"
    );

    foreach ($stmt_ship_presets->fetchAll() as $row) {
        $ship_name = trim((string) ($row['cl_scpreset_name'] ?? '')) ?: 'Vaisseau inconnu';
        $manufacturer = trim((string) ($row['cl_scpreset_manufacturer'] ?? '')) ?: 'Manufacture inconnue';
        $manufacturer_key = function_exists('mb_strtolower')
            ? mb_strtolower($manufacturer, 'UTF-8')
            : strtolower($manufacturer);

        $ship_preset_manufacturers[$manufacturer_key] = $manufacturer;

        $ship_preset_rows[] = [
            'id' => (string) ($row['cl_scpreset_id'] ?? ''),
            'name' => $ship_name,
            'manufacturer' => $manufacturer,
            'creator' => trim((string) ($row['cl_scpreset_creator'] ?? '')) ?: 'Inconnu',
            'description' => trim((string) ($row['cl_scpreset_description'] ?? '')) ?: 'Aucune description disponible pour ce preset.',
            'link' => trim((string) ($row['cl_scpreset_link'] ?? '')),
        ];
    }

        natcasesort($ship_preset_manufacturers);
        $ship_preset_manufacturers = array_values($ship_preset_manufacturers);
    } catch (Throwable $e) {
        $ship_preset_error = 'Impossible de charger les presets de vaisseaux pour le moment.';
    }
}

if ($has_member_access) {
    try {
    if (!isset($db) || !($db instanceof PDO)) {
        $db = db();
    }

    $stmt_item_custom_public = $db->query(
        "SELECT
            c.cl_scitemcustom_id,
            o.cl_scobjs_name,
            o.cl_scobjs_uuid,
            o.cl_scobjs_type,
            o.cl_scobjs_subtype,
            COALESCE(NULLIF(TRIM(a.cl_auth_user), ''), 'Inconnu') AS creator_name,
            cs.cl_scitemcustomstat_id,
            cs.cl_scitemcustomstat_sign,
            cs.cl_scitemcustomstat_value,
            st.cl_scstatsitem_name,
            st.cl_scstatsitem_unit
         FROM tbl_scitemcustom c
         INNER JOIN tbl_scobjs o ON o.cl_scobjs_id = c.cl_scitemcustom_obj_id
         LEFT JOIN tbl_auth a ON a.cl_auth_id = c.cl_scitemcustom_owner_auth_id
         LEFT JOIN tbl_scitemcustomstat cs ON cs.cl_scitemcustomstat_itemcustom_id = c.cl_scitemcustom_id
         LEFT JOIN tbl_scstatsitem st ON st.cl_scstatsitem_id = cs.cl_scitemcustomstat_stat_id
         WHERE c.cl_scitemcustom_owner_auth_id IS NOT NULL
         ORDER BY o.cl_scobjs_name ASC, creator_name ASC, c.cl_scitemcustom_id ASC, st.cl_scstatsitem_name ASC, cs.cl_scitemcustomstat_id ASC"
    );

    $grouped_item_custom_public = [];

    foreach ($stmt_item_custom_public->fetchAll() as $row) {
        $item_id = (int) ($row['cl_scitemcustom_id'] ?? 0);
        if ($item_id <= 0) {
            continue;
        }

        if (!isset($grouped_item_custom_public[$item_id])) {
            $name = trim((string) ($row['cl_scobjs_name'] ?? '')) ?: 'Objet inconnu';
            $creator = trim((string) ($row['creator_name'] ?? '')) ?: 'Inconnu';
            $type = trim((string) ($row['cl_scobjs_type'] ?? ''));
            $subtype = trim((string) ($row['cl_scobjs_subtype'] ?? ''));
            $uuid = trim((string) ($row['cl_scobjs_uuid'] ?? ''));

            $grouped_item_custom_public[$item_id] = [
                'id' => $item_id,
                'name' => $name,
                'creator' => $creator,
                'type' => $type,
                'subtype' => $subtype,
                'uuid' => $uuid,
                'stats' => [],
                'search_parts' => [$name, $creator, $type, $subtype, $uuid],
            ];
        }

        if (!empty($row['cl_scitemcustomstat_id'])) {
            $stat_name = trim((string) ($row['cl_scstatsitem_name'] ?? '')) ?: 'Stat inconnue';
            $stat_sign = trim((string) ($row['cl_scitemcustomstat_sign'] ?? ''));
            $stat_value_raw = $row['cl_scitemcustomstat_value'] ?? 0;
            $stat_unit = trim((string) ($row['cl_scstatsitem_unit'] ?? ''));
            $stat_preview = index_itemcustom_stat_preview($stat_sign, $stat_value_raw, $stat_unit);

            $grouped_item_custom_public[$item_id]['stats'][] = [
                'name' => $stat_name,
                'preview' => $stat_preview,
            ];

            $grouped_item_custom_public[$item_id]['search_parts'][] = $stat_name;
            $grouped_item_custom_public[$item_id]['search_parts'][] = $stat_preview;
        }
    }

        $item_custom_public_types_lookup = [];

        foreach ($grouped_item_custom_public as $item_custom_public_row) {
            $item_custom_public_row['search'] = trim(implode(' ', array_filter($item_custom_public_row['search_parts'], static function ($value) {
                return trim((string) $value) !== '';
            })));
            unset($item_custom_public_row['search_parts']);
            $item_custom_public_rows[] = $item_custom_public_row;

            $item_custom_public_type_label = $item_custom_public_row['type'] !== '' ? $item_custom_public_row['type'] : 'Type inconnu';
            $item_custom_public_type_key = strtolower($item_custom_public_type_label);
            if (!isset($item_custom_public_types_lookup[$item_custom_public_type_key])) {
                $item_custom_public_types_lookup[$item_custom_public_type_key] = $item_custom_public_type_label;
            }
        }

        natcasesort($item_custom_public_types_lookup);
        $item_custom_public_types = array_values($item_custom_public_types_lookup);
    } catch (Throwable $e) {
        $item_custom_public_error = 'Impossible de charger les objets Item Custom pour le moment.';
    }
}

if ($has_vanilla_db_access) {
    $vanilla_db_search = trim((string) ($_GET['vanilla_search'] ?? ''));
    $vanilla_db_current_page = max(1, (int) ($_GET['vanilla_page'] ?? 1));
    $should_open_vanilla_db_modal = (
        (isset($_GET['open_modal']) && (string) $_GET['open_modal'] === 'vanilla-db')
        || $vanilla_db_search !== ''
        || isset($_GET['vanilla_page'])
    );

    $vanilla_db_base_query = ['open_modal' => 'vanilla-db'];
    if ($vanilla_db_search !== '') {
        $vanilla_db_base_query['vanilla_search'] = $vanilla_db_search;
    }
    $vanilla_db_reset_url = 'index.php?' . http_build_query(['open_modal' => 'vanilla-db']);

    try {
        if (!isset($db) || !($db instanceof PDO)) {
            $db = db();
        }

        $vanilla_db_where_sql = '';
        $vanilla_db_bindings = [];

        if ($vanilla_db_search !== '') {
            $vanilla_db_where_sql = "
                WHERE (
                    cl_scobjs_name LIKE :vanilla_search
                    OR cl_scobjs_type LIKE :vanilla_search
                    OR cl_scobjs_subtype LIKE :vanilla_search
                    OR cl_scobjs_uuid LIKE :vanilla_search
                    OR cl_scobjs_rarity LIKE :vanilla_search
                    OR cl_scobjs_description LIKE :vanilla_search
                )";
            $vanilla_db_bindings[':vanilla_search'] = '%' . $vanilla_db_search . '%';
        }

        $stmt_vanilla_db_count = $db->prepare(
            "SELECT COUNT(*)
             FROM tbl_scobjs" . $vanilla_db_where_sql
        );

        foreach ($vanilla_db_bindings as $bindingName => $bindingValue) {
            $stmt_vanilla_db_count->bindValue($bindingName, $bindingValue, PDO::PARAM_STR);
        }

        $stmt_vanilla_db_count->execute();
        $vanilla_db_total_rows = (int) $stmt_vanilla_db_count->fetchColumn();
        $vanilla_db_total_pages = max(1, (int) ceil($vanilla_db_total_rows / $vanilla_db_per_page));
        $vanilla_db_current_page = min($vanilla_db_current_page, $vanilla_db_total_pages);
        $vanilla_db_offset = ($vanilla_db_current_page - 1) * $vanilla_db_per_page;

        $stmt_vanilla_db = $db->prepare(
            "SELECT cl_scobjs_id, cl_scobjs_name, cl_scobjs_type, cl_scobjs_subtype, cl_scobjs_uuid, cl_scobjs_rarity, cl_scobjs_description
             FROM tbl_scobjs" . $vanilla_db_where_sql . "
             ORDER BY cl_scobjs_id DESC
             LIMIT :vanilla_limit OFFSET :vanilla_offset"
        );

        foreach ($vanilla_db_bindings as $bindingName => $bindingValue) {
            $stmt_vanilla_db->bindValue($bindingName, $bindingValue, PDO::PARAM_STR);
        }
        $stmt_vanilla_db->bindValue(':vanilla_limit', $vanilla_db_per_page, PDO::PARAM_INT);
        $stmt_vanilla_db->bindValue(':vanilla_offset', $vanilla_db_offset, PDO::PARAM_INT);
        $stmt_vanilla_db->execute();

        foreach ($stmt_vanilla_db->fetchAll() as $row) {
            $name = trim((string) ($row['cl_scobjs_name'] ?? '')) ?: 'Objet inconnu';
            $type = trim((string) ($row['cl_scobjs_type'] ?? '')) ?: '—';
            $subtype = trim((string) ($row['cl_scobjs_subtype'] ?? '')) ?: '—';
            $uuid = trim((string) ($row['cl_scobjs_uuid'] ?? '')) ?: '—';
            $rarity = index_scan_normalize_rarity($row['cl_scobjs_rarity'] ?? '');
            $description = trim((string) ($row['cl_scobjs_description'] ?? ''));

            $vanilla_db_rows[] = [
                'id' => (int) ($row['cl_scobjs_id'] ?? 0),
                'name' => $name,
                'type' => $type,
                'subtype' => $subtype,
                'uuid' => $uuid,
                'image_url' => $uuid !== '—' ? 'https://cstone.space/uifimages/' . rawurlencode($uuid) . '.png' : null,
                'rarity' => $rarity !== '' ? $rarity : '—',
                'rarity_label' => $rarity !== '' ? index_scan_rarity_label($rarity) : 'Non définie',
                'rarity_class' => index_scan_rarity_class($rarity),
                'description_html' => index_vanilla_description_html($description),
            ];
        }

        if ($vanilla_db_total_rows > 0) {
            $vanilla_db_result_start = $vanilla_db_offset + 1;
            $vanilla_db_result_end = $vanilla_db_offset + count($vanilla_db_rows);
        }
    } catch (Throwable $e) {
        $vanilla_db_error = 'Impossible de charger la base des objets pour le moment.';
    }
}
?>
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta name="keywords" content="BlackOps Agency, Star Citizen, Advocacy, UEE, Sécurité, Exploration, Renseignement, Patrouilles, Chasses de primes, Investigation, Neutralisation de menaces, Assistance humanitaire, Abordages, Réseaux anti-toxicité, Formation tactique, Entraînements, Coopération, Zones UEE, Systèmes inexplorés, Lore Star Citizen, Missions multi-joueurs, Protocole Arkange, Protocole Vigilance, Respect des lois impériales, Justice interstellaire, Criminalité galactique, Piraterie, XenoThreat, Vanduul, Sécurité spatiale, Leadership BlackOps, Collaboration stratégique, Combat spatial, Star Citizen gameplay, Exploration stratégique, Missions BlackOps Agency, Réputation UEE, Gestion des conflits, BlackOps, Agency, Recrutement Star Citizen, Zones de guerre, Star Citizen immersion.">
    
	<title>Rapid Emergency & Action Combat Team / Star Citizen</title>
    
	<link rel="stylesheet" type="text/css" href="css/styles.css">
	<link rel="stylesheet" type="text/css" href="css/default.css" />
	<link rel="stylesheet" type="text/css" href="css/component.css" />
	<link rel="stylesheet" type="text/css" href="css/switch.css" />
	<link rel="stylesheet" type="text/css" href="css/styles-modal.css" />
	<script src="js/modernizr.custom.js"></script>
	<style>
		.modal-scan-reference {
			width: 92%;
			max-width: 1400px;
			min-width: 960px;
		}

		.scan-reference-dialog {
			background: linear-gradient(180deg, rgba(24, 28, 37, 0.98), rgba(11, 14, 20, 0.98));
			border: 1px solid rgba(162, 155, 120, 0.35);
			box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45);
		}

		.scan-reference-dialog h3 {
			font-size: 1.8em;
			letter-spacing: 0.08em;
		}

		.scan-reference-dialog > div {
			padding: 22px 26px 26px;
		}

		.scan-reference-intro,
		.scan-reference-empty,
		.scan-reference-error {
			margin: 0 0 18px;
			padding: 12px 14px !important;
			border-radius: 10px;
			font-size: 0.95em;
			text-align: left !important;
		}

		.scan-reference-intro {
			background: rgba(162, 155, 120, 0.12);
			border: 1px solid rgba(162, 155, 120, 0.18);
		}

		.scan-reference-empty {
			background: rgba(255, 255, 255, 0.06);
			border: 1px solid rgba(255, 255, 255, 0.12);
		}

		.scan-reference-error {
			background: rgba(140, 32, 32, 0.18);
			border: 1px solid rgba(255, 88, 88, 0.25);
			color: #ffbdbd;
		}

		.scan-reference-filter-bar {
			display: flex;
			justify-content: space-between;
			align-items: center;
			gap: 14px;
			margin: 0 0 14px;
			padding: 10px 12px;
			border: 1px solid rgba(162, 155, 120, 0.18);
			border-radius: 10px;
			background: rgba(162, 155, 120, 0.07);
		}

		.scan-reference-filter-actions {
			display: flex;
			gap: 8px;
			flex-wrap: wrap;
		}

		.scan-reference-filter-btn {
			padding: 7px 12px;
			border: 1px solid rgba(162, 155, 120, 0.35);
			border-radius: 999px;
			background: rgba(162, 155, 120, 0.14);
			color: #f2eed9;
			font-size: 0.60em;
			font-weight: 700;
			letter-spacing: 0.06em;
			text-transform: uppercase;
			cursor: pointer;
			text-decoration: none;
			text-align: center;
		}

		.vanilla-db-search-btn {
			background: rgba(162, 155, 120, 0.2);
		}

		.scan-reference-filter-btn:hover,
		.scan-reference-filter-btn:focus-visible {
			background: rgba(162, 155, 120, 0.22);
			outline: none;
		}

		.scan-reference-filter-btn.is-disabled {
			opacity: 0.45;
			cursor: not-allowed;
		}

		.scan-reference-filter-status {
			margin: 0;
			font-size: 0.74em;
			color: rgba(255, 255, 255, 0.72);
			text-align: right;
		}

		.scan-reference-table-wrapper {
			max-height: 65vh;
			overflow: auto;
			border: 1px solid rgba(162, 155, 120, 0.22);
			border-radius: 12px;
			background: rgba(6, 9, 14, 0.65);
		}

		.scan-reference-table {
			width: 100%;
			border-collapse: collapse;
			min-width: 880px;
			font-size: 0.84em;
		}

		.scan-reference-table th,
		.scan-reference-table td {
			padding: 9px 11px;
			border-bottom: 1px solid rgba(255, 255, 255, 0.08);
			vertical-align: middle;
			text-align: left;
		}

		.scan-reference-table th {
			position: sticky;
			top: 0;
			z-index: 2;
			background: rgba(18, 22, 30, 0.96);
			text-transform: uppercase;
			font-size: 0.74em;
			letter-spacing: 0.08em;
			color: #d7cfac;
		}

		.scan-reference-table tbody tr {
			cursor: pointer;
			transition: background 0.18s ease, box-shadow 0.18s ease, opacity 0.18s ease;
		}

		.scan-reference-table tbody tr:hover {
			background: rgba(162, 155, 120, 0.08);
		}

		.scan-reference-table tbody tr.is-selected {
			background: rgba(162, 155, 120, 0.16);
			box-shadow: inset 0 0 0 1px rgba(162, 155, 120, 0.35);
		}

		.scan-reference-table tbody tr.is-hidden-by-filter {
			display: none;
		}

		.scan-reference-name span {
			display: block;
			font-weight: 700;
			font-size: 0.94em;
		}

		.scan-reference-recovery {
			min-width: 180px;
		}

		.scan-reference-pill {
			display: inline-block;
			margin: 0 5px 5px 0;
			padding: 4px 8px;
			border-radius: 999px;
			background: rgba(162, 155, 120, 0.16);
			border: 1px solid rgba(162, 155, 120, 0.24);
			font-size: 0.72em;
			white-space: nowrap;
		}

		.scan-reference-value {
			text-align: center;
			font-variant-numeric: tabular-nums;
			font-weight: 700;
			font-size: 0.92em;
			white-space: nowrap;
		}

		.scan-reference-muted {
			color: rgba(255, 255, 255, 0.35);
		}

		.scan-rarity-L .scan-reference-name span,
		.scan-rarity-L .scan-reference-value {
			color: #ff8000;
		}

		.scan-rarity-E .scan-reference-name span,
		.scan-rarity-E .scan-reference-value {
			color: #a335ee;
		}

		.scan-rarity-R .scan-reference-name span,
		.scan-rarity-R .scan-reference-value {
			color: #4db2ff;
		}

		.scan-rarity-U .scan-reference-name span,
		.scan-rarity-U .scan-reference-value {
			color: #1eff00;
		}

		.scan-rarity-C .scan-reference-name span,
		.scan-rarity-C .scan-reference-value {
			color: #ffffff;
		}

		.scan-rarity-none .scan-reference-name span,
		.scan-rarity-none .scan-reference-value {
			color: #b5bcc8;
		}

		.modal-ship-presets {
			width: 92%;
			max-width: 1320px;
			min-width: 940px;
		}

		.modal-item-custom {
			width: 94%;
			max-width: 1500px;
			min-width: 1040px;
		}

		.modal-vanilla-db {
			width: 92%;
			max-width: 1440px;
			min-width: 980px;
		}

		.item-custom-dialog {
			display: flex;
			flex-direction: column;
			background: linear-gradient(180deg, rgba(15, 20, 29, 0.98), rgba(7, 10, 16, 0.98));
			border: 1px solid rgba(162, 155, 120, 0.35);
			box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45);
			max-height: min(88vh, 980px);
		}

		.item-custom-dialog h3 {
			font-size: 1.75em;
			letter-spacing: 0.08em;
		}

		.item-custom-dialog > div {
			display: flex;
			flex-direction: column;
			flex: 1 1 auto;
			min-height: 0;
			overflow: hidden;
			padding: 22px 26px 26px;
		}

		.item-custom-empty,
		.item-custom-error {
			margin: 0 0 18px;
			padding: 12px 14px !important;
			border-radius: 10px;
			font-size: 0.95em;
			text-align: left !important;
		}


		.item-custom-empty {
			background: rgba(255, 255, 255, 0.06);
			border: 1px solid rgba(255, 255, 255, 0.12);
		}

		.item-custom-error {
			background: rgba(140, 32, 32, 0.18);
			border: 1px solid rgba(255, 88, 88, 0.25);
			color: #ffbdbd;
		}

		.item-custom-filter-bar {
			display: flex;
			flex-direction: column;
			align-items: stretch;
			gap: 10px;
			margin: 0 0 18px;
			padding: 14px 16px;
			border-radius: 14px;
			background: rgba(255, 255, 255, 0.04);
			border: 1px solid rgba(162, 155, 120, 0.18);
		}

		.item-custom-filter-top {
			display: flex;
			align-items: center;
			gap: 14px;
			width: 100%;
		}

		.item-custom-search-wrap {
			display: flex;
			align-items: center;
			gap: 12px;
			flex: 1 1 auto;
			min-width: 0;
		}

		.item-custom-type-filters {
			display: flex;
			align-items: flex-start;
			gap: 8px;
			width: 100%;
		}

		.item-custom-type-label {
			font-size: 0.64em;
			font-weight: 700;
			letter-spacing: 0.08em;
			text-transform: uppercase;
			color: rgba(255, 255, 255, 0.62);
		}

		.item-custom-type-options {
			display: flex;
			align-items: center;
			gap: 6px;
			flex-wrap: wrap;
		}

		.item-custom-type-chip {
			position: relative;
			display: inline-flex;
			align-items: center;
			cursor: pointer;
		}

		.item-custom-type-chip input {
			position: absolute;
			opacity: 0;
			pointer-events: none;
		}

		.item-custom-type-chip span {
			display: inline-flex;
			align-items: center;
			padding: 4px 9px;
			min-height: 24px;
			border-radius: 999px;
			border: 1px solid rgba(162, 155, 120, 0.22);
			background: rgba(255, 255, 255, 0.028);
			color: rgba(255, 255, 255, 0.76);
			font-size: 0.62em;
			font-weight: 400;
			letter-spacing: 0.03em;
			line-height: 1;
			transition: border-color 0.18s ease, background 0.18s ease, color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
		}

		.item-custom-type-chip input:checked + span {
			border-color: rgba(162, 155, 120, 0.72);
			background: rgba(162, 155, 120, 0.18);
			color: #fff7dd;
			box-shadow: inset 0 0 0 1px rgba(162, 155, 120, 0.18);
		}

		.item-custom-type-chip input:focus-visible + span {
			outline: 2px solid rgba(162, 155, 120, 0.45);
			outline-offset: 2px;
		}

		.item-custom-search-input {
			width: 100%;
			padding: 10px 14px;
			border-radius: 10px;
			border: 1px solid rgba(162, 155, 120, 0.3);
			background: rgba(10, 14, 21, 0.95);
			color: #ffffff;
			font-size: 0.92em;
		}

		.item-custom-search-input:focus-visible {
			outline: 2px solid rgba(162, 155, 120, 0.45);
			outline-offset: 2px;
		}

		.item-custom-reset-btn {
			padding: 10px 14px;
			border-radius: 999px;
			border: 1px solid rgba(162, 155, 120, 0.34);
			background: rgba(162, 155, 120, 0.1);
			color: #f6f1dc;
			font-size: 0.76em;
			font-weight: 700;
			letter-spacing: 0.08em;
			text-transform: uppercase;
			cursor: pointer;
		}

		.item-custom-filter-status {
			margin: 0;
			flex: 0 0 auto;
			font-size: 0.85em;
			color: rgba(255, 255, 255, 0.7);
			text-align: right;
			white-space: nowrap;
		}

		.item-custom-grid {
			display: flex;
			flex-direction: column;
			flex: 1 1 auto;
			gap: 8px;
			min-height: clamp(320px, 52vh, 620px);
			max-height: none;
			overflow-y: auto;
			padding-right: 4px;
		}

		.item-custom-card {
			display: grid;
			grid-template-columns: 56px minmax(0, 430px) minmax(320px, 1.65fr);
			gap: 14px;
			align-items: center;
			padding: 7px 14px 8px;
			border-radius: 12px;
			background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.022));
			border: 1px solid rgba(162, 155, 120, 0.2);
			box-shadow: 0 8px 18px rgba(0, 0, 0, 0.18);
		}

		.item-custom-card-media {
			position: relative;
			display: flex;
			align-items: center;
			justify-content: center;
			width: 52px !important;
			height: 52px !important;
			min-width: 52px;
			min-height: 52px;
			aspect-ratio: 1 / 1;
			overflow: hidden;
			border-radius: 10px;
			border: 1px solid rgba(255, 255, 255, 0.12);
			background: rgba(255, 255, 255, 0.04);
			box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
			cursor: zoom-in;
			flex-shrink: 0;
		}

		.item-custom-card-media.is-image-missing {
			cursor: default;
		}

		.item-custom-card-media.is-image-missing::after {
			content: 'N/A';
			position: absolute;
			inset: 0;
			display: flex;
			align-items: center;
			justify-content: center;
			font-size: 0.62em;
			font-weight: 700;
			letter-spacing: 0.12em;
			color: rgba(255, 255, 255, 0.45);
			background: linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0.01));
		}

		.item-custom-card-main {
			display: flex;
			flex-direction: column;
			justify-content: center;
			gap: 1px;
			min-width: 0;
			padding-top: 0;
		}

		.item-custom-card-stats {
			display: flex;
			flex-direction: column;
			gap: 4px;
			min-width: 0;
		}

		.item-custom-card-stats-header {
			display: flex;
			justify-content: flex-end;
			align-items: center;
		}

		.item-custom-card-thumb {
			width: 100% !important;
			height: 100% !important;
			min-width: 100%;
			max-width: none;
			border-radius: 0;
			object-fit: cover;
			background: transparent;
			border: 0;
			box-shadow: none;
			display: block;
			flex: 1 0 auto;
		}

		.item-custom-card-media.is-image-missing .item-custom-card-thumb,
		.item-custom-card-media.is-image-missing .item-custom-card-preview {
			display: none !important;
		}

		.item-custom-card-preview {
			visibility: hidden;
			opacity: 0;
			position: absolute;
			top: -10px;
			left: 68px;
			z-index: 1000;
			padding: 5px;
			background: rgba(11, 15, 22, 0.97);
			border: 1px solid rgba(162, 155, 120, 0.5);
			border-radius: 10px;
			box-shadow: 0 14px 40px rgba(0, 0, 0, 0.55), 0 0 20px rgba(162, 155, 120, 0.2);
			backdrop-filter: blur(12px);
			transition: opacity 0.18s ease, visibility 0.18s ease;
			pointer-events: none;
			overflow: hidden;
		}

		.item-custom-card-preview img {
			width: 320px;
			height: 320px;
			object-fit: contain;
			display: block;
			border-radius: 6px;
			background: rgba(255, 255, 255, 0.02);
		}

		.item-custom-card-media:hover .item-custom-card-preview,
		.item-custom-card-media:focus-within .item-custom-card-preview {
			visibility: visible;
			opacity: 1;
		}

		.item-custom-card-type {
			margin: 0;
			font-size: 0.65em;
			text-transform: uppercase;
			letter-spacing: 0.115em;
			line-height: 1.08;
			color: rgba(162, 155, 120, 0.95);
		}

		.item-custom-card-name {
			margin: 0;
			font-size: 0.97em;
			line-height: 1.08;
			color: #ffffff;
			word-break: normal;
			overflow-wrap: normal;
			hyphens: none;
		}

		.item-custom-card-meta {
			margin: 0;
			font-size: 0.73em;
			line-height: 1.08;
			color: rgba(255, 255, 255, 0.68);
		}

		.item-custom-card-count {
			display: inline-flex;
			align-items: center;
			justify-content: center;
			padding: 3px 9px;
			border-radius: 999px;
			background: rgba(162, 155, 120, 0.12);
			border: 1px solid rgba(162, 155, 120, 0.22);
			color: #f6f1dc;
			font-size: 0.6em;
			font-weight: 700;
			letter-spacing: 0.075em;
			text-transform: uppercase;
			white-space: nowrap;
		}

		.item-custom-stats-list {
			display: flex;
			flex-wrap: wrap;
			gap: 5px 6px;
			margin: 0;
			padding: 0;
			list-style: none;
		}

		.item-custom-stat-chip {
			display: inline-flex;
			align-items: center;
			flex-wrap: nowrap;
			gap: 10px;
			padding: 6px 18px 7px !important;
			padding-left: 18px !important;
			padding-right: 18px !important;
			border-radius: 11px;
			background: rgba(255, 255, 255, 0.05);
			border: 1px solid rgba(255, 255, 255, 0.1);
			min-height: 30px;
			max-width: 100%;
			box-sizing: border-box;
			box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03);
		}

		.item-custom-stat-name {
			font-size: 0.72em;
			color: rgba(255, 255, 255, 0.76);
			white-space: nowrap;
			line-height: 1.05;
		}

		.item-custom-stat-value {
			font-size: 0.79em;
			font-weight: 700;
			color: #ffffff;
			word-break: keep-all;
			white-space: nowrap;
			padding: 0 2px;
		}

		.item-custom-stat-chip.sign-plus {
			border-color: rgba(127, 255, 185, 0.24);
			background: rgba(0, 255, 136, 0.1);
		}

		.item-custom-stat-chip.sign-plus .item-custom-stat-value {
			color: #7fffb9;
		}

		.item-custom-stat-chip.sign-minus {
			border-color: rgba(255, 120, 120, 0.22);
			background: rgba(255, 77, 77, 0.1);
		}

		.item-custom-stat-chip.sign-minus .item-custom-stat-value {
			color: #ffb0b0;
		}

		.item-custom-stat-chip.sign-neutral {
			background: rgba(255, 255, 255, 0.045);
		}

		.item-custom-stat-chip.sign-neutral .item-custom-stat-value {
			color: #f1f1f1;
		}

		.item-custom-card-empty {
			margin: 0;
			padding: 12px 14px;
			border-radius: 12px;
			background: rgba(255, 255, 255, 0.04);
			border: 1px solid rgba(255, 255, 255, 0.08);
			color: rgba(255, 255, 255, 0.72);
			font-size: 0.88em;
		}

		.item-custom-card.is-hidden-by-search,
		.item-custom-card.is-hidden-by-type {
			display: none;
		}

		.ship-presets-dialog {
			background: linear-gradient(180deg, rgba(17, 22, 31, 0.98), rgba(8, 11, 18, 0.98));
			border: 1px solid rgba(162, 155, 120, 0.35);
			box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45);
		}

		.ship-presets-dialog h3 {
			font-size: 1.75em;
			letter-spacing: 0.08em;
		}

		.ship-presets-dialog > div {
			padding: 22px 26px 26px;
		}

		.ship-presets-empty,
		.ship-presets-error {
			margin: 0 0 18px;
			padding: 12px 14px !important;
			border-radius: 10px;
			font-size: 0.95em;
			text-align: left !important;
		}


		.ship-presets-empty {
			background: rgba(255, 255, 255, 0.06);
			border: 1px solid rgba(255, 255, 255, 0.12);
		}

		.ship-presets-error {
			background: rgba(140, 32, 32, 0.18);
			border: 1px solid rgba(255, 88, 88, 0.25);
			color: #ffbdbd;
		}

		.ship-presets-filter-bar {
			display: flex;
			align-items: flex-end;
			gap: 16px;
			margin: 0 0 18px;
			padding: 14px 16px;
			border-radius: 14px;
			background: rgba(255, 255, 255, 0.04);
			border: 1px solid rgba(162, 155, 120, 0.18);
			flex-wrap: wrap;
		}

		.ship-presets-filter-group {
			display: flex;
			flex-direction: column;
			gap: 8px;
			min-width: 240px;
			flex: 1 1 240px;
		}

		.ship-presets-filter-label {
			margin: 0;
			font-size: 0.8em;
			font-weight: 700;
			letter-spacing: 0.08em;
			text-transform: uppercase;
			color: rgba(255, 255, 255, 0.88);
		}

		.ship-presets-filter-select {
			width: 100%;
			padding: 10px 14px;
			border-radius: 10px;
			border: 1px solid rgba(162, 155, 120, 0.3);
			background: rgba(10, 14, 21, 0.95);
			color: #ffffff;
			font-size: 0.92em;
		}

		.ship-presets-filter-select:disabled {
			opacity: 0.55;
			cursor: not-allowed;
		}

		.ship-presets-filter-select:focus-visible {
			outline: 2px solid rgba(162, 155, 120, 0.45);
			outline-offset: 2px;
		}

		.ship-presets-filter-status {
			margin: 0 0 0 auto;
			font-size: 0.85em;
			color: rgba(255, 255, 255, 0.7);
			flex: 1 1 220px;
			text-align: right;
			align-self: center;
		}

		.ship-presets-grid {
			display: grid;
			grid-template-columns: repeat(3, minmax(0, 1fr));
			gap: 18px;
			max-height: 68vh;
			overflow-y: auto;
			padding-right: 4px;
		}

		.ship-preset-card {
			display: flex;
			flex-direction: column;
			justify-content: space-between;
			min-height: 290px;
			padding: 18px;
			border-radius: 16px;
			background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.025));
			border: 1px solid rgba(162, 155, 120, 0.22);
			box-shadow: 0 12px 30px rgba(0, 0, 0, 0.22);
			gap: 14px;
		}

		.ship-preset-card-header {
			display: flex;
			flex-direction: column;
			gap: 8px;
		}

		.ship-preset-card-manufacturer {
			margin: 0;
			font-size: 0.74em;
			text-transform: uppercase;
			letter-spacing: 0.14em;
			color: rgba(162, 155, 120, 0.95);
		}

		.ship-preset-card-name {
			margin: 0;
			font-size: 1.35em;
			line-height: 1.2;
			color: #ffffff;
			text-transform: uppercase;
		}

		.ship-preset-card-meta {
			margin: 0;
			font-size: 0.78em;
			color: rgba(255, 255, 255, 0.68);
		}

		.ship-preset-card-description {
			margin: 0;
			font-size: 0.88em;
			line-height: 1.6;
			color: rgba(255, 255, 255, 0.82);
			flex: 1;
		}

		.ship-preset-card-link {
			display: inline-flex;
			align-items: center;
			justify-content: center;
			padding: 10px 14px;
			border-radius: 999px;
			border: 1px solid rgba(162, 155, 120, 0.4);
			background: rgba(162, 155, 120, 0.12);
			color: #f6f1dc;
			font-size: 0.76em;
			font-weight: 700;
			letter-spacing: 0.08em;
			text-transform: uppercase;
			text-decoration: none;
			transition: background 0.18s ease, transform 0.18s ease;
		}

		.ship-preset-card-link:hover,
		.ship-preset-card-link:focus-visible {
			background: rgba(162, 155, 120, 0.22);
			transform: translateY(-1px);
			outline: none;
		}

		.ship-preset-card.is-hidden-by-ship-filter {
			display: none;
		}

		.vanilla-db-dialog {
			display: flex;
			flex-direction: column;
			background: linear-gradient(180deg, rgba(18, 22, 31, 0.98), rgba(8, 11, 18, 0.98));
			border: 1px solid rgba(162, 155, 120, 0.35);
			box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45);
			max-height: min(88vh, 980px);
		}

		.vanilla-db-dialog h3 {
			font-size: 1.75em;
			letter-spacing: 0.08em;
		}

		.vanilla-db-dialog > div {
			display: flex;
			flex-direction: column;
			flex: 1 1 auto;
			min-height: 0;
			overflow: hidden;
			padding: 22px 26px 26px;
		}

		.vanilla-db-empty,
		.vanilla-db-error {
			margin: 0 0 18px;
			padding: 12px 14px !important;
			border-radius: 10px;
			font-size: 0.95em;
			text-align: left !important;
		}

		.vanilla-db-empty {
			background: rgba(255, 255, 255, 0.06);
			border: 1px solid rgba(255, 255, 255, 0.12);
		}

		.vanilla-db-error {
			background: rgba(140, 32, 32, 0.18);
			border: 1px solid rgba(255, 88, 88, 0.25);
			color: #ffbdbd;
		}

		.vanilla-db-filter-bar {
			display: flex;
			align-items: center;
			gap: 14px;
			margin: 0 0 18px;
			padding: 14px 16px;
			border-radius: 14px;
			background: rgba(255, 255, 255, 0.04);
			border: 1px solid rgba(162, 155, 120, 0.18);
			flex-wrap: wrap;
		}

		.vanilla-db-search-wrap {
			display: flex;
			align-items: center;
			gap: 12px;
			flex: 1 1 420px;
			min-width: 260px;
		}

		.vanilla-db-search-input {
			width: 100%;
			padding: 10px 14px;
			border-radius: 10px;
			border: 1px solid rgba(162, 155, 120, 0.3);
			background: rgba(10, 14, 21, 0.95);
			color: #ffffff;
			font-size: 0.92em;
		}

		.vanilla-db-search-input:focus-visible {
			outline: 2px solid rgba(162, 155, 120, 0.45);
			outline-offset: 2px;
		}

		.vanilla-db-search-btn,
		.vanilla-db-reset-btn {
			padding: 10px 14px;
			border-radius: 999px;
			border: 1px solid rgba(162, 155, 120, 0.34);
			background: rgba(162, 155, 120, 0.1);
			color: #f6f1dc;
			font-size: 0.76em;
			font-weight: 700;
			letter-spacing: 0.08em;
			text-transform: uppercase;
			cursor: pointer;
			text-decoration: none;
			text-align: center;
		}

		.vanilla-db-search-btn {
			background: rgba(162, 155, 120, 0.2);
		}

		.vanilla-db-status {
			margin: 0 0 0 auto;
			font-size: 0.85em;
			color: rgba(255, 255, 255, 0.7);
			text-align: right;
			flex: 1 1 220px;
		}

		.vanilla-db-grid {
			display: flex;
			flex-direction: column;
			flex: 1 1 auto;
			gap: 8px;
			min-height: clamp(320px, 54vh, 700px);
			overflow-y: auto;
			padding-right: 4px;
		}
			.vanilla-db-card {
				grid-template-columns: 56px minmax(260px, 380px) minmax(320px, 1fr);
				align-items: start;
			}

			.vanilla-db-card-main {
			display: flex;
			flex-direction: column;
			justify-content: flex-start;
			align-self: start;
			gap: 6px;
			min-width: 0;
			padding-top: 0;
		}

		.vanilla-db-card-topline {
			display: flex;
			align-items: center;
			justify-content: flex-start;
			flex-wrap: wrap;
			gap: 8px;
			margin: 0;
		}

		.vanilla-db-card-type-badge {
			display: inline-flex;
			align-items: center;
			padding: 4px 9px;
			border-radius: 999px;
			border: 1px solid rgba(162, 155, 120, 0.28);
			background: rgba(162, 155, 120, 0.12);
			color: rgba(246, 241, 220, 0.96);
			font-size: 0.7em;
			font-weight: 500;
			letter-spacing: 0.08em;
			line-height: 1;
			text-transform: uppercase;
		}

		.vanilla-db-card-subtype {
			color: rgba(255, 255, 255, 0.72);
			font-size: 0.8em;
			font-weight: 400;
			letter-spacing: 0.04em;
			line-height: 1.2;
			text-transform: uppercase;
		}

		.vanilla-db-card-meta {
			margin: 0;
			color: rgba(255, 255, 255, 0.68);
			font-size: 0.8em;
			line-height: 1.35;
		}

		.vanilla-db-card-meta span {
			word-break: break-all;
		}

		.vanilla-db-card-uuid {
			display: inline-block;
			font-size: 0.76em;
			color: rgba(255, 255, 255, 0.58);
			letter-spacing: 0.02em;
		}

			.vanilla-db-card-estimate {
				display: inline-flex;
				align-items: center;
				gap: 6px;
				flex-wrap: wrap;
				font-size: 0.88em;
				color: #ffe6a6;
			}

			.vanilla-db-card-estimate strong {
				font-size: 0.92em;
				letter-spacing: 0.04em;
				text-transform: uppercase;
				color: rgba(255, 255, 255, 0.7);
			}

			.vanilla-db-card-estimate-value.is-loading {
				color: rgba(255, 255, 255, 0.62);
			}

			.vanilla-db-card-estimate-value.is-unavailable {
				color: rgba(255, 255, 255, 0.52);
			}
			.vanilla-db-card-details {
				display: flex;
				align-items: flex-start;
				justify-content: flex-start;
				min-width: 0;
			}

			.vanilla-db-card-description {
				width: 100%;
				margin: 0;
				font-size: 0.8em;
				line-height: 1.45;
				color: rgba(255, 255, 255, 0.8);
				word-break: break-word;
				overflow-wrap: anywhere;
			}

			.vanilla-db-card-description p {
				margin: 0 0 0.45em;
			}

			.vanilla-db-card-description p:last-child {
				margin-bottom: 0;
			}

			.vanilla-db-muted {
			color: rgba(255, 255, 255, 0.45);
		}

		.item-custom-card-name.vanilla-db-item-name {
			text-shadow: 0 0 10px rgba(255, 255, 255, 0.08);
		}

		.item-custom-card-name.vanilla-db-item-name.scan-rarity-L { color: #ff8000; }
		.item-custom-card-name.vanilla-db-item-name.scan-rarity-E { color: #a335ee; }
		.item-custom-card-name.vanilla-db-item-name.scan-rarity-R { color: #4db2ff; }
		.item-custom-card-name.vanilla-db-item-name.scan-rarity-U { color: #1eff00; }
		.item-custom-card-name.vanilla-db-item-name.scan-rarity-C { color: #ffffff; }
		.item-custom-card-name.vanilla-db-item-name.scan-rarity-none { color: #b5bcc8; }

		.vanilla-db-hover-preview {
			position: fixed;
			top: 0;
			left: 0;
			z-index: 10000;
			display: none;
			width: min(360px, calc(100vw - 32px));
			padding: 6px;
			border-radius: 12px;
			border: 1px solid rgba(162, 155, 120, 0.42);
			background: rgba(9, 13, 19, 0.98);
			box-shadow: 0 18px 44px rgba(0, 0, 0, 0.58), 0 0 18px rgba(162, 155, 120, 0.18);
			backdrop-filter: blur(14px);
			pointer-events: none;
		}

		.vanilla-db-hover-preview.is-visible {
			display: block;
		}

		.vanilla-db-hover-preview img {
			display: block;
			width: 100%;
			height: auto;
			max-height: min(360px, calc(100vh - 32px));
			object-fit: contain;
			border-radius: 8px;
			background: rgba(255, 255, 255, 0.02);
		}

		.vanilla-db-pagination {
			display: flex;
			align-items: center;
			justify-content: space-between;
			gap: 12px;
			margin-top: 16px;
			padding: 14px 16px;
			border-radius: 14px;
			background: rgba(255, 255, 255, 0.04);
			border: 1px solid rgba(162, 155, 120, 0.18);
			flex-wrap: wrap;
		}

		.vanilla-db-pagination-pages {
			display: flex;
			align-items: center;
			gap: 8px;
			flex-wrap: wrap;
		}

		.vanilla-db-pagination-summary {
			margin: 0;
			font-size: 0.84em;
			color: rgba(255, 255, 255, 0.68);
		}

		.vanilla-db-page-link,
		.vanilla-db-page-current,
		.vanilla-db-page-ellipsis {
			display: inline-flex;
			align-items: center;
			justify-content: center;
			min-width: 40px;
			height: 40px;
			padding: 0 12px;
			border-radius: 999px;
			font-size: 0.82em;
			font-weight: 700;
			letter-spacing: 0.04em;
		}

		.vanilla-db-page-link {
			border: 1px solid rgba(162, 155, 120, 0.24);
			background: rgba(162, 155, 120, 0.08);
			color: #f6f1dc;
			text-decoration: none;
		}

		.vanilla-db-page-link:hover,
		.vanilla-db-page-link:focus-visible {
			background: rgba(162, 155, 120, 0.18);
			outline: none;
		}

		.vanilla-db-page-current {
			border: 1px solid rgba(255, 255, 255, 0.18);
			background: rgba(255, 255, 255, 0.12);
			color: #ffffff;
		}

		.vanilla-db-page-ellipsis {
			min-width: auto;
			height: auto;
			padding: 0 2px;
			color: rgba(255, 255, 255, 0.45);
		}

		.vanilla-db-card.is-hidden-by-search {
			display: none;
		}


		@media (max-width: 1100px) {
			.modal-scan-reference,
			.modal-ship-presets,
			.modal-item-custom,
			.modal-vanilla-db {
				width: 96%;
				min-width: 0;
			}

			.scan-reference-dialog h3,
			.ship-presets-dialog h3,
			.item-custom-dialog h3,
			.vanilla-db-dialog h3 {
				font-size: 1.2em;
			}

			.scan-reference-filter-bar {
				flex-direction: column;
				align-items: stretch;
			}

			.scan-reference-filter-status {
				text-align: left;
			}

			.ship-presets-filter-bar {
				align-items: stretch;
			}

			.vanilla-db-filter-bar {
				align-items: stretch;
			}

			.vanilla-db-status {
				margin-left: 0;
				text-align: left;
			}

			.ship-presets-filter-status {
				margin-left: 0;
				text-align: left;
			}

			.ship-presets-grid {
				grid-template-columns: repeat(2, minmax(0, 1fr));
			}

			.item-custom-filter-top {
				align-items: stretch;
			}

			.item-custom-filter-status {
				text-align: left;
				white-space: normal;
			}

			.item-custom-card {
				grid-template-columns: 52px minmax(280px, 1.9fr) minmax(220px, 1.3fr);
				gap: 10px;
				padding: 7px 10px;
			}

			.vanilla-db-card {
				grid-template-columns: 52px minmax(220px, 1fr) minmax(140px, auto);
			}

			.item-custom-card-preview {
				left: 62px;
			}
		}

		@media (max-width: 720px) {
			.item-custom-dialog {
				max-height: 92vh;
			}

			.item-custom-grid {
				min-height: min(42vh, 340px);
			}

			.ship-presets-grid {
				grid-template-columns: 1fr;
			}

			.ship-preset-card {
				min-height: 0;
			}

			.item-custom-filter-top,
			.item-custom-search-wrap,
			.item-custom-type-filters,
			.vanilla-db-search-wrap {
				flex-direction: column;
				align-items: stretch;
			}

			.item-custom-filter-status {
				text-align: left;
			}

			.item-custom-card {
				grid-template-columns: 52px minmax(0, 1fr);
				padding: 8px;
				gap: 8px;
			}

			.vanilla-db-card-main,
			.vanilla-db-card-details {
				grid-column: 1 / -1;
			}

			.item-custom-card-media {
				width: 48px !important;
				height: 48px !important;
				min-width: 48px;
				min-height: 48px;
			}

			.item-custom-card-stats {
				grid-column: 1 / -1;
			}

			.item-custom-card-stats-header {
				justify-content: flex-start;
			}

			.item-custom-card-preview {
				display: none;
			}

			.item-custom-stat-chip {
				width: 100%;
				justify-content: space-between;
				padding: 6px 14px !important;
				padding-left: 14px !important;
				padding-right: 14px !important;
			}

			.item-custom-stat-name {
				white-space: normal;
			}
		}
	</style>
</head>

<body>
	<?php if ($has_member_access || $has_vanilla_db_access): ?>
		<div class="assets-div-menu">
			<?php if ($has_member_access): ?>
				<a href="#" class="md-trigger" data-modal="modal-ScanReference">Signatures de minage</a>
				<a href="#" class="md-trigger" data-modal="modal-ShipPresets">Presets de vaisseaux</a>
			<?php endif; ?>
			<?php if ($has_vanilla_db_access): ?>
				<a href="#" class="md-trigger" data-modal="modal-VanillaDb">Objets Vanilla DB</a>
			<?php endif; ?>
			<?php if ($has_member_access): ?>
				<a href="#" class="md-trigger" data-modal="modal-ItemCustom">Objet(s) personnalisé(s)</a>
			<?php endif; ?>
		</div>
	<?php endif; ?>
	
	<div class="connexion-div-menu <?php echo $is_authenticated ? 'is-authenticated' : 'md-trigger'; ?>" data-login-label="Connexion" <?php echo $is_authenticated ? '' : 'data-modal="modal-Login"'; ?> id="accountPanel">
		<span id="accountLabel"><?php echo htmlspecialchars($is_authenticated ? ('Bonjour, ' . $session_cl_auth_user) : 'Connexion', ENT_QUOTES, 'UTF-8'); ?></span>
		<span class="connexion-actions" id="accountActions" <?php echo $is_authenticated ? '' : 'hidden'; ?>>
			<a id="adminLink" class="connexion-action-btn connexion-action-admin" href="admin.php" title="Zone d'administration" aria-label="Zone d'administration" <?php echo $has_member_access ? '' : 'hidden'; ?>>
				<span class="connexion-action-icon" aria-hidden="true">
					<svg viewBox="0 0 24 24" role="img" focusable="false">
						<path d="M10.33 2.04c1-.2 2.03-.2 3.03 0l.4 2.04c.45.12.89.3 1.29.54l1.78-1.07c.84.56 1.56 1.29 2.12 2.12l-1.07 1.78c.24.4.42.84.54 1.29l2.04.4c.2 1 .2 2.03 0 3.03l-2.04.4a5.98 5.98 0 0 1-.54 1.29l1.07 1.78a8.04 8.04 0 0 1-2.12 2.12l-1.78-1.07c-.4.24-.84.42-1.29.54l-.4 2.04c-1 .2-2.03.2-3.03 0l-.4-2.04a5.98 5.98 0 0 1-1.29-.54l-1.78 1.07a8.04 8.04 0 0 1-2.12-2.12l1.07-1.78a5.98 5.98 0 0 1-.54-1.29l-2.04-.4a7.64 7.64 0 0 1 0-3.03l2.04-.4c.12-.45.3-.89.54-1.29L3.91 5.72A8.04 8.04 0 0 1 6.03 3.6l1.78 1.07c.4-.24.84-.42 1.29-.54l.4-2.04ZM12 8.25A3.75 3.75 0 1 0 12 15.75 3.75 3.75 0 0 0 12 8.25Z" fill="currentColor"/>
					</svg>
				</span>
				<span class="sr-only">Administration</span>
			</a>
			<a id="logoutLink" class="connexion-action-btn connexion-action-logout" href="logout.php" title="Déconnexion" aria-label="Déconnexion">
				<span class="connexion-action-icon" aria-hidden="true">
					<svg viewBox="0 0 24 24" role="img" focusable="false">
						<path d="M10 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h4v-2H6V5h4V3Zm5.59 4.59L14.17 9l2.58 2.59H9v2h7.75l-2.58 2.59 1.42 1.41L20.59 12l-5-4.41Z" fill="currentColor"/>
					</svg>
				</span>
				<span class="sr-only">Déconnexion</span>
			</a>
		</span>
	</div>
	
	<div class="se-switch switch-center" role="group" aria-label="Choix entre FR et EN">
	  <a class="se-switch__btn is-active" href="index.php" data-site="se1" aria-current="page">🇫🇷</a>
	  <a class="se-switch__btn" href="index-en.php" data-site="se2">🇬🇧</a>
	</div>

    <div class="md-modal md-effect-1" id="modal-Login">	
		<div class="md-content">
			<h3>
				<img class="float-left" src="img/icon_bops.png" width="48" height="48" alt="" />
				INTERFACE DE CONNEXION
				<a class="frame-icon-close md-close float-right" href="#"><img src="img/icon_close.png" width="48" height="48" alt="" /></a>
			</h3>
			<div>
				<p class="txt-center">Entrer vos identifiants pour acceder à l'espace sécurisé.*</p>
				<form class="js-login-form" method="post" action="login.php">
				  <div>
					<p class="txt-center"><input class="connexion-champ" id="idr" type="text" name="cl_auth_user" placeholder="RID" required /></p>
					<p class="txt-center"><input class="connexion-champ" id="pwr" type="password" name="cl_auth_pass" placeholder="MOT DE PASSE" required /></p>
				  </div>
				  <div>
					<p class="txt-center"><input class="connexion-bouton" type="submit" value="S'authentifier" /></p>
					<p class="txt-center login-status" id="loginStatus" aria-live="polite"></p>
				  </div>
				</form>
				<p class="txt-center txt-s10">* Accès sous haute surveillance. En confirmant vos identifiants, vous acceptez les protocoles de sécurité de l'initiative R.E.A.C.T. Toute infraction aux protocoles est passible de sanctions.</p>
			</div>
		</div>
	</div>
	
	<div class="md-modal md-effect-1" id="modal-About">	
		<div class="md-content">
			<h3>
				<img class="float-left" src="img/icon_bops.png" width="48" height="48" alt="" />
				EN SAVOIR PLUS
				<a class="frame-icon-close md-close float-right" href="#"><img src="img/icon_close.png" width="48" height="48" alt="" /></a>
			</h3>
			<div>
				<img class="float-left" src="img/fl_security.png" width="300" height="460" alt="" />
				<p>La sécurité et la protection des intérêts impériaux sont des priorités absolues pour l’agence.</p>
				<p>En tant que garante de l’ordre dans les zones sous juridiction de l’UEE, l’agence BOPS s'engage à prévenir, neutraliser et répondre efficacement à toutes les formes de menaces, qu'elles soient internes ou externes aux territoires de l'Empire.</p>
				<p>Cette mission repose sur une approche combinant vigilance, réactivité et expertise tactique, afin d’assurer la stabilité, la sécurité des citoyens et le respect des lois impériales.</p>
				<p>Chaque opération est conçue pour inspirer confiance aux populations locales tout en projetant une image de force et de discipline au sein de l’univers connu.</p>
				<p class="ul-style">
					— Surveillance active des secteurs critiques pour dissuader les menaces potentielles.</br>
					— Protection rapprochée de convois, personnalités importantes ou cargaisons sensibles.</br>
					— Neutralisation de vaisseaux hostiles ou suspects, avec récupération d’actifs stratégiques.</br>
					— Ciblage et capture ou élimination de fugitifs dangereux, conformément aux lois impériales.</br>
					— Protection des civils en détresse et aide aux infrastructures endommagées.</br>
					— Collecte et analyse d’informations sur des activités suspectes, incidents ou organisations hostiles.
				</p>
			</div>
		</div>
	</div>

	<?php if ($has_member_access): ?>
	<div class="md-modal md-effect-1 modal-ship-presets" id="modal-ShipPresets">	
		<div class="md-content ship-presets-dialog">
			<h3>
				<img class="float-left" src="img/icon_bops.png" width="48" height="48" alt="" />
				PRESETS DE VAISSEAUX
				<a class="frame-icon-close md-close float-right" href="#"><img src="img/icon_close.png" width="48" height="48" alt="" /></a>
			</h3>
			<div>
				<?php if ($ship_preset_error !== null): ?>
					<p class="ship-presets-error"><?php echo htmlspecialchars($ship_preset_error, ENT_QUOTES, 'UTF-8'); ?></p>
				<?php elseif ($ship_preset_rows === []): ?>
					<p class="ship-presets-empty">Aucun preset de vaisseau n'est enregistré pour le moment.</p>
				<?php else: ?>
					<div class="ship-presets-filter-bar">
						<div class="ship-presets-filter-group">
							<label class="ship-presets-filter-label" for="shipPresetManufacturerFilter">Filtrer par manufacture</label>
							<select id="shipPresetManufacturerFilter" class="ship-presets-filter-select">
								<option value="">Toutes les manufactures</option>
								<?php foreach ($ship_preset_manufacturers as $ship_preset_manufacturer): ?>
									<option value="<?php echo htmlspecialchars($ship_preset_manufacturer, ENT_QUOTES, 'UTF-8'); ?>"><?php echo htmlspecialchars($ship_preset_manufacturer, ENT_QUOTES, 'UTF-8'); ?></option>
								<?php endforeach; ?>
							</select>
						</div>
						<div class="ship-presets-filter-group">
							<label class="ship-presets-filter-label" for="shipPresetShipFilter">Filtrer par vaisseau</label>
							<select id="shipPresetShipFilter" class="ship-presets-filter-select" disabled>
								<option value="">Choisis d'abord une manufacture</option>
							</select>
						</div>
						<p class="ship-presets-filter-status" id="shipPresetFilterStatus"></p>
					</div>
					<div class="ship-presets-grid" id="shipPresetsGrid">
						<?php foreach ($ship_preset_rows as $ship_preset_row): ?>
							<article class="ship-preset-card" data-manufacturer="<?php echo htmlspecialchars($ship_preset_row['manufacturer'], ENT_QUOTES, 'UTF-8'); ?>" data-ship-name="<?php echo htmlspecialchars($ship_preset_row['name'], ENT_QUOTES, 'UTF-8'); ?>">
								<div class="ship-preset-card-header">
									<p class="ship-preset-card-manufacturer"><?php echo htmlspecialchars($ship_preset_row['manufacturer'], ENT_QUOTES, 'UTF-8'); ?></p>
									<h4 class="ship-preset-card-name"><?php echo htmlspecialchars($ship_preset_row['name'], ENT_QUOTES, 'UTF-8'); ?></h4>
									<p class="ship-preset-card-meta">Créé par <?php echo htmlspecialchars($ship_preset_row['creator'], ENT_QUOTES, 'UTF-8'); ?></p>
								</div>
								<p class="ship-preset-card-description"><?php echo htmlspecialchars($ship_preset_row['description'], ENT_QUOTES, 'UTF-8'); ?></p>
								<a href="<?php echo htmlspecialchars($ship_preset_row['link'], ENT_QUOTES, 'UTF-8'); ?>" target="_blank" rel="noopener noreferrer" class="ship-preset-card-link">Voir la configuration</a>
							</article>
						<?php endforeach; ?>
					</div>
				<?php endif; ?>
			</div>
		</div>
	</div>

	<?php endif; ?>


	<?php if ($has_member_access): ?>
	<div class="md-modal md-effect-1 modal-item-custom" id="modal-ItemCustom">	
		<div class="md-content item-custom-dialog">
			<h3>
				<img class="float-left" src="img/icon_bops.png" width="48" height="48" alt="" />
				OBJET(S) PERSONNALISÉ(S)
				<a class="frame-icon-close md-close float-right" href="#"><img src="img/icon_close.png" width="48" height="48" alt="" /></a>
			</h3>
			<div>
				<?php if ($item_custom_public_error !== null): ?>
					<p class="item-custom-error"><?php echo htmlspecialchars($item_custom_public_error, ENT_QUOTES, 'UTF-8'); ?></p>
				<?php elseif ($item_custom_public_rows === []): ?>
					<p class="item-custom-empty">Aucun objet Item Custom n'est disponible pour le moment.</p>
				<?php else: ?>
					<div class="item-custom-filter-bar">
						<div class="item-custom-filter-top">
							<div class="item-custom-search-wrap">
								<input type="search" id="itemCustomSearch" class="item-custom-search-input" placeholder="Rechercher un objet, un créateur ou une statistique..." autocomplete="off">
								<button type="button" id="itemCustomSearchReset" class="item-custom-reset-btn">Réinitialiser</button>
							</div>
							<p class="item-custom-filter-status" id="itemCustomSearchStatus"></p>
						</div>
						<?php if ($item_custom_public_types !== []): ?>
							<div class="item-custom-type-filters" id="itemCustomTypeFilters">
								<span class="item-custom-type-label">Filtrer par type</span>
								<div class="item-custom-type-options">
									<?php foreach ($item_custom_public_types as $item_custom_public_type): ?>
										<label class="item-custom-type-chip">
											<input type="checkbox" class="item-custom-type-checkbox" value="<?php echo htmlspecialchars($item_custom_public_type, ENT_QUOTES, 'UTF-8'); ?>">
											<span><?php echo htmlspecialchars($item_custom_public_type, ENT_QUOTES, 'UTF-8'); ?></span>
										</label>
									<?php endforeach; ?>
								</div>
							</div>
						<?php endif; ?>
					</div>
					<div class="item-custom-grid" id="itemCustomGrid">
						<?php foreach ($item_custom_public_rows as $item_custom_public_row): ?>
							<?php $item_custom_stat_count = count($item_custom_public_row['stats']); ?>
							<article class="item-custom-card" data-item-search="<?php echo htmlspecialchars($item_custom_public_row['search'], ENT_QUOTES, 'UTF-8'); ?>" data-item-type="<?php echo htmlspecialchars($item_custom_public_row['type'] !== '' ? $item_custom_public_row['type'] : 'Type inconnu', ENT_QUOTES, 'UTF-8'); ?>">
								<div class="item-custom-card-media">
									<img src="https://cstone.space/uifimages/<?php echo htmlspecialchars($item_custom_public_row['uuid'], ENT_QUOTES, 'UTF-8'); ?>.png" class="item-custom-card-thumb" alt="Aperçu de <?php echo htmlspecialchars($item_custom_public_row['name'], ENT_QUOTES, 'UTF-8'); ?>" loading="lazy" onerror="this.closest('.item-custom-card-media').classList.add('is-image-missing'); this.remove();">
									<div class="item-custom-card-preview" aria-hidden="true">
										<img src="https://cstone.space/uifimages/<?php echo htmlspecialchars($item_custom_public_row['uuid'], ENT_QUOTES, 'UTF-8'); ?>.png" alt="" onerror="this.closest('.item-custom-card-media').classList.add('is-image-missing'); this.closest('.item-custom-card-preview').remove();">
									</div>
								</div>
								<div class="item-custom-card-main">
									<p class="item-custom-card-type"><?php echo htmlspecialchars(trim(($item_custom_public_row['type'] !== '' ? $item_custom_public_row['type'] : 'Type inconnu') . ($item_custom_public_row['subtype'] !== '' ? ' / ' . $item_custom_public_row['subtype'] : '')), ENT_QUOTES, 'UTF-8'); ?></p>
									<h4 class="item-custom-card-name"><?php echo htmlspecialchars($item_custom_public_row['name'], ENT_QUOTES, 'UTF-8'); ?></h4>
									<p class="item-custom-card-meta">Créé par <?php echo htmlspecialchars($item_custom_public_row['creator'], ENT_QUOTES, 'UTF-8'); ?></p>
								</div>
								<div class="item-custom-card-stats">
									<div class="item-custom-card-stats-header">
										<span class="item-custom-card-count"><?php echo $item_custom_stat_count; ?> stat<?php echo $item_custom_stat_count > 1 ? 's' : ''; ?></span>
									</div>
									<?php if ($item_custom_stat_count === 0): ?>
										<p class="item-custom-card-empty">Aucune statistique personnalisée n'a encore été enregistrée pour cet objet.</p>
									<?php else: ?>
										<ul class="item-custom-stats-list">
											<?php foreach ($item_custom_public_row['stats'] as $item_custom_stat): ?>
												<?php
													$item_custom_stat_preview = trim((string) ($item_custom_stat['preview'] ?? ''));
													$item_custom_stat_sign_class = 'sign-neutral';
													if ($item_custom_stat_preview !== '') {
														if (strpos($item_custom_stat_preview, '+') === 0) {
															$item_custom_stat_sign_class = 'sign-plus';
														} elseif (strpos($item_custom_stat_preview, '-') === 0) {
															$item_custom_stat_sign_class = 'sign-minus';
														}
													}
												?>
												<li class="item-custom-stat-chip <?php echo $item_custom_stat_sign_class; ?>">
													<span class="item-custom-stat-name"><?php echo htmlspecialchars($item_custom_stat['name'], ENT_QUOTES, 'UTF-8'); ?></span>
													<span class="item-custom-stat-value"><?php echo htmlspecialchars($item_custom_stat['preview'], ENT_QUOTES, 'UTF-8'); ?></span>
												</li>
											<?php endforeach; ?>
										</ul>
									<?php endif; ?>
								</div>
							</article>
						<?php endforeach; ?>
					</div>
				<?php endif; ?>
			</div>
		</div>
	</div>

	<?php endif; ?>

	<?php if ($has_vanilla_db_access): ?>
		<div class="md-modal md-effect-1 modal-vanilla-db" id="modal-VanillaDb">
			<div class="md-content vanilla-db-dialog">
				<h3>
					<img class="float-left" src="img/icon_bops.png" width="48" height="48" alt="" />
					BASE DE DONNEES VANILLA
					<a class="frame-icon-close md-close float-right" href="#"><img src="img/icon_close.png" width="48" height="48" alt="" /></a>
				</h3>
				<div>

					<?php if ($vanilla_db_error !== null): ?>
						<p class="vanilla-db-error"><?php echo htmlspecialchars($vanilla_db_error, ENT_QUOTES, 'UTF-8'); ?></p>
					<?php else: ?>
						<form class="vanilla-db-filter-bar" method="get" action="index.php">
							<input type="hidden" name="open_modal" value="vanilla-db" />
							<input type="hidden" name="vanilla_page" value="1" />
							<div class="vanilla-db-search-wrap">
								<input type="search" id="vanillaDbSearch" name="vanilla_search" class="vanilla-db-search-input" placeholder="Rechercher un objet, un type, un sous-type, une rareté ou un UUID..." autocomplete="off" value="<?php echo htmlspecialchars($vanilla_db_search, ENT_QUOTES, 'UTF-8'); ?>" />
								<button type="submit" class="vanilla-db-search-btn">Rechercher</button>
								<a href="<?php echo htmlspecialchars($vanilla_db_reset_url, ENT_QUOTES, 'UTF-8'); ?>" class="vanilla-db-reset-btn">Réinitialiser</a>
							</div>
							<p class="vanilla-db-status">
								<?php if ($vanilla_db_total_rows > 0): ?>
									Affichage de <strong><?php echo $vanilla_db_result_start; ?></strong> à <strong><?php echo $vanilla_db_result_end; ?></strong> sur <strong><?php echo $vanilla_db_total_rows; ?></strong> objet(s)<?php echo $vanilla_db_search !== '' ? ' pour « ' . htmlspecialchars($vanilla_db_search, ENT_QUOTES, 'UTF-8') . ' »' : ''; ?>.
								<?php else: ?>
									Aucun objet trouvé<?php echo $vanilla_db_search !== '' ? ' pour « ' . htmlspecialchars($vanilla_db_search, ENT_QUOTES, 'UTF-8') . ' »' : ''; ?>.
								<?php endif; ?>
							</p>
						</form>

						<?php if ($vanilla_db_rows === []): ?>
							<p class="vanilla-db-empty">Aucun objet n'est actuellement enregistré dans la BASE D'OBJETS.</p>
						<?php else: ?>
							<div class="vanilla-db-grid" id="vanillaDbGrid">
							<?php foreach ($vanilla_db_rows as $vanilla_db_row): ?>
							<article class="item-custom-card vanilla-db-card">
								<div class="item-custom-card-media<?php echo $vanilla_db_row['image_url'] === null ? ' is-image-missing' : ''; ?>"<?php if ($vanilla_db_row['image_url'] !== null): ?> data-preview-src="<?php echo htmlspecialchars($vanilla_db_row['image_url'], ENT_QUOTES, 'UTF-8'); ?>" data-preview-label="<?php echo htmlspecialchars($vanilla_db_row['name'], ENT_QUOTES, 'UTF-8'); ?>"<?php endif; ?>>
									<?php if ($vanilla_db_row['image_url'] !== null): ?>
										<img src="<?php echo htmlspecialchars($vanilla_db_row['image_url'], ENT_QUOTES, 'UTF-8'); ?>" class="item-custom-card-thumb" alt="Aperçu de <?php echo htmlspecialchars($vanilla_db_row['name'], ENT_QUOTES, 'UTF-8'); ?>" loading="lazy" onerror="this.closest('.item-custom-card-media').classList.add('is-image-missing'); this.remove();">
									<?php endif; ?>
								</div>
								<div class="item-custom-card-main vanilla-db-card-main">
									<p class="vanilla-db-card-topline">
										<span class="vanilla-db-card-type-badge"><?php echo htmlspecialchars($vanilla_db_row['type'], ENT_QUOTES, 'UTF-8'); ?></span>
										<?php if ($vanilla_db_row['subtype'] !== '—'): ?><span class="vanilla-db-card-subtype"><?php echo htmlspecialchars($vanilla_db_row['subtype'], ENT_QUOTES, 'UTF-8'); ?></span><?php endif; ?>
									</p>
									<h4 class="item-custom-card-name vanilla-db-item-name <?php echo htmlspecialchars($vanilla_db_row['rarity_class'], ENT_QUOTES, 'UTF-8'); ?>" title="<?php echo htmlspecialchars($vanilla_db_row['rarity_label'], ENT_QUOTES, 'UTF-8'); ?>"><?php echo htmlspecialchars($vanilla_db_row['name'], ENT_QUOTES, 'UTF-8'); ?></h4>
									<p class="vanilla-db-card-meta"><span class="vanilla-db-card-estimate" data-uex-estimate data-uex-query="<?php echo htmlspecialchars($vanilla_db_row['name'], ENT_QUOTES, 'UTF-8'); ?>"><strong>Estimation UEX :</strong> <span class="vanilla-db-card-estimate-value is-loading" data-uex-estimate-value>Chargement...</span></span></p>
									<p class="vanilla-db-card-meta"><?php if ($vanilla_db_row['uuid'] !== '—'): ?><span class="vanilla-db-card-uuid">UUID : <?php echo htmlspecialchars($vanilla_db_row['uuid'], ENT_QUOTES, 'UTF-8'); ?></span><?php else: ?><span class="vanilla-db-muted vanilla-db-card-uuid">UUID : —</span><?php endif; ?></p>
								</div>
								<div class="vanilla-db-card-details">
									<div class="vanilla-db-card-description"><?php echo $vanilla_db_row['description_html']; ?></div>
								</div>
							</article>
							<?php endforeach; ?>
							</div>

							<?php if ($vanilla_db_total_pages > 1): ?>
								<?php
								$vanilla_db_page_window_start = max(1, $vanilla_db_current_page - 2);
								$vanilla_db_page_window_end = min($vanilla_db_total_pages, $vanilla_db_current_page + 2);

								if (($vanilla_db_page_window_end - $vanilla_db_page_window_start) < 4) {
									if ($vanilla_db_page_window_start === 1) {
										$vanilla_db_page_window_end = min($vanilla_db_total_pages, 5);
									} elseif ($vanilla_db_page_window_end === $vanilla_db_total_pages) {
										$vanilla_db_page_window_start = max(1, $vanilla_db_total_pages - 4);
									}
								}
								?>
								<nav class="vanilla-db-pagination" aria-label="Pagination des objets vanilla">
									<p class="vanilla-db-pagination-summary">Page <strong><?php echo $vanilla_db_current_page; ?></strong> sur <strong><?php echo $vanilla_db_total_pages; ?></strong>.</p>
									<div class="vanilla-db-pagination-pages">
										<?php if ($vanilla_db_current_page > 1): ?>
											<?php $vanilla_db_page_query = $vanilla_db_base_query; $vanilla_db_page_query['vanilla_page'] = 1; ?>
											<a class="vanilla-db-page-link" href="index.php?<?php echo htmlspecialchars(http_build_query($vanilla_db_page_query), ENT_QUOTES, 'UTF-8'); ?>">«</a>
											<?php $vanilla_db_page_query = $vanilla_db_base_query; $vanilla_db_page_query['vanilla_page'] = $vanilla_db_current_page - 1; ?>
											<a class="vanilla-db-page-link" href="index.php?<?php echo htmlspecialchars(http_build_query($vanilla_db_page_query), ENT_QUOTES, 'UTF-8'); ?>">‹</a>
										<?php endif; ?>

										<?php if ($vanilla_db_page_window_start > 1): ?>
											<?php $vanilla_db_page_query = $vanilla_db_base_query; $vanilla_db_page_query['vanilla_page'] = 1; ?>
											<a class="vanilla-db-page-link" href="index.php?<?php echo htmlspecialchars(http_build_query($vanilla_db_page_query), ENT_QUOTES, 'UTF-8'); ?>">1</a>
											<?php if ($vanilla_db_page_window_start > 2): ?>
												<span class="vanilla-db-page-ellipsis">…</span>
											<?php endif; ?>
										<?php endif; ?>

										<?php for ($vanilla_db_page_number = $vanilla_db_page_window_start; $vanilla_db_page_number <= $vanilla_db_page_window_end; $vanilla_db_page_number++): ?>
											<?php if ($vanilla_db_page_number === $vanilla_db_current_page): ?>
												<span class="vanilla-db-page-current"><?php echo $vanilla_db_page_number; ?></span>
											<?php else: ?>
												<?php $vanilla_db_page_query = $vanilla_db_base_query; $vanilla_db_page_query['vanilla_page'] = $vanilla_db_page_number; ?>
												<a class="vanilla-db-page-link" href="index.php?<?php echo htmlspecialchars(http_build_query($vanilla_db_page_query), ENT_QUOTES, 'UTF-8'); ?>"><?php echo $vanilla_db_page_number; ?></a>
											<?php endif; ?>
										<?php endfor; ?>

										<?php if ($vanilla_db_page_window_end < $vanilla_db_total_pages): ?>
											<?php if ($vanilla_db_page_window_end < ($vanilla_db_total_pages - 1)): ?>
												<span class="vanilla-db-page-ellipsis">…</span>
											<?php endif; ?>
											<?php $vanilla_db_page_query = $vanilla_db_base_query; $vanilla_db_page_query['vanilla_page'] = $vanilla_db_total_pages; ?>
											<a class="vanilla-db-page-link" href="index.php?<?php echo htmlspecialchars(http_build_query($vanilla_db_page_query), ENT_QUOTES, 'UTF-8'); ?>"><?php echo $vanilla_db_total_pages; ?></a>
										<?php endif; ?>

										<?php if ($vanilla_db_current_page < $vanilla_db_total_pages): ?>
											<?php $vanilla_db_page_query = $vanilla_db_base_query; $vanilla_db_page_query['vanilla_page'] = $vanilla_db_current_page + 1; ?>
											<a class="vanilla-db-page-link" href="index.php?<?php echo htmlspecialchars(http_build_query($vanilla_db_page_query), ENT_QUOTES, 'UTF-8'); ?>">›</a>
											<?php $vanilla_db_page_query = $vanilla_db_base_query; $vanilla_db_page_query['vanilla_page'] = $vanilla_db_total_pages; ?>
											<a class="vanilla-db-page-link" href="index.php?<?php echo htmlspecialchars(http_build_query($vanilla_db_page_query), ENT_QUOTES, 'UTF-8'); ?>">»</a>
										<?php endif; ?>
									</div>
								</nav>
							<?php endif; ?>
						<?php endif; ?>
					<?php endif; ?>
				</div>
			</div>
		</div>
	<?php endif; ?>

	<?php if ($has_member_access): ?>
		<div class="md-modal md-effect-1 modal-scan-reference" id="modal-ScanReference">	
			<div class="md-content scan-reference-dialog">
				<h3>
					<img class="float-left" src="img/icon_bops.png" width="48" height="48" alt="" />
					TABLEAU DES SIGNATURES DE SCAN
					<a class="frame-icon-close md-close float-right" href="#"><img src="img/icon_close.png" width="48" height="48" alt="" /></a>
				</h3>
				<div>

					<?php if ($scan_reference_error !== null): ?>
						<p class="scan-reference-error"><?php echo htmlspecialchars($scan_reference_error, ENT_QUOTES, 'UTF-8'); ?></p>
					<?php elseif ($scan_reference_rows === []): ?>
						<p class="scan-reference-empty">Aucune donnée de scan n'est configurée pour le moment.</p>
					<?php else: ?>
						<div class="scan-reference-filter-bar">
							<div class="scan-reference-filter-actions">
								<button type="button" class="scan-reference-filter-btn" id="scanReferenceIsolateBtn">Isoler</button>
								<button type="button" class="scan-reference-filter-btn" id="scanReferenceClearBtn">Supprimer le filtrage</button>
							</div>
							<p class="scan-reference-filter-status" id="scanReferenceFilterStatus">Clique sur les lignes à conserver puis sur « Isoler ».</p>
						</div>
						<div class="scan-reference-table-wrapper">
							<table class="scan-reference-table" id="scanReferenceTable">
								<thead>
									<tr>
										<th>Ressource</th>
										<th>Récupérations</th>
										<?php for ($occurrence = 1; $occurrence <= $scan_reference_max_occurrence; $occurrence++): ?>
											<th>x <?php echo $occurrence; ?></th>
										<?php endfor; ?>
									</tr>
								</thead>
								<tbody>
									<?php foreach ($scan_reference_rows as $scan_reference_row): ?>
										<tr class="scan-reference-row <?php echo htmlspecialchars($scan_reference_row['rarity_class'], ENT_QUOTES, 'UTF-8'); ?>" data-resource-id="<?php echo htmlspecialchars($scan_reference_row['id'], ENT_QUOTES, 'UTF-8'); ?>" data-resource-name="<?php echo htmlspecialchars($scan_reference_row['name'], ENT_QUOTES, 'UTF-8'); ?>">
											<td class="scan-reference-name">
												<span><?php echo htmlspecialchars($scan_reference_row['name'], ENT_QUOTES, 'UTF-8'); ?></span>
											</td>
											<td class="scan-reference-recovery">
												<?php if ($scan_reference_row['recovery_modes'] !== []): ?>
													<?php foreach ($scan_reference_row['recovery_modes'] as $recovery_mode): ?>
														<span class="scan-reference-pill"><?php echo htmlspecialchars($recovery_mode, ENT_QUOTES, 'UTF-8'); ?></span>
													<?php endforeach; ?>
												<?php else: ?>
													<span class="scan-reference-muted">—</span>
												<?php endif; ?>
											</td>
											<?php for ($occurrence = 1; $occurrence <= $scan_reference_max_occurrence; $occurrence++): ?>
												<td class="scan-reference-value">
													<?php echo array_key_exists($occurrence - 1, $scan_reference_row['scan_steps']) ? number_format((int) $scan_reference_row['scan_steps'][$occurrence - 1], 0, ',', ' ') : '<span class="scan-reference-muted">—</span>'; ?>
												</td>
											<?php endfor; ?>
										</tr>
									<?php endforeach; ?>
								</tbody>
							</table>
						</div>
					<?php endif; ?>
				</div>
			</div>
		</div>
	<?php endif; ?>
	
	<div class="center-page-bops"></div>
	
	<div class="center-div-menu">
		<div class="padding50">
			
			<p class="txt-center txt-bold txt-s40 small-caps padding25 txt-or">Rapid Emergency & Action Combat Team</p>
			<!-- <p class="txt-center txt-bold txt-italic txt-s20 padding15 txt-or"><span class="padding5">SÉCURITÉ</span> —— <span class="padding5">INTELLIGENCE</span> —— <span class="padding5">SAUVETAGE</span></p> -->
			<p class="txt-justify padding5">Fondée pour combattre la criminalité extrême à travers l’Univers, la R.E.A.C.T. est un label opérationnel indépendant. Nous unissons des pilotes dévoués de tous horizons pour neutraliser les menaces là où la loi fait défaut.</p>
			<p class="txt-center txt-bold txt-s22 padding25 txt-or">—————— La R.E.A.C.T. n’est pas une organisation, mais un standard tactique ——————</p>
			<p class="txt-justify padding5">C’est une initiative inter-organisations conçue pour les joueurs qui partagent la même vision : protéger les citoyens et les PNJs des entités hostiles. Porter l’insigne R.E.A.C.T. ne signifie pas quitter votre organisation ; cela signifie rejoindre un réseau d'intervention rapide.</p>
		</div>
		<div class="center-div-menu-flex txt-bold">
			<div class="menu-item md-trigger" data-modal="modal-About"><a href="#">> EN SAVOIR PLUS <</a></div>
		</div>
	</div>

    <div class="black-filter"></div>

    <!-- Vidéo de fond -->
    <div class="video-container" aria-hidden="true">
        <iframe
            id="react-video"
            src="https://www.youtube-nocookie.com/embed/tFDqWOqm1G8?controls=0&autoplay=1&mute=1&playsinline=1&loop=1&playlist=tFDqWOqm1G8&cc_load_policy=0&iv_load_policy=3&modestbranding=1&rel=0&enablejsapi=1"
            title="Présentation R.E.A.C.T — YouTube"
            loading="lazy"
            allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; fullscreen"
            allowfullscreen
            referrerpolicy="strict-origin-when-cross-origin">
        </iframe>
    </div>
	
	<div class="md-overlay"></div><!-- the overlay element -->

	<!-- classie.js by @desandro: https://github.com/desandro/classie -->
	<script src="js/classie.js"></script>
	<script src="js/modalEffects.js"></script>
	<script src="js/auth.js"></script>

	<!-- for the blur effect -->
	<!-- by @derSchepp https://github.com/Schepp/CSS-Filters-Polyfill -->
	<script>
		// this is important for IEs
		var polyfilter_scriptpath = '/js/';
	</script>
	<script src="js/cssParser.js"></script>
	<script src="js/css-filters-polyfill.js"></script>
	

    <script>
		(function initScanReferenceFilter() {
			const storageKey = 'scanReferenceIsolatedResources.v1';
			const table = document.getElementById('scanReferenceTable');
			const status = document.getElementById('scanReferenceFilterStatus');
			const isolateButton = document.getElementById('scanReferenceIsolateBtn');
			const clearButton = document.getElementById('scanReferenceClearBtn');

			if (!table || !status || !isolateButton || !clearButton) {
				return;
			}

			const rows = Array.from(table.querySelectorAll('.scan-reference-row'));
			const selectedIds = new Set();
			let activeFilterIds = [];

			function saveFilter(ids) {
				if (!Array.isArray(ids) || ids.length === 0) {
					window.localStorage.removeItem(storageKey);
					return;
				}

				window.localStorage.setItem(storageKey, JSON.stringify(ids));
			}

			function loadFilter() {
				try {
					const raw = window.localStorage.getItem(storageKey);
					if (!raw) {
						return [];
					}

					const parsed = JSON.parse(raw);
					return Array.isArray(parsed) ? parsed.map(String).filter(Boolean) : [];
				} catch (error) {
					window.localStorage.removeItem(storageKey);
					return [];
				}
			}

			function getVisibleCount() {
				return rows.filter((row) => !row.classList.contains('is-hidden-by-filter')).length;
			}

			function refreshStatus() {
				const selectedCount = selectedIds.size;
				const visibleCount = getVisibleCount();
				const totalCount = rows.length;
				const filterIsActive = activeFilterIds.length > 0;

				isolateButton.classList.toggle('is-disabled', selectedCount === 0);
				isolateButton.disabled = selectedCount === 0;
				clearButton.classList.toggle('is-disabled', !filterIsActive);
				clearButton.disabled = !filterIsActive;

				if (filterIsActive) {
					status.textContent = 'Filtre actif : ' + visibleCount + ' ressource(s) affichée(s) sur ' + totalCount + '.';
					return;
				}

				if (selectedCount > 0) {
					status.textContent = selectedCount + ' ressource(s) sélectionnée(s). Clique sur « Isoler » pour n’afficher que celles-ci.';
					return;
				}

				status.textContent = 'Clique sur les lignes à conserver puis sur « Isoler ».';
			}

			function applyFilter(ids) {
				activeFilterIds = Array.isArray(ids) ? ids.map(String).filter(Boolean) : [];
				const filterSet = new Set(activeFilterIds);

				rows.forEach((row) => {
					const rowId = String(row.dataset.resourceId || '');
					const shouldHide = filterSet.size > 0 && !filterSet.has(rowId);
					row.classList.toggle('is-hidden-by-filter', shouldHide);
				});

				refreshStatus();
			}

			function clearSelection() {
				selectedIds.clear();
				rows.forEach((row) => row.classList.remove('is-selected'));
				refreshStatus();
			}

			rows.forEach((row) => {
				row.addEventListener('click', function () {
					const rowId = String(row.dataset.resourceId || '');
					if (!rowId) {
						return;
					}

					if (selectedIds.has(rowId)) {
						selectedIds.delete(rowId);
						row.classList.remove('is-selected');
					} else {
						selectedIds.add(rowId);
						row.classList.add('is-selected');
					}

					refreshStatus();
				});
			});

			isolateButton.addEventListener('click', function () {
				if (selectedIds.size === 0) {
					refreshStatus();
					return;
				}

				const ids = Array.from(selectedIds);
				saveFilter(ids);
				applyFilter(ids);
				clearSelection();
			});

			clearButton.addEventListener('click', function () {
				saveFilter([]);
				applyFilter([]);
			});


			applyFilter(loadFilter());
		})();
    </script>


    <script>
		(function initVanillaDbModalState() {
			const shouldOpen = <?php echo $should_open_vanilla_db_modal ? 'true' : 'false'; ?>;
			const modal = document.getElementById('modal-VanillaDb');
			const searchInput = document.getElementById('vanillaDbSearch');

			if (!shouldOpen || !modal || typeof classie === 'undefined') {
				return;
			}

			classie.add(modal, 'md-show');

			if (searchInput) {
				window.requestAnimationFrame(function () {
					searchInput.focus();
					searchInput.setSelectionRange(searchInput.value.length, searchInput.value.length);
				});
			}
		})();
    </script>

    <script>
		(function initVanillaDbImagePreview() {
			const modal = document.getElementById('modal-VanillaDb');
			if (!modal) {
				return;
			}

			const mediaNodes = Array.from(modal.querySelectorAll('.item-custom-card-media[data-preview-src]'));
			if (mediaNodes.length === 0) {
				return;
			}

			let preview = document.getElementById('vanillaDbImagePreview');
			if (!preview) {
				preview = document.createElement('div');
				preview.id = 'vanillaDbImagePreview';
				preview.className = 'vanilla-db-hover-preview';
				preview.setAttribute('aria-hidden', 'true');
				preview.innerHTML = '<img alt="">';
				document.body.appendChild(preview);
			}

			const previewImage = preview.querySelector('img');
			let activeNode = null;

			function movePreview(event) {
				if (!activeNode || !preview.classList.contains('is-visible')) {
					return;
				}

				const offset = 22;
				const bounds = preview.getBoundingClientRect();
				let left = event.clientX + offset;
				let top = event.clientY + offset;

				if ((left + bounds.width) > (window.innerWidth - 16)) {
					left = event.clientX - bounds.width - offset;
				}

				if ((top + bounds.height) > (window.innerHeight - 16)) {
					top = event.clientY - bounds.height - offset;
				}

				left = Math.max(8, left);
				top = Math.max(8, top);

				preview.style.transform = 'translate(' + left + 'px, ' + top + 'px)';
			}

			function hidePreview() {
				activeNode = null;
				preview.classList.remove('is-visible');
				preview.style.transform = 'translate(-9999px, -9999px)';
				previewImage.removeAttribute('src');
				previewImage.alt = '';
			}

			function showPreview(node, event) {
				const src = node.dataset.previewSrc || '';
				if (src === '') {
					return;
				}

				activeNode = node;
				previewImage.src = src;
				previewImage.alt = node.dataset.previewLabel || '';
				preview.classList.add('is-visible');
				movePreview(event);
			}

			previewImage.addEventListener('error', hidePreview);
			window.addEventListener('scroll', hidePreview, { passive: true });
			window.addEventListener('resize', hidePreview);

			mediaNodes.forEach(function (node) {
				node.addEventListener('mouseenter', function (event) {
					showPreview(node, event);
				});
				node.addEventListener('mousemove', movePreview);
				node.addEventListener('mouseleave', hidePreview);
				node.addEventListener('focusin', function () {
					const rect = node.getBoundingClientRect();
					showPreview(node, {
						clientX: rect.right,
						clientY: rect.top
					});
				});
				node.addEventListener('focusout', hidePreview);
			});
		})();
    </script>

    <script>
			(function initVanillaDbPriceEstimates() {
				const modal = document.getElementById('modal-VanillaDb');
				if (!modal) {
					return;
				}

				const estimateNodes = Array.from(modal.querySelectorAll('[data-uex-estimate]'));
				if (estimateNodes.length === 0) {
					return;
				}

				let hasLoaded = false;
				let isLoading = false;

				function applyEstimate(node, estimate) {
					const valueNode = node.querySelector('[data-uex-estimate-value]');
					if (!valueNode) {
						return;
					}

					valueNode.classList.remove('is-loading', 'is-unavailable');

					if (!estimate || !estimate.has_estimate) {
						valueNode.textContent = estimate && estimate.error ? 'Indisponible' : 'Aucune annonce WTS';
						valueNode.classList.add('is-unavailable');
						if (estimate && estimate.sample_count) {
							valueNode.title = estimate.sample_count + ' annonce(s) analysée(s)';
						}
						return;
					}

					valueNode.textContent = estimate.formatted || '—';
					valueNode.title = 'Moyenne calculée sur ' + (estimate.sample_count || 0) + ' annonce(s) WTS';
				}

				function markGlobalFailure() {
					estimateNodes.forEach(function (node) {
						applyEstimate(node, { has_estimate: false, error: true, sample_count: 0 });
					});
				}

				function loadEstimates() {
					if (hasLoaded || isLoading) {
						return;
					}

					const names = estimateNodes
						.map(function (node) {
							return node.dataset.uexQuery || '';
						})
						.filter(function (name, index, array) {
							return name !== '' && array.indexOf(name) === index;
						});

					if (names.length === 0) {
						hasLoaded = true;
						return;
					}

					isLoading = true;
					const params = new URLSearchParams();
					params.set('ajax', 'vanilla-price-estimates');
					names.forEach(function (name) {
						params.append('names[]', name);
					});

					fetch('index.php?' + params.toString(), {
						credentials: 'same-origin',
						headers: {
							'Accept': 'application/json'
						}
					})
						.then(function (response) {
							if (!response.ok) {
								throw new Error('HTTP ' + response.status);
							}
							return response.json();
						})
						.then(function (payload) {
							const estimates = payload && payload.estimates ? payload.estimates : {};
							estimateNodes.forEach(function (node) {
								applyEstimate(node, estimates[node.dataset.uexQuery || ''] || null);
							});
							hasLoaded = true;
						})
						.catch(function () {
							markGlobalFailure();
						})
						.finally(function () {
							isLoading = false;
						});
				}

				if (modal.classList.contains('md-show')) {
					loadEstimates();
				}

				const observer = new MutationObserver(function () {
					if (modal.classList.contains('md-show')) {
						loadEstimates();
					}
				});

				observer.observe(modal, {
					attributes: true,
					attributeFilter: ['class']
				});
			})();
    </script>

    <script>
		(function initItemCustomSearch() {
			const searchInput = document.getElementById('itemCustomSearch');
			const resetButton = document.getElementById('itemCustomSearchReset');
			const status = document.getElementById('itemCustomSearchStatus');
			const grid = document.getElementById('itemCustomGrid');
			const typeCheckboxes = Array.from(document.querySelectorAll('.item-custom-type-checkbox'));

			if (!searchInput || !resetButton || !status || !grid) {
				return;
			}

			const cards = Array.from(grid.querySelectorAll('.item-custom-card'));

			function normalizeValue(value) {
				return String(value || '')
					.toLowerCase()
					.normalize('NFD')
					.replace(/[̀-ͯ]/g, '')
					.trim();
			}

			function getSelectedTypes() {
				return typeCheckboxes
					.filter((checkbox) => checkbox.checked)
					.map((checkbox) => ({
						label: checkbox.value,
						value: normalizeValue(checkbox.value)
					}));
			}

			function applyFilter() {
				const query = normalizeValue(searchInput.value);
				const selectedTypes = getSelectedTypes();
				const selectedTypeSet = new Set(selectedTypes.map((type) => type.value));
				let visibleCount = 0;

				cards.forEach((card) => {
					const haystack = normalizeValue(card.dataset.itemSearch || '');
					const itemType = normalizeValue(card.dataset.itemType || '');
					const matchesQuery = query === '' || haystack.includes(query);
					const matchesType = selectedTypeSet.size === 0 || selectedTypeSet.has(itemType);
					const isVisible = matchesQuery && matchesType;
					card.classList.toggle('is-hidden-by-search', !matchesQuery);
					card.classList.toggle('is-hidden-by-type', matchesQuery && !matchesType);
					if (isVisible) {
						visibleCount += 1;
					}
				});

				if (query === '' && selectedTypeSet.size === 0) {
					status.textContent = visibleCount + ' objet(s) affiché(s) sur ' + cards.length + '.';
					return;
				}

				const activeFilters = [];
				if (query !== '') {
					activeFilters.push('la recherche « ' + searchInput.value.trim() + ' »');
				}
				if (selectedTypes.length > 0) {
					activeFilters.push((selectedTypes.length > 1 ? 'les types ' : 'le type ') + selectedTypes.map((type) => '« ' + type.label + ' »').join(', '));
				}

				status.textContent = visibleCount + ' objet(s) correspondent à ' + activeFilters.join(' + ') + '.';
			}

			searchInput.addEventListener('input', applyFilter);
			typeCheckboxes.forEach((checkbox) => {
				checkbox.addEventListener('change', applyFilter);
			});
			resetButton.addEventListener('click', function () {
				searchInput.value = '';
				typeCheckboxes.forEach((checkbox) => {
					checkbox.checked = false;
				});
				applyFilter();
				searchInput.focus();
			});

			applyFilter();
		})();
    </script>

    <script>
		(function initShipPresetFilter() {
			const manufacturerSelect = document.getElementById('shipPresetManufacturerFilter');
			const shipSelect = document.getElementById('shipPresetShipFilter');
			const status = document.getElementById('shipPresetFilterStatus');
			const grid = document.getElementById('shipPresetsGrid');

			if (!manufacturerSelect || !shipSelect || !status || !grid) {
				return;
			}

			const cards = Array.from(grid.querySelectorAll('.ship-preset-card'));
			const manufacturerToShips = new Map();

			cards.forEach((card) => {
				const manufacturer = String(card.dataset.manufacturer || '').trim();
				const shipName = String(card.dataset.shipName || '').trim();

				if (!manufacturerToShips.has(manufacturer)) {
					manufacturerToShips.set(manufacturer, new Set());
				}

				if (shipName !== '') {
					manufacturerToShips.get(manufacturer).add(shipName);
				}
			});

			function setShipOptions(manufacturer) {
				const previousValue = shipSelect.value;
				shipSelect.innerHTML = '';

				if (manufacturer === '') {
					shipSelect.disabled = true;
					shipSelect.append(new Option("Choisis d'abord une manufacture", ''));
					shipSelect.value = '';
					return;
				}

				shipSelect.disabled = false;
				shipSelect.append(new Option('Tous les vaisseaux de cette manufacture', ''));

				const ships = Array.from(manufacturerToShips.get(manufacturer) || []);
				ships.sort((a, b) => a.localeCompare(b, 'fr', { sensitivity: 'base' }));

				ships.forEach((shipName) => {
					shipSelect.append(new Option(shipName, shipName));
				});

				shipSelect.value = ships.includes(previousValue) ? previousValue : '';
			}

			function refreshStatus() {
				const visibleCards = cards.filter((card) => !card.classList.contains('is-hidden-by-ship-filter'));
				const visibleShips = new Set(
					visibleCards
						.map((card) => String(card.dataset.shipName || '').trim())
						.filter(Boolean)
				);
				const selectedManufacturer = manufacturerSelect.value;
				const selectedShip = shipSelect.value;

				if (selectedManufacturer !== '' && selectedShip !== '') {
					status.textContent = visibleCards.length + ' preset(s) affiché(s) pour ' + selectedShip + ' chez ' + selectedManufacturer + '.';
					return;
				}

				if (selectedManufacturer !== '') {
					status.textContent = visibleCards.length + ' preset(s) affiché(s) pour ' + visibleShips.size + ' vaisseau(x) chez ' + selectedManufacturer + '.';
					return;
				}

				status.textContent = visibleCards.length + ' preset(s) affiché(s) sur ' + cards.length + ' pour ' + visibleShips.size + ' vaisseau(x).';
			}

			function applyFilter() {
				const selectedManufacturer = manufacturerSelect.value;
				const selectedShip = shipSelect.value;

				cards.forEach((card) => {
					const manufacturer = String(card.dataset.manufacturer || '').trim();
					const shipName = String(card.dataset.shipName || '').trim();
					const hideByManufacturer = selectedManufacturer !== '' && manufacturer !== selectedManufacturer;
					const hideByShip = selectedShip !== '' && shipName !== selectedShip;
					card.classList.toggle('is-hidden-by-ship-filter', hideByManufacturer || hideByShip);
				});

				refreshStatus();
			}

			manufacturerSelect.addEventListener('change', function () {
				setShipOptions(manufacturerSelect.value);
				applyFilter();
			});

			shipSelect.addEventListener('change', applyFilter);
			setShipOptions(manufacturerSelect.value);
			applyFilter();
		})();
    </script>

    <script>
        // On ajoute dynamiquement l'origine à l'URL de l'iframe (recommandé par l'API YouTube)
        (function attachOrigin(){
            const iframe = document.getElementById('react-video');
            const url = new URL(iframe.src);
            if (!url.searchParams.has('origin')) {
                url.searchParams.set('origin', window.location.origin);
                iframe.src = url.toString();
            }
        })();

        // Utilitaires pour parler au lecteur via postMessage (API YouTube)
        function ytCommand(func, args = []) {
            const iframe = document.getElementById('react-video');
            if (!iframe || !iframe.contentWindow) return;
            iframe.contentWindow.postMessage(JSON.stringify({ event: 'command', func, args }), '*');
        }

        // Au premier geste utilisateur : on remet le son et on met le volume à 50 %
        function enableSoundOnce() {
            ytCommand('unMute');
            ytCommand('setVolume', [50]);

            // Masquer le bouton
            const btn = document.getElementById('unmute-btn');
            if (btn) btn.style.display = 'none';

            // Retirer les écouteurs pour ne pas répéter l’action
            window.removeEventListener('pointerdown', enableSoundOnce);
            window.removeEventListener('keydown', enableSoundOnce);
            window.removeEventListener('touchstart', enableSoundOnce, { passive: true });
        }

        // Bouton dédié
        // document.getElementById('unmute-btn').addEventListener('click', enableSoundOnce);

        // …ou n’importe quel premier geste sur la page
        //window.addEventListener('pointerdown', enableSoundOnce, { once: true });
        //window.addEventListener('keydown',      enableSoundOnce, { once: true });
        //window.addEventListener('touchstart',   enableSoundOnce, { once: true, passive: true });
    </script>
	<div class="footer txt-s12 txt-center">
		<p>
			<a href="https://robertsspaceindustries.com/en/orgs/REACT" target="_blank" title="Notre page RSI"><img src="img/icon09b.png" width="48" height="48" alt="" /></a>
			<a href="https://discord.gg/dAvST8E7Mq" target="_blank" title="Notre Discord"><img src="img/icon08b.png" width="48" height="48" alt="" /></a>
			<a href="https://robertsspaceindustries.com" target="_blank" title="RSI"><img src="img/icon10.png" width="48" height="48" alt="" /></a>
		</p>
		<p>Copyright © 2024-<?php echo date('Y'); ?> | www.react-sc.fr | Tous droits réservés.</p>
	</div>
</body>

</html>
