<?php
if (!defined('WPINC')) {
    die;
}

$project_id = isset($aysa_agent8_canonical_project_id) ? intval($aysa_agent8_canonical_project_id) : intval(get_option('aysa_project_id', 0));
$wp_project_id = intval(get_option('aysa_project_id', 0));
$site_host = wp_parse_url(home_url('/'), PHP_URL_HOST);
$site_host = is_string($site_host) ? strtolower($site_host) : '';
$nonce = wp_create_nonce('aysa_nonce');
$keyword_cache_nonce = wp_create_nonce('aysa_keyword_cache_nonce');
$google_oauth_nonce = wp_create_nonce('aysa_google_oauth_nonce');
$content_strategy_nonce = wp_create_nonce('aysa_content_strategy_nonce');
$publishing_calendar_embed_url = add_query_arg(array(
    'page' => 'aysa-research',
    'tab' => 'content-strategy',
    'strategy_tab' => 'publication-calendar',
    'embedded' => '1',
    'project_id' => $project_id,
    'wp_project_id' => $wp_project_id,
), admin_url('admin.php'));
$wallet_snapshot = isset($aysa_agent8_wallet_snapshot) && is_array($aysa_agent8_wallet_snapshot) ? $aysa_agent8_wallet_snapshot : array();
$available_credits = intval($wallet_snapshot['available_credits'] ?? 0);
$latest_usage_amount = intval($wallet_snapshot['latest_usage_amount_cents'] ?? 0);
?>

<div class="wrap aysa-agent8-page">
    <div class="aysa-agent8-shell">
        <header class="aysa-agent8-topbar">
            <div class="aysa-agent8-brand">
                <h1>Agent 8</h1>
                <p>Conversational SEO workspace for dialogue, approvals, and research.</p>
            </div>
            <div class="aysa-agent8-topmeta">
                <span class="aysa-agent8-meta-pill">Version <strong id="aysa-agent8-version">-</strong></span>
                <span class="aysa-agent8-meta-pill">Module <strong id="aysa-agent8-module">-</strong></span>
                <span class="aysa-agent8-meta-pill">Tab <strong id="aysa-agent8-tab">-</strong></span>
                <label class="aysa-agent8-meta-pill" for="aysa-agent8-language">
                    Language
                    <select id="aysa-agent8-language">
                        <option value="en">English</option>
                        <option value="ro">Romana</option>
                        <option value="bg">Bulgarian</option>
                        <option value="fr">French</option>
                        <option value="de">German</option>
                        <option value="it">Italian</option>
                        <option value="es">Spanish</option>
                        <option value="pt">Portuguese</option>
                        <option value="nl">Dutch</option>
                        <option value="pl">Polish</option>
                        <option value="cs">Czech</option>
                        <option value="sk">Slovak</option>
                        <option value="sl">Slovenian</option>
                        <option value="hr">Croatian</option>
                        <option value="hu">Hungarian</option>
                        <option value="el">Greek</option>
                        <option value="da">Danish</option>
                        <option value="sv">Swedish</option>
                        <option value="fi">Finnish</option>
                        <option value="et">Estonian</option>
                        <option value="lv">Latvian</option>
                        <option value="lt">Lithuanian</option>
                        <option value="mt">Maltese</option>
                        <option value="ga">Irish</option>
                        <option value="is">Icelandic</option>
                        <option value="no">Norwegian</option>
                        <option value="sq">Albanian</option>
                        <option value="sr">Serbian</option>
                        <option value="uk">Ukrainian</option>
                        <option value="tr">Turkish</option>
                        <option value="mk">Macedonian</option>
                        <option value="bs">Bosnian</option>
                    </select>
                </label>
                <span class="aysa-agent8-meta-pill" id="aysa-agent8-credits-pill" hidden>Credits <strong id="aysa-agent8-credits"><?php echo esc_html((string) $available_credits); ?></strong></span>
                <span class="aysa-agent8-meta-pill" id="aysa-agent8-last-usage-pill" hidden>Last usage <strong id="aysa-agent8-last-usage"><?php echo esc_html((string) $latest_usage_amount); ?></strong></span>
                <button type="button" class="button button-secondary" id="aysa-agent8-google-disconnect">Google Disconnect</button>
                <button type="button" class="button button-secondary" id="aysa-agent8-factory-reset-dry-run">Factory Reset Dry Run</button>
                <button type="button" class="button button-secondary" id="aysa-agent8-reset">Reset</button>
            </div>
        </header>

        <section class="aysa-agent8-chatframe">
            <div class="aysa-agent8-hidden-meta" aria-hidden="true">
                <span id="aysa-agent8-phase">conversation</span>
                <span id="aysa-agent8-step">conversation</span>
                <span id="aysa-agent8-owner">conversation</span>
                <span id="aysa-agent8-capability">Conversational</span>
            </div>
            <div class="aysa-agent8-system-note" id="aysa-agent8-factory-reset-dry-run-summary" hidden></div>

            <div class="aysa-agent8-transcript" id="aysa-agent8-transcript"></div>

            <div class="aysa-agent8-composer-wrap">
                <div class="aysa-agent8-persistent-actions" id="aysa-agent8-persistent-actions" hidden></div>
                <div class="aysa-agent8-pending" id="aysa-agent8-pending" hidden>Agent 8 is thinking...</div>
                <div class="aysa-agent8-composer">
                    <textarea id="aysa-agent8-input" rows="1" placeholder="Write to Agent 8 what you want to clarify or do next."></textarea>
                    <div class="aysa-agent8-composer-actions">
                        <button type="button" class="button button-primary" id="aysa-agent8-send">Send</button>
                    </div>
                </div>
            </div>
        </section>
    </div>
</div>

<div class="aysa-agent8-modal" id="aysa-agent8-competitors-modal" hidden>
    <div class="aysa-agent8-modal-backdrop" data-competitors-modal-close="1"></div>
    <div class="aysa-agent8-modal-dialog" role="dialog" aria-modal="true" aria-labelledby="aysa-agent8-competitors-modal-title">
        <div class="aysa-agent8-modal-header">
            <div>
                <p class="aysa-agent8-card-kicker">Competitors</p>
                <h2 class="aysa-agent8-modal-title" id="aysa-agent8-competitors-modal-title">Competitors</h2>
            </div>
            <button type="button" class="button button-secondary" id="aysa-agent8-competitors-modal-close">Close</button>
        </div>
        <div class="aysa-agent8-modal-intro" id="aysa-agent8-competitors-modal-intro"></div>
        <div class="aysa-agent8-modal-status" id="aysa-agent8-competitors-modal-status" hidden></div>
        <div class="aysa-agent8-modal-table-wrap">
            <table class="aysa-agent8-modal-table">
                <thead>
                    <tr>
                        <th id="aysa-agent8-competitors-col-name">Name</th>
                        <th id="aysa-agent8-competitors-col-url">URL</th>
                        <th id="aysa-agent8-competitors-col-status">Status</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody id="aysa-agent8-competitors-modal-body"></tbody>
            </table>
        </div>
        <div class="aysa-agent8-modal-footer">
            <button type="button" class="button button-primary" id="aysa-agent8-competitors-modal-done">Done</button>
        </div>
    </div>
</div>

<div class="aysa-agent8-modal" id="aysa-agent8-keyword-modal" hidden>
    <div class="aysa-agent8-modal-backdrop" data-modal-close="1"></div>
    <div class="aysa-agent8-modal-dialog" role="dialog" aria-modal="true" aria-labelledby="aysa-agent8-keyword-modal-title">
        <div class="aysa-agent8-modal-header">
            <div>
                <p class="aysa-agent8-card-kicker">Keyword Review</p>
                <h2 class="aysa-agent8-modal-title" id="aysa-agent8-keyword-modal-title">Keywordurile active</h2>
            </div>
            <button type="button" class="button button-secondary" id="aysa-agent8-keyword-modal-close">Închide</button>
        </div>
        <div class="aysa-agent8-modal-intro" id="aysa-agent8-keyword-modal-intro"></div>
        <div class="aysa-agent8-modal-status" id="aysa-agent8-keyword-modal-status" hidden></div>
        <div class="aysa-agent8-modal-table-wrap">
            <table class="aysa-agent8-modal-table">
                <thead>
                    <tr>
                        <th>Keyword</th>
                        <th>Volum</th>
                        <th>Pagină asociată</th>
                        <th>Status</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody id="aysa-agent8-keyword-modal-body"></tbody>
            </table>
        </div>
        <div class="aysa-agent8-modal-footer">
            <button type="button" class="button button-primary" id="aysa-agent8-keyword-modal-done">Continuă cu lista actuală</button>
        </div>
    </div>
</div>

<div class="aysa-agent8-modal" id="aysa-agent8-missing-pages-modal" hidden>
    <div class="aysa-agent8-modal-backdrop" data-missing-pages-modal-close="1"></div>
    <div class="aysa-agent8-modal-dialog" role="dialog" aria-modal="true" aria-labelledby="aysa-agent8-missing-pages-modal-title">
        <div class="aysa-agent8-modal-header">
            <div>
                <p class="aysa-agent8-card-kicker">Missing Pages</p>
                <h2 class="aysa-agent8-modal-title" id="aysa-agent8-missing-pages-modal-title">Oportunități de pagini</h2>
            </div>
            <button type="button" class="button button-secondary" id="aysa-agent8-missing-pages-modal-close">Închide</button>
        </div>
        <div class="aysa-agent8-modal-intro" id="aysa-agent8-missing-pages-modal-intro"></div>
        <div class="aysa-agent8-modal-status" id="aysa-agent8-missing-pages-modal-status" hidden></div>
        <div class="aysa-agent8-modal-scroll-body" id="aysa-agent8-missing-pages-modal-body"></div>
        <div class="aysa-agent8-modal-footer" id="aysa-agent8-missing-pages-static-footer" hidden>
            <button type="button" class="button button-primary" id="aysa-agent8-missing-pages-send-to-plan" data-action-key="send_missing_pages_to_plan">Trimite în plan</button>
            <button type="button" class="button button-primary" id="aysa-agent8-missing-pages-modal-done">Continuă</button>
        </div>
    </div>
</div>

<div class="aysa-agent8-modal" id="aysa-agent8-content-strategy-modal" hidden>
    <div class="aysa-agent8-modal-backdrop" data-content-strategy-modal-close="1"></div>
    <div class="aysa-agent8-modal-dialog" role="dialog" aria-modal="true" aria-labelledby="aysa-agent8-content-strategy-modal-title">
        <div class="aysa-agent8-modal-header">
            <div>
                <p class="aysa-agent8-card-kicker">Content Strategy</p>
                <h2 class="aysa-agent8-modal-title" id="aysa-agent8-content-strategy-modal-title">Plan editorial</h2>
            </div>
            <button type="button" class="button button-secondary" id="aysa-agent8-content-strategy-modal-close">Închide</button>
        </div>
        <div class="aysa-agent8-modal-intro" id="aysa-agent8-content-strategy-modal-intro"></div>
        <div class="aysa-agent8-modal-status" id="aysa-agent8-content-strategy-modal-status" hidden></div>
        <div class="aysa-agent8-modal-scroll-body" id="aysa-agent8-content-strategy-modal-body"></div>
        <div class="aysa-agent8-modal-footer">
            <button type="button" class="button button-primary" id="aysa-agent8-content-strategy-save" data-action-key="update_content_strategy_items">Salvează schimbările</button>
            <button type="button" class="button button-primary" id="aysa-agent8-content-strategy-modal-done">Continuă</button>
        </div>
    </div>
</div>

<div class="aysa-agent8-modal" id="aysa-agent8-publishing-calendar-modal" hidden>
    <div class="aysa-agent8-modal-backdrop" data-publishing-calendar-modal-close="1"></div>
    <div class="aysa-agent8-modal-dialog aysa-agent8-modal-dialog-iframe" role="dialog" aria-modal="true" aria-labelledby="aysa-agent8-publishing-calendar-modal-title">
        <div class="aysa-agent8-modal-header">
            <div>
                <p class="aysa-agent8-card-kicker">Publishing Calendar</p>
                <h2 class="aysa-agent8-modal-title" id="aysa-agent8-publishing-calendar-modal-title">Calendar editorial</h2>
            </div>
            <button type="button" class="button button-secondary" id="aysa-agent8-publishing-calendar-modal-close">Închide</button>
        </div>
        <div class="aysa-agent8-modal-intro" id="aysa-agent8-publishing-calendar-modal-intro">Calendarul editorial real din Content Strategy este încărcat aici.</div>
        <div class="aysa-agent8-modal-scroll-body" id="aysa-agent8-publishing-calendar-native" hidden></div>
        <div class="aysa-agent8-modal-iframe-wrap">
            <iframe id="aysa-agent8-publishing-calendar-frame" title="Publishing Calendar" loading="eager" referrerpolicy="same-origin"></iframe>
        </div>
        <div class="aysa-agent8-modal-footer">
            <button type="button" class="button button-primary" id="aysa-agent8-publishing-calendar-modal-done">Continuă</button>
        </div>
    </div>
</div>

<div class="aysa-agent8-modal" id="aysa-agent8-technical-modal" hidden>
    <div class="aysa-agent8-modal-backdrop" data-technical-modal-close="1"></div>
    <div class="aysa-agent8-modal-dialog" role="dialog" aria-modal="true" aria-labelledby="aysa-agent8-technical-modal-title">
        <div class="aysa-agent8-modal-header">
            <div>
                <p class="aysa-agent8-card-kicker">Technical</p>
                <h2 class="aysa-agent8-modal-title" id="aysa-agent8-technical-modal-title">Technical Optimization</h2>
            </div>
            <button type="button" class="button button-secondary" id="aysa-agent8-technical-modal-close">Închide</button>
        </div>
        <div class="aysa-agent8-modal-intro" id="aysa-agent8-technical-modal-intro"></div>
        <div class="aysa-agent8-modal-status" id="aysa-agent8-technical-modal-status" hidden></div>
        <div class="aysa-agent8-modal-scroll-body" id="aysa-agent8-technical-modal-body"></div>
        <div class="aysa-agent8-modal-footer">
            <button type="button" class="button button-primary" id="aysa-agent8-technical-modal-done">Continuă</button>
        </div>
    </div>
</div>

<div class="aysa-agent8-modal" id="aysa-agent8-help-modal" hidden>
    <div class="aysa-agent8-modal-backdrop" data-help-modal-close="1"></div>
    <div class="aysa-agent8-modal-dialog" role="dialog" aria-modal="true" aria-labelledby="aysa-agent8-help-modal-title">
        <div class="aysa-agent8-modal-header">
            <div>
                <p class="aysa-agent8-card-kicker">Help</p>
                <h2 class="aysa-agent8-modal-title" id="aysa-agent8-help-modal-title">Explicație</h2>
            </div>
            <button type="button" class="button button-secondary" id="aysa-agent8-help-modal-close">Închide</button>
        </div>
        <div class="aysa-agent8-modal-intro" id="aysa-agent8-help-modal-body"></div>
    </div>
</div>

<div class="aysa-agent8-modal" id="aysa-agent8-article-preview-modal" hidden>
    <div class="aysa-agent8-modal-backdrop" data-article-preview-modal-close="1"></div>
    <div class="aysa-agent8-modal-dialog" role="dialog" aria-modal="true" aria-labelledby="aysa-agent8-article-preview-modal-title">
        <div class="aysa-agent8-modal-header">
            <div>
                <p class="aysa-agent8-modal-kicker">ARTICLE REVIEW</p>
                <h2 class="aysa-agent8-modal-title" id="aysa-agent8-article-preview-modal-title">Article preview</h2>
            </div>
            <button type="button" class="button" id="aysa-agent8-article-preview-modal-close" data-article-preview-modal-close="1">Close</button>
        </div>
        <div class="aysa-agent8-modal-status" id="aysa-agent8-article-preview-modal-status" hidden></div>
        <div class="aysa-agent8-modal-scroll-body" id="aysa-agent8-article-preview-modal-body"></div>
        <div class="aysa-agent8-modal-footer">
            <button type="button" class="button" id="aysa-agent8-article-preview-email" data-action-key="send_offpage_draft_article_approval_email">Send approval email</button>
            <button type="button" class="button button-primary" id="aysa-agent8-article-preview-approve" data-action-key="approve_offpage_draft_article">Approve article</button>
        </div>
    </div>
</div>

<div class="aysa-agent8-modal" id="aysa-agent8-purchase-preview-modal" hidden>
    <div class="aysa-agent8-modal-backdrop" data-purchase-preview-modal-close="1"></div>
    <div class="aysa-agent8-modal-dialog" role="dialog" aria-modal="true" aria-labelledby="aysa-agent8-purchase-preview-modal-title">
        <div class="aysa-agent8-modal-header">
            <div>
                <p class="aysa-agent8-modal-kicker">OFF-PAGE ORDER REVIEW</p>
                <h2 class="aysa-agent8-modal-title" id="aysa-agent8-purchase-preview-modal-title">Order preview</h2>
            </div>
            <button type="button" class="button" id="aysa-agent8-purchase-preview-modal-close" data-purchase-preview-modal-close="1">Close</button>
        </div>
        <div class="aysa-agent8-modal-status" id="aysa-agent8-purchase-preview-modal-status" hidden></div>
        <div class="aysa-agent8-modal-scroll-body" id="aysa-agent8-purchase-preview-modal-body"></div>
        <div class="aysa-agent8-modal-footer">
            <button type="button" class="button" id="aysa-agent8-purchase-preview-email">Send approval email</button>
            <button type="button" class="button button-primary" id="aysa-agent8-purchase-preview-place">Place order</button>
        </div>
    </div>
</div>


<style>
body.toplevel_page_aysa-agent8 .notice,
body.toplevel_page_aysa-agent8 div.updated,
body.toplevel_page_aysa-agent8 div.error,
body.admin_page_aysa-agent8 .notice,
body.admin_page_aysa-agent8 div.updated,
body.admin_page_aysa-agent8 div.error,
body.aysa-ai-seo_page_aysa-agent8 .notice,
body.aysa-ai-seo_page_aysa-agent8 div.updated,
body.aysa-ai-seo_page_aysa-agent8 div.error { display:none!important; }

body.toplevel_page_aysa-agent8 #wpcontent,
body.admin_page_aysa-agent8 #wpcontent,
body.aysa-ai-seo_page_aysa-agent8 #wpcontent { padding-left:0; }

body.toplevel_page_aysa-agent8 #wpbody,
body.toplevel_page_aysa-agent8 #wpbody-content,
body.admin_page_aysa-agent8 #wpbody,
body.admin_page_aysa-agent8 #wpbody-content,
body.aysa-ai-seo_page_aysa-agent8 #wpbody,
body.aysa-ai-seo_page_aysa-agent8 #wpbody-content {
    height: calc(100vh - 32px);
    min-height: calc(100vh - 32px);
    overflow: hidden;
    box-sizing: border-box;
}

.aysa-agent8-page {
    margin: 0;
    padding: 18px 18px 0;
    height: calc(100vh - 32px);
    min-height: calc(100vh - 32px);
    width: 100%;
    overflow: hidden;
    box-sizing: border-box;
}

.aysa-agent8-shell {
    height: 100%;
    width: 100%;
    max-width: none;
    margin: 0;
    padding: 0 0 18px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    box-sizing: border-box;
}

.aysa-agent8-topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 18px;
}

.aysa-agent8-brand h1 {
    margin: 0;
    font-size: 30px;
    line-height: 1;
    color: #14233b;
}

.aysa-agent8-brand p {
    margin: 6px 0 0;
    color: #617087;
    font-size: 13px;
}

.aysa-agent8-topmeta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
}

.aysa-agent8-meta-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 34px;
    padding: 0 12px;
    border: 1px solid #d7e0ef;
    border-radius: 999px;
    background: rgba(255,255,255,.76);
    color: #42526b;
    font-size: 12px;
    backdrop-filter: blur(10px);
}

.aysa-agent8-chatframe {
    min-height: 0;
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    background:
        radial-gradient(circle at top left, rgba(230,238,255,.75), transparent 38%),
        linear-gradient(180deg, #f7faff 0%, #ffffff 28%);
    border: 1px solid #d9e2f0;
    border-radius: 22px;
    box-shadow: 0 18px 42px rgba(18, 36, 70, .08);
    overflow: hidden;
}

.aysa-agent8-context-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 18px 28px 14px;
    border-bottom: 1px solid rgba(217, 226, 240, .75);
    background: linear-gradient(180deg, rgba(255,255,255,.92) 0%, rgba(246,249,255,.86) 100%);
}

.aysa-agent8-context-copy {
    min-width: 0;
}

.aysa-agent8-context-kicker {
    margin: 0 0 4px;
    color: #5f708b;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
}

.aysa-agent8-context-title {
    margin: 0;
    color: #173055;
    font-size: 20px;
    line-height: 1.2;
}

.aysa-agent8-technical-rail {
    display: flex;
    gap: 10px;
    overflow-x: auto;
    padding: 14px 28px 16px;
    border-bottom: 1px solid rgba(217, 226, 240, .75);
    background: rgba(250, 252, 255, .88);
}

.aysa-agent8-technical-rail::-webkit-scrollbar {
    height: 8px;
}

.aysa-agent8-technical-rail::-webkit-scrollbar-thumb {
    background: rgba(114, 135, 166, .28);
    border-radius: 999px;
}

.aysa-agent8-technical-rail-item {
    min-width: 164px;
    padding: 12px 14px;
    border: 1px solid #d8e2f2;
    border-radius: 16px;
    background: rgba(255,255,255,.95);
    color: #1d3558;
    text-align: left;
    cursor: pointer;
    box-shadow: 0 8px 20px rgba(18, 36, 70, .05);
    transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease, background .15s ease;
}

.aysa-agent8-technical-rail-item:hover {
    transform: translateY(-1px);
    box-shadow: 0 12px 24px rgba(18, 36, 70, .08);
    border-color: #bfd0ea;
}

.aysa-agent8-technical-rail-item.is-active {
    border-color: #275dad;
    background: linear-gradient(180deg, #eef5ff 0%, #f8fbff 100%);
    box-shadow: 0 12px 26px rgba(39, 93, 173, .12);
}

.aysa-agent8-technical-rail-name {
    display: block;
    margin: 0 0 10px;
    font-size: 13px;
    font-weight: 700;
}

.aysa-agent8-technical-rail-status {
    display: inline-flex;
    align-items: center;
    min-height: 24px;
    padding: 0 9px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .02em;
    text-transform: uppercase;
}

.aysa-agent8-technical-rail-meta {
    margin-top: 10px;
    font-size: 12px;
    color: #5f708b;
    line-height: 1.35;
}

.aysa-agent8-technical-status-idle {
    background: #eef2f7;
    color: #5f708b;
}

.aysa-agent8-technical-status-queued,
.aysa-agent8-technical-status-running {
    background: #fff2d8;
    color: #8a5b00;
}

.aysa-agent8-technical-status-ready {
    background: #e7f6eb;
    color: #187542;
}

.aysa-agent8-technical-status-review_required {
    background: #fff0db;
    color: #9a5a00;
}

.aysa-agent8-technical-status-applied {
    background: #e5f1ff;
    color: #275dad;
}

.aysa-agent8-technical-status-failed {
    background: #fde9e8;
    color: #b42318;
}

.aysa-agent8-hidden-meta {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
}

.aysa-agent8-transcript {
    min-height: 0;
    flex: 1 1 auto;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 26px 28px 18px;
    scroll-behavior: smooth;
}

.aysa-agent8-timeline {
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.aysa-agent8-message {
    max-width: min(88%, 920px);
    padding: 14px 16px;
    border-radius: 18px;
    line-height: 1.58;
    white-space: pre-wrap;
    font-size: 15px;
    word-break: break-word;
}

.aysa-agent8-message.assistant {
    background: #f3f6fc;
    color: #183153;
    border: 1px solid #e2e9f5;
    border-top-left-radius: 8px;
}

.aysa-agent8-message.user {
    margin-left: auto;
    background: #173460;
    color: #fff;
    border: 1px solid rgba(10, 25, 55, .08);
    border-top-right-radius: 8px;
}

.aysa-agent8-inline-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding-left: 2px;
}

.aysa-agent8-inline-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 10px;
    border-radius: 999px;
    background: #eef4ff;
    border: 1px solid #c8d9ff;
    color: #174ea6;
    font-size: 12px;
    margin: 4px 6px 0 0;
}

.aysa-agent8-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 34px;
    padding: 0 14px;
    border: 1px solid #1f8a4c;
    border-radius: 999px;
    background: linear-gradient(180deg, #34c46a 0%, #239b52 100%);
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    box-shadow: 0 8px 18px rgba(35, 155, 82, .18);
    transition: background .15s ease, border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}

.aysa-agent8-suggestion-secondary {
    border-color: #d0dced;
    background: rgba(255,255,255,.94);
    color: #24405f;
    box-shadow: none;
}

.aysa-agent8-suggestion-secondary:hover {
    background: #f4f8ff;
    border-color: #bfd0ea;
    box-shadow: 0 8px 18px rgba(18, 36, 70, .08);
}

.aysa-agent8-chip:hover {
    background: linear-gradient(180deg, #3ad875 0%, #28ad5d 100%);
    border-color: #187542;
    box-shadow: 0 12px 24px rgba(35, 155, 82, .24);
    transform: translateY(-1px);
}

.aysa-agent8-chip:focus-visible {
    outline: 2px solid rgba(35, 155, 82, .28);
    outline-offset: 2px;
}

.aysa-agent8-chip[disabled] {
    cursor: not-allowed;
    opacity: .58;
    box-shadow: none;
    transform: none;
}

.aysa-agent8-chip[disabled]:hover {
    background: linear-gradient(180deg, #34c46a 0%, #239b52 100%);
    border-color: #1f8a4c;
    box-shadow: none;
    transform: none;
}

.aysa-agent8-card {
    width: min(100%, 920px);
    background: rgba(255,255,255,.88);
    border: 1px solid #d9e3f2;
    border-radius: 18px;
    box-shadow: 0 10px 24px rgba(19, 35, 69, .06);
    overflow: hidden;
}

.aysa-agent8-card-header {
    padding: 14px 16px 10px;
    border-bottom: 1px solid #e8eef7;
    background: rgba(244,248,255,.88);
}

.aysa-agent8-card-kicker {
    margin: 0 0 4px;
    color: #60708a;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
}

.aysa-agent8-card-title {
    margin: 0;
    color: #173055;
    font-size: 15px;
    font-weight: 700;
}

.aysa-agent8-card-body {
    padding: 14px 16px 16px;
    color: #30435f;
    font-size: 14px;
    line-height: 1.55;
}

.aysa-agent8-card-summary {
    display: grid;
    gap: 8px;
    margin-top: 10px;
}

.aysa-agent8-card-summary-row {
    color: #485a75;
    font-size: 13px;
}

.aysa-agent8-technical-section {
    margin-bottom: 16px;
    padding: 14px 16px;
    border: 1px solid #e0e8f4;
    border-radius: 16px;
    background: #fbfdff;
}

.aysa-agent8-technical-section h3 {
    margin: 0 0 10px;
    color: #173055;
    font-size: 15px;
}

.aysa-agent8-technical-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px 14px;
}

.aysa-agent8-technical-grid div {
    color: #30435f;
    font-size: 13px;
}

.aysa-agent8-technical-list {
    margin: 10px 0 0 18px;
    color: #30435f;
    font-size: 13px;
}

.aysa-agent8-technical-list li {
    margin-bottom: 6px;
}

.aysa-agent8-technical-bundles {
    display: grid;
    gap: 10px;
    margin-top: 10px;
}

.aysa-agent8-technical-bundle {
    border: 1px solid #dce7f8;
    border-radius: 12px;
    background: #f8fbff;
    padding: 12px;
}

.aysa-agent8-technical-bundle[data-execution-state="prepared"] {
    border-color: #b9d3ff;
    background: #f4f8ff;
}

.aysa-agent8-technical-bundle[data-execution-state="applied"] {
    border-color: #b8dfc2;
    background: #f5fbf6;
}

.aysa-agent8-technical-bundle[data-execution-state="verification_pending"] {
    border-color: #f0d58c;
    background: #fffaf0;
}

.aysa-agent8-technical-bundle[data-execution-state="failed"] {
    border-color: #f1c0c0;
    background: #fff7f7;
}

.aysa-agent8-technical-bundle-head {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 8px;
}

.aysa-agent8-technical-bundle-actions {
    margin-top: 10px;
}

.aysa-agent8-technical-bundle-actions .aysa-agent8-chip {
    margin: 0 6px 6px 0;
}

.aysa-agent8-technical-bundle details {
    margin-top: 8px;
}

.aysa-agent8-technical-bundle summary {
    cursor: pointer;
    color: #245da8;
    font-weight: 600;
}

.aysa-agent8-metadata-approval-summary {
    display: grid;
    gap: 10px;
    margin: 12px 0 0;
}

.aysa-agent8-metadata-approval-summary-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
}

.aysa-agent8-metadata-approval-stat {
    padding: 12px;
    border: 1px solid #dce7f8;
    border-radius: 12px;
    background: #fff;
}

.aysa-agent8-metadata-approval-stat strong {
    display: block;
    color: #173055;
    font-size: 18px;
    line-height: 1.2;
}

.aysa-agent8-metadata-approval-stat span {
    display: block;
    margin-top: 4px;
    color: #5b6f8f;
    font-size: 12px;
}

.aysa-agent8-metadata-guidance {
    padding: 12px 14px;
    border-radius: 12px;
    background: #eef5ff;
    color: #26415f;
    font-size: 13px;
}

.aysa-agent8-metadata-buckets {
    display: grid;
    gap: 10px;
    margin-top: 12px;
}

.aysa-agent8-metadata-bucket {
    border: 1px solid #dce7f8;
    border-radius: 12px;
    background: #fff;
    overflow: hidden;
}

.aysa-agent8-metadata-bucket[data-decision="preserve"] {
    border-color: #c9e8cf;
}

.aysa-agent8-metadata-bucket[data-decision="rewrite"] {
    border-color: #bfd4ff;
}

.aysa-agent8-metadata-bucket[data-decision="manual_review"] {
    border-color: #f0d58c;
}

.aysa-agent8-metadata-bucket[data-decision="decorative_ignore"] {
    border-color: #d1d5db;
}

.aysa-agent8-metadata-bucket summary {
    list-style: none;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    cursor: pointer;
}

.aysa-agent8-metadata-bucket summary::-webkit-details-marker {
    display: none;
}

.aysa-agent8-metadata-bucket-title {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.aysa-agent8-metadata-bucket-title strong {
    color: #173055;
    font-size: 14px;
}

.aysa-agent8-metadata-bucket-title span {
    color: #5b6f8f;
    font-size: 12px;
}

.aysa-agent8-metadata-bucket-count {
    min-width: 36px;
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: #eef4ff;
    color: #173055;
    font-weight: 700;
    font-size: 13px;
}

.aysa-agent8-metadata-bucket-body {
    display: grid;
    gap: 10px;
    padding: 0 16px 16px;
}

.aysa-agent8-metadata-row {
    padding: 12px;
    border: 1px solid #e5edf8;
    border-radius: 12px;
    background: #fbfdff;
}

.aysa-agent8-metadata-row-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 8px;
}

.aysa-agent8-metadata-row-url {
    color: #245da8;
    font-size: 12px;
    word-break: break-word;
}

.aysa-agent8-metadata-row-reason {
    margin: 8px 0 0;
    color: #30435f;
    font-size: 13px;
}

.aysa-agent8-metadata-row-copy {
    display: grid;
    gap: 8px;
    margin-top: 10px;
}

.aysa-agent8-metadata-copy-block {
    padding: 10px 12px;
    border-radius: 10px;
    background: #fff;
    border: 1px solid #e5edf8;
}

.aysa-agent8-metadata-copy-block strong {
    display: block;
    margin-bottom: 6px;
    color: #173055;
    font-size: 12px;
}

.aysa-agent8-metadata-copy-block p {
    margin: 0;
    color: #30435f;
    font-size: 13px;
    line-height: 1.5;
}

.aysa-agent8-metadata-row details {
    margin-top: 10px;
}

.aysa-agent8-metadata-row details summary {
    padding: 0;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: #245da8;
    font-size: 12px;
    font-weight: 600;
}

.aysa-agent8-metadata-row-advanced {
    display: grid;
    gap: 6px;
    margin-top: 8px;
    font-size: 12px;
    color: #5b6f8f;
}

.aysa-agent8-metadata-empty {
    padding: 10px 12px;
    border-radius: 10px;
    background: #f7f9fc;
    color: #5b6f8f;
    font-size: 12px;
}

@media (max-width: 720px) {
    .aysa-agent8-metadata-approval-summary-grid,
    .aysa-agent8-technical-grid,
    .aysa-agent8-card-grid {
        grid-template-columns: 1fr;
    }
}

.aysa-agent8-card-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 14px;
}

.aysa-agent8-card-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px 14px;
}

.aysa-agent8-card-grid div,
.aysa-agent8-card-grid li {
    color: #31455f;
    font-size: 13px;
}

.aysa-agent8-card-grid ul {
    margin: 6px 0 0 18px;
}

.aysa-agent8-card-callout {
    margin-bottom: 12px;
    padding: 10px 12px;
    border: 1px solid #e1d6bb;
    border-radius: 12px;
    background: #fff8e7;
    color: #765c21;
    font-size: 13px;
}

.aysa-agent8-card-contract-issue {
    border-color: #efcccc;
    box-shadow: 0 10px 24px rgba(124, 33, 33, .08);
}

.aysa-agent8-card-contract-issue .aysa-agent8-card-header {
    background: rgba(255, 244, 244, .92);
    border-bottom-color: #f0d8d8;
}

.aysa-agent8-system-note {
    width: min(100%, 920px);
    color: #5d6d86;
    font-size: 13px;
    padding: 4px 2px 0;
}

.aysa-agent8-reset-preview {
    width: min(100%, 980px);
    display: grid;
    gap: 14px;
    color: #1f2a44;
}

.aysa-agent8-reset-preview h2,
.aysa-agent8-reset-preview h3 {
    margin: 0;
    color: #111827;
}

.aysa-agent8-reset-preview h2 {
    font-size: 18px;
}

.aysa-agent8-reset-preview h3 {
    font-size: 15px;
}

.aysa-agent8-reset-preview p {
    margin: 6px 0 0;
}

.aysa-agent8-reset-warning,
.aysa-agent8-reset-panel {
    border: 1px solid #dbe4f0;
    border-radius: 8px;
    background: #fff;
    padding: 14px 16px;
}

.aysa-agent8-reset-warning {
    border-color: #f0c36d;
    background: #fff8e6;
}

.aysa-agent8-reset-context {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px 18px;
    margin-top: 10px;
}

.aysa-agent8-reset-context div {
    min-width: 0;
}

.aysa-agent8-reset-label {
    display: block;
    color: #64748b;
    font-size: 12px;
    margin-bottom: 2px;
}

.aysa-agent8-reset-value {
    overflow-wrap: anywhere;
    color: #111827;
    font-weight: 700;
}

.aysa-agent8-reset-columns {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px;
}

.aysa-agent8-reset-list {
    margin: 10px 0 0 18px;
}

.aysa-agent8-reset-list li {
    margin: 5px 0;
}

.aysa-agent8-reset-code {
    display: block;
    width: 100%;
    box-sizing: border-box;
    margin-top: 10px;
    padding: 10px 12px;
    border: 1px solid #cbd5e1;
    border-radius: 8px;
    background: #f8fafc;
    color: #111827;
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
    font-size: 13px;
    overflow-wrap: anywhere;
    user-select: all;
}

.aysa-agent8-reset-confirm {
    display: grid;
    gap: 10px;
    margin-top: 12px;
}

.aysa-agent8-reset-confirm input {
    width: 100%;
    min-height: 38px;
    border: 1px solid #cbd5e1;
    border-radius: 8px;
    padding: 8px 10px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
}

.aysa-agent8-reset-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.aysa-agent8-reset-status {
    color: #64748b;
    font-size: 13px;
}

.aysa-agent8-reset-advanced {
    border: 1px solid #dbe4f0;
    border-radius: 8px;
    background: #f8fafc;
    padding: 10px 12px;
}

.aysa-agent8-reset-advanced summary {
    cursor: pointer;
    font-weight: 700;
    color: #334155;
}

.aysa-agent8-reset-advanced pre {
    max-height: 360px;
    overflow: auto;
    margin: 10px 0 0;
    white-space: pre-wrap;
    color: #475569;
}

.aysa-agent8-composer-wrap {
    flex: 0 0 auto;
    padding: 0 18px 18px;
    background: linear-gradient(180deg, rgba(247,250,255,0) 0%, rgba(247,250,255,.9) 28%, #fff 100%);
}

.aysa-agent8-pending {
    width: 100%;
    max-width: 1180px;
    margin: 0 auto 8px;
    color: #5e6d85;
    font-size: 13px;
}

.aysa-agent8-thinking-dots {
    display: inline-flex;
    gap: 2px;
    margin-left: 2px;
}

.aysa-agent8-thinking-dots span {
    animation: aysaAgent8ThinkingDot 1.1s infinite ease-in-out;
}

.aysa-agent8-thinking-dots span:nth-child(2) {
    animation-delay: .16s;
}

.aysa-agent8-thinking-dots span:nth-child(3) {
    animation-delay: .32s;
}

@keyframes aysaAgent8ThinkingDot {
    0%, 80%, 100% {
        opacity: .35;
        transform: translateY(0);
    }
    40% {
        opacity: 1;
        transform: translateY(-2px);
    }
}

@media (prefers-reduced-motion: reduce) {
    .aysa-agent8-thinking-dots span {
        animation: none;
    }
}

.aysa-agent8-async-sticky {
    width: 100%;
    max-width: 1180px;
    border: 1px solid #d8e1f0;
    background: #ffffff;
    box-shadow: 0 12px 26px rgba(16, 34, 69, .08);
}

.aysa-agent8-async-sticky {
    margin: 0 auto 8px;
    padding: 7px 10px;
    border-radius: 14px;
    color: #243b63;
    font-size: 12px;
}

.aysa-agent8-async-sticky-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

.aysa-agent8-async-title {
    font-weight: 800;
    color: #17213a;
}

.aysa-agent8-async-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border-radius: 999px;
    padding: 5px 9px;
    background: #eef6ff;
    color: #24538a;
    font-size: 12px;
    font-weight: 800;
}

.aysa-agent8-async-pill::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 999px;
    background: #3b82f6;
    animation: aysaAgent8AsyncPulse 1.2s infinite ease-in-out;
}

.aysa-agent8-async-pill[data-status="completed"] {
    background: #eaf8ef;
    color: #18713b;
}

.aysa-agent8-async-pill[data-status="completed"]::before {
    background: #22c55e;
    animation: none;
}

.aysa-agent8-async-pill[data-status="failed"] {
    background: #fff1f2;
    color: #b4232f;
}

.aysa-agent8-async-pill[data-status="failed"]::before {
    background: #ef4444;
    animation: none;
}

.aysa-agent8-async-pill[data-status="retrying"] {
    background: #fff7ed;
    color: #9a4a09;
}

.aysa-agent8-async-pill[data-status="retrying"]::before {
    background: #f97316;
}

.aysa-agent8-async-percent {
    font-size: 28px;
    font-weight: 900;
    color: #17213a;
}

.aysa-agent8-async-bar {
    height: 10px;
    border-radius: 999px;
    background: #e7edf7;
    overflow: hidden;
    margin: 10px 0 8px;
}

.aysa-agent8-async-fill {
    height: 100%;
    border-radius: inherit;
    background: linear-gradient(90deg, #2563eb, #22c55e);
    transition: width .35s ease;
}

.aysa-agent8-async-meta {
    color: #4b5d78;
    font-size: 13px;
    line-height: 1.45;
}

.aysa-agent8-async-refresh {
    border: 1px solid #b8c9e5;
    border-radius: 999px;
    background: #f8fbff;
    color: #24538a;
    cursor: pointer;
    font-weight: 800;
    padding: 4px 8px;
    font-size: 12px;
}

.aysa-agent8-async-sticky-mini {
    flex: 1;
    height: 6px;
    border-radius: 999px;
    background: #e7edf7;
    overflow: hidden;
    min-width: 90px;
}

.aysa-agent8-async-sticky-mini span {
    display: block;
    height: 100%;
    background: linear-gradient(90deg, #2563eb, #22c55e);
}

@keyframes aysaAgent8AsyncPulse {
    0%, 100% {
        opacity: .45;
        transform: scale(.85);
    }
    50% {
        opacity: 1;
        transform: scale(1.08);
    }
}

@media (prefers-reduced-motion: reduce) {
    .aysa-agent8-async-pill::before,
    .aysa-agent8-async-fill {
        animation: none;
        transition: none;
    }
}

.aysa-agent8-composer {
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    display: flex;
    align-items: flex-end;
    gap: 12px;
    padding: 12px;
    border: 1px solid #d8e1f0;
    border-radius: 20px;
    background: rgba(255,255,255,.96);
    box-shadow: 0 12px 26px rgba(16, 34, 69, .08);
}

.aysa-agent8-composer textarea {
    width: 100%;
    min-height: 58px;
    max-height: 180px;
    border: 0;
    outline: 0;
    resize: none;
    background: transparent;
    color: #172f52;
    font-size: 15px;
    line-height: 1.5;
    padding: 2px 4px;
    box-shadow: none;
}

.aysa-agent8-composer textarea::placeholder {
    color: #74829a;
}

.aysa-agent8-composer-actions {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
}

.aysa-agent8-composer-actions .button {
    min-width: 92px;
    height: 42px;
    border-radius: 14px;
}

.aysa-agent8-modal[hidden] { display:none!important; }

.aysa-agent8-modal {
    position: fixed;
    inset: 0;
    z-index: 999999;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}

.aysa-agent8-modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(15, 27, 51, .45);
}

.aysa-agent8-modal-dialog {
    position: relative;
    width: min(1440px, calc(100vw - 32px));
    max-height: calc(100vh - 48px);
    display: flex;
    flex-direction: column;
    background: #fff;
    border: 1px solid #d9e3f2;
    border-radius: 20px;
    box-shadow: 0 24px 60px rgba(12, 27, 52, .22);
    overflow: visible;
}

.aysa-agent8-modal-dialog-iframe {
    width: min(1440px, calc(100vw - 32px));
    height: calc(100vh - 48px);
    max-height: calc(100vh - 48px);
}

.aysa-agent8-modal-header,
.aysa-agent8-modal-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 18px;
    border-bottom: 1px solid #e7edf7;
    background: #f8fbff;
}

.aysa-agent8-modal-footer {
    border-top: 1px solid #e7edf7;
    border-bottom: 0;
    justify-content: flex-end;
    background: #fff;
}

.aysa-agent8-modal-title {
    margin: 0;
    color: #173055;
    font-size: 20px;
    line-height: 1.2;
}

.aysa-agent8-modal-status {
    margin: 14px 18px 0;
    padding: 10px 12px;
    border-radius: 12px;
    font-size: 13px;
    color: #21466f;
    background: #eef6ff;
    border: 1px solid #d5e6fb;
}

.aysa-agent8-modal-intro {
    padding: 14px 18px 0;
    color: #42546f;
    font-size: 14px;
    line-height: 1.5;
}

.aysa-agent8-modal-table-wrap {
    flex: 1 1 auto;
    min-height: 0;
    overflow-x: auto;
    overflow-y: visible;
    padding: 14px 18px 18px;
}

.aysa-agent8-modal-scroll-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 14px 18px 18px;
}

.aysa-agent8-modal-iframe-wrap {
    flex: 1 1 auto;
    min-height: 0;
    padding: 0 18px 18px;
}

.aysa-agent8-modal-iframe-wrap iframe {
    width: 100%;
    height: 100%;
    min-height: 640px;
    border: 1px solid #dce6f4;
    border-radius: 14px;
    background: #fff;
}

.aysa-agent8-calendar-native-summary {
    margin-bottom: 12px;
    padding: 10px 12px;
    border: 1px solid #d5e6fb;
    border-radius: 12px;
    background: #eef6ff;
    color: #21466f;
}

.aysa-agent8-calendar-native-controls {
    display: grid;
    grid-template-columns: repeat(5, minmax(120px, 1fr));
    gap: 10px;
    margin: 0 0 12px;
}

.aysa-agent8-calendar-native-controls label {
    display: flex;
    flex-direction: column;
    gap: 4px;
    color: #405670;
    font-size: 12px;
    font-weight: 700;
}

.aysa-agent8-calendar-native-label-line {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

.aysa-agent8-calendar-native-controls select {
    width: 100%;
    min-height: 34px;
}

.aysa-agent8-calendar-native-range {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin: 0 0 12px;
    color: #405670;
    font-size: 13px;
}

.aysa-agent8-calendar-native-list {
    display: grid;
    gap: 16px;
}

.aysa-agent8-calendar-native-day {
    border: 1px solid #dbe6f4;
    border-radius: 16px;
    overflow: hidden;
    background: #f8fbff;
}

.aysa-agent8-calendar-native-day-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 14px;
    border-bottom: 1px solid #dbe6f4;
    background: #eef6ff;
    color: #173055;
}

.aysa-agent8-calendar-native-day-count {
    color: #5c6f89;
    font-size: 12px;
}

.aysa-agent8-calendar-native-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 14px;
    margin: 10px;
    padding: 12px;
    border: 1px solid #e1e8f2;
    border-radius: 14px;
    background: #fff;
}

.aysa-agent8-calendar-native-title {
    color: #17233c;
    font-weight: 700;
    line-height: 1.35;
}

.aysa-agent8-calendar-native-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 8px;
    color: #5c6f89;
    font-size: 12px;
}

.aysa-agent8-calendar-native-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    border: 1px solid #d6e1ef;
    border-radius: 999px;
    padding: 3px 8px;
    background: #f5f8fc;
    color: #31486a;
}

.aysa-agent8-calendar-info-trigger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    width: 18px;
    height: 18px;
    border: 1px solid #1d4ed8;
    border-radius: 999px;
    box-shadow: 0 2px 5px rgba(37, 99, 235, 0.22);
    background: #2563eb;
    color: #fff;
    cursor: pointer;
    font-size: 12px;
    font-weight: 800;
    line-height: 1;
}

.aysa-agent8-calendar-info-trigger:hover,
.aysa-agent8-calendar-info-trigger:focus {
    background: #1d4ed8;
    border-color: #173ea5;
    outline: 2px solid rgba(37, 99, 235, 0.18);
    outline-offset: 1px;
}

.aysa-agent8-calendar-explainer {
    position: fixed;
    z-index: 1000002;
    max-width: 280px;
    padding: 10px 12px;
    border: 1px solid #cfdced;
    border-radius: 12px;
    box-shadow: 0 12px 28px rgba(18, 38, 63, 0.18);
    background: #fff;
    color: #26364f;
    font-size: 13px;
    line-height: 1.4;
}

.aysa-agent8-calendar-explainer-title {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 4px;
    font-weight: 800;
}

.aysa-agent8-calendar-explainer-close {
    border: 0;
    background: transparent;
    color: #61728a;
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
}

.aysa-agent8-calendar-native-actions {
    flex: 0 0 auto;
}

.aysa-agent8-calendar-native-footer {
    position: sticky;
    bottom: 0;
    display: flex;
    gap: 8px;
    justify-content: flex-end;
    margin-top: 16px;
    padding: 12px 0 0;
    background: linear-gradient(180deg, rgba(255,255,255,0), #fff 28%);
}

.aysa-agent8-modal-iframe-wrap {
    flex: 1 1 auto;
    min-height: 0;
    padding: 0 18px 18px;
}

.aysa-agent8-modal-iframe-wrap iframe {
    width: 100%;
    height: 100%;
    min-height: 640px;
    border: 1px solid #dce6f4;
    border-radius: 14px;
    background: #fff;
}

.aysa-agent8-modal-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: 13px;
}

.aysa-agent8-modal-table th,
.aysa-agent8-modal-table td {
    padding: 10px 12px;
    border-bottom: 1px solid #e8eef7;
    text-align: left;
    vertical-align: top;
    color: #31455f;
}

.aysa-agent8-modal-table th {
    background: #f8fbff;
    color: #4d5f79;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: .04em;
    position: sticky;
    top: 0;
    z-index: 15;
}

.aysa-agent8-keyword-status {
    display: inline-flex;
    align-items: center;
    min-height: 26px;
    padding: 0 10px;
    border-radius: 999px;
    background: #eef3fb;
    color: #3c5578;
    font-size: 12px;
}

.aysa-agent8-keyword-refuse[disabled] {
    opacity: .55;
    cursor: default;
}

.aysa-agent8-keyword-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.aysa-agent8-keyword-mapping-table {
    table-layout: fixed;
}

.aysa-agent8-keyword-mapping-table th,
.aysa-agent8-keyword-mapping-table td {
    overflow-wrap: anywhere;
}

.aysa-agent8-keyword-mapping-keyword {
    display: grid;
    gap: 4px;
}

.aysa-agent8-keyword-mapping-meta,
.aysa-agent8-keyword-mapping-url {
    color: #64748b;
    font-size: 11px;
    line-height: 1.35;
}

.aysa-agent8-keyword-mapping-page {
    display: grid;
    gap: 3px;
}

.aysa-agent8-keyword-mapping-page a {
    font-weight: 700;
    text-decoration: none;
}

.aysa-agent8-keyword-mapping-decision {
    display: grid;
    gap: 8px;
}

.aysa-agent8-keyword-mapping-primary-actions,
.aysa-agent8-keyword-mapping-secondary-actions,
.aysa-agent8-keyword-mapping-replacement-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
}

.aysa-agent8-keyword-mapping-replacement {
    display: none;
    margin-top: 8px;
    padding: 10px;
    border: 1px solid #d8e4f4;
    border-radius: 10px;
    background: #f8fbff;
}

.aysa-agent8-keyword-mapping-row.is-changing-page .aysa-agent8-keyword-mapping-replacement {
    display: block;
}

.aysa-agent8-keyword-mapping-replacement-label {
    display: block;
    margin-bottom: 6px;
    color: #4d5f79;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
}

.aysa-agent8-keyword-mapping-replacement select,
.aysa-agent8-keyword-mapping-replacement input {
    min-width: min(100%, 260px);
    max-width: 100%;
}

.aysa-agent8-help-button {
    width: 24px;
    min-width: 24px;
    height: 24px;
    padding: 0;
    border-radius: 999px;
    border: 1px solid #c9d7ea;
    background: #fff;
    color: #274b7a;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
}

.aysa-agent8-help-button:hover {
    background: #eef6ff;
}

.aysa-agent8-content-strategy-item {
    padding: 12px 0;
    border-top: 1px solid #eef2f7;
}

.aysa-agent8-content-strategy-item.is-rejected {
    opacity: .6;
}

.aysa-agent8-content-strategy-item-head {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    align-items: flex-start;
}

.aysa-agent8-content-strategy-item-meta,
.aysa-agent8-content-strategy-item-links,
.aysa-agent8-content-strategy-item-actions {
    margin-top: 8px;
    color: #4a5d77;
}

.aysa-agent8-content-strategy-item-actions {
    display: flex;
    gap: 8px;
    align-items: center;
    flex-wrap: wrap;
}

.aysa-agent8-content-strategy-association {
    min-width: 260px;
    padding: 7px 10px;
    border: 1px solid #cbd8ea;
    border-radius: 10px;
}

.aysa-agent8-content-strategy-page-search,
.aysa-agent8-content-strategy-manual {
    min-width: 320px;
    max-width: 100%;
    padding: 7px 10px;
    border: 1px solid #cbd8ea;
    border-radius: 10px;
}

.aysa-agent8-content-strategy-picker {
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: min(560px, 100%);
}

.aysa-agent8-content-strategy-picker-hint,
.aysa-agent8-content-strategy-selected-url {
    font-size: 12px;
    color: #667892;
}

.aysa-agent8-missing-pages-decision-group {
    margin-bottom: 14px;
    border: 1px solid #dfe8f5;
    border-radius: 16px;
    background: #fff;
    overflow: hidden;
}

.aysa-agent8-missing-pages-group-head {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    align-items: flex-start;
    padding: 14px 16px;
    background: #f8fbff;
    border-bottom: 1px solid #e7eef8;
}

.aysa-agent8-missing-pages-group-title {
    margin: 0;
    font-size: 15px;
    color: #23344d;
}

.aysa-agent8-missing-pages-group-note {
    margin-top: 4px;
    color: #60718a;
    font-size: 12px;
}

.aysa-agent8-missing-pages-group-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: flex-end;
}

.aysa-agent8-missing-pages-list {
    padding: 4px 14px 70px;
}

.aysa-agent8-missing-pages-item {
    display: grid;
    grid-template-columns: auto minmax(180px, 1.2fr) minmax(130px, .6fr) minmax(150px, .7fr) minmax(180px, 1fr) auto;
    gap: 10px;
    align-items: center;
    padding: 10px 0;
    border-bottom: 1px solid #eef2f7;
}

.aysa-agent8-missing-pages-item.is-saving {
    opacity: .72;
}

.aysa-agent8-missing-pages-keyword {
    font-weight: 700;
    color: #20324a;
}

.aysa-agent8-missing-pages-meta,
.aysa-agent8-missing-pages-reason {
    color: #64748b;
    font-size: 12px;
    line-height: 1.35;
}

.aysa-agent8-missing-pages-inline-actions {
    display: flex;
    gap: 6px;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
}

.aysa-agent8-missing-pages-save-status {
    display: inline-flex;
    align-items: center;
    min-height: 26px;
    padding: 4px 10px;
    border-radius: 999px;
    color: #53657d;
    background: #f1f5f9;
    font-size: 12px;
    font-weight: 700;
}

.aysa-agent8-missing-pages-save-status.is-saving {
    color: #31568a;
    background: #eef6ff;
}

.aysa-agent8-missing-pages-save-status.is-saved {
    color: #17633a;
    background: #e9f9ef;
}

.aysa-agent8-missing-pages-save-status.is-existing {
    color: #6a4d0f;
    background: #fff7df;
}

.aysa-agent8-missing-pages-save-status.is-error {
    color: #a02e24;
    background: #fff0ef;
}

.aysa-agent8-missing-pages-sticky {
    position: sticky;
    bottom: 0;
    z-index: 20;
    display: flex;
    justify-content: space-between;
    gap: 12px;
    align-items: center;
    margin: 0 -18px -18px;
    padding: 12px 18px;
    border-top: 1px solid #dbe6f4;
    background: rgba(248, 251, 255, .96);
    backdrop-filter: blur(6px);
}

.aysa-agent8-missing-pages-sticky-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: flex-end;
}

@media (max-width: 960px) {
    .aysa-agent8-missing-pages-item {
        grid-template-columns: auto 1fr;
        align-items: flex-start;
    }

    .aysa-agent8-missing-pages-inline-actions {
        grid-column: 1 / -1;
        justify-content: flex-start;
    }
}

@media (max-width: 960px) {
    .aysa-agent8-page {
        padding: 14px 10px 0;
    }

    .aysa-agent8-shell {
        padding: 0 0 10px;
    }

    .aysa-agent8-topbar {
        flex-direction: column;
        align-items: flex-start;
    }

    .aysa-agent8-topmeta {
        justify-content: flex-start;
    }

    .aysa-agent8-message,
    .aysa-agent8-card,
    .aysa-agent8-system-note {
        max-width: 100%;
        width: 100%;
    }

    .aysa-agent8-reset-context,
    .aysa-agent8-reset-columns {
        grid-template-columns: 1fr;
    }

    .aysa-agent8-transcript {
        padding: 20px 16px 14px;
    }
}

@media (max-width: 782px) {
    body.toplevel_page_aysa-agent8 #wpbody,
    body.toplevel_page_aysa-agent8 #wpbody-content,
    body.admin_page_aysa-agent8 #wpbody,
    body.admin_page_aysa-agent8 #wpbody-content,
    body.aysa-ai-seo_page_aysa-agent8 #wpbody,
    body.aysa-ai-seo_page_aysa-agent8 #wpbody-content {
        height: auto;
        min-height: calc(100vh - 46px);
        overflow: visible;
    }

    .aysa-agent8-page {
        height: auto;
        min-height: calc(100vh - 46px);
        overflow: visible;
        padding: 12px 0 0;
    }

    .aysa-agent8-shell {
        min-height: calc(100vh - 46px);
        padding: 0 0 10px;
    }

    .aysa-agent8-topbar {
        padding: 0 10px;
    }

    .aysa-agent8-chatframe {
        border-radius: 18px;
    }

    .aysa-agent8-transcript {
        padding: 16px 12px 14px;
    }

    .aysa-agent8-card-grid {
        grid-template-columns: 1fr;
    }

    .aysa-agent8-composer-wrap {
        padding: 0 10px 10px;
    }

    .aysa-agent8-composer {
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
    }

    .aysa-agent8-composer-actions {
        justify-content: flex-end;
    }

    .aysa-agent8-modal {
        padding: 10px;
    }

    .aysa-agent8-modal-dialog {
        width: calc(100vw - 20px);
        max-height: calc(100vh - 20px);
    }
}
</style>

<script type="text/javascript">
jQuery(function($) {
    let currentWalletSnapshot = <?php echo wp_json_encode($wallet_snapshot); ?>;
    renderWallet(currentWalletSnapshot);
    const ajaxUrl = window.ajaxurl;
    const nonce = <?php echo wp_json_encode($nonce); ?>;
    const keywordCacheNonce = <?php echo wp_json_encode($keyword_cache_nonce); ?>;
    const googleOauthNonce = <?php echo wp_json_encode($google_oauth_nonce); ?>;
    const contentStrategyNonce = <?php echo wp_json_encode($content_strategy_nonce); ?>;
    const publishingCalendarEmbedUrl = <?php echo wp_json_encode($publishing_calendar_embed_url); ?>;
    const siteHost = <?php echo wp_json_encode($site_host); ?>;
    let projectId = <?php echo (int) $project_id; ?>;
    const wpProjectId = <?php echo (int) $wp_project_id; ?>;
    let conversationLanguage = 'en';
    let state = {};
    let conversationId = '';
    let transcript = [];
    let pendingApproval = null;
    let currentProjection = null;
    let currentAllowedActionKeys = [];
    let currentAllowedActionsAuthoritative = false;
    let currentSuggestions = [];
    let persistentActions = [];
    let currentProductMap = [];
    let currentContractIssue = null;
    let currentUiCommand = null;
    let oauthCallbackJustReturned = false;
    let oauthStatusRefreshPending = false;
    let pendingExternalAction = null;
    let pendingExternalActionConsumed = false;
    let currentConversationRunId = '';
    let conversationPollTimer = null;
    let conversationPollFailures = 0;
    let conversationPollStartedAt = 0;
    const bootstrapBackgroundThresholdMs = 5000;
    let conversationRequestEpoch = 0;
    let agent8ForegroundRequest = null;
    let currentAsyncJob = null;
    let currentAsyncProgress = null;
    let asyncPollTimer = null;
    let finalizedBusinessProfileAutofillRuns = {};
    let finalizedCompetitionProposalRuns = {};
    let pendingGeneralFieldInput = '';

    let asyncLastEventId = 0;
    let currentModuleSlug = '';

    function reflectAgent8CommunicationsInChat() {
        $.post(ajaxUrl, {
            action: 'aysa_agent8_notifications_fetch',
            nonce: contentStrategyNonce,
            project_id: projectId,
            limit: 5
        }).done(function(response) {
            const data = response && response.success && response.data ? response.data : {};
            const items = Array.isArray(data.notifications) ? data.notifications.slice().reverse() : [];
            const storageKey = 'aysa_agent8_reflected_events_' + String(projectId || '');
            let reflected = [];
            try {
                reflected = JSON.parse(window.localStorage.getItem(storageKey) || '[]');
            } catch (e) {
                reflected = [];
            }
            const reflectedSet = new Set(Array.isArray(reflected) ? reflected.map(String) : []);
            let changed = false;
            items.forEach(function(item) {
                const eventId = String(item.event_id || '');
                const eventType = String(item.event_type || '');
                if (!eventId || reflectedSet.has(eventId)) {
                    return;
                }
                if (!/daily_summary|content_published|email_failed|needs_attention|blocked/i.test(eventType)) {
                    return;
                }
                const emailStatus = String(item.email_status || '');
                const recipient = String(item.recipient || '');
                const suffix = emailStatus
                    ? '\nEmail status: ' + emailStatus + (recipient ? ' (' + recipient + ')' : '')
                    : '';
                transcript.push({
                    role: 'assistant',
                    message: String(item.message || item.title || 'Agent8 communication sent.') + suffix
                });
                reflectedSet.add(eventId);
                changed = true;
            });
            if (changed) {
                window.localStorage.setItem(storageKey, JSON.stringify(Array.from(reflectedSet).slice(-50)));
                renderTranscript();
            }
        });
    }
    let currentTabSlug = '';
    let currentTechnicalOverviewSummary = null;
    let currentTechnicalWorkspaceSnapshot = null;
    let currentPublishingCalendarSnapshot = null;
    let currentPublishingCalendarScheduleContract = null;
    let currentPublishingCalendarRowContracts = {};
    let currentPublishingCalendarFilters = {
        month: '',
        page_type: '',
        content_type: '',
        status: '',
        source: ''
    };
    let currentPublishingCalendarVisibleLimit = 50;
    let currentPublishingCalendarScheduleNotice = null;

    function nextConversationRequestEpoch() {
        conversationRequestEpoch += 1;
        return conversationRequestEpoch;
    }

    function isCurrentConversationRequestEpoch(epoch) {
        return Number(epoch || 0) === Number(conversationRequestEpoch || 0);
    }

    function isAgent8ForegroundPending() {
        return !!agent8ForegroundRequest;
    }

    function showAgent8Thinking(epoch, type, sourceButton, actionKey) {
        const requestEpoch = Number(epoch || 0) || 0;
        $('[data-agent8-loader="1"][data-agent8-epoch="' + requestEpoch + '"]').remove();
        agent8ForegroundRequest = {
            epoch: requestEpoch,
            type: String(type || 'message'),
            sourceButton: sourceButton && sourceButton.length ? sourceButton : null,
            actionKey: String(actionKey || '')
        };
        if (agent8ForegroundRequest.sourceButton) {
            agent8ForegroundRequest.sourceButton.prop('disabled', true).attr('data-agent8-loading-epoch', String(requestEpoch));
        }
        $('#aysa-agent8-pending').attr('data-mode', 'thinking').attr('data-epoch', String(requestEpoch));
        applyUiLanguage();
        $('#aysa-agent8-pending').removeAttr('hidden');
        renderTranscript();
    }

    function clearAgent8Thinking(epoch, keepPendingVisible) {
        const requestEpoch = Number(epoch || 0) || 0;
        $('[data-agent8-loader="1"][data-agent8-epoch="' + requestEpoch + '"]').remove();
        if (agent8ForegroundRequest && Number(agent8ForegroundRequest.epoch || 0) === requestEpoch) {
            if (agent8ForegroundRequest.sourceButton) {
                agent8ForegroundRequest.sourceButton.prop('disabled', false).removeAttr('data-agent8-loading-epoch');
            }
            agent8ForegroundRequest = null;
            if (!keepPendingVisible) {
                $('#aysa-agent8-pending').attr('hidden', 'hidden').removeAttr('data-epoch');
            }
            return true;
        }
        return false;
    }

    function appendAgent8ReadableError(message) {
        transcript.push({
            role: 'assistant',
            message: String(message || 'Agent8 request failed.')
        });
    }

    function uiText(key, language) {
        const lang = String(language || 'en').toLowerCase();
        const dict = {
            en: {
                composer_placeholder: 'Write to Agent 8 what you want to clarify or do next.',
                send: 'Send',
                close: 'Close',
                done: 'Done',
                continue: 'Continue',
                continue_with_current_list: 'Continue with the current list',
                delete: 'Delete',
                undo: 'Undo',
                competitors_name: 'Name',
                competitors_status: 'Status',
                send_to_plan: 'Send to plan',
                pending_thinking: 'Agent 8 is thinking...',
                pending_background: 'Running in the background...',
                pending_google_disconnect: 'Disconnecting Google...'
            },
            ro: {
                composer_placeholder: 'Scrie-i lui Agent 8 ce vrei să clarifici sau să facă mai departe.',
                send: 'Trimite',
                close: 'Închide',
                done: 'Gata',
                continue: 'Continuă',
                continue_with_current_list: 'Continuă cu lista actuală',
                delete: 'Șterge',
                undo: 'Undo',
                competitors_name: 'Nume',
                competitors_status: 'Status',
                send_to_plan: 'Trimite în plan',
                pending_thinking: 'Agent 8 gândește...',
                pending_background: 'Rulează în fundal...',
                pending_google_disconnect: 'Se deconectează Google...'
            }
        };
        const pack = dict[lang] || dict.en;
        return pack[key] || dict.en[key] || '';
    }

    function normalizeLanguageCode(value) {
        const normalized = String(value || '').toLowerCase().replace('_', '-').trim();
        const base = normalized.split('-')[0];
        const supported = [
            'en', 'ro', 'bg', 'fr', 'de', 'it', 'es', 'pt', 'nl', 'pl', 'cs', 'sk', 'sl', 'hr', 'hu',
            'el', 'da', 'sv', 'fi', 'et', 'lv', 'lt', 'mt', 'ga', 'is', 'no', 'sq', 'sr', 'uk', 'tr', 'mk', 'bs'
        ];
        return supported.indexOf(base) >= 0 ? base : 'en';
    }

    function detectMessageLanguage(message) {
        const normalized = (' ' + String(message || '')
            .toLowerCase()
            .normalize('NFD')
            .replace(/[\u0300-\u036f]/g, ' ')
            .replace(/[^a-z\\s]/g, ' ')
            .replace(/\\s+/g, ' ')
            .trim() + ' ');
        if (normalized.trim() === '') {
            return '';
        }
        const maps = [
            ['ro', [' si ', ' sunt ', ' vreau ', ' pentru ', ' obiectivele ', ' setari ', ' setările ', ' cuvinte ', ' keyworduri ', ' pagina ', ' pagini ', ' competitorii ', ' competitori ', ' arata ', ' arata mi ', ' lipsa ', ' lipsă ', ' romana ', ' romaneste ', ' romaneste ', ' vorbesc ', ' vorbeste ', ' vorbim ', ' limbi ', ' straine ', ' stii ', ' cheia ', ' activare ']],
            ['bg', [' iskam ', ' za ', ' stranica ', ' stranici ', ' dumi ', ' proekt ']],
            ['fr', [' bonjour ', ' salut ', ' je ', ' suis ', ' francais ', ' francaise ', ' france ', ' parle ', ' parlez ', ' vous ', ' anglais ', ' pour ', ' avec ', ' pages ', ' mots ', ' cles ', ' objectif ', ' vente ']],
            ['de', [' hallo ', ' ich ', ' bin ', ' deutsch ', ' deutsche ', ' spreche ', ' fur ', ' seite ', ' seiten ', ' schlusselwort ', ' ziel ', ' verkauf ', ' mochte ']],
            ['it', [' ciao ', ' per ', ' sito ', ' pagine ', ' parole ', ' chiave ', ' obiettivo ', ' vendite ']],
            ['es', [' hola ', ' hablo ', ' espanol ', ' espanola ', ' para ', ' sitio ', ' paginas ', ' palabras ', ' clave ', ' objetivo ', ' ventas ']],
            ['pt', [' ola ', ' para ', ' paginas ', ' palavras ', ' chave ', ' objetivo ', ' vendas ']],
            ['nl', [' hallo ', ' voor ', ' pagina ', ' paginas ', ' zoekwoord ', ' doel ', ' verkopen ']],
            ['pl', [' czesc ', ' dla ', ' strona ', ' strony ', ' slowa ', ' kluczowe ', ' cel ', ' sprzedaz ']],
            ['cs', [' ahoj ', ' pro ', ' stranka ', ' stranky ', ' klicova ', ' slova ', ' cil ', ' prodej ']],
            ['el', [' gia ', ' istoselida ', ' lexeis ', ' stoxos ', ' poliseis ']],
            ['tr', [' merhaba ', ' icin ', ' sayfa ', ' anahtar ', ' hedef ', ' satis ']],
        ];
        for (let i = 0; i < maps.length; i += 1) {
            const language = maps[i][0];
            const words = maps[i][1];
            for (let j = 0; j < words.length; j += 1) {
                if (normalized.indexOf(words[j]) >= 0) {
                    return language;
                }
            }
        }
        return '';
    }

    function isSyncApprovalActionKey(actionKey) {
        const key = String(actionKey || '').trim();
        return [
            'connect_google',
            'save_google_property_selection',
            'continue_without_google',
            'run_general_autofill',
            'confirm_general_profile',
            'update_general_field',
            'save_objectives',
            'save_seo_settings',
            'generate_competition_proposal',
            'regenerate_competition_proposal',
            'accept_competition_proposal',
            'save_tone_of_voice',
            'send_missing_pages_to_plan',
            'update_content_strategy_items',
            'refresh_research_keyword_discovery',
            'refresh_research_competitor_gap',
            'refresh_research_competitor_identification',
            'refresh_research_competitor_backlinks',
            'refresh_research_sitemap_competition',
            'apply_onpage_meta_batch',
            'apply_onpage_rewrite_batch'
        ].indexOf(key) >= 0;
    }

    function isSyncActionKey(actionKey) {
        const key = String(actionKey || '').trim();
        return [
	            'show_found_keywords',
	            'run_general_autofill',
	            'show_setup_seo_settings',
	            'draft_seo_settings',
	            'save_seo_settings',
	            'show_research_competitors',
            'show_keyword_mapping',
            'show_missing_pages',
            'show_planned_content',
            'show_publishing_calendar',
            'show_content_strategy',
            'update_content_strategy_items',
            'schedule_publishing_plan',
            'reject_found_keyword',
            'reject_research_competitor',
            'reject_missing_page',
            'reject_planned_content',
            'accept_keyword_mapping',
            'reject_keyword_mapping',
            'request_mapping_alternative',
            'apply_mapping_replacement',
            'undo_recent_delete',
            'show_technical_overview',
            'guide_technical_optimization',
            'show_technical_site_audit',
            'refresh_technical_site_audit',
            'update_technical_site_audit_issue_lifecycle',
            'prepare_metadata_remediation',
            'prepare_response_code_review',
            'prepare_indexability_review',
            'prepare_internal_linking_plan',
            'prepare_image_alt_text',
            'apply_metadata_remediation',
            'apply_response_code_review',
            'apply_indexability_review',
            'apply_internal_linking_plan',
            'apply_image_alt_text',
            'verify_metadata_remediation',
            'verify_response_code_review',
            'verify_indexability_review',
            'verify_internal_linking_plan',
            'verify_image_alt_text',
            'ignore_site_audit_action_bundle',
            'show_technical_pagespeed',
            'refresh_technical_pagespeed',
            'export_technical_pagespeed_pdf',
            'ask_technical_pagespeed_recipient',
            'email_technical_pagespeed_pdf',
            'show_technical_schema',
            'refresh_technical_schema',
            'apply_technical_schema_recommended',
            'disable_technical_schema',
            'show_technical_redirects_review',
            'show_technical_redirect_conflicts',
            'refresh_technical_redirects_review',
            'apply_technical_redirect_candidate',
            'mark_technical_gone_candidate',
            'ignore_technical_404_candidate',
            'apply_technical_redirects_batch',
            'mark_technical_gone_batch',
            'ignore_technical_404_batch',
            'show_technical_sitemap_robots',
            'refresh_technical_sitemap_robots',
            'unblock_technical_robots',
            'generate_aysa_sitemap',
            'save_technical_robots',
            'restore_recommended_robots',
            'enforce_aysa_sitemap_authority',
            'disable_conflicting_sitemap_providers',
            'show_technical_internal_linking',
            'refresh_technical_internal_linking',
            'preview_technical_internal_linking',
            'apply_technical_internal_linking',
            'preview_offpage_draft_article',
            'send_offpage_draft_article_approval_email'
        ].indexOf(key) >= 0;
    }

    function applyUiLanguage() {
        $('#aysa-agent8-language').val(normalizeLanguageCode(conversationLanguage));
        $('#aysa-agent8-input').attr('placeholder', uiText('composer_placeholder', conversationLanguage));
        $('#aysa-agent8-send').text(uiText('send', conversationLanguage));
        $('#aysa-agent8-competitors-modal-close, #aysa-agent8-keyword-modal-close, #aysa-agent8-missing-pages-modal-close, #aysa-agent8-content-strategy-modal-close, #aysa-agent8-publishing-calendar-modal-close, #aysa-agent8-technical-modal-close, #aysa-agent8-help-modal-close, #aysa-agent8-article-preview-modal-close, #aysa-agent8-purchase-preview-modal-close').text(uiText('close', conversationLanguage));
        $('#aysa-agent8-competitors-modal-done').text(uiText('done', conversationLanguage));
        $('#aysa-agent8-keyword-modal-done').text(uiText('continue_with_current_list', conversationLanguage));
        $('#aysa-agent8-missing-pages-modal-done, #aysa-agent8-content-strategy-modal-done, #aysa-agent8-publishing-calendar-modal-done, #aysa-agent8-technical-modal-done').text(uiText('continue', conversationLanguage));
        $('#aysa-agent8-missing-pages-send-to-plan').text(uiText('send_to_plan', conversationLanguage));
        $('#aysa-agent8-competitors-col-name').text(uiText('competitors_name', conversationLanguage));
        $('#aysa-agent8-competitors-col-url').text('URL');
        $('#aysa-agent8-competitors-col-status').text(uiText('competitors_status', conversationLanguage));
        const $pending = $('#aysa-agent8-pending');
        const pendingMode = String($pending.attr('data-mode') || 'thinking');
        const pendingKey = pendingMode === 'background'
            ? 'pending_background'
            : (pendingMode === 'google_disconnect' ? 'pending_google_disconnect' : 'pending_thinking');
        $pending.text(uiText(pendingKey, conversationLanguage));
    }

    (function consumePendingExternalAction() {
        try {
            const raw = window.localStorage.getItem('aysa_agent8_pending_action');
            if (!raw) {
                return;
            }
            const parsed = JSON.parse(raw);
            if (parsed && typeof parsed === 'object' && parsed.action_key) {
                pendingExternalAction = parsed;
            }
            window.localStorage.removeItem('aysa_agent8_pending_action');
        } catch (e) {
            pendingExternalAction = null;
        }
    })();

    (function consumeOauthCallbackParams() {
        try {
            const url = new URL(window.location.href);
            const params = url.searchParams;
            const hasOauthCallbackMarkers = params.has('aysa_google') || params.has('aysa_google_error') || params.has('aysa_google_replayed');
            if (!hasOauthCallbackMarkers) {
                return;
            }
            oauthCallbackJustReturned = true;
            oauthStatusRefreshPending = true;
            params.delete('aysa_google');
            params.delete('aysa_google_error');
            params.delete('aysa_google_project');
            params.delete('aysa_google_replayed');
            const next = url.pathname + (params.toString() ? '?' + params.toString() : '');
            window.history.replaceState({}, document.title, next);
        } catch (e) {
            oauthCallbackJustReturned = true;
            oauthStatusRefreshPending = true;
        }
    })();

    function escapeHtml(value) {
        return $('<div>').text(value || '').html();
    }

    function escapeAttribute(value) {
        return escapeHtml(value).replace(/"/g, '&quot;');
    }

    function sanitizeAssistantDisplayMessage(value) {
        let text = String(value || '');
        const replacements = {
            accept_competition_proposal: conversationLanguage === 'ro' ? 'acceptarea propunerii' : 'accepting the proposal',
            regenerate_competition_proposal: conversationLanguage === 'ro' ? 'refacerea propunerii' : 'rebuilding the proposal',
            generate_competition_proposal: conversationLanguage === 'ro' ? 'generarea propunerii' : 'generating the proposal',
            run_general_autofill: conversationLanguage === 'ro' ? 'reanalyzarea site-ului' : 'reanalyzing the website',
            confirm_general_profile: conversationLanguage === 'ro' ? 'salvarea profilului' : 'saving the profile',
            save_seo_settings: conversationLanguage === 'ro' ? 'salvarea setărilor SEO' : 'saving SEO settings',
            save_objectives: conversationLanguage === 'ro' ? 'salvarea obiectivelor' : 'saving objectives',
            save_tone_of_voice: conversationLanguage === 'ro' ? 'salvarea tonului' : 'saving the tone'
        };
        Object.keys(replacements).forEach((key) => {
            const pattern = new RegExp('`?' + key + '`?', 'g');
            text = text.replace(pattern, replacements[key]);
        });
        text = text.replace(/`?quality_status=valid`?/g, conversationLanguage === 'ro' ? 'propunerea este validă' : 'the proposal is valid');
        text = text.replace(/`?allowed_action_keys`?/g, conversationLanguage === 'ro' ? 'acțiunile disponibile' : 'available actions');
        return text;
    }

    function formatMessageHtml(value) {
        const escaped = escapeHtml(sanitizeAssistantDisplayMessage(value || ''));
        const withLinks = escaped.replace(/(https?:\/\/[^\s<]+)/g, (match) => {
            return '<a href="' + match + '" target="_blank" rel="noopener">' + match + '</a>';
        });
        return withLinks.replace(/\n/g, '<br>');
    }

    function decodeMessage(value) {
        return decodeURIComponent(String(value || ''));
    }

    function normalizeSearchText(value) {
        return String(value || '').toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '').trim();
    }

    function contentStrategyPageOptions() {
        return currentUiCommand && Array.isArray(currentUiCommand.page_options) ? currentUiCommand.page_options : [];
    }

    function resolveContentStrategyPageCandidate(rawValue) {
        const raw = String(rawValue || '').trim();
        if (!raw) {
            return null;
        }
        const normalizedRaw = normalizeSearchText(raw);
        const options = contentStrategyPageOptions();
        let partialMatch = null;

        for (let i = 0; i < options.length; i++) {
            const option = options[i] && typeof options[i] === 'object' ? options[i] : null;
            if (!option) {
                continue;
            }
            const url = String(option.url || '').trim();
            const title = String(option.title || '').trim();
            const slug = String(option.slug || '').trim();
            const searchValue = String(option.search_value || '').trim();
            const haystack = [url, title, slug, searchValue].map(normalizeSearchText).filter(Boolean);
            if (haystack.includes(normalizedRaw)) {
                return option;
            }
            if (!partialMatch && haystack.some((entry) => entry.indexOf(normalizedRaw) >= 0)) {
                partialMatch = option;
            }
        }

        return partialMatch;
    }

    function syncContentStrategyAssociation($row) {
        const selectedCandidate = resolveContentStrategyPageCandidate($row.find('.aysa-agent8-content-strategy-page-search').val());
        const manualValue = String($row.find('.aysa-agent8-content-strategy-manual').val() || '').trim();
        const hiddenValue = selectedCandidate
            ? String(selectedCandidate.url || '').trim()
            : manualValue;
        $row.find('.aysa-agent8-content-strategy-association').val(hiddenValue);
        $row.find('.aysa-agent8-content-strategy-selected-url').text(hiddenValue || '-');
    }

    function openExternalUrl(url, title) {
        const targetUrl = String(url || '').trim();
        if (!targetUrl) {
            return;
        }
        const normalizedTitle = String(title || '').toLowerCase();
        const looksLikePdf = /\.pdf(?:$|[?#])/i.test(targetUrl) || normalizedTitle.indexOf('pdf') !== -1 || normalizedTitle.indexOf('download') !== -1;
        if (looksLikePdf) {
            window.location.href = targetUrl;
            return;
        }
        const link = document.createElement('a');
        link.href = targetUrl;
        link.target = '_blank';
        link.rel = 'noopener noreferrer';
        link.style.display = 'none';
        document.body.appendChild(link);
        link.click();
        window.setTimeout(function() {
            if (link.parentNode) {
                link.parentNode.removeChild(link);
            }
        }, 0);
    }

    function t(messages) {
        if (conversationLanguage === 'bg' && messages.bg) {
            return messages.bg;
        }
        if (conversationLanguage === 'ro' && messages.ro) {
            return messages.ro;
        }
        return messages.en || '';
    }

    function isSetupProjection(projection) {
        const type = String(projection && projection.type ? projection.type : '').toLowerCase();
        return [
            'activation',
            'integrations',
            'general',
            'objectives',
            'seo_settings',
            'competition',
            'tone_of_voice'
        ].indexOf(type) !== -1;
    }

    function setupControllerFromProjection(projection) {
        if (!projection || typeof projection !== 'object' || !projection.step_contract || typeof projection.step_contract !== 'object') {
            return null;
        }
        const contract = projection.step_contract;
        const hasAllowedActionKeys = Array.isArray(contract.allowed_action_keys);
        const allowed = hasAllowedActionKeys
            ? contract.allowed_action_keys.map((key) => String(key || '').trim()).filter(Boolean)
            : [];
        return {
            projection: projection,
            contract: contract,
            hasAllowedActionKeys: hasAllowedActionKeys,
            stepKey: String(contract.step_key || projection.type || ''),
            stepState: String(contract.step_state || contract.state || ''),
            qualityStatus: String(contract.quality_status || projection.quality_status || ''),
            missingFields: Array.isArray(contract.missing_fields) ? contract.missing_fields.map((field) => String(field || '').trim()).filter(Boolean) : [],
            nextMissingQuestion: String(contract.next_missing_question || projection.next_missing_question || '').trim(),
            primaryAction: String(contract.primary_action || '').trim(),
            nextAction: String(contract.next_action || '').trim(),
            allowedActionKeys: allowed.filter((key, index, all) => all.indexOf(key) === index)
        };
    }

    function currentSetupController() {
        const controller = isSetupProjection(currentProjection) ? setupControllerFromProjection(currentProjection) : null;
        return controller && controller.hasAllowedActionKeys ? controller : null;
    }

    function setupActionAllowed(controller, actionKey) {
        const key = String(actionKey || '').trim();
        return !!(controller && key && controller.allowedActionKeys.indexOf(key) !== -1);
    }

    function setupActionLabel(actionKey) {
        const ro = conversationLanguage === 'ro';
        const labels = {
            show_setup_activation: ro ? 'Activation' : 'Activation',
            validate_activation_key: ro ? 'Validează cheia' : 'Validate key',
            show_setup_google_connectivity: ro ? 'Google Integrations' : 'Google Integrations',
            connect_google: ro ? 'Conectează Google' : 'Connect Google',
            refresh_google_status: ro ? 'Refresh Google status' : 'Refresh Google status',
            save_google_property_selection: ro ? 'Salvează selecția Google' : 'Save Google selection',
            continue_without_google: ro ? 'Continuă fără Google' : 'Continue without Google',
            show_setup_business_profile: ro ? 'Business Profile' : 'Business Profile',
            run_general_autofill: ro ? 'Reanalizează site-ul pentru detaliile lipsă' : 'Reanalyze website for missing details',
            confirm_general_profile: ro ? 'Salvează profilul' : 'Save profile',
            update_general_field: ro ? 'Completează manual' : 'Fill manually',
            show_setup_objectives: ro ? 'Objectives' : 'Objectives',
            draft_objectives: ro ? 'Alege obiectivele' : 'Choose objectives',
	            save_objectives: ro ? 'Salvează obiectivele' : 'Save objectives',
	            show_setup_seo_settings: ro ? 'SEO Settings' : 'SEO Settings',
			            draft_seo_settings: 'Auto-generate SEO settings',
	            save_seo_settings: 'Save SEO settings',
	            show_setup_competition: ro ? 'Competition' : 'Competition',
            generate_competition_proposal: ro ? 'Generează propunerea' : 'Generate proposal',
            regenerate_competition_proposal: ro ? 'Refă propunerea' : 'Rebuild proposal',
            accept_competition_proposal: ro ? 'Acceptă propunerea' : 'Accept proposal',
            show_setup_tone_of_voice: ro ? 'Tone of Voice' : 'Tone of Voice',
            save_tone_of_voice: ro ? 'Salvează tonul' : 'Save tone',
            start_keyword_research: ro ? 'Pornește keyword research' : 'Start keyword research'
        };
        return labels[actionKey] || actionKey.replace(/_/g, ' ');
    }

    function setupActionsFromContract(projection) {
        const controller = setupControllerFromProjection(projection);
        if (!controller) {
            return [];
        }
        const actions = [];
        const addAction = function(actionKey, style, payload) {
            if (!setupActionAllowed(controller, actionKey)) {
                return;
            }
            actions.push({
                type: 'action',
                action_key: actionKey,
                label: setupActionLabel(actionKey),
                action_payload: payload && typeof payload === 'object' ? payload : undefined,
                style: style || 'default'
            });
        };

        if (controller.stepKey === 'business_profile' || String(projection.type || '') === 'general') {
            if (controller.missingFields.indexOf('support_phone') !== -1) {
                actions.push({
                    type: 'prompt_general_field',
                    label: conversationLanguage === 'ro' ? 'Adaugă numărul de telefon' : 'Add phone number',
                    message: conversationLanguage === 'ro' ? 'Scrie numărul public de contact, ex. 0722...' : 'Type the public phone number, e.g. 0722...',
                    action_payload: { field: 'support_phone' },
                    non_executing_prompt: true,
                    style: 'primary'
                });
            }
            addAction('run_general_autofill', 'primary');
            addAction('confirm_general_profile', 'primary');
            addAction('show_setup_seo_settings', 'default');
            addAction('show_setup_business_profile', 'default');
            return actions;
        }

	        if (controller.stepKey === 'objectives' || String(projection.type || '') === 'objectives') {
	            if (controller.missingFields.indexOf('objectives') !== -1) {
                actions.push({
                    type: 'message',
                    label: conversationLanguage === 'ro' ? 'Leads + sales' : 'Leads + sales',
                    message: conversationLanguage === 'ro' ? 'obiectivele mele sunt leads si sales' : 'my objectives are leads and sales',
                    non_executing_prompt: true,
                    style: 'primary'
                });
                actions.push({
                    type: 'message',
                    label: conversationLanguage === 'ro' ? 'Vizitatori + awareness' : 'Visitors + awareness',
                    message: conversationLanguage === 'ro' ? 'obiectivele mele sunt vizitatori si awareness' : 'my objectives are visitors and awareness',
                    non_executing_prompt: true,
                    style: 'default'
                });
            }
            addAction('save_objectives', 'primary');
            addAction('show_setup_seo_settings', 'default');
            addAction('show_setup_objectives', 'default');
	            return actions;
	        }

	        if (controller.stepKey === 'seo_settings' || String(projection.type || '') === 'seo_settings') {
	            const firstMissing = controller.missingFields.length ? String(controller.missingFields[0] || '') : '';
	            const promptOptions = {
	                targeted_search_engine: [
	                    { label: 'Google', message: 'google' },
	                    { label: 'Bing', message: 'bing' }
	                ],
	                targeted_country: [
	                    { label: conversationLanguage === 'ro' ? 'România' : 'Romania', message: 'romania' },
	                    { label: conversationLanguage === 'ro' ? 'Altă țară' : 'Another country', message: conversationLanguage === 'ro' ? 'vreau alta tara' : 'i want another country' }
	                ],
	                targeted_region: [
	                    { label: 'Ilfov', message: 'regiune ilfov' },
	                    { label: conversationLanguage === 'ro' ? 'București' : 'Bucharest', message: 'regiune bucuresti' }
	                ],
	                primary_language: [
	                    { label: conversationLanguage === 'ro' ? 'Română' : 'Romanian', message: 'romana' },
	                    { label: 'English', message: 'english' }
	                ],
	                update_frequency: [
	                    { label: conversationLanguage === 'ro' ? 'Lunar' : 'Monthly', message: 'lunar' },
	                    { label: conversationLanguage === 'ro' ? 'Săptămânal' : 'Weekly', message: 'saptamanal' }
	                ],
	                language_optimize: [
	                    { label: conversationLanguage === 'ro' ? 'Română' : 'Romanian', message: 'optimizare limba romana' },
	                    { label: 'English', message: 'optimize english' }
	                ],
	                device_optimize: [
	                    { label: 'Mobile', message: 'mobile' },
	                    { label: 'Desktop', message: 'desktop' },
	                    { label: conversationLanguage === 'ro' ? 'Toate' : 'All', message: 'all devices' }
	                ]
	            };
	            (promptOptions[firstMissing] || []).forEach((option) => {
	                actions.push({
	                    type: 'message',
	                    label: option.label,
	                    message: option.message,
	                    non_executing_prompt: true,
	                    style: 'default'
	                });
	            });
	            addAction('draft_seo_settings', 'primary');
	            addAction('save_seo_settings', 'primary');
	            addAction('show_setup_seo_settings', 'default');
	            return actions;
	        }

	        if (controller.stepKey === 'competition' || String(projection.type || '') === 'competition') {
            addAction('accept_competition_proposal', 'primary', {
                proposal_id: String(projection.proposal_id || ''),
                proposal_version: Number(projection.proposal_version || 0),
                seed_keywords: Array.isArray(projection.seed_keywords) ? projection.seed_keywords : [],
                keywords: Array.isArray(projection.keywords) ? projection.keywords : [],
                competitors: Array.isArray(projection.competitors) ? projection.competitors : [],
                excluded_competitors: Array.isArray(projection.excluded_competitors) ? projection.excluded_competitors : []
            });
            addAction('regenerate_competition_proposal', 'default');
            addAction('generate_competition_proposal', 'primary');
            addAction('show_setup_tone_of_voice', 'default');
            addAction('show_setup_competition', 'default');
            return actions;
        }

        controller.allowedActionKeys.forEach((actionKey) => {
            addAction(actionKey, actionKey.indexOf('show_') === 0 ? 'default' : 'primary');
        });
        return actions;
    }

    function renderChipRow(actions) {
        const list = Array.isArray(actions) ? actions : [];
        if (!list.length) {
            return '';
        }

        return '<div class="aysa-agent8-inline-chips">' + list.map((action) => {
            const label = escapeHtml(action.label || action.message || 'Continuă');
            const type = String(action.type || 'message');
            const url = encodeURIComponent(String(action.url || ''));
            const message = encodeURIComponent(String(action.message || action.label || ''));
            const actionKey = encodeURIComponent(String(action.action_key || ''));
            const actionPayload = action.action_payload && typeof action.action_payload === 'object'
                ? window.encodeURIComponent(JSON.stringify(action.action_payload))
                : '';
            const style = String(action.style || 'default');
            const disabledReason = String(action.disabled_reason || '');
            const isForegroundAction = !!(
                agent8ForegroundRequest
                && String(agent8ForegroundRequest.type || '') === 'action'
                && String(agent8ForegroundRequest.actionKey || '')
                && String(agent8ForegroundRequest.actionKey || '') === String(action.action_key || '')
            );
            const disabled = disabledReason || isForegroundAction
                ? ' disabled aria-disabled="true" title="' + escapeHtml(disabledReason || 'Agent8 is working on this action.') + '"'
                : '';
            return '<button type="button" class="aysa-agent8-chip aysa-agent8-suggestion aysa-agent8-suggestion-' + escapeHtml(style) + '" data-type="' + escapeHtml(type) + '" data-url="' + url + '" data-message="' + message + '" data-action-key="' + actionKey + '" data-action-payload="' + actionPayload + '"' + disabled + '>' + label + '</button>';
        }).join('') + '</div>';
    }

    function renderPersistentActionBar() {
        const list = Array.isArray(persistentActions) ? persistentActions : [];
        const $el = $('#aysa-agent8-persistent-actions');
        if (isTechnicalScopeActive() || !list.length) {
            $el.attr('hidden', 'hidden').html('');
            return;
        }
        const reviewType = currentUiCommand && typeof currentUiCommand === 'object' ? String(currentUiCommand.review_type || '') : '';
        const activeByUiType = {
            open_keyword_review: reviewType === 'found_keywords' ? 'show_found_keywords' : 'show_keyword_mapping',
            open_research_competitors_review: 'show_research_competitors',
            open_missing_pages_review: 'show_missing_pages',
            open_content_strategy_review: 'show_planned_content',
        };
        const activeByProjectionType = {
            found_keywords: 'show_found_keywords',
            research_competitors: 'show_research_competitors',
            missing_pages: 'show_missing_pages',
            planned_content: 'show_planned_content',
            content_strategy: 'show_planned_content',
            keyword_mapping: 'show_keyword_mapping',
        };
        const uiType = currentUiCommand && typeof currentUiCommand === 'object' ? String(currentUiCommand.type || '') : '';
        const projectionType = currentProjection && typeof currentProjection === 'object' ? String(currentProjection.type || '') : '';
        const activeActionKey = activeByUiType[uiType] || activeByProjectionType[projectionType] || '';
        const normalizedList = list.map((action) => {
            const row = Object.assign({}, action || {});
            if (activeActionKey && String(row.action_key || '') === activeActionKey) {
                row.style = 'primary';
            }
            return row;
        });
        $el.removeAttr('hidden').html(renderChipRow(normalizedList));
        sanitizeUnauthorizedActionButtons($el);
    }

    function renderContractIssueCard(issue) {
        if (!issue || issue.status !== 'invalid') {
            return '';
        }

        const details = issue.details && typeof issue.details === 'object' ? issue.details : {};
        const rows = [
            { label: 'Phase', value: issue.phase || '-' },
            { label: 'Step', value: issue.currentStep || '-' },
            { label: 'Conversation', value: issue.conversationId || '-' },
            { label: 'Issue', value: issue.issueCode || '-' }
        ].map((row) => {
            return '<div class="aysa-agent8-card-summary-row"><strong>' + escapeHtml(row.label) + ':</strong> ' + escapeHtml(String(row.value || '-')) + '</div>';
        }).join('');
        const detailRows = Object.keys(details).map((key) => {
            return '<div class="aysa-agent8-card-summary-row"><strong>' + escapeHtml(String(key)) + ':</strong> ' + escapeHtml(String(details[key] || '')) + '</div>';
        }).join('');

        return '' +
            '<div class="aysa-agent8-card aysa-agent8-card-contract-issue">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">Contract</p>' +
                    '<h3 class="aysa-agent8-card-title">Acțiune inconcludentă</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    '<div class="aysa-agent8-card-callout">Răspunsul backend este incomplet sau inconsistent pentru stadiul curent. UI-ul nu va inventa butoane pentru acest pas.</div>' +
                    '<div class="aysa-agent8-card-summary">' + rows + detailRows + '</div>' +
                '</div>' +
            '</div>';
    }

    const canonicalProposalMetadataKeys = [
        'proposal_id',
        'proposal_version',
        'step_key',
        'status',
        'quality_status',
        'source',
        'data',
        'quality_flags',
        'validation_warnings',
        'created_at',
        'updated_at',
        'accepted_at'
    ];

    function isPlainObject(value) {
        return !!(value && typeof value === 'object' && !Array.isArray(value));
    }

    function hasRenderableFields(value) {
        return isPlainObject(value) && Object.keys(value).some((key) => {
            return canonicalProposalMetadataKeys.indexOf(key) === -1 && value[key] != null && value[key] !== '';
        });
    }

    function getCanonicalProposalData(projection) {
        const proposal = projection && isPlainObject(projection.proposal) ? projection.proposal : {};
        if (hasRenderableFields(proposal.data)) {
            return proposal.data;
        }

        const flat = {};
        Object.keys(proposal).forEach((key) => {
            if (canonicalProposalMetadataKeys.indexOf(key) >= 0) {
                return;
            }
            flat[key] = proposal[key];
        });

        if (hasRenderableFields(flat)) {
            return flat;
        }

        return {};
    }

    function formatMainFieldValue(value) {
        if (Array.isArray(value)) {
            return value.map((item) => {
                if (item == null) {
                    return '';
                }
                return isPlainObject(item) ? '' : String(item);
            }).filter(Boolean).join(', ');
        }
        if (isPlainObject(value)) {
            return '';
        }
        return value == null ? '' : String(value);
    }

    function formatDebugFieldValue(value) {
        if (Array.isArray(value)) {
            return value.map((item) => isPlainObject(item) ? JSON.stringify(item) : String(item || '')).filter(Boolean).join(', ');
        }
        if (isPlainObject(value)) {
            return JSON.stringify(value);
        }
        return value == null ? '' : String(value);
    }

    function renderApprovalCard(request) {
        if (!request || !request.action_key) {
            return '';
        }
        const setupController = currentSetupController();
        if (setupController && !setupActionAllowed(setupController, String(request.action_key || ''))) {
            return '';
        }
        if (!setupController && currentAllowedActionsAuthoritative && currentAllowedActionKeys.indexOf(String(request.action_key || '')) === -1) {
            return '';
        }
        if (
            String(request.action_key || '') === 'accept_competition_proposal'
            && currentProjection
            && String(currentProjection.type || '') === 'competition'
            && String(currentProjection.quality_status || '') !== 'valid'
        ) {
            return '';
        }

        const summary = request.summary || {};
        const approvalPayload = request.approval_payload && typeof request.approval_payload === 'object'
            ? request.approval_payload
            : {};
        const proposalId = String(summary.proposal_id || approvalPayload.proposal_id || '');
        const proposalVersion = String(summary.proposal_version || approvalPayload.proposal_version || '');
        const rows = Object.keys(summary).map((key) => {
            if (key === 'proposal_id' || key === 'proposal_version') {
                return '';
            }
            const raw = Array.isArray(summary[key]) ? summary[key].join(', ') : String(summary[key] || '');
            if (!raw) {
                return '';
            }
            return '<div class="aysa-agent8-card-summary-row"><strong>' + escapeHtml(key.replace(/_/g, ' ')) + ':</strong> ' + escapeHtml(raw) + '</div>';
        }).join('');
        const proposalMeta = proposalId || proposalVersion
            ? '<div class="aysa-agent8-card-summary-row aysa-agent8-card-meta"><small>' +
                (proposalId ? '<span><strong>proposal_id:</strong> ' + escapeHtml(proposalId) + '</span>' : '') +
                (proposalId && proposalVersion ? ' · ' : '') +
                (proposalVersion ? '<span><strong>proposal_version:</strong> ' + escapeHtml(proposalVersion) + '</span>' : '') +
            '</small></div>'
            : '';

        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">Approval</p>' +
                    '<h3 class="aysa-agent8-card-title">' + escapeHtml(request.title || 'Confirm action') + '</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    '<div>' + escapeHtml(request.message || '') + '</div>' +
                    '<div class="aysa-agent8-card-summary">' + rows + proposalMeta + '</div>' +
                    '<div class="aysa-agent8-card-actions">' +
                        '<button type="button" class="button button-secondary" id="aysa-agent8-decline">' + escapeHtml(request.cancel_label || 'Nu acum') + '</button>' +
                        '<button type="button" class="button button-primary" id="aysa-agent8-approve">' + escapeHtml(request.confirmation_label || 'Confirmă') + '</button>' +
                    '</div>' +
                '</div>' +
            '</div>';
    }

    function setupFieldLabel(field) {
        const ro = conversationLanguage === 'ro';
        const labels = {
            targeted_search_engine: ro ? 'motor de căutare' : 'search engine',
            targeted_country: ro ? 'țară' : 'country',
            targeted_region: ro ? 'regiune' : 'region',
            targeted_city: ro ? 'oraș' : 'city',
            primary_language: ro ? 'limbă conținut' : 'content language',
            update_frequency: ro ? 'frecvență actualizare' : 'update frequency',
            language_optimize: ro ? 'limbă optimizare' : 'SEO language',
            device_optimize: ro ? 'device' : 'device',
            support_phone: ro ? 'telefon public' : 'public phone'
        };
        return labels[field] || String(field || '').replace(/_/g, ' ');
    }

    function setupQuestionForField(field) {
        const ro = conversationLanguage === 'ro';
        const questions = {
            targeted_search_engine: ro ? 'Pentru ce motor de căutare vrei optimizarea?' : 'Which search engine should we optimize for?',
            targeted_country: ro ? 'Pentru ce țară vrei optimizarea?' : 'Which country should we target?',
            targeted_region: ro ? 'Pentru ce regiune vrei optimizarea?' : 'Which region should we target?',
            targeted_city: ro ? 'Pentru ce oraș vrei optimizarea?' : 'Which city should we target?',
            primary_language: ro ? 'În ce limbă să fie conținutul?' : 'What language should the content use?',
            update_frequency: ro ? 'Cât de des vrei să actualizăm recomandările SEO?' : 'How often should we update SEO recommendations?',
            language_optimize: ro ? 'Pentru ce limbă vrei optimizarea SEO?' : 'Which language should we optimize SEO for?',
            device_optimize: ro ? 'Pe ce device vrei să optimizăm?' : 'Which device should we optimize for?'
        };
        return questions[field] || '';
    }

    function renderSetupStepMeta(projection) {
        const contract = projection && projection.step_contract && typeof projection.step_contract === 'object'
            ? projection.step_contract
            : null;
        if (!contract) {
            return '';
        }
        const stateLabelMap = {
            draft_empty: conversationLanguage === 'ro' ? 'Lipsesc date' : 'Missing data',
            draft_partial: conversationLanguage === 'ro' ? 'Draft parțial' : 'Partial draft',
            review_ready: conversationLanguage === 'ro' ? 'Gata de salvare' : 'Ready to save',
            saved: conversationLanguage === 'ro' ? 'Salvat' : 'Saved',
            invalid_stale: conversationLanguage === 'ro' ? 'Propunere invalidă' : 'Invalid proposal',
            partial_needs_competitors: conversationLanguage === 'ro' ? 'Parțial: lipsesc competitori validați' : 'Partial: needs validated competitors',
            needs_clarification: conversationLanguage === 'ro' ? 'Are nevoie de clarificare' : 'Needs clarification'
        };
        const stepState = String(contract.step_state || contract.state || '');
        const missingFields = Array.isArray(contract.missing_fields) ? contract.missing_fields : [];
        let nextQuestion = String(contract.next_missing_question || projection.next_missing_question || '').trim();
        if (!nextQuestion && String(projection && projection.type || '') === 'seo_settings' && missingFields.length) {
            nextQuestion = setupQuestionForField(String(missingFields[0] || ''));
        }
        const nextEnabled = !!contract.next_action_enabled;
        const explicitNextLabel = String(contract.next_label || '').trim();
        const nextLabel = explicitNextLabel || (nextEnabled
            ? (conversationLanguage === 'ro' ? 'Pasul următor este activ.' : 'Next step is active.')
            : (conversationLanguage === 'ro' ? 'Pasul următor rămâne blocat până salvezi pasul curent.' : 'Next step stays blocked until you save the current step.'));
        return '' +
            '<div class="aysa-agent8-card-summary-row"><strong>' + escapeHtml(conversationLanguage === 'ro' ? 'Stare pas' : 'Step state') + ':</strong> ' + escapeHtml(stateLabelMap[stepState] || stepState || '-') + '</div>' +
            (missingFields.length ? '<div class="aysa-agent8-card-callout"><strong>' + escapeHtml(conversationLanguage === 'ro' ? 'Lipsește' : 'Missing') + ':</strong> ' + escapeHtml(missingFields.map(setupFieldLabel).join(', ')) + '</div>' : '') +
            (nextQuestion ? '<div class="aysa-agent8-card-callout"><strong>' + escapeHtml(conversationLanguage === 'ro' ? 'Următorul câmp' : 'Next needed') + ':</strong> ' + escapeHtml(nextQuestion) + '</div>' : '') +
            '<div class="aysa-agent8-card-summary-row"><em>' + escapeHtml(nextLabel) + '</em></div>';
    }

    function renderGeneralProjection(projection) {
        const proposal = projection && projection.proposal && typeof projection.proposal === 'object' ? projection.proposal : {};
        const proposalData = getCanonicalProposalData(projection);
        const debugKeys = ['source', 'field_confidence', 'validation_warnings', 'missing_or_uncertain_fields'];
        const rows = Object.keys(proposalData).map((key) => {
            if (debugKeys.indexOf(key) >= 0) {
                return '';
            }
            const value = formatMainFieldValue(proposalData[key]);
            if (!value) {
                return '';
            }
            return '<div><strong>' + escapeHtml(key.replace(/_/g, ' ')) + ':</strong> ' + escapeHtml(value) + '</div>';
        }).join('');
        const debugRows = debugKeys.map((key) => {
            const value = formatDebugFieldValue(proposal[key] || projection[key] || '');
            if (!value) {
                return '';
            }
            return '<div><strong>' + escapeHtml(key.replace(/_/g, ' ')) + ':</strong> ' + escapeHtml(value) + '</div>';
        }).join('');
        const missingFields = Array.isArray(projection.missing_fields) ? projection.missing_fields : [];
        const missingBlock = missingFields.length
            ? '<div class="aysa-agent8-card-callout"><strong>Missing required fields:</strong> ' + escapeHtml(missingFields.join(', ')) + '</div>'
            : '';
        const uncertainFields = Array.isArray(projection.uncertain_fields) ? projection.uncertain_fields : [];
        const uncertainBlock = uncertainFields.length
            ? '<div class="aysa-agent8-card-callout"><strong>' + escapeHtml(conversationLanguage === 'ro' ? 'Opțional / de verificat' : 'Optional / needs confirmation') + ':</strong> ' + escapeHtml(uncertainFields.join(', ')) + '</div>'
            : '';
        const debugBlock = debugRows
            ? '<details class="aysa-agent8-card-summary-row"><summary>' + escapeHtml(conversationLanguage === 'ro' ? 'Detalii debug' : 'Debug details') + '</summary><div class="aysa-agent8-card-grid">' + debugRows + '</div></details>'
            : '';

        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">General Details</p>' +
                    '<h3 class="aysa-agent8-card-title">Business profile proposal</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    missingBlock +
                    renderSetupStepMeta(projection) +
                    uncertainBlock +
                    '<div class="aysa-agent8-card-grid">' + rows + '</div>' +
                    debugBlock +
                '</div>' +
            '</div>';
    }

    function renderIntegrationProjection(projection) {
        const google = projection && projection.google && typeof projection.google === 'object' ? projection.google : {};
        const rawStatus = String(projection && projection.status ? projection.status : '');
        const selectedGsc = String(google.selected_gsc_site || '');
        const selectedGa4 = String(google.selected_ga4_property || '');
        const suggestedGsc = String(google.suggested_gsc_site || '');
        const suggestedGa4 = String(google.suggested_ga4_property || '');
        const effectiveGsc = selectedGsc || suggestedGsc;
        const effectiveGa4 = selectedGa4 || suggestedGa4;
        let statusLabel = rawStatus || '-';
        let hint = '';
        if (rawStatus === 'connected') {
            statusLabel = 'Conectat';
            hint = 'Google este conectat și putem continua cu proprietățile disponibile.';
        } else if (rawStatus === 'oauth_ready') {
            statusLabel = 'Autorizare în curs';
            hint = 'Autorizarea Google a fost pornită. Dacă ai revenit din OAuth, folosește refresh sau continuă selecția proprietăților.';
        } else if (rawStatus === 'disconnected') {
            statusLabel = 'Neconectat';
            hint = 'Google nu este conectat încă pentru proiectul acesta.';
        } else if (rawStatus === 'skipped') {
            statusLabel = 'Sărit';
            hint = 'Ai ales să continui fără Google.';
        }
        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">Integrations</p>' +
                    '<h3 class="aysa-agent8-card-title">Google status</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    renderSetupStepMeta(projection) +
                    (hint ? '<div class="aysa-agent8-card-callout">' + escapeHtml(hint) + '</div>' : '') +
                    '<div class="aysa-agent8-card-grid">' +
                        '<div><strong>Email:</strong> ' + escapeHtml(String(google.email || '')) + '</div>' +
                        '<div><strong>Status:</strong> ' + escapeHtml(statusLabel) + '</div>' +
                        '<div><strong>GSC sites:</strong> ' + escapeHtml(String(google.gsc_sites_count || 0)) + '</div>' +
                        '<div><strong>GA4 properties:</strong> ' + escapeHtml(String(google.ga4_properties_count || 0)) + '</div>' +
                        '<div><strong>GSC folosit:</strong> ' + escapeHtml(effectiveGsc) + '</div>' +
                        '<div><strong>GA4 folosit:</strong> ' + escapeHtml(effectiveGa4) + '</div>' +
                        '<div><strong>GSC selectat:</strong> ' + escapeHtml(selectedGsc) + '</div>' +
                        '<div><strong>GA4 selectat:</strong> ' + escapeHtml(selectedGa4) + '</div>' +
                        '<div><strong>GSC sugerat:</strong> ' + escapeHtml(suggestedGsc) + '</div>' +
                        '<div><strong>GA4 sugerat:</strong> ' + escapeHtml(suggestedGa4) + '</div>' +
                    '</div>' +
                '</div>' +
            '</div>';
    }

    function renderActivationProjection(projection) {
        const verified = !!(projection && projection.verified);
        const projectId = Number(projection && projection.project_id ? projection.project_id : 0);
        const canonicalProjectId = Number(projection && projection.canonical_project_id ? projection.canonical_project_id : 0);
        const planCode = String(projection && projection.plan_code ? projection.plan_code : '');
        const validatedAt = String(projection && projection.validated_at ? projection.validated_at : '');

        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">Activation</p>' +
                    '<h3 class="aysa-agent8-card-title">Activation status</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    renderSetupStepMeta(projection) +
                    '<div class="aysa-agent8-card-grid">' +
                        '<div><strong>Status:</strong> ' + escapeHtml(verified ? 'validated' : 'not validated') + '</div>' +
                        '<div><strong>Project ID:</strong> ' + escapeHtml(projectId ? String(projectId) : '-') + '</div>' +
                        '<div><strong>Canonical Project ID:</strong> ' + escapeHtml(canonicalProjectId ? String(canonicalProjectId) : '-') + '</div>' +
                        '<div><strong>Plan:</strong> ' + escapeHtml(planCode || '-') + '</div>' +
                        '<div><strong>Validated at:</strong> ' + escapeHtml(validatedAt || '-') + '</div>' +
                    '</div>' +
                '</div>' +
            '</div>';
    }

    function competitionNormalizedState(value) {
        return String(value == null ? '' : value).trim().toLowerCase();
    }

    function competitionAcceptedState(value) {
        const state = competitionNormalizedState(value);
        return state === 'accepted' || state === 'approved' || state === 'saved';
    }

    function competitionStepContractState(projection) {
        const contract = projection && projection.step_contract && typeof projection.step_contract === 'object'
            ? projection.step_contract
            : {};
        return competitionNormalizedState(contract.state || contract.step_state || projection.state || projection.step_state || '');
    }

    function competitionProjectionAccepted(projection) {
        const stepState = competitionStepContractState(projection);
        return stepState ? competitionAcceptedState(stepState) : false;
    }

    function renderCompetitionProjection(projection) {
        const keywords = Array.isArray(projection.keywords)
            ? projection.keywords.map((item) => String(item || '').trim()).filter((item) => item && item !== '0')
            : [];
        const competitors = Array.isArray(projection.competitors)
            ? projection.competitors.map((item) => String(item || '').trim()).filter((item) => item && item !== '0')
            : [];
        const accepted = competitionProjectionAccepted(projection);
        const stepState = competitionStepContractState(projection);
        const proposalUnavailable = !accepted && (keywords.length === 0 && competitors.length === 0 || ['invalid_stale', 'needs_clarification'].indexOf(stepState) !== -1);
        const renderList = function(items) {
            if (!items.length) {
                return '<div>-</div>';
            }
            return '<ul>' + items.map((item) => '<li>' + escapeHtml(String(item || '')) + '</li>').join('') + '</ul>';
        };

        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">Competition</p>' +
                    '<h3 class="aysa-agent8-card-title">Seed keywords and competitors</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    renderSetupStepMeta(projection) +
                    (proposalUnavailable
                        ? '<div class="aysa-agent8-card-callout"><strong>' + escapeHtml(conversationLanguage === 'ro' ? 'Propunere indisponibilă' : 'Proposal unavailable') + '</strong></div>'
                        : '<div class="aysa-agent8-card-grid">' +
                            '<div><strong>Status:</strong> ' + escapeHtml(accepted ? 'accepted' : 'proposal') + '</div>' +
                            '<div><strong>Seed keywords:</strong>' + renderList(keywords) + '</div>' +
                            '<div><strong>Competitors:</strong>' + renderList(competitors) + '</div>' +
                        '</div>') +
                '</div>' +
            '</div>';
    }

    function renderObjectivesProjection(projection) {
        const objectives = Array.isArray(projection.objectives) ? projection.objectives : [];
        const customObjectives = String(projection.custom_objectives || '');
        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">Objectives</p>' +
                    '<h3 class="aysa-agent8-card-title">Obiective salvate</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    renderSetupStepMeta(projection) +
                    '<div class="aysa-agent8-card-grid">' +
                        '<div><strong>Obiective:</strong> ' + escapeHtml(objectives.length ? objectives.join(', ') : '-') + '</div>' +
                        (customObjectives ? '<div><strong>Obiective custom:</strong> ' + escapeHtml(customObjectives) + '</div>' : '') +
                    '</div>' +
                '</div>' +
            '</div>';
    }

    function renderSeoSettingsProjection(projection) {
        const proposal = projection && isPlainObject(projection.proposal) ? projection.proposal : {};
        const proposalData = isPlainObject(proposal.data) ? proposal.data : {};
        const proposalDataSettings = isPlainObject(proposalData.seo_settings) ? proposalData.seo_settings : proposalData;
        const proposalSettings = isPlainObject(proposal.seo_settings) ? proposal.seo_settings : {};
        const legacySettings = projection && isPlainObject(projection.seo_settings) ? projection.seo_settings : {};
        const flatProjectionSettings = {};
        [
            'targeted_search_engine',
            'targeted_country',
            'targeted_region',
            'targeted_city',
            'primary_language',
            'update_frequency',
            'language_optimize',
            'device_optimize'
        ].forEach((key) => {
            if (projection && projection[key] != null) {
                flatProjectionSettings[key] = projection[key];
            }
        });
	        const settings = Object.assign({}, flatProjectionSettings, legacySettings, proposalSettings, proposalDataSettings);
	        const hasSavedSettings = !!(projection && projection.saved);
	        const guidance = conversationLanguage === 'ro'
	            ? 'Aceste setări controlează piața SEO: unde optimizăm, în ce limbă, cât de des actualizăm recomandările și pentru ce device. Poți genera automat ce se poate deduce din site sau poți alege valorile manual.'
	            : 'These settings define the SEO target: where we optimize, language, update cadence, and device. You can auto-generate what can be inferred from the site or choose values manually.';
	        return '' +
	            '<div class="aysa-agent8-card">' +
	                '<div class="aysa-agent8-card-header">' +
	                    '<p class="aysa-agent8-card-kicker">SEO Settings</p>' +
	                    '<h3 class="aysa-agent8-card-title">' + escapeHtml(hasSavedSettings ? 'Setări SEO salvate' : 'Setări SEO curente') + '</h3>' +
	                '</div>' +
	                '<div class="aysa-agent8-card-body">' +
	                    '<p class="aysa-agent8-card-muted">' + escapeHtml(guidance) + '</p>' +
	                    renderSetupStepMeta(projection) +
                    '<div class="aysa-agent8-card-grid">' +
                        '<div><strong>Motor:</strong> ' + escapeHtml(String(settings.targeted_search_engine || '-')) + '</div>' +
                        '<div><strong>Țară:</strong> ' + escapeHtml(String(settings.targeted_country || '-')) + '</div>' +
                        '<div><strong>Regiune:</strong> ' + escapeHtml(String(settings.targeted_region || '-')) + '</div>' +
                        '<div><strong>Oraș:</strong> ' + escapeHtml(String(settings.targeted_city || '-')) + '</div>' +
                        '<div><strong>Limbă:</strong> ' + escapeHtml(String(settings.primary_language || '-')) + '</div>' +
                        '<div><strong>Frecvență:</strong> ' + escapeHtml(String(settings.update_frequency || '-')) + '</div>' +
                        '<div><strong>Optimizare limbă:</strong> ' + escapeHtml(String(settings.language_optimize || '-')) + '</div>' +
                        '<div><strong>Device:</strong> ' + escapeHtml(String(settings.device_optimize || '-')) + '</div>' +
                    '</div>' +
                '</div>' +
            '</div>';
    }

    function renderToneProjection(projection) {
        const tone = String(projection.tone || '');
        const toneSaved = !!(projection && projection.saved) || tone.trim() !== '';
        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">Tone Of Voice</p>' +
                    '<h3 class="aysa-agent8-card-title">' + escapeHtml(toneSaved ? 'Ton salvat' : 'Ton curent') + '</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    renderSetupStepMeta(projection) +
                    '<div class="aysa-agent8-card-grid">' +
                        '<div><strong>Ton:</strong> ' + escapeHtml(tone || '-') + '</div>' +
                    '</div>' +
                '</div>' +
            '</div>';
    }

    function renderKeywordMappingProjection(projection) {
        const summary = projection && projection.summary && typeof projection.summary === 'object' ? projection.summary : {};
        const ro = conversationLanguage === 'ro';
        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">Keyword Mapping</p>' +
                    '<h3 class="aysa-agent8-card-title">' + escapeHtml(ro ? 'Rezumat simplu' : 'Simple Summary') + '</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    '<div class="aysa-agent8-card-grid">' +
                        '<div><strong>' + escapeHtml(ro ? 'Teme' : 'Themes') + ':</strong> ' + escapeHtml(String(summary.clusters_total || 0)) + '</div>' +
                        '<div><strong>' + escapeHtml(ro ? 'Keyworduri active' : 'Active Keywords') + ':</strong> ' + escapeHtml(String(summary.keywords_kept || 0)) + '</div>' +
                        '<div><strong>' + escapeHtml(ro ? 'Mapate' : 'Mapped') + ':</strong> ' + escapeHtml(String(summary.mapped || 0)) + '</div>' +
                        '<div><strong>' + escapeHtml(ro ? 'De revizuit' : 'For Review') + ':</strong> ' + escapeHtml(String(summary.review || 0)) + '</div>' +
                        '<div><strong>' + escapeHtml(ro ? 'Nemapate' : 'Unmapped') + ':</strong> ' + escapeHtml(String(summary.not_mapped || 0)) + '</div>' +
                    '</div>' +
                '</div>' +
            '</div>';
    }

    function renderMissingPagesProjection(projection) {
        const summary = projection && projection.summary && typeof projection.summary === 'object' ? projection.summary : {};
        const ro = conversationLanguage === 'ro';
        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">Missing Pages</p>' +
                    '<h3 class="aysa-agent8-card-title">' + escapeHtml(ro ? 'Rezumat simplu' : 'Simple Summary') + '</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    '<div class="aysa-agent8-card-grid">' +
                        '<div><strong>' + escapeHtml(ro ? 'Grupuri' : 'Groups') + ':</strong> ' + escapeHtml(String(summary.groups || 0)) + '</div>' +
                        '<div><strong>' + escapeHtml(ro ? 'Oportunități' : 'Opportunities') + ':</strong> ' + escapeHtml(String(summary.items || 0)) + '</div>' +
                    '</div>' +
                '</div>' +
            '</div>';
    }

    function renderContentStrategyProjection(projection) {
        const summary = projection && projection.summary && typeof projection.summary === 'object' ? projection.summary : {};
        const ro = conversationLanguage === 'ro';
        const statuses = summary.statuses && typeof summary.statuses === 'object' ? summary.statuses : {};
        const next = summary.next && typeof summary.next === 'object' ? summary.next : null;
        const statusRows = Object.keys(statuses).map((key) => {
            return '<div class="aysa-agent8-card-summary-row"><strong>' + escapeHtml(String(key)) + ':</strong> ' + escapeHtml(String(statuses[key] || 0)) + '</div>';
        }).join('');
        const nextBlock = next
            ? '<div class="aysa-agent8-card-callout"><strong>' + escapeHtml(ro ? 'Următorul item' : 'Next Item') + ':</strong> ' + escapeHtml(String(next.title || ('#' + String(next.id || '')))) + (next.scheduled_for ? ' · ' + escapeHtml(String(next.scheduled_for)) : '') + '</div>'
            : '';
        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">Content Strategy</p>' +
                    '<h3 class="aysa-agent8-card-title">' + escapeHtml(ro ? 'Rezumat simplu' : 'Simple Summary') + '</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    '<div class="aysa-agent8-card-grid">' +
                        '<div><strong>' + escapeHtml(ro ? 'Total itemi' : 'Total Items') + ':</strong> ' + escapeHtml(String(summary.items || 0)) + '</div>' +
                    '</div>' +
                    nextBlock +
                    '<div class="aysa-agent8-card-summary">' + statusRows + '</div>' +
                '</div>' +
            '</div>';
    }

    function renderPublishingCalendarProjection(projection) {
        const summary = projection && projection.summary && typeof projection.summary === 'object' ? projection.summary : {};
        const ro = conversationLanguage === 'ro';
        const today = summary.today && typeof summary.today === 'object' ? summary.today : {};
        const scheduled = Array.isArray(today.scheduled) ? today.scheduled.length : 0;
        const published = Array.isArray(today.published) ? today.published.length : 0;
        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">Publishing Calendar</p>' +
                    '<h3 class="aysa-agent8-card-title">' + escapeHtml(ro ? 'Rezumat simplu' : 'Simple Summary') + '</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    '<div class="aysa-agent8-card-grid">' +
                        '<div><strong>' + escapeHtml(ro ? 'Evenimente' : 'Events') + ':</strong> ' + escapeHtml(String(summary.events || 0)) + '</div>' +
                        '<div><strong>' + escapeHtml(ro ? 'Azi programate' : 'Scheduled Today') + ':</strong> ' + escapeHtml(String(scheduled)) + '</div>' +
                        '<div><strong>' + escapeHtml(ro ? 'Azi publicate' : 'Published Today') + ':</strong> ' + escapeHtml(String(published)) + '</div>' +
                    '</div>' +
                '</div>' +
            '</div>';
    }

    function renderPlanMutationProjection(projection) {
        const summary = projection && projection.summary && typeof projection.summary === 'object' ? projection.summary : {};
        const ro = conversationLanguage === 'ro';
        const contentStrategy = projection && projection.content_strategy && typeof projection.content_strategy === 'object'
            ? projection.content_strategy
            : {};
        const publishingCalendar = projection && projection.publishing_calendar && typeof projection.publishing_calendar === 'object'
            ? projection.publishing_calendar
            : {};
        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">Send To Plan</p>' +
                    '<h3 class="aysa-agent8-card-title">' + escapeHtml(ro ? 'Rezultat actualizat' : 'Updated Result') + '</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    '<div class="aysa-agent8-card-grid">' +
                        '<div><strong>' + escapeHtml(ro ? 'Adăugate' : 'Added') + ':</strong> ' + escapeHtml(String(summary.added || 0)) + '</div>' +
                        '<div><strong>' + escapeHtml(ro ? 'Existente deja' : 'Already Existing') + ':</strong> ' + escapeHtml(String(summary.existing || 0)) + '</div>' +
                        '<div><strong>' + escapeHtml(ro ? 'Erori' : 'Errors') + ':</strong> ' + escapeHtml(String(summary.errors || 0)) + '</div>' +
                        '<div><strong>' + escapeHtml(ro ? 'Total în Content Strategy' : 'Total in Content Strategy') + ':</strong> ' + escapeHtml(String(contentStrategy.items || 0)) + '</div>' +
                        '<div><strong>' + escapeHtml(ro ? 'Evenimente calendar' : 'Calendar Events') + ':</strong> ' + escapeHtml(String(publishingCalendar.events || 0)) + '</div>' +
                    '</div>' +
                '</div>' +
            '</div>';
    }

    function humanizeSlug(value) {
        const raw = String(value || '').trim();
        if (!raw) {
            return '-';
        }
        return raw.replace(/[_-]+/g, ' ').replace(/\b\w/g, function(ch) {
            return ch.toUpperCase();
        });
    }

    function isTechnicalScopeActive() {
        if (currentModuleSlug === 'technical_seo') {
            return true;
        }
        if (currentModuleSlug && currentModuleSlug !== 'technical_seo') {
            return false;
        }
        const projectionType = currentProjection && typeof currentProjection === 'object' ? String(currentProjection.type || '') : '';
        const uiType = currentUiCommand && typeof currentUiCommand === 'object' ? String(currentUiCommand.type || '') : '';
        return projectionType.indexOf('technical_') === 0 || uiType.indexOf('open_technical_') === 0;
    }

    function technicalModuleDefinitions() {
        return [
            { key: 'site_audit', label: 'Site Audit', actionKey: 'show_technical_site_audit' },
            { key: 'pagespeed', label: 'PageSpeed', actionKey: 'show_technical_pagespeed' },
            { key: 'schema', label: 'Schema', actionKey: 'show_technical_schema' },
            { key: 'redirects', label: 'Redirects / 404', actionKey: 'show_technical_redirects_review' },
            { key: 'sitemap_robots', label: 'Sitemap + Robots', actionKey: 'show_technical_sitemap_robots' },
            { key: 'internal_linking', label: 'Internal Linking Workspace (local)', actionKey: 'show_technical_internal_linking' }
        ];
    }

    function normalizeTechnicalStatus(value) {
        const raw = String(value || '').trim().toLowerCase();
        if (!raw) {
            return 'idle';
        }
        if (raw === 'completed' || raw === 'succeeded' || raw === 'success') {
            return 'ready';
        }
        if (raw === 'requested') {
            return 'queued';
        }
        if (raw === 'review' || raw === 'needs_review') {
            return 'review_required';
        }
        return raw;
    }

    function technicalStatusLabel(status) {
        const normalized = normalizeTechnicalStatus(status);
        return t({
            ro: ({
                idle: 'Idle',
                queued: 'Queued',
                running: 'Running',
                ready: 'Ready',
                review_required: 'Review',
                applied: 'Applied',
                failed: 'Failed'
            })[normalized] || humanizeSlug(normalized),
            bg: humanizeSlug(normalized),
            en: ({
                idle: 'Idle',
                queued: 'Queued',
                running: 'Running',
                ready: 'Ready',
                review_required: 'Review',
                applied: 'Applied',
                failed: 'Failed'
            })[normalized] || humanizeSlug(normalized)
        });
    }

    function deriveTechnicalSummaryPatch(actionResult, projection) {
        const actionKey = String(actionResult && actionResult.action_key ? actionResult.action_key : '');
        const summary = actionResult && actionResult.summary && typeof actionResult.summary === 'object'
            ? actionResult.summary
            : (projection && projection.summary && typeof projection.summary === 'object' ? projection.summary : {});
        if (!summary || typeof summary !== 'object') {
            return null;
        }

        if (projection && (projection.type === 'technical_overview' || projection.type === 'technical_optimization_guide')) {
            return summary;
        }

        const patch = {};
        if (actionKey === 'show_technical_site_audit' || actionKey === 'refresh_technical_site_audit') {
            patch.site_audit_status = summary.status || patch.site_audit_status;
            patch.site_audit_issues = summary.issues || 0;
            patch.site_audit_ready = !!(actionResult && actionResult.ui_command);
        } else if (actionKey === 'show_technical_pagespeed' || actionKey === 'refresh_technical_pagespeed') {
            patch.pagespeed_status = summary.status || patch.pagespeed_status;
            patch.pagespeed_overall_score = summary.overall_score || 0;
            patch.pagespeed_ready = !!(actionResult && actionResult.ui_command);
        } else if (actionKey === 'show_technical_sitemap_robots' || actionKey === 'refresh_technical_sitemap_robots') {
            patch.sitemap_robots_status = summary.status || patch.sitemap_robots_status;
            patch.sitemap_robots_checks = summary.checks || 0;
            patch.sitemap_robots_errors = summary.errors || 0;
            patch.sitemap_robots_ready = !!(actionResult && actionResult.ui_command);
        } else if (actionKey === 'show_technical_redirects_review' || actionKey === 'refresh_technical_redirects_review') {
            patch.redirects_status = summary.status || patch.redirects_status;
            patch.redirect_ready = summary.redirect_candidates || summary.redirect_ready || 0;
            patch.gone_candidates = summary.gone_candidates || 0;
            patch.redirects_ready = !!(actionResult && actionResult.ui_command);
        } else if (actionKey === 'show_technical_schema' || actionKey === 'refresh_technical_schema') {
            patch.schema_status = summary.status || patch.schema_status;
            patch.schema_pages = summary.total_pages || 0;
            patch.schema_ready = !!(actionResult && actionResult.ui_command);
        } else if (actionKey === 'show_technical_internal_linking' || actionKey === 'refresh_technical_internal_linking') {
            patch.internal_linking_status = summary.status || patch.internal_linking_status;
            patch.internal_linking_keywords = summary.keywords || 0;
            patch.internal_linking_preview_links = summary.preview_links_to_add || 0;
            patch.internal_linking_ready = !!(actionResult && actionResult.ui_command);
        }

        return Object.keys(patch).length ? patch : null;
    }

    function summarizeTechnicalMeta(moduleKey, status, summary, technicalState) {
        const normalizedStatus = normalizeTechnicalStatus(status);
        const moduleSummary = summary && typeof summary === 'object' ? summary : {};
        const stateEntry = technicalState && technicalState[moduleKey] && typeof technicalState[moduleKey] === 'object'
            ? technicalState[moduleKey]
            : {};
        if (moduleKey === 'site_audit') {
            return moduleSummary.site_audit_issues > 0
                ? String(moduleSummary.site_audit_issues) + ' ' + t({ ro: 'probleme', bg: 'issues', en: 'issues' })
                : (normalizedStatus === 'running' ? t({ ro: 'scanare în curs', bg: 'running', en: 'crawl running' }) : t({ ro: 'fără snapshot', bg: 'no snapshot', en: 'no snapshot' }));
        }
        if (moduleKey === 'pagespeed') {
            return moduleSummary.pagespeed_overall_score > 0
                ? t({ ro: 'scor ', bg: 'score ', en: 'score ' }) + String(moduleSummary.pagespeed_overall_score)
                : (normalizedStatus === 'running' ? t({ ro: 'test în curs', bg: 'running', en: 'test running' }) : t({ ro: 'fără snapshot', bg: 'no snapshot', en: 'no snapshot' }));
        }
        if (moduleKey === 'sitemap_robots') {
            return moduleSummary.sitemap_robots_errors > 0
                ? String(moduleSummary.sitemap_robots_errors) + ' ' + t({ ro: 'probleme', bg: 'issues', en: 'issues' })
                : (moduleSummary.sitemap_robots_checks > 0 ? String(moduleSummary.sitemap_robots_checks) + ' ' + t({ ro: 'checks', bg: 'checks', en: 'checks' }) : t({ ro: 'fără snapshot', bg: 'no snapshot', en: 'no snapshot' }));
        }
        if (moduleKey === 'redirects') {
            if ((moduleSummary.redirect_ready || 0) > 0) {
                return String(moduleSummary.redirect_ready) + ' ' + t({ ro: 'fixuri gata', bg: 'ready', en: 'ready fixes' });
            }
            if ((moduleSummary.redirect_review_required || 0) > 0 || (moduleSummary.redirect_conflicts || 0) > 0) {
                return String((moduleSummary.redirect_review_required || 0) + (moduleSummary.redirect_conflicts || 0)) + ' ' + t({ ro: 'de revizuit', bg: 'review', en: 'for review' });
            }
            return normalizedStatus === 'running' ? t({ ro: 'analiză în curs', bg: 'running', en: 'analysis running' }) : t({ ro: 'fără snapshot', bg: 'no snapshot', en: 'no snapshot' });
        }
        if (moduleKey === 'schema') {
            return moduleSummary.schema_pages > 0
                ? String(moduleSummary.schema_pages) + ' ' + t({ ro: 'pagini', bg: 'pages', en: 'pages' })
                : (normalizedStatus === 'running' ? t({ ro: 'scanare în curs', bg: 'running', en: 'scan running' }) : t({ ro: 'fără snapshot', bg: 'no snapshot', en: 'no snapshot' }));
        }
        if (moduleKey === 'internal_linking') {
            return moduleSummary.internal_linking_preview_links > 0
                ? String(moduleSummary.internal_linking_preview_links) + ' ' + t({ ro: 'linkuri propuse', bg: 'preview', en: 'links proposed' })
                : ((moduleSummary.internal_linking_keywords || 0) > 0 ? String(moduleSummary.internal_linking_keywords) + ' ' + t({ ro: 'keyworduri', bg: 'keywords', en: 'keywords' }) : t({ ro: 'fără snapshot', bg: 'no snapshot', en: 'no snapshot' }));
        }
        return String(stateEntry.provider || '');
    }

    function deriveTechnicalRailModules() {
        const context = state && state.context && typeof state.context === 'object' ? state.context : {};
        const technicalState = context.technical_state && typeof context.technical_state === 'object' ? context.technical_state : {};
        const summary = currentTechnicalOverviewSummary && typeof currentTechnicalOverviewSummary === 'object' ? currentTechnicalOverviewSummary : {};

        return technicalModuleDefinitions().map((module) => {
            const stateEntry = technicalState[module.key] && typeof technicalState[module.key] === 'object' ? technicalState[module.key] : {};
            let status = normalizeTechnicalStatus(stateEntry.status || summary[module.key + '_status'] || 'idle');
            if (status === 'idle') {
                if (module.key === 'redirects' && ((summary.redirect_review_required || 0) > 0 || (summary.redirect_conflicts || 0) > 0)) {
                    status = 'review_required';
                } else if (summary[module.key + '_ready']) {
                    status = 'ready';
                }
            }
            const isActive = currentModuleSlug === 'technical_seo'
                && ((module.key === 'redirects' && currentTabSlug === 'redirects_404') || currentTabSlug === module.key || (module.key === 'site_audit' && currentTabSlug === 'overview' && String(currentProjection && currentProjection.type || '') === 'technical_site_audit'));
            return {
                key: module.key,
                label: module.label,
                actionKey: module.actionKey,
                status: status,
                meta: summarizeTechnicalMeta(module.key, status, summary, technicalState),
                active: !!isActive
            };
        });
    }

    function renderTechnicalRail() {
        return;
    }

    function renderContextBar() {
        return;
    }

    function renderProductGuideCard() {
        if (!Array.isArray(currentProductMap) || !currentProductMap.length) {
            return '';
        }
        return '';
    }

    function renderOnpageProjection(projection) {
        const summary = projection && projection.summary && typeof projection.summary === 'object' ? projection.summary : {};
        const selectedEntityKey = String(projection && projection.selected_entity_key ? projection.selected_entity_key : '');
        const runType = String(summary.run_type || projection.run_type || '');
        const previewRows = Array.isArray(summary.preview_rows) ? summary.preview_rows : [];
        const title = String(projection && projection.title ? projection.title : 'Page Update Workspace');
        const intro = String(projection && projection.intro ? projection.intro : '');
        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">On-Page SEO</p>' +
                    '<h3 class="aysa-agent8-card-title">' + escapeHtml(title) + '</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    (intro ? '<p class="aysa-agent8-card-summary-row">' + escapeHtml(intro) + '</p>' : '') +
                    '<div class="aysa-agent8-card-grid">' +
                        '<div><strong>Entities:</strong> ' + escapeHtml(String(summary.total_entities || 0)) + '</div>' +
                        '<div><strong>Optimized:</strong> ' + escapeHtml(String(summary.optimized || 0)) + '</div>' +
                        '<div><strong>Needs work:</strong> ' + escapeHtml(String(summary.needs_work || summary.not_optimized || 0)) + '</div>' +
                        '<div><strong>Not optimized:</strong> ' + escapeHtml(String(summary.not_optimized || 0)) + '</div>' +
                        '<div><strong>Meta ready:</strong> ' + escapeHtml(String(summary.meta_ready || 0)) + '</div>' +
                        '<div><strong>Mapping review:</strong> ' + escapeHtml(String(summary.mapping_review || 0)) + '</div>' +
                        '<div><strong>Rewrite review:</strong> ' + escapeHtml(String(summary.rewrite_review || 0)) + '</div>' +
                        '<div><strong>Run type:</strong> ' + escapeHtml(runType || '-') + '</div>' +
                        '<div><strong>Selected entity:</strong> ' + escapeHtml(selectedEntityKey || '-') + '</div>' +
                    '</div>' +
                    (previewRows.length ? '<div class="aysa-agent8-card-summary-row"><strong>Preview</strong><br>' + previewRows.slice(0, 5).map((row) => {
                        return escapeHtml(String(row.title || row.url || row.entity_key || '-'))
                            + ' · '
                            + escapeHtml(String(row.main_keyword || '-'))
                            + ' · meta=' + escapeHtml(String(row.meta_state || '-'))
                            + ' · rewrite=' + escapeHtml(String(row.rewrite_state || '-'))
                            + ' · mapping=' + escapeHtml(String(row.mapping_state || '-'));
                    }).join('<br>') + '</div>' : '') +
                '</div>' +
            '</div>';
    }

    function renderOffpageProjection(projection) {
        const summary = projection && projection.summary && typeof projection.summary === 'object' ? projection.summary : {};
        const title = String(projection && projection.title ? projection.title : 'Off-Page SEO');
        const previewRows = Array.isArray(summary.preview_rows) ? summary.preview_rows : [];
        const capabilities = Array.isArray(summary.capabilities) ? summary.capabilities : [];
        let extra = '';
        if (capabilities.length) {
            extra += '<div class="aysa-agent8-card-summary-row"><strong>Capabilities:</strong> ' + escapeHtml(capabilities.join(', ')) + '</div>';
        }
        if (previewRows.length) {
            extra += '<div class="aysa-agent8-card-summary-row"><strong>Preview</strong><br>' + previewRows.slice(0, 5).map((row) => {
                if (!row || typeof row !== 'object') {
                    return '-';
                }
                return escapeHtml(String(
                    row.location_name
                    || row.portal_domain
                    || row.order_ref
                    || row.source_url
                    || row.published_url
                    || row.target_url
                    || row.draft_id
                    || '-'
                ));
            }).join('<br>') + '</div>';
        }
        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">Off-Page SEO</p>' +
                    '<h3 class="aysa-agent8-card-title">' + escapeHtml(title) + '</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    '<div class="aysa-agent8-card-grid">' +
                        Object.entries(summary).filter(([key, value]) => key !== 'preview_rows' && key !== 'capabilities' && typeof value !== 'object').slice(0, 8).map(([key, value]) => {
                            return '<div><strong>' + escapeHtml(humanizeSlug(String(key))) + ':</strong> ' + escapeHtml(String(value)) + '</div>';
                        }).join('') +
                    '</div>' +
                    extra +
                '</div>' +
            '</div>';
    }

    function renderMonitoringProjection(projection) {
        const summary = projection && projection.summary && typeof projection.summary === 'object' ? projection.summary : {};
        const title = String(projection && projection.title ? projection.title : 'Monitoring');
        const previewRows = Array.isArray(summary.preview_rows) ? summary.preview_rows : [];
        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">Monitoring</p>' +
                    '<h3 class="aysa-agent8-card-title">' + escapeHtml(title) + '</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    '<div class="aysa-agent8-card-grid">' +
                        Object.entries(summary).filter(([key, value]) => key !== 'preview_rows' && typeof value !== 'object').slice(0, 8).map(([key, value]) => {
                            return '<div><strong>' + escapeHtml(humanizeSlug(String(key))) + ':</strong> ' + escapeHtml(String(value)) + '</div>';
                        }).join('') +
                    '</div>' +
                    (previewRows.length ? '<div class="aysa-agent8-card-summary-row"><strong>Preview</strong><br>' + previewRows.slice(0, 6).map((row) => {
                        if (!row || typeof row !== 'object') {
                            return '-';
                        }
                        return escapeHtml(String(
                            row.keyword
                            || row.question
                            || row.query
                            || row.text
                            || row.link
                            || '-'
                        ));
                    }).join('<br>') + '</div>' : '') +
                '</div>' +
            '</div>';
    }

    function buildPostResearchProjectionFromContext(context) {
        const artifact = context && context.post_research_artifact && typeof context.post_research_artifact === 'object'
            ? context.post_research_artifact
            : {};
        const researchSummary = artifact.research_summary && typeof artifact.research_summary === 'object'
            ? artifact.research_summary
            : {};
        const counts = researchSummary.counts && typeof researchSummary.counts === 'object'
            ? researchSummary.counts
            : {};
        const keywordMapping = artifact.keyword_mapping && typeof artifact.keyword_mapping === 'object'
            ? artifact.keyword_mapping
            : {};
        const keywordSummary = keywordMapping.summary && typeof keywordMapping.summary === 'object'
            ? keywordMapping.summary
            : {};
        const keywordCount = Number(counts.candidate_keywords || keywordSummary.keywords_kept || 0);
        const mappedCount = Number(counts.mapped_keywords || keywordSummary.mapped || 0);
        const competitorCount = Number(counts.competitors || 0);
        const reviewProgress = context && context.research_review && typeof context.research_review === 'object'
            ? context.research_review
            : {};
        let currentBlock = {
            id: 'keywords',
            title: 'Keywords',
            summary: conversationLanguage === 'ro'
                ? 'Am găsit ' + keywordCount + ' keyworduri și am mapat ' + mappedCount + ' către pagini sau oportunități.'
                : 'I found ' + keywordCount + ' keywords and mapped ' + mappedCount + ' of them to pages or opportunities.',
            action_key: 'show_found_keywords',
            cta_label: conversationLanguage === 'ro' ? 'Revizuiește Keywords' : 'Review Keywords'
        };
        if (reviewProgress.keywords_reviewed && !reviewProgress.competitors_reviewed) {
            currentBlock = {
                id: 'competitors',
                title: 'Competitors',
                summary: conversationLanguage === 'ro'
                    ? 'Am păstrat ' + competitorCount + ' competitori ca bază pentru comparație și strategie.'
                    : 'I kept ' + competitorCount + ' competitors as the comparison base for strategy.',
                action_key: 'show_research_competitors',
                cta_label: conversationLanguage === 'ro' ? 'Revizuiește Competitors' : 'Review Competitors'
            };
        } else if (reviewProgress.competitors_reviewed && !reviewProgress.keyword_mapping_reviewed) {
            currentBlock = {
                id: 'keyword_mapping',
                title: 'Site Structure: Keyword Mapping',
                summary: conversationLanguage === 'ro'
                    ? 'Verificăm cum sunt legate keywordurile de paginile existente înainte să decidem ce lipsește.'
                    : 'We review how keywords are connected to existing pages before deciding what is missing.',
                action_key: 'show_keyword_mapping',
                cta_label: conversationLanguage === 'ro' ? 'Revizuiește Keyword Mapping' : 'Review Keyword Mapping'
            };
        } else if (reviewProgress.keyword_mapping_reviewed && !reviewProgress.missing_pages_reviewed) {
            currentBlock = {
                id: 'missing_pages',
                title: 'Site Structure: Missing Pages',
                summary: conversationLanguage === 'ro'
                    ? 'Verificăm oportunitățile de pagini lipsă.'
                    : 'We review the missing page opportunities.',
                action_key: 'show_missing_pages',
                cta_label: conversationLanguage === 'ro' ? 'Revizuiește Missing Pages' : 'Review Missing Pages'
            };
        } else if (reviewProgress.missing_pages_reviewed && !reviewProgress.content_reviewed) {
            currentBlock = {
                id: 'content_plan',
                title: 'Content Plan',
                summary: conversationLanguage === 'ro'
                    ? 'Verificăm planul de conținut pregătit din research.'
                    : 'We review the content plan prepared from research.',
                action_key: 'show_planned_content',
                cta_label: conversationLanguage === 'ro' ? 'Revizuiește Content Plan' : 'Review Content Plan'
            };
        } else if (reviewProgress.content_reviewed) {
            currentBlock = {
                id: 'technical_seo',
                title: 'Technical SEO',
                summary: conversationLanguage === 'ro'
                    ? 'Review-ul de research este parcurs. Următorul pas este Technical SEO.'
                    : 'The research review sequence is complete. The next step is Technical SEO.',
                action_key: 'show_technical_overview',
                cta_label: conversationLanguage === 'ro' ? 'Continuă cu Technical SEO' : 'Continue to Technical SEO'
            };
        }
        const reviewBlocks = [currentBlock];
        const conclusionCounts = normalizePostResearchCounts(researchSummary && researchSummary.counts ? researchSummary.counts : {}, reviewBlocks);

        return {
            type: 'post_research_workspace',
            title: conversationLanguage === 'ro' ? 'Research review' : 'Research Review',
            summary: researchSummary,
            conclusion: {
                counts: conclusionCounts
            },
            review_blocks: reviewBlocks
        };
    }

    function normalizePostResearchCounts(primaryCounts, reviewBlocks) {
        const blocks = Array.isArray(reviewBlocks) ? reviewBlocks : [];
        const fallbackCounts = {};
        blocks.forEach((block) => {
            const blockCounts = block && block.counts && typeof block.counts === 'object' ? block.counts : {};
            Object.keys(blockCounts).forEach((key) => {
                if (fallbackCounts[key] == null) {
                    fallbackCounts[key] = blockCounts[key];
                }
            });
        });
        const source = primaryCounts && typeof primaryCounts === 'object' ? primaryCounts : {};
        const value = (keys, defaultValue) => {
            for (let i = 0; i < keys.length; i += 1) {
                const key = keys[i];
                if (source[key] != null && source[key] !== '') {
                    return Number(source[key]) || 0;
                }
                if (fallbackCounts[key] != null && fallbackCounts[key] !== '') {
                    return Number(fallbackCounts[key]) || 0;
                }
            }
            return defaultValue || 0;
        };
        const keywordsFound = value(['keywords_found', 'candidate_keywords', 'keywords']);
        const mappedKeywords = value(['mapped_keywords', 'mapped']);
        return {
            keywords_found: keywordsFound,
            mapped_keywords: mappedKeywords,
            review_needed_keywords: value(['review_needed_keywords', 'needs_review'], Math.max(0, keywordsFound - mappedKeywords)),
            missing_pages: value(['missing_pages', 'missing_page_count']),
            planned_content_items: value(['planned_content_items', 'planned_items', 'content_ideas']),
            competitor_gaps: value(['competitor_gaps', 'competitors', 'competitive_signals'])
        };
    }

    function renderPostResearchProjection(projection) {
        const blocks = Array.isArray(projection && projection.review_blocks) ? projection.review_blocks : [];
        const conclusion = projection && projection.conclusion && typeof projection.conclusion === 'object' ? projection.conclusion : {};
        const summary = projection && projection.summary && typeof projection.summary === 'object' ? projection.summary : {};
        const summaryCounts = summary && summary.counts && typeof summary.counts === 'object' ? summary.counts : {};
        const conclusionCounts = conclusion && conclusion.counts && typeof conclusion.counts === 'object' ? conclusion.counts : {};
        const hasPositiveCount = (items) => Object.keys(items || {}).some((key) => Number(items[key] || 0) > 0);
        const primaryCounts = hasPositiveCount(conclusionCounts) || !hasPositiveCount(summaryCounts)
            ? Object.assign({}, summaryCounts, conclusionCounts)
            : summaryCounts;
        const counts = normalizePostResearchCounts(primaryCounts, blocks);
        const reviewNeeds = Array.isArray(conclusion.review_needs) ? conclusion.review_needs : [];
        const recommendedOrder = Array.isArray(conclusion.recommended_order) ? conclusion.recommended_order : [];
        const title = String(projection && projection.title ? projection.title : t({
            ro: 'Research Conclusion',
            bg: 'Research Conclusion',
            en: 'Research Conclusion'
        }));
        const intro = t({
            ro: 'Research-ul este gata. Înainte să mergem mai departe, îți arăt ce am găsit și ce merită verificat.',
            bg: 'Research-ът е готов. Първо показвам какво е намерено и какво трябва да се прегледа.',
            en: 'The research is complete. Before moving forward, I will show what I found and what needs review.'
        });
        const summaryRows = [
            [t({ ro: 'Keyworduri găsite', en: 'Keywords found' }), counts.keywords_found],
            [t({ ro: 'Keyworduri mapate', en: 'Mapped keywords' }), counts.mapped_keywords],
            [t({ ro: 'De verificat', en: 'Needs review' }), counts.review_needed_keywords],
            [t({ ro: 'Pagini lipsă', en: 'Missing pages' }), counts.missing_pages],
            [t({ ro: 'Idei de conținut', en: 'Content ideas' }), counts.planned_content_items],
            [t({ ro: 'Semnale competitive', en: 'Competitive signals' }), counts.competitor_gaps]
        ].map((row) => {
            return '<div class="aysa-agent8-card-summary-row"><strong>' + escapeHtml(row[0]) + '</strong><span>' + escapeHtml(String(row[1] == null ? 0 : row[1])) + '</span></div>';
        }).join('');
        const reviewHtml = reviewNeeds.length ? '<ul>' + reviewNeeds.map((item) => '<li>' + escapeHtml(String(item)) + '</li>').join('') + '</ul>' : '';
        const orderHtml = recommendedOrder.length ? '<ol>' + recommendedOrder.map((item) => '<li>' + escapeHtml(String(item && item.label ? item.label : item)) + '</li>').join('') + '</ol>' : '';
        const approvalNote = String(conclusion.approval_note || '');
        const blockHtml = blocks.slice(0, 2).map((block) => {
            const actionKey = String(block && block.action_key ? block.action_key : '');
            const ctaLabel = String(block && block.cta_label ? block.cta_label : 'Open');
            const actions = actionKey ? [{
                type: 'action',
                action_key: actionKey,
                label: ctaLabel,
                style: 'primary'
            }] : [];
            return '' +
                '<div class="aysa-agent8-card-summary-row" style="padding:12px;border:1px solid #dbe3ef;border-radius:12px;background:#fff;">' +
                    '<strong>' + escapeHtml(String(block && block.title ? block.title : 'Review block')) + '</strong>' +
                    '<p style="margin:6px 0 10px;">' + escapeHtml(String(block && block.summary ? block.summary : '')) + '</p>' +
                    renderChipRow(actions) +
                '</div>';
        }).join('');

        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">Research</p>' +
                    '<h3 class="aysa-agent8-card-title">' + escapeHtml(title) + '</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    '<p class="aysa-agent8-card-summary-row">' + escapeHtml(intro) + '</p>' +
                    '<div class="aysa-agent8-card-summary">' + summaryRows + '</div>' +
                    '<div class="aysa-agent8-card-summary-row" style="display:block;"><strong>' + escapeHtml(t({ ro: 'Ce trebuie verificat', en: 'What needs review' })) + '</strong>' + reviewHtml + '</div>' +
                    '<div class="aysa-agent8-card-summary-row" style="display:block;"><strong>' + escapeHtml(t({ ro: 'Ordinea recomandată', en: 'Recommended order' })) + '</strong>' + orderHtml + '</div>' +
                    (approvalNote ? '<p class="aysa-agent8-card-summary-row">' + escapeHtml(approvalNote) + '</p>' : '') +
                    '<div class="aysa-agent8-card-summary">' + blockHtml + '</div>' +
                '</div>' +
            '</div>';
    }

    function renderProjectionCard(projection) {
        if (!projection || typeof projection !== 'object') {
            return '';
        }
        if (projection.type === 'post_research_workspace') {
            return renderPostResearchProjection(projection);
        }
        if (projection.type === 'activation') {
            return renderActivationProjection(projection);
        }
        if (projection.type === 'general') {
            return renderGeneralProjection(projection);
        }
        if (projection.type === 'integrations') {
            return renderIntegrationProjection(projection);
        }
        if (projection.type === 'competition') {
            return renderCompetitionProjection(projection);
        }
        if (projection.type === 'objectives') {
            return renderObjectivesProjection(projection);
        }
        if (projection.type === 'seo_settings') {
            return renderSeoSettingsProjection(projection);
        }
        if (projection.type === 'tone_of_voice') {
            return renderToneProjection(projection);
        }
        if (projection.type === 'keyword_mapping') {
            return renderKeywordMappingProjection(projection);
        }
        if (projection.type === 'missing_pages') {
            return renderMissingPagesProjection(projection);
        }
        if (projection.type === 'content_strategy') {
            return renderContentStrategyProjection(projection);
        }
        if (projection.type === 'publishing_calendar') {
            return renderPublishingCalendarProjection(projection);
        }
        if (
            projection.type === 'technical_overview'
            || projection.type === 'technical_optimization_guide'
            || projection.type === 'technical_site_audit'
            || projection.type === 'technical_pagespeed'
            || projection.type === 'technical_schema'
            || projection.type === 'technical_redirects'
            || projection.type === 'technical_redirects_review'
            || projection.type === 'technical_sitemap_robots'
            || projection.type === 'technical_internal_linking'
        ) {
            return renderTechnicalProjection(projection);
        }
        if (projection.type === 'plan_mutation_result') {
            return renderPlanMutationProjection(projection);
        }
        if (
            projection.type === 'onpage_optimization'
            || projection.type === 'onpage_meta_generation'
            || projection.type === 'onpage_keyword_validation'
            || projection.type === 'onpage_rewrite_generation'
            || projection.type === 'onpage_keyword_association'
            || projection.type === 'onpage_apply_queue'
        ) {
            return renderOnpageProjection(projection);
        }
        if (
            projection.type === 'offpage_google_business_profile'
            || projection.type === 'offpage_link_exchange'
            || projection.type === 'offpage_backlink_audit'
            || projection.type === 'offpage_draft_articles'
            || projection.type === 'offpage_published_articles'
        ) {
            return renderOffpageProjection(projection);
        }
        if (
            projection.type === 'monitoring_rank_tracking'
            || projection.type === 'monitoring_ai_monitoring'
            || projection.type === 'monitoring_keyword_overview'
            || projection.type === 'monitoring_query_packs'
        ) {
            return renderMonitoringProjection(projection);
        }
        return '';
    }

    function renderPendingNote() {
        const $pending = $('#aysa-agent8-pending');
        if ($pending.attr('hidden')) {
            return '';
        }
        const epoch = agent8ForegroundRequest
            ? String(agent8ForegroundRequest.epoch || '')
            : String($pending.attr('data-epoch') || conversationRequestEpoch || '');
        const text = String($pending.text() || 'Agent8 is thinking...').replace(/\bAgent 8\b/g, 'Agent8').replace(/\.*\s*$/, '');
        const dots = '<span class="aysa-agent8-thinking-dots" aria-hidden="true"><span>.</span><span>.</span><span>.</span></span>';
        return '<div class="aysa-agent8-message assistant" data-agent8-loader="1" data-agent8-epoch="' + escapeHtml(epoch) + '">' + escapeHtml(text) + dots + '</div>';
    }

    function shouldRenderInlineSuggestions() {
        if (!currentSuggestions.length) {
            return false;
        }
        return true;
    }

    function renderTranscript() {
        const timeline = [];
        const suppressHistoricalCompetitionAccepted = !!(
            currentProjection
            && String(currentProjection.type || '') === 'competition'
            && competitionStepContractState(currentProjection)
            && !competitionAcceptedState(competitionStepContractState(currentProjection))
        );
        transcript.forEach((item) => {
            const role = item.role === 'user' ? 'user' : 'assistant';
            const rawMessage = String(item.message || '');
            if (suppressHistoricalCompetitionAccepted && role === 'assistant' && /^Accepted\.\s+Competition set/i.test(rawMessage)) {
                return;
            }
            const messageHtml = role === 'user'
                ? escapeHtml(rawMessage)
                : formatMessageHtml(rawMessage);
            timeline.push('<div class="aysa-agent8-message ' + role + '">' + messageHtml + '</div>');
        });

        const suppressCompetitionProjection = !!(
            pendingApproval
            && String(pendingApproval.action_key || '') === 'regenerate_competition_proposal'
            && currentProjection
            && String(currentProjection.type || '') === 'competition'
        );

        if (currentProjection && !suppressCompetitionProjection) {
            timeline.push(renderProjectionCard(currentProjection));
        }
        if (currentProductMap.length) {
            timeline.push(renderProductGuideCard());
        }
        if (currentContractIssue) {
            timeline.push(renderContractIssueCard(currentContractIssue));
        }
        if (pendingApproval) {
            timeline.push(renderApprovalCard(pendingApproval));
        }
        if (shouldRenderInlineSuggestions()) {
            timeline.push('<div id="aysa-agent8-suggestions">' + renderChipRow(currentSuggestions) + '</div>');
        }
        timeline.push(renderPendingNote());

        const html = '<div class="aysa-agent8-timeline">' + timeline.join('') + '</div>';
        const $el = $('#aysa-agent8-transcript');
        $el.html(html);
        renderContextBar();
        renderTechnicalRail();
        renderPersistentActionBar();
        renderAsyncProgressSticky();
        sanitizeUnauthorizedActionButtons($el);
        $el.scrollTop($el[0].scrollHeight);
    }

    function renderStatus(result) {
        const currentState = result && result.state ? result.state : {};
        state = currentState;
        currentProductMap = Array.isArray(result && result.product_map) ? result.product_map : [];
        conversationId = String((result && result.conversation_id) || conversationId || '');
        $('#aysa-agent8-phase').text(result.phase || 'conversation');
        $('#aysa-agent8-step').text(result.current_step || 'conversation');
        $('#aysa-agent8-owner').text(result.owner || 'conversation');
        $('#aysa-agent8-capability').text(result.capability_level || 'Conversational');
        $('#aysa-agent8-version').text(result.agent_version || '-');
        currentModuleSlug = String(result.module || '');
        currentTabSlug = String(result.tab || '');
        $('#aysa-agent8-module').text(humanizeSlug(result.module || ''));
        $('#aysa-agent8-tab').text(humanizeSlug(result.tab || ''));
    }

    function resetVisibleConversationStatus() {
        state = {};
        currentProductMap = [];
        currentModuleSlug = '';
        currentTabSlug = '';
        currentAsyncProgress = null;
        $('#aysa-agent8-phase').text('conversation');
        $('#aysa-agent8-step').text('conversation');
        $('#aysa-agent8-owner').text('conversation');
        $('#aysa-agent8-module').text('-');
        $('#aysa-agent8-tab').text('-');
    }

    function deriveAvailableCredits(snapshot) {
        const data = snapshot || {};
        const balance = data.balance_cents != null ? (Number(data.balance_cents) || 0) : null;
        const reserved = data.reserved_links_cents != null ? (Number(data.reserved_links_cents) || 0) : 0;
        const computedFromBalance = balance != null ? Math.max(0, balance - reserved) : null;
        if (data.available_credits != null) {
            const explicit = Number(data.available_credits) || 0;
            return computedFromBalance != null ? Math.min(explicit, computedFromBalance) : explicit;
        }
        if (data.spendable_cents != null) {
            const explicit = Number(data.spendable_cents) || 0;
            return computedFromBalance != null ? Math.min(explicit, computedFromBalance) : explicit;
        }
        if (data.available_credits_cents != null) {
            const explicit = Number(data.available_credits_cents) || 0;
            return computedFromBalance != null ? Math.min(explicit, computedFromBalance) : explicit;
        }
        if (data.credits_available != null) {
            const explicit = Number(data.credits_available) || 0;
            return computedFromBalance != null ? Math.min(explicit, computedFromBalance) : explicit;
        }
        if (computedFromBalance != null) {
            return computedFromBalance;
        }
        return 0;
    }

    function normalizeWalletSnapshot(snapshot) {
        const data = snapshot && typeof snapshot === 'object' ? Object.assign({}, snapshot) : {};
        if (data.available_credits == null) {
            if (data.credits_available != null) {
                data.available_credits = data.credits_available;
            } else if (data.available_credits_cents != null) {
                data.available_credits = data.available_credits_cents;
            } else if (data.spendable_cents != null) {
                data.available_credits = data.spendable_cents;
            }
        }
        if (hasWalletSnapshot(data)) {
            data.available_credits = deriveAvailableCredits(data);
        }
        return data;
    }

    function hasWalletSnapshot(snapshot) {
        const data = snapshot && typeof snapshot === 'object' ? snapshot : {};
        return data.available_credits != null ||
            data.credits_available != null ||
            data.available_credits_cents != null ||
            data.spendable_cents != null ||
            data.balance_cents != null;
    }

    function renderWallet(snapshot) {
        const data = normalizeWalletSnapshot(snapshot || currentWalletSnapshot || {});
        if (hasWalletSnapshot(data)) {
            currentWalletSnapshot = data;
            syncWalletVisibility(true);
        }
        const credits = data.available_credits != null ? Number(data.available_credits) || 0 : deriveAvailableCredits(data);
        $('#aysa-agent8-credits').text(String(credits || 0));
        $('#aysa-agent8-last-usage').text(String(data.latest_usage_amount_cents || 0));
    }

    function isActivationVerifiedResult(result) {
        const data = result || {};
        const phase = String(data.phase || '').toLowerCase();
        const currentStep = String(data.current_step || '').toLowerCase();
        if (phase === 'activation' || phase === 'preactivation' || currentStep === 'activation' || currentStep === 'preactivation') {
            return false;
        }
        const activation = data && data.state && data.state.context && data.state.context.activation && typeof data.state.context.activation === 'object'
            ? data.state.context.activation
            : null;
        if (activation && activation.verified != null) {
            return !!activation.verified;
        }
        return false;
    }

function syncWalletVisibility(isVisible) {
        const visible = !!isVisible;
        const $creditsPill = $('#aysa-agent8-credits-pill');
        const $lastUsagePill = $('#aysa-agent8-last-usage-pill');
        if (visible) {
            $creditsPill.removeAttr('hidden').css('display', 'inline-flex');
            $lastUsagePill.removeAttr('hidden').css('display', 'inline-flex');
        } else {
            $creditsPill.attr('hidden', 'hidden').css('display', 'none');
            $lastUsagePill.attr('hidden', 'hidden').css('display', 'none');
        }
    }

    function backendAllowedActionKeys(result) {
        if (Array.isArray(result && result.allowed_actions)) {
            return result.allowed_actions
                .map((key) => String(key || ''))
                .filter((key, index, all) => key && all.indexOf(key) === index);
        }
        const scoped = result && result.active_scope && Array.isArray(result.active_scope.allowed_actions)
            ? result.active_scope.allowed_actions
            : [];
        return scoped
            .map((key) => String(key || ''))
            .filter((key, index, all) => key && all.indexOf(key) === index);
    }

    function hasBackendAllowedActionsContract(result) {
        return Array.isArray(result && result.allowed_actions)
            || !!(result && result.active_scope && Array.isArray(result.active_scope.allowed_actions));
    }

    function isBackendActionAllowed(actionKey) {
        const key = String(actionKey || '').trim();
        if (!key) {
            return false;
        }
        const setupController = currentSetupController();
        if (setupController) {
            return setupActionAllowed(setupController, key);
        }
        return !currentAllowedActionsAuthoritative || currentAllowedActionKeys.indexOf(key) !== -1;
    }

    function sanitizeUnauthorizedActionButtons(root) {
        const setupController = currentSetupController();
        if (!currentAllowedActionsAuthoritative && !setupController) {
            return;
        }
        const $root = root && root.length ? root : $(document);
        $root.find('[data-action-key]').each(function() {
            const $item = $(this);
            const actionKey = String($item.attr('data-action-key') || '').trim();
            const allowed = setupController ? setupActionAllowed(setupController, actionKey) : currentAllowedActionKeys.indexOf(actionKey) !== -1;
            if (actionKey && !allowed) {
                if (!$item.is(':disabled')) {
                    $item.attr('data-aysa-auth-disabled', '1');
                }
                $item.attr('hidden', 'hidden')
                    .attr('aria-hidden', 'true')
                    .attr('data-agent8-unauthorized-action', actionKey)
                    .attr('data-aysa-unauthorized-hidden', '1')
                    .prop('disabled', true);
            } else if (actionKey && String($item.attr('data-agent8-unauthorized-action') || '') === actionKey) {
                $item.removeAttr('hidden')
                    .removeAttr('aria-hidden')
                    .removeAttr('data-agent8-unauthorized-action')
                    .removeAttr('data-aysa-unauthorized-hidden');
                if (String($item.attr('data-aysa-auth-disabled') || '') === '1') {
                    $item.prop('disabled', false)
                        .removeAttr('data-aysa-auth-disabled');
                }
            }
        });
    }

    function syncInlineUi(result) {
        currentUiCommand = null;
        currentProjection = null;
        const previousTechnicalOverviewSummary = currentTechnicalOverviewSummary && typeof currentTechnicalOverviewSummary === 'object'
            ? currentTechnicalOverviewSummary
            : {};
        const previousTechnicalWorkspaceSnapshot = currentTechnicalWorkspaceSnapshot && typeof currentTechnicalWorkspaceSnapshot === 'object'
            ? currentTechnicalWorkspaceSnapshot
            : {};
        currentTechnicalOverviewSummary = previousTechnicalOverviewSummary;
        currentTechnicalWorkspaceSnapshot = previousTechnicalWorkspaceSnapshot;
        pendingApproval = result && result.approval_request && typeof result.approval_request === 'object'
            ? result.approval_request
            : null;
        currentAllowedActionsAuthoritative = hasBackendAllowedActionsContract(result);
        currentAllowedActionKeys = backendAllowedActionKeys(result);
        currentSuggestions = Array.isArray(result && result.suggested_actions) ? result.suggested_actions : [];
        persistentActions = Array.isArray(result && result.persistent_actions) ? result.persistent_actions : [];
        currentContractIssue = result && result.contract_status === 'invalid'
            ? {
                status: 'invalid',
                issueCode: String(result.contract_issue_code || ''),
                details: result.contract_issue_details && typeof result.contract_issue_details === 'object'
                    ? result.contract_issue_details
                    : {},
                phase: String(result.phase || ''),
                currentStep: String(result.current_step || ''),
                conversationId: String(result.conversation_id || '')
            }
            : null;
        const actionResult = result && result.action_result && typeof result.action_result === 'object'
            ? result.action_result
            : null;
        if (currentContractIssue) {
            pendingApproval = null;
            currentAllowedActionKeys = [];
            currentSuggestions = [];
            persistentActions = [];
        }
        currentUiCommand = actionResult && actionResult.ui_command && typeof actionResult.ui_command === 'object'
            ? actionResult.ui_command
            : null;
        currentProjection = actionResult && actionResult.projection && typeof actionResult.projection === 'object'
            ? actionResult.projection
            : null;
        const resultModuleSlug = String((actionResult && actionResult.module) || (result && result.module) || '').toLowerCase();
        if (resultModuleSlug !== 'technical_seo') {
            const projectionType = currentProjection && typeof currentProjection === 'object'
                ? String(currentProjection.type || '')
                : '';
            const uiType = currentUiCommand && typeof currentUiCommand === 'object'
                ? String(currentUiCommand.type || '')
                : '';
            if (projectionType.indexOf('technical_') === 0) {
                currentProjection = null;
            }
            if (uiType.indexOf('open_technical_') === 0) {
                currentUiCommand = null;
            }
        }
        if (actionResult && actionResult.workspace_snapshot && typeof actionResult.workspace_snapshot === 'object') {
            currentTechnicalWorkspaceSnapshot = actionResult.workspace_snapshot;
            if (currentUiCommand && currentUiCommand.type === 'open_publishing_calendar_modal') {
                currentPublishingCalendarSnapshot = actionResult.workspace_snapshot;
                currentPublishingCalendarScheduleContract = currentPublishingCalendarSnapshot && currentPublishingCalendarSnapshot.schedule_contract && typeof currentPublishingCalendarSnapshot.schedule_contract === 'object'
                    ? currentPublishingCalendarSnapshot.schedule_contract
                    : (currentUiCommand.schedule_contract && typeof currentUiCommand.schedule_contract === 'object' ? currentUiCommand.schedule_contract : null);
                currentPublishingCalendarRowContracts = collectPublishingCalendarRowContracts(currentPublishingCalendarSnapshot);
                if (actionResult.summary && typeof actionResult.summary === 'object') {
                    currentPublishingCalendarSnapshot.summary = actionResult.summary;
                }
            }
        }
        if (!currentProjection && actionResult && actionResult.workspace_snapshot && typeof actionResult.workspace_snapshot === 'object' && currentUiCommand && currentUiCommand.type === 'open_keyword_review') {
            currentProjection = {
                type: 'keyword_mapping',
                summary: actionResult.workspace_snapshot.summary && typeof actionResult.workspace_snapshot.summary === 'object'
                    ? actionResult.workspace_snapshot.summary
                    : {}
            };
        }
        if (!currentProjection && actionResult && actionResult.summary && typeof actionResult.summary === 'object') {
            const actionKey = String(actionResult.action_key || '');
            if (actionKey === 'show_missing_pages') {
                currentProjection = { type: 'missing_pages', summary: actionResult.summary };
            } else if (actionKey === 'show_content_strategy') {
                currentProjection = { type: 'content_strategy', summary: actionResult.summary };
            } else if (actionKey === 'show_publishing_calendar') {
                currentProjection = { type: 'publishing_calendar', summary: actionResult.summary };
            } else if (actionKey === 'send_missing_pages_to_plan') {
                currentProjection = { type: 'plan_mutation_result', summary: actionResult.summary };
            }
        }
        if (currentProjection && currentProjection.type === 'technical_overview' && currentProjection.summary && typeof currentProjection.summary === 'object') {
            currentTechnicalOverviewSummary = currentProjection.summary;
        } else {
            const technicalSummaryPatch = deriveTechnicalSummaryPatch(actionResult, currentProjection);
            if (technicalSummaryPatch && typeof technicalSummaryPatch === 'object') {
                currentTechnicalOverviewSummary = Object.assign({}, currentTechnicalOverviewSummary || {}, technicalSummaryPatch);
            }
        }

        const setupController = currentSetupController();
        if (setupController) {
            currentAllowedActionsAuthoritative = true;
            currentAllowedActionKeys = setupController.allowedActionKeys.slice();
            currentSuggestions = setupActionsFromContract(currentProjection);
            persistentActions = [];
            if (pendingApproval && !setupActionAllowed(setupController, String(pendingApproval.action_key || ''))) {
                pendingApproval = null;
            }
            return;
        }
        if (isSetupProjection(currentProjection)) {
            currentAllowedActionsAuthoritative = true;
            currentAllowedActionKeys = [];
            currentSuggestions = [];
            persistentActions = [];
            pendingApproval = null;
            return;
        }

        const phase = String(result && result.phase ? result.phase : '').toLowerCase();
        const currentStep = String(result && result.current_step ? result.current_step : '').toLowerCase();
        const currentModule = String(result && result.module ? result.module : '').toLowerCase();
        const currentTab = String(result && result.tab ? result.tab : '').toLowerCase();
        const stateContext = result && result.state && result.state.context && typeof result.state.context === 'object'
            ? result.state.context
            : {};
        const localDecisions = stateContext && stateContext.local_decisions && typeof stateContext.local_decisions === 'object'
            ? stateContext.local_decisions
            : {};
        const generalProfile = stateContext && stateContext.general_profile && typeof stateContext.general_profile === 'object'
            ? stateContext.general_profile
            : {};
        const generalProposal = generalProfile && generalProfile.proposal && typeof generalProfile.proposal === 'object'
            ? generalProfile.proposal
            : null;
        const preferences = stateContext && stateContext.curated_memory && stateContext.curated_memory.preferences && typeof stateContext.curated_memory.preferences === 'object'
            ? stateContext.curated_memory.preferences
            : {};
        const artifactRunStatus = String(
            (stateContext && stateContext.post_research_artifact && stateContext.post_research_artifact.run_status) ||
            (result && result.action_result && result.action_result.run && result.action_result.run.status) ||
            (currentAsyncJob && currentAsyncJob.status) ||
            ''
        ).toLowerCase();
        if (!currentProjection && artifactRunStatus === 'completed' && (phase === 'post_research_workspace' || currentModule === 'research_analysis')) {
            currentProjection = buildPostResearchProjectionFromContext(stateContext);
        }
        const latestResearchCompleted = phase === 'post_research_workspace'
            || artifactRunStatus === 'completed';
        const latestResearchActive = latestResearchCompleted
            || phase === 'research_in_progress'
            || currentStep === 'research_in_progress'
            || ((phase === 'keyword-research' || currentStep === 'keyword-research' || currentStep === 'keyword-discovery') && artifactRunStatus !== '')
            || artifactRunStatus === 'queued'
            || artifactRunStatus === 'running';
        const generalPrepared = !!generalProposal;
        const generalConfirmed = !!(generalProfile.validated || localDecisions.general_profile_confirmed);
        const objectivesSaved = !!localDecisions.objectives_saved;
        const seoSettingsSaved = !!localDecisions.seo_settings_saved;
        const competitionProposal = stateContext && stateContext.competition && typeof stateContext.competition === 'object'
            && stateContext.competition.proposal && typeof stateContext.competition.proposal === 'object'
            ? stateContext.competition.proposal
            : {};
        const competitionHasProposal = !!(
            currentProjection && currentProjection.type === 'competition' && currentProjection.has_proposal
        ) || !!(
            Array.isArray(competitionProposal.keywords) && competitionProposal.keywords.length
        ) || !!(
            Array.isArray(competitionProposal.competitors) && competitionProposal.competitors.length
        );
        const competitionAccepted = !!(
            currentProjection
            && currentProjection.type === 'competition'
            && competitionProjectionAccepted(currentProjection)
        ) || !!(stateContext && stateContext.competition && stateContext.competition.accepted) || !!localDecisions.competition_proposal_accepted;
        const currentCompetitionStepState = currentProjection && currentProjection.type === 'competition'
            ? competitionStepContractState(currentProjection)
            : '';
        const currentCompetitionContract = currentProjection && currentProjection.type === 'competition' && currentProjection.step_contract && typeof currentProjection.step_contract === 'object'
            ? currentProjection.step_contract
            : {};
        const currentCompetitionAllowedActionKeys = Array.isArray(currentCompetitionContract.allowed_action_keys)
            ? currentCompetitionContract.allowed_action_keys.map((key) => String(key || ''))
            : [];
        const currentCompetitionReviewable = !!(currentProjection && currentProjection.type === 'competition' && currentCompetitionStepState && !competitionAcceptedState(currentCompetitionStepState));
        const effectiveCompetitionAccepted = currentCompetitionReviewable ? false : competitionAccepted;
        const competitionQualityStatus = String(
            (currentProjection && currentProjection.type === 'competition' && currentProjection.quality_status)
            || competitionProposal.quality_status
            || ''
        );
        const competitionCanAccept = effectiveCompetitionAccepted || competitionQualityStatus === 'valid';
        const toneSaved = !!localDecisions.tone_saved;
        const shouldHideCompetitionActions = effectiveCompetitionAccepted || (!currentCompetitionReviewable && (phase === 'tone-of-voice' || currentStep === 'tone-of-voice' || toneSaved || latestResearchCompleted));
        const setupProjectionActiveForActions = isSetupProjection(currentProjection);

        const filterClosedActions = function(actions) {
            const list = Array.isArray(actions) ? actions : [];
            return list.filter((action) => {
                const actionKey = String(action && action.action_key ? action.action_key : '');
                if (!actionKey) {
                    return true;
                }
                if (currentAllowedActionsAuthoritative && currentAllowedActionKeys.indexOf(actionKey) === -1 && currentCompetitionAllowedActionKeys.indexOf(actionKey) === -1) {
                    return false;
                }
                if (action && action.available === false) {
                    return false;
                }
                if (setupProjectionActiveForActions && currentAllowedActionsAuthoritative) {
                    return true;
                }
                if ((generalConfirmed || !generalPrepared) && actionKey === 'confirm_general_profile') {
                    return false;
                }
                if (objectivesSaved && actionKey === 'save_objectives') {
                    return false;
                }
                if (seoSettingsSaved && actionKey === 'save_seo_settings') {
                    return false;
                }
                if (shouldHideCompetitionActions && (actionKey === 'accept_competition_proposal' || actionKey === 'regenerate_competition_proposal' || actionKey === 'generate_competition_proposal')) {
                    return false;
                }
                if (!competitionCanAccept && (actionKey === 'accept_competition_proposal' || actionKey === 'show_setup_tone_of_voice')) {
                    return false;
                }
                if (!competitionHasProposal && (actionKey === 'accept_competition_proposal' || actionKey === 'regenerate_competition_proposal')) {
                    return false;
                }
                if (toneSaved && actionKey === 'save_tone_of_voice') {
                    return false;
                }
                if (toneSaved && (actionKey === 'show_setup_tone_of_voice' || actionKey === 'show_setup_objectives')) {
                    return false;
                }
                if (latestResearchActive && actionKey === 'start_keyword_research') {
                    return false;
                }
                if (latestResearchCompleted && actionKey.indexOf('refresh_research_') === 0) {
                    return false;
                }
                if (!setupProjectionActiveForActions && latestResearchCompleted && actionKey.indexOf('show_setup_') === 0) {
                    return false;
                }
                return true;
            });
        };

        currentSuggestions = filterClosedActions(currentSuggestions);
        persistentActions = filterClosedActions(persistentActions);
        if (isTechnicalScopeActive()) {
            persistentActions = [];
        }

        if (shouldHideCompetitionActions && !toneSaved && !latestResearchCompleted && (!currentAllowedActionsAuthoritative || currentAllowedActionKeys.indexOf('show_setup_tone_of_voice') !== -1)) {
            const hasToneShortcut = currentSuggestions.some((action) => {
                return String(action && action.action_key ? action.action_key : '') === 'show_setup_tone_of_voice';
            });
            if (!hasToneShortcut) {
                currentSuggestions.unshift({
                    type: 'action',
                    action_key: 'show_setup_tone_of_voice',
                    label: conversationLanguage === 'ro' ? 'Vezi Tone of Voice' : 'Show Tone of Voice'
                });
            }
            const hasPersistentToneShortcut = persistentActions.some((action) => {
                return String(action && action.action_key ? action.action_key : '') === 'show_setup_tone_of_voice';
            });
            if (!hasPersistentToneShortcut) {
                persistentActions.unshift({
                    type: 'action',
                    action_key: 'show_setup_tone_of_voice',
                    label: conversationLanguage === 'ro' ? 'Vezi Tone of Voice' : 'Show Tone of Voice'
                });
            }
            if (pendingApproval && String(pendingApproval.action_key || '') === 'accept_competition_proposal') {
                pendingApproval = null;
            }
        }
        if (pendingApproval && currentAllowedActionsAuthoritative && currentAllowedActionKeys.indexOf(String(pendingApproval.action_key || '')) === -1) {
            pendingApproval = null;
        }

        if (toneSaved && !persistentActions.some((action) => {
            const actionKey = String(action && action.action_key ? action.action_key : '');
            return actionKey === 'start_keyword_research' || actionKey === 'show_research_keyword_discovery' || actionKey === 'show_found_keywords';
        })) {
            const researchShortcut = latestResearchCompleted
                    ? (!currentAllowedActionsAuthoritative || currentAllowedActionKeys.indexOf('show_found_keywords') !== -1
                        ? {
                            type: 'action',
                            action_key: 'show_found_keywords',
                            label: conversationLanguage === 'ro' ? 'Vezi rezultatele research' : 'Review research results'
                        }
                        : null)
                    : latestResearchActive
                        ? {
                            type: 'message',
                            message: conversationLanguage === 'ro' ? 'care este statusul keyword research?' : 'what is the keyword research status?',
                            label: conversationLanguage === 'ro' ? 'Vezi progresul research-ului' : 'View research progress'
                        }
                        : (!currentAllowedActionsAuthoritative || currentAllowedActionKeys.indexOf('start_keyword_research') !== -1
                            ? {
                            type: 'action',
                            action_key: 'start_keyword_research',
                            label: conversationLanguage === 'ro' ? 'Pornește keyword research' : 'Start keyword research'
                        }
                            : null);
            if (researchShortcut) {
                persistentActions.unshift(researchShortcut);
            }
        }

        if (currentSuggestions.length && persistentActions.length) {
            const currentActionKeys = {};
            currentSuggestions.forEach((action) => {
                const actionKey = String(action && action.action_key ? action.action_key : '');
                if (actionKey) {
                    currentActionKeys[actionKey] = true;
                }
            });
            persistentActions = persistentActions.filter((action) => {
                const actionKey = String(action && action.action_key ? action.action_key : '');
                return !actionKey || !currentActionKeys[actionKey];
            });
        }
    }

    function renderTechnicalProjection(projection) {
        const summary = projection && projection.summary && typeof projection.summary === 'object'
            ? projection.summary
            : {};
        const type = String(projection && projection.type ? projection.type : 'technical_overview');
        const titleMap = {
            technical_overview: 'Technical Overview',
            technical_optimization_guide: 'Technical Overview',
            technical_site_audit: 'Site Audit',
            technical_pagespeed: 'PageSpeed',
            technical_sitemap_robots: 'Sitemap + Robots',
            technical_schema: 'Schema',
            technical_redirects: 'Redirects / 404',
            technical_redirects_review: 'Redirects / 404',
            technical_internal_linking: 'Internal Linking Workspace (local)'
        };
        const intro = String(projection && projection.intro ? projection.intro : '');
        const sections = Array.isArray(projection && projection.sections) ? projection.sections : [];
        const topPriorities = Array.isArray(projection && projection.top_priorities) ? projection.top_priorities : [];
        const autoActions = Array.isArray(projection && projection.auto_actions) ? projection.auto_actions : [];
        const needsConfirmation = Array.isArray(projection && projection.needs_confirmation) ? projection.needs_confirmation : [];
        const niceLabel = function(key) {
            return String(key || '').replace(/_/g, ' ');
        };
        const renderList = function(title, items) {
            const list = Array.isArray(items) ? items.filter(Boolean) : [];
            if (!list.length) {
                return '';
            }
            return '' +
                '<div class="aysa-agent8-card-summary-row">' +
                    '<strong>' + escapeHtml(title) + '</strong>' +
                    '<ul style="margin:8px 0 0 18px;">' +
                        list.map((item) => '<li>' + escapeHtml(niceLabel(String(item))) + '</li>').join('') +
                    '</ul>' +
                '</div>';
        };
        const renderSummaryRows = function(data) {
            return Object.keys(data || {}).map((key) => {
                const value = data[key];
                if (value == null || value === '' || (Array.isArray(value) && !value.length)) {
                    return '';
                }
                return '<div class="aysa-agent8-card-summary-row"><strong>' + escapeHtml(niceLabel(key)) + ':</strong> ' + escapeHtml(String(value)) + '</div>';
            }).join('');
        };
        const sectionHtml = sections.map((section) => {
            const sectionSummary = section && section.summary && typeof section.summary === 'object' ? section.summary : {};
            return '' +
                '<div class="aysa-agent8-card-summary-row" style="padding-top:10px;">' +
                    '<strong>' + escapeHtml(String(section && section.title ? section.title : 'Section')) + '</strong>' +
                    '<div style="margin-top:6px;">' + renderSummaryRows(sectionSummary) + '</div>' +
                '</div>';
        }).join('');
        const summaryBuckets = [];
        if (summary.status) {
            summaryBuckets.push('<div class="aysa-agent8-card-summary-row"><strong>Pe scurt:</strong> ' + escapeHtml(String(summary.status)) + '</div>');
        }
        if (summary.site_audit_issues != null || summary.pagespeed_overall_score != null || summary.redirect_ready != null) {
            const quickRows = {};
            if (summary.site_audit_status) quickRows['site audit status'] = summary.site_audit_status;
            if (summary.site_audit_issues != null) quickRows['site audit issues'] = summary.site_audit_issues;
            if (summary.pagespeed_status) quickRows['pagespeed status'] = summary.pagespeed_status;
            if (summary.pagespeed_overall_score != null) quickRows['pagespeed overall score'] = summary.pagespeed_overall_score;
            if (summary.sitemap_robots_status) quickRows['sitemap robots status'] = summary.sitemap_robots_status;
            if (summary.redirects_status) quickRows['redirects status'] = summary.redirects_status;
            if (summary.redirect_ready != null) quickRows['redirect fixes ready'] = summary.redirect_ready;
            if (summary.schema_status) quickRows['schema status'] = summary.schema_status;
            if (summary.internal_linking_status) quickRows['internal linking status'] = summary.internal_linking_status;
            summaryBuckets.push(renderSummaryRows(quickRows));
        } else {
            summaryBuckets.push(renderSummaryRows(summary));
        }
        return '' +
            '<div class="aysa-agent8-card">' +
                '<div class="aysa-agent8-card-header">' +
                    '<p class="aysa-agent8-card-kicker">Technical</p>' +
                    '<h3 class="aysa-agent8-card-title">' + escapeHtml(titleMap[type] || 'Technical Optimization') + '</h3>' +
                '</div>' +
                '<div class="aysa-agent8-card-body">' +
                    (intro ? '<p class="aysa-agent8-card-summary-row">' + escapeHtml(intro) + '</p>' : '') +
                    '<div class="aysa-agent8-card-summary">' +
                        summaryBuckets.join('') +
                        renderList('Ce merită atacat prima dată', topPriorities) +
                        renderList('Se poate rezolva automat', autoActions) +
                        renderList('Cere confirmare', needsConfirmation) +
                        sectionHtml +
                    '</div>' +
                '</div>' +
            '</div>';
    }

    function executeUiCommand(result, isBootstrap) {
        const actionResult = result && result.action_result ? result.action_result : null;
        const command = actionResult && actionResult.ui_command ? actionResult.ui_command : null;
        const actionKey = String(actionResult && actionResult.action_key ? actionResult.action_key : '');
        if (!command) {
            return;
        }
        if (command.type === 'open_keyword_review') {
            if ([
                'show_keyword_mapping',
                'show_found_keywords',
                'reject_found_keyword',
                'accept_keyword_mapping',
                'reject_keyword_mapping',
                'request_mapping_alternative',
                'apply_mapping_replacement',
                'undo_recent_delete'
            ].indexOf(actionKey) < 0) {
                return;
            }
            openKeywordReviewModal();
            return;
        }
        if (command.type === 'open_research_competitors_review') {
            if (['show_research_competitors', 'reject_research_competitor', 'undo_recent_delete'].indexOf(actionKey) < 0) {
                return;
            }
            openCompetitorsReviewModal();
            return;
        }
        if (command.type === 'open_missing_pages_review') {
            if ([
                'show_missing_pages',
                'send_missing_pages_to_plan',
                'reject_missing_page',
                'accept_missing_page_ai_proposal',
                'choose_missing_page_existing_page',
                'keep_missing_page',
                'undo_recent_delete'
            ].indexOf(actionKey) < 0) {
                return;
            }
            openMissingPagesReviewModal();
            return;
        }
        if (command.type === 'open_content_strategy_review') {
            if (['show_content_strategy', 'show_planned_content', 'update_content_strategy_items', 'reject_planned_content', 'undo_recent_delete'].indexOf(actionKey) < 0) {
                return;
            }
            openContentStrategyReviewModal();
            return;
        }
        if (command.type === 'open_publishing_calendar_modal') {
            if (['show_publishing_calendar'].indexOf(actionKey) < 0) {
                return;
            }
            openPublishingCalendarModal(command);
            return;
        }
        if (command.type === 'open_offpage_article_preview') {
            if (['preview_offpage_draft_article'].indexOf(actionKey) < 0) {
                return;
            }
            openArticlePreviewModal(command);
            return;
        }
        if (command.type === 'open_offpage_purchase_preview') {
            if (['preview_offpage_link_insertion_order', 'preview_offpage_seo_text_ads_order'].indexOf(actionKey) < 0) {
                return;
            }
            openPurchasePreviewModal(command);
            return;
        }
        if (
            command.type === 'open_technical_overview'
            || command.type === 'open_technical_site_audit_review'
            || command.type === 'open_technical_pagespeed_review'
            || command.type === 'open_technical_schema_review'
            || command.type === 'open_technical_redirects_review'
            || command.type === 'open_technical_sitemap_robots_review'
            || command.type === 'open_technical_internal_linking_review'
        ) {
            openTechnicalReviewModal();
            return;
        }
        if (command.type === 'open_url') {
            const targetUrl = String(command.url || '');
            if (!targetUrl) {
                return;
            }
            openExternalUrl(targetUrl, command.title || '');
            return;
        }
        if (command.type !== 'oauth_start') {
            return;
        }
        if (isBootstrap || oauthCallbackJustReturned) {
            oauthCallbackJustReturned = false;
            return;
        }
        const authUrl = String(command.auth_url || '');
        if (!authUrl) {
            return;
        }
        window.location.href = authUrl;
    }

    function stopAsyncPolling() {
        currentAsyncJob = null;
        asyncLastEventId = 0;
        if (asyncPollTimer) {
            window.clearTimeout(asyncPollTimer);
            asyncPollTimer = null;
        }
    }

    function stopConversationPolling() {
        currentConversationRunId = '';
        if (conversationPollTimer) {
            window.clearTimeout(conversationPollTimer);
            conversationPollTimer = null;
        }
    }

    function scheduleConversationPolling(mode, userMessage, extraPayload) {
        if (!currentConversationRunId || conversationPollTimer) {
            return;
        }
        conversationPollTimer = window.setTimeout(function() {
            conversationPollTimer = null;
            pollConversationStatus(mode, userMessage, extraPayload);
        }, 500);
    }

    function resetConversationPollingHealth() {
        conversationPollFailures = 0;
        conversationPollStartedAt = Date.now();
    }

    function abortConversationPolling(message) {
        stopConversationPolling();
        currentConversationRunId = '';
        conversationPollFailures = 0;
        conversationPollStartedAt = 0;
        $('#aysa-agent8-send').prop('disabled', false);
        $('#aysa-agent8-pending').attr('hidden', 'hidden');
        renderTranscript();
        if (message) {
            alert(String(message));
        }
    }

    function shouldAbortConversationPolling() {
        const ageMs = conversationPollStartedAt > 0 ? (Date.now() - conversationPollStartedAt) : 0;
        return conversationPollFailures >= 5 || ageMs > 30000;
    }

    function relaxBootstrapPendingIfSlow(mode) {
        if (mode !== 'bootstrap') {
            return;
        }
        return;
    }

    function startConversationAsync(mode, userMessage, extraPayload) {
        const requestEpoch = extraPayload && extraPayload.request_epoch != null
            ? (Number(extraPayload.request_epoch) || 0)
            : conversationRequestEpoch;
        const payload = Object.assign({
            action: 'aysa_conversation_async_start',
            task: 'agent8',
            nonce: nonce,
            mode: mode,
            project_id: projectId,
            wp_project_id: wpProjectId,
            site_host: siteHost,
            conversation_language: conversationLanguage,
            request_epoch: requestEpoch
        }, extraPayload || {});
        if (conversationId) {
            payload.conversation_id = conversationId;
        }
        if (userMessage) {
            payload.user_message = userMessage;
        }
        if (mode === 'message' && state && typeof state === 'object' && Object.keys(state).length) {
            payload.client_state = JSON.stringify(state);
        }

        pendingApproval = null;
        currentSuggestions = [];
        currentConversationRunId = '';
        resetConversationPollingHealth();
        $('#aysa-agent8-send').prop('disabled', true);
        $('#aysa-agent8-pending').attr('data-mode', 'thinking');
        applyUiLanguage();
        $('#aysa-agent8-pending').removeAttr('hidden');
        renderTranscript();

        $.post(ajaxUrl, payload).done(function(response) {
            if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                return;
            }
            if (!response || !response.success || !response.data) {
                abortConversationPolling('Agent 8 bootstrap failed.');
                return;
            }
            currentConversationRunId = String(response.data.run_id || '');
            const status = String(response.data.status || '');
            if (status === 'completed' && response.data.result) {
                stopConversationPolling();
                $('#aysa-agent8-send').prop('disabled', false);
                $('#aysa-agent8-pending').attr('hidden', 'hidden');
                applyResult(response.data.result.result || {}, response.data.result.wallet_snapshot || {}, mode === 'bootstrap' || mode === 'reset');
                return;
            }
            if (!currentConversationRunId) {
                abortConversationPolling('Agent 8 bootstrap did not start correctly.');
                return;
            }
            scheduleConversationPolling(mode, userMessage, Object.assign({}, extraPayload || {}, { request_epoch: requestEpoch }));
        }).fail(function(xhr) {
            if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                return;
            }
            abortConversationPolling(
                xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message
                    ? xhr.responseJSON.data.message
                    : 'Agent 8 bootstrap failed.'
            );
        });
    }

    function pollConversationStatus(mode, userMessage, extraPayload) {
        const requestEpoch = extraPayload && extraPayload.request_epoch != null
            ? (Number(extraPayload.request_epoch) || 0)
            : conversationRequestEpoch;
        if (!isCurrentConversationRequestEpoch(requestEpoch)) {
            stopConversationPolling();
            return;
        }
        if (!currentConversationRunId) {
            return;
        }
        const payload = Object.assign({
            action: 'aysa_conversation_async_status',
            nonce: nonce,
            task: 'agent8',
            mode: mode,
            project_id: projectId,
            wp_project_id: wpProjectId,
            site_host: siteHost,
            conversation_language: conversationLanguage,
            run_id: currentConversationRunId,
            request_epoch: requestEpoch
        }, extraPayload || {});
        if (conversationId) {
            payload.conversation_id = conversationId;
        }
        if (userMessage) {
            payload.user_message = userMessage;
        }
        $.post(ajaxUrl, payload).done(function(response) {
            if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                return;
            }
            if (!response || !response.success || !response.data) {
                conversationPollFailures += 1;
                if (shouldAbortConversationPolling()) {
                    abortConversationPolling('Agent 8 is temporarily unavailable. Refresh the page and try again.');
                    return;
                }
                scheduleConversationPolling(mode, userMessage, extraPayload);
                return;
            }
            conversationPollFailures = 0;
            const data = response.data || {};
            const status = String(data.status || '');
            if (status === 'queued' || status === 'running') {
                relaxBootstrapPendingIfSlow(mode);
                scheduleConversationPolling(mode, userMessage, extraPayload);
                return;
            }
            stopConversationPolling();
            if (status === 'completed' && data.result) {
                $('#aysa-agent8-send').prop('disabled', false);
                $('#aysa-agent8-pending').attr('hidden', 'hidden');
                applyResult(data.result.result || {}, data.result.wallet_snapshot || {}, mode === 'bootstrap' || mode === 'reset');
                return;
            }
            alert(String((data && data.error) || 'Agent 8 request failed.'));
            $('#aysa-agent8-send').prop('disabled', false);
            $('#aysa-agent8-pending').attr('hidden', 'hidden');
            renderTranscript();
        }).fail(function() {
            if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                return;
            }
            conversationPollFailures += 1;
            if (shouldAbortConversationPolling()) {
                abortConversationPolling('Agent 8 status polling failed repeatedly. Refresh the page to resume.');
                return;
            }
            relaxBootstrapPendingIfSlow(mode);
            scheduleConversationPolling(mode, userMessage, extraPayload);
        });
    }

    function appendAsyncStatusEvents(events) {
        if (!Array.isArray(events) || !events.length) {
            return;
        }
        events.forEach((event) => {
            const message = String(event && event.message_text ? event.message_text : '');
            if (!message) {
                return;
            }
            transcript.push({ role: 'assistant', message: message });
            const eventId = Number(event.id || 0) || 0;
            if (eventId > asyncLastEventId) {
                asyncLastEventId = eventId;
            }
        });
    }

    function asyncTaskLabel(taskKey) {
        const normalized = String(taskKey || '').toLowerCase().replace(/-/g, '_');
        if (!normalized) {
            return conversationLanguage === 'ro' ? 'următoarea etapă' : 'next step';
        }
        if (normalized.indexOf('business_profile') >= 0 && normalized.indexOf('crawl') >= 0) {
            return conversationLanguage === 'ro' ? 'colectarea dovezilor business' : 'business evidence collection';
        }
        if (normalized.indexOf('business_profile') >= 0 && normalized.indexOf('ai_extract') >= 0) {
            return conversationLanguage === 'ro' ? 'interpretarea semantică a profilului' : 'semantic profile interpretation';
        }
        if (normalized.indexOf('business_profile') >= 0 && normalized.indexOf('guardrail') >= 0) {
            return conversationLanguage === 'ro' ? 'validarea câmpurilor business' : 'business field validation';
        }
        if (normalized.indexOf('business_profile') >= 0 && normalized.indexOf('projection') >= 0) {
            return conversationLanguage === 'ro' ? 'pregătirea propunerii Business Profile' : 'Business Profile proposal sync';
        }
        if (normalized.indexOf('site_audit') >= 0 || normalized.indexOf('crawl') >= 0) {
            return conversationLanguage === 'ro' ? 'auditul tehnic al site-ului' : 'site audit';
        }
        if (normalized.indexOf('pagespeed') >= 0 || normalized.indexOf('lighthouse') >= 0) {
            return 'PageSpeed';
        }
        if (normalized.indexOf('schema') >= 0) {
            return 'Schema';
        }
        if (normalized.indexOf('redirect') >= 0 || normalized.indexOf('404') >= 0) {
            return conversationLanguage === 'ro' ? 'verificarea redirecturilor' : 'redirect review';
        }
        if (normalized.indexOf('sitemap') >= 0 || normalized.indexOf('robots') >= 0) {
            return 'Sitemap / Robots';
        }
        if (normalized.indexOf('internal_link') >= 0 || normalized.indexOf('internal-link') >= 0) {
            return conversationLanguage === 'ro' ? 'legături interne' : 'internal linking';
        }
        if (normalized.indexOf('competitor') >= 0) {
            return conversationLanguage === 'ro' ? 'analiza competitorilor' : 'competitor analysis';
        }
        if (normalized.indexOf('mapping') >= 0 || normalized.indexOf('rerank') >= 0) {
            return conversationLanguage === 'ro' ? 'maparea keywordurilor către pagini' : 'keyword mapping';
        }
        if (normalized.indexOf('missing') >= 0) {
            return conversationLanguage === 'ro' ? 'identificarea paginilor lipsă' : 'missing pages analysis';
        }
        if (normalized.indexOf('plan') >= 0 || normalized.indexOf('strategy') >= 0) {
            return conversationLanguage === 'ro' ? 'construirea planului de conținut' : 'content planning';
        }
        if (normalized.indexOf('sync') >= 0 || normalized.indexOf('projection') >= 0 || normalized.indexOf('rag') >= 0) {
            return conversationLanguage === 'ro' ? 'sincronizarea finală a rezultatelor' : 'final result sync';
        }
        if (normalized.indexOf('keyword') >= 0 || normalized.indexOf('seed') >= 0 || normalized.indexOf('cluster') >= 0) {
            return conversationLanguage === 'ro' ? 'descoperirea și structurarea keywordurilor' : 'keyword discovery';
        }
        return taskKey;
    }

    function asyncJobTitle(progress) {
        const source = progress && typeof progress === 'object' ? progress : {};
        const jobType = String(
            source.job_type ||
            (currentAsyncJob && currentAsyncJob.job_type) ||
            ''
        ).toLowerCase().replace(/-/g, '_');
        const endpoint = String(
            source.status_endpoint ||
            (currentAsyncJob && currentAsyncJob.status_endpoint) ||
            ''
        ).toLowerCase();
        if (jobType.indexOf('business_profile') >= 0 || endpoint.indexOf('/setup/general/autofill') >= 0) {
            return 'Business Profile';
        }
        if (jobType.indexOf('setup_competition') >= 0 || endpoint.indexOf('/setup/competition/proposal') >= 0) {
            return 'Competition';
        }
        if (jobType.indexOf('site_audit') >= 0 || endpoint.indexOf('technical-site-audit') >= 0) {
            return conversationLanguage === 'ro' ? 'Site Audit' : 'Site Audit';
        }
        if (jobType.indexOf('pagespeed') >= 0 || endpoint.indexOf('technical-pagespeed') >= 0) {
            return 'PageSpeed';
        }
        if (jobType.indexOf('schema') >= 0 || endpoint.indexOf('technical-schema') >= 0) {
            return 'Schema';
        }
        if (jobType.indexOf('redirect') >= 0 || endpoint.indexOf('technical-redirects') >= 0) {
            return conversationLanguage === 'ro' ? 'Redirecturi' : 'Redirects';
        }
        if (jobType.indexOf('sitemap') >= 0 || jobType.indexOf('robots') >= 0 || endpoint.indexOf('technical-sitemap-robots') >= 0) {
            return 'Sitemap / Robots';
        }
        if (jobType.indexOf('internal_link') >= 0 || endpoint.indexOf('internal-link') >= 0) {
            return conversationLanguage === 'ro' ? 'Legături interne' : 'Internal Linking';
        }
        if (jobType.indexOf('onpage') >= 0 || endpoint.indexOf('onpage') >= 0) {
            return 'On-Page';
        }
        if (jobType.indexOf('keyword') >= 0 || endpoint.indexOf('keyword') >= 0) {
            return 'Keyword Research';
        }
        return conversationLanguage === 'ro' ? 'Job în fundal' : 'Background job';
    }

    function asyncEndpointForJobType(jobType) {
        const key = String(jobType || '').toLowerCase().replace(/-/g, '_');
        const byJobType = {
            business_profile_autofill: '/v1/setup/general/autofill/status',
            setup_competition_proposal: '/v1/setup/competition/proposal/status',
            keyword_research: '/v1/research-runs/keyword/status',
            technical_site_audit: '/v1/research-runs/technical-site-audit/status',
            technical_pagespeed: '/v1/research-runs/technical-pagespeed/status',
            technical_schema: '/v1/research-runs/technical-schema/status',
            technical_redirects: '/v1/research-runs/technical-redirects/status',
            technical_sitemap_robots: '/v1/research-runs/technical-sitemap-robots/status',
            technical_optimization: '/v1/research-runs/technical-optimization/status',
            internal_linking: '/v1/internal-link-runs/status',
            onpage: '/v1/onpage-runs/status'
        };
        return byJobType[key] || '';
    }

    function buildAsyncProgress(status) {
        const run = status && status.run && typeof status.run === 'object' ? status.run : {};
        const tasks = Array.isArray(status && status.tasks) ? status.tasks : [];
        const asyncOutcome = asyncOutcomeFromStatus(status);
        let completed = 0;
        let running = 0;
        let queued = 0;
        let failed = 0;
        let retrying = 0;
        let currentTask = String(run.current_task_key || '');
        tasks.forEach((task) => {
            const taskStatus = String(task && task.status ? task.status : '').toLowerCase();
            if (taskStatus === 'completed') {
                completed += 1;
            } else if (taskStatus === 'running') {
                running += 1;
                if (!currentTask) {
                    currentTask = String(task.task_key || '');
                }
            } else if (taskStatus === 'queued') {
                queued += 1;
            } else if (taskStatus === 'failed') {
                failed += 1;
            } else if (taskStatus === 'retry' || taskStatus === 'retrying') {
                retrying += 1;
            }
        });
        const total = tasks.length;
        const rawStatus = String(run.status || (currentAsyncJob && currentAsyncJob.status) || '').toLowerCase();
        const runType = String(run.run_type || '');
        const resolvedJobType = String((status && status.job_type) || runType || (currentAsyncJob && currentAsyncJob.job_type) || '');
        const resolvedEndpoint = String((status && status.status_endpoint) || asyncEndpointForJobType(resolvedJobType) || (currentAsyncJob && currentAsyncJob.status_endpoint) || '');
        const statusProjection = status && status.projection && typeof status.projection === 'object' ? status.projection : {};
        const projectionMissingFields = Array.isArray(statusProjection.missing_fields) ? statusProjection.missing_fields : [];
        let statusKey = retrying > 0 && (rawStatus === 'queued' || rawStatus === 'running') ? 'retrying' : (rawStatus || 'running');
        const rawTerminalStatuses = [
            'completed',
            'completed_with_missing_required',
            'completed_with_safe_fallback',
            'failed',
            'timeout',
            'queued_without_worker',
            'provider_failed',
            'sync_failed',
            'no_candidates'
        ];
        const rawStatusIsTerminal = rawTerminalStatuses.indexOf(rawStatus) !== -1;
        if (asyncOutcome && rawStatusIsTerminal) {
            statusKey = asyncOutcomeStatusKey(asyncOutcome, statusKey);
        } else if (statusKey === 'completed' && resolvedJobType.toLowerCase().replace(/-/g, '_').indexOf('business_profile') >= 0 && projectionMissingFields.length) {
            statusKey = 'completed_with_missing_required';
        }
        const terminalOutcome = statusKey === 'completed'
            || statusKey === 'completed_with_missing_required'
            || statusKey === 'completed_with_safe_fallback'
            || statusKey === 'outcome_success'
            || statusKey === 'outcome_partial'
            || statusKey === 'outcome_safe_fallback'
            || statusKey === 'outcome_sync_failed'
            || statusKey === 'outcome_provider_failed'
            || statusKey === 'outcome_no_candidates';
        const percent = total > 0 && !asyncOutcome
            ? Math.max(0, Math.min(100, Math.round((completed / total) * 100)))
            : (terminalOutcome ? 100 : (total > 0 ? Math.max(0, Math.min(100, Math.round((completed / total) * 100))) : 0));
        return {
            run_id: Number(run.id || (currentAsyncJob && currentAsyncJob.run_id) || 0) || 0,
            job_type: resolvedJobType,
            status_endpoint: resolvedEndpoint,
            status: statusKey,
            async_outcome: asyncOutcome,
            error_summary: status && status.error_summary && typeof status.error_summary === 'object'
                ? status.error_summary
                : (run && run.error_summary && typeof run.error_summary === 'object' ? run.error_summary : null),
            completed: completed,
            running: running,
            queued: queued,
            failed: failed,
            retrying: retrying,
            total: total,
            percent: percent,
            missing_fields: projectionMissingFields,
            next_missing_question: String(statusProjection.next_missing_question || ''),
            current_task: currentTask,
            current_label: asyncTaskLabel(currentTask),
            updated_at: new Date()
        };
    }

    function asyncOutcomeFromStatus(status) {
        if (!status || typeof status !== 'object') {
            return null;
        }
        if (status.async_outcome && typeof status.async_outcome === 'object') {
            return status.async_outcome;
        }
        if (status.run && status.run.async_outcome && typeof status.run.async_outcome === 'object') {
            return status.run.async_outcome;
        }
        if (status.projection && status.projection.async_outcome && typeof status.projection.async_outcome === 'object') {
            return status.projection.async_outcome;
        }
        return null;
    }

    function asyncOutcomeStatusKey(outcome, fallbackStatus) {
        const runOutcome = String(outcome && outcome.run_outcome ? outcome.run_outcome : '').toLowerCase();
        const businessState = String(outcome && outcome.business_state ? outcome.business_state : '').toLowerCase();
        if (runOutcome === 'success') {
            return 'outcome_success';
        }
        if (runOutcome === 'safe_fallback') {
            return 'outcome_safe_fallback';
        }
        if (runOutcome === 'partial' || businessState === 'draft_partial') {
            return 'outcome_partial';
        }
        if (runOutcome === 'sync_failed') {
            return 'outcome_sync_failed';
        }
        if (runOutcome === 'provider_failed') {
            return 'outcome_provider_failed';
        }
        if (runOutcome === 'no_candidates') {
            return 'outcome_no_candidates';
        }
        if (runOutcome === 'timeout') {
            return 'timeout';
        }
        if (runOutcome === 'queued_without_worker') {
            return 'queued_without_worker';
        }
        return fallbackStatus || 'running';
    }

    function asyncProgressStatusLabel(status) {
        const key = String(status || '').toLowerCase();
        const labels = {
            queued: conversationLanguage === 'ro' ? 'În coadă' : 'Queued',
            running: conversationLanguage === 'ro' ? 'Rulează' : 'Running',
            retrying: conversationLanguage === 'ro' ? 'Retry sigur' : 'Retrying',
            queued_without_worker: conversationLanguage === 'ro' ? 'Așteaptă workerul' : 'Waiting for worker',
            timeout: conversationLanguage === 'ro' ? 'Timeout' : 'Timeout',
            completed: conversationLanguage === 'ro' ? 'Complet' : 'Completed',
            completed_with_missing_required: conversationLanguage === 'ro' ? 'Draft pregătit' : 'Draft ready',
            completed_with_safe_fallback: conversationLanguage === 'ro' ? 'Completat parțial' : 'Completed with fallback',
            outcome_success: conversationLanguage === 'ro' ? 'Gata pentru review' : 'Ready for review',
            outcome_partial: conversationLanguage === 'ro' ? 'Draft incomplet' : 'Draft needs completion',
            outcome_safe_fallback: conversationLanguage === 'ro' ? 'Fallback · completare manuală' : 'Fallback · manual input required',
            outcome_sync_failed: conversationLanguage === 'ro' ? 'Sync eșuat' : 'Sync failed',
            outcome_provider_failed: conversationLanguage === 'ro' ? 'Analiză eșuată' : 'Analysis failed',
            outcome_no_candidates: conversationLanguage === 'ro' ? 'Fără rezultate acționabile' : 'No actionable results',
            failed: conversationLanguage === 'ro' ? 'Eșuat' : 'Failed',
            blocked: conversationLanguage === 'ro' ? 'Blocat' : 'Blocked'
        };
        return labels[key] || (key ? key : (conversationLanguage === 'ro' ? 'Rulează' : 'Running'));
    }

    function asyncProgressMessage(progress) {
        const status = String(progress && progress.status ? progress.status : '').toLowerCase();
        const jobType = String(progress && progress.job_type ? progress.job_type : '').toLowerCase().replace(/-/g, '_');
        const isBusinessProfile = jobType.indexOf('business_profile') >= 0;
        const isCompetitionProposal = jobType.indexOf('setup_competition') >= 0;
        const outcome = progress && progress.async_outcome && typeof progress.async_outcome === 'object' ? progress.async_outcome : null;
        if (outcome) {
            const outcomeReason = outcome.status_reason ? String(outcome.status_reason) : '';
            const recoveryActions = Array.isArray(outcome.recovery_actions) ? outcome.recovery_actions : [];
            if (status === 'outcome_success') {
                return conversationLanguage === 'ro' ? 'Rezultatele sunt pregătite pentru review.' : 'Results ready for review.';
            }
            if (status === 'outcome_partial') {
                return conversationLanguage === 'ro' ? 'Draft generat, dar mai trebuie completat.' : 'Draft generated, needs completion.';
            }
            if (status === 'outcome_safe_fallback') {
                return conversationLanguage === 'ro' ? 'Draft generat prin fallback. Este nevoie de completare manuală.' : 'Draft generated using fallback, manual input required.';
            }
            if (status === 'outcome_sync_failed') {
                const hint = recoveryActions.indexOf('retry_plugin_projection_sync') !== -1
                    ? (conversationLanguage === 'ro' ? ' Poți relua sincronizarea.' : ' You can retry sync.')
                    : '';
                return (conversationLanguage === 'ro' ? 'Datele au fost generate, dar sincronizarea în WordPress a eșuat.' : 'Data generated but sync to WordPress failed.') + hint;
            }
            if (status === 'outcome_provider_failed') {
                return conversationLanguage === 'ro' ? 'Analiza a eșuat înainte să producă date utilizabile.' : 'Analysis failed before usable data was produced.';
            }
            if (status === 'outcome_no_candidates') {
                return conversationLanguage === 'ro' ? 'Nu am găsit rezultate acționabile pentru review.' : 'No actionable results found.';
            }
            if (status === 'timeout') {
                return conversationLanguage === 'ro' ? 'Procesarea durează prea mult.' : 'Processing took too long.';
            }
            if (status === 'queued_without_worker') {
                return conversationLanguage === 'ro' ? 'Așteaptă workerul să preia jobul.' : 'Waiting for worker.';
            }
            if (outcomeReason) {
                return outcomeReason;
            }
        }
        if (status === 'completed_with_safe_fallback') {
            const error = progress && progress.error_summary && typeof progress.error_summary === 'object' ? progress.error_summary : null;
            const errorText = error && error.message ? String(error.message) : '';
            if (errorText) {
                return errorText;
            }
            return conversationLanguage === 'ro'
                ? 'AI-ul nu a putut interpreta complet profilul, așa că am păstrat doar câmpurile verificate direct. Completează manual detaliile lipsă.'
                : 'AI extraction failed, so I kept only directly verified fields. Please complete the missing details manually.';
        }
        if (status === 'completed_with_missing_required') {
            const missing = Array.isArray(progress && progress.missing_fields) ? progress.missing_fields : [];
            if (missing.length === 1 && String(missing[0]) === 'support_phone') {
                return conversationLanguage === 'ro'
                    ? 'Draftul Business Profile este pregătit. Mai lipsește numărul de telefon public pentru salvare.'
                    : 'Business Profile draft is ready. I still need the public phone number before saving.';
            }
            return conversationLanguage === 'ro'
                ? 'Draftul Business Profile este pregătit. Mai lipsesc câteva câmpuri obligatorii pentru salvare.'
                : 'Business Profile draft is ready. A few required fields are still needed before saving.';
        }
        if (status === 'completed') {
            if (isCompetitionProposal) {
                return conversationLanguage === 'ro' ? 'Propunerea Competition este pregătită pentru review.' : 'Competition proposal ready for review.';
            }
            if (isBusinessProfile) {
                return conversationLanguage === 'ro' ? 'Business Profile este pregătit pentru review.' : 'Business Profile draft ready for review.';
            }
            return conversationLanguage === 'ro' ? 'Keyword research s-a terminat. Rezultatele sunt pregătite pentru review.' : 'Keyword research completed. Results are ready for review.';
        }
        if (status === 'failed') {
            const error = progress && progress.error_summary && typeof progress.error_summary === 'object' ? progress.error_summary : null;
            const errorText = error && error.message ? String(error.message) : '';
            if (errorText) {
                return errorText;
            }
            return conversationLanguage === 'ro' ? 'Jobul s-a oprit cu eroare. Poți verifica statusul pentru detalii.' : 'The job stopped with an error. You can refresh the status for details.';
        }
        if (status === 'queued_without_worker' || status === 'timeout') {
            const error = progress && progress.error_summary && typeof progress.error_summary === 'object' ? progress.error_summary : null;
            const errorText = error && error.message ? String(error.message) : '';
            if (errorText) {
                return errorText;
            }
            return status === 'queued_without_worker'
                ? (conversationLanguage === 'ro' ? 'Jobul este în coadă, dar workerul nu l-a preluat încă.' : 'The job is queued, but the worker has not picked it up yet.')
                : (conversationLanguage === 'ro' ? 'Jobul durează mai mult decât era de așteptat.' : 'The job is taking longer than expected.');
        }
        if (status === 'retrying') {
            return conversationLanguage === 'ro' ? 'Încă lucrează în siguranță. Un task este reluat.' : 'Still working safely. One task is being retried.';
        }
        if (status === 'queued') {
            if (isCompetitionProposal) {
                return conversationLanguage === 'ro' ? 'Așteaptă ca workerul să înceapă propunerea Competition.' : 'Waiting for the worker to start the Competition proposal.';
            }
            if (isBusinessProfile) {
                return conversationLanguage === 'ro' ? 'Așteaptă ca workerul să înceapă analiza website-ului.' : 'Waiting for the worker to start website analysis.';
            }
            return conversationLanguage === 'ro' ? 'Așteaptă ca workerul să preia următoarele taskuri.' : 'Waiting for the worker to pick up the next tasks.';
        }
        if (isBusinessProfile) {
            return conversationLanguage === 'ro' ? 'Agent8 analizează website-ul și interpretează profilul business.' : 'Agent8 is analyzing the website and interpreting the business profile.';
        }
        if (isCompetitionProposal) {
            return conversationLanguage === 'ro' ? 'Construiesc propunerea de keyworduri și competitori.' : 'Building keyword and competitor proposal...';
        }
        return conversationLanguage === 'ro' ? 'Agent8 încă lucrează în fundal.' : 'Agent8 is still working in the background.';
    }

    function competitionFinalHandoffMessage(status) {
        const projection = status && status.projection && typeof status.projection === 'object' ? status.projection : {};
        if (projection && projection.needs_clarification) {
            return conversationLanguage === 'ro'
                ? 'Nu am putut construi încă o propunere Competition sigură. Adaugă seed keywords sau competitori direcți și pot reîncerca.'
                : 'I could not build a safe Competition proposal yet. Add seed keywords or direct competitors and I can retry.';
        }
        const keywords = Array.isArray(projection.keywords || projection.seed_keywords)
            ? (projection.keywords || projection.seed_keywords).map((item) => String(item || '').trim()).filter(Boolean)
            : [];
        const competitors = Array.isArray(projection.competitors)
            ? projection.competitors.map((item) => String(item || '').trim()).filter(Boolean)
            : [];
        if (!keywords.length && !competitors.length) {
            return asyncProgressMessage(currentAsyncProgress);
        }
        const keywordText = keywords.length ? keywords.slice(0, 5).join(', ') : '-';
        const competitorText = competitors.length ? competitors.slice(0, 5).join(', ') : '-';
        return conversationLanguage === 'ro'
            ? 'Propunerea Competition este gata. Seed keywords: ' + keywordText + '. Competitori: ' + competitorText + '.'
            : 'Competition proposal is ready. Seed keywords: ' + keywordText + '. Competitors: ' + competitorText + '.';
    }

    function maybeAppendCompetitionFinalHandoff(status, progress) {
        const jobType = String(progress && progress.job_type ? progress.job_type : '').toLowerCase().replace(/-/g, '_');
        if (jobType.indexOf('setup_competition') < 0) {
            return;
        }
        const runId = Number(progress && progress.run_id ? progress.run_id : 0) || 0;
        if (runId <= 0 || finalizedCompetitionProposalRuns[String(runId)]) {
            return;
        }
        const statusKey = String(progress && progress.status ? progress.status : '').toLowerCase();
        const terminalStatuses = ['completed', 'outcome_success', 'outcome_no_candidates', 'outcome_provider_failed', 'outcome_sync_failed', 'timeout', 'failed'];
        if (terminalStatuses.indexOf(statusKey) === -1) {
            return;
        }
        const message = competitionFinalHandoffMessage(status);
        if (!message) {
            return;
        }
        finalizedCompetitionProposalRuns[String(runId)] = true;
        transcript.push({
            role: 'assistant',
            message: message
        });
    }

    function businessProfileFinalHandoffMessage(progress) {
        const status = String(progress && progress.status ? progress.status : '').toLowerCase();
        const outcome = progress && progress.async_outcome && typeof progress.async_outcome === 'object' ? progress.async_outcome : null;
        const runOutcome = String(outcome && outcome.run_outcome ? outcome.run_outcome : '').toLowerCase();
        const businessState = String(outcome && outcome.business_state ? outcome.business_state : '').toLowerCase();
        const missingFields = Array.isArray(progress && progress.missing_fields)
            ? progress.missing_fields.map((field) => String(field || '').trim()).filter(Boolean)
            : [];
        const missingText = missingFields.length ? ': ' + missingFields.join(', ') : '';
        const nextQuestion = String(progress && progress.next_missing_question ? progress.next_missing_question : '').trim();
        const nextText = nextQuestion ? ' Next: ' + nextQuestion : '';
        if (status === 'outcome_safe_fallback' || status === 'completed_with_safe_fallback' || runOutcome === 'safe_fallback') {
            return 'Analysis finished using a safe fallback. I only kept fields that could be verified. Manual completion is still required' + missingText + '.' + nextText;
        }
        if (status === 'outcome_success' || status === 'completed' || runOutcome === 'success' || businessState === 'reviewable') {
            return 'Business profile draft is ready for review.';
        }
        if (status === 'outcome_sync_failed' || runOutcome === 'sync_failed') {
            return 'Data may have been generated, but sync failed. Please retry sync or refresh.';
        }
        if (status === 'outcome_partial' || runOutcome === 'partial' || businessState === 'draft_partial' || status === 'completed_with_missing_required') {
            return 'Draft generated, but required fields are still missing' + missingText + '.' + nextText;
        }
        if (status === 'outcome_provider_failed' || status === 'outcome_no_candidates' || status === 'timeout' || status === 'failed') {
            return asyncProgressMessage(progress);
        }
        return '';
    }

    function maybeAppendBusinessProfileFinalHandoff(progress) {
        const jobType = String(progress && progress.job_type ? progress.job_type : '').toLowerCase().replace(/-/g, '_');
        if (jobType.indexOf('business_profile') < 0) {
            return;
        }
        const runId = Number(progress && progress.run_id ? progress.run_id : 0) || 0;
        if (runId <= 0 || finalizedBusinessProfileAutofillRuns[String(runId)]) {
            return;
        }
        const status = String(progress && progress.status ? progress.status : '').toLowerCase();
        const terminalStatuses = [
            'completed',
            'completed_with_missing_required',
            'completed_with_safe_fallback',
            'outcome_success',
            'outcome_partial',
            'outcome_safe_fallback',
            'outcome_sync_failed',
            'outcome_provider_failed',
            'outcome_no_candidates',
            'timeout',
            'failed'
        ];
        if (terminalStatuses.indexOf(status) === -1) {
            return;
        }
        const message = businessProfileFinalHandoffMessage(progress);
        if (!message) {
            return;
        }
        finalizedBusinessProfileAutofillRuns[String(runId)] = true;
        transcript.push({
            role: 'assistant',
            message: message
        });
    }

    function asyncProgressTime(value) {
        const date = value instanceof Date ? value : new Date();
        try {
            return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
        } catch (e) {
            return '';
        }
    }

    function renderAsyncProgressSticky() {
        $('#aysa-agent8-async-sticky').remove();
        if (!currentAsyncProgress) {
            return;
        }
        const status = String(currentAsyncProgress.status || '').toLowerCase();
        if (status !== 'queued' && status !== 'running' && status !== 'retrying') {
            return;
        }
        const jobType = String(currentAsyncProgress.job_type || '').toLowerCase().replace(/-/g, '_');
        const isCompletedBusinessProfile = jobType.indexOf('business_profile') >= 0 && (status === 'completed' || status === 'completed_with_missing_required' || status === 'completed_with_safe_fallback' || status === 'outcome_success' || status === 'outcome_partial' || status === 'outcome_safe_fallback');
        if (isCompletedBusinessProfile && (currentModuleSlug !== 'setup_seo_profile' || currentTabSlug !== 'business_profile')) {
            currentAsyncProgress = null;
            currentAsyncJob = null;
            return;
        }
        const percent = Number(currentAsyncProgress.percent || 0) || 0;
        const total = Number(currentAsyncProgress.total || 0) || 0;
        const countText = total > 0
            ? String(currentAsyncProgress.completed || 0) + '/' + String(total)
            : (status === 'completed' || status === 'outcome_success' || status === 'outcome_partial' || status === 'outcome_safe_fallback' || status === 'outcome_sync_failed' || status === 'outcome_provider_failed' || status === 'outcome_no_candidates'
                ? (conversationLanguage === 'ro' ? 'complet' : 'completed')
                : (conversationLanguage === 'ro' ? 'progres indisponibil' : 'progress unavailable'));
        const title = asyncJobTitle(currentAsyncProgress);
        let statusLabelText = asyncProgressStatusLabel(status);
        if (jobType.indexOf('business_profile') >= 0 && status === 'outcome_partial') {
            statusLabelText = conversationLanguage === 'ro' ? 'Analiză completă · Profilul trebuie completat' : 'Analysis complete · Business Profile needs completion';
        }
        if (status === 'completed_with_missing_required' && Array.isArray(currentAsyncProgress.missing_fields) && currentAsyncProgress.missing_fields.length === 1 && String(currentAsyncProgress.missing_fields[0]) === 'support_phone') {
            statusLabelText = conversationLanguage === 'ro' ? 'Draft pregătit · Lipsește telefonul' : 'Draft ready · Needs phone';
        }
        const detailText = (status === 'failed' || status === 'completed_with_missing_required' || status === 'completed_with_safe_fallback' || status === 'outcome_success' || status === 'outcome_partial' || status === 'outcome_safe_fallback' || status === 'outcome_sync_failed' || status === 'outcome_provider_failed' || status === 'outcome_no_candidates' || status === 'timeout' || status === 'queued_without_worker')
            ? asyncProgressMessage(currentAsyncProgress)
            : countText;
        const html = '<div class="aysa-agent8-async-sticky" id="aysa-agent8-async-sticky">'
            + '<div class="aysa-agent8-async-sticky-row"><strong>' + escapeHtml(title) + ' · ' + escapeHtml(String(percent)) + '% · ' + escapeHtml(statusLabelText) + '</strong><span class="aysa-agent8-async-sticky-mini" title="' + escapeAttribute(countText + ' · ' + String(currentAsyncProgress.current_label || '')) + '"><span style="width:' + escapeHtml(String(percent)) + '%"></span></span><span class="aysa-agent8-async-meta">' + escapeHtml(detailText) + '</span><button type="button" class="aysa-agent8-async-refresh">Refresh</button></div>'
            + '</div>';
        $('#aysa-agent8-pending').after(html);
    }

    function asyncStatusEndpoint() {
        const endpoint = String(
            (currentAsyncProgress && currentAsyncProgress.status_endpoint) ||
            (currentAsyncJob && currentAsyncJob.status_endpoint) ||
            ''
        );
        if (endpoint) {
            return endpoint;
        }
        const jobType = String(
            (currentAsyncJob && currentAsyncJob.job_type) ||
            (currentAsyncProgress && currentAsyncProgress.job_type) ||
            ''
        ).toLowerCase().replace(/-/g, '_');
        if (jobType.indexOf('business_profile') >= 0) {
            return '/v1/setup/general/autofill/status';
        }
        if (jobType.indexOf('setup_competition') >= 0) {
            return '/v1/setup/competition/proposal/status';
        }
        if (jobType.indexOf('site_audit') >= 0) {
            return '/v1/research-runs/technical-site-audit/status';
        }
        if (jobType.indexOf('pagespeed') >= 0) {
            return '/v1/research-runs/technical-pagespeed/status';
        }
        if (jobType.indexOf('schema') >= 0) {
            return '/v1/research-runs/technical-schema/status';
        }
        if (jobType.indexOf('redirect') >= 0) {
            return '/v1/research-runs/technical-redirects/status';
        }
        if (jobType.indexOf('sitemap') >= 0 || jobType.indexOf('robots') >= 0) {
            return '/v1/research-runs/technical-sitemap-robots/status';
        }
        if (jobType.indexOf('internal_link') >= 0) {
            return '/v1/internal-link-runs/status';
        }
        if (jobType.indexOf('onpage') >= 0) {
            return '/v1/onpage-runs/status';
        }
        return asyncEndpointForJobType(jobType) || '/v1/research-runs/keyword/status';
    }

    function ensureAsyncPollingTargetFromProgress() {
        if (!currentAsyncProgress || typeof currentAsyncProgress !== 'object') {
            return;
        }
        if (!currentAsyncJob || typeof currentAsyncJob !== 'object') {
            currentAsyncJob = {};
        }
        if (currentAsyncProgress.run_id) {
            currentAsyncJob.run_id = Number(currentAsyncProgress.run_id || 0) || 0;
        }
        if (currentAsyncProgress.status) {
            currentAsyncJob.status = String(currentAsyncProgress.status || 'running');
        }
        if (currentAsyncProgress.job_type) {
            currentAsyncJob.job_type = String(currentAsyncProgress.job_type || '');
        }
        if (currentAsyncProgress.status_endpoint || currentAsyncJob.job_type) {
            currentAsyncJob.status_endpoint = String(currentAsyncProgress.status_endpoint || asyncStatusEndpoint());
        }
    }

    function scheduleAsyncPolling() {
        ensureAsyncPollingTargetFromProgress();
        const hasStatusEndpoint = !!(currentAsyncJob && (currentAsyncJob.status_endpoint || currentAsyncJob.job_type));
        const hasRunId = !!(currentAsyncJob && currentAsyncJob.run_id);
        if (!currentAsyncJob || (!hasRunId && !hasStatusEndpoint) || asyncPollTimer) {
            return;
        }
        const status = String(currentAsyncJob.status || '');
        if (status && status !== 'queued' && status !== 'running') {
            stopAsyncPolling();
            return;
        }
        asyncPollTimer = window.setTimeout(pollAsyncJobStatus, 4000);
    }

    function pollAsyncJobStatus() {
        asyncPollTimer = null;
        ensureAsyncPollingTargetFromProgress();
        const hasStatusEndpoint = !!(currentAsyncJob && (currentAsyncJob.status_endpoint || currentAsyncJob.job_type));
        const hasRunId = !!(currentAsyncJob && currentAsyncJob.run_id);
        if (!currentAsyncJob || (!hasRunId && !hasStatusEndpoint)) {
            return;
        }

        $.post(ajaxUrl, {
            action: 'aysa_keyword_research_run_status',
            nonce: nonce,
            project_id: projectId,
            run_id: currentAsyncJob.run_id || 0,
            status_endpoint: asyncStatusEndpoint(),
            job_type: String((currentAsyncJob && currentAsyncJob.job_type) || (currentAsyncProgress && currentAsyncProgress.job_type) || ''),
            after_event_id: asyncLastEventId
        }).done(function(response) {
            if (!response || !response.success || !response.data || !response.data.status) {
                scheduleAsyncPolling();
                return;
            }

            const status = response.data.status || {};
            const run = status.run || {};
            const walletSnapshot = response.data.wallet_snapshot || {};
            const billing = status.billing || {};

            currentAsyncJob = Object.assign({}, currentAsyncJob || {}, {
                run_id: Number(run.id || currentAsyncJob.run_id || 0) || 0,
                status: String(run.status || currentAsyncJob.status || ''),
                job_type: String((status && status.job_type) || (run && run.run_type) || (currentAsyncJob && currentAsyncJob.job_type) || ''),
                status_endpoint: String((status && status.status_endpoint) || asyncEndpointForJobType((status && status.job_type) || (run && run.run_type) || (currentAsyncJob && currentAsyncJob.job_type) || '') || (currentAsyncJob && currentAsyncJob.status_endpoint) || '')
            });
            currentAsyncProgress = buildAsyncProgress(status);
            const jobType = String((status && status.job_type) || (run && run.run_type) || '').toLowerCase().replace(/-/g, '_');
            const statusProjection = status && status.projection && typeof status.projection === 'object'
                ? status.projection
                : null;
            const normalizedRunStatus = String(run.status || '').toLowerCase();
            const businessProfileCompleted = normalizedRunStatus === 'completed' || normalizedRunStatus === 'completed_with_safe_fallback' || normalizedRunStatus === 'completed_with_missing_required';
	            if (businessProfileCompleted && jobType.indexOf('business_profile') >= 0 && statusProjection) {
	                currentProjection = statusProjection;
                currentModuleSlug = 'setup_seo_profile';
                currentTabSlug = 'business_profile';
                $('#aysa-agent8-module').text(humanizeSlug(currentModuleSlug));
                $('#aysa-agent8-tab').text(humanizeSlug(currentTabSlug));
                const businessController = currentSetupController();
                if (businessController) {
                    currentAllowedActionsAuthoritative = true;
                    currentAllowedActionKeys = businessController.allowedActionKeys.slice();
                    currentSuggestions = setupActionsFromContract(statusProjection);
                    persistentActions = [];
                } else if (isSetupProjection(statusProjection)) {
                    currentAllowedActionsAuthoritative = true;
                    currentAllowedActionKeys = [];
                    currentSuggestions = [];
                    persistentActions = [];
                }
			            }

	            const competitionCompleted = normalizedRunStatus === 'completed';
	            if (competitionCompleted && jobType.indexOf('setup_competition') >= 0 && statusProjection) {
	                currentProjection = statusProjection;
	                currentModuleSlug = 'setup_seo_profile';
	                currentTabSlug = 'competition';
	                $('#aysa-agent8-module').text(humanizeSlug(currentModuleSlug));
	                $('#aysa-agent8-tab').text(humanizeSlug(currentTabSlug));
                    const competitionController = currentSetupController();
                    if (competitionController) {
                        currentAllowedActionsAuthoritative = true;
                        currentAllowedActionKeys = competitionController.allowedActionKeys.slice();
                        currentSuggestions = setupActionsFromContract(statusProjection);
                        persistentActions = [];
                    } else if (isSetupProjection(statusProjection)) {
                        currentAllowedActionsAuthoritative = true;
                        currentAllowedActionKeys = [];
                        currentSuggestions = [];
                        persistentActions = [];
                    }
		            }

            if (billing && typeof billing === 'object' && billing.actual_credits_cents != null) {
                walletSnapshot.latest_usage_amount_cents = Number(billing.actual_credits_cents) || 0;
            }

            appendAsyncStatusEvents(status.events || []);
            maybeAppendBusinessProfileFinalHandoff(currentAsyncProgress);
            maybeAppendCompetitionFinalHandoff(status, currentAsyncProgress);
            renderWallet(walletSnapshot);
            renderTranscript();

            const runStatus = String(run.status || '');
            if (runStatus === 'queued' || runStatus === 'running') {
                scheduleAsyncPolling();
            } else {
                stopAsyncPolling();
            }
        }).fail(function() {
            scheduleAsyncPolling();
        });
    }

    function applyResult(result, walletSnapshot, replaceAll) {
        const responseLanguage = String(
            (result && result.state && result.state.meta && result.state.meta.language) ||
            result.conversation_language ||
            conversationLanguage ||
            'en'
        ).toLowerCase();
        if (/^[a-z]{2}$/.test(responseLanguage)) {
            conversationLanguage = responseLanguage;
        }
        applyUiLanguage();
        const actionWallet = result && result.action_result && result.action_result.credit_gate && result.action_result.credit_gate.wallet_snapshot
            ? result.action_result.credit_gate.wallet_snapshot
            : null;
        const resultWallet = result && result.wallet_snapshot && typeof result.wallet_snapshot === 'object'
            ? result.wallet_snapshot
            : {};
        const resultTopLevelWallet = result && (
            result.available_credits != null ||
            result.credits_available != null ||
            result.available_credits_cents != null
        ) ? {
            available_credits: result.available_credits,
            credits_available: result.credits_available,
            available_credits_cents: result.available_credits_cents
        } : {};
        const effectiveWalletSnapshot = normalizeWalletSnapshot(Object.assign(
            {},
            currentWalletSnapshot || {},
            walletSnapshot || {},
            resultWallet,
            resultTopLevelWallet,
            actionWallet && typeof actionWallet === 'object' ? actionWallet : {}
        ));
        renderStatus(result || {});
        if (Array.isArray(result && result.messages)) {
            if (replaceAll) {
                transcript = result.messages.slice();
            } else {
                const existingTranscriptKeys = {};
                transcript.forEach((item) => {
                    existingTranscriptKeys[String(item.role || '') + "\n" + String(item.message || '')] = true;
                });
                result.messages.forEach((item) => {
                    const key = String(item.role || '') + "\n" + String(item.message || '');
                    if (!existingTranscriptKeys[key]) {
                        transcript.push(item);
                        existingTranscriptKeys[key] = true;
                    }
                });
            }
        } else if (replaceAll) {
            transcript = Array.isArray(result.messages) ? result.messages.slice() : [];
        }
        syncInlineUi(result || {});
        const previousAsyncRunId = Number(currentAsyncJob && currentAsyncJob.run_id ? currentAsyncJob.run_id : 0) || 0;
        const previousAsyncProgress = currentAsyncProgress && typeof currentAsyncProgress === 'object' ? currentAsyncProgress : null;
        const nextAsyncJob = result && result.action_result && result.action_result.async_job && typeof result.action_result.async_job === 'object'
            ? result.action_result.async_job
            : null;
        const nextRun = result && result.action_result && result.action_result.run && typeof result.action_result.run === 'object'
            ? result.action_result.run
            : null;
        if (nextAsyncJob) {
            const nextJobType = String(nextAsyncJob.job_type || (nextRun && nextRun.run_type) || '').toLowerCase().replace(/-/g, '_');
            const initialAsyncTasks = nextJobType === 'business_profile_autofill'
                && result
                && result.action_result
                && Array.isArray(result.action_result.tasks)
                ? result.action_result.tasks
                : [];
            currentAsyncJob = nextAsyncJob;
            currentAsyncProgress = buildAsyncProgress({
                run: Object.assign({}, nextRun || {}, {
                    id: nextAsyncJob.run_id || (nextRun && nextRun.id) || 0,
                    status: nextAsyncJob.status || (nextRun && nextRun.status) || 'queued'
                }),
                tasks: initialAsyncTasks
            });
        } else if (nextRun && Number(nextRun.id || 0) > 0) {
            currentAsyncJob = Object.assign({}, currentAsyncJob || {}, {
                run_id: Number(nextRun.id || 0) || 0,
                status: String(nextRun.status || (currentAsyncJob && currentAsyncJob.status) || '')
            });
            currentAsyncProgress = buildAsyncProgress({
                run: nextRun,
                tasks: []
            });
        } else if (currentAsyncJob && ['queued', 'running'].indexOf(String(currentAsyncJob.status || '')) >= 0) {
            // Preserve the live research job while the user opens sync review surfaces.
            currentAsyncJob = currentAsyncJob;
        } else {
            currentAsyncJob = null;
        }
        if (
            previousAsyncProgress
            && currentAsyncProgress
            && Number(previousAsyncProgress.run_id || 0) === Number(currentAsyncProgress.run_id || 0)
            && Number(previousAsyncProgress.total || 0) > 0
            && Number(currentAsyncProgress.total || 0) <= 0
            && String(currentAsyncProgress.status || '').toLowerCase() !== 'failed'
        ) {
            currentAsyncProgress = Object.assign({}, previousAsyncProgress, {
                status: currentAsyncProgress.status || previousAsyncProgress.status,
                updated_at: new Date()
            });
        }
        if (currentProjection && String(currentProjection.type || '') === 'technical_schema') {
            const schemaSummary = currentProjection.summary && typeof currentProjection.summary === 'object'
                ? currentProjection.summary
                : {};
            const schemaStatus = String(schemaSummary.status || '').toLowerCase();
            if (schemaStatus === 'failed') {
                const schemaModuleState = schemaSummary.module_state && typeof schemaSummary.module_state === 'object'
                    ? schemaSummary.module_state
                    : {};
                const schemaRunId = Number(schemaModuleState.run_id || schemaModuleState.job_id || (currentAsyncJob && currentAsyncJob.run_id) || 0) || 0;
                const schemaErrorSummary = schemaSummary.error_summary && typeof schemaSummary.error_summary === 'object'
                    ? schemaSummary.error_summary
                    : {
                        message: String(schemaModuleState.last_error || 'Schema snapshot could not be loaded from WordPress.')
                    };
                currentAsyncJob = {
                    run_id: schemaRunId,
                    status: 'failed',
                    job_type: 'technical_schema',
                    status_endpoint: '/v1/research-runs/technical-schema/status'
                };
                currentAsyncProgress = {
                    run_id: schemaRunId,
                    job_type: 'technical_schema',
                    status_endpoint: '/v1/research-runs/technical-schema/status',
                    status: 'failed',
                    error_summary: schemaErrorSummary,
                    completed: 0,
                    running: 0,
                    queued: 0,
                    failed: 1,
                    retrying: 0,
                    total: 0,
                    percent: 0,
                    current_task: 'technical_schema_fetch_snapshot',
                    current_label: asyncTaskLabel('technical_schema_fetch_snapshot'),
                    updated_at: new Date()
                };
            }
        }
        const currentAsyncRunId = Number(currentAsyncJob && currentAsyncJob.run_id ? currentAsyncJob.run_id : 0) || 0;
        if (currentAsyncRunId !== previousAsyncRunId) {
            asyncLastEventId = 0;
        }
        renderWallet(effectiveWalletSnapshot);
        renderTranscript();
        if (
            result
            && (!result.ui_command || typeof result.ui_command !== 'object')
            && result.action_result
            && result.action_result.ui_command
            && typeof result.action_result.ui_command === 'object'
        ) {
            result.ui_command = result.action_result.ui_command;
        }
        executeUiCommand(result || {}, !!replaceAll);
        scheduleAsyncPolling();
        if (replaceAll && pendingExternalAction && !pendingExternalActionConsumed) {
            pendingExternalActionConsumed = true;
            transcript.push({
                role: 'assistant',
                message: 'Am preluat din Site Audit un bundle tehnic și pornesc acum aprobarea explicită în Agent8.'
            });
            renderTranscript();
            postAction(
                String(pendingExternalAction.action_key || ''),
                pendingExternalAction.action_payload && typeof pendingExternalAction.action_payload === 'object'
                    ? pendingExternalAction.action_payload
                    : {}
            );
        }
    }

    function normalizeKeywordStatus(value) {
        const status = String(value || 'review');
        if (status === 'selected') {
            return t({ ro: 'Păstrat', bg: 'Запазен', en: 'Kept' });
        }
        if (status === 'excluded') {
            return t({ ro: 'Refuzat', bg: 'Отказан', en: 'Rejected' });
        }
        return t({ ro: 'Review', bg: 'Преглед', en: 'Review' });
    }

    function keywordReviewTexts() {
        return {
            title: t({
                ro: 'Verifică pe scurt keywordurile și paginile asociate',
                bg: 'Прегледай накратко keyword-ите и свързаните страници',
                en: 'Quickly review the keywords and linked pages'
            }),
            intro: t({
                ro: 'Keyword mapping înseamnă că am legat cuvintele cheie pe care oamenii le caută în Google de paginile existente de pe site. Aici verifici doar dacă acel cuvânt cheie merită păstrat și dacă pagina asociată este potrivită. După acest pas, într-un modal separat vom vedea și paginile care lipsesc.',
                bg: 'Keyword mapping означава, че свързах ключовите думи, които хората търсят в Google, със съществуващите страници на сайта. Тук проверяваш само дали keyword-ът си струва да се запази и дали свързаната страница е правилна. След тази стъпка ще видим и липсващите страници в отделен modal.',
                en: 'Keyword mapping means I linked the keywords people search for on Google to the pages that already exist on your site. Here you only check whether the keyword should stay and whether the linked page is the right one. After this step, we will review missing pages in a separate modal.'
            }),
            introHelpTitle: t({
                ro: 'Ce înseamnă keyword mapping',
                bg: 'Какво означава keyword mapping',
                en: 'What keyword mapping means'
            }),
            introHelpBody: t({
                ro: 'În acest pas, Agent 8 îți arată cum a potrivit căutările reale din Google cu paginile deja existente pe site. Ideea nu este să verifici tot SEO-ul, ci doar două lucruri simple: 1. keywordul este bun pentru businessul tău; 2. pagina asociată este pagina corectă pentru acel keyword. Dacă keywordul nu este bun, îl scoatem. Dacă keywordul este bun, dar pagina nu este potrivită, scoatem doar asocierea și corectăm mai târziu pagina. În pasul următor vom vedea separat paginile care lipsesc complet, adică zone unde site-ul nu are încă o pagină potrivită.',
                bg: 'На тази стъпка Agent 8 ти показва как е съпоставил реалните търсения в Google със страниците, които вече съществуват на сайта. Идеята не е да проверяваш цялото SEO, а само две прости неща: 1. keyword-ът е добър за бизнеса ти; 2. свързаната страница е правилната за този keyword. Ако keyword-ът не е добър, го махаме. Ако keyword-ът е добър, но страницата не е правилна, махаме само свързването и после коригираме страницата. На следващата стъпка ще видим отделно липсващите страници, тоест местата, където сайтът още няма подходяща страница.',
                en: 'At this step, Agent 8 shows how it matched real Google searches to pages that already exist on your site. The idea is not to review all of SEO, but just two simple things: 1. the keyword is good for your business; 2. the linked page is the right page for that keyword. If the keyword is not good, we remove it. If the keyword is good but the page is wrong, we remove only the association and correct the page later. In the next step, we will separately review the missing pages, meaning places where the site does not yet have a suitable page.'
            }),
            keywordReject: t({ ro: 'Refuz keyword', bg: 'Откажи keyword', en: 'Reject keyword' }),
            associationReject: t({ ro: 'Refuz asocierea', bg: 'Откажи свързването', en: 'Reject association' }),
            keywordHelp: t({
                ro: 'Folosește asta dacă acel keyword nu este relevant pentru businessul tău sau nu vrei să-l folosim mai departe. Acțiunea scoate keywordul complet din lista activă și nu îl mai tratăm ca prioritate în pașii următori.',
                bg: 'Използвай това, ако този keyword не е релевантен за бизнеса ти или не искаш да го използваме по-нататък. Действието премахва keyword-а напълно от активния списък и няма да го третираме като приоритет в следващите стъпки.',
                en: 'Use this if that keyword is not relevant for your business or you do not want to use it going forward. This removes the keyword completely from the active list and we will not treat it as a priority in the next steps.'
            }),
            associationHelp: t({
                ro: 'Folosește asta dacă keywordul este bun, dar pagina pe care am legat-o nu este potrivită. Acțiunea scoate doar asocierea din review-ul curent. Keywordul rămâne bun, doar că trebuie să ne spui sau să stabilim ulterior ce pagină ar trebui folosită în loc.',
                bg: 'Използвай това, ако keyword-ът е добър, но страницата, която сме свързали, не е правилна. Действието премахва само свързването от текущия преглед. Keyword-ът остава добър, но после трябва да ни кажеш или да уточним коя страница трябва да се използва вместо това.',
                en: 'Use this if the keyword is good, but the page we linked is not the right one. This removes only the association from the current review. The keyword stays valid, but later you should tell us or we should decide which page should be used instead.'
            }),
            saving: t({ ro: 'Se salvează...', bg: 'Запазва се...', en: 'Saving...' }),
            keywordRemoved: t({
                ro: 'Am scos keywordul din listă. Dacă vrei, mai scoatem și altele, apoi continuăm.',
                bg: 'Премахнах keyword-а от списъка. Ако искаш, можем да махнем и други, после да продължим.',
                en: 'I removed the keyword from the list. If you want, we can remove others too and then continue.'
            }),
            associationCleared: t({
                ro: 'Am scos asocierea din review-ul curent. Dacă vrei, spune-mi ce pagină ar trebui folosită în loc.',
                bg: 'Премахнах свързването от текущия преглед. Ако искаш, кажи ми коя страница да използваме вместо това.',
                en: 'I removed the association from the current review. If you want, tell me which page we should use instead.'
            }),
            saveError: t({
                ro: 'Nu am putut salva modificarea.',
                bg: 'Не успях да запазя промяната.',
                en: 'I could not save the change.'
            }),
            noPage: t({ ro: '-', bg: '-', en: '-' })
        };
    }

	    function currentReviewPaginationPayload() {
	        const pagination = currentUiCommand && currentUiCommand.pagination && typeof currentUiCommand.pagination === 'object'
	            ? currentUiCommand.pagination
	            : {};
	        return {
	            offset: Math.max(0, Number(pagination.offset || 0)),
	            limit: Math.max(1, Number(pagination.limit || 24))
	        };
	    }

	    function shortKeywordReviewUrl(value) {
	        const raw = String(value || '').trim();
	        if (!raw) {
	            return '-';
	        }
	        try {
	            const parsed = new URL(raw, window.location.origin);
	            const parts = parsed.pathname.split('/').filter(Boolean);
	            const slug = parts.length ? parts[parts.length - 1] : parsed.hostname;
	            return slug ? slug.replace(/-/g, ' ') : parsed.hostname;
	        } catch (e) {
	            const parts = raw.split('/').filter(Boolean);
	            return (parts.length ? parts[parts.length - 1] : raw).replace(/-/g, ' ');
	        }
	    }

	    function renderKeywordReviewModal() {
	        const texts = keywordReviewTexts();
	        const command = currentUiCommand && currentUiCommand.type === 'open_keyword_review' ? currentUiCommand : null;
	        const reviewType = String((command && command.review_type) || 'keyword_mapping');
        const rows = command && Array.isArray(command.rows) ? command.rows : [];
        const pagination = command && command.pagination && typeof command.pagination === 'object' ? command.pagination : {};
        const totalItems = Number(pagination.total_items || (command && command.summary && command.summary.total_items) || (command && command.summary && command.summary.items) || rows.length || 0);
        const offset = Math.max(0, Number(pagination.offset || 0));
        const visibleCount = rows.length;
        const startRange = totalItems > 0 && visibleCount > 0 ? offset + 1 : 0;
        const endRange = totalItems > 0 && visibleCount > 0 ? offset + visibleCount : 0;
        $('#aysa-agent8-keyword-modal-title').text(String((command && command.title) || texts.title));
        $('#aysa-agent8-keyword-modal-intro').html(
            '<div style="display:flex;gap:8px;align-items:flex-start;">' +
                '<div style="flex:1 1 auto;">' + escapeHtml(String((command && command.intro) || texts.intro)) + '</div>' +
                '<button type="button" class="aysa-agent8-help-button" id="aysa-agent8-keyword-intro-help" data-help-title="' + encodeURIComponent(texts.introHelpTitle) + '" data-help-body="' + encodeURIComponent(texts.introHelpBody) + '">?</button>' +
            '</div>'
        );
        const rangeHtml = (reviewType === 'found_keywords' || reviewType === 'keyword_mapping')
            ? '<div style="margin-top:8px;display:flex;gap:10px;align-items:center;flex-wrap:wrap;">' +
                '<span>' + escapeHtml('Showing ' + startRange + '-' + endRange + ' of ' + totalItems) + '</span>' +
                (pagination.has_more
	                    ? '<button type="button" class="button button-secondary aysa-agent8-keyword-load-more" data-action-key="' + escapeAttribute(reviewType === 'found_keywords' ? 'show_found_keywords' : 'show_keyword_mapping') + '" data-next-offset="' + escapeAttribute(String(pagination.next_offset || endRange)) + '" data-limit="' + escapeAttribute(String(pagination.limit || visibleCount || 24)) + '">Load more</button>'
                    : '') +
              '</div>'
            : '';
        if (command && command.banner && command.banner.message) {
            const undoHtml = command.banner.undo_available
                ? ' <button type="button" class="button button-secondary aysa-agent8-inline-undo" data-action-key="' + encodeURIComponent(String(command.banner.undo_action_key || 'undo_recent_delete')) + '">' + escapeHtml(uiText('undo', conversationLanguage)) + '</button>'
                : '';
            $('#aysa-agent8-keyword-modal-status').html(escapeHtml(String(command.banner.message)) + undoHtml + rangeHtml).removeAttr('hidden');
        } else if (rangeHtml) {
            $('#aysa-agent8-keyword-modal-status').html(rangeHtml).removeAttr('hidden');
	        } else {
	            $('#aysa-agent8-keyword-modal-status').text('').attr('hidden', 'hidden');
		    }

	        const $keywordTable = $('#aysa-agent8-keyword-modal .aysa-agent8-modal-table');
	        if (reviewType === 'keyword_mapping') {
	            $keywordTable.addClass('aysa-agent8-keyword-mapping-table');
	            $keywordTable.find('thead tr').html(
	                '<th style="width:24%;">Keyword</th>' +
	                '<th style="width:26%;">Current mapped page</th>' +
	                '<th style="width:22%;">Decision</th>' +
	                '<th style="width:28%;">Change page</th>'
	            );
	        } else {
	            $keywordTable.removeClass('aysa-agent8-keyword-mapping-table');
	            $keywordTable.find('thead tr').html(
	                '<th>Keyword</th>' +
	                '<th>Volum</th>' +
	                '<th>Pagină asociată</th>' +
	                '<th>Status</th>' +
	                '<th></th>'
	            );
	        }
	        const bottomLoadMoreHtml = pagination.has_more
	            ? '<tr><td colspan="' + (reviewType === 'keyword_mapping' ? '4' : '5') + '" style="text-align:center;padding:16px;">' +
	                '<button type="button" class="button button-secondary aysa-agent8-keyword-load-more" data-action-key="' + escapeAttribute(reviewType === 'found_keywords' ? 'show_found_keywords' : 'show_keyword_mapping') + '" data-next-offset="' + escapeAttribute(String(pagination.next_offset || endRange)) + '" data-limit="' + escapeAttribute(String(pagination.limit || visibleCount || 24)) + '">Load more</button>' +
	              '</td></tr>'
	            : '';
	        $('#aysa-agent8-keyword-modal-body').html(rows.map((row) => {
	            const page = String(row.associated_page || '');
            const pageHtml = page
                ? '<a href="' + escapeHtml(page) + '" target="_blank" rel="noopener">' + escapeHtml(page) + '</a>'
                : '<span>' + escapeHtml(texts.noPage) + '</span>';
            const itemId = String(row.id || row.row_key || '');
            const alternatives = Array.isArray(row.alternative_candidates) ? row.alternative_candidates : [];
            const reviewContext = [];
            if (reviewType === 'keyword_mapping') {
                if (row.is_primary) {
                    reviewContext.push('Primary keyword');
                } else if (row.primary_keyword) {
                    reviewContext.push('Secondary · Primary: ' + String(row.primary_keyword));
                }
                if (Array.isArray(row.secondary_keywords) && row.secondary_keywords.length) {
                    reviewContext.push('Secondaries: ' + String(row.secondary_keywords.length));
                }
            }
            if (row.mapping_source) {
                reviewContext.push('Source: ' + String(row.mapping_source));
            }
            if (row.confidence != null && row.confidence !== '') {
                reviewContext.push('Score: ' + String(row.confidence));
            } else if (row.score != null && row.score !== '') {
                reviewContext.push('Score: ' + String(row.score));
            }
            if (row.page_type) {
                reviewContext.push('Page: ' + String(row.page_type));
            }
            if (row.intent) {
                reviewContext.push('Intent: ' + String(row.intent));
            }
            const reviewContextHtml = reviewType === 'keyword_mapping' && reviewContext.length
                ? '<div style="margin-top:4px;color:#64748b;font-size:11px;line-height:1.35;">' + escapeHtml(reviewContext.join(' · ')) + '</div>'
                : '';
	            const alternativeControls = reviewType === 'keyword_mapping'
	                ? (
	                    '<div class="aysa-agent8-keyword-mapping-replacement">' +
	                        '<span class="aysa-agent8-keyword-mapping-replacement-label">' + escapeHtml(row.replacement_url ? 'Replacement selected' : 'Choose replacement page') + '</span>' +
	                        '<div class="aysa-agent8-keyword-mapping-replacement-row">' +
	                            '<select class="aysa-agent8-mapping-alternative-select" data-item-id="' + escapeHtml(itemId) + '">' +
	                                '<option value="">' + escapeHtml('Select replacement page...') + '</option>' +
	                                alternatives.map((url) => {
	                                    const normalizedUrl = String(url);
	                                    const selected = row.replacement_url && normalizedUrl === String(row.replacement_url) ? ' selected' : '';
	                                    return '<option value="' + escapeAttribute(normalizedUrl) + '"' + selected + '>' + escapeHtml(shortKeywordReviewUrl(normalizedUrl)) + '</option>';
	                                }).join('') +
	                              '</select>' +
	                            '<input type="text" class="aysa-agent8-mapping-replacement-input" data-item-id="' + escapeHtml(itemId) + '" placeholder="Paste URL manually" value="' + escapeAttribute(String(row.replacement_url || '')) + '" />' +
	                            '<button type="button" class="button button-primary aysa-agent8-mapping-apply" data-action-key="apply_mapping_replacement" data-item-id="' + escapeHtml(itemId) + '"' + (row.replacement_url ? '' : ' disabled') + '>Apply</button>' +
	                        '</div>' +
	                    '</div>'
	                )
	                : '';
            const primaryRejectAction = reviewType === 'found_keywords'
                ? 'reject_found_keyword'
                : 'reject_keyword_mapping';
            const primaryRejectLabel = reviewType === 'found_keywords'
                ? texts.keywordReject
                : texts.associationReject;
	            if (reviewType === 'keyword_mapping') {
	                const replacementOpenClass = row.replacement_url ? ' is-changing-page' : '';
	                const pageLabel = shortKeywordReviewUrl(page);
	                const keywordMeta = [
	                    'Vol. ' + String(row.volume || 0),
	                    row.is_primary ? 'Primary' : (row.primary_keyword ? 'Secondary' : ''),
	                    row.intent ? 'Intent: ' + String(row.intent) : ''
	                ].filter(Boolean).join(' · ');
	                return '' +
	                    '<tr class="aysa-agent8-keyword-mapping-row' + replacementOpenClass + '" data-row-key="' + escapeHtml(String(row.row_key || '')) + '" data-item-id="' + escapeHtml(itemId) + '">' +
	                        '<td><div class="aysa-agent8-keyword-mapping-keyword"><strong>' + escapeHtml(String(row.keyword || '')) + '</strong><span class="aysa-agent8-keyword-mapping-meta">' + escapeHtml(keywordMeta) + '</span></div></td>' +
	                        '<td><div class="aysa-agent8-keyword-mapping-page">' + (page ? '<a href="' + escapeAttribute(page) + '" target="_blank" rel="noopener" title="' + escapeAttribute(page) + '">' + escapeHtml(pageLabel) + '</a><span class="aysa-agent8-keyword-mapping-url" title="' + escapeAttribute(page) + '">' + escapeHtml(page) + '</span>' : '<span>' + escapeHtml(texts.noPage) + '</span>') + '</div></td>' +
	                        '<td><div class="aysa-agent8-keyword-mapping-decision"><span class="aysa-agent8-keyword-status">' + escapeHtml(normalizeKeywordStatus(row.status)) + '</span>' + reviewContextHtml + '<div class="aysa-agent8-keyword-mapping-secondary-actions"><button type="button" class="button button-secondary aysa-agent8-mapping-accept" data-action-key="accept_keyword_mapping" data-item-id="' + escapeHtml(itemId) + '">Keep match</button><button type="button" class="button button-secondary aysa-agent8-review-delete" data-action-key="reject_found_keyword" data-item-id="' + escapeHtml(String(row.found_keyword_id || '')) + '">Remove keyword</button></div></div></td>' +
	                        '<td><div class="aysa-agent8-keyword-mapping-primary-actions"><button type="button" class="button button-secondary aysa-agent8-mapping-alternative" data-action-key="request_mapping_alternative" data-item-id="' + escapeHtml(itemId) + '" data-has-alternatives="' + (alternatives.length ? '1' : '0') + '">Wrong page / choose another</button></div>' + alternativeControls + '</td>' +
	                    '</tr>';
	            }
	            return '' +
	                '<tr data-row-key="' + escapeHtml(String(row.row_key || '')) + '">' +
	                    '<td><strong>' + escapeHtml(String(row.keyword || '')) + '</strong></td>' +
	                    '<td>' + escapeHtml(String(row.volume || 0)) + '</td>' +
	                    '<td>' + pageHtml + '</td>' +
	                    '<td><span class="aysa-agent8-keyword-status">' + escapeHtml(normalizeKeywordStatus(row.status)) + '</span>' + reviewContextHtml + '</td>' +
	                    '<td><div class="aysa-agent8-keyword-actions"><button type="button" class="button button-secondary aysa-agent8-review-delete" data-action-key="' + primaryRejectAction + '" data-item-id="' + escapeHtml(itemId) + '">' + escapeHtml(texts.keywordReject) + '</button></div></td>' +
	                '</tr>';
	        }).join('') + bottomLoadMoreHtml);
	    }

    function renderCompetitorsReviewModal() {
        const command = currentUiCommand && currentUiCommand.type === 'open_research_competitors_review' ? currentUiCommand : null;
        const rows = command && Array.isArray(command.rows) ? command.rows : [];
        $('#aysa-agent8-competitors-modal-title').text(String((command && command.title) || 'Competitors'));
        $('#aysa-agent8-competitors-modal-intro').text(String((command && command.intro) || ''));
        if (command && command.banner && command.banner.message) {
            const undoHtml = command.banner.undo_available
                ? ' <button type="button" class="button button-secondary aysa-agent8-inline-undo" data-action-key="' + encodeURIComponent(String(command.banner.undo_action_key || 'undo_recent_delete')) + '">' + escapeHtml(uiText('undo', conversationLanguage)) + '</button>'
                : '';
            $('#aysa-agent8-competitors-modal-status').html(escapeHtml(String(command.banner.message)) + undoHtml).removeAttr('hidden');
        } else {
            $('#aysa-agent8-competitors-modal-status').text('').attr('hidden', 'hidden');
        }
        $('#aysa-agent8-competitors-modal-body').html(rows.map((row) => {
            const url = String(row.url || '');
            const urlHtml = url ? '<a href="' + escapeAttribute(url) + '" target="_blank" rel="noopener">' + escapeHtml(url) + '</a>' : '<span>-</span>';
            return '' +
                '<tr>' +
                    '<td><strong>' + escapeHtml(String(row.name || '')) + '</strong></td>' +
                    '<td>' + urlHtml + '</td>' +
                    '<td>' + escapeHtml(String(row.status || 'active')) + '</td>' +
                    '<td><button type="button" class="button button-secondary aysa-agent8-review-delete" data-action-key="reject_research_competitor" data-item-id="' + escapeHtml(String(row.id || '')) + '">' + escapeHtml(uiText('delete', conversationLanguage)) + '</button></td>' +
                '</tr>';
        }).join(''));
    }

    function renderMissingPagesReviewModal() {
        const command = currentUiCommand && currentUiCommand.type === 'open_missing_pages_review' ? currentUiCommand : null;
        const groups = command && Array.isArray(command.groups) ? command.groups : [];
        const pagination = command && command.pagination && typeof command.pagination === 'object' ? command.pagination : {};
        const totalItems = Number(pagination.total_items || (command && command.summary && command.summary.total_items) || (command && command.summary && command.summary.items) || 0);
        const offset = Math.max(0, Number(pagination.offset || 0));
        const visibleCount = groups.reduce((count, group) => count + (Array.isArray(group.items) ? group.items.length : 0), 0);
        const startRange = totalItems > 0 && visibleCount > 0 ? offset + 1 : 0;
        const endRange = totalItems > 0 && visibleCount > 0 ? offset + visibleCount : 0;
        $('#aysa-agent8-missing-pages-modal-title').text(String((command && command.title) || 'Missing Pages'));
        $('#aysa-agent8-missing-pages-modal-intro').text(String((command && command.intro) || '') + ' Changing a page type or pressing Save sends that item into the content plan.');
        $('#aysa-agent8-missing-pages-send-to-plan, #aysa-agent8-missing-pages-send-selected').text('Save selected to plan');
        $('#aysa-agent8-missing-pages-modal-done').text('Continue without saving more');
        const rangeHtml = pagination && Number(pagination.limit || 0) > 0
            ? '<div style="margin-top:8px;display:flex;gap:10px;align-items:center;flex-wrap:wrap;">' +
                '<span>' + escapeHtml('Showing ' + startRange + '-' + endRange + ' of ' + totalItems) + '</span>' +
                (pagination.has_more
                    ? '<button type="button" class="button button-secondary aysa-agent8-missing-pages-load-more" data-action-key="show_missing_pages" data-next-offset="' + escapeAttribute(String(pagination.next_offset || endRange)) + '" data-limit="' + escapeAttribute(String(pagination.limit || visibleCount || 24)) + '">Load more</button>'
                    : '') +
              '</div>'
            : '';
        if (command && command.banner && command.banner.message) {
            const undoHtml = command.banner.undo_available
                ? ' <button type="button" class="button button-secondary aysa-agent8-inline-undo" data-action-key="' + encodeURIComponent(String(command.banner.undo_action_key || 'undo_recent_delete')) + '">' + escapeHtml(uiText('undo', conversationLanguage)) + '</button>'
                : '';
            $('#aysa-agent8-missing-pages-modal-status').html(escapeHtml(String(command.banner.message)) + undoHtml + rangeHtml).removeAttr('hidden');
        } else if (rangeHtml) {
            $('#aysa-agent8-missing-pages-modal-status').html(rangeHtml).removeAttr('hidden');
        } else {
            $('#aysa-agent8-missing-pages-modal-status').text('').attr('hidden', 'hidden');
        }
        const rows = [];
        groups.forEach((group) => {
            (Array.isArray(group.items) ? group.items : []).forEach((item) => rows.push({ group, item }));
        });
        const buckets = [
            { key: 'high', title: 'High confidence', note: 'Clear commercial/local opportunities that are usually safe to send to plan.', rows: [] },
            { key: 'review', title: 'Needs review', note: 'Useful ideas, but check the page type or intent before sending.', rows: [] },
            { key: 'noise', title: 'Suspicious / noise', note: 'Lower confidence, branded, broad, or ambiguous queries. Reject in batch if they do not fit.', rows: [] }
        ];
        const bucketFor = (item) => {
            const keyword = String(item.primary_keyword || item.keyword || '').toLowerCase();
            const intent = String(item.intent || '').toLowerCase();
            const reason = String(item.recommendation_reason || '').toLowerCase();
            const pageType = String(item.recommended_page_type || item.page_type || '').toLowerCase();
            const suspicious = /(magnolia|iris|youtube|facebook|pinterest|program|poze|imagini|near me|langa mine|ieftin|gratis|olx|emag)/i.test(keyword)
                || /unknown|informational/.test(intent)
                || /noise|brand|competitor/.test(reason);
            if (suspicious) {
                return 'noise';
            }
            if (/commercial|transactional|local/.test(intent) || /bragadiru|ilfov|livrare|flori|buchet/.test(keyword)) {
                return 'high';
            }
            if (pageType === 'article') {
                return 'review';
            }
            return 'review';
        };
        rows.forEach((row) => {
            const key = bucketFor(row.item);
            const bucket = buckets.find((candidate) => candidate.key === key) || buckets[1];
            bucket.rows.push(row);
        });
        const renderItem = ({ group, item }) => {
            const keyword = String(item.primary_keyword || item.keyword || '-');
            const pageType = String(item.recommended_page_type || group.page_type || 'landing_page');
            const source = String(item.source || 'missing_pages');
            const reason = String(item.recommendation_reason || item.resolution_reason || 'No suitable existing page was found.');
            const intent = String(item.intent || 'unknown');
            const resolutionStatus = String(item.resolution_status || 'unresolved');
            const savedState = resolutionStatus === 'sent_to_plan' ? 'saved' : (resolutionStatus === 'existing_in_plan' ? 'existing' : 'idle');
            const savedClass = savedState === 'saved' ? ' is-saved' : (savedState === 'existing' ? ' is-existing' : '');
            const savedLabel = savedState === 'saved' ? 'Saved to plan' : (savedState === 'existing' ? 'Already in plan' : 'Not saved');
            const volume = Number(item.volume || item.search_volume || 0);
            return '' +
                '<div class="aysa-agent8-missing-pages-item" data-item-id="' + escapeHtml(String(item.id || '')) + '" data-keyword="' + encodeURIComponent(keyword) + '" data-intent="' + encodeURIComponent(intent) + '" data-source="' + encodeURIComponent(source) + '" data-reason="' + encodeURIComponent(reason) + '" data-resolution-status="' + encodeURIComponent(resolutionStatus) + '">' +
	                    '<input type="checkbox" class="aysa-agent8-missing-page-select" />' +
	                    '<div>' +
	                        '<div class="aysa-agent8-missing-pages-keyword">' + escapeHtml(keyword) + '</div>' +
	                        '<div class="aysa-agent8-missing-pages-meta">' + escapeHtml(intent) + (volume > 0 ? ' · Vol. ' + escapeHtml(String(volume)) : '') + '</div>' +
	                    '</div>' +
	                    '<select class="aysa-agent8-missing-page-type" aria-label="Page type">' +
	                        '<option value="product"' + (pageType === 'product' ? ' selected' : '') + '>product</option>' +
	                        '<option value="landing_page"' + (pageType === 'landing_page' ? ' selected' : '') + '>landing_page</option>' +
                        '<option value="category_page"' + (pageType === 'category_page' ? ' selected' : '') + '>category_page</option>' +
                        '<option value="article"' + (pageType === 'article' ? ' selected' : '') + '>article</option>' +
                    '</select>' +
	                    '<span class="aysa-agent8-missing-pages-save-status' + savedClass + '" data-save-state="' + escapeAttribute(savedState) + '">' + escapeHtml(savedLabel) + '</span>' +
	                    '<div class="aysa-agent8-missing-pages-reason">' + escapeHtml(reason || 'Missing suitable page') + '</div>' +
	                    '<div class="aysa-agent8-missing-pages-inline-actions">' +
	                        '<button type="button" class="button button-secondary aysa-agent8-missing-page-save" data-action-key="send_missing_pages_to_plan">Save to plan</button>' +
	                        '<button type="button" class="button button-link-delete aysa-agent8-missing-page-reject" data-action-key="reject_missing_page">Reject</button>' +
	                    '</div>' +
	                '</div>';
	        };
	        const bottomLoadMoreHtml = pagination.has_more
	            ? '<div style="text-align:center;margin:16px 0;">' +
	                '<button type="button" class="button button-secondary aysa-agent8-missing-pages-load-more" data-action-key="show_missing_pages" data-next-offset="' + escapeAttribute(String(pagination.next_offset || endRange)) + '" data-limit="' + escapeAttribute(String(pagination.limit || visibleCount || 24)) + '">Load more</button>' +
	              '</div>'
	            : '';
	        $('#aysa-agent8-missing-pages-modal-body').html(
	            buckets.filter((bucket) => bucket.rows.length > 0).map((bucket) => '' +
                '<div class="aysa-agent8-missing-pages-decision-group" data-decision-group="' + escapeAttribute(bucket.key) + '">' +
                    '<div class="aysa-agent8-missing-pages-group-head">' +
                        '<div>' +
                            '<h3 class="aysa-agent8-missing-pages-group-title">' + escapeHtml(bucket.title) + ' (' + escapeHtml(String(bucket.rows.length)) + ')</h3>' +
                            '<div class="aysa-agent8-missing-pages-group-note">' + escapeHtml(bucket.note) + '</div>' +
                        '</div>' +
                        '<div class="aysa-agent8-missing-pages-group-actions">' +
                            '<button type="button" class="button button-secondary aysa-agent8-missing-pages-select-group">Select all in group</button>' +
                            '<button type="button" class="button button-secondary aysa-agent8-missing-pages-clear-group">Clear group selection</button>' +
                        '</div>' +
                    '</div>' +
                    '<div class="aysa-agent8-missing-pages-list">' +
                        bucket.rows.map(renderItem).join('') +
                    '</div>' +
                '</div>'
	            ).join('') +
	            bottomLoadMoreHtml +
	            '<div class="aysa-agent8-missing-pages-sticky">' +
                '<strong><span id="aysa-agent8-missing-pages-selected-count">0</span> selected</strong>' +
                '<div class="aysa-agent8-missing-pages-sticky-actions">' +
                    '<button type="button" class="button button-secondary" id="aysa-agent8-missing-pages-clear-selected">Clear selection</button>' +
                    '<button type="button" class="button button-primary" id="aysa-agent8-missing-pages-send-selected" data-action-key="send_missing_pages_to_plan">Save selected to plan</button>' +
                '</div>' +
            '</div>'
        );
        updateMissingPagesSelectionBar();
    }

    function renderContentStrategyReviewModal() {
        const command = currentUiCommand && currentUiCommand.type === 'open_content_strategy_review' ? currentUiCommand : null;
        const directItems = command && Array.isArray(command.items) ? command.items : [];
        const pageOptions = command && Array.isArray(command.page_options) ? command.page_options : [];
        const pagination = command && command.pagination && typeof command.pagination === 'object' ? command.pagination : {};
        const totalItems = Number(pagination.total_items || (command && command.summary && command.summary.total_items) || (command && command.summary && command.summary.items) || directItems.length || 0);
        const offset = Math.max(0, Number(pagination.offset || 0));
        const visibleCount = directItems.length;
        const startRange = totalItems > 0 && visibleCount > 0 ? offset + 1 : 0;
        const endRange = totalItems > 0 && visibleCount > 0 ? offset + visibleCount : 0;
        const groups = command && Array.isArray(command.groups) && command.groups.length
            ? command.groups
            : (directItems.length ? [{ group_key: 'planned_content', label: 'Planned Items', count: directItems.length, items: directItems }] : []);
        const searchLabel = conversationLanguage === 'ro' ? 'Caută pagină existentă' : 'Search existing page';
        const searchPlaceholder = conversationLanguage === 'ro'
            ? 'Caută după numele paginii sau slug'
            : 'Search by page name or slug';
        const manualLabel = conversationLanguage === 'ro' ? 'Sau lipește URL manual' : 'Or paste a URL manually';
        const selectedUrlLabel = conversationLanguage === 'ro' ? 'URL selectat' : 'Selected URL';
        const pickerHint = conversationLanguage === 'ro'
            ? 'Nu trebuie să știi URL-ul exact. Caută pagina după nume, iar Agent8 folosește URL-ul canonic.'
            : 'You do not need to know the exact URL. Search by page name and Agent8 will use the canonical URL.';
        $('#aysa-agent8-content-strategy-modal-title').text(String((command && command.title) || 'Content Strategy'));
        $('#aysa-agent8-content-strategy-modal-intro').text(String((command && command.intro) || ''));
        if (command && command.banner && command.banner.message) {
            const undoHtml = command.banner.undo_available
                ? ' <button type="button" class="button button-secondary aysa-agent8-inline-undo" data-action-key="' + encodeURIComponent(String(command.banner.undo_action_key || 'undo_recent_delete')) + '">' + escapeHtml(uiText('undo', conversationLanguage)) + '</button>'
                : '';
            $('#aysa-agent8-content-strategy-modal-status').html(escapeHtml(String(command.banner.message)) + undoHtml).removeAttr('hidden');
        } else {
            $('#aysa-agent8-content-strategy-modal-status').text('').attr('hidden', 'hidden');
        }
        const rangeHtml = Number(pagination.limit || 0) > 0
            ? '<div style="margin-top:8px;display:flex;gap:10px;align-items:center;flex-wrap:wrap;">' +
                '<span>' + escapeHtml('Showing ' + startRange + '-' + endRange + ' of ' + totalItems) + '</span>' +
                (pagination.has_more
	                    ? '<button type="button" class="button button-secondary aysa-agent8-content-strategy-load-more" data-action-key="show_planned_content" data-next-offset="' + escapeAttribute(String(pagination.next_offset || endRange)) + '" data-limit="' + escapeAttribute(String(pagination.limit || visibleCount || 24)) + '">Load more</button>'
                    : '') +
              '</div>'
            : '';
        if (rangeHtml) {
            const existingStatus = $('#aysa-agent8-content-strategy-modal-status').html();
            $('#aysa-agent8-content-strategy-modal-status').html((existingStatus ? existingStatus : '') + rangeHtml).removeAttr('hidden');
        }
	        const bottomLoadMoreHtml = pagination.has_more
	            ? '<div style="text-align:center;margin:16px 0;">' +
	                '<button type="button" class="button button-secondary aysa-agent8-content-strategy-load-more" data-action-key="show_planned_content" data-next-offset="' + escapeAttribute(String(pagination.next_offset || endRange)) + '" data-limit="' + escapeAttribute(String(pagination.limit || visibleCount || 24)) + '">Load more</button>' +
	              '</div>'
	            : '';
	        $('#aysa-agent8-content-strategy-modal-body').html(groups.map((group) => {
            const items = Array.isArray(group.items) ? group.items : [];
            return '' +
                '<div class="aysa-agent8-card" style="margin-bottom:16px;">' +
                    '<div class="aysa-agent8-card-header">' +
                        '<p class="aysa-agent8-card-kicker">Strategie</p>' +
                        '<h3 class="aysa-agent8-card-title">' + escapeHtml(String(group.label || group.group_key || '-')) + ' (' + escapeHtml(String(group.count || items.length || 0)) + ')</h3>' +
                    '</div>' +
                    '<div class="aysa-agent8-card-body">' +
                        items.map((item) => {
                            const title = String(item.title || item.proposed_title || '-');
                            const keywords = Array.isArray(item.keywords) ? item.keywords : [];
                            const associatedPageRaw = String(item.associated_page || '').trim();
                            const associatedPage = associatedPageRaw || 'neasociată încă';
                            const knownOption = pageOptions.find((option) => String((option && option.url) || '').trim() === associatedPageRaw) || null;
                            const searchValue = knownOption ? String(knownOption.search_value || '') : '';
                            const manualValue = knownOption ? '' : associatedPageRaw;
                            const datalistId = 'aysa-agent8-content-strategy-pages-' + escapeAttribute(String(item.item_id || item.id || title).replace(/[^a-zA-Z0-9_-]+/g, '-'));
                            const timing = String(item.published_at || item.scheduled_for || item.generated_at || '').trim();
                            const timingLabel = item.published_at ? 'Publicat' : (item.scheduled_for ? 'Programat' : 'Generat');
                            const keywordLine = keywords.length ? '<div class="aysa-agent8-card-summary-row"><strong>Keyworduri:</strong> ' + escapeHtml(keywords.join(', ')) + '</div>' : '';
                            const keywordValue = String(item.keyword || item.target_keyword || '').trim();
                            const themeValue = String(item.theme || '').trim();
                            const contentType = String(item.content_type || '').trim();
                            const priority = String(item.priority || '').trim();
                            const intent = String(item.intent || '').trim();
                            const source = String(item.source || '').trim();
                            const reason = String(item.reason || '').trim();
                            const eeat = String(item.eeat || item.authority_style || '').trim();
                            const freshness = String(item.freshness || item.seasonality || '').trim();
                            const editorialType = String(item.editorial_type || '').trim();
                            const editorialMeta = [
                                contentType ? '<span><strong>Content:</strong> ' + escapeHtml(contentType) + '</span>' : '',
                                priority ? '<span><strong>Prioritate:</strong> ' + escapeHtml(priority) + '</span>' : '',
                                intent ? '<span><strong>Intent:</strong> ' + escapeHtml(intent) + '</span>' : '',
                                source ? '<span><strong>Sursă:</strong> ' + escapeHtml(source) + '</span>' : ''
                            ].filter(Boolean).join(' · ');
                            const planningMeta = [
                                keywordValue ? '<span><strong>Keyword:</strong> ' + escapeHtml(keywordValue) + '</span>' : '',
                                themeValue ? '<span><strong>Temă:</strong> ' + escapeHtml(themeValue) + '</span>' : '',
                                eeat ? '<span><strong>EEAT:</strong> ' + escapeHtml(eeat) + '</span>' : '',
                                freshness ? '<span><strong>Freshness:</strong> ' + escapeHtml(freshness) + '</span>' : '',
                                editorialType ? '<span><strong>Editorial:</strong> ' + escapeHtml(editorialType) + '</span>' : ''
                            ].filter(Boolean).join(' · ');
                            const publicUrl = String(item.public_url || '').trim();
                            const editUrl = String(item.edit_url || '').trim();
                            const links = [];
                            if (publicUrl) {
                                links.push('<a href="' + escapeAttribute(publicUrl) + '" target="_blank" rel="noopener">Vezi public</a>');
                            }
                            if (editUrl) {
                                links.push('<a href="' + escapeAttribute(editUrl) + '" target="_blank" rel="noopener">Editează</a>');
                            }
                            return '' +
                                '<div class="aysa-agent8-content-strategy-item" data-item-id="' + escapeAttribute(String(item.item_id || '')) + '" data-id="' + escapeAttribute(String(item.id || '')) + '">' +
                                    '<div class="aysa-agent8-content-strategy-item-head">' +
                                        '<strong>' + escapeHtml(title) + '</strong>' +
                                        '<button type="button" class="button button-secondary aysa-agent8-content-strategy-reject" data-action-key="reject_planned_content">Refuz</button>' +
                                    '</div>' +
                                    '<div class="aysa-agent8-content-strategy-item-meta">' +
                                        '<span><strong>Tip pagină:</strong> ' + escapeHtml(String(item.recommended_page_type || item.target_page_type || '-')) + '</span>' +
                                        ' · <span><strong>Status:</strong> ' + escapeHtml(String(item.status || item.execution_stage || '-')) + '</span>' +
                                        ' · <span><strong>Pagină asociată:</strong> ' + escapeHtml(associatedPage) + '</span>' +
                                    '</div>' +
                                    (editorialMeta ? '<div class="aysa-agent8-content-strategy-item-meta">' + editorialMeta + '</div>' : '') +
                                    (planningMeta ? '<div class="aysa-agent8-content-strategy-item-meta">' + planningMeta + '</div>' : '') +
                                    (reason ? '<div class="aysa-agent8-card-summary-row"><strong>Motiv:</strong> ' + escapeHtml(reason) + '</div>' : '') +
                                    '<div class="aysa-agent8-content-strategy-item-actions">' +
                                        '<label>Asociază</label>' +
                                        '<div class="aysa-agent8-content-strategy-picker">' +
                                            '<input type="hidden" class="aysa-agent8-content-strategy-association" value="' + escapeAttribute(associatedPageRaw) + '">' +
                                            '<label>' + escapeHtml(searchLabel) + '</label>' +
                                            '<input type="text" class="aysa-agent8-content-strategy-page-search" list="' + datalistId + '" value="' + escapeAttribute(searchValue) + '" placeholder="' + escapeAttribute(searchPlaceholder) + '">' +
                                            '<datalist id="' + datalistId + '">' +
                                                pageOptions.map((option) => {
                                                    return '<option value="' + escapeAttribute(String((option && option.search_value) || '')) + '"></option>';
                                                }).join('') +
                                            '</datalist>' +
                                            '<div class="aysa-agent8-content-strategy-picker-hint">' + escapeHtml(pickerHint) + '</div>' +
                                            '<label>' + escapeHtml(manualLabel) + '</label>' +
                                            '<input type="text" class="aysa-agent8-content-strategy-manual" value="' + escapeAttribute(manualValue) + '" placeholder="https://...">' +
                                            '<div class="aysa-agent8-content-strategy-selected-url"><strong>' + escapeHtml(selectedUrlLabel) + ':</strong> <span>' + escapeHtml(associatedPageRaw || '-') + '</span></div>' +
                                        '</div>' +
                                    '</div>' +
                                    (timing ? '<div class="aysa-agent8-content-strategy-item-meta"><strong>' + escapeHtml(timingLabel) + ':</strong> ' + escapeHtml(timing) + '</div>' : '') +
                                    (links.length ? '<div class="aysa-agent8-content-strategy-item-links">' + links.join(' · ') + '</div>' : '') +
                                    keywordLine +
                                '</div>';
                        }).join('') +
                    '</div>' +
                '</div>';
	        }).join('') + bottomLoadMoreHtml);
	    }

    function renderTechnicalSummaryGrid(summary) {
        const data = summary && typeof summary === 'object' ? summary : {};
        const rows = Object.keys(data).map((key) => {
            return '<div><strong>' + escapeHtml(String(key)) + ':</strong> ' + escapeHtml(String(data[key] == null ? '-' : data[key])) + '</div>';
        }).join('');
        return rows ? '<div class="aysa-agent8-technical-grid">' + rows + '</div>' : '';
    }

    function renderTechnicalList(rows, mapper) {
        const list = Array.isArray(rows) ? rows.slice(0, 20) : [];
        if (!list.length) {
            return '';
        }
        return '<ul class="aysa-agent8-technical-list">' + list.map((row) => '<li>' + mapper(row) + '</li>').join('') + '</ul>';
    }

    function encodeBundlePayload(payload) {
        try {
            return window.encodeURIComponent(JSON.stringify(reduceBundleActionPayload(payload || {})));
        } catch (e) {
            return '';
        }
    }

    function reduceBundleActionPayload(payload) {
        const source = payload && typeof payload === 'object' ? payload : {};
        const allowed = [
            'bundle_action_key',
            'bundle_type',
            'issue_category',
            'issue_title',
            'affected_count',
            'baseline_affected_count',
            'target_scope',
            'next_step',
            'action_label',
            'reason',
            'execution_package_id',
            'package_id'
        ];
        const reduced = {};
        allowed.forEach((key) => {
            if (Object.prototype.hasOwnProperty.call(source, key)) {
                reduced[key] = source[key];
            }
        });
        return reduced;
    }

    function technicalHumanReason(reason, row) {
        const normalized = String(reason || '').trim();
        const flags = Array.isArray(row && row.flags) ? row.flags : [];
        const notes = Array.isArray(row && row.notes) ? row.notes : [];
        if (!normalized && flags.indexOf('missing') !== -1) {
            return 'The current description is missing.';
        }
        const map = {
            already_optimized: 'The current description is already strong enough, so I recommend leaving it unchanged.',
            existing_meta_description_passes_quality_gate: 'The current description is good enough already.',
            missing_current_description: 'The current description is missing.',
            metadata_missing: 'The current description is missing.',
            current_description_too_short: 'The current description is too short to do the job well.',
            current_description_too_long: 'The current description is too long.',
            duplicate_description_flagged_by_site_audit: 'This description looks duplicated, so I recommend replacing it.',
            current_description_truncated_or_incomplete: 'The current description looks cut off or incomplete.',
            current_description_generic_or_filler: 'The current text sounds too generic.',
            current_description_low_relevance_to_page_intent: 'The current text does not clearly match what this page is about.',
            primary_keyword_missing_from_current_description: 'The main keyword is missing.',
            secondary_keyword_missing_from_current_description: 'The supporting keyword signal is missing.',
            keyword_context_missing_for_preserve_check: 'I do not have enough keyword context to decide safely.',
            secondary_keyword_context_missing_for_preserve_check: 'I need review because the text may be okay, but I do not have enough supporting keyword context.',
            current_description_only_borderline_length: 'I need review because the text is borderline but not clearly weak.',
            no_clear_wordpress_post_mapping: 'I could not safely match this page to a WordPress page.',
            post_not_editable: 'This page is not in a safe editable state right now.',
            duplicate_proposed_value_in_batch: 'This proposed text duplicates another rewrite in the same batch.',
            empty_proposed_value: 'I could not generate a safe replacement yet.',
            invalid_proposed_value: 'I could not generate a safe replacement yet.'
        };
        if (map[normalized]) {
            return map[normalized];
        }
        if (flags.indexOf('generic_filler') !== -1) {
            return 'The current text sounds too generic.';
        }
        if (flags.indexOf('missing_primary_keyword') !== -1) {
            return 'The main keyword is missing.';
        }
        if (flags.indexOf('truncated') !== -1) {
            return 'The current description looks cut off or incomplete.';
        }
        if (flags.indexOf('too_long') !== -1) {
            return 'The current description is too long.';
        }
        if (flags.indexOf('too_short') !== -1) {
            return 'The current description is too short to do the job well.';
        }
        if (notes.some((note) => String(note).indexOf('secondary_keywords_not_available') === 0)) {
            return 'I need review because the text may be okay, but I do not have enough supporting keyword context.';
        }
        return normalized ? humanizeSlug(normalized) + '.' : 'I reviewed this description and kept it out of automatic changes.';
    }

    function metadataDecisionBadge(decision) {
        const normalized = String(decision || '').trim();
        if (normalized === 'preserve') {
            return 'Keep';
        }
        if (normalized === 'rewrite') {
            return 'Rewrite';
        }
        return 'Review';
    }

    function normalizeMetadataDecisionRows(packageData) {
        const packageRows = packageData && typeof packageData === 'object' ? packageData : {};
        const rewriteRows = Array.isArray(packageRows.items) ? packageRows.items.map((item) => {
            const currentValue = String(item.old_value || '').trim();
            const proposedValue = String(item.proposed_value || '').trim();
            return {
                decision: 'rewrite',
                page: String(item.url || '-'),
                currentValue: currentValue,
                proposedValue: proposedValue,
                shortReason: technicalHumanReason(String(item.overwrite_reason || ''), {
                    flags: item.quality_flags || [],
                    notes: item.quality_notes || []
                }),
                rawReason: String(item.overwrite_reason || ''),
                flags: Array.isArray(item.quality_flags) ? item.quality_flags : [],
                notes: Array.isArray(item.quality_notes) ? item.quality_notes : [],
                confidence: Number(item.confidence || 0) || 0
            };
        }) : [];
        const skippedRows = Array.isArray(packageRows.skipped) ? packageRows.skipped : [];
        const manualRows = [];
        const keepRows = [];
        const blockedRows = [];
        skippedRows.forEach((item) => {
            const quality = item && item.candidate_quality && typeof item.candidate_quality === 'object' ? item.candidate_quality : {};
            const decision = String(quality.decision || '').trim();
            const row = {
                decision: decision || 'manual_review',
                page: String(item && item.url ? item.url : '-'),
                currentValue: String(item && item.old_value ? item.old_value : ''),
                proposedValue: String(item && item.proposed_value ? item.proposed_value : ''),
                shortReason: technicalHumanReason(String(quality.overwrite_reason || item.reason || ''), {
                    flags: quality.quality_flags || [],
                    notes: quality.notes || []
                }),
                rawReason: String(quality.overwrite_reason || item.reason || ''),
                flags: Array.isArray(quality.quality_flags) ? quality.quality_flags : [],
                notes: Array.isArray(quality.notes) ? quality.notes : [],
                confidence: Number(quality.quality_score || item.quality_score || 0) || 0
            };
            if (decision === 'preserve') {
                keepRows.push(row);
            } else if (decision === 'manual_review') {
                manualRows.push(row);
            } else {
                blockedRows.push(row);
            }
        });
        return {
            keep: keepRows,
            rewrite: rewriteRows,
            review: manualRows.concat(blockedRows)
        };
    }

    function renderMetadataDecisionRow(row, index) {
        const page = String(row && row.page ? row.page : '-');
        const currentValue = String(row && row.currentValue ? row.currentValue : '').trim();
        const proposedValue = String(row && row.proposedValue ? row.proposedValue : '').trim();
        const advancedId = 'aysa-agent8-metadata-advanced-' + String(index);
        return '' +
            '<div class="aysa-agent8-metadata-row">' +
                '<div class="aysa-agent8-metadata-row-head">' +
                    '<div>' +
                        '<strong>' + escapeHtml(metadataDecisionBadge(row && row.decision ? row.decision : 'manual_review')) + '</strong>' +
                        '<div class="aysa-agent8-metadata-row-url">' + escapeHtml(page) + '</div>' +
                    '</div>' +
                    '<span class="aysa-agent8-badge">' + escapeHtml(String((row && row.confidence) || 0)) + '%</span>' +
                '</div>' +
                '<p class="aysa-agent8-metadata-row-reason">' + escapeHtml(String(row && row.shortReason ? row.shortReason : '')) + '</p>' +
                '<div class="aysa-agent8-metadata-row-copy">' +
                    '<div class="aysa-agent8-metadata-copy-block">' +
                        '<strong>Current description</strong>' +
                        '<p>' + escapeHtml(currentValue || 'No current description found.') + '</p>' +
                    '</div>' +
                    (proposedValue
                        ? '<div class="aysa-agent8-metadata-copy-block"><strong>Recommended description</strong><p>' + escapeHtml(proposedValue) + '</p></div>'
                        : '') +
                '</div>' +
                '<details id="' + escapeAttribute(advancedId) + '">' +
                    '<summary>Advanced details</summary>' +
                    '<div class="aysa-agent8-metadata-row-advanced">' +
                        '<div><strong>Machine reason:</strong> ' + escapeHtml(String(row && row.rawReason ? row.rawReason : '-')) + '</div>' +
                        '<div><strong>Quality flags:</strong> ' + escapeHtml(Array.isArray(row && row.flags) && row.flags.length ? row.flags.join(', ') : '-') + '</div>' +
                        '<div><strong>Notes:</strong> ' + escapeHtml(Array.isArray(row && row.notes) && row.notes.length ? row.notes.join(' | ') : '-') + '</div>' +
                    '</div>' +
                '</details>' +
            '</div>';
    }

    function renderMetadataDecisionBucket(bucketKey, title, intro, rows, openByDefault, startIndex) {
        const list = Array.isArray(rows) ? rows : [];
        const detailsOpen = openByDefault ? ' open' : '';
        const bodyHtml = list.length
            ? list.map((row, rowIndex) => renderMetadataDecisionRow(row, startIndex + rowIndex)).join('')
            : '<div class="aysa-agent8-metadata-empty">Nothing is in this section right now.</div>';
        return '' +
            '<details class="aysa-agent8-metadata-bucket" data-decision="' + escapeAttribute(bucketKey) + '"' + detailsOpen + '>' +
                '<summary>' +
                    '<span class="aysa-agent8-metadata-bucket-title">' +
                        '<strong>' + escapeHtml(title) + '</strong>' +
                        '<span>' + escapeHtml(intro) + '</span>' +
                    '</span>' +
                    '<span class="aysa-agent8-metadata-bucket-count">' + escapeHtml(String(list.length)) + '</span>' +
                '</summary>' +
                '<div class="aysa-agent8-metadata-bucket-body">' + bodyHtml + '</div>' +
            '</details>';
    }

    function renderMetadataBundleReview(bundle, actionPayload, applyActionKey, verifyActionKey, skipPayload) {
        const metadataPackage = bundle && bundle.metadata_execution_package && typeof bundle.metadata_execution_package === 'object'
            && (Array.isArray(bundle.metadata_execution_package.items) || Array.isArray(bundle.metadata_execution_package.skipped))
            ? bundle.metadata_execution_package
            : ((bundle && bundle.last_prepare_result && bundle.last_prepare_result.metadata_execution_package && typeof bundle.last_prepare_result.metadata_execution_package === 'object')
                ? bundle.last_prepare_result.metadata_execution_package
                : ((bundle && bundle.last_prepare_result && bundle.last_prepare_result.execution_package && typeof bundle.last_prepare_result.execution_package === 'object')
                    ? bundle.last_prepare_result.execution_package
                    : {}));
        if (!metadataPackage || (!Array.isArray(metadataPackage.items) && !Array.isArray(metadataPackage.skipped))) {
            return '';
        }
        const buckets = normalizeMetadataDecisionRows(metadataPackage);
        const reconciliation = metadataPackage.count_reconciliation && typeof metadataPackage.count_reconciliation === 'object'
            ? metadataPackage.count_reconciliation
            : {};
        const rawCandidateRows = Number(reconciliation.candidate_input_rows || metadataPackage.total_candidates || 0) || 0;
        const keepCount = buckets.keep.length;
        const rewriteCount = buckets.rewrite.length;
        const reviewCount = buckets.review.length;
        const blockedCount = Math.max(0, rawCandidateRows - (keepCount + rewriteCount + reviewCount));
        const issueCount = Number(bundle && bundle.affected_count ? bundle.affected_count : 0) || 0;
        const blockerLine = blockedCount > 0
            ? 'Some rows could not be prepared yet because WordPress mapping or quality confidence was not strong enough.'
            : 'Most of the difference comes from rows that were kept as-is or held for review instead of being changed automatically.';
        return '' +
            '<div class="aysa-agent8-metadata-approval-summary">' +
                '<div class="aysa-agent8-metadata-guidance">I only rewrite descriptions automatically when the current one is clearly weak. If the current description already looks strong enough, I leave it alone. If I am not sure, I ask for review.</div>' +
                '<div class="aysa-agent8-metadata-approval-summary-grid">' +
                    '<div class="aysa-agent8-metadata-approval-stat"><strong>' + escapeHtml(String(issueCount)) + '</strong><span>metadata issues found</span></div>' +
                    '<div class="aysa-agent8-metadata-approval-stat"><strong>' + escapeHtml(String(rawCandidateRows)) + '</strong><span>raw candidate rows analyzed</span></div>' +
                    '<div class="aysa-agent8-metadata-approval-stat"><strong>' + escapeHtml(String(rewriteCount)) + '</strong><span>safe rewrites ready for approval</span></div>' +
                    '<div class="aysa-agent8-metadata-approval-stat"><strong>' + escapeHtml(String(keepCount + reviewCount + blockedCount)) + '</strong><span>rows kept or flagged for review</span></div>' +
                '</div>' +
                '<div class="aysa-agent8-card-summary-row"><strong>Main blocker:</strong> ' + escapeHtml(blockerLine) + '</div>' +
            '</div>' +
            '<div class="aysa-agent8-metadata-buckets">' +
                renderMetadataDecisionBucket('preserve', 'Keep as-is', 'This description is already strong enough, so I recommend leaving it unchanged.', buckets.keep, false, 0) +
                renderMetadataDecisionBucket('rewrite', 'Rewrite automatically', 'This description is missing or weak, so I recommend replacing it with a better version.', buckets.rewrite, true, buckets.keep.length) +
                renderMetadataDecisionBucket('manual_review', 'Needs review', 'This description might be usable, but I do not have enough confidence to change it automatically.', buckets.review, true, buckets.keep.length + buckets.rewrite.length) +
            '</div>' +
            '<div class="aysa-agent8-technical-bundle-actions">' +
                '<button type="button" class="aysa-agent8-chip aysa-agent8-bundle-action" data-action-key="' + escapeHtml(actionKeyFromPayload(actionPayload, applyActionKey)) + '" data-action-payload="' + actionPayload + '"' + (rewriteCount <= 0 ? ' disabled' : '') + '>Approve all safe rewrites</button>' +
                '<button type="button" class="aysa-agent8-chip aysa-agent8-metadata-review-trigger" data-target-decision="manual_review">Review manual items</button>' +
                '<button type="button" class="aysa-agent8-chip aysa-agent8-bundle-action" data-action-key="ignore_site_audit_action_bundle" data-action-payload="' + skipPayload + '">Skip for now</button>' +
                '<button type="button" class="aysa-agent8-chip aysa-agent8-bundle-action" data-action-key="' + escapeHtml(verifyActionKey) + '" data-action-payload="' + actionPayload + '">Verify live metadata</button>' +
            '</div>';
    }

    function imageAltHumanReason(reason, row) {
        const normalized = String(reason || '').trim();
        const flags = Array.isArray(row && row.flags) ? row.flags : [];
        const map = {
            existing_alt_already_present: 'This image already has alt text, so I recommend leaving it unchanged.',
            attachment_mapping_missing: 'I could not safely match this image to a WordPress media item.',
            decorative_image_detected: 'This image looks decorative, so I do not recommend adding alt text automatically.',
            image_context_not_aligned_for_keyword_enrichment: 'The page context does not clearly match what is visible in the image.',
            image_alt_confidence_below_threshold: 'I need review because the generated alt text is not confident enough.',
            image_alt_missing_or_weak: 'This image is missing alt text or needs a better description.',
            image_analysis_failed: 'I could not analyze this image safely.',
            decorative_ignore: 'This image looks decorative, so I left it out of automatic changes.'
        };
        if (map[normalized]) {
            return map[normalized];
        }
        if (flags.indexOf('decorative') !== -1) {
            return 'This image looks decorative, so I do not recommend adding alt text automatically.';
        }
        if (flags.indexOf('context_mismatch') !== -1) {
            return 'The page context does not clearly match what is visible in the image.';
        }
        return normalized ? humanizeSlug(normalized) + '.' : 'I reviewed this image and kept it out of automatic changes.';
    }

    function imageAltDecisionBadge(decision) {
        const normalized = String(decision || '').trim();
        if (normalized === 'preserve') {
            return 'Keep';
        }
        if (normalized === 'rewrite') {
            return 'Rewrite';
        }
        if (normalized === 'decorative_ignore') {
            return 'Decorative';
        }
        return 'Review';
    }

    function normalizeImageAltDecisionRows(packageData) {
        const packageRows = packageData && typeof packageData === 'object' ? packageData : {};
        const out = { keep: [], rewrite: [], review: [], decorative: [] };
        const pushRow = function(item, fallbackDecision) {
            const quality = item && item.candidate_quality && typeof item.candidate_quality === 'object' ? item.candidate_quality : {};
            const decision = String(item && item.decision ? item.decision : (quality.decision || fallbackDecision || 'manual_review')).trim() || 'manual_review';
            const row = {
                decision: decision,
                page: String(item && item.page_url ? item.page_url : '-'),
                imageUrl: String(item && item.image_url ? item.image_url : '-'),
                imageFilename: String(item && item.image_filename ? item.image_filename : ''),
                currentValue: String(item && (item.current_value || item.old_value || item.existing_alt) ? (item.current_value || item.old_value || item.existing_alt) : '').trim(),
                proposedValue: String(item && item.proposed_value ? item.proposed_value : '').trim(),
                imageDescription: String(item && item.image_description ? item.image_description : '').trim(),
                shortReason: imageAltHumanReason(String(item && item.reason ? item.reason : (quality.overwrite_reason || '')), {
                    flags: item && item.quality_flags ? item.quality_flags : (quality.quality_flags || [])
                }),
                rawReason: String(item && item.reason ? item.reason : (quality.overwrite_reason || '')),
                flags: Array.isArray(item && item.quality_flags) ? item.quality_flags : (Array.isArray(quality.quality_flags) ? quality.quality_flags : []),
                confidence: Number(item && item.confidence ? item.confidence : (quality.quality_score || 0)) || 0,
                contextAlignment: String(item && item.context_alignment ? item.context_alignment : '-')
            };
            if (decision === 'rewrite') {
                out.rewrite.push(row);
            } else if (decision === 'preserve') {
                out.keep.push(row);
            } else if (decision === 'decorative_ignore') {
                out.decorative.push(row);
            } else {
                out.review.push(row);
            }
        };
        (Array.isArray(packageRows.items) ? packageRows.items : []).forEach((item) => pushRow(item, 'rewrite'));
        (Array.isArray(packageRows.skipped) ? packageRows.skipped : []).forEach((item) => pushRow(item, 'manual_review'));
        return out;
    }

    function renderImageAltDecisionRow(row, index) {
        const advancedId = 'aysa-agent8-image-alt-advanced-' + String(index);
        return '' +
            '<div class="aysa-agent8-metadata-row">' +
                '<div class="aysa-agent8-metadata-row-head">' +
                    '<div>' +
                        '<strong>' + escapeHtml(imageAltDecisionBadge(row && row.decision ? row.decision : 'manual_review')) + '</strong>' +
                        '<div class="aysa-agent8-metadata-row-url">' + escapeHtml(String(row && row.page ? row.page : '-')) + '</div>' +
                    '</div>' +
                    '<span class="aysa-agent8-badge">' + escapeHtml(String((row && row.confidence) || 0)) + '%</span>' +
                '</div>' +
                '<p class="aysa-agent8-metadata-row-reason">' + escapeHtml(String(row && row.shortReason ? row.shortReason : '')) + '</p>' +
                '<div class="aysa-agent8-card-summary-row"><strong>Image:</strong> ' + escapeHtml(String((row && (row.imageFilename || row.imageUrl)) || '-')) + '</div>' +
                '<div class="aysa-agent8-metadata-row-copy">' +
                    '<div class="aysa-agent8-metadata-copy-block">' +
                        '<strong>Current alt text</strong>' +
                        '<p>' + escapeHtml(String((row && row.currentValue) || 'No alt text found.')) + '</p>' +
                    '</div>' +
                    (row && row.proposedValue
                        ? '<div class="aysa-agent8-metadata-copy-block"><strong>Recommended alt text</strong><p>' + escapeHtml(String(row.proposedValue)) + '</p></div>'
                        : '') +
                '</div>' +
                (row && row.imageDescription
                    ? '<div class="aysa-agent8-card-summary-row"><strong>Image description:</strong> ' + escapeHtml(String(row.imageDescription)) + '</div>'
                    : '') +
                '<details id="' + escapeAttribute(advancedId) + '">' +
                    '<summary>Advanced details</summary>' +
                    '<div class="aysa-agent8-metadata-row-advanced">' +
                        '<div><strong>Machine reason:</strong> ' + escapeHtml(String(row && row.rawReason ? row.rawReason : '-')) + '</div>' +
                        '<div><strong>Context alignment:</strong> ' + escapeHtml(String(row && row.contextAlignment ? row.contextAlignment : '-')) + '</div>' +
                        '<div><strong>Quality flags:</strong> ' + escapeHtml(Array.isArray(row && row.flags) && row.flags.length ? row.flags.join(', ') : '-') + '</div>' +
                    '</div>' +
                '</details>' +
            '</div>';
    }

    function renderImageAltDecisionBucket(bucketKey, title, intro, rows, openByDefault, startIndex) {
        const list = Array.isArray(rows) ? rows : [];
        const detailsOpen = openByDefault ? ' open' : '';
        const bodyHtml = list.length
            ? list.map((row, rowIndex) => renderImageAltDecisionRow(row, startIndex + rowIndex)).join('')
            : '<div class="aysa-agent8-metadata-empty">Nothing is in this section right now.</div>';
        return '' +
            '<details class="aysa-agent8-metadata-bucket" data-decision="' + escapeAttribute(bucketKey) + '"' + detailsOpen + '>' +
                '<summary>' +
                    '<span class="aysa-agent8-metadata-bucket-title">' +
                        '<strong>' + escapeHtml(title) + '</strong>' +
                        '<span>' + escapeHtml(intro) + '</span>' +
                    '</span>' +
                    '<span class="aysa-agent8-metadata-bucket-count">' + escapeHtml(String(list.length)) + '</span>' +
                '</summary>' +
                '<div class="aysa-agent8-metadata-bucket-body">' + bodyHtml + '</div>' +
            '</details>';
    }

    function renderImageAltBundleReview(bundle, actionPayload, applyActionKey, verifyActionKey, skipPayload) {
        const imageAltPackage = bundle && bundle.image_alt_execution_package && typeof bundle.image_alt_execution_package === 'object'
            && (Array.isArray(bundle.image_alt_execution_package.items) || Array.isArray(bundle.image_alt_execution_package.skipped))
            ? bundle.image_alt_execution_package
            : ((bundle && bundle.last_prepare_result && bundle.last_prepare_result.image_alt_execution_package && typeof bundle.last_prepare_result.image_alt_execution_package === 'object')
                ? bundle.last_prepare_result.image_alt_execution_package
                : ((bundle && bundle.last_prepare_result && bundle.last_prepare_result.execution_package && typeof bundle.last_prepare_result.execution_package === 'object')
                    ? bundle.last_prepare_result.execution_package
                    : {}));
        if (!imageAltPackage || (!Array.isArray(imageAltPackage.items) && !Array.isArray(imageAltPackage.skipped))) {
            return '';
        }
        const buckets = normalizeImageAltDecisionRows(imageAltPackage);
        const total = Number(imageAltPackage.total_candidates || 0) || (buckets.keep.length + buckets.rewrite.length + buckets.review.length + buckets.decorative.length);
        return '' +
            '<div class="aysa-agent8-metadata-approval-summary">' +
                '<div class="aysa-agent8-metadata-guidance">I only rewrite alt text automatically when the image is clearly mapped, non-decorative, and the visual description is confident. If I am not sure, I hold it for review.</div>' +
                '<div class="aysa-agent8-metadata-approval-summary-grid">' +
                    '<div class="aysa-agent8-metadata-approval-stat"><strong>' + escapeHtml(String(total)) + '</strong><span>image rows analyzed</span></div>' +
                    '<div class="aysa-agent8-metadata-approval-stat"><strong>' + escapeHtml(String(buckets.rewrite.length)) + '</strong><span>safe rewrites ready for approval</span></div>' +
                    '<div class="aysa-agent8-metadata-approval-stat"><strong>' + escapeHtml(String(buckets.keep.length)) + '</strong><span>rows kept as-is</span></div>' +
                    '<div class="aysa-agent8-metadata-approval-stat"><strong>' + escapeHtml(String(buckets.review.length + buckets.decorative.length)) + '</strong><span>rows held for review or ignored</span></div>' +
                '</div>' +
            '</div>' +
            '<div class="aysa-agent8-metadata-buckets">' +
                renderImageAltDecisionBucket('preserve', 'Keep as-is', 'This image already has usable alt text, so I recommend leaving it unchanged.', buckets.keep, false, 0) +
                renderImageAltDecisionBucket('rewrite', 'Rewrite automatically', 'This image is missing alt text or needs a stronger description, so I recommend replacing it.', buckets.rewrite, true, buckets.keep.length) +
                renderImageAltDecisionBucket('manual_review', 'Needs review', 'This image might be fine, but I do not have enough confidence to change it automatically.', buckets.review, true, buckets.keep.length + buckets.rewrite.length) +
                renderImageAltDecisionBucket('decorative_ignore', 'Decorative ignore', 'This image looks decorative, so I do not recommend adding alt text automatically.', buckets.decorative, false, buckets.keep.length + buckets.rewrite.length + buckets.review.length) +
            '</div>' +
            '<div class="aysa-agent8-technical-bundle-actions">' +
                '<button type="button" class="aysa-agent8-chip aysa-agent8-bundle-action" data-action-key="' + escapeHtml(actionKeyFromPayload(actionPayload, applyActionKey)) + '" data-action-payload="' + actionPayload + '"' + (buckets.rewrite.length <= 0 ? ' disabled' : '') + '>Approve all safe rewrites</button>' +
                '<button type="button" class="aysa-agent8-chip aysa-agent8-metadata-review-trigger" data-target-decision="manual_review">Review manual items</button>' +
                '<button type="button" class="aysa-agent8-chip aysa-agent8-bundle-action" data-action-key="ignore_site_audit_action_bundle" data-action-payload="' + skipPayload + '">Skip for now</button>' +
                '<button type="button" class="aysa-agent8-chip aysa-agent8-bundle-action" data-action-key="' + escapeHtml(verifyActionKey) + '" data-action-payload="' + actionPayload + '">Verify live image alt</button>' +
            '</div>';
    }

    function canonicalHumanReason(reason) {
        const normalized = String(reason || '').trim();
        const map = {
            self_canonical_missing: 'This page is missing a canonical tag, so I recommend adding a self-canonical.',
            canonical_review_required: 'This canonical issue needs review before changing it automatically.',
            canonical_chain_or_noncanonical_link_requires_review: 'This canonical signal looks risky or indirect, so I held it for review.',
            self_canonical_target_mismatch: 'The recommended self-canonical target does not match the page URL, so I held it for review.',
            confidence_below_auto_threshold: 'I need review because the canonical recommendation is not confident enough.',
            no_clear_wordpress_post_mapping: 'I could not map this URL to a clear WordPress post.',
            indexability_signal_requires_manual_review: 'This indexing signal needs review before changing canonicals automatically.'
        };
        return map[normalized] || (normalized ? humanizeSlug(normalized) + '.' : 'I reviewed this canonical signal and kept it out of automatic changes.');
    }

    function canonicalDecisionBadge(decision) {
        const normalized = String(decision || '').trim();
        if (normalized === 'preserve') return 'Keep';
        if (normalized === 'self_canonical') return 'Self-canonical';
        if (normalized === 'rewrite') return 'Rewrite';
        return 'Review';
    }

    function normalizeCanonicalDecisionRows(packageData) {
        const packageRows = packageData && typeof packageData === 'object' ? packageData : {};
        const out = { keep: [], selfCanonical: [], rewrite: [], review: [] };
        const pushRow = function(item, fallbackDecision) {
            const quality = item && item.candidate_quality && typeof item.candidate_quality === 'object' ? item.candidate_quality : {};
            const decision = String(item && (item.recommended_action || item.decision) ? (item.recommended_action || item.decision) : (quality.decision || fallbackDecision || 'manual_review')).trim() || 'manual_review';
            const row = {
                decision: decision,
                page: String(item && item.page_url ? item.page_url : '-'),
                currentValue: String(item && (item.current_canonical_url || item.old_value) ? (item.current_canonical_url || item.old_value) : '').trim(),
                proposedValue: String(item && (item.recommended_target_url || item.proposed_value) ? (item.recommended_target_url || item.proposed_value) : '').trim(),
                shortReason: canonicalHumanReason(String(item && item.reason ? item.reason : (quality.overwrite_reason || ''))),
                rawReason: String(item && item.reason ? item.reason : (quality.overwrite_reason || '')),
                flags: Array.isArray(item && item.quality_flags) ? item.quality_flags : (Array.isArray(quality.quality_flags) ? quality.quality_flags : []),
                confidence: Number(item && item.confidence ? item.confidence : (quality.quality_score || 0)) || 0,
                provider: String(item && item.canonical_provider ? item.canonical_provider : '-')
            };
            if (decision === 'preserve') {
                out.keep.push(row);
            } else if (decision === 'self_canonical') {
                out.selfCanonical.push(row);
            } else if (decision === 'rewrite') {
                out.rewrite.push(row);
            } else {
                out.review.push(row);
            }
        };
        (Array.isArray(packageRows.items) ? packageRows.items : []).forEach((item) => pushRow(item, 'manual_review'));
        (Array.isArray(packageRows.skipped) ? packageRows.skipped : []).forEach((item) => pushRow(item, 'manual_review'));
        return out;
    }

    function renderCanonicalDecisionRow(row, index) {
        const advancedId = 'aysa-agent8-canonical-advanced-' + String(index);
        return '' +
            '<div class="aysa-agent8-metadata-row">' +
                '<div class="aysa-agent8-metadata-row-head">' +
                    '<div>' +
                        '<strong>' + escapeHtml(canonicalDecisionBadge(row && row.decision ? row.decision : 'manual_review')) + '</strong>' +
                        '<div class="aysa-agent8-metadata-row-url">' + escapeHtml(String(row && row.page ? row.page : '-')) + '</div>' +
                    '</div>' +
                    '<span class="aysa-agent8-badge">' + escapeHtml(String((row && row.confidence) || 0)) + '%</span>' +
                '</div>' +
                '<p class="aysa-agent8-metadata-row-reason">' + escapeHtml(String(row && row.shortReason ? row.shortReason : '')) + '</p>' +
                '<div class="aysa-agent8-card-summary-row"><strong>Provider:</strong> ' + escapeHtml(String((row && row.provider) || '-')) + '</div>' +
                '<div class="aysa-agent8-metadata-row-copy">' +
                    '<div class="aysa-agent8-metadata-copy-block">' +
                        '<strong>Current canonical</strong>' +
                        '<p>' + escapeHtml(String((row && row.currentValue) || 'No canonical found.')) + '</p>' +
                    '</div>' +
                    (row && row.proposedValue
                        ? '<div class="aysa-agent8-metadata-copy-block"><strong>Recommended canonical</strong><p>' + escapeHtml(String(row.proposedValue)) + '</p></div>'
                        : '') +
                '</div>' +
                '<details id="' + escapeAttribute(advancedId) + '">' +
                    '<summary>Advanced details</summary>' +
                    '<div class="aysa-agent8-metadata-row-advanced">' +
                        '<div><strong>Machine reason:</strong> ' + escapeHtml(String(row && row.rawReason ? row.rawReason : '-')) + '</div>' +
                        '<div><strong>Quality flags:</strong> ' + escapeHtml(Array.isArray(row && row.flags) && row.flags.length ? row.flags.join(', ') : '-') + '</div>' +
                    '</div>' +
                '</details>' +
            '</div>';
    }

    function renderCanonicalDecisionBucket(bucketKey, title, intro, rows, openByDefault, startIndex) {
        const list = Array.isArray(rows) ? rows : [];
        const detailsOpen = openByDefault ? ' open' : '';
        const bodyHtml = list.length
            ? list.map((row, rowIndex) => renderCanonicalDecisionRow(row, startIndex + rowIndex)).join('')
            : '<div class="aysa-agent8-metadata-empty">Nothing is in this section right now.</div>';
        return '' +
            '<details class="aysa-agent8-metadata-bucket" data-decision="' + escapeAttribute(bucketKey) + '"' + detailsOpen + '>' +
                '<summary>' +
                    '<span class="aysa-agent8-metadata-bucket-title">' +
                        '<strong>' + escapeHtml(title) + '</strong>' +
                        '<span>' + escapeHtml(intro) + '</span>' +
                    '</span>' +
                    '<span class="aysa-agent8-metadata-bucket-count">' + escapeHtml(String(list.length)) + '</span>' +
                '</summary>' +
                '<div class="aysa-agent8-metadata-bucket-body">' + bodyHtml + '</div>' +
            '</details>';
    }

    function renderCanonicalBundleReview(bundle, actionPayload, applyActionKey, verifyActionKey, skipPayload) {
        const canonicalPackage = bundle && bundle.canonical_execution_package && typeof bundle.canonical_execution_package === 'object'
            && (Array.isArray(bundle.canonical_execution_package.items) || Array.isArray(bundle.canonical_execution_package.skipped))
            ? bundle.canonical_execution_package
            : ((bundle && bundle.last_prepare_result && bundle.last_prepare_result.canonical_execution_package && typeof bundle.last_prepare_result.canonical_execution_package === 'object')
                ? bundle.last_prepare_result.canonical_execution_package
                : {});
        if (!canonicalPackage || (!Array.isArray(canonicalPackage.items) && !Array.isArray(canonicalPackage.skipped))) {
            return '';
        }
        const buckets = normalizeCanonicalDecisionRows(canonicalPackage);
        const total = Number(canonicalPackage.total_candidates || 0) || (buckets.keep.length + buckets.selfCanonical.length + buckets.rewrite.length + buckets.review.length);
        const safeApproveCount = buckets.selfCanonical.length + buckets.rewrite.length;
        return '' +
            '<div class="aysa-agent8-metadata-approval-summary">' +
                '<div class="aysa-agent8-metadata-guidance">I only change canonicals automatically when the target is clear, mapped, and safe. If the signal is ambiguous, I hold it for review.</div>' +
                '<div class="aysa-agent8-metadata-approval-summary-grid">' +
                    '<div class="aysa-agent8-metadata-approval-stat"><strong>' + escapeHtml(String(total)) + '</strong><span>canonical rows analyzed</span></div>' +
                    '<div class="aysa-agent8-metadata-approval-stat"><strong>' + escapeHtml(String(buckets.selfCanonical.length)) + '</strong><span>self-canonical fixes</span></div>' +
                    '<div class="aysa-agent8-metadata-approval-stat"><strong>' + escapeHtml(String(buckets.rewrite.length)) + '</strong><span>rewrite rows</span></div>' +
                    '<div class="aysa-agent8-metadata-approval-stat"><strong>' + escapeHtml(String(buckets.keep.length + buckets.review.length)) + '</strong><span>rows kept or held for review</span></div>' +
                '</div>' +
            '</div>' +
            '<div class="aysa-agent8-metadata-buckets">' +
                renderCanonicalDecisionBucket('preserve', 'Keep', 'This page already has a usable canonical, so I recommend leaving it unchanged.', buckets.keep, false, 0) +
                renderCanonicalDecisionBucket('self_canonical', 'Self-canonical', 'This page should clearly point to itself, so I recommend adding a self-canonical.', buckets.selfCanonical, true, buckets.keep.length) +
                renderCanonicalDecisionBucket('rewrite', 'Rewrite', 'This page has a clear supported canonical target, so I recommend updating it.', buckets.rewrite, true, buckets.keep.length + buckets.selfCanonical.length) +
                renderCanonicalDecisionBucket('manual_review', 'Review', 'This canonical issue could be risky or ambiguous, so it needs review first.', buckets.review, true, buckets.keep.length + buckets.selfCanonical.length + buckets.rewrite.length) +
            '</div>' +
            '<div class="aysa-agent8-technical-bundle-actions">' +
                '<button type="button" class="aysa-agent8-chip aysa-agent8-bundle-action" data-action-key="' + escapeHtml(actionKeyFromPayload(actionPayload, applyActionKey)) + '" data-action-payload="' + actionPayload + '"' + (safeApproveCount <= 0 ? ' disabled' : '') + '>Approve all safe canonical changes</button>' +
                '<button type="button" class="aysa-agent8-chip aysa-agent8-metadata-review-trigger" data-target-decision="manual_review">Review manual items</button>' +
                '<button type="button" class="aysa-agent8-chip aysa-agent8-bundle-action" data-action-key="ignore_site_audit_action_bundle" data-action-payload="' + skipPayload + '">Skip for now</button>' +
                '<button type="button" class="aysa-agent8-chip aysa-agent8-bundle-action" data-action-key="' + escapeHtml(verifyActionKey) + '" data-action-payload="' + actionPayload + '">Verify live canonical</button>' +
            '</div>';
    }

    function actionKeyFromPayload(actionPayload, fallbackActionKey) {
        return String(fallbackActionKey || '');
    }

    function buildReducedSiteAuditFallbackPackage(bundle, family, previewRows, affectedCount) {
        const urls = Array.isArray(previewRows) ? previewRows.slice(0, 8) : [];
        if (!urls.length && Number(affectedCount || 0) > 0) {
            urls.push(String(affectedCount) + ' affected rows in reduced Site Audit payload');
        }
        const reason = 'I need review because the prepared package rows are not included in this reduced payload.';
        const skipped = urls.map((url) => {
            const pageUrl = String(url || '-');
            if (family === 'image_alt') {
                return {
                    decision: 'manual_review',
                    reason: 'reduced_payload_manual_review',
                    page_url: pageUrl,
                    image_url: '',
                    old_value: '',
                    proposed_value: '',
                    confidence: 0,
                    quality_flags: ['reduced_payload']
                };
            }
            if (family === 'canonical') {
                return {
                    decision: 'manual_review',
                    recommended_action: 'manual_review',
                    reason: 'reduced_payload_manual_review',
                    page_url: pageUrl,
                    current_canonical_url: '',
                    recommended_target_url: '',
                    confidence: 0,
                    quality_flags: ['reduced_payload']
                };
            }
            return {
                url: pageUrl,
                field: 'meta_description',
                old_value: '',
                proposed_value: '',
                overwrite_decision: 'manual_review',
                overwrite_reason: 'reduced_payload_manual_review',
                quality_flags: ['reduced_payload'],
                confidence: 0,
                notes: [reason]
            };
        });
        return {
            package_id: String((bundle && bundle.execution_package_id) || ''),
            total_candidates: Number(affectedCount || skipped.length || 0) || 0,
            safe_auto_apply_count: 0,
            manual_review_needed_count: skipped.length,
            items: [],
            skipped: skipped
        };
    }

    function siteAuditPackageHasRows(packageData) {
        if (!packageData || typeof packageData !== 'object') {
            return false;
        }
        const items = Array.isArray(packageData.items) ? packageData.items.length : 0;
        const skipped = Array.isArray(packageData.skipped) ? packageData.skipped.length : 0;
        return (items + skipped) > 0;
    }

    function renderTechnicalActionBundles(bundles) {
        const items = Array.isArray(bundles) ? bundles.slice(0, 6) : [];
        if (!items.length) {
            return '';
        }
        return '<div class="aysa-agent8-technical-bundles">' + items.map((bundle) => {
            const actionKey = String((bundle && bundle.action_key) || '');
            const executionState = String((bundle && bundle.execution_state) || 'open');
            const affectedCount = Number((bundle && bundle.affected_count) || 0) || 0;
            const applyActionKey = actionKey.replace(/^prepare_/, 'apply_');
            const verifyActionKey = actionKey.replace(/^prepare_/, 'verify_');
            const isMetadataBundle = actionKey === 'prepare_metadata_remediation';
            const isCanonicalBundle = actionKey === 'prepare_indexability_review';
            const isImageAltBundle = actionKey === 'prepare_image_alt_text';
            const hasPreparedMetadataPackage = isMetadataBundle && bundle && (
                (bundle.metadata_execution_package && typeof bundle.metadata_execution_package === 'object'
                    && siteAuditPackageHasRows(bundle.metadata_execution_package))
                || (bundle.last_prepare_result && bundle.last_prepare_result.metadata_execution_package && typeof bundle.last_prepare_result.metadata_execution_package === 'object'
                    && siteAuditPackageHasRows(bundle.last_prepare_result.metadata_execution_package))
                || (bundle.last_prepare_result && bundle.last_prepare_result.execution_package && typeof bundle.last_prepare_result.execution_package === 'object'
                    && siteAuditPackageHasRows(bundle.last_prepare_result.execution_package))
            );
            const hasPreparedCanonicalPackage = isCanonicalBundle && bundle && (
                (bundle.canonical_execution_package && typeof bundle.canonical_execution_package === 'object'
                    && siteAuditPackageHasRows(bundle.canonical_execution_package))
                || (bundle.last_prepare_result && bundle.last_prepare_result.canonical_execution_package && typeof bundle.last_prepare_result.canonical_execution_package === 'object'
                    && siteAuditPackageHasRows(bundle.last_prepare_result.canonical_execution_package))
            );
            const hasPreparedImageAltPackage = isImageAltBundle && bundle && (
                (bundle.image_alt_execution_package && typeof bundle.image_alt_execution_package === 'object'
                    && siteAuditPackageHasRows(bundle.image_alt_execution_package))
                || (bundle.last_prepare_result && bundle.last_prepare_result.image_alt_execution_package && typeof bundle.last_prepare_result.image_alt_execution_package === 'object'
                    && siteAuditPackageHasRows(bundle.last_prepare_result.image_alt_execution_package))
                || (bundle.last_prepare_result && bundle.last_prepare_result.execution_package && typeof bundle.last_prepare_result.execution_package === 'object'
                    && siteAuditPackageHasRows(bundle.last_prepare_result.execution_package))
            );
            const actionPayload = encodeBundlePayload({
                bundle_action_key: actionKey,
                bundle_type: String((bundle && bundle.bundle_type) || ''),
                issue_category: String((bundle && bundle.issue_category) || ''),
                issue_title: String((bundle && bundle.issue_title) || ''),
                affected_count: affectedCount,
                baseline_affected_count: affectedCount,
                target_scope: String((bundle && bundle.target_scope) || ''),
                next_step: String((bundle && bundle.next_step) || ''),
                action_label: String((bundle && bundle.action_label) || ''),
                reason: String((bundle && bundle.reason) || ''),
                execution_package_id: String((bundle && bundle.execution_package_id) || ''),
                package_id: String((bundle && bundle.execution_package_id) || '')
            });
            const skipPayload = encodeBundlePayload({
                bundle_action_key: actionKey,
                action_label: String((bundle && bundle.action_label) || ''),
                affected_count: affectedCount
            });
            const previewRows = Array.isArray(bundle && bundle.affected_urls_preview) ? bundle.affected_urls_preview.slice(0, 8) : [];
            const reviewHtml = previewRows.length
                ? '<ul class="aysa-agent8-technical-list">' + previewRows.map((url) => '<li>' + escapeHtml(String(url || '-')) + '</li>').join('') + '</ul>'
                : '<div class="aysa-agent8-card-summary-row">Affected rows are stored in the Site Audit dataset; this card shows the safe scope before apply.</div>';
            const metadataReviewHtml = hasPreparedMetadataPackage || (isMetadataBundle && executionState !== 'open')
                ? renderMetadataBundleReview(
                    hasPreparedMetadataPackage ? bundle : Object.assign({}, bundle, { metadata_execution_package: buildReducedSiteAuditFallbackPackage(bundle, 'metadata', previewRows, affectedCount) }),
                    actionPayload,
                    applyActionKey,
                    verifyActionKey,
                    skipPayload
                )
                : '';
            const canonicalReviewHtml = hasPreparedCanonicalPackage || (isCanonicalBundle && executionState !== 'open')
                ? renderCanonicalBundleReview(
                    hasPreparedCanonicalPackage ? bundle : Object.assign({}, bundle, { canonical_execution_package: buildReducedSiteAuditFallbackPackage(bundle, 'canonical', previewRows, affectedCount) }),
                    actionPayload,
                    applyActionKey,
                    verifyActionKey,
                    skipPayload
                )
                : '';
            const imageAltReviewHtml = hasPreparedImageAltPackage || (isImageAltBundle && executionState !== 'open')
                ? renderImageAltBundleReview(
                    hasPreparedImageAltPackage ? bundle : Object.assign({}, bundle, { image_alt_execution_package: buildReducedSiteAuditFallbackPackage(bundle, 'image_alt', previewRows, affectedCount) }),
                    actionPayload,
                    applyActionKey,
                    verifyActionKey,
                    skipPayload
                )
                : '';
            return '<div class="aysa-agent8-technical-bundle" data-execution-state="' + escapeHtml(executionState) + '">'
                + '<div class="aysa-agent8-technical-bundle-head"><strong>' + escapeHtml(String((bundle && bundle.action_label) || (bundle && bundle.issue_title) || 'Preparation bundle')) + '</strong><span class="aysa-agent8-badge">' + escapeHtml(String((bundle && bundle.priority_label) || 'Medium')) + '</span></div>'
                + '<div class="aysa-agent8-card-summary-row"><strong>Status:</strong> ' + escapeHtml(executionState) + '</div>'
                + '<div class="aysa-agent8-card-summary-row"><strong>Explain:</strong> ' + escapeHtml(String((bundle && bundle.reason) || '-')) + '</div>'
                + '<div class="aysa-agent8-card-summary-row"><strong>Impact:</strong> ' + escapeHtml(String((bundle && bundle.reason) || 'This can affect crawling, indexing, rankings, or search-result quality.')) + '</div>'
                + '<div class="aysa-agent8-card-summary-row"><strong>Affected scope:</strong> ' + escapeHtml(String(affectedCount)) + ' rows · ' + escapeHtml(String((bundle && bundle.target_scope) || 'audit review')) + '</div>'
                + '<div class="aysa-agent8-card-summary-row"><strong>Recommended action:</strong> ' + escapeHtml(String((bundle && bundle.next_step) || 'Prepare a safe remediation package, review it, then apply only after approval.')) + '</div>'
                + '<details><summary>Review affected pages / evidence</summary>' + reviewHtml
                + '<div class="aysa-agent8-card-summary-row"><strong>Source files:</strong> ' + escapeHtml(Array.isArray(bundle && bundle.source_files) && bundle.source_files.length ? bundle.source_files.join(', ') : 'audit dataset') + '</div></details>'
                + (metadataReviewHtml || canonicalReviewHtml || imageAltReviewHtml || (
                    '<div class="aysa-agent8-technical-bundle-actions">'
                    + '<button type="button" class="aysa-agent8-chip aysa-agent8-bundle-action" data-action-key="' + escapeHtml(actionKey) + '" data-action-payload="' + actionPayload + '">Prepare package</button>'
                    + '<button type="button" class="aysa-agent8-chip aysa-agent8-bundle-action" data-action-key="' + escapeHtml(applyActionKey) + '" data-action-payload="' + actionPayload + '">' + ((isMetadataBundle || isImageAltBundle || isCanonicalBundle) ? 'Approve rewrite' : 'Mark package applied') + '</button>'
                    + '<button type="button" class="aysa-agent8-chip aysa-agent8-bundle-action" data-action-key="' + escapeHtml(verifyActionKey) + '" data-action-payload="' + actionPayload + '">' + (isMetadataBundle ? 'Verify live metadata' : (isImageAltBundle ? 'Verify live image alt' : (isCanonicalBundle ? 'Verify live canonical' : 'Check audit delta'))) + '</button>'
                    + '<button type="button" class="aysa-agent8-chip aysa-agent8-bundle-action" data-action-key="ignore_site_audit_action_bundle" data-action-payload="' + skipPayload + '">Skip for now</button>'
                    + '</div>'
                ))
                + '</div>';
        }).join('') + '</div>';
    }

    function mergeTechnicalActionBundles(recommended, persisted) {
        const merged = [];
        const seen = new Set();
        const persistedItems = Array.isArray(persisted) ? persisted : [];
        const recommendedItems = Array.isArray(recommended) ? recommended : [];
        persistedItems.forEach((bundle) => {
            const key = String(bundle && bundle.action_key ? bundle.action_key : '');
            if (!key || seen.has(key)) {
                return;
            }
            seen.add(key);
            merged.push(bundle);
        });
        recommendedItems.forEach((bundle) => {
            const key = String(bundle && bundle.action_key ? bundle.action_key : '');
            if (!key || seen.has(key)) {
                return;
            }
            seen.add(key);
            merged.push(bundle);
        });
        return merged;
    }

    function renderTechnicalReviewModal() {
        const command = currentUiCommand && typeof currentUiCommand === 'object' ? currentUiCommand : null;
        if (!command) {
            return;
        }

        $('#aysa-agent8-technical-modal-title').text(String(command.title || 'Technical Optimization'));
        $('#aysa-agent8-technical-modal-intro').text(String(command.intro || ''));

        let html = '';
        if (command.type === 'open_technical_overview') {
            const sections = Array.isArray(command.sections) ? command.sections : [];
            html = sections.map((section) => {
                return '<div class="aysa-agent8-technical-section">' +
                    '<h3>' + escapeHtml(String(section.title || '-')) + '</h3>' +
                    renderTechnicalSummaryGrid(section.summary) +
                '</div>';
            }).join('');
        } else {
            const snapshot = command.snapshot && typeof command.snapshot === 'object' ? command.snapshot : {};
            html += '<div class="aysa-agent8-technical-section"><h3>Overview</h3>' + renderTechnicalSummaryGrid(Object.fromEntries((Array.isArray(snapshot.overview_rows) ? snapshot.overview_rows : []).map((row) => [String(row.metric || '-'), String(row.value || '-')])) ) + '</div>';

            if (command.type === 'open_technical_site_audit_review') {
                const conclusion = snapshot.conclusion && typeof snapshot.conclusion === 'object' ? snapshot.conclusion : {};
                if (conclusion.summary || conclusion.main_problem || conclusion.business_impact || (Array.isArray(conclusion.what_to_do_first) && conclusion.what_to_do_first.length) || (Array.isArray(conclusion.top_issues) && conclusion.top_issues.length)) {
                    html += '<div class="aysa-agent8-technical-section"><h3>Conclusions</h3>';
                    if (conclusion.summary) {
                        html += '<p>' + escapeHtml(String(conclusion.summary)) + '</p>';
                    }
                    html += renderTechnicalSummaryGrid({
                        'Audit mode': String(snapshot.mode || 'baseline_full'),
                        'Version': snapshot.version_number ? ('v' + String(snapshot.version_number)) : '-',
                        'History': snapshot.history_count ? String(snapshot.history_count) : '0',
                        'Conclusion status': String(conclusion.status_label || conclusion.status || '-')
                    });
                    if (conclusion.main_problem || conclusion.business_impact) {
                        html += '<h4>Main problem</h4><p>' + escapeHtml(String(conclusion.main_problem || '-')) + '</p>';
                        html += '<h4>Why it matters</h4><p>' + escapeHtml(String(conclusion.business_impact || '-')) + '</p>';
                    }
                    html += '<h4>What to do first</h4>' + renderTechnicalList(conclusion.what_to_do_first || conclusion.priority_actions, (row) => escapeHtml(String(row || '-')));
                    html += '<h4>Top issues</h4>' + renderTechnicalList(conclusion.top_issues, (row) => {
                        return '<strong>' + escapeHtml(String((row && row.title) || '-')) + '</strong> · '
                            + escapeHtml(String((row && row.priority_label) || '-')) + ' · '
                            + escapeHtml(String((row && row.affected_display) || ((row && row.affected_pages) || '0') + ' pages')) + '<br>'
                            + escapeHtml(String((row && row.impact_plain) || '-')) + '<br>'
                            + '<em>' + escapeHtml(String((row && row.first_action_plain) || '-')) + '</em>';
                    });
                    html += '<h4>Guided execution plan</h4><p>The Site Audit crawl and analysis costs 500 credits. Any fix you approve after the audit is billed separately per action, and Agent8 does not run remediation automatically after the audit.</p><p>Start with one issue family, review the affected scope, prepare the package, then apply only after Agent8 asks for approval. Verification stays audit-delta based.</p>' + renderTechnicalActionBundles(mergeTechnicalActionBundles(conclusion.recommended_actions, snapshot.action_bundles));
                    html += '</div>';
                }
                const issueRows = Array.isArray(snapshot.rows) ? snapshot.rows : [];
                const issueInitialLimit = Number(snapshot.rows_initial_limit || 20);
                const visibleIssueRows = issueRows.slice(0, issueInitialLimit);
                html += '<div class="aysa-agent8-technical-section"><h3>Issues</h3><p>' + escapeHtml(String(visibleIssueRows.length)) + ' shown of ' + escapeHtml(String(snapshot.rows_total || issueRows.length || 0)) + '</p>' + renderTechnicalList(visibleIssueRows, (row) => {
                    const title = escapeHtml(String(row.title_plain || row.title || '-'));
                    const priority = escapeHtml(String(row.priority_label || row.severity || '-'));
                    const affected = escapeHtml(String(row.affected_display || ((row.affected_pages || '0') + ' pages')));
                    const impact = escapeHtml(String(row.impact_plain || '-'));
                    const lifecycle = escapeHtml(String(row.lifecycle_state || 'open'));
                    const issueId = String(row.issue_id || row.key || '');
                    const acceptedPayload = encodeURIComponent(JSON.stringify({ issue_id: issueId, lifecycle_state: 'accepted' }));
                    const ignoredPayload = encodeURIComponent(JSON.stringify({ issue_id: issueId, lifecycle_state: 'ignored' }));
                    const resolvedPayload = encodeURIComponent(JSON.stringify({ issue_id: issueId, lifecycle_state: 'resolved' }));
                    return '<strong>' + title + '</strong> · ' + priority + ' · ' + affected + ' · lifecycle: ' + lifecycle + '<br>' + impact
                        + '<div class="aysa-agent8-technical-bundle-actions">'
                        + '<button type="button" class="aysa-agent8-chip aysa-agent8-bundle-action" data-action-key="update_technical_site_audit_issue_lifecycle" data-action-payload="' + acceptedPayload + '">Accept issue</button>'
                        + '<button type="button" class="aysa-agent8-chip aysa-agent8-bundle-action" data-action-key="update_technical_site_audit_issue_lifecycle" data-action-payload="' + ignoredPayload + '">Ignore issue</button>'
                        + '<button type="button" class="aysa-agent8-chip aysa-agent8-bundle-action" data-action-key="update_technical_site_audit_issue_lifecycle" data-action-payload="' + resolvedPayload + '">Mark resolved</button>'
                        + '</div>';
                }) + (issueRows.length > visibleIssueRows.length ? '<button type="button" class="button button-secondary aysa-agent8-technical-show-more" data-kind="issues">View all ' + escapeHtml(String(issueRows.length)) + ' issues</button>' : '') + '</div>';
                const pageRows = Array.isArray(snapshot.pages) ? snapshot.pages : [];
                const pageInitialLimit = Number(snapshot.pages_initial_limit || 20);
                const visiblePageRows = pageRows.slice(0, pageInitialLimit);
                html += '<div class="aysa-agent8-technical-section"><h3>Crawled Pages</h3><p>' + escapeHtml(String(visiblePageRows.length)) + ' shown of ' + escapeHtml(String(snapshot.pages_total || pageRows.length || 0)) + '</p>' + renderTechnicalList(visiblePageRows, (row) => {
                    return '<strong>' + escapeHtml(String(row.title || row.url || '-')) + '</strong> · ' + escapeHtml(String(row.status_code || '-')) + ' · ' + escapeHtml(String(row.url || '-'));
                }) + (pageRows.length > visiblePageRows.length ? '<button type="button" class="button button-secondary aysa-agent8-technical-show-more" data-kind="pages">View all ' + escapeHtml(String(pageRows.length)) + ' crawled pages</button>' : '') + '</div>';
            } else if (command.type === 'open_technical_site_audit_bundle_review') {
                const bundle = snapshot.bundle && typeof snapshot.bundle === 'object' ? snapshot.bundle : {};
                html += '<div class="aysa-agent8-technical-section"><h3>Prepared bundle</h3>';
                html += renderTechnicalSummaryGrid({
                    'Bundle': String(bundle.action_label || bundle.issue_title || '-'),
                    'Priority': String(bundle.priority_label || '-'),
                    'Affected URLs': String(bundle.affected_count || 0),
                    'Target scope': String(bundle.target_scope || '-')
                });
                html += '<p>' + escapeHtml(String(bundle.reason || '-')) + '</p>';
                html += '<h4>Next step</h4><p>' + escapeHtml(String(bundle.next_step || '-')) + '</p>';
                if (String(bundle.action_key || '') === 'prepare_metadata_remediation') {
                    const bundlePayload = encodeBundlePayload({
                        bundle_action_key: String(bundle.action_key || ''),
                        action_label: String(bundle.action_label || ''),
                        affected_count: Number(bundle.affected_count || 0) || 0,
                        execution_package_id: String(bundle.execution_package_id || ''),
                        package_id: String(bundle.execution_package_id || '')
                    });
                    html += renderMetadataBundleReview(
                        bundle,
                        bundlePayload,
                        String(bundle.action_key || '').replace(/^prepare_/, 'apply_'),
                        String(bundle.action_key || '').replace(/^prepare_/, 'verify_'),
                        encodeBundlePayload({
                            bundle_action_key: String(bundle.action_key || ''),
                            action_label: String(bundle.action_label || ''),
                            affected_count: Number(bundle.affected_count || 0) || 0
                        })
                    );
                } else if (String(bundle.action_key || '') === 'prepare_image_alt_text') {
                    const bundlePayload = encodeBundlePayload({
                        bundle_action_key: String(bundle.action_key || ''),
                        action_label: String(bundle.action_label || ''),
                        affected_count: Number(bundle.affected_count || 0) || 0,
                        execution_package_id: String(bundle.execution_package_id || ''),
                        package_id: String(bundle.execution_package_id || '')
                    });
                    html += renderImageAltBundleReview(
                        bundle,
                        bundlePayload,
                        String(bundle.action_key || '').replace(/^prepare_/, 'apply_'),
                        String(bundle.action_key || '').replace(/^prepare_/, 'verify_'),
                        encodeBundlePayload({
                            bundle_action_key: String(bundle.action_key || ''),
                            action_label: String(bundle.action_label || ''),
                            affected_count: Number(bundle.affected_count || 0) || 0
                        })
                    );
                }
                html += '<h4>Source files</h4>' + renderTechnicalList(bundle.source_files, (row) => escapeHtml(String(row || '-')));
                html += '<h4>Preview URLs</h4>' + renderTechnicalList(bundle.affected_urls_preview, (row) => escapeHtml(String(row || '-')));
                html += '</div>';
            } else if (command.type === 'open_technical_pagespeed_review') {
                html += '<div class="aysa-agent8-technical-section"><h3>Priority Actions</h3>' + renderTechnicalList(snapshot.priority_actions, (row) => {
                    return escapeHtml(String((row && row.action) || row || '-'));
                }) + '</div>';
                html += '<div class="aysa-agent8-technical-section"><h3>Opportunities</h3>' + renderTechnicalList(snapshot.rows, (row) => {
                    return '<strong>' + escapeHtml(String(row.title || '-')) + '</strong> · ' + escapeHtml(String(row.strategy || '-')) + ' · ' + escapeHtml(String(row.display_value || '-'));
                }) + '</div>';
            } else if (command.type === 'open_technical_schema_review') {
                html += '<div class="aysa-agent8-technical-section"><h3>Coverage Rows</h3>' + renderTechnicalList(snapshot.rows, (row) => {
                    return '<strong>' + escapeHtml(String(row.title || row.url || '-')) + '</strong> · '
                        + escapeHtml(String(row.schema_type || '-')) + ' · '
                        + escapeHtml(String(row.status || '-'));
                }) + '</div>';
                html += '<div class="aysa-agent8-technical-section"><h3>Detailed Validation</h3>' + renderTechnicalList(snapshot.coverage_rows, (row) => {
                    return '<strong>' + escapeHtml(String(row.title || row.url || '-')) + '</strong> · '
                        + escapeHtml(String(row.google_target_label || row.google_target || '-')) + ' · '
                        + escapeHtml(String(row.execution_eligibility || row.status || '-'));
                }) + '</div>';
            } else if (command.type === 'open_technical_redirects_review') {
                html += '<div class="aysa-agent8-technical-section"><h3>Current Rows</h3>' + renderTechnicalList(snapshot.rows, (row) => {
                    return '<strong>' + escapeHtml(String(row.source_url || row.url || '-')) + '</strong> · '
                        + escapeHtml(String(row.kind || row.status || '-')) + ' · '
                        + escapeHtml(String(row.suggested_action || '-'));
                }) + '</div>';
                const bulk = snapshot.bulk_candidates && typeof snapshot.bulk_candidates === 'object' ? snapshot.bulk_candidates : {};
                html += '<div class="aysa-agent8-technical-section"><h3>Bulk Redirect Candidates</h3>' + renderTechnicalList(Array.isArray(bulk.redirect) ? bulk.redirect : [], (row) => {
                    return '<strong>' + escapeHtml(String(row.source_url || '-')) + '</strong> → ' + escapeHtml(String(row.suggested_target_url || row.target_url || row.redirect_target || '-'));
                }) + '</div>';
                html += '<div class="aysa-agent8-technical-section"><h3>Bulk Gone Candidates</h3>' + renderTechnicalList(Array.isArray(bulk.gone) ? bulk.gone : [], (row) => {
                    return '<strong>' + escapeHtml(String(row.source_url || '-')) + '</strong> · ' + escapeHtml(String(row.suggested_reason || '-'));
                }) + '</div>';
            } else if (command.type === 'open_technical_sitemap_robots_review') {
                html += '<div class="aysa-agent8-technical-section"><h3>Checks</h3>' + renderTechnicalList(snapshot.rows, (row) => {
                    return '<strong>' + escapeHtml(String(row.label || '-')) + '</strong> · ' + escapeHtml(String(row.status || '-'));
                }) + '</div>';
                html += '<div class="aysa-agent8-technical-section"><h3>Sitemaps</h3>' + renderTechnicalList(snapshot.sitemaps, (row) => {
                    return '<strong>' + escapeHtml(String(row.url || '-')) + '</strong> · ' + escapeHtml(String(row.status || (row.reachable ? 'reachable' : 'unreachable') || '-'));
                }) + '</div>';
                html += '<div class="aysa-agent8-technical-section"><h3>robots.txt</h3>' + renderTechnicalList(snapshot.robots_rows, (row) => {
                    return '<strong>' + escapeHtml(String(row.field || '-')) + ':</strong> ' + escapeHtml(String(row.value || '-'));
                }) + '</div>';
            } else if (command.type === 'open_technical_internal_linking_review') {
                if (snapshot.preview_summary) {
                    html += '<div class="aysa-agent8-technical-section"><h3>Preview Summary</h3><div class="aysa-agent8-card-summary-row">' + escapeHtml(String(snapshot.preview_summary)) + '</div></div>';
                }
                html += '<div class="aysa-agent8-technical-section"><h3>Current Links</h3>' + renderTechnicalList(snapshot.rows, (row) => {
                    return '<strong>' + escapeHtml(String(row.keyword || '-')) + '</strong> · target: ' + escapeHtml(String(row.target_title || row.target_url || '-')) + ' · links: ' + escapeHtml(String(row.total_links || '0'));
                }) + '</div>';
                const previewPackage = snapshot.preview_package && typeof snapshot.preview_package === 'object' ? snapshot.preview_package : {};
                const packageItems = Array.isArray(previewPackage.items) ? previewPackage.items : [];
                if (packageItems.length) {
                    html += '<div class="aysa-agent8-technical-section"><h3>Exact Proposed Changes</h3>' + renderTechnicalList(packageItems, (row) => {
                        const risks = Array.isArray(row.risk_flags) && row.risk_flags.length ? ' · risks: ' + row.risk_flags.join(', ') : '';
                        return '<strong>' + escapeHtml(String(row.source_title || row.source_url || '-')) + '</strong>'
                            + ' → <em>' + escapeHtml(String(row.anchor_text || '-')) + '</em>'
                            + ' → ' + escapeHtml(String(row.target_title || row.target_url || '-'))
                            + ' · confidence: ' + escapeHtml(String(row.confidence || '0'))
                            + ' · status: ' + escapeHtml(String(row.status || '-'))
                            + risks;
                    }) + '</div>';
                }
                html += '<div class="aysa-agent8-technical-section"><h3>Preview</h3>' + renderTechnicalList(snapshot.preview_rows, (row) => {
                    if (row.source_url || row.anchor_text || row.target_url) {
                        return '<strong>' + escapeHtml(String(row.source_title || row.source_url || '-')) + '</strong>'
                            + ' → <em>' + escapeHtml(String(row.anchor_text || '-')) + '</em>'
                            + ' → ' + escapeHtml(String(row.target_title || row.target_url || '-'))
                            + ' · status: ' + escapeHtml(String(row.status || '-'));
                    }
                    return '<strong>' + escapeHtml(String(row.content_title || '-')) + '</strong> · links: ' + escapeHtml(String(row.links_count || '0')) + ' · keywords: ' + escapeHtml(String(row.keywords || '-'));
                }) + '</div>';
            }
        }

        $('#aysa-agent8-technical-modal-body').html(html || '<div class="aysa-agent8-card-summary-row">Niciun detaliu tehnic disponibil.</div>');
        sanitizeUnauthorizedActionButtons($('#aysa-agent8-technical-modal'));
    }

    function openKeywordReviewModal() {
        if (!currentUiCommand || currentUiCommand.type !== 'open_keyword_review') {
            return;
        }
        renderKeywordReviewModal();
        sanitizeUnauthorizedActionButtons($('#aysa-agent8-keyword-modal'));
        $('#aysa-agent8-keyword-modal').removeAttr('hidden');
    }

    function openCompetitorsReviewModal() {
        if (!currentUiCommand || currentUiCommand.type !== 'open_research_competitors_review') {
            return;
        }
        renderCompetitorsReviewModal();
        sanitizeUnauthorizedActionButtons($('#aysa-agent8-competitors-modal'));
        $('#aysa-agent8-competitors-modal').removeAttr('hidden');
    }

    function openMissingPagesReviewModal() {
        if (!currentUiCommand || currentUiCommand.type !== 'open_missing_pages_review') {
            return;
        }
        renderMissingPagesReviewModal();
        sanitizeUnauthorizedActionButtons($('#aysa-agent8-missing-pages-modal'));
        $('#aysa-agent8-missing-pages-modal').removeAttr('hidden');
    }

    function openContentStrategyReviewModal() {
        if (!currentUiCommand || currentUiCommand.type !== 'open_content_strategy_review') {
            return;
        }
        renderContentStrategyReviewModal();
        sanitizeUnauthorizedActionButtons($('#aysa-agent8-content-strategy-modal'));
        $('#aysa-agent8-content-strategy-modal').removeAttr('hidden');
    }

    function openPublishingCalendarModal(command) {
        const modalCommand = command && typeof command === 'object' ? command : currentUiCommand;
        const title = String((modalCommand && modalCommand.title) || (conversationLanguage === 'ro' ? 'Calendar editorial' : 'Publishing Calendar'));
        const intro = String((modalCommand && modalCommand.intro) || (conversationLanguage === 'ro'
            ? 'Calendarul editorial real din Content Strategy este încărcat aici.'
            : 'The real editorial calendar from Content Strategy is loaded here.'));
        $('#aysa-agent8-publishing-calendar-modal-title').text(title);
        $('#aysa-agent8-publishing-calendar-modal-intro').text(intro);
        const separator = publishingCalendarEmbedUrl.indexOf('?') >= 0 ? '&' : '?';
        const frameUrl = publishingCalendarEmbedUrl + separator + '_ts=' + String(Date.now());
        const $frame = $('#aysa-agent8-publishing-calendar-frame');
        $('#aysa-agent8-publishing-calendar-modal').removeAttr('hidden');
        const renderedNative = renderPublishingCalendarNative();
        $('#aysa-agent8-publishing-calendar-modal .aysa-agent8-modal-iframe-wrap').toggle(!renderedNative);
        $('#aysa-agent8-publishing-calendar-modal-done').toggle(!renderedNative);
        loadPublishingCalendarNativeFromAjax();
        window.requestAnimationFrame(function() {
            $frame.attr('src', frameUrl);
        });
    }

    function loadPublishingCalendarNativeFromAjax() {
        const $native = $('#aysa-agent8-publishing-calendar-native');
        $native.html('<div class="aysa-agent8-calendar-native-summary">Loading calendar...</div>').removeAttr('hidden');
        $.post(ajaxUrl, {
            action: 'aysa_get_content_calendar',
            nonce: contentStrategyNonce,
            project_id: projectId || wpProjectId
        }).done(function(response) {
            if (!response || !response.success || !response.data || !Array.isArray(response.data.events)) {
                renderPublishingCalendarNative();
                return;
            }
            const mergedEvents = response.data.events.map(function(event) {
                const copy = event && typeof event === 'object' ? Object.assign({}, event) : event;
                if (copy && typeof copy === 'object') {
                    const strategyId = String(copy.strategy_id || '').trim();
                    const itemId = String((copy.strategy_id || copy.id || '') || '').replace(/^local-/, '');
                    const contract = currentPublishingCalendarRowContracts[itemId] || (strategyId ? currentPublishingCalendarRowContracts[strategyId] : null);
                    if (contract && typeof contract === 'object') {
                        copy.row_contract = contract;
                    }
                }
                return copy;
            });
	        currentPublishingCalendarSnapshot = {
	            events: mergedEvents,
	            today: response.data.today || {},
	            summary: { events: mergedEvents.length },
	            schedule_contract: currentPublishingCalendarScheduleContract
	        };
        currentPublishingCalendarVisibleLimit = 50;
        const renderedNative = renderPublishingCalendarNative();
        $('#aysa-agent8-publishing-calendar-modal .aysa-agent8-modal-iframe-wrap').toggle(!renderedNative);
        $('#aysa-agent8-publishing-calendar-modal-done').toggle(!renderedNative);
        }).fail(function() {
            renderPublishingCalendarNative();
        });
    }

    function calendarEventDate(event) {
        return String((event && (event.scheduled_for_local || event.scheduled_for || event.datetime)) || '');
    }

    function calendarEventMonth(event) {
        const date = calendarEventDate(event);
        return date.length >= 7 ? date.slice(0, 7) : '';
    }

    function calendarEventPageType(event) {
        return String((event && (event.recommended_page_type || event.target_page_type || event.page_type || '')) || '').trim();
    }

    function calendarEventContentType(event) {
        return String((event && event.content_type) || '').trim();
    }

    function calendarEventStatus(event) {
        return String((event && event.status) || '').trim();
    }

    function calendarEventIsSchedulable(event) {
        const status = calendarEventStatus(event).toLowerCase();
        return status === 'proposed' || status === 'planned';
    }

    function calendarEventSource(event) {
        return String((event && (event.source || event.strategy_type || event.reason_source)) || '').trim();
    }

    function collectPublishingCalendarRowContracts(snapshot) {
        const contracts = {};
        const source = snapshot && typeof snapshot === 'object' ? snapshot : {};
        if (source.row_contracts && typeof source.row_contracts === 'object') {
            Object.keys(source.row_contracts).forEach(function(key) {
                const contract = source.row_contracts[key];
                if (contract && typeof contract === 'object') {
                    contracts[String(key)] = contract;
                    if (contract.row_id) {
                        contracts[String(contract.row_id)] = contract;
                    }
                }
            });
        }
        const events = Array.isArray(source.events) ? source.events : [];
        events.forEach(function(event) {
            if (!event || typeof event !== 'object' || !event.row_contract || typeof event.row_contract !== 'object') {
                return;
            }
            const strategyId = String(event.strategy_id || '').trim();
            const itemId = String((event.strategy_id || event.id || '') || '').replace(/^local-/, '');
            if (itemId) {
                contracts[itemId] = event.row_contract;
            }
            if (strategyId) {
                contracts[strategyId] = event.row_contract;
            }
        });
        return contracts;
    }

    function uniqueCalendarFilterValues(events, getter) {
        const seen = {};
        return events.map(getter).filter((value) => {
            const key = String(value || '').trim();
            if (!key || seen[key]) {
                return false;
            }
            seen[key] = true;
            return true;
        }).sort((a, b) => String(a).localeCompare(String(b)));
    }

    function calendarExplainerText(kind, value) {
        const key = String(value || '').trim().toLowerCase();
        const sourceMap = {
            missing_pages: 'Ideas created because research found searches that need a page your site does not clearly cover yet.',
            authority_building: 'Content meant to build trust and expertise, so visitors and search engines see the site as more authoritative.',
            seasonal_events: 'Seasonal content tied to dates, holidays, or recurring buying moments.',
            evergreen_fresh: 'Evergreen topics that stay useful over time, refreshed with current details when needed.',
            local_seo: 'Local-intent content focused on the city, nearby areas, and customers searching close to your business.',
            competitor_sitemap: 'Ideas inspired by competitor pages or sitemap gaps that may be worth covering.',
            competitor_analysis: 'Ideas derived from competitor research and topics they already cover.',
            cluster_based: 'Ideas grouped from related keyword themes, so one page can cover a coherent topic.',
            customer_journey: 'Content planned for different customer decision stages, from discovery to purchase.',
            intent_layering: 'Content organized by search intent, such as informational, commercial, or transactional needs.',
            persona_based: 'Ideas aimed at a specific customer type or buying situation.',
            serp_features: 'Content designed around search result features like snippets, local packs, or rich results.'
        };
        const contentTypeMap = {
            post: 'An article or blog-style page that explains a topic, answers questions, or supports discovery.',
            article: 'An informational article that helps users learn before they choose or buy.',
            landing_page: 'A focused commercial page built to target a service, category, location, or offer.',
            page: 'A standard site page, usually more stable than a blog article.'
        };
        const pageTypeMap = {
            article: 'Best for informational searches, guides, comparisons, and educational topics.',
            landing_page: 'Best for commercial or local-intent searches where the user may be ready to contact or buy.',
            category: 'Best for broader product or service groups, not one narrow product.',
            product: 'Best for a specific product or very specific purchase intent.'
        };
        if (kind === 'source') {
            return sourceMap[key] || 'This source describes why the item was added to the editorial plan.';
        }
        if (kind === 'content_type') {
            return contentTypeMap[key] || 'This describes the format the content should take.';
        }
        if (kind === 'page_type') {
            return pageTypeMap[key] || 'This describes the kind of page that best matches the search intent.';
        }
        return '';
    }

    function calendarInfoTrigger(kind, value) {
        const explanation = calendarExplainerText(kind, value);
        if (!explanation) {
            return '';
        }
        return '<button type="button" class="aysa-agent8-calendar-info-trigger" data-info-kind="' + escapeAttribute(kind) + '" data-info-value="' + escapeAttribute(value) + '" title="' + escapeAttribute('Explain ' + value) + '" aria-label="' + escapeAttribute('Explain ' + value) + '">?</button>';
    }

    function calendarFilterSelect(filterKey, label, values) {
        const currentValue = String(currentPublishingCalendarFilters[filterKey] || '');
        const options = ['<option value="">' + escapeHtml(conversationLanguage === 'ro' ? 'Toate' : 'All') + '</option>']
            .concat(values.map((value) => {
                const selected = String(value) === currentValue ? ' selected' : '';
                return '<option value="' + escapeAttribute(value) + '"' + selected + '>' + escapeHtml(value) + '</option>';
            })).join('');
        const infoKind = filterKey === 'source' ? 'source' : (filterKey === 'content_type' ? 'content_type' : (filterKey === 'page_type' ? 'page_type' : ''));
        const currentInfoValue = currentValue || (values.length ? values[0] : '');
        return '<label><span class="aysa-agent8-calendar-native-label-line">' + escapeHtml(label) + (infoKind && currentInfoValue ? calendarInfoTrigger(infoKind, currentInfoValue) : '') + '</span><select class="aysa-agent8-calendar-native-filter" data-filter-key="' + escapeAttribute(filterKey) + '">' + options + '</select></label>';
    }

    function renderPublishingCalendarNative() {
        const snapshot = currentPublishingCalendarSnapshot && typeof currentPublishingCalendarSnapshot === 'object'
            ? currentPublishingCalendarSnapshot
            : {};
        const events = Array.isArray(snapshot.events) ? snapshot.events : [];
        const $native = $('#aysa-agent8-publishing-calendar-native');
        if (!events.length) {
            $native.html('').attr('hidden', 'hidden');
            return false;
        }
        const today = snapshot.today && typeof snapshot.today === 'object' ? snapshot.today : {};
        const totalEvents = Number(snapshot.summary && snapshot.summary.events ? snapshot.summary.events : events.length) || events.length;
        const filteredEvents = events.filter((event) => {
            if (currentPublishingCalendarFilters.month && calendarEventMonth(event) !== currentPublishingCalendarFilters.month) {
                return false;
            }
            if (currentPublishingCalendarFilters.page_type && calendarEventPageType(event) !== currentPublishingCalendarFilters.page_type) {
                return false;
            }
            if (currentPublishingCalendarFilters.content_type && calendarEventContentType(event) !== currentPublishingCalendarFilters.content_type) {
                return false;
            }
            if (currentPublishingCalendarFilters.status && calendarEventStatus(event) !== currentPublishingCalendarFilters.status) {
                return false;
            }
            if (currentPublishingCalendarFilters.source && calendarEventSource(event) !== currentPublishingCalendarFilters.source) {
                return false;
            }
            return true;
        });
	        const scheduleContract = snapshot.schedule_contract && typeof snapshot.schedule_contract === 'object'
	            ? snapshot.schedule_contract
	            : null;
	        const hasSchedulableEvents = !!scheduleContract && events.some(calendarEventIsSchedulable);
        currentPublishingCalendarRowContracts = {};
        const scheduleNotice = currentPublishingCalendarScheduleNotice && typeof currentPublishingCalendarScheduleNotice === 'object'
            ? String(currentPublishingCalendarScheduleNotice.message || '')
            : '';
        const scheduleNoticeType = currentPublishingCalendarScheduleNotice && typeof currentPublishingCalendarScheduleNotice === 'object'
            ? String(currentPublishingCalendarScheduleNotice.type || 'info')
            : 'info';
        const visibleLimit = Math.max(1, Number(currentPublishingCalendarVisibleLimit || 50));
        const visibleEvents = filteredEvents.slice(0, visibleLimit);
        const visibleCount = visibleEvents.length;
        const hasMore = visibleCount < filteredEvents.length;
        const activeFilters = Object.keys(currentPublishingCalendarFilters)
            .filter((key) => String(currentPublishingCalendarFilters[key] || '') !== '')
            .map((key) => String(currentPublishingCalendarFilters[key]));
        const filterSummary = activeFilters.length
            ? activeFilters.join(' · ')
            : (conversationLanguage === 'ro' ? 'toate evenimentele' : 'all events');
        const summary = conversationLanguage === 'ro'
            ? 'Calendarul conține ' + totalEvents + ' evenimente. Filtru activ: ' + filterSummary + '. Pentru azi: ' + String(today.scheduled_count || 0) + ' programate și ' + String(today.published_count || 0) + ' publicate.'
            : 'The calendar contains ' + totalEvents + ' events. Active filter: ' + filterSummary + '. Today: ' + String(today.scheduled_count || 0) + ' scheduled and ' + String(today.published_count || 0) + ' published.';
        const controls = '<div class="aysa-agent8-calendar-native-controls">' +
            calendarFilterSelect('month', conversationLanguage === 'ro' ? 'Lună' : 'Month', uniqueCalendarFilterValues(events, calendarEventMonth)) +
            calendarFilterSelect('page_type', conversationLanguage === 'ro' ? 'Tip pagină' : 'Page type', uniqueCalendarFilterValues(events, calendarEventPageType)) +
            calendarFilterSelect('content_type', conversationLanguage === 'ro' ? 'Tip conținut' : 'Content type', uniqueCalendarFilterValues(events, calendarEventContentType)) +
            calendarFilterSelect('status', 'Status', uniqueCalendarFilterValues(events, calendarEventStatus)) +
            calendarFilterSelect('source', conversationLanguage === 'ro' ? 'Sursă' : 'Source', uniqueCalendarFilterValues(events, calendarEventSource)) +
        '</div>';
        const rangeText = filteredEvents.length
            ? (conversationLanguage === 'ro'
                ? 'Afișare 1-' + visibleCount + ' din ' + filteredEvents.length + ' evenimente filtrate'
                : 'Showing 1-' + visibleCount + ' of ' + filteredEvents.length + ' filtered events')
            : (conversationLanguage === 'ro' ? 'Niciun eveniment pentru filtrele active' : 'No events for the active filters');
        const groups = {};
        visibleEvents.forEach((event) => {
            const rawDate = calendarEventDate(event);
            const dayKey = rawDate.slice(0, 10) || 'unscheduled';
            if (!groups[dayKey]) {
                groups[dayKey] = [];
            }
            groups[dayKey].push(event);
        });
        const rows = Object.keys(groups).sort().map((dayKey) => {
            const dayEvents = groups[dayKey];
            const dayLabel = dayKey === 'unscheduled'
                ? (conversationLanguage === 'ro' ? 'Fără dată' : 'Unscheduled')
                : new Date(dayKey + 'T12:00:00').toLocaleDateString(conversationLanguage === 'ro' ? 'ro-RO' : 'en-US', {
                    weekday: 'long',
                    year: 'numeric',
                    month: 'short',
                    day: 'numeric'
            });
            const eventRows = dayEvents.map((event) => {
            const title = String(event && event.title ? event.title : 'Untitled');
            const date = calendarEventDate(event);
            const strategyId = String((event && event.strategy_id) || '').trim();
            const itemId = String((event && (event.strategy_id || event.id || '')) || '').replace(/^local-/, '');
                const rowContract = event && event.row_contract && typeof event.row_contract === 'object'
                    ? event.row_contract
                    : null;
                if (itemId && rowContract) {
                    currentPublishingCalendarRowContracts[itemId] = rowContract;
                    if (strategyId) {
                        currentPublishingCalendarRowContracts[strategyId] = rowContract;
                    }
                }
                const contentType = String((event && event.content_type) || '');
                const pageType = calendarEventPageType(event);
                const intent = String((event && event.intent) || '');
                const status = String((event && event.status) || '');
                const source = calendarEventSource(event);
                const theme = String((event && (event.keyword || event.theme || event.target_keyword)) || '');
            return '<div class="aysa-agent8-calendar-native-row">' +
                    '<div>' +
                        '<div class="aysa-agent8-calendar-native-title">' + escapeHtml(title) + '</div>' +
                        '<div class="aysa-agent8-calendar-native-meta">' +
                            '<span class="aysa-agent8-calendar-native-badge">' + escapeHtml(date || '-') + '</span>' +
                            (contentType ? '<span class="aysa-agent8-calendar-native-badge">' + escapeHtml(contentType) + calendarInfoTrigger('content_type', contentType) + '</span>' : '') +
                            (pageType ? '<span class="aysa-agent8-calendar-native-badge">' + escapeHtml(pageType) + calendarInfoTrigger('page_type', pageType) + '</span>' : '') +
                            (intent ? '<span class="aysa-agent8-calendar-native-badge">' + escapeHtml(intent) + '</span>' : '') +
                            (status ? '<span class="aysa-agent8-calendar-native-badge">' + escapeHtml(status) + '</span>' : '') +
                            (source ? '<span class="aysa-agent8-calendar-native-badge">' + escapeHtml(source) + calendarInfoTrigger('source', source) + '</span>' : '') +
                            (theme ? '<span class="aysa-agent8-calendar-native-badge">' + escapeHtml(theme) + '</span>' : '') +
                        '</div>' +
                    '</div>' +
                    '<div class="aysa-agent8-calendar-native-actions">' +
                    (itemId ? '<button type="button" class="button button-secondary aysa-agent8-calendar-native-reject" data-action-key="' + escapeAttribute(rowContract ? 'update_content_strategy_items' : (strategyId && /^[0-9]+$/.test(strategyId) ? 'update_content_strategy_items' : 'reject_planned_content')) + '" data-item-id="' + escapeAttribute(itemId) + '" data-strategy-id="' + escapeAttribute(strategyId) + '" data-has-row-contract="' + escapeAttribute(rowContract ? '1' : '0') + '">Reject</button>' : '') +
                '</div>' +
            '</div>';
        }).join('');
        return '<section class="aysa-agent8-calendar-native-day">' +
            '<div class="aysa-agent8-calendar-native-day-head"><strong>' + escapeHtml(dayLabel) + '</strong><span class="aysa-agent8-calendar-native-day-count">' + escapeHtml(String(dayEvents.length)) + ' itemi</span></div>' +
                eventRows +
            '</section>';
        }).join('');
    $native.html(
        '<div class="aysa-agent8-calendar-native-summary">' + escapeHtml(summary) + '</div>' +
        (scheduleNotice ? '<div class="aysa-agent8-calendar-native-summary aysa-agent8-calendar-native-schedule-' + escapeAttribute(scheduleNoticeType) + '">' + escapeHtml(scheduleNotice) + '</div>' : '') +
        controls +
        '<div class="aysa-agent8-calendar-native-range"><span>' + escapeHtml(rangeText) + '</span>' + (hasMore ? '<button type="button" class="button button-secondary aysa-agent8-calendar-native-load-more" data-next-limit="' + escapeAttribute(String(visibleLimit + 50)) + '">' + escapeHtml(conversationLanguage === 'ro' ? 'Încarcă mai multe' : 'Load more') + '</button>' : '') + '</div>' +
        '<div class="aysa-agent8-calendar-native-list">' + rows + '</div>' +
        (hasMore ? '<div class="aysa-agent8-calendar-native-range aysa-agent8-calendar-native-range-bottom"><span>' + escapeHtml(rangeText) + '</span><button type="button" class="button button-secondary aysa-agent8-calendar-native-load-more" data-next-limit="' + escapeAttribute(String(visibleLimit + 50)) + '">' + escapeHtml(conversationLanguage === 'ro' ? 'Încarcă mai multe' : 'Load more') + '</button></div>' : '') +
        (hasSchedulableEvents ? '<div class="aysa-agent8-calendar-native-footer"><button type="button" class="button button-primary" id="aysa-agent8-calendar-native-continue" data-action-key="schedule_publishing_plan">' + escapeHtml(conversationLanguage === 'ro' ? 'Continuă cu planul curent' : 'Continue with current plan') + '</button></div>' : '')
    ).removeAttr('hidden');
    sanitizeUnauthorizedActionButtons($native);
    return true;
}

    function handlePublishingScheduleSuccess(result) {
        const actionResult = result && result.action_result && typeof result.action_result === 'object'
            ? result.action_result
            : {};
        const summary = actionResult.summary && typeof actionResult.summary === 'object'
            ? actionResult.summary
            : {};
        const scheduled = Math.max(0, Number(summary.scheduled || summary.queued || 0) || 0);
        const baseMessage = conversationLanguage === 'ro'
            ? 'Planul editorial a fost programat. Itemii vor fi generați la orele programate.'
            : 'Publishing plan scheduled. Items will be generated at their scheduled times.';
        const countMessage = scheduled > 0
            ? (conversationLanguage === 'ro' ? String(scheduled) + ' itemi programați. ' : String(scheduled) + ' items scheduled. ')
            : '';
        currentPublishingCalendarScheduleNotice = {
            type: 'success',
            message: countMessage + baseMessage
        };
        $('#aysa-agent8-calendar-native-continue')
            .prop('disabled', true)
            .text(conversationLanguage === 'ro' ? 'Programat' : 'Scheduled');
        loadPublishingCalendarNativeFromAjax();
    }

    function handlePublishingScheduleError(message) {
        currentPublishingCalendarScheduleNotice = {
            type: 'error',
            message: message || (conversationLanguage === 'ro'
                ? 'Programarea a eșuat. Încearcă din nou.'
                : 'Scheduling failed. Please try again.')
        };
        $('#aysa-agent8-calendar-native-continue')
            .prop('disabled', false)
            .text(conversationLanguage === 'ro' ? 'Continuă cu planul curent' : 'Continue with current plan');
        renderPublishingCalendarNative();
    }

    function isPublishingCalendarRejectButton(sourceButton) {
        return !!(sourceButton && sourceButton.length && sourceButton.hasClass('aysa-agent8-calendar-native-reject'));
    }

    function handlePublishingCalendarRejectSuccess() {
        currentPublishingCalendarScheduleNotice = {
            type: 'success',
            message: conversationLanguage === 'ro'
                ? 'Itemul a fost refuzat și calendarul a fost actualizat.'
                : 'The item was rejected and the calendar was refreshed.'
        };
        $('.aysa-agent8-calendar-native-reject:disabled').text(conversationLanguage === 'ro' ? 'Refuzat' : 'Rejected');
        loadPublishingCalendarNativeFromAjax();
    }

    function handlePublishingCalendarRejectError(sourceButton, message) {
        currentPublishingCalendarScheduleNotice = {
            type: 'error',
            message: message || (conversationLanguage === 'ro'
                ? 'Refuzul a eșuat. Încearcă din nou.'
                : 'Reject failed. Please try again.')
        };
        if (sourceButton && sourceButton.length) {
            sourceButton.prop('disabled', false).text('Reject');
        }
        renderPublishingCalendarNative();
    }

    function sanitizeArticlePreviewHtml(html) {
        const $wrap = $('<div></div>').html(String(html || ''));
        $wrap.find('script, style, iframe, object, embed, form').remove();
        $wrap.find('*').each(function() {
            $.each(this.attributes || [], function() {
                const name = String(this.name || '').toLowerCase();
                const value = String(this.value || '');
                if (name.indexOf('on') === 0 || (name === 'href' && value.toLowerCase().indexOf('javascript:') === 0)) {
                    $(this.ownerElement).removeAttr(this.name);
                }
            });
        });
        return $wrap.html();
    }

    function openArticlePreviewModal(command) {
        const modalCommand = command && typeof command === 'object' ? command : currentUiCommand;
        const draftId = parseInt(modalCommand && modalCommand.draft_id ? modalCommand.draft_id : 0, 10) || 0;
        const orderRef = String((modalCommand && modalCommand.order_ref) || '');
        const portalDomain = String((modalCommand && modalCommand.portal_domain) || '');
        const targetUrl = String((modalCommand && modalCommand.target_url) || '');
        const warning = String((modalCommand && modalCommand.warning) || 'Approving this changes Adverlink state.');
        const $status = $('#aysa-agent8-article-preview-modal-status');
        const $body = $('#aysa-agent8-article-preview-modal-body');
        $('#aysa-agent8-article-preview-modal').removeAttr('hidden');
        $status.text('Loading article preview...').removeAttr('hidden');
        $body.html('');
        $('#aysa-agent8-article-preview-email, #aysa-agent8-article-preview-approve').prop('disabled', draftId <= 0).attr('data-draft-id', String(draftId));
        if (draftId <= 0) {
            $status.text('No draft article is available for preview.').removeAttr('hidden');
            return;
        }
        $.post(ajaxUrl, {
            action: 'aysa_adverlink_get_publisher_article_draft',
            nonce: nonce,
            draft_id: draftId
        }).done(function(response) {
            if (!response || !response.success || !response.data || !response.data.draft) {
                $status.text((response && response.data) ? String(response.data) : 'Could not load draft.').removeAttr('hidden');
                return;
            }
            const draft = response.data.draft || {};
            const title = String(draft.title || 'Adverlink article draft');
            const excerpt = String(draft.excerpt || '');
            const bodyHtml = sanitizeArticlePreviewHtml(String(draft.body_html || draft.content || ''));
            $('#aysa-agent8-article-preview-modal-title').text(title);
            $status.attr('hidden', 'hidden').text('');
            $body.html(
                '<div class="aysa-agent8-card"><div class="aysa-agent8-card-body">' +
                    '<div class="aysa-agent8-card-grid">' +
                        '<div><strong>Draft ID:</strong> ' + escapeHtml(String(draftId)) + '</div>' +
                        '<div><strong>Order ref:</strong> ' + escapeHtml(orderRef || String(draft.order_ref || '-')) + '</div>' +
                        '<div><strong>Portal/domain:</strong> ' + escapeHtml(portalDomain || String(draft.portal_domain || '-')) + '</div>' +
                        '<div><strong>Target URL:</strong> ' + (targetUrl ? '<a href="' + escapeHtml(targetUrl) + '" target="_blank" rel="noopener noreferrer">' + escapeHtml(targetUrl) + '</a>' : '-') + '</div>' +
                    '</div>' +
                    '<div class="aysa-agent8-modal-status" style="margin-top:14px;">' + escapeHtml(warning) + '</div>' +
                '</div></div>' +
                (excerpt ? '<div class="aysa-agent8-card"><div class="aysa-agent8-card-body"><strong>Excerpt</strong><p>' + escapeHtml(excerpt) + '</p></div></div>' : '') +
                '<div class="aysa-agent8-card"><div class="aysa-agent8-card-body"><strong>Full article body</strong><div class="aysa-agent8-article-preview-body">' + (bodyHtml || '<p>No article body returned.</p>') + '</div></div></div>'
            );
        }).fail(function(xhr) {
            $status.text(xhr && xhr.responseJSON && xhr.responseJSON.data ? String(xhr.responseJSON.data) : 'Could not load draft.').removeAttr('hidden');
        });
        sanitizeUnauthorizedActionButtons($('#aysa-agent8-article-preview-modal'));
    }

    function purchasePreviewPayload(command) {
        const modalCommand = command && typeof command === 'object' ? command : currentUiCommand;
        const orderContract = modalCommand && modalCommand.metadata && typeof modalCommand.metadata.order_contract === 'object'
            ? modalCommand.metadata.order_contract
            : {};
        return {
            flow: String((modalCommand && modalCommand.flow) || ''),
            portal_id: String((modalCommand && modalCommand.portal_id) || ''),
            portal_domain: String((modalCommand && modalCommand.portal_domain) || ''),
            authority: modalCommand && modalCommand.authority !== undefined ? Number(modalCommand.authority || 0) : 0,
            score: modalCommand && modalCommand.score !== undefined ? Number(modalCommand.score || 0) : 0,
            service_type: String((modalCommand && modalCommand.service_type) || ''),
            billing_type: String((modalCommand && modalCommand.billing_type) || ''),
            target_url: String((modalCommand && modalCommand.target_url) || ''),
            keyword: String((modalCommand && modalCommand.keyword) || ''),
            estimated_cost_cents: Number((modalCommand && modalCommand.estimated_cost_cents) || 0),
            monthly_cost_cents: Number((modalCommand && modalCommand.monthly_cost_cents) || 0),
            included_link_eligible: modalCommand && modalCommand.included_link_eligible !== undefined ? modalCommand.included_link_eligible : null,
            order_intent_id: String(orderContract.order_intent_id || ''),
            quote_hash: String(orderContract.quote_hash || ''),
            payload_hash: String(orderContract.payload_hash || ''),
            idempotency_key: String(orderContract.idempotency_key || '')
        };
    }

    function openPurchasePreviewModal(command) {
        const payload = purchasePreviewPayload(command);
        const isSeoTextAds = payload.flow === 'seo_text_ads' || payload.service_type === 'seo_ads_text';
        const cost = isSeoTextAds ? payload.monthly_cost_cents : payload.estimated_cost_cents;
        const title = isSeoTextAds ? 'SEO Text Ads order preview' : 'Link Insertion order preview';
        const warning = String((command && command.warning) || 'Placing this order changes Adverlink state and may consume credits.');
        $('#aysa-agent8-purchase-preview-modal-title').text(title);
        $('#aysa-agent8-purchase-preview-modal-status').text(warning).removeAttr('hidden');
        $('#aysa-agent8-purchase-preview-modal').removeAttr('hidden');
        $('#aysa-agent8-purchase-preview-email, #aysa-agent8-purchase-preview-place')
            .prop('disabled', !payload.portal_id || !payload.portal_domain)
            .attr('data-action-key', function() {
                return this.id === 'aysa-agent8-purchase-preview-email'
                    ? (isSeoTextAds ? 'send_offpage_seo_text_ads_approval_email' : 'send_offpage_link_insertion_approval_email')
                    : (isSeoTextAds ? 'place_offpage_seo_text_ads_order' : 'place_offpage_link_insertion_order');
            })
            .attr('data-payload', window.encodeURIComponent(JSON.stringify(payload)));
        $('#aysa-agent8-purchase-preview-modal-body').html(
            '<div class="aysa-agent8-card"><div class="aysa-agent8-card-body">' +
                '<div class="aysa-agent8-card-grid">' +
                    '<div><strong>Portal/domain:</strong> ' + escapeHtml(payload.portal_domain || '-') + '</div>' +
                    '<div><strong>Authority:</strong> ' + escapeHtml(payload.authority ? payload.authority.toFixed(1) : '-') + '</div>' +
                    '<div><strong>Score:</strong> ' + escapeHtml(payload.score ? payload.score.toFixed(1) : '-') + '</div>' +
                    '<div><strong>Service type:</strong> ' + escapeHtml(payload.service_type || (isSeoTextAds ? 'seo_ads_text' : 'link_insertion')) + '</div>' +
                    '<div><strong>Billing type:</strong> ' + escapeHtml(isSeoTextAds ? 'monthly' : 'one-time') + '</div>' +
                    '<div><strong>Estimated cost:</strong> ' + escapeHtml(String(cost || 0)) + ' credits' + (isSeoTextAds ? ' / month' : '') + '</div>' +
                    '<div><strong>Target URL:</strong> ' + (payload.target_url ? '<a href="' + escapeHtml(payload.target_url) + '" target="_blank" rel="noopener noreferrer">' + escapeHtml(payload.target_url) + '</a>' : '-') + '</div>' +
                    '<div><strong>Keyword/anchor:</strong> ' + escapeHtml(payload.keyword || '-') + '</div>' +
                    '<div><strong>Included link eligibility:</strong> ' + escapeHtml(payload.included_link_eligible === null ? 'Not available' : (payload.included_link_eligible ? 'Eligible' : 'Not eligible')) + '</div>' +
                '</div>' +
            '</div></div>'
        );
        sanitizeUnauthorizedActionButtons($('#aysa-agent8-purchase-preview-modal'));
    }

    function openTechnicalReviewModal() {
        if (!currentUiCommand || !String(currentUiCommand.type || '').startsWith('open_technical_')) {
            return;
        }
        $('#aysa-agent8-technical-modal-status').text('').attr('hidden', 'hidden');
        renderTechnicalReviewModal();
        $('#aysa-agent8-technical-modal').removeAttr('hidden');
    }

    function closeKeywordReviewModal() {
        $('#aysa-agent8-keyword-modal').attr('hidden', 'hidden');
    }

    function closeCompetitorsReviewModal() {
        $('#aysa-agent8-competitors-modal').attr('hidden', 'hidden');
    }

    function closeMissingPagesReviewModal() {
        $('#aysa-agent8-missing-pages-modal').attr('hidden', 'hidden');
    }

    function closeContentStrategyReviewModal() {
        $('#aysa-agent8-content-strategy-modal').attr('hidden', 'hidden');
    }

    function closePublishingCalendarModal() {
        $('#aysa-agent8-publishing-calendar-modal').attr('hidden', 'hidden');
        $('#aysa-agent8-publishing-calendar-frame').attr('src', 'about:blank');
    }

    function closeTechnicalReviewModal() {
        $('#aysa-agent8-technical-modal').attr('hidden', 'hidden');
    }

    function closeArticlePreviewModal() {
        $('#aysa-agent8-article-preview-modal').attr('hidden', 'hidden');
    }

    function closePurchasePreviewModal() {
        $('#aysa-agent8-purchase-preview-modal').attr('hidden', 'hidden');
    }

	    function collectMissingPagesModalItems() {
	        const items = [];
	        $('#aysa-agent8-missing-pages-modal-body .aysa-agent8-missing-pages-item').has('.aysa-agent8-missing-page-select:checked').each(function() {
	            const $row = $(this);
	            const item = missingPagePayloadFromRow($row);
	            if (item) {
	                items.push(item);
	            }
	        });
	        return items;
	    }

	    function missingPagePayloadFromRow($row) {
	        const keyword = decodeMessage($row.attr('data-keyword') || '');
	        if (!keyword) {
	            return null;
	        }
	        return {
	            item_id: String($row.attr('data-item-id') || ''),
	            keyword: keyword,
	            intent: decodeMessage($row.attr('data-intent') || '') || 'unknown',
	            source: decodeMessage($row.attr('data-source') || '') || 'missing_pages',
	            recommendation_reason: decodeMessage($row.attr('data-reason') || ''),
	            recommended_page_type: String($row.find('.aysa-agent8-missing-page-type').val() || 'landing_page'),
	            resolution_status: decodeMessage($row.attr('data-resolution-status') || '') || 'unresolved'
	        };
	    }

	    function setMissingPageSaveState($rows, state, message) {
	        const stateClass = state === 'saving' ? 'is-saving' : (state === 'saved' ? 'is-saved' : (state === 'existing' ? 'is-existing' : (state === 'error' ? 'is-error' : '')));
	        $rows.each(function() {
	            const $row = $(this);
	            const $status = $row.find('.aysa-agent8-missing-pages-save-status');
	            $row.toggleClass('is-saving', state === 'saving');
	            $row.find('button, select, input').prop('disabled', state === 'saving');
	            $status
	                .removeClass('is-saving is-saved is-existing is-error')
	                .addClass(stateClass)
	                .attr('data-save-state', state)
	                .text(message);
	        });
	    }

	    function saveMissingPagesRows($rows, items) {
	        if (!$rows.length || !Array.isArray(items) || !items.length) {
	            return;
	        }
	        const requestEpoch = conversationRequestEpoch;
	        const payload = {
	            action: 'aysa_agent8_conversation',
	            nonce: nonce,
	            mode: 'action',
	            action_key: 'send_missing_pages_to_plan',
	            project_id: projectId,
	            wp_project_id: wpProjectId,
	            site_host: siteHost,
	            conversation_language: conversationLanguage,
	            request_epoch: requestEpoch,
	            action_payload: JSON.stringify({ items: items })
	        };
	        if (conversationId) {
	            payload.conversation_id = conversationId;
	        }
	        setMissingPageSaveState($rows, 'saving', 'Saving...');
	        $.post(ajaxUrl, payload).done(function(response) {
	            if (!response || !response.success || !response.data) {
	                setMissingPageSaveState($rows, 'error', 'Error');
	                $('#aysa-agent8-missing-pages-modal-status').text((response && response.data && response.data.message) ? response.data.message : 'Agent 8 action failed.').removeAttr('hidden');
	                return;
	            }
	            const result = response.data.result || {};
	            const actionResult = result.action_result && typeof result.action_result === 'object' ? result.action_result : {};
	            const summary = actionResult.summary && typeof actionResult.summary === 'object' ? actionResult.summary : {};
	            const existing = Number(summary.existing || 0);
	            const added = Number(summary.added || 0);
	            if (existing > 0 && added <= 0) {
	                setMissingPageSaveState($rows, 'existing', 'Already in plan');
	            } else {
	                setMissingPageSaveState($rows, 'saved', 'Saved to plan');
	            }
	            $rows.find('.aysa-agent8-missing-page-select').prop('checked', false);
	            updateMissingPagesSelectionBar();
	            $('#aysa-agent8-missing-pages-modal-status').text(String(added + existing || items.length) + ' item(s) saved to the content plan.').removeAttr('hidden');
	        }).fail(function(xhr) {
	            setMissingPageSaveState($rows, 'error', 'Error');
	            $('#aysa-agent8-missing-pages-modal-status').text(xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message ? xhr.responseJSON.data.message : 'Agent 8 action failed.').removeAttr('hidden');
	        });
	    }

    function updateMissingPagesSelectionBar() {
        const selected = $('#aysa-agent8-missing-pages-modal-body .aysa-agent8-missing-page-select:checked').length;
        $('#aysa-agent8-missing-pages-selected-count').text(String(selected));
    }

    function collectContentStrategyModalItems() {
        const items = [];
        $('#aysa-agent8-content-strategy-modal-body .aysa-agent8-content-strategy-item').each(function() {
            const $row = $(this);
            const id = parseInt(String($row.attr('data-id') || '0'), 10);
            if (!id) {
                return;
            }
            syncContentStrategyAssociation($row);
            items.push({
                id: id,
                rejected: $row.hasClass('is-rejected'),
                associated_page: String($row.find('.aysa-agent8-content-strategy-association').val() || '').trim()
            });
        });
        return items;
    }

    function openHelpModal(title, body) {
        $('#aysa-agent8-help-modal-title').text(String(title || 'Help'));
        $('#aysa-agent8-help-modal-body').text(String(body || ''));
        $('#aysa-agent8-help-modal').removeAttr('hidden');
    }

    function closeHelpModal() {
        $('#aysa-agent8-help-modal').attr('hidden', 'hidden');
    }

    function updateUiCommandKeywordState(clusterId, keyword) {
        if (!currentUiCommand || currentUiCommand.type !== 'open_keyword_review' || !Array.isArray(currentUiCommand.rows)) {
            return;
        }
        currentUiCommand.rows = currentUiCommand.rows.filter((row) => {
            return !(String(row.cluster_id || '') === String(clusterId || '') && String(row.keyword || '') === String(keyword || ''));
        });
    }

    function clearUiCommandKeywordAssociation(rowKey) {
        if (!currentUiCommand || currentUiCommand.type !== 'open_keyword_review' || !Array.isArray(currentUiCommand.rows)) {
            return;
        }
        currentUiCommand.rows = currentUiCommand.rows.map((row) => {
            if (String(row.row_key || '') !== String(rowKey || '')) {
                return row;
            }
            const next = Object.assign({}, row);
            next.associated_page = '';
            return next;
        });
    }

    function normalizeApprovalIntentMessage(value) {
        return String(value || '')
            .toLowerCase()
            .normalize('NFD')
            .replace(/[\u0300-\u036f]/g, '')
            .replace(/\s+/g, ' ')
            .trim();
    }

    function matchesApprovalPhrase(value, phrases) {
        const normalized = ' ' + normalizeApprovalIntentMessage(value) + ' ';
        if (!normalized.trim()) {
            return false;
        }
        return (Array.isArray(phrases) ? phrases : []).some((token) => {
            const phrase = normalizeApprovalIntentMessage(token);
            if (!phrase) {
                return false;
            }
            const escaped = phrase.replace(/[.*+?^${}()|[\]\\]/g, '\\$&').replace(/\s+/g, '\\s+');
            const re = new RegExp('(^|[^A-Za-z0-9_])' + escaped + '($|[^A-Za-z0-9_])', 'i');
            return re.test(normalized);
        });
    }

    function isNegativeApprovalIntent(value) {
        return matchesApprovalPhrase(value, [
            'nu e ok',
            'nu este ok',
            'nu-i ok',
            'nu vreau',
            'nu imi place',
            'nu-mi place',
            'mai schimba',
            'mai schimbă',
            'corecteaza',
            'corectează'
        ]);
    }

    function looksLikeApprovalConfirm(value) {
        const normalized = normalizeApprovalIntentMessage(value);
        if (!normalized || isNegativeApprovalIntent(normalized)) {
            return false;
        }
        return [
            'ok',
            'e ok',
            'este ok',
            'da',
            'yes',
            'confirm',
            'confirma',
            'salveaza',
            'save',
            'approve'
        ].indexOf(normalized) >= 0;
    }

    function looksLikeApprovalDecline(value) {
        const normalized = normalizeApprovalIntentMessage(value);
        if (!normalized) {
            return false;
        }
        return [
            'nu acum',
            'not now',
            'cancel',
            'anuleaza',
            'inchide'
        ].indexOf(normalized) >= 0;
    }

    function postConversation(mode, userMessage, options) {
        options = options && typeof options === 'object' ? options : {};
        const requestEpoch = conversationRequestEpoch;
        if (mode === 'message' && isAgent8ForegroundPending()) {
            return;
        }
        if (mode === 'message' && pendingApproval && pendingApproval.action_key) {
            if (looksLikeApprovalConfirm(userMessage)) {
                postApproval(true);
                return;
            }
            if (looksLikeApprovalDecline(userMessage)) {
                postApproval(false);
                return;
            }
        }
        if (mode === 'message' && userMessage) {
            const detectedLanguage = detectMessageLanguage(userMessage);
            if (detectedLanguage) {
                conversationLanguage = normalizeLanguageCode(detectedLanguage);
                applyUiLanguage();
            }
        }
        const payload = {
            action: 'aysa_agent8_conversation',
            nonce: nonce,
            mode: mode,
            project_id: projectId,
            wp_project_id: wpProjectId,
            site_host: siteHost,
            conversation_language: conversationLanguage,
            request_epoch: requestEpoch
        };
        if (options.forceFreshBootstrap) {
            payload.force_fresh_bootstrap = 1;
        }
        if (conversationId) {
            payload.conversation_id = conversationId;
        }
        if (userMessage) {
            payload.user_message = userMessage;
        }
        if (mode === 'message' && state && typeof state === 'object' && Object.keys(state).length) {
            payload.client_state = JSON.stringify(state);
        }

        pendingApproval = null;
        currentSuggestions = [];
        currentConversationRunId = '';
        $('#aysa-agent8-send').prop('disabled', true);
        showAgent8Thinking(requestEpoch, 'message', null);
        $.post(ajaxUrl, payload).done(function(response) {
            if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                clearAgent8Thinking(requestEpoch);
                return;
            }
            if (!response || !response.success || !response.data) {
                appendAgent8ReadableError((response && response.data && response.data.message) ? response.data.message : 'Agent8 request failed.');
                return;
            }
            stopConversationPolling();
            clearAgent8Thinking(requestEpoch);
            applyResult(response.data.result || {}, response.data.wallet_snapshot || {}, mode === 'bootstrap' || mode === 'reset');
        }).fail(function(xhr) {
            if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                clearAgent8Thinking(requestEpoch);
                return;
            }
            appendAgent8ReadableError(xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message ? xhr.responseJSON.data.message : 'Agent8 request failed.');
        }).always(function() {
            if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                return;
            }
            $('#aysa-agent8-send').prop('disabled', false);
            clearAgent8Thinking(requestEpoch);
            renderTranscript();
        });
    }

    function postApproval(approved, sourceButton) {
        const requestEpoch = conversationRequestEpoch;
        if (isAgent8ForegroundPending()) {
            return;
        }
        if (!pendingApproval || !pendingApproval.action_key) {
            return;
        }
        const approvalRequest = pendingApproval;
        if (isSyncApprovalActionKey(approvalRequest.action_key)) {
            const payload = {
                action: 'aysa_agent8_conversation',
                nonce: nonce,
                mode: 'approval',
                action_key: approvalRequest.action_key,
                approved: approved ? 1 : 0,
                project_id: projectId,
                wp_project_id: wpProjectId,
                site_host: siteHost,
                conversation_language: conversationLanguage,
                request_epoch: requestEpoch
            };
            if (conversationId) {
                payload.conversation_id = conversationId;
            }

            pendingApproval = null;
            currentSuggestions = [];
            currentConversationRunId = '';
            showAgent8Thinking(requestEpoch, 'approval', sourceButton && sourceButton.length ? sourceButton : null);
            $.post(ajaxUrl, payload).done(function(response) {
                if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                    clearAgent8Thinking(requestEpoch);
                    return;
                }
                if (!response || !response.success || !response.data) {
                    appendAgent8ReadableError((response && response.data && response.data.message) ? response.data.message : 'Agent8 action failed.');
                    return;
                }
                stopConversationPolling();
                clearAgent8Thinking(requestEpoch);
                applyResult(response.data.result || {}, response.data.wallet_snapshot || {}, false);
            }).fail(function(xhr) {
                if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                    clearAgent8Thinking(requestEpoch);
                    return;
                }
                appendAgent8ReadableError(xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message ? xhr.responseJSON.data.message : 'Agent8 action failed.');
            }).always(function() {
                if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                    return;
                }
                clearAgent8Thinking(requestEpoch);
                renderTranscript();
            });
            return;
        }
        const payload = {
            action: 'aysa_conversation_async_start',
            task: 'agent8',
            nonce: nonce,
            mode: 'approval',
            action_key: approvalRequest.action_key,
            approved: approved ? 1 : 0,
            project_id: projectId,
            wp_project_id: wpProjectId,
            site_host: siteHost,
            conversation_language: conversationLanguage,
            request_epoch: requestEpoch
        };
        if (conversationId) {
            payload.conversation_id = conversationId;
        }

        pendingApproval = null;
        currentSuggestions = [];
        showAgent8Thinking(requestEpoch, 'approval', sourceButton && sourceButton.length ? sourceButton : null);
        $('#aysa-agent8-pending').attr('data-mode', 'background');
        $.post(ajaxUrl, payload).done(function(response) {
            if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                clearAgent8Thinking(requestEpoch);
                return;
            }
            if (!response || !response.success || !response.data) {
                appendAgent8ReadableError((response && response.data && response.data.message) ? response.data.message : 'Agent8 action failed.');
                return;
            }
            currentConversationRunId = String(response.data.run_id || '');
            const status = String(response.data.status || '');
            if (status === 'completed' && response.data.result) {
                stopConversationPolling();
                clearAgent8Thinking(requestEpoch);
                applyResult(response.data.result.result || {}, response.data.result.wallet_snapshot || {}, false);
                return;
            }
            scheduleConversationPolling('approval', '', {
                action_key: approvalRequest.action_key,
                approved: approved ? 1 : 0,
                request_epoch: requestEpoch
            });
            clearAgent8Thinking(requestEpoch, true);
        }).fail(function(xhr) {
            if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                clearAgent8Thinking(requestEpoch);
                return;
            }
            appendAgent8ReadableError(xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message ? xhr.responseJSON.data.message : 'Agent8 action failed.');
        }).always(function() {
            if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                return;
            }
            if (!currentConversationRunId) {
                clearAgent8Thinking(requestEpoch);
                renderTranscript();
            }
        });
    }

    function postAction(actionKey, actionPayload, sourceButton) {
        const normalizedActionKey = String(actionKey || '').trim();
        if (!normalizedActionKey) {
            return;
        }
        if (!isBackendActionAllowed(normalizedActionKey)) {
            appendAgent8ReadableError(conversationLanguage === 'ro'
                ? 'Acțiunea nu este disponibilă în stadiul curent.'
                : 'This action is not available in the current state.');
            renderTranscript();
            return;
        }
        if (isAgent8ForegroundPending()) {
            return;
        }
        const requestEpoch = nextConversationRequestEpoch();

        if (isSyncActionKey(normalizedActionKey)) {
            const payload = {
                action: 'aysa_agent8_conversation',
                nonce: nonce,
                mode: 'action',
                action_key: normalizedActionKey,
                project_id: projectId,
                wp_project_id: wpProjectId,
                site_host: siteHost,
                conversation_language: conversationLanguage,
                request_epoch: requestEpoch
            };
            if (conversationId) {
                payload.conversation_id = conversationId;
            }
            if (actionPayload && typeof actionPayload === 'object') {
                payload.action_payload = JSON.stringify(actionPayload);
            }

            pendingApproval = null;
            showAgent8Thinking(requestEpoch, 'action', sourceButton && sourceButton.length ? sourceButton : null, normalizedActionKey);
            $.post(ajaxUrl, payload).done(function(response) {
                if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                    clearAgent8Thinking(requestEpoch);
                    return;
                }
                if (!response || !response.success || !response.data) {
                    if (normalizedActionKey === 'schedule_publishing_plan') {
                        handlePublishingScheduleError((response && response.data && response.data.message) ? response.data.message : '');
                    }
                    if (isPublishingCalendarRejectButton(sourceButton)) {
                        handlePublishingCalendarRejectError(sourceButton, (response && response.data && response.data.message) ? response.data.message : '');
                    }
                    appendAgent8ReadableError((response && response.data && response.data.message) ? response.data.message : 'Agent8 action failed.');
                    return;
                }
                stopConversationPolling();
                clearAgent8Thinking(requestEpoch);
                applyResult(response.data.result || {}, response.data.wallet_snapshot || {}, false);
                if (normalizedActionKey === 'schedule_publishing_plan') {
                    handlePublishingScheduleSuccess(response.data.result || {});
                }
                if (isPublishingCalendarRejectButton(sourceButton)) {
                    handlePublishingCalendarRejectSuccess();
                }
            }).fail(function(xhr) {
                if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                    clearAgent8Thinking(requestEpoch);
                    return;
                }
                if (normalizedActionKey === 'schedule_publishing_plan') {
                    handlePublishingScheduleError(xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message ? xhr.responseJSON.data.message : '');
                }
                if (isPublishingCalendarRejectButton(sourceButton)) {
                    handlePublishingCalendarRejectError(sourceButton, xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message ? xhr.responseJSON.data.message : '');
                }
                appendAgent8ReadableError(xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message ? xhr.responseJSON.data.message : 'Agent8 action failed.');
            }).always(function() {
                if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                    return;
                }
                clearAgent8Thinking(requestEpoch);
                renderTranscript();
            });
            return;
        }

        const payload = {
            action: 'aysa_conversation_async_start',
            task: 'agent8',
            nonce: nonce,
            mode: 'action',
            action_key: normalizedActionKey,
            project_id: projectId,
            wp_project_id: wpProjectId,
            site_host: siteHost,
            conversation_language: conversationLanguage,
            request_epoch: requestEpoch
        };
        if (conversationId) {
            payload.conversation_id = conversationId;
        }
        if (actionPayload && typeof actionPayload === 'object') {
            payload.action_payload = JSON.stringify(actionPayload);
        }

        pendingApproval = null;
        showAgent8Thinking(requestEpoch, 'action', sourceButton && sourceButton.length ? sourceButton : null, normalizedActionKey);
        $('#aysa-agent8-pending').attr('data-mode', 'background');
        $.post(ajaxUrl, payload).done(function(response) {
            if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                clearAgent8Thinking(requestEpoch);
                return;
            }
            if (!response || !response.success || !response.data) {
                appendAgent8ReadableError((response && response.data && response.data.message) ? response.data.message : 'Agent8 action failed.');
                return;
            }
            currentConversationRunId = String(response.data.run_id || '');
            const status = String(response.data.status || '');
            if (status === 'completed' && response.data.result) {
                stopConversationPolling();
                clearAgent8Thinking(requestEpoch);
                applyResult(response.data.result.result || {}, response.data.result.wallet_snapshot || {}, false);
                return;
            }
            scheduleConversationPolling('action', '', {
                action_key: normalizedActionKey,
                action_payload: actionPayload && typeof actionPayload === 'object' ? JSON.stringify(actionPayload) : '',
                request_epoch: requestEpoch
            });
            clearAgent8Thinking(requestEpoch, true);
        }).fail(function(xhr) {
            if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                clearAgent8Thinking(requestEpoch);
                return;
            }
            appendAgent8ReadableError(xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message ? xhr.responseJSON.data.message : 'Agent8 action failed.');
        }).always(function() {
            if (!isCurrentConversationRequestEpoch(requestEpoch)) {
                return;
            }
            if (!currentConversationRunId) {
                clearAgent8Thinking(requestEpoch);
                renderTranscript();
            }
        });
    }

    function disconnectGoogle() {
        $('#aysa-agent8-send, #aysa-agent8-reset, #aysa-agent8-google-disconnect').prop('disabled', true);
        $('#aysa-agent8-pending').attr('data-mode', 'google_disconnect');
        applyUiLanguage();
        $('#aysa-agent8-pending').removeAttr('hidden');
        renderTranscript();

        $.post(ajaxUrl, {
            action: 'aysa_google_disconnect',
            nonce: googleOauthNonce,
            project_id: projectId,
            wp_project_id: wpProjectId
        }).done(function(response) {
            if (!response || !response.success) {
                alert((response && response.data) ? String(response.data) : 'Google disconnect failed.');
                return;
            }

            state = {};
            transcript = [];
            pendingApproval = null;
            conversationId = '';
            currentProjection = null;
            currentSuggestions = [];
            currentContractIssue = null;
            renderTranscript();
            postConversation('bootstrap', '', { forceFreshBootstrap: true });
        }).fail(function(xhr) {
            alert(xhr && xhr.responseJSON && xhr.responseJSON.data ? xhr.responseJSON.data : 'Google disconnect failed.');
        }).always(function() {
            $('#aysa-agent8-send, #aysa-agent8-reset, #aysa-agent8-google-disconnect').prop('disabled', false);
            $('#aysa-agent8-pending').attr('data-mode', 'thinking');
            applyUiLanguage();
            $('#aysa-agent8-pending').attr('hidden', 'hidden');
            renderTranscript();
        });
    }

    function autoresizeComposer() {
        const el = document.getElementById('aysa-agent8-input');
        if (!el) {
            return;
        }
        el.style.height = 'auto';
        el.style.height = Math.min(el.scrollHeight, 180) + 'px';
    }

    $('#aysa-agent8-send').on('click', function() {
        if (isAgent8ForegroundPending()) {
            return;
        }
        const value = ($('#aysa-agent8-input').val() || '').trim();
        if (!value) {
            return;
        }
        if (pendingGeneralFieldInput === 'support_phone' && !/^\+?[0-9][0-9\s\-\(\)]{7,}$/.test(value)) {
            appendAgent8ReadableError(conversationLanguage === 'ro'
                ? 'Scrie numărul public de contact, de exemplu 0722237373.'
                : 'Type the public contact phone number, for example 0722237373.');
            renderTranscript();
            return;
        }
        pendingGeneralFieldInput = '';
        $('#aysa-agent8-input').val('');
        autoresizeComposer();
        postConversation('message', value);
    });

    $('#aysa-agent8-input').on('input', function() {
        autoresizeComposer();
    });

    $('#aysa-agent8-input').on('keydown', function(event) {
        if (event.key === 'Enter' && !event.shiftKey) {
            event.preventDefault();
            $('#aysa-agent8-send').trigger('click');
        }
    });

    $(document).on('click', '.aysa-agent8-suggestion', function() {
        const $sourceButton = $(this);
        if ($sourceButton.is(':disabled') || isAgent8ForegroundPending()) {
            return;
        }
        const type = String($sourceButton.attr('data-type') || 'message');
        if (type === 'open_keyword_review') {
            openKeywordReviewModal();
            return;
        }
        if (type === 'open_missing_pages_review') {
            openMissingPagesReviewModal();
            return;
        }
        if (type === 'open_research_competitors_review') {
            openCompetitorsReviewModal();
            return;
        }
        if (type === 'open_content_strategy_review') {
            openContentStrategyReviewModal();
            return;
        }
        if (
            type === 'open_technical_overview'
            || type === 'open_technical_site_audit_review'
            || type === 'open_technical_pagespeed_review'
            || type === 'open_technical_schema_review'
            || type === 'open_technical_redirects_review'
            || type === 'open_technical_sitemap_robots_review'
            || type === 'open_technical_internal_linking_review'
        ) {
            openTechnicalReviewModal();
            return;
        }
        if (type === 'action') {
            const actionKey = decodeMessage($sourceButton.attr('data-action-key') || '');
            let actionPayload = {};
            try {
                actionPayload = JSON.parse(window.decodeURIComponent(String($sourceButton.attr('data-action-payload') || '')));
            } catch (e) {
                actionPayload = {};
            }
            if (actionKey) {
                postAction(actionKey, actionPayload, $sourceButton);
            }
            return;
        }
        if (type === 'prompt_general_field') {
            let actionPayload = {};
            try {
                actionPayload = JSON.parse(window.decodeURIComponent(String($sourceButton.attr('data-action-payload') || '')));
            } catch (e) {
                actionPayload = {};
            }
            pendingGeneralFieldInput = String(actionPayload.field || '').trim();
            const message = decodeMessage($sourceButton.attr('data-message') || '');
            const $input = $('#aysa-agent8-input');
            if (message) {
                $input.attr('placeholder', message);
            }
            $input.focus();
            return;
        }
        if (type === 'open_url') {
            const url = decodeMessage($sourceButton.attr('data-url') || '');
            if (url) {
                openExternalUrl(url, $sourceButton.attr('data-title') || '');
            }
            return;
        }
        const message = decodeMessage($sourceButton.attr('data-message') || '');
        if (!message) {
            return;
        }
        postConversation('message', message);
    });

    $(document).on('click', '.aysa-agent8-technical-rail-item', function() {
        const $sourceButton = $(this);
        if ($sourceButton.is(':disabled') || isAgent8ForegroundPending()) {
            return;
        }
        const actionKey = String($sourceButton.attr('data-action-key') || '').trim();
        if (!actionKey) {
            return;
        }
        postAction(actionKey, {}, $sourceButton);
    });

    $(document).on('click', '.aysa-agent8-async-refresh', function() {
        if (asyncPollTimer) {
            window.clearTimeout(asyncPollTimer);
            asyncPollTimer = null;
        }
        if (
            String(currentTabSlug || '') === 'schema'
            || (currentProjection && String(currentProjection.type || '') === 'technical_schema')
            || (currentAsyncProgress && String(currentAsyncProgress.job_type || '') === 'technical_schema')
        ) {
            currentAsyncJob = Object.assign({}, currentAsyncJob || {}, {
                run_id: 0,
                job_type: 'technical_schema',
                status_endpoint: '/v1/research-runs/technical-schema/status'
            });
        }
        ensureAsyncPollingTargetFromProgress();
        pollAsyncJobStatus();
    });

    $(document).on('click', '#aysa-agent8-approve', function() {
        postApproval(true, $(this));
    });

    $(document).on('click', '#aysa-agent8-decline', function() {
        postApproval(false, $(this));
    });

    $(document).on('click', '#aysa-agent8-article-preview-modal-close, [data-article-preview-modal-close="1"]', function() {
        closeArticlePreviewModal();
    });

    $(document).on('click', '#aysa-agent8-purchase-preview-modal-close, [data-purchase-preview-modal-close="1"]', function() {
        closePurchasePreviewModal();
    });

    $(document).on('click', '#aysa-agent8-article-preview-email', function() {
        const draftId = parseInt($(this).attr('data-draft-id') || '0', 10) || 0;
        if (draftId > 0) {
            postAction('send_offpage_draft_article_approval_email', { draft_id: draftId }, $(this));
        }
    });

    $(document).on('click', '#aysa-agent8-purchase-preview-email', function() {
        let payload = {};
        try {
            payload = JSON.parse(window.decodeURIComponent(String($(this).attr('data-payload') || '')));
        } catch (e) {
            payload = {};
        }
        const actionKey = payload.flow === 'seo_text_ads' ? 'send_offpage_seo_text_ads_approval_email' : 'send_offpage_link_insertion_approval_email';
        postAction(actionKey, payload, $(this));
    });

    $(document).on('click', '#aysa-agent8-purchase-preview-place', function() {
        let payload = {};
        try {
            payload = JSON.parse(window.decodeURIComponent(String($(this).attr('data-payload') || '')));
        } catch (e) {
            payload = {};
        }
        const actionKey = payload.flow === 'seo_text_ads' ? 'place_offpage_seo_text_ads_order' : 'place_offpage_link_insertion_order';
        postAction(actionKey, payload, $(this));
    });

    $(document).on('click', '#aysa-agent8-article-preview-approve', function() {
        const draftId = parseInt($(this).attr('data-draft-id') || '0', 10) || 0;
        if (draftId > 0) {
            postAction('approve_offpage_draft_article', { draft_id: draftId }, $(this));
        }
    });

    $(document).on('click', '#aysa-agent8-keyword-modal-close, #aysa-agent8-keyword-modal-done, [data-modal-close="1"]', function() {
        closeKeywordReviewModal();
    });

    $(document).on('click', '.aysa-agent8-keyword-load-more', function() {
        const nextOffset = Math.max(0, Number($(this).attr('data-next-offset') || 0));
	        const limit = Math.max(1, Number($(this).attr('data-limit') || 24));
        const reviewType = currentUiCommand && typeof currentUiCommand === 'object'
            ? String(currentUiCommand.review_type || 'keyword_mapping')
            : 'keyword_mapping';
        postAction(reviewType === 'found_keywords' ? 'show_found_keywords' : 'show_keyword_mapping', {
            offset: nextOffset,
            limit: limit
        });
    });

    $(document).on('click', '#aysa-agent8-competitors-modal-close, #aysa-agent8-competitors-modal-done, [data-competitors-modal-close="1"]', function() {
        closeCompetitorsReviewModal();
    });

    $(document).on('click', '#aysa-agent8-missing-pages-modal-close, #aysa-agent8-missing-pages-modal-done, [data-missing-pages-modal-close="1"]', function() {
        closeMissingPagesReviewModal();
    });

	    $(document).on('change', '.aysa-agent8-missing-page-select', function() {
	        updateMissingPagesSelectionBar();
	    });

	    $(document).on('change', '.aysa-agent8-missing-page-type', function() {
	        const $row = $(this).closest('.aysa-agent8-missing-pages-item');
	        const item = missingPagePayloadFromRow($row);
	        if (!item) {
	            return;
	        }
	        saveMissingPagesRows($row, [item]);
	    });

    $(document).on('click', '.aysa-agent8-missing-pages-select-group', function() {
        $(this).closest('.aysa-agent8-missing-pages-decision-group').find('.aysa-agent8-missing-page-select').prop('checked', true);
        updateMissingPagesSelectionBar();
    });

    $(document).on('click', '.aysa-agent8-missing-pages-clear-group', function() {
        $(this).closest('.aysa-agent8-missing-pages-decision-group').find('.aysa-agent8-missing-page-select').prop('checked', false);
        updateMissingPagesSelectionBar();
    });

    $(document).on('click', '#aysa-agent8-missing-pages-clear-selected', function() {
        const selected = $('#aysa-agent8-missing-pages-modal-body .aysa-agent8-missing-page-select:checked').closest('.aysa-agent8-missing-pages-item');
        if (!selected.length) {
            $('#aysa-agent8-missing-pages-modal-status').text('Nu există itemi selectați.').removeAttr('hidden');
            return;
        }
        selected.each(function() {
            $(this).find('.aysa-agent8-missing-page-select').prop('checked', false);
        });
        updateMissingPagesSelectionBar();
        $('#aysa-agent8-missing-pages-modal-status').text(String(selected.length) + ' itemi au fost debifați din selecția curentă.').removeAttr('hidden');
    });

    $(document).on('click', '#aysa-agent8-missing-pages-send-selected', function() {
        $('#aysa-agent8-missing-pages-send-to-plan').trigger('click');
    });

    $(document).on('click', '.aysa-agent8-missing-pages-load-more', function() {
        const nextOffset = Math.max(0, Number($(this).attr('data-next-offset') || 0));
	        const limit = Math.max(1, Number($(this).attr('data-limit') || 24));
        postAction('show_missing_pages', {
            offset: nextOffset,
            limit: limit
        });
    });

    $(document).on('click', '#aysa-agent8-content-strategy-modal-close, #aysa-agent8-content-strategy-modal-done, [data-content-strategy-modal-close="1"]', function() {
        closeContentStrategyReviewModal();
    });

    $(document).on('click', '#aysa-agent8-publishing-calendar-modal-close, #aysa-agent8-publishing-calendar-modal-done, [data-publishing-calendar-modal-close="1"]', function() {
        closePublishingCalendarModal();
    });

    $(document).on('click', '#aysa-agent8-technical-modal-close, #aysa-agent8-technical-modal-done, [data-technical-modal-close="1"]', function() {
        closeTechnicalReviewModal();
    });

    $(document).on('click', '.aysa-agent8-technical-show-more', function() {
        if (!currentUiCommand || !currentUiCommand.snapshot || typeof currentUiCommand.snapshot !== 'object') {
            return;
        }
        const kind = String($(this).attr('data-kind') || '');
        if (kind === 'issues') {
            currentUiCommand.snapshot.rows_initial_limit = Array.isArray(currentUiCommand.snapshot.rows) ? currentUiCommand.snapshot.rows.length : 20;
        } else if (kind === 'pages') {
            currentUiCommand.snapshot.pages_initial_limit = Array.isArray(currentUiCommand.snapshot.pages) ? currentUiCommand.snapshot.pages.length : 20;
        }
        renderTechnicalReviewModal();
    });

    $(document).on('click', '.aysa-agent8-metadata-review-trigger', function() {
        const decision = String($(this).attr('data-target-decision') || 'manual_review');
        const $target = $('#aysa-agent8-technical-modal-body').find('.aysa-agent8-metadata-bucket[data-decision="' + decision + '"]');
        if (!$target.length) {
            return;
        }
        $target.attr('open', 'open');
        const targetTop = $target.offset() && $('#aysa-agent8-technical-modal-body').offset()
            ? ($target.offset().top - $('#aysa-agent8-technical-modal-body').offset().top + $('#aysa-agent8-technical-modal-body').scrollTop() - 16)
            : 0;
        $('#aysa-agent8-technical-modal-body').animate({ scrollTop: Math.max(0, targetTop) }, 180);
    });

	    $(document).on('click', '.aysa-agent8-missing-page-reject', function() {
	        const itemId = String($(this).closest('.aysa-agent8-missing-pages-item').attr('data-item-id') || '');
	        if (!itemId) {
	            return;
	        }
		        postAction('reject_missing_page', Object.assign(currentReviewPaginationPayload(), { item_id: itemId }));
	    });

	    $(document).on('click', '.aysa-agent8-missing-page-save', function() {
	        const $row = $(this).closest('.aysa-agent8-missing-pages-item');
	        const item = missingPagePayloadFromRow($row);
	        if (!item) {
	            return;
	        }
	        saveMissingPagesRows($row, [item]);
	    });

    $(document).on('click', '.aysa-agent8-missing-page-accept-plan', function() {
        const $row = $(this).closest('.aysa-agent8-missing-pages-item');
        const keyword = decodeMessage($row.attr('data-keyword') || '');
        if (!keyword) {
            return;
        }
        postAction('send_missing_pages_to_plan', {
            items: [{
                keyword: keyword,
                intent: decodeMessage($row.attr('data-intent') || '') || 'unknown',
                source: decodeMessage($row.attr('data-source') || '') || 'missing_pages',
                recommendation_reason: decodeMessage($row.attr('data-reason') || ''),
                recommended_page_type: String($row.find('.aysa-agent8-missing-page-type').val() || 'landing_page'),
                resolution_status: decodeMessage($row.attr('data-resolution-status') || '') || 'unresolved'
            }]
        });
    });

    $(document).on('click', '.aysa-agent8-missing-page-accept-existing', function() {
        const $row = $(this).closest('.aysa-agent8-missing-pages-item');
        const itemId = String($row.attr('data-item-id') || '');
        if (!itemId) {
            return;
        }
        const selected = String($row.find('.aysa-agent8-missing-page-existing-select').val() || '');
        if (!selected) {
            return;
        }
	        postAction('accept_missing_page_ai_proposal', Object.assign(currentReviewPaginationPayload(), { item_id: itemId, selected_page_url: selected }));
    });

    $(document).on('click', '.aysa-agent8-missing-page-choose-existing', function() {
        const $row = $(this).closest('.aysa-agent8-missing-pages-item');
        const itemId = String($row.attr('data-item-id') || '');
        if (!itemId) {
            return;
        }
        const selected = String($row.find('.aysa-agent8-missing-page-existing-select').val() || '');
        if (!selected) {
            return;
        }
	        postAction('choose_missing_page_existing_page', Object.assign(currentReviewPaginationPayload(), { item_id: itemId, selected_page_url: selected }));
    });

    $(document).on('click', '.aysa-agent8-missing-page-keep', function() {
        const itemId = String($(this).closest('.aysa-agent8-missing-pages-item').attr('data-item-id') || '');
        if (!itemId) {
            return;
        }
	        postAction('keep_missing_page', Object.assign(currentReviewPaginationPayload(), { item_id: itemId }));
    });

	    $(document).on('click', '#aysa-agent8-missing-pages-send-to-plan', function() {
	        const $rows = $('#aysa-agent8-missing-pages-modal-body .aysa-agent8-missing-pages-item').has('.aysa-agent8-missing-page-select:checked');
	        const items = collectMissingPagesModalItems();
	        if (!items.length) {
	            $('#aysa-agent8-missing-pages-modal-status').text('Nu mai există itemi selectați pentru plan.').removeAttr('hidden');
	            return;
	        }
	        saveMissingPagesRows($rows, items);
	    });

    $(document).on('click', '.aysa-agent8-content-strategy-reject', function() {
        const $button = $(this);
        const $row = $button.closest('.aysa-agent8-content-strategy-item');
        const itemId = String($row.attr('data-item-id') || '');
        if (!itemId) {
            return;
        }
        $button.prop('disabled', true).text('Se salvează...');
	        postAction('reject_planned_content', Object.assign(currentReviewPaginationPayload(), { item_id: itemId }));
    });

    $(document).on('click', '.aysa-agent8-calendar-native-reject', function() {
        const $button = $(this);
        const itemId = String($button.attr('data-item-id') || '').trim();
        const strategyId = String($button.attr('data-strategy-id') || '').trim();
        if (!itemId) {
            return;
        }
        $button.prop('disabled', true).text('Se salvează...');
        const rowContract = currentPublishingCalendarRowContracts[itemId] || (strategyId ? currentPublishingCalendarRowContracts[strategyId] : null);
        if (rowContract && typeof rowContract === 'object') {
            const rowId = Number(rowContract.row_id || strategyId || itemId);
            postAction('update_content_strategy_items', {
                row_contract: rowContract,
                items: [{
                    id: rowId,
                    rejected: true,
                    row_contract: rowContract
                }]
            }, $button);
            return;
        }
        if (strategyId && /^[0-9]+$/.test(strategyId)) {
            postAction('update_content_strategy_items', {
                items: [{
                    id: Number(strategyId),
                    rejected: true
                }]
            }, $button);
            return;
        }
        postAction('reject_planned_content', { item_id: itemId }, $button);
    });

    $(document).on('change', '.aysa-agent8-calendar-native-filter', function() {
        const filterKey = String($(this).attr('data-filter-key') || '').trim();
        if (!Object.prototype.hasOwnProperty.call(currentPublishingCalendarFilters, filterKey)) {
            return;
        }
        currentPublishingCalendarFilters[filterKey] = String($(this).val() || '');
        currentPublishingCalendarVisibleLimit = 50;
        renderPublishingCalendarNative();
    });

    $(document).on('click', '.aysa-agent8-calendar-native-load-more', function() {
        currentPublishingCalendarVisibleLimit = Math.max(50, Number($(this).attr('data-next-limit') || 100));
        renderPublishingCalendarNative();
    });

    let calendarExplainerTimer = null;
    function hideCalendarExplainer() {
        $('.aysa-agent8-calendar-explainer').fadeOut(160, function() {
            $(this).remove();
        });
        if (calendarExplainerTimer) {
            window.clearTimeout(calendarExplainerTimer);
            calendarExplainerTimer = null;
        }
    }

    function showCalendarExplainer($trigger) {
        const kind = String($trigger.attr('data-info-kind') || '');
        const value = String($trigger.attr('data-info-value') || '');
        const explanation = calendarExplainerText(kind, value);
        if (!explanation) {
            return;
        }
        hideCalendarExplainer();
        const rect = $trigger[0].getBoundingClientRect();
        const title = value.replace(/_/g, ' ');
        const $bubble = $('<div class="aysa-agent8-calendar-explainer" role="status">' +
            '<div class="aysa-agent8-calendar-explainer-title"><span>' + escapeHtml(title) + '</span><button type="button" class="aysa-agent8-calendar-explainer-close" aria-label="Close">×</button></div>' +
            '<div>' + escapeHtml(explanation) + '</div>' +
        '</div>');
        $('body').append($bubble);
        const width = $bubble.outerWidth();
        const height = $bubble.outerHeight();
        const preferredLeft = rect.left + (rect.width / 2) - (width / 2);
        const left = Math.min(Math.max(12, preferredLeft), Math.max(12, window.innerWidth - width - 12));
        const preferredTop = rect.bottom + 8;
        const top = preferredTop + height > window.innerHeight - 12
            ? Math.max(12, rect.top - height - 8)
            : preferredTop;
        $bubble.css({ left: left + 'px', top: top + 'px' }).hide().fadeIn(120);
        calendarExplainerTimer = window.setTimeout(hideCalendarExplainer, 5200);
    }

    $(document).on('click mouseenter', '.aysa-agent8-calendar-info-trigger', function(event) {
        event.preventDefault();
        event.stopPropagation();
        showCalendarExplainer($(this));
    });

    $(document).on('click', '.aysa-agent8-calendar-explainer-close', function(event) {
        event.preventDefault();
        hideCalendarExplainer();
    });

	    $(document).on('click', '#aysa-agent8-calendar-native-continue', function() {
	        $(this).prop('disabled', true).text(conversationLanguage === 'ro' ? 'Se programează...' : 'Scheduling...');
	        const schedulePayload = currentPublishingCalendarScheduleContract && typeof currentPublishingCalendarScheduleContract === 'object'
	            ? Object.assign({}, currentPublishingCalendarScheduleContract)
	            : {};
	        postAction('schedule_publishing_plan', schedulePayload, $(this));
	    });

    $(document).on('input change', '.aysa-agent8-content-strategy-page-search, .aysa-agent8-content-strategy-manual', function() {
        const $row = $(this).closest('.aysa-agent8-content-strategy-item');
        if (!$row.length) {
            return;
        }
        if ($(this).hasClass('aysa-agent8-content-strategy-page-search')) {
            const candidate = resolveContentStrategyPageCandidate($(this).val());
            if (candidate) {
                $row.find('.aysa-agent8-content-strategy-manual').val('');
            }
        }
        syncContentStrategyAssociation($row);
    });

    $(document).on('click', '#aysa-agent8-content-strategy-save', function() {
        const items = collectContentStrategyModalItems();
        if (!items.length) {
            $('#aysa-agent8-content-strategy-modal-status').text('Nu există modificări salvabile în lista curentă.').removeAttr('hidden');
            return;
        }
        postAction('update_content_strategy_items', { items });
    });

    $(document).on('click', '.aysa-agent8-content-strategy-load-more', function() {
        const nextOffset = Math.max(0, Number($(this).attr('data-next-offset') || 0));
	        const limit = Math.max(1, Number($(this).attr('data-limit') || 24));
        postAction('show_planned_content', {
            offset: nextOffset,
            limit: limit
        });
    });

    $(document).on('click', '#aysa-agent8-help-modal-close, [data-help-modal-close="1"]', function() {
        closeHelpModal();
    });

    $(document).on('click', '.aysa-agent8-review-delete', function() {
        const actionKey = decodeMessage($(this).attr('data-action-key') || '');
        const itemId = String($(this).attr('data-item-id') || '');
        if (!actionKey || !itemId) {
            return;
        }
	        postAction(actionKey, Object.assign(currentReviewPaginationPayload(), { item_id: itemId }));
    });

    $(document).on('click', '.aysa-agent8-mapping-accept', function() {
        const itemId = String($(this).attr('data-item-id') || '');
        if (!itemId) {
            return;
        }
	        postAction('accept_keyword_mapping', Object.assign(currentReviewPaginationPayload(), { item_id: itemId }));
    });

	    $(document).on('click', '.aysa-agent8-mapping-alternative', function() {
	        const $button = $(this);
	        const itemId = String($button.attr('data-item-id') || '');
	        if (!itemId) {
	            return;
	        }
	        const $row = $button.closest('.aysa-agent8-keyword-mapping-row');
	        $row.toggleClass('is-changing-page');
	        if (!$row.hasClass('is-changing-page')) {
	            return;
	        }
	        if (String($button.attr('data-has-alternatives') || '') !== '1') {
	            postAction('request_mapping_alternative', Object.assign(currentReviewPaginationPayload(), { item_id: itemId }));
	        }
	    });

	    $(document).on('change input', '.aysa-agent8-mapping-alternative-select, .aysa-agent8-mapping-replacement-input', function() {
	        const $row = $(this).closest('.aysa-agent8-keyword-mapping-row');
	        const selected = String($row.find('.aysa-agent8-mapping-alternative-select').val() || '').trim();
	        const manual = String($row.find('.aysa-agent8-mapping-replacement-input').val() || '').trim();
	        $row.find('.aysa-agent8-mapping-apply').prop('disabled', !(selected || manual));
	    });

	    $(document).on('click', '.aysa-agent8-mapping-apply', function() {
	        const itemId = String($(this).attr('data-item-id') || '');
	        if (!itemId) {
	            return;
	        }
	        const $row = $(this).closest('.aysa-agent8-keyword-mapping-row');
	        const $select = $row.find('.aysa-agent8-mapping-alternative-select[data-item-id="' + itemId + '"]');
	        const $input = $row.find('.aysa-agent8-mapping-replacement-input[data-item-id="' + itemId + '"]');
	        const replacementUrl = String(($select.length ? $select.val() : '') || ($input.val() || '') || '').trim();
        if (!replacementUrl) {
            return;
        }
	        postAction('apply_mapping_replacement', Object.assign(currentReviewPaginationPayload(), { item_id: itemId, replacement_url: replacementUrl }));
    });

    $(document).on('click', '.aysa-agent8-inline-undo', function() {
        const actionKey = decodeMessage($(this).attr('data-action-key') || 'undo_recent_delete');
	        postAction(actionKey, currentReviewPaginationPayload());
    });


    $(document).on('click', '.aysa-agent8-help-keyword, .aysa-agent8-help-association', function() {
        const texts = keywordReviewTexts();
        const help = decodeMessage($(this).attr('data-help') || '');
        if (help) {
            openHelpModal(texts.title, help);
        }
    });

    $(document).on('click', '#aysa-agent8-keyword-intro-help', function() {
        const title = decodeMessage($(this).attr('data-help-title') || '');
        const body = decodeMessage($(this).attr('data-help-body') || '');
        openHelpModal(title, body);
    });

    let lastFactoryResetDryRunResult = null;

    function factoryResetDryRunValue(path, fallback) {
        let cursor = lastFactoryResetDryRunResult;
        path.forEach((key) => {
            if (cursor && Object.prototype.hasOwnProperty.call(cursor, key)) {
                cursor = cursor[key];
            } else {
                cursor = null;
            }
        });
        return cursor === null || typeof cursor === 'undefined' ? fallback : cursor;
    }

    function factoryResetDryRunWpUserLabel(target) {
        const adminBarName = ($('#wp-admin-bar-my-account .display-name').first().text() || '').trim();
        if (adminBarName) {
            return adminBarName;
        }
        return String((target && target.wp_user_id) || '');
    }

    function factoryResetDryRunCount(path) {
        return Number(factoryResetDryRunValue(path, 0) || 0);
    }

    function renderFactoryResetDryRunSummary(payload) {
        lastFactoryResetDryRunResult = payload || {};
        const target = factoryResetDryRunValue(['target'], {});
        const wp = factoryResetDryRunValue(['wordpress'], {});
        const api = factoryResetDryRunValue(['api'], {});
        const conversation = api && api.conversation ? api.conversation : {};
        const research = api && api.research ? api.research : {};
        const wpCustomRows = (wp.custom_tables || []).reduce((sum, row) => sum + Number(row.count || 0), 0);
        const ragCount = Number((conversation.project_knowledge_docs || {}).count || 0) + Number((conversation.project_rag_requests || {}).count || 0);
        const confirmationPhrase = String(factoryResetDryRunValue(['confirmation_phrase'], ''));
        const executeToken = String(factoryResetDryRunValue(['execute', 'token'], ''));
        const expiresMinutes = String(factoryResetDryRunValue(['execute', 'expires_in_minutes'], ''));
        const html = [
            '<div class="aysa-agent8-reset-preview">',
                '<section class="aysa-agent8-reset-warning">',
                    '<h2>' + escapeHtml('⚠️ This is a preview. Nothing has been deleted.') + '</h2>',
                    '<p>This shows what will be removed if you run a full reset of AYSA test data.</p>',
                '</section>',
                '<section class="aysa-agent8-reset-panel">',
                    '<h3>Current context</h3>',
                    '<div class="aysa-agent8-reset-context">',
                        '<div><span class="aysa-agent8-reset-label">Site</span><span class="aysa-agent8-reset-value">' + escapeHtml(String(target.site_host || '')) + '</span></div>',
                        '<div><span class="aysa-agent8-reset-label">Project</span><span class="aysa-agent8-reset-value">' + escapeHtml(String(target.project_id || '')) + '</span></div>',
                        '<div><span class="aysa-agent8-reset-label">Website</span><span class="aysa-agent8-reset-value">' + escapeHtml(String(target.website_id || '')) + '</span></div>',
                        '<div><span class="aysa-agent8-reset-label">WordPress user</span><span class="aysa-agent8-reset-value">' + escapeHtml(factoryResetDryRunWpUserLabel(target)) + '</span></div>',
                        '<div><span class="aysa-agent8-reset-label">AYSA user</span><span class="aysa-agent8-reset-value">' + escapeHtml(String(target.aysa_user_id || '')) + '</span></div>',
                    '</div>',
                '</section>',
                '<div class="aysa-agent8-reset-columns">',
                    '<section class="aysa-agent8-reset-panel">',
                        '<h3>This will be deleted</h3>',
                        '<ul class="aysa-agent8-reset-list">',
                            '<li>Agent8 chat sessions (' + escapeHtml(String((conversation.project_conversation_sessions || {}).count || 0)) + ')</li>',
                            '<li>Chat messages (' + escapeHtml(String((conversation.project_conversation_messages || {}).count || 0)) + ')</li>',
                            '<li>Setup &amp; configuration (' + escapeHtml(String(factoryResetDryRunCount(['wordpress', 'options', 'count']))) + ' items)</li>',
                            '<li>Local session state (' + escapeHtml(String(factoryResetDryRunCount(['wordpress', 'user_meta', 'count']))) + ' item)</li>',
                            '<li>Action history (' + escapeHtml(String((conversation.project_action_history || {}).count || 0)) + ' entries)</li>',
                            '<li>Research data:<ul><li>Runs: ' + escapeHtml(String((research.runs || {}).count || 0)) + '</li><li>Tasks: ' + escapeHtml(String((research.tasks || {}).count || 0)) + '</li><li>Events: ' + escapeHtml(String((research.events || {}).count || 0)) + '</li></ul></li>',
                            '<li>Generated knowledge (RAG): ' + escapeHtml(String(ragCount)) + '</li>',
                            '<li>Other AYSA runtime rows: ' + escapeHtml(String(wpCustomRows)) + '</li>',
                        '</ul>',
                    '</section>',
                    '<section class="aysa-agent8-reset-panel">',
                        '<h3>This will NOT be deleted</h3>',
                        '<ul class="aysa-agent8-reset-list">',
                            '<li>Website content (posts, pages, products)</li>',
                            '<li>Media (images, files)</li>',
                            '<li>Orders &amp; customers</li>',
                            '<li>Billing &amp; credits</li>',
                            '<li>SEO changes already applied</li>',
                            '<li>Redirects and server config</li>',
                            '<li>Other websites/projects</li>',
                        '</ul>',
                    '</section>',
                '</div>',
                '<section class="aysa-agent8-reset-panel">',
                    '<h3>Confirmation required later</h3>',
                    '<p>To proceed, you will need to type:</p>',
                    '<code class="aysa-agent8-reset-code">' + escapeHtml(confirmationPhrase) + '</code>',
                    '<p>This prevents accidental data loss.</p>',
                    executeToken ? '<div class="aysa-agent8-reset-confirm"><input type="text" id="aysa-agent8-factory-reset-confirmation" autocomplete="off" spellcheck="false" placeholder="Type the exact confirmation phrase"><div class="aysa-agent8-reset-actions"><button type="button" class="button button-primary" id="aysa-agent8-factory-reset-execute">Run Factory Test Reset</button><span class="aysa-agent8-reset-status" id="aysa-agent8-factory-reset-execute-status">Dry-run snapshot expires in ' + escapeHtml(expiresMinutes) + ' minutes.</span></div></div>' : '',
                '</section>',
                '<details class="aysa-agent8-reset-advanced">',
                    '<summary>Advanced details</summary>',
                    '<pre>' + escapeHtml(JSON.stringify(payload, null, 2)) + '</pre>',
                '</details>',
            '</div>'
        ].join('');
        $('#aysa-agent8-factory-reset-dry-run-summary').html(html).removeAttr('hidden');
    }

    $('#aysa-agent8-factory-reset-dry-run').on('click', function() {
        const $button = $(this);
        $button.prop('disabled', true);
        $('#aysa-agent8-factory-reset-dry-run-summary').text('Running Factory Reset dry-run...').removeAttr('hidden');
        $.post(ajaxUrl, {
            action: 'aysa_agent8_factory_reset_dry_run',
            nonce: nonce,
            project_id: projectId,
            site_host: siteHost
        }).done(function(response) {
            if (!response || !response.success) {
                $('#aysa-agent8-factory-reset-dry-run-summary').text(response && response.data && response.data.message ? response.data.message : 'Factory Reset dry-run failed.').removeAttr('hidden');
                return;
            }
            renderFactoryResetDryRunSummary(response.data || {});
        }).fail(function(xhr) {
            $('#aysa-agent8-factory-reset-dry-run-summary').text(xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message ? xhr.responseJSON.data.message : 'Factory Reset dry-run failed.').removeAttr('hidden');
        }).always(function() {
            $button.prop('disabled', false);
        });
    });

    $(document).on('click', '#aysa-agent8-factory-reset-execute', function() {
        const $button = $(this);
        const phrase = String($('#aysa-agent8-factory-reset-confirmation').val() || '').trim();
        const token = String(factoryResetDryRunValue(['execute', 'token'], ''));
        $('#aysa-agent8-factory-reset-execute-status').text('Validating reset request...');
        $button.prop('disabled', true);
        $.post(ajaxUrl, {
            action: 'aysa_agent8_factory_reset_execute',
            nonce: nonce,
            project_id: projectId,
            site_host: siteHost,
            token: token,
            confirmation_phrase: phrase
        }).done(function(response) {
            if (!response || !response.success) {
                $('#aysa-agent8-factory-reset-execute-status').text(response && response.data && response.data.message ? response.data.message : 'Factory Reset execute failed.');
                $button.prop('disabled', false);
                return;
            }
            $('#aysa-agent8-factory-reset-execute-status').text('Factory Test Reset completed. Reloading clean state...');
            window.setTimeout(function() {
                window.location.reload();
            }, 900);
        }).fail(function(xhr) {
            $('#aysa-agent8-factory-reset-execute-status').text(xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message ? xhr.responseJSON.data.message : 'Factory Reset execute failed.');
            $button.prop('disabled', false);
        });
    });

    $('#aysa-agent8-reset').on('click', function() {
        nextConversationRequestEpoch();
        stopConversationPolling();
        conversationId = '';
        transcript = [];
        pendingApproval = null;
        currentProjection = null;
        currentSuggestions = [];
        persistentActions = [];
        currentContractIssue = null;
        currentUiCommand = null;
        currentAsyncJob = null;
        currentConversationRunId = '';
        resetVisibleConversationStatus();
        applyUiLanguage();
        renderTranscript();
        $('#aysa-agent8-send, #aysa-agent8-reset, #aysa-agent8-google-disconnect').prop('disabled', true);
        $('#aysa-agent8-pending').attr('data-mode', 'thinking').removeAttr('hidden');
        $.post(ajaxUrl, {
            action: 'aysa_apprentice_reset_test',
            nonce: nonce,
            project_id: projectId,
            site_host: siteHost
        }).done(function(response) {
            if (!response || !response.success) {
                alert(response && response.data && response.data.message ? response.data.message : 'Agent 8 reset failed.');
                $('#aysa-agent8-send, #aysa-agent8-reset, #aysa-agent8-google-disconnect').prop('disabled', false);
                $('#aysa-agent8-pending').attr('hidden', 'hidden');
                return;
            }
            window.location.reload();
        }).fail(function(xhr) {
            alert(xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message ? xhr.responseJSON.data.message : 'Agent 8 reset failed.');
            $('#aysa-agent8-send, #aysa-agent8-reset, #aysa-agent8-google-disconnect').prop('disabled', false);
            $('#aysa-agent8-pending').attr('hidden', 'hidden');
        });
    });

    $('#aysa-agent8-language').on('change', function() {
        conversationLanguage = normalizeLanguageCode($(this).val());
        applyUiLanguage();
    });

    $('#aysa-agent8-google-disconnect').on('click', function() {
        disconnectGoogle();
    });

    applyUiLanguage();
    resetVisibleConversationStatus();
    $('#aysa-agent8-send').prop('disabled', true);
    $('#aysa-agent8-pending').attr('data-mode', 'thinking');
    $('#aysa-agent8-pending').removeAttr('hidden');

    $(document).on('click', '.aysa-agent8-bundle-action', function() {
        const $sourceButton = $(this);
        if ($sourceButton.is(':disabled') || isAgent8ForegroundPending()) {
            return;
        }
        const actionKey = String($sourceButton.attr('data-action-key') || '').trim();
        if (!actionKey) {
            return;
        }
        let actionPayload = {};
        try {
            actionPayload = JSON.parse(window.decodeURIComponent(String($sourceButton.attr('data-action-payload') || '')));
        } catch (e) {
            actionPayload = {};
        }
        postAction(actionKey, actionPayload, $sourceButton);
    });

    autoresizeComposer();
    reflectAgent8CommunicationsInChat();
    const bootstrapEpoch = conversationRequestEpoch;
    if (oauthStatusRefreshPending) {
        oauthStatusRefreshPending = false;
        postConversation('message', 'verifica statusul google');
    } else {
        postConversation('bootstrap', '');
    }
});
</script>
