<?php
/**
 * ============================================
 * FLOWBOT DCI v4.0 - PROFESSIONAL DASHBOARD
 * Complete UI Redesign: 78+ Progress Bars
 * ============================================
 */
declare(strict_types=1);

// Variables from controller
$baseUrl = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/\\');
$pageTitle = 'Processing Dashboard';
$csrfToken = $csrfToken ?? '';
$processId = $processId ?? '';
$isInitializing = $isInitializing ?? false;

// Data with safe defaults
$data = $data ?? [];
$logs = $logs ?? [];

// Core Stats
$totalLinks = max($data['total_links'] ?? 0, 1);
$processedLinks = $data['processed_links'] ?? 0;
$importedLinks = $data['imported_links'] ?? 0;
$ignoredLinks = $data['ignored_links'] ?? 0;
$errorLinks = $data['error_links'] ?? 0;

// Calculate percentages
$processedPercent = round(($processedLinks / $totalLinks) * 100, 1);
$importedPercent = round(($importedLinks / $totalLinks) * 100, 1);
$ignoredPercent = round(($ignoredLinks / $totalLinks) * 100, 1);
$errorPercent = round(($errorLinks / $totalLinks) * 100, 1);
$totalProcessedPercent = round((($processedLinks + $ignoredLinks + $errorLinks) / $totalLinks) * 100, 1);

// Times
$elapsedTime = gmdate('H:i:s', (int)($data['elapsed_time'] ?? 0));
$remainingTime = gmdate('H:i:s', (int)($data['remaining_time'] ?? 0));
$processingRate = $data['processing_rate'] ?? 0;

// Remaining links
$remainingLinks = 0;
foreach ($data['phase_queues'] ?? [] as $queue) {
    $remainingLinks += count($queue);
}

// Current phase
$currentPhase = $data['phase_index'] ?? 0;

// Status
$isComplete = ($remainingLinks === 0 && !$isInitializing && $totalLinks > 0);
$processStatus = $data['status'] ?? ($isComplete ? 'completed' : ($isInitializing ? 'initializing' : 'running'));
$isPaused = $processStatus === 'paused';

// Domain stats
$domainStats = $data['domain_stats'] ?? [];
$totalDomains = count($domainStats);

// Success rate
$successRate = $totalLinks > 0 ? round(($importedLinks / $totalLinks) * 100, 1) : 0;

// HTTP codes
$httpCodes = $data['http_codes'] ?? [];
arsort($httpCodes);

// Detailed stats
$ignoredDetails = $data['ignored_details'] ?? ['duplicate' => 0, 'invalid_url' => 0, 'blocked_domain' => 0, 'non_html' => 0];
$errorDetails = $data['error_details'] ?? ['timeout' => 0, 'http_429' => 0, 'http_404' => 0, 'http_403' => 0, 'http_5xx' => 0, 'connection' => 0, 'metadata' => 0, 'other' => 0];
$requestStats = $data['request_stats'] ?? ['total_requests' => 0, 'total_response_time' => 0, 'response_times' => []];
$retryStats = $data['retry_stats'] ?? ['total_retries' => 0, 'retries_by_phase' => [0=>0,1=>0,2=>0,3=>0], 'urls_with_retries' => 0];
$phaseStats = $data['phase_stats'] ?? [];
$phaseQueues = $data['phase_queues'] ?? [[], [], [], []];

// Phase configs
$phaseConfigs = [
    0 => ['concurrency' => 300, 'timeout' => 5],
    1 => ['concurrency' => 200, 'timeout' => 8],
    2 => ['concurrency' => 150, 'timeout' => 12],
    3 => ['concurrency' => 100, 'timeout' => 20],
];

// Calculate totals for bars
$ignoredTotal = array_sum($ignoredDetails);
$errorTotal = ($errorDetails['http_403'] ?? 0) + ($errorDetails['http_404'] ?? 0) + ($errorDetails['http_429'] ?? 0) +
              ($errorDetails['http_5xx'] ?? 0) + ($errorDetails['timeout'] ?? 0) + ($errorDetails['connection'] ?? 0) +
              ($errorDetails['metadata'] ?? 0) + ($errorDetails['other'] ?? 0);

// HTTP code categories
$http2xx = array_filter($httpCodes, fn($k) => $k >= 200 && $k < 300, ARRAY_FILTER_USE_KEY);
$http3xx = array_filter($httpCodes, fn($k) => $k >= 300 && $k < 400, ARRAY_FILTER_USE_KEY);
$http4xx = array_filter($httpCodes, fn($k) => $k >= 400 && $k < 500, ARRAY_FILTER_USE_KEY);
$http5xx = array_filter($httpCodes, fn($k) => $k >= 500, ARRAY_FILTER_USE_KEY);
$maxHttpCount = max(1, ...array_values($httpCodes ?: [1]));

// Domain health counts
$healthyDomains = 0;
$warningDomains = 0;
$problematicDomains = 0;
foreach ($domainStats as $stats) {
    $total = $stats['total'] ?? 0;
    $error = $stats['error'] ?? 0;
    $errorRate = $total > 0 ? ($error / $total) : 0;
    if ($errorRate > 0.5) $problematicDomains++;
    elseif ($errorRate > 0.2) $warningDomains++;
    else $healthyDomains++;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?= htmlspecialchars($pageTitle) ?> - Flowb0t DCI v4.0</title>
    <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><rect width='32' height='32' rx='8' fill='%233B82F6'/><path d='M8 10h16M8 16h12M8 22h8' stroke='white' stroke-width='2.5' stroke-linecap='round'/></svg>">
    <link rel="stylesheet" href="<?= $baseUrl ?>/assets/css/v4-styles.css?v=<?= time() ?>">
</head>
<body>
    <?php if ($isInitializing): ?>
    <!-- Initializing Overlay -->
    <div id="initializingOverlay" class="initializing-overlay">
        <div class="init-content">
            <div class="init-spinner"></div>
            <h2 class="init-title">Preparing Processing...</h2>
            <div class="init-steps">
                <div class="init-step active" id="stepExtract">
                    <span class="step-icon"><svg class="spinner-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18"><circle cx="12" cy="12" r="10" stroke-opacity="0.25"/><path d="M12 2a10 10 0 0 1 10 10" stroke-linecap="round"/></svg></span>
                    <span class="step-text">Extracting URLs...</span>
                </div>
                <div class="init-step" id="stepInit">
                    <span class="step-icon">&#9675;</span>
                    <span class="step-text">Initializing tracker...</span>
                </div>
                <div class="init-step" id="stepCreate">
                    <span class="step-icon">&#9675;</span>
                    <span class="step-text">Creating process...</span>
                </div>
            </div>
            <p class="init-subtitle">Page loaded instantly! Initialization in progress...</p>
        </div>
    </div>
    <?php endif; ?>

    <!-- Navigation -->
    <nav class="main-nav">
        <div class="nav-container">
            <div class="nav-brand">
                <a href="<?= $baseUrl ?>/" class="brand-link">
                    <span class="brand-logo">
                        <svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <rect width="32" height="32" rx="8" fill="url(#brand-gradient)"/>
                            <path d="M8 10h16M8 16h12M8 22h8" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
                            <circle cx="24" cy="22" r="4" fill="#10B981"/>
                            <defs><linearGradient id="brand-gradient" x1="0" y1="0" x2="32" y2="32"><stop stop-color="#3B82F6"/><stop offset="1" stop-color="#8B5CF6"/></linearGradient></defs>
                        </svg>
                    </span>
                    <span class="brand-text">Flowb0t DCI</span>
                    <span class="brand-version">v4.0</span>
                </a>
            </div>
            <div class="nav-main">
                <a href="<?= $baseUrl ?>/" class="nav-link">
                    <svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></svg>
                    <span>Dashboard</span>
                </a>
                <a href="<?= $baseUrl ?>/history" class="nav-link">
                    <svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"/><polyline points="12,7 12,12 16,14"/></svg>
                    <span>History</span>
                </a>
            </div>
            <div class="nav-right">
                <span class="status-indicator <?= $processStatus ?>" id="statusIndicator">
                    <span class="status-dot"></span>
                    <span id="statusText"><?= ucfirst($processStatus) ?></span>
                </span>
            </div>
        </div>
    </nav>

    <!-- Main Content -->
    <main class="main-content" id="mainContent" style="<?= $isInitializing ? 'opacity: 0.3; pointer-events: none;' : '' ?>">

        <?php if ($isComplete): ?>
        <!-- Completion Banner -->
        <div class="completion-banner" id="completionBanner">
            <div class="completion-icon">
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="32" height="32"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
            </div>
            <div class="completion-info">
                <h2 class="completion-title">Processing Complete!</h2>
                <p class="completion-subtitle">Processed <?= number_format($totalLinks) ?> URLs in <?= $elapsedTime ?> with <?= $successRate ?>% success rate</p>
            </div>
            <div class="completion-actions">
                <a href="<?= $baseUrl ?>/?export=<?= urlencode($processId) ?>" class="btn btn-primary">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
                    Export Results
                </a>
                <a href="<?= $baseUrl ?>/new" class="btn btn-secondary">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="16"/><line x1="8" y1="12" x2="16" y2="12"/></svg>
                    New Process
                </a>
            </div>
        </div>
        <?php endif; ?>

        <!-- HERO SECTION -->
        <section class="hero-section" id="heroSection">
            <div class="hero-header">
                <h1 class="hero-title">Processing Dashboard</h1>
                <div class="hero-meta">
                    <span class="hero-meta-item"><strong id="heroProcessed"><?= number_format($processedLinks) ?></strong> / <?= number_format($totalLinks) ?> URLs</span>
                    <span class="hero-meta-item">ETA: <strong id="heroEta"><?= $remainingTime ?></strong></span>
                </div>
            </div>

            <!-- Main Progress Bar -->
            <div class="hero-progress">
                <div class="hero-progress-bar">
                    <div class="hero-progress-fill" id="heroProgressFill" style="width: <?= $totalProcessedPercent ?>%"></div>
                    <span class="hero-progress-text" id="heroProgressText"><?= $totalProcessedPercent ?>%</span>
                </div>
            </div>

            <!-- Hero Stats -->
            <div class="hero-stats">
                <div class="hero-stat success">
                    <div class="hero-stat-value" id="statImported"><?= number_format($importedLinks) ?></div>
                    <div class="hero-stat-label">Imported</div>
                </div>
                <div class="hero-stat warning">
                    <div class="hero-stat-value" id="statIgnored"><?= number_format($ignoredLinks) ?></div>
                    <div class="hero-stat-label">Ignored</div>
                </div>
                <div class="hero-stat error">
                    <div class="hero-stat-value" id="statErrors"><?= number_format($errorLinks) ?></div>
                    <div class="hero-stat-label">Errors</div>
                </div>
                <div class="hero-stat info">
                    <div class="hero-stat-value" id="statRemaining"><?= number_format($remainingLinks) ?></div>
                    <div class="hero-stat-label">Remaining</div>
                </div>
            </div>
        </section>

        <!-- 3-COLUMN DASHBOARD GRID -->
        <div class="dashboard-grid">

            <!-- LEFT COLUMN -->
            <div class="dashboard-column">

                <!-- Core Progress -->
                <div class="card">
                    <div class="card-header">
                        <span class="card-title">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 20V10"/><path d="M18 20V4"/><path d="M6 20v-4"/></svg>
                            Core Progress
                        </span>
                    </div>
                    <div class="card-body">
                        <div class="progress-item">
                            <div class="progress-header"><span class="progress-label">Processed</span><span class="progress-value" id="coreProcessedVal"><?= $processedLinks ?> (<?= $processedPercent ?>%)</span></div>
                            <div class="progress-bar lg"><div class="progress-fill processed" id="coreProcessedBar" style="width: <?= $processedPercent ?>%"></div></div>
                        </div>
                        <div class="progress-item">
                            <div class="progress-header"><span class="progress-label">Imported</span><span class="progress-value" id="coreImportedVal"><?= $importedLinks ?> (<?= $importedPercent ?>%)</span></div>
                            <div class="progress-bar lg"><div class="progress-fill imported" id="coreImportedBar" style="width: <?= $importedPercent ?>%"></div></div>
                        </div>
                        <div class="progress-item">
                            <div class="progress-header"><span class="progress-label">Ignored</span><span class="progress-value" id="coreIgnoredVal"><?= $ignoredLinks ?> (<?= $ignoredPercent ?>%)</span></div>
                            <div class="progress-bar lg"><div class="progress-fill ignored" id="coreIgnoredBar" style="width: <?= $ignoredPercent ?>%"></div></div>
                        </div>
                        <div class="progress-item">
                            <div class="progress-header"><span class="progress-label">Errors</span><span class="progress-value" id="coreErrorsVal"><?= $errorLinks ?> (<?= $errorPercent ?>%)</span></div>
                            <div class="progress-bar lg"><div class="progress-fill errors" id="coreErrorsBar" style="width: <?= $errorPercent ?>%"></div></div>
                        </div>
                    </div>
                </div>

                <!-- Ignored by Type -->
                <div class="card">
                    <div class="card-header">
                        <span class="card-title">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="4.93" y1="4.93" x2="19.07" y2="19.07"/></svg>
                            Ignored by Type
                        </span>
                        <span class="card-badge" id="ignoredTotalBadge"><?= $ignoredTotal ?></span>
                    </div>
                    <div class="card-body">
                        <?php
                        $ignoredTypes = [
                            ['id' => 'duplicate', 'label' => 'Duplicates', 'value' => $ignoredDetails['duplicate'] ?? 0, 'color' => 'blue'],
                            ['id' => 'invalid', 'label' => 'Invalid URL', 'value' => $ignoredDetails['invalid_url'] ?? 0, 'color' => 'orange'],
                            ['id' => 'blocked', 'label' => 'Blocked Domain', 'value' => $ignoredDetails['blocked_domain'] ?? 0, 'color' => 'red'],
                            ['id' => 'nonhtml', 'label' => 'Non-HTML', 'value' => $ignoredDetails['non_html'] ?? 0, 'color' => 'gray'],
                        ];
                        foreach ($ignoredTypes as $type):
                            $pct = $ignoredTotal > 0 ? round(($type['value'] / $ignoredTotal) * 100, 1) : 0;
                        ?>
                        <div class="progress-item">
                            <div class="progress-header"><span class="progress-label"><?= $type['label'] ?></span><span class="progress-value" id="ignored<?= ucfirst($type['id']) ?>Val"><?= $type['value'] ?></span></div>
                            <div class="progress-bar"><div class="progress-fill <?= $type['color'] ?>" id="ignored<?= ucfirst($type['id']) ?>Bar" style="width: <?= $pct ?>%"></div></div>
                        </div>
                        <?php endforeach; ?>
                    </div>
                </div>

                <!-- Errors by Type -->
                <div class="card">
                    <div class="card-header">
                        <span class="card-title">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>
                            Errors by Type
                        </span>
                        <span class="card-badge" id="errorTotalBadge"><?= $errorTotal ?></span>
                    </div>
                    <div class="card-body">
                        <?php
                        $errorTypes = [
                            ['id' => '403', 'label' => 'HTTP 403', 'value' => $errorDetails['http_403'] ?? 0, 'color' => 'red'],
                            ['id' => '404', 'label' => 'HTTP 404', 'value' => $errorDetails['http_404'] ?? 0, 'color' => 'orange'],
                            ['id' => '429', 'label' => 'HTTP 429', 'value' => $errorDetails['http_429'] ?? 0, 'color' => 'yellow'],
                            ['id' => '5xx', 'label' => 'HTTP 5xx', 'value' => $errorDetails['http_5xx'] ?? 0, 'color' => 'purple'],
                            ['id' => 'timeout', 'label' => 'Timeout', 'value' => $errorDetails['timeout'] ?? 0, 'color' => 'gray'],
                            ['id' => 'connection', 'label' => 'Connection', 'value' => $errorDetails['connection'] ?? 0, 'color' => 'cyan'],
                            ['id' => 'metadata', 'label' => 'Metadata', 'value' => $errorDetails['metadata'] ?? 0, 'color' => 'pink'],
                            ['id' => 'other', 'label' => 'Other', 'value' => $errorDetails['other'] ?? 0, 'color' => 'gray'],
                        ];
                        foreach ($errorTypes as $type):
                            $pct = $errorTotal > 0 ? round(($type['value'] / $errorTotal) * 100, 1) : 0;
                        ?>
                        <div class="progress-item">
                            <div class="progress-header"><span class="progress-label"><?= $type['label'] ?></span><span class="progress-value" id="error<?= $type['id'] ?>Val"><?= $type['value'] ?></span></div>
                            <div class="progress-bar"><div class="progress-fill <?= $type['color'] ?>" id="error<?= $type['id'] ?>Bar" style="width: <?= $pct ?>%"></div></div>
                        </div>
                        <?php endforeach; ?>
                    </div>
                </div>

                <!-- Retry Stats -->
                <div class="card">
                    <div class="card-header">
                        <span class="card-title">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg>
                            Retry Stats
                        </span>
                    </div>
                    <div class="card-body">
                        <div class="retry-header">
                            <span class="retry-total" id="retryTotal"><?= $retryStats['total_retries'] ?? 0 ?></span>
                            <span class="retry-success-rate" id="retrySuccessRate">0% success</span>
                        </div>
                        <div class="retry-phases">
                            <?php
                            $maxRetries = max(1, max($retryStats['retries_by_phase'][0] ?? 0, $retryStats['retries_by_phase'][1] ?? 0, $retryStats['retries_by_phase'][2] ?? 0, $retryStats['retries_by_phase'][3] ?? 0));
                            for ($i = 0; $i <= 3; $i++):
                                $retryCount = $retryStats['retries_by_phase'][$i] ?? 0;
                                $retryPct = $maxRetries > 0 ? round(($retryCount / $maxRetries) * 100, 1) : 0;
                            ?>
                            <div class="retry-phase">
                                <span class="retry-phase-label">P<?= $i ?></span>
                                <div class="retry-phase-bar"><div class="progress-fill phase-<?= $i ?>" id="retryPhase<?= $i ?>Bar" style="width: <?= $retryPct ?>%"></div></div>
                                <span class="retry-phase-count" id="retryPhase<?= $i ?>Val"><?= $retryCount ?></span>
                            </div>
                            <?php endfor; ?>
                        </div>
                    </div>
                </div>

                <!-- Time Stats -->
                <div class="card">
                    <div class="card-header">
                        <span class="card-title">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
                            Time Stats
                        </span>
                    </div>
                    <div class="card-body">
                        <div class="time-grid">
                            <div class="time-item"><div class="time-label">Elapsed</div><div class="time-value" id="timeElapsed"><?= $elapsedTime ?></div></div>
                            <div class="time-item"><div class="time-label">Remaining</div><div class="time-value" id="timeRemaining"><?= $remainingTime ?></div></div>
                            <div class="time-item"><div class="time-label">Rate</div><div class="time-value" id="processingRate"><?= $processingRate ?>/s</div></div>
                            <div class="time-item"><div class="time-label">Domains</div><div class="time-value" id="totalDomains"><?= $totalDomains ?></div></div>
                        </div>
                    </div>
                </div>

                <!-- Controls -->
                <?php if (!$isComplete): ?>
                <div class="card">
                    <div class="card-header">
                        <span class="card-title">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
                            Controls
                        </span>
                    </div>
                    <div class="card-body">
                        <div class="control-buttons" id="controlButtons">
                            <?php if ($isPaused): ?>
                            <button class="btn-control btn-resume" id="btnResume" data-id="<?= htmlspecialchars($processId) ?>">
                                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><polygon points="5 3 19 12 5 21 5 3"/></svg>
                                Resume
                            </button>
                            <?php else: ?>
                            <button class="btn-control btn-pause" id="btnPause" data-id="<?= htmlspecialchars($processId) ?>">
                                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg>
                                Pause
                            </button>
                            <?php endif; ?>
                            <button class="btn-control btn-cancel" id="btnCancel" data-id="<?= htmlspecialchars($processId) ?>">
                                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>
                                Cancel
                            </button>
                        </div>
                    </div>
                </div>
                <?php endif; ?>
            </div>

            <!-- CENTER COLUMN -->
            <div class="dashboard-column">

                <!-- Phase Pipeline -->
                <div class="card">
                    <div class="card-header">
                        <span class="card-title">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
                            Phase Pipeline
                        </span>
                    </div>
                    <div class="card-body">
                        <div class="phase-pipeline">
                            <?php for ($i = 0; $i <= 3; $i++):
                                $stats = $phaseStats[$i] ?? ['success' => 0, 'retry' => 0, 'error' => 0];
                                $queueCount = count($phaseQueues[$i] ?? []);
                                $isActive = ($i === $currentPhase) && !$isComplete;
                                $isCompleted = ($i < $currentPhase) || $isComplete;
                                $totalPhaseItems = $stats['success'] + $stats['retry'] + $stats['error'] + $queueCount;
                                $phaseProgress = $totalPhaseItems > 0 ? round((($stats['success'] + $stats['error']) / $totalPhaseItems) * 100, 1) : 0;
                                $status = $isActive ? 'active' : ($isCompleted ? 'completed' : ($queueCount > 0 ? 'waiting' : 'pending'));
                            ?>
                            <div class="phase-card <?= $isActive ? 'active' : '' ?> <?= $isCompleted ? 'completed' : '' ?>" data-phase="<?= $i ?>">
                                <div class="phase-header">
                                    <span class="phase-name">
                                        <span class="phase-badge"><?= $i ?></span>
                                        Phase <?= $i ?>
                                    </span>
                                    <span class="phase-status <?= $status ?>"><?= ucfirst($status) ?></span>
                                </div>
                                <div class="progress-item">
                                    <div class="progress-bar"><div class="progress-fill phase-<?= $i ?>" id="phaseProgress<?= $i ?>" style="width: <?= $phaseProgress ?>%"></div></div>
                                </div>
                                <div class="phase-stats-row">
                                    <span class="phase-stat success" id="phaseStat<?= $i ?>Success">&#10003; <?= $stats['success'] ?></span>
                                    <span class="phase-stat retry" id="phaseStat<?= $i ?>Retry">&#8635; <?= $stats['retry'] ?></span>
                                    <span class="phase-stat error" id="phaseStat<?= $i ?>Error">&#10007; <?= $stats['error'] ?></span>
                                    <span class="phase-stat" id="phaseQueue<?= $i ?>">Queue: <?= $queueCount ?></span>
                                </div>
                                <div class="phase-config">
                                    <span>Concurrency: <?= $phaseConfigs[$i]['concurrency'] ?></span>
                                    <span>Timeout: <?= $phaseConfigs[$i]['timeout'] ?>s</span>
                                </div>
                            </div>
                            <?php endfor; ?>
                        </div>
                    </div>
                </div>

                <!-- Performance -->
                <div class="card">
                    <div class="card-header">
                        <span class="card-title">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
                            Performance Live
                        </span>
                    </div>
                    <div class="card-body">
                        <div class="performance-grid">
                            <div class="perf-item">
                                <div class="perf-label">URLs/second</div>
                                <div class="perf-value" id="perfSpeed">0.0</div>
                                <div class="perf-bar"><div class="progress-fill green" id="perfSpeedBar" style="width: 0%"></div></div>
                            </div>
                            <div class="perf-item">
                                <div class="perf-label">Avg Latency</div>
                                <div class="perf-value"><span id="perfLatency">0</span>ms</div>
                                <div class="perf-bar"><div class="progress-fill orange" id="perfLatencyBar" style="width: 0%"></div></div>
                            </div>
                            <div class="perf-item">
                                <div class="perf-label">Success Rate</div>
                                <div class="perf-value"><span id="perfSuccessRate"><?= $successRate ?></span>%</div>
                                <div class="perf-bar"><div class="progress-fill green" id="perfSuccessBar" style="width: <?= $successRate ?>%"></div></div>
                            </div>
                            <div class="perf-item">
                                <div class="perf-label">Batch Progress</div>
                                <div class="perf-value"><span id="perfBatchCurrent">0</span>/<span id="perfBatchTotal">0</span></div>
                                <div class="perf-bar"><div class="progress-fill blue" id="perfBatchBar" style="width: 0%"></div></div>
                            </div>
                        </div>
                        <div class="chart-container">
                            <canvas id="speedChart" height="80"></canvas>
                        </div>
                    </div>
                </div>

                <!-- Error Trend -->
                <div class="card">
                    <div class="card-header">
                        <span class="card-title">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
                            Error Trend (Last 60s)
                        </span>
                    </div>
                    <div class="card-body">
                        <div class="chart-container-small" style="height: 120px;">
                            <canvas id="errorTrendChart"></canvas>
                        </div>
                        <div class="error-trend-legend" style="display: flex; justify-content: space-around; margin-top: 8px; font-size: 11px;">
                            <span style="color: #F59E0B;">● <span id="errorTrend403">0</span> 403</span>
                            <span style="color: #EF4444;">● <span id="errorTrend404">0</span> 404</span>
                            <span style="color: #8B5CF6;">● <span id="errorTrend429">0</span> 429</span>
                            <span style="color: #EC4899;">● <span id="errorTrend5xx">0</span> 5xx</span>
                            <span style="color: #6B7280;">● <span id="errorTrendOther">0</span> other</span>
                        </div>
                    </div>
                </div>

                <!-- Request Stats -->
                <div class="card">
                    <div class="card-header">
                        <span class="card-title">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21.21 15.89A10 10 0 1 1 8 2.83"/><path d="M22 12A10 10 0 0 0 12 2v10z"/></svg>
                            Request Stats
                        </span>
                    </div>
                    <div class="card-body">
                        <div class="time-grid" style="margin-bottom: 12px;">
                            <div class="time-item"><div class="time-label">Total Requests</div><div class="time-value" id="totalRequests"><?= $requestStats['total_requests'] ?? 0 ?></div></div>
                            <div class="time-item"><div class="time-label">Total Time</div><div class="time-value" id="totalResponseTime"><?= round(($requestStats['total_response_time'] ?? 0), 1) ?>s</div></div>
                        </div>
                        <!-- Response Time Histogram -->
                        <div class="chart-container-small" style="height: 100px; margin-bottom: 12px;">
                            <canvas id="latencyHistogram"></canvas>
                        </div>
                        <div class="latency-stats" style="display: flex; justify-content: space-between; font-size: 11px; margin-bottom: 12px;">
                            <span>Min: <strong id="latencyMin">-</strong></span>
                            <span>Avg: <strong id="latencyAvg">-</strong></span>
                            <span>Max: <strong id="latencyMax">-</strong></span>
                        </div>
                        <div class="percentiles-grid">
                            <div class="percentile-item">
                                <div class="percentile-label">p50</div>
                                <div class="percentile-value" id="p50">-</div>
                                <div class="percentile-bar"><div class="progress-fill green" id="p50Bar" style="width: 0%"></div></div>
                            </div>
                            <div class="percentile-item">
                                <div class="percentile-label">p90</div>
                                <div class="percentile-value" id="p90">-</div>
                                <div class="percentile-bar"><div class="progress-fill yellow" id="p90Bar" style="width: 0%"></div></div>
                            </div>
                            <div class="percentile-item">
                                <div class="percentile-label">p99</div>
                                <div class="percentile-value" id="p99">-</div>
                                <div class="percentile-bar"><div class="progress-fill red" id="p99Bar" style="width: 0%"></div></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- RIGHT COLUMN -->
            <div class="dashboard-column">

                <!-- HTTP Codes -->
                <div class="card">
                    <div class="card-header">
                        <span class="card-title">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/></svg>
                            HTTP Codes
                        </span>
                    </div>
                    <div class="card-body">
                        <!-- HTTP Code Distribution Doughnut Chart -->
                        <div class="chart-container-small" style="height: 180px; margin-bottom: 16px;">
                            <canvas id="httpCodeChart"></canvas>
                        </div>
                        <div class="http-totals-row" style="display: flex; justify-content: space-around; margin-bottom: 12px; font-size: 12px;">
                            <span class="text-success"><strong id="http2xxTotal">0</strong> 2xx</span>
                            <span class="text-info"><strong id="http3xxTotal">0</strong> 3xx</span>
                            <span class="text-warning"><strong id="http4xxTotal">0</strong> 4xx</span>
                            <span class="text-error"><strong id="http5xxTotal">0</strong> 5xx</span>
                        </div>
                        <div class="http-codes-grid" id="httpCodesGrid">
                            <!-- 2xx Success -->
                            <div class="http-category success">
                                <div class="http-category-header">2xx Success</div>
                                <div id="http2xxContainer">
                                    <?php foreach ($http2xx as $code => $count): $pct = round(($count / $maxHttpCount) * 100, 1); ?>
                                    <div class="http-code-row">
                                        <span class="http-code-badge success"><?= $code ?></span>
                                        <div class="http-code-bar"><div class="progress-fill green" style="width: <?= $pct ?>%"></div></div>
                                        <span class="http-code-count"><?= number_format($count) ?></span>
                                    </div>
                                    <?php endforeach; if (empty($http2xx)): ?><span class="text-muted">-</span><?php endif; ?>
                                </div>
                            </div>
                            <!-- 3xx Redirect -->
                            <div class="http-category redirect">
                                <div class="http-category-header">3xx Redirect</div>
                                <div id="http3xxContainer">
                                    <?php foreach ($http3xx as $code => $count): $pct = round(($count / $maxHttpCount) * 100, 1); ?>
                                    <div class="http-code-row">
                                        <span class="http-code-badge redirect"><?= $code ?></span>
                                        <div class="http-code-bar"><div class="progress-fill blue" style="width: <?= $pct ?>%"></div></div>
                                        <span class="http-code-count"><?= number_format($count) ?></span>
                                    </div>
                                    <?php endforeach; if (empty($http3xx)): ?><span class="text-muted">-</span><?php endif; ?>
                                </div>
                            </div>
                            <!-- 4xx Client Error -->
                            <div class="http-category client-error">
                                <div class="http-category-header">4xx Client</div>
                                <div id="http4xxContainer">
                                    <?php foreach ($http4xx as $code => $count): $pct = round(($count / $maxHttpCount) * 100, 1); ?>
                                    <div class="http-code-row">
                                        <span class="http-code-badge client-error"><?= $code ?></span>
                                        <div class="http-code-bar"><div class="progress-fill yellow" style="width: <?= $pct ?>%"></div></div>
                                        <span class="http-code-count"><?= number_format($count) ?></span>
                                    </div>
                                    <?php endforeach; if (empty($http4xx)): ?><span class="text-muted">-</span><?php endif; ?>
                                </div>
                            </div>
                            <!-- 5xx Server Error -->
                            <div class="http-category server-error">
                                <div class="http-category-header">5xx Server</div>
                                <div id="http5xxContainer">
                                    <?php foreach ($http5xx as $code => $count): $pct = round(($count / $maxHttpCount) * 100, 1); ?>
                                    <div class="http-code-row">
                                        <span class="http-code-badge server-error"><?= $code ?></span>
                                        <div class="http-code-bar"><div class="progress-fill red" style="width: <?= $pct ?>%"></div></div>
                                        <span class="http-code-count"><?= number_format($count) ?></span>
                                    </div>
                                    <?php endforeach; if (empty($http5xx)): ?><span class="text-muted">-</span><?php endif; ?>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- Top Domains -->
                <div class="card">
                    <div class="card-header">
                        <span class="card-title">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
                            Top Domains (<span id="domainCount"><?= $totalDomains ?></span>)
                        </span>
                    </div>
                    <div class="card-body">
                        <!-- Domain Performance Bar Chart -->
                        <div class="chart-container-small" style="height: 200px; margin-bottom: 16px;">
                            <canvas id="domainChart"></canvas>
                        </div>
                        <div style="display: flex; gap: 12px; margin-bottom: 12px; font-size: 12px;">
                            <span id="healthyDomainsCount" class="text-success">&#9679; <?= $healthyDomains ?> healthy</span>
                            <span id="warningDomainsCount" class="text-warning">&#9679; <?= $warningDomains ?> warning</span>
                            <span id="problematicDomainsCount" class="text-error">&#9679; <?= $problematicDomains ?> problem</span>
                        </div>
                        <div class="domain-list" id="domainList">
                            <?php
                            $sortedDomains = $domainStats;
                            uasort($sortedDomains, fn($a, $b) => ($b['total'] ?? 0) <=> ($a['total'] ?? 0));
                            foreach (array_slice($sortedDomains, 0, 15, true) as $domain => $stats):
                                $total = $stats['total'] ?? 0;
                                $success = $stats['success'] ?? 0;
                                $error = $stats['error'] ?? 0;
                                $pct = $total > 0 ? round(($success / $total) * 100) : 0;
                                $errorRate = $total > 0 ? ($error / $total) : 0;
                                $healthClass = $errorRate > 0.5 ? 'problematic' : ($errorRate > 0.2 ? 'warning' : 'healthy');
                            ?>
                            <div class="domain-item <?= $healthClass ?>">
                                <div class="domain-icon"><?= strtoupper(substr($domain, 0, 2)) ?></div>
                                <div class="domain-info">
                                    <div class="domain-name"><?= htmlspecialchars($domain) ?></div>
                                    <div class="domain-progress">
                                        <div class="domain-bar"><div class="domain-bar-fill" style="width: <?= $pct ?>%"></div></div>
                                        <span class="domain-stats"><?= $success ?>/<?= $total ?> (<?= $pct ?>%)</span>
                                    </div>
                                </div>
                                <?php if ($error > 0): ?><span class="domain-error-count"><?= $error ?></span><?php endif; ?>
                            </div>
                            <?php endforeach; ?>
                            <?php if (empty($domainStats)): ?>
                            <div class="empty-state"><p class="empty-state-text">Waiting for data...</p></div>
                            <?php endif; ?>
                        </div>
                    </div>
                </div>

                <!-- Circuit Breaker -->
                <div class="card">
                    <div class="card-header">
                        <span class="card-title">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg>
                            Circuit Breaker
                        </span>
                    </div>
                    <div class="card-body">
                        <div class="circuit-status" id="circuitStatus">
                            <div class="circuit-indicator closed" id="circuitIndicator">
                                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="24" height="24"><polyline points="20 6 9 17 4 12"/></svg>
                            </div>
                            <div class="circuit-info">
                                <div class="circuit-status-text" id="circuitStatusText">Closed (OK)</div>
                                <div class="circuit-detail">Blocked domains: <span id="blockedDomains">0</span></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- LIVE LOGS SECTION -->
        <section class="log-section">
            <div class="log-header">
                <span class="log-title">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
                    Live Logs
                </span>
                <div class="log-filters">
                    <button class="filter-btn active" data-filter="all">All</button>
                    <button class="filter-btn" data-filter="success">&#10003; Success</button>
                    <button class="filter-btn" data-filter="error">&#10007; Error</button>
                    <button class="filter-btn" data-filter="ignored">&#9675; Ignored</button>
                </div>
                <input type="text" class="log-search" id="logSearch" placeholder="Filter URL or domain...">
                <span class="log-count" id="logCount"><?= count($logs) ?> entries</span>
            </div>
            <div class="log-container" id="logContainer">
                <?php foreach (array_slice($logs, -100) as $log):
                    $logClass = $log['class'] ?? 'info';
                    $httpCode = $log['http_code'] ?? '-';
                    $codeClass = ($httpCode >= 200 && $httpCode < 300) ? 'success' : (($httpCode >= 300 && $httpCode < 400) ? 'redirect' : (($httpCode >= 400 && $httpCode < 500) ? 'client-error' : 'server-error'));
                ?>
                <div class="log-entry <?= $logClass ?>" data-type="<?= $logClass ?>">
                    <div class="log-row-main">
                        <span class="log-timestamp"><?= isset($log['timestamp']) ? date('H:i:s', strtotime($log['timestamp'])) : '--:--:--' ?></span>
                        <span class="log-icon"><?= $logClass === 'success' ? '&#10003;' : ($logClass === 'error' ? '&#10007;' : '&#9675;') ?></span>
                        <span class="log-code <?= $codeClass ?>"><?= $httpCode ?></span>
                        <span class="log-duration"><?= isset($log['response_time']) ? round($log['response_time'] * 1000) . 'ms' : '-' ?></span>
                        <span class="log-domain"><?= htmlspecialchars($log['domain'] ?? '-') ?></span>
                    </div>
                    <div class="log-row-url"><?= htmlspecialchars($log['url'] ?? '') ?></div>
                    <?php if (!empty($log['message'])): ?><div class="log-row-message"><?= htmlspecialchars($log['message']) ?></div><?php endif; ?>
                </div>
                <?php endforeach; ?>
                <?php if (empty($logs)): ?>
                <div class="empty-state" id="logsEmptyState"><p class="empty-state-text">Waiting for logs...</p></div>
                <?php endif; ?>
            </div>
        </section>
    </main>

    <!-- Toast Container -->
    <div id="toastContainer" class="toast-container"></div>

    <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
    <script>
    (function() {
        'use strict';

        const API_BASE = '<?= $baseUrl ?>/api/v1';
        const CSRF_TOKEN = '<?= htmlspecialchars($csrfToken) ?>';
        const PROCESS_ID = '<?= htmlspecialchars($processId) ?>';
        const POLL_INTERVAL = 2000;
        const IS_INITIALIZING = <?= $isInitializing ? 'true' : 'false' ?>;

        let isComplete = <?= $isComplete ? 'true' : 'false' ?>;
        let isPaused = <?= $isPaused ? 'true' : 'false' ?>;
        let isInitialized = !IS_INITIALIZING;
        let pollTimer = null;
        let processingStartTime = Date.now();
        let isProcessing = false;

        // Speed tracking
        const speedHistory = [];
        const speedLabels = [];
        const MAX_SPEED_POINTS = 30;
        let speedChart = null;
        let lastProcessed = <?= $processedLinks ?>;
        let lastTime = Date.now();

        // Previous stats for animation
        let prevStats = {
            imported: <?= $importedLinks ?>,
            ignored: <?= $ignoredLinks ?>,
            errors: <?= $errorLinks ?>,
            remaining: <?= $remainingLinks ?>
        };

        // ==========================================
        // INITIALIZATION
        // ==========================================
        async function initializeProcess() {
            if (!IS_INITIALIZING) return true;
            console.log('[Init] Starting...');
            updateInitStep('stepExtract', 'loading');

            try {
                const response = await fetch(`${API_BASE}/process/${PROCESS_ID}/initialize`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': CSRF_TOKEN }
                });
                const result = await response.json();
                console.log('[Init] Result:', result);

                if (result.success) {
                    updateInitStep('stepExtract', 'done');
                    updateInitStep('stepInit', 'done');
                    updateInitStep('stepCreate', 'done');
                    await new Promise(r => setTimeout(r, 500));
                    hideInitializingOverlay();
                    isInitialized = true;
                    processingStartTime = Date.now();
                    updateStatusIndicator('running');
                    showToast('Process started with ' + result.total_links + ' URLs', 'success');
                    return true;
                } else {
                    showToast('Error: ' + (result.error || 'Init failed'), 'error');
                    return false;
                }
            } catch (error) {
                console.error('[Init] Error:', error);
                showToast('Connection error', 'error');
                return false;
            }
        }

        function updateInitStep(stepId, status) {
            const step = document.getElementById(stepId);
            if (!step) return;
            step.classList.remove('active');
            if (status === 'loading') {
                step.classList.add('active');
                step.querySelector('.step-icon').innerHTML = '<svg class="spinner-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18"><circle cx="12" cy="12" r="10" stroke-opacity="0.25"/><path d="M12 2a10 10 0 0 1 10 10" stroke-linecap="round"/></svg>';
            } else if (status === 'done') {
                step.classList.add('done');
                step.querySelector('.step-icon').innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" width="18" height="18"><polyline points="20 6 9 17 4 12"/></svg>';
            }
        }

        function hideInitializingOverlay() {
            const overlay = document.getElementById('initializingOverlay');
            const mainContent = document.getElementById('mainContent');
            if (overlay) { overlay.style.opacity = '0'; setTimeout(() => overlay.remove(), 300); }
            if (mainContent) { mainContent.style.opacity = '1'; mainContent.style.pointerEvents = 'auto'; }
        }

        function updateStatusIndicator(status) {
            const indicator = document.getElementById('statusIndicator');
            const text = document.getElementById('statusText');
            if (indicator) indicator.className = 'status-indicator ' + status;
            if (text) text.textContent = status.charAt(0).toUpperCase() + status.slice(1);
        }

        // ==========================================
        // SPEED CHART
        // ==========================================
        function initSpeedChart() {
            const ctx = document.getElementById('speedChart');
            if (!ctx || !window.Chart) return;
            speedChart = new Chart(ctx, {
                type: 'line',
                data: {
                    labels: speedLabels,
                    datasets: [{
                        label: 'URLs/s',
                        data: speedHistory,
                        borderColor: 'rgba(59, 130, 246, 1)',
                        backgroundColor: 'rgba(59, 130, 246, 0.1)',
                        fill: true,
                        tension: 0.4,
                        pointRadius: 0,
                        borderWidth: 2
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    animation: { duration: 0 },
                    plugins: { legend: { display: false } },
                    scales: {
                        x: { display: false },
                        y: { beginAtZero: true, ticks: { color: 'rgba(255,255,255,0.5)', font: { size: 10 } }, grid: { color: 'rgba(255,255,255,0.05)' } }
                    }
                }
            });
        }

        function updateSpeedChart(currentProcessed) {
            const now = Date.now();
            const timeDiff = (now - lastTime) / 1000;
            const processedDiff = currentProcessed - lastProcessed;

            if (timeDiff > 0.5) {
                const speed = Math.round((processedDiff / timeDiff) * 10) / 10;
                speedHistory.push(speed);
                speedLabels.push('');
                if (speedHistory.length > MAX_SPEED_POINTS) { speedHistory.shift(); speedLabels.shift(); }
                if (speedChart) speedChart.update('none');
                lastProcessed = currentProcessed;
                lastTime = now;
                return speed;
            }
            return speedHistory.length > 0 ? speedHistory[speedHistory.length - 1] : 0;
        }

        // ==========================================
        // HTTP CODE DOUGHNUT CHART
        // ==========================================
        let httpCodeChart = null;
        function initHttpCodeChart() {
            const ctx = document.getElementById('httpCodeChart');
            if (!ctx || !window.Chart) return;
            httpCodeChart = new Chart(ctx, {
                type: 'doughnut',
                data: {
                    labels: ['2xx', '3xx', '4xx', '5xx'],
                    datasets: [{
                        data: [0, 0, 0, 0],
                        backgroundColor: ['#10B981', '#3B82F6', '#F59E0B', '#EF4444'],
                        borderColor: '#1a1f2e',
                        borderWidth: 2
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    animation: { duration: 300 },
                    cutout: '65%',
                    plugins: {
                        legend: { display: false }
                    }
                }
            });
        }

        function updateHttpCodeChart(httpCodes) {
            if (!httpCodeChart) return;
            let total2xx = 0, total3xx = 0, total4xx = 0, total5xx = 0;
            Object.entries(httpCodes || {}).forEach(([code, count]) => {
                const c = parseInt(code);
                if (c >= 200 && c < 300) total2xx += count;
                else if (c >= 300 && c < 400) total3xx += count;
                else if (c >= 400 && c < 500) total4xx += count;
                else if (c >= 500) total5xx += count;
            });
            httpCodeChart.data.datasets[0].data = [total2xx, total3xx, total4xx, total5xx];
            httpCodeChart.update('none');
            setText('http2xxTotal', total2xx);
            setText('http3xxTotal', total3xx);
            setText('http4xxTotal', total4xx);
            setText('http5xxTotal', total5xx);
        }

        // ==========================================
        // DOMAIN PERFORMANCE BAR CHART
        // ==========================================
        let domainChart = null;
        function initDomainChart() {
            const ctx = document.getElementById('domainChart');
            if (!ctx || !window.Chart) return;
            domainChart = new Chart(ctx, {
                type: 'bar',
                data: {
                    labels: [],
                    datasets: [{
                        label: 'Success Rate',
                        data: [],
                        backgroundColor: [],
                        borderRadius: 4,
                        barThickness: 16
                    }]
                },
                options: {
                    indexAxis: 'y',
                    responsive: true,
                    maintainAspectRatio: false,
                    animation: { duration: 300 },
                    plugins: { legend: { display: false } },
                    scales: {
                        x: { beginAtZero: true, max: 100, ticks: { color: 'rgba(255,255,255,0.5)', font: { size: 10 } }, grid: { color: 'rgba(255,255,255,0.05)' } },
                        y: { ticks: { color: 'rgba(255,255,255,0.7)', font: { size: 10 } }, grid: { display: false } }
                    }
                }
            });
        }

        function updateDomainChart(domainStats) {
            if (!domainChart) return;
            const sorted = Object.entries(domainStats || {})
                .map(([domain, stats]) => ({
                    domain: domain.substring(0, 15),
                    rate: stats.total > 0 ? Math.round((stats.success / stats.total) * 100) : 0,
                    total: stats.total || 0
                }))
                .sort((a, b) => b.total - a.total)
                .slice(0, 8);

            domainChart.data.labels = sorted.map(d => d.domain);
            domainChart.data.datasets[0].data = sorted.map(d => d.rate);
            domainChart.data.datasets[0].backgroundColor = sorted.map(d =>
                d.rate >= 80 ? '#10B981' : d.rate >= 50 ? '#F59E0B' : '#EF4444'
            );
            domainChart.update('none');
        }

        // ==========================================
        // ERROR TREND LINE CHART
        // ==========================================
        let errorTrendChart = null;
        const errorTrendHistory = { '403': [], '404': [], '429': [], '5xx': [], 'other': [] };
        const errorTrendLabels = [];
        const MAX_ERROR_POINTS = 30;
        let lastErrorDetails = { http_403: 0, http_404: 0, http_429: 0, http_5xx: 0, other: 0 };

        function initErrorTrendChart() {
            const ctx = document.getElementById('errorTrendChart');
            if (!ctx || !window.Chart) return;
            errorTrendChart = new Chart(ctx, {
                type: 'line',
                data: {
                    labels: errorTrendLabels,
                    datasets: [
                        { label: '403', data: errorTrendHistory['403'], borderColor: '#F59E0B', backgroundColor: 'transparent', tension: 0.4, pointRadius: 0, borderWidth: 2 },
                        { label: '404', data: errorTrendHistory['404'], borderColor: '#EF4444', backgroundColor: 'transparent', tension: 0.4, pointRadius: 0, borderWidth: 2 },
                        { label: '429', data: errorTrendHistory['429'], borderColor: '#8B5CF6', backgroundColor: 'transparent', tension: 0.4, pointRadius: 0, borderWidth: 2 },
                        { label: '5xx', data: errorTrendHistory['5xx'], borderColor: '#EC4899', backgroundColor: 'transparent', tension: 0.4, pointRadius: 0, borderWidth: 2 },
                        { label: 'other', data: errorTrendHistory['other'], borderColor: '#6B7280', backgroundColor: 'transparent', tension: 0.4, pointRadius: 0, borderWidth: 2 }
                    ]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    animation: { duration: 0 },
                    plugins: { legend: { display: false } },
                    scales: {
                        x: { display: false },
                        y: { beginAtZero: true, ticks: { color: 'rgba(255,255,255,0.5)', font: { size: 9 }, stepSize: 1 }, grid: { color: 'rgba(255,255,255,0.05)' } }
                    }
                }
            });
        }

        function updateErrorTrendChart(errorDetails) {
            if (!errorTrendChart) return;
            const e = errorDetails || {};
            const new403 = (e.http_403 || 0) - lastErrorDetails.http_403;
            const new404 = (e.http_404 || 0) - lastErrorDetails.http_404;
            const new429 = (e.http_429 || 0) - lastErrorDetails.http_429;
            const new5xx = (e.http_5xx || 0) - lastErrorDetails.http_5xx;
            const newOther = ((e.timeout || 0) + (e.connection || 0) + (e.metadata || 0) + (e.other || 0)) - lastErrorDetails.other;

            errorTrendHistory['403'].push(Math.max(0, new403));
            errorTrendHistory['404'].push(Math.max(0, new404));
            errorTrendHistory['429'].push(Math.max(0, new429));
            errorTrendHistory['5xx'].push(Math.max(0, new5xx));
            errorTrendHistory['other'].push(Math.max(0, newOther));
            errorTrendLabels.push('');

            if (errorTrendLabels.length > MAX_ERROR_POINTS) {
                Object.values(errorTrendHistory).forEach(arr => arr.shift());
                errorTrendLabels.shift();
            }

            lastErrorDetails = {
                http_403: e.http_403 || 0,
                http_404: e.http_404 || 0,
                http_429: e.http_429 || 0,
                http_5xx: e.http_5xx || 0,
                other: (e.timeout || 0) + (e.connection || 0) + (e.metadata || 0) + (e.other || 0)
            };

            errorTrendChart.update('none');
            setText('errorTrend403', e.http_403 || 0);
            setText('errorTrend404', e.http_404 || 0);
            setText('errorTrend429', e.http_429 || 0);
            setText('errorTrend5xx', e.http_5xx || 0);
            setText('errorTrendOther', (e.timeout || 0) + (e.connection || 0) + (e.metadata || 0) + (e.other || 0));
        }

        // ==========================================
        // LATENCY HISTOGRAM CHART
        // ==========================================
        let latencyHistogram = null;
        function initLatencyHistogram() {
            const ctx = document.getElementById('latencyHistogram');
            if (!ctx || !window.Chart) return;
            latencyHistogram = new Chart(ctx, {
                type: 'bar',
                data: {
                    labels: ['0-100ms', '100-500ms', '500ms-1s', '1s-3s', '3s+'],
                    datasets: [{
                        data: [0, 0, 0, 0, 0],
                        backgroundColor: ['#10B981', '#34D399', '#F59E0B', '#FB923C', '#EF4444'],
                        borderRadius: 4
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    animation: { duration: 300 },
                    plugins: { legend: { display: false } },
                    scales: {
                        x: { ticks: { color: 'rgba(255,255,255,0.5)', font: { size: 9 } }, grid: { display: false } },
                        y: { beginAtZero: true, ticks: { color: 'rgba(255,255,255,0.5)', font: { size: 9 } }, grid: { color: 'rgba(255,255,255,0.05)' } }
                    }
                }
            });
        }

        function updateLatencyHistogram(requestStats) {
            if (!latencyHistogram) return;
            const times = requestStats?.response_times || [];
            const buckets = [0, 0, 0, 0, 0]; // 0-100, 100-500, 500-1000, 1000-3000, 3000+
            times.forEach(t => {
                if (t < 100) buckets[0]++;
                else if (t < 500) buckets[1]++;
                else if (t < 1000) buckets[2]++;
                else if (t < 3000) buckets[3]++;
                else buckets[4]++;
            });
            latencyHistogram.data.datasets[0].data = buckets;
            latencyHistogram.update('none');

            // Update min/avg/max
            if (times.length > 0) {
                const min = Math.min(...times);
                const max = Math.max(...times);
                const avg = Math.round(times.reduce((a, b) => a + b, 0) / times.length);
                setText('latencyMin', min + 'ms');
                setText('latencyAvg', avg + 'ms');
                setText('latencyMax', max + 'ms');
            }
        }

        // ==========================================
        // UPDATE ALL PROGRESS BARS
        // ==========================================
        function updateProgress(data) {
            if (!data) return;

            const total = Math.max(data.total_links || 1, 1);
            const imported = data.imported_links || 0;
            const ignored = data.ignored_links || 0;
            const errors = data.error_links || 0;
            const processed = imported + ignored + errors;
            const remaining = total - processed;
            const percent = Math.round((processed / total) * 100 * 10) / 10;

            // Hero section
            setBar('heroProgressFill', percent);
            setText('heroProgressText', percent + '%');
            setText('heroProcessed', processed.toLocaleString());

            // Hero stats with animation
            animateValue('statImported', prevStats.imported, imported);
            animateValue('statIgnored', prevStats.ignored, ignored);
            animateValue('statErrors', prevStats.errors, errors);
            animateValue('statRemaining', prevStats.remaining, remaining);
            prevStats = { imported, ignored, errors, remaining };

            // Core progress bars
            setBar('coreProcessedBar', (processed / total) * 100);
            setText('coreProcessedVal', processed + ' (' + ((processed / total) * 100).toFixed(1) + '%)');
            setBar('coreImportedBar', (imported / total) * 100);
            setText('coreImportedVal', imported + ' (' + ((imported / total) * 100).toFixed(1) + '%)');
            setBar('coreIgnoredBar', (ignored / total) * 100);
            setText('coreIgnoredVal', ignored + ' (' + ((ignored / total) * 100).toFixed(1) + '%)');
            setBar('coreErrorsBar', (errors / total) * 100);
            setText('coreErrorsVal', errors + ' (' + ((errors / total) * 100).toFixed(1) + '%)');

            // Speed and performance
            const speed = updateSpeedChart(processed);
            setText('perfSpeed', speed.toFixed(1));
            setBar('perfSpeedBar', Math.min((speed / 100) * 100, 100));

            // Ignored breakdown
            const ignoredDetails = data.ignored_details || {};
            const ignoredTotal = (ignoredDetails.duplicate || 0) + (ignoredDetails.invalid_url || 0) + (ignoredDetails.blocked_domain || 0) + (ignoredDetails.non_html || 0);
            setText('ignoredTotalBadge', ignoredTotal);
            updateBreakdownBar('ignoredDuplicate', ignoredDetails.duplicate || 0, ignoredTotal);
            updateBreakdownBar('ignoredInvalid', ignoredDetails.invalid_url || 0, ignoredTotal);
            updateBreakdownBar('ignoredBlocked', ignoredDetails.blocked_domain || 0, ignoredTotal);
            updateBreakdownBar('ignoredNonhtml', ignoredDetails.non_html || 0, ignoredTotal);

            // Error breakdown
            const errorDetails = data.error_details || {};
            const errorTotal = (errorDetails.http_403 || 0) + (errorDetails.http_404 || 0) + (errorDetails.http_429 || 0) + (errorDetails.http_5xx || 0) + (errorDetails.timeout || 0) + (errorDetails.connection || 0) + (errorDetails.metadata || 0) + (errorDetails.other || 0);
            setText('errorTotalBadge', errorTotal);
            updateBreakdownBar('error403', errorDetails.http_403 || 0, errorTotal);
            updateBreakdownBar('error404', errorDetails.http_404 || 0, errorTotal);
            updateBreakdownBar('error429', errorDetails.http_429 || 0, errorTotal);
            updateBreakdownBar('error5xx', errorDetails.http_5xx || 0, errorTotal);
            updateBreakdownBar('errortimeout', errorDetails.timeout || 0, errorTotal);
            updateBreakdownBar('errorconnection', errorDetails.connection || 0, errorTotal);
            updateBreakdownBar('errormetadata', errorDetails.metadata || 0, errorTotal);
            updateBreakdownBar('errorother', errorDetails.other || 0, errorTotal);

            // Phase stats
            const phaseStats = data.phase_stats || {};
            const phaseQueues = data.phase_queues || [[], [], [], []];
            const currentPhase = data.phase_index || 0;
            for (let i = 0; i <= 3; i++) {
                const stats = phaseStats[i] || { success: 0, retry: 0, error: 0 };
                const queueCount = (phaseQueues[i] || []).length;
                const phaseTotal = stats.success + stats.retry + stats.error + queueCount;
                const phaseProgress = phaseTotal > 0 ? ((stats.success + stats.error) / phaseTotal) * 100 : 0;
                setBar('phaseProgress' + i, phaseProgress);
                setText('phaseStat' + i + 'Success', '&#10003; ' + stats.success);
                setText('phaseStat' + i + 'Retry', '&#8635; ' + stats.retry);
                setText('phaseStat' + i + 'Error', '&#10007; ' + stats.error);
                setText('phaseQueue' + i, 'Queue: ' + queueCount);

                const card = document.querySelector(`.phase-card[data-phase="${i}"]`);
                if (card) {
                    card.classList.toggle('active', i === currentPhase && !isComplete);
                    card.classList.toggle('completed', i < currentPhase || isComplete);
                }
            }

            // Retry stats
            const retryStats = data.retry_stats || { total_retries: 0, retries_by_phase: [0, 0, 0, 0] };
            setText('retryTotal', retryStats.total_retries || 0);
            const maxRetries = Math.max(1, ...Object.values(retryStats.retries_by_phase || {}));
            for (let i = 0; i <= 3; i++) {
                const retryCount = retryStats.retries_by_phase?.[i] || 0;
                setBar('retryPhase' + i + 'Bar', (retryCount / maxRetries) * 100);
                setText('retryPhase' + i + 'Val', retryCount);
            }

            // Request stats
            const requestStats = data.request_stats || {};
            setText('totalRequests', (requestStats.total_requests || 0).toLocaleString());
            setText('totalResponseTime', (requestStats.total_response_time || 0).toFixed(1) + 's');

            const avgLatency = requestStats.total_requests > 0 ? Math.round((requestStats.total_response_time / requestStats.total_requests) * 1000) : 0;
            setText('perfLatency', avgLatency);
            setBar('perfLatencyBar', Math.min((avgLatency / 500) * 100, 100));

            // Percentiles
            const times = requestStats.response_times || [];
            if (times.length > 0) {
                const sorted = [...times].sort((a, b) => a - b);
                const p50 = Math.round(sorted[Math.floor(sorted.length * 0.5)] * 1000);
                const p90 = Math.round(sorted[Math.floor(sorted.length * 0.9)] * 1000);
                const p99 = Math.round(sorted[Math.floor(sorted.length * 0.99)] * 1000);
                setText('p50', p50 + 'ms');
                setText('p90', p90 + 'ms');
                setText('p99', p99 + 'ms');
                setBar('p50Bar', Math.min((p50 / 500) * 100, 100));
                setBar('p90Bar', Math.min((p90 / 500) * 100, 100));
                setBar('p99Bar', Math.min((p99 / 500) * 100, 100));
            }

            // Performance
            const successRate = total > 0 ? ((imported / total) * 100).toFixed(1) : 0;
            setText('perfSuccessRate', successRate);
            setBar('perfSuccessBar', successRate);

            // Time stats
            setText('timeElapsed', formatTime(data.elapsed_time || 0));
            setText('timeRemaining', formatTime(data.remaining_time || 0));
            setText('heroEta', formatTime(data.remaining_time || 0));
            setText('processingRate', speed.toFixed(1) + '/s');

            // HTTP codes
            updateHttpCodes(data.http_codes || {});
            updateHttpCodeChart(data.http_codes || {});

            // Domains
            updateDomains(data.domain_stats || {});
            updateDomainChart(data.domain_stats || {});

            // Error trend chart
            updateErrorTrendChart(data.error_details || {});

            // Latency histogram
            updateLatencyHistogram(data.request_stats || {});

            // Circuit breaker
            updateCircuitBreaker(data.domain_stats || {});

            // Check completion - FIXED: Set isComplete FIRST to prevent race condition
            if (remaining === 0 && total > 0 && !isComplete) {
                isComplete = true;  // Set IMMEDIATELY to prevent duplicate banners
                const elapsedMs = Date.now() - processingStartTime;
                if (elapsedMs < 5000) {
                    isComplete = false;  // Reset if too early
                    return;
                }
                stopPolling();
                showCompletionBanner(total, imported, ignored, errors);
            }
        }

        function setBar(id, percent) {
            const el = document.getElementById(id);
            if (el) el.style.width = Math.min(Math.max(percent, 0), 100) + '%';
        }

        function setText(id, value) {
            const el = document.getElementById(id);
            if (el) el.innerHTML = value;
        }

        function updateBreakdownBar(id, value, total) {
            const pct = total > 0 ? (value / total) * 100 : 0;
            setBar(id + 'Bar', pct);
            setText(id + 'Val', value);
        }

        function formatTime(seconds) {
            const h = Math.floor(seconds / 3600);
            const m = Math.floor((seconds % 3600) / 60);
            const s = Math.floor(seconds % 60);
            return `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;
        }

        function animateValue(elementId, start, end, duration = 250) {
            const element = document.getElementById(elementId);
            if (!element || start === end) return;
            const range = end - start;
            const startTime = performance.now();
            function update(currentTime) {
                const elapsed = currentTime - startTime;
                const progress = Math.min(elapsed / duration, 1);
                const eased = 1 - Math.pow(1 - progress, 3);
                const current = Math.round(start + range * eased);
                element.textContent = current.toLocaleString();
                if (progress < 1) requestAnimationFrame(update);
            }
            requestAnimationFrame(update);
        }

        function updateHttpCodes(httpCodes) {
            const maxCount = Math.max(1, ...Object.values(httpCodes));
            const categories = { '2xx': [], '3xx': [], '4xx': [], '5xx': [] };
            for (const [code, count] of Object.entries(httpCodes)) {
                const num = parseInt(code);
                if (num >= 200 && num < 300) categories['2xx'].push({ code, count });
                else if (num >= 300 && num < 400) categories['3xx'].push({ code, count });
                else if (num >= 400 && num < 500) categories['4xx'].push({ code, count });
                else if (num >= 500) categories['5xx'].push({ code, count });
            }
            for (const [cat, codes] of Object.entries(categories)) {
                const container = document.getElementById('http' + cat + 'Container');
                if (container) {
                    const colorClass = cat === '2xx' ? 'green' : (cat === '3xx' ? 'blue' : (cat === '4xx' ? 'yellow' : 'red'));
                    const badgeClass = cat === '2xx' ? 'success' : (cat === '3xx' ? 'redirect' : (cat === '4xx' ? 'client-error' : 'server-error'));
                    container.innerHTML = codes.length > 0 ? codes.map(c => `
                        <div class="http-code-row">
                            <span class="http-code-badge ${badgeClass}">${c.code}</span>
                            <div class="http-code-bar"><div class="progress-fill ${colorClass}" style="width: ${(c.count / maxCount) * 100}%"></div></div>
                            <span class="http-code-count">${c.count.toLocaleString()}</span>
                        </div>
                    `).join('') : '<span class="text-muted">-</span>';
                }
            }
        }

        function updateDomains(domainStats) {
            const sorted = Object.entries(domainStats).sort((a, b) => (b[1].total || 0) - (a[1].total || 0));
            let healthy = 0, warning = 0, problematic = 0;

            const container = document.getElementById('domainList');
            if (container) {
                container.innerHTML = sorted.slice(0, 15).map(([domain, stats]) => {
                    const total = stats.total || 0;
                    const success = stats.success || 0;
                    const error = stats.error || 0;
                    const pct = total > 0 ? Math.round((success / total) * 100) : 0;
                    const errorRate = total > 0 ? (error / total) : 0;
                    let healthClass = 'healthy';
                    if (errorRate > 0.5) { healthClass = 'problematic'; problematic++; }
                    else if (errorRate > 0.2) { healthClass = 'warning'; warning++; }
                    else { healthy++; }
                    return `
                        <div class="domain-item ${healthClass}">
                            <div class="domain-icon">${domain.substring(0, 2).toUpperCase()}</div>
                            <div class="domain-info">
                                <div class="domain-name">${escapeHtml(domain)}</div>
                                <div class="domain-progress">
                                    <div class="domain-bar"><div class="domain-bar-fill" style="width: ${pct}%"></div></div>
                                    <span class="domain-stats">${success}/${total} (${pct}%)</span>
                                </div>
                            </div>
                            ${error > 0 ? `<span class="domain-error-count">${error}</span>` : ''}
                        </div>
                    `;
                }).join('') || '<div class="empty-state"><p class="empty-state-text">Waiting for data...</p></div>';
            }

            setText('domainCount', sorted.length);
            setText('healthyDomainsCount', '&#9679; ' + healthy + ' healthy');
            setText('warningDomainsCount', '&#9679; ' + warning + ' warning');
            setText('problematicDomainsCount', '&#9679; ' + problematic + ' problem');
        }

        function updateCircuitBreaker(domainStats) {
            let blockedCount = 0;
            for (const stats of Object.values(domainStats)) {
                const total = stats.total || 0;
                const error = stats.error || 0;
                if (total >= 3 && (error / total) >= 0.5) blockedCount++;
            }
            const indicator = document.getElementById('circuitIndicator');
            const statusText = document.getElementById('circuitStatusText');
            setText('blockedDomains', blockedCount);
            if (blockedCount === 0) {
                if (indicator) indicator.className = 'circuit-indicator closed';
                if (statusText) statusText.textContent = 'Closed (OK)';
            } else {
                if (indicator) indicator.className = 'circuit-indicator open';
                if (statusText) statusText.textContent = 'Open (' + blockedCount + ' problematic)';
            }
        }

        function escapeHtml(text) {
            if (!text) return '';
            const div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }

        // ==========================================
        // LIVE LOGS
        // ==========================================
        let totalLogCount = <?= count($logs) ?>;

        function appendLiveLogs(logs) {
            const container = document.getElementById('logContainer');
            if (!container || !logs || logs.length === 0) return;

            const emptyState = document.getElementById('logsEmptyState');
            if (emptyState) emptyState.remove();

            logs.forEach(log => {
                const entry = document.createElement('div');
                const logClass = log.class || 'info';
                const httpCode = log.http_code || '-';
                const codeClass = (httpCode >= 200 && httpCode < 300) ? 'success' : ((httpCode >= 300 && httpCode < 400) ? 'redirect' : ((httpCode >= 400 && httpCode < 500) ? 'client-error' : 'server-error'));
                const timestamp = log.timestamp ? new Date(log.timestamp).toLocaleTimeString('en-US', { hour12: false }) : '--:--:--';
                const responseTime = log.response_time ? Math.round(log.response_time * 1000) + 'ms' : '-';
                const domain = log.domain || (log.url ? new URL(log.url).hostname : '-');
                const icon = logClass === 'success' ? '&#10003;' : (logClass === 'error' ? '&#10007;' : '&#9675;');

                entry.className = 'log-entry ' + logClass;
                entry.dataset.type = logClass;
                entry.innerHTML = `
                    <div class="log-row-main">
                        <span class="log-timestamp">${timestamp}</span>
                        <span class="log-icon">${icon}</span>
                        <span class="log-code ${codeClass}">${httpCode}</span>
                        <span class="log-duration">${responseTime}</span>
                        <span class="log-domain">${escapeHtml(domain)}</span>
                    </div>
                    <div class="log-row-url">${escapeHtml(log.url || '')}</div>
                    ${log.message ? `<div class="log-row-message">${escapeHtml(log.message)}</div>` : ''}
                `;
                entry.style.opacity = '0';
                entry.style.transform = 'translateY(-10px)';
                container.insertBefore(entry, container.firstChild);
                requestAnimationFrame(() => {
                    entry.style.transition = 'opacity 0.3s, transform 0.3s';
                    entry.style.opacity = '1';
                    entry.style.transform = 'translateY(0)';
                });
                totalLogCount++;
            });

            setText('logCount', totalLogCount + ' entries');

            // Limit entries
            const entries = container.querySelectorAll('.log-entry');
            if (entries.length > 200) {
                for (let i = 200; i < entries.length; i++) entries[i].remove();
            }

            filterLogs();
        }

        // Log filtering
        let currentFilter = 'all';
        const logSearch = document.getElementById('logSearch');
        const filterBtns = document.querySelectorAll('.filter-btn');

        filterBtns.forEach(btn => {
            btn.addEventListener('click', () => {
                filterBtns.forEach(b => b.classList.remove('active'));
                btn.classList.add('active');
                currentFilter = btn.dataset.filter;
                filterLogs();
            });
        });

        if (logSearch) {
            logSearch.addEventListener('input', debounce(filterLogs, 300));
        }

        function filterLogs() {
            const searchTerm = logSearch ? logSearch.value.toLowerCase() : '';
            const entries = document.querySelectorAll('.log-entry');
            entries.forEach(entry => {
                const type = entry.dataset.type;
                const text = entry.textContent.toLowerCase();
                const matchesFilter = currentFilter === 'all' || type === currentFilter;
                const matchesSearch = !searchTerm || text.includes(searchTerm);
                entry.style.display = matchesFilter && matchesSearch ? 'flex' : 'none';
            });
        }

        function debounce(fn, delay) {
            let timeout;
            return function(...args) {
                clearTimeout(timeout);
                timeout = setTimeout(() => fn.apply(this, args), delay);
            };
        }

        // ==========================================
        // API & POLLING
        // ==========================================
        async function apiCall(endpoint, method = 'GET', data = null) {
            const options = { method, headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': CSRF_TOKEN } };
            if (data && method !== 'GET') options.body = JSON.stringify(data);
            try {
                const response = await fetch(`${API_BASE}/${endpoint}`, options);
                return await response.json();
            } catch (error) {
                return { success: false, error: { message: error.message } };
            }
        }

        async function pollProgress() {
            if (isComplete || !isInitialized) return;
            const result = await apiCall(`process/${PROCESS_ID}/live`);
            if (result.success) updateProgress(result.data);
        }

        function startPolling() {
            if (pollTimer) clearInterval(pollTimer);
            pollTimer = setInterval(pollProgress, POLL_INTERVAL);
            pollProgress();
        }

        function stopPolling() {
            if (pollTimer) { clearInterval(pollTimer); pollTimer = null; }
        }

        document.addEventListener('visibilitychange', () => {
            if (document.hidden) stopPolling();
            else if (!isComplete && isInitialized) startPolling();
        });

        // ==========================================
        // PROCESSING LOOP
        // ==========================================
        async function runProcessingLoop() {
            if (isProcessing || isComplete || isPaused || !isInitialized) return;
            isProcessing = true;

            while (!isComplete && !isPaused && isInitialized) {
                try {
                    const response = await fetch(`${API_BASE}/process/${PROCESS_ID}/run`, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': CSRF_TOKEN }
                    });

                    if (!response.ok) { await new Promise(r => setTimeout(r, 2000)); continue; }

                    const result = await response.json();
                    if (!result.success) {
                        if (result.error === 'Process not found') { showToast('Process not found', 'error'); break; }
                        await new Promise(r => setTimeout(r, 2000));
                        continue;
                    }

                    if (result.data) updateProgress(result.data);
                    if (result.logs && result.logs.length > 0) appendLiveLogs(result.logs);

                    if (result.complete || result.status === 'completed') {
                        if (isComplete) break;  // FIXED: Skip if already handled by updateProgress()
                        const elapsedMs = Date.now() - processingStartTime;
                        if (elapsedMs < 5000) { await new Promise(r => setTimeout(r, 500)); continue; }
                        isComplete = true;
                        stopPolling();
                        showCompletionBanner(result.data?.total_links || 0, result.data?.imported_links || 0, result.data?.ignored_links || 0, result.data?.error_links || 0);
                        break;
                    }

                    if (result.status === 'paused') { isPaused = true; break; }
                    if (result.status === 'cancelled') { isComplete = true; break; }

                    await new Promise(r => setTimeout(r, 100));
                } catch (error) {
                    await new Promise(r => setTimeout(r, 2000));
                }
            }

            isProcessing = false;
        }

        // ==========================================
        // COMPLETION BANNER
        // ==========================================
        function showCompletionBanner(total, imported, ignored, errors) {
            const successRate = total > 0 ? ((imported / total) * 100).toFixed(1) : 0;
            const timeElapsed = document.getElementById('timeElapsed')?.textContent || '00:00:00';
            updateStatusIndicator('completed');

            // Update hero
            setBar('heroProgressFill', 100);
            setText('heroProgressText', '100%');

            // Add banner if not exists
            if (!document.getElementById('completionBanner')) {
                const heroSection = document.getElementById('heroSection');
                if (heroSection) {
                    const banner = document.createElement('div');
                    banner.id = 'completionBanner';
                    banner.className = 'completion-banner';
                    banner.innerHTML = `
                        <div class="completion-icon">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="32" height="32"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
                        </div>
                        <div class="completion-info">
                            <h2 class="completion-title">Processing Complete!</h2>
                            <p class="completion-subtitle">Processed ${total.toLocaleString()} URLs in ${timeElapsed} with ${successRate}% success rate</p>
                        </div>
                        <div class="completion-actions">
                            <a href="<?= $baseUrl ?>/?export=<?= urlencode($processId) ?>" class="btn btn-primary">
                                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
                                Export Results
                            </a>
                            <a href="<?= $baseUrl ?>/new" class="btn btn-secondary">
                                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="16"/><line x1="8" y1="12" x2="16" y2="12"/></svg>
                                New Process
                            </a>
                        </div>
                    `;
                    heroSection.insertAdjacentElement('beforebegin', banner);
                }
            }

            // Hide controls
            const controls = document.getElementById('controlButtons');
            if (controls) controls.style.display = 'none';

            showToast('Processing complete!', 'success');
        }

        // ==========================================
        // TOAST NOTIFICATIONS
        // ==========================================
        function showToast(message, type = 'info') {
            const container = document.getElementById('toastContainer');
            if (!container) return;
            const toast = document.createElement('div');
            toast.className = 'toast toast-' + type;
            toast.innerHTML = '<span>' + message + '</span>';
            container.appendChild(toast);
            setTimeout(() => toast.remove(), 4000);
        }

        // ==========================================
        // CONTROLS
        // ==========================================
        const btnPause = document.getElementById('btnPause');
        const btnResume = document.getElementById('btnResume');
        const btnCancel = document.getElementById('btnCancel');

        if (btnPause) {
            btnPause.addEventListener('click', async () => {
                btnPause.disabled = true;
                const result = await apiCall(`process/${PROCESS_ID}/pause`, 'POST');
                if (result.success) { showToast('Process paused', 'warning'); location.reload(); }
                else { showToast(result.error?.message || 'Failed', 'error'); btnPause.disabled = false; }
            });
        }

        if (btnResume) {
            btnResume.addEventListener('click', async () => {
                btnResume.disabled = true;
                const result = await apiCall(`process/${PROCESS_ID}/resume`, 'POST');
                if (result.success) {
                    // v5.0-beta FIX: Don't reload! Set flag directly and restart loop
                    showToast('Process resumed', 'success');
                    isPaused = false;

                    // Swap Resume button with Pause button
                    const controlButtons = document.getElementById('controlButtons');
                    if (controlButtons) {
                        const pauseBtn = document.createElement('button');
                        pauseBtn.className = 'btn-control btn-pause';
                        pauseBtn.id = 'btnPause';
                        pauseBtn.dataset.id = PROCESS_ID;
                        pauseBtn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg> Pause';
                        pauseBtn.addEventListener('click', async () => {
                            pauseBtn.disabled = true;
                            const r = await apiCall(`process/${PROCESS_ID}/pause`, 'POST');
                            if (r.success) { showToast('Process paused', 'warning'); location.reload(); }
                            else { showToast(r.error?.message || 'Failed', 'error'); pauseBtn.disabled = false; }
                        });
                        btnResume.replaceWith(pauseBtn);
                    }

                    // Restart the processing loop directly
                    runProcessingLoop();
                } else {
                    showToast(result.error?.message || 'Failed', 'error');
                    btnResume.disabled = false;
                }
            });
        }

        if (btnCancel) {
            btnCancel.addEventListener('click', async () => {
                if (!confirm('Cancel process?')) return;
                btnCancel.disabled = true;
                const result = await apiCall(`process/${PROCESS_ID}/cancel`, 'POST');
                if (result.success) {
                    showToast('Process cancelled', 'error');
                    stopPolling();
                    setTimeout(() => { window.location.href = '<?= $baseUrl ?>/'; }, 1500);
                } else {
                    showToast(result.error?.message || 'Failed', 'error');
                    btnCancel.disabled = false;
                }
            });
        }

        // ==========================================
        // MAIN
        // ==========================================
        async function main() {
            // Initialize all charts
            initSpeedChart();
            initHttpCodeChart();
            initDomainChart();
            initErrorTrendChart();
            initLatencyHistogram();

            if (IS_INITIALIZING) {
                const success = await initializeProcess();
                if (success) { startPolling(); runProcessingLoop(); }
            } else if (!isComplete) {
                startPolling();
                runProcessingLoop();
            }
        }

        main();
    })();
    </script>
</body>
</html>
