/* global formeSEOAgent, jQuery, Chart */
( function ( $ ) {
	'use strict';

	var cfg    = formeSEOAgent;
	var ajax   = cfg.ajaxUrl;
	var nonce  = cfg.nonce;
	var hasKey = cfg.hasKey;
	var page   = cfg.currentPage || '';

	// Current result raw data (for copy button)
	var _lastRaw   = null;
	var _lastTool  = null;
	// Current content project id
	var _contentProjectId = null;
	// Audit job history state
	var _auditJobsOffset = 0;
	var _auditJobsLimit  = 20;
	var _activeJobPoller = null;
	// Reports cache — shared across all widgets on current page load
	var _reportCache = null;

	// ── Utilities ─────────────────────────────────────────────────────────────

	function post( action, data ) {
		return $.post( ajax, $.extend( { action: action, nonce: nonce }, data ) );
	}

	function spinner( msg ) {
		$( '#csa-spinner-msg' ).text( msg || 'Please wait…' );
		$( '#csa-spinner-overlay' ).show();
	}

	function hideSpinner() {
		$( '#csa-spinner-overlay' ).hide();
	}

	function toast( msg, type ) {
		var $c = $( '#csa-toasts' );
		if ( ! $c.length ) {
			$c = $( '<div id="csa-toasts"></div>' ).appendTo( 'body' );
		}
		var icons = { success: '✓', error: '✕', warning: '⚠', info: 'ℹ' };
		var icon  = icons[ type ] || icons.info;
		var $t    = $(
			'<div class="csa-toast csa-toast--' + ( type || 'info' ) + '">' +
			'<span class="csa-toast-icon">' + icon + '</span>' +
			'<span>' + escHtml( msg ) + '</span>' +
			'</div>'
		).appendTo( $c );

		setTimeout( function () {
			$t.css( 'animation', 'csa-toast-out .2s ease forwards' );
			setTimeout( function () { $t.remove(); }, 220 );
		}, 3600 );
	}

	function friendlyError( code, msg ) {
		if ( code === 401 ) return 'Authentication failed — please check your API key in Settings.';
		if ( code === 429 ) return 'Rate limit reached — please wait a moment before trying again.';
		if ( code >= 500 )  return 'Server error — the Claude SEO backend is temporarily unavailable.';
		return msg || 'An unexpected error occurred.';
	}

	function escHtml( str ) {
		return String( str )
			.replace( /&/g, '&amp;' )
			.replace( /</g, '&lt;' )
			.replace( />/g, '&gt;' )
			.replace( /"/g, '&quot;' );
	}

	function cleanAiFooter( raw ) {

		if ( ! raw ) {
			return '';
		}

		raw = raw.replace(
			/━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[\s\S]*$/m,
			''
		);

		raw = raw.replace(
			/Built by agricidaniel[\s\S]*$/mi,
			''
		);

		return raw.trim();
	}

	function inlineMarkdown( text ) {
		return text
			.replace( /\*\*(.*?)\*\*/g, '<strong>$1</strong>' )
			.replace( /\*(.*?)\*/g, '<em>$1</em>' )
			.replace( /`([^`]+)`/g, '<code>$1</code>' );
	}

	function markdownToHtml( markdown ) {
		var src = String( markdown || '' );

		// Remove assistant preamble / chatter
		src = src.replace( /^I have all the data needed[\s\S]*?---\s*/i, '' );
		src = src.replace( /^I have (?:sufficient|enough) data[\s\S]*?(?:report\.|report now\.|full report\.)\s*/im, '' );

		// ── STEP 1: Extract fenced code blocks FIRST so later cleanup never touches their content
		var codeBlocks = [];
		src = src.replace( /```([a-zA-Z0-9_-]*)\n?([\s\S]*?)```/g, function ( match, lang, code ) {
			var key = '%%CODEBLOCK_' + codeBlocks.length + '%%';
			codeBlocks.push( '<pre><code>' + escHtml( code.trim() ) + '</code></pre>' );
			return key;
		} );

		// ── STEP 2: Extract pipe tables BEFORE escaping so we can build real <table> HTML
		var tables = [];
		var lines  = src.split( '\n' );
		var out    = [];
		var tBuf   = [];

		function flushTable() {
			if ( tBuf.length < 2 ) { out = out.concat( tBuf ); tBuf = []; return; }
			var isSep = /^\|\s*[-:]+[-|\s:]*\|/.test( tBuf[1] );
			var headerRow = tBuf[0];
			var dataRows  = isSep ? tBuf.slice( 2 ) : tBuf.slice( 1 );

			function parseCols( row ) {
				return row.replace( /^\||\|$/g, '' ).split( '|' ).map( function ( c ) { return c.trim(); } );
			}

			var tHtml = '<table><thead><tr>';
			parseCols( headerRow ).forEach( function ( c ) { tHtml += '<th>' + escHtml( c ) + '</th>'; } );
			tHtml += '</tr></thead><tbody>';
			dataRows.forEach( function ( row ) {
				if ( /^\|\s*[-:]+[-|\s:]*\|/.test( row ) ) return; // skip extra separator rows
				tHtml += '<tr>';
				parseCols( row ).forEach( function ( c ) { tHtml += '<td>' + escHtml( c ) + '</td>'; } );
				tHtml += '</tr>';
			} );
			tHtml += '</tbody></table>';

			var key = '%%TABLE_' + tables.length + '%%';
			tables.push( tHtml );
			out.push( key );
			tBuf = [];
		}

		lines.forEach( function ( line ) {
			if ( /^\s*\|/.test( line ) ) {
				tBuf.push( line );
			} else {
				flushTable();
				out.push( line );
			}
		} );
		flushTable();
		src = out.join( '\n' );

		// ── STEP 3: Remove horizontal rules and box-drawing lines (now safe — no raw code fences remain)
		src = src.replace( /^---+$/gm, '' );
		src = src.replace( /^.*[┌┐└┘│─╔╗╚╝║═╠╣╦╩╬]+.*$/gm, '' );

		// ── STEP 4: Escape remaining text and apply block/inline markdown
		var html = escHtml( src );

		// Headings
		html = html
			.replace( /^# (.*)$/gm, '<h1>$1</h1>' )
			.replace( /^## (.*)$/gm, '<h2>$1</h2>' )
			.replace( /^### (.*)$/gm, function ( match, text ) {
				var cls = '';
				if      ( /^C\d+\s*[—–\-]/.test( text ) ) cls = ' csa-issue-h--critical';
				else if ( /^H\d+\s*[—–\-]/.test( text ) ) cls = ' csa-issue-h--high';
				else if ( /^M\d+\s*[—–\-]/.test( text ) ) cls = ' csa-issue-h--medium';
				else if ( /^Q\d*\s*[—–\-]?/.test( text ) && /quick.win/i.test( text ) ) cls = ' csa-issue-h--win';
				return '<h3 class="' + cls.trim() + '">' + text + '</h3>';
			} )
			.replace( /^#### (.*)$/gm, '<h4>$1</h4>' );

		// Inline formatting
		html = html
			.replace( /\*\*(.*?)\*\*/g, '<strong>$1</strong>' )
			.replace( /\*(.*?)\*/g, '<em>$1</em>' )
			.replace( /`([^`]+)`/g, '<code>$1</code>' );

		// Unordered lists
		html = html.replace( /(?:^|\n)[*\-] (.*)(?=\n|$)/g, '\n<li>$1</li>' );

		// Ordered lists
		html = html.replace( /(?:^|\n)\d+\. (.*)(?=\n|$)/g, '\n<li class="csa-ol-li">$1</li>' );

		// Wrap consecutive <li> into <ul>
		html = html.replace( /(<li[\s\S]*?<\/li>)/g, '<ul>$1</ul>' );
		html = html.replace( /<\/ul>\s*<ul>/g, '' );

		// Paragraphs — skip block-level elements and placeholders
		var parts = html
			.split( /\n{2,}/ )
			.map( function ( part ) {
				part = part.trim();
				if ( ! part ) return '';
				if (
					part.indexOf( '<h1' )       === 0 ||
					part.indexOf( '<h2' )       === 0 ||
					part.indexOf( '<h3' )       === 0 ||
					part.indexOf( '<h4' )       === 0 ||
					part.indexOf( '<ul' )       === 0 ||
					part.indexOf( '%%CODEBLOCK_' ) === 0 ||
					part.indexOf( '%%TABLE_' )  === 0
				) {
					return part;
				}
				return '<p>' + part.replace( /\n/g, '<br>' ) + '</p>';
			} )
			.join( '' );

		// ── STEP 6: Restore code blocks and tables
		codeBlocks.forEach( function ( block, i ) {
			parts = parts.replace( '%%CODEBLOCK_' + i + '%%', block );
		} );
		tables.forEach( function ( tHtml, i ) {
			parts = parts.replace( '%%TABLE_' + i + '%%', tHtml );
		} );

		// ── STEP 7: Clean up any empty block elements produced by stripped sections
		parts = parts.replace( /<h[1-6][^>]*>\s*<\/h[1-6]>/g, '' );
		parts = parts.replace( /<pre[^>]*>\s*<\/pre>/g, '' );
		parts = parts.replace( /<p[^>]*>(\s|&nbsp;|<br\s*\/?>)*<\/p>/g, '' );

		return '<div class="csa-report-markdown">' + parts + '</div>';
	}

	function prettyJSON( obj ) {
		try { return JSON.stringify( obj, null, 2 ); }
		catch ( e ) { return String( obj ); }
	}

	function cap( str ) {
		return str ? str.charAt(0).toUpperCase() + str.slice(1) : '';
	}

	function scoreColor( score ) {
		if ( score >= 80 ) return '#16a34a';
		if ( score >= 60 ) return '#d97706';
		return '#dc2626';
	}

	function debounce( fn, delay ) {
		var timer;
		return function () {
			var ctx  = this, args = arguments;
			clearTimeout( timer );
			timer = setTimeout( function () { fn.apply( ctx, args ); }, delay );
		};
	}

	function priorityClass( priority ) {
		var map = { high: 'high', medium: 'medium', low: 'low' };
		return map[ priority ] || 'low';
	}

	function severityClass( severity ) {
		var map = { high: 'high', medium: 'medium', low: 'low', info: 'low' };
		return map[ severity ] || 'medium';
	}

	// ── Reports cache helpers ─────────────────────────────────────────────────

	function getReports( cb ) {
		if ( _reportCache ) { cb( _reportCache ); return; }
		post( 'forme_seo_get_reports', { limit: 50, offset: 0 } )
			.done( function ( res ) {
				_reportCache = res.success ? ( res.data.reports || [] ) : [];
				cb( _reportCache );
			} )
			.fail( function () { cb( [] ); } );
	}

	function getLatestReport( tool, cb ) {
		getReports( function ( reports ) {
			cb( reports.find( function ( r ) {
				return r.tool === tool && r.status === 'completed';
			} ) || null );
		} );
	}

	function openReportDrawer( reportId, tool ) {
		$( '#csa-report-detail-title' ).text( cap( tool ) + ' Report' );
		$( '#csa-report-drawer-overlay' ).show();
		$( '#csa-report-detail-card' ).show();
		$( '#csa-report-detail-content' ).html(
			'<div class="csa-result-loading"><div class="csa-spinner-sm"></div><span>Loading report…</span></div>'
		);
		post( 'forme_seo_get_report', { report_id: reportId } )
			.done( function ( res ) {
				if ( res.success ) {
					var tempHtml = $( '<div>' );
					renderReportInto( tool, res.data, tempHtml );
					$( '#csa-report-detail-content' ).html( tempHtml.html() );
				} else {
					$( '#csa-report-detail-content' ).html( '<p class="csa-error-msg">Could not load report.</p>' );
				}
			} )
			.fail( function () {
				$( '#csa-report-detail-content' ).html( '<p class="csa-error-msg">Network error.</p>' );
			} );
	}

	function extractSectionLines( raw, headingPatterns ) {

		var lines = String( raw || '' ).split( '\n' );

		var out = [];
		var inSection = false;

		lines.forEach( function ( line ) {

			var t = line.trim();

			// Find section start
			if ( ! inSection ) {

				var matched = headingPatterns.some( function ( rx ) {
					return rx.test( t );
				} );

				if ( matched ) {
					inSection = true;
				}

				return;
			}

			// Stop ONLY at next MAJOR numbered section
			if (
				/^\d+\.\s+[A-Z]/.test( t ) &&
				! headingPatterns.some( function ( rx ) {
					return rx.test( t );
				} )
			) {
				return false;
			}

			out.push( t );

		} );

		return out;
	}

	function cleanListItem( text ) {
		return String( text || '' )
			.replace( /^\|\s*/, '' )
			.replace( /\s*\|$/, '' )
			.replace( /^[-*]\s+/, '' )
			.replace( /^\d+\.\s+/, '' )
			.replace( /^#+\s*/, '' )
			.trim();
	}

	function parseAuditActionPlan( raw ) {

		var match = raw.match(
			/(?:\d+\.\s+)?Prioritized Action Plan([\s\S]*?)(?:\d+\.\s+)?(?:Strengths to Preserve|4-Phase Roadmap|$)/i
		);

		if ( ! match ) {
			return [];
		}

		var section = match[1];

		var out = [];

		section.split( '\n' ).forEach( function ( line ) {

			line = line.trim();

			if (
				! /^\|/.test( line ) ||
				line.indexOf( '---' ) > -1
			) {
				return;
			}

			var cols = line.split( '|' )
				.map( function ( c ) {
					return c.trim();
				} )
				.filter( Boolean );

			if (
				cols.length >= 4 &&
				!/^(#|Action|Priority|Owner|Timeline|Timeframe)$/i.test( cols[0] ) &&
				!/^Action$/i.test( cols[1] )
			) {
				out.push( cols[1] );
			}

		} );

		return out.slice( 0, 5 );
	}

	function parseQuickWins( raw ) {
		raw = String( raw || '' );

		var match = raw.match(
			/(?:^|\n)(?:#+\s*)?(?:\d+\.\s*)?Quick Wins(?: Table)?\s*\n([\s\S]*?)(?=\n(?:#+\s*)?(?:\d+\.\s*)?Prioritized Action Plan|\n(?:#+\s*)?(?:\d+\.\s*)?Action Plan|$)/i
		);

		if ( ! match ) {
			return [];
		}

		var out = [];

		match[1].split( '\n' ).forEach( function ( line ) {
			var t = line.trim();

			if ( ! /^\|/.test( t ) || t.indexOf( '---' ) > -1 ) {
				return;
			}

			var cols = t.split( '|' )
				.map( function ( c ) { return c.trim(); } )
				.filter( Boolean );

			// Table has columns: # | Action | Effort | Impact
			// Skip header row (first col is '#' or non-numeric text)
			if (
				cols.length >= 4 &&
				/^\d+$/.test( cols[0] ) &&
				cols[1]
			) {
				out.push( cols[1] );
			}
		} );

		return out.slice( 0, 5 );
	}

	function getReportScore( r ) {
		var raw = getReportRaw ? getReportRaw( r ) : '';

		var score =
			r.score ||
			( r.result && r.result.score ) ||
			0;

		if ( score > 0 ) {
			return parseInt( score, 10 );
		}

		var match =
			raw.match( /SEO Health Score:\s*(\d+)\s*\/\s*100/i ) ||
			raw.match( /Overall Score:\s*(\d+)\s*\/\s*100/i ) ||
			raw.match( /TOTAL[\s\S]{0,80}?(\d+)\s*\/\s*100/i ) ||
			raw.match( /TOTAL\s*\|[^|]*\|[^|]*\|\s*[\d.]+\s*→\s*(\d+)\s*\|/i ) ||
			raw.match( /SEO HEALTH SCORE[^0-9]*(\d+)\s*\/\s*100/i );

		return match ? parseInt( match[1], 10 ) : 0;
	}

	// ── Header badge ──────────────────────────────────────────────────────────

	function setHeaderBadge( state ) {
		var labels = { connected: 'Connected', disconnected: 'Not Connected', checking: 'Checking…' };
		$( '#csa-header-badge' )
			.attr( 'class', 'csa-header-badge csa-header-badge--' + state )
			.find( '.csa-header-badge-label' )
			.text( labels[ state ] || state );
	}

	// ── Account rendering ─────────────────────────────────────────────────────

	function renderAccount( me, usage ) {
		if ( me ) {
			var plan = ( me.plan || 'free' ).toLowerCase();

			setHeaderBadge( 'connected' );

			$( '#csa-status-dot' ).attr( 'class', 'csa-dot csa-dot--ok' ).attr( 'title', 'Connected' );
			$( '#csa-status-msg' ).text( 'Connected' );
			$( '#csa-acc-email' ).text( me.email || '—' );
			$( '#csa-account-rows' ).show();

			var planLabel = plan.charAt(0).toUpperCase() + plan.slice(1);
			var status = me.subscription_status || ( plan === 'free' ? 'Free' : 'Active' );
			var statusLabel = cap( status.replace( /_/g, ' ' ) );

			$( '#csa-plan-badge' ).text( planLabel ).attr( 'class', 'csa-badge csa-badge--' + plan );
			$( '#csa-plan-name' ).text( me.plan_display || planLabel );
			var status = me.subscription_status || ( plan === 'free' ? 'free' : 'active' );
				var isCanceling = status === 'canceling';

				$( '#csa-plan-status' )
					.text( isCanceling ? 'Canceling' : cap( status.replace( /_/g, ' ' ) ) )
					.attr( 'class', 'csa-kv__v csa-plan-status-pill csa-plan-status--' + status );

				$( '#csa-plan-renews' )
					.text( me.renews_at ? new Date( me.renews_at ).toLocaleDateString() : '—' );

				$( '#csa-plan-renews' )
					.closest( '.csa-kv' )
					.find( '.csa-kv__k' )
					.text( isCanceling ? 'Access until' : 'Renews' );

			$( '.csa-plan' ).removeClass( 'is-current' );
			$( '.csa-plan[data-plan="' + plan + '"]' ).addClass( 'is-current' );
			$( '.csa-current-badge' ).hide();
			$( '#csa-' + plan + '-badge' ).show();

			$( '.csa-upgrade-btn' ).show();
			$( '.csa-plan[data-plan="' + plan + '"] .csa-upgrade-btn' ).hide();
		}

		if ( usage ) {
			var period = usage.period || usage.month || '';
			$( '#csa-usage-period' ).text( period );

			function applyBar( category, barId, labelId ) {
				var cat   = usage[ category ] || {};
				var used  = cat.used  != null ? cat.used  : ( cat.count != null ? cat.count : 0 );
				var limit = cat.limit != null ? cat.limit : ( cat.max   != null ? cat.max   : 0 );
				var pct   = limit > 0 ? Math.min( 100, Math.round( used / limit * 100 ) ) : ( used > 0 ? 100 : 0 );
				var txt   = limit > 0 ? ( used + ' / ' + limit ) : ( used > 0 ? used + ' used' : '0 used' );
				$( '#' + labelId ).text( txt );
				$( '#' + barId ).css( 'width', pct + '%' );
			}

			applyBar( 'seo',     'csa-bar-seo',     'csa-usage-seo-label' );
			applyBar( 'content', 'csa-bar-content', 'csa-usage-content-label' );
			applyBar( 'blog',    'csa-bar-blog',    'csa-usage-blog-label' );
		}
	}

	function statusError( msg ) {
		setHeaderBadge( 'disconnected' );
		$( '#csa-status-dot' ).attr( 'class', 'csa-dot csa-dot--err' ).attr( 'title', msg );
		$( '#csa-status-msg' ).text( msg );
	}

	// ── Auto-load on dashboard ────────────────────────────────────────────────

	function refreshAccount() {
		post( 'forme_seo_refresh' )
			.done( function ( res ) {
				if ( res.success ) {
					renderAccount( res.data.me, res.data.usage );
				} else {
					statusError( friendlyError( res.data && res.data.code, res.data && res.data.message ) );
				}
			} )
			.fail( function () { statusError( 'Could not reach server.' ); } );
	}

	if ( hasKey && page === 'claude-seo-agent' && $( '#csa-card-status' ).length ) {
		refreshAccount();
		loadSeoHealthFromAudit();
		//loadTasksSidebar();
		//loadQuickWins();
		loadReportsHistory( 5 );

		// ── GSC ─────────────────────────────

		if ( $( '#csa-gsc-property-select' ).length ) {
			loadGscProperties();
		}

		if (
			formeSEOAgent.gscConnected &&
			formeSEOAgent.gscProperty &&
			typeof loadGscOverview === 'function'
		) {
			loadGscOverview();
		}
	}
	if ( hasKey && page === 'claude-seo-agent-website-audit' ) {
		initWebsiteAudit();
	}
	if ( hasKey && page === 'claude-seo-agent-content-plan' ) {
		initContentPlan();
	}
	if ( hasKey && page === 'claude-seo-agent-articles' ) {
		loadArticlesPage();
	}
	if ( hasKey && page === 'claude-seo-agent-reports' ) {
		loadReportsPage();
	}

	// ── Refresh button ────────────────────────────────────────────────────────

	$( '#csa-refresh-btn' ).on( 'click', function () {
		var $btn = $( this ).prop( 'disabled', true );
		spinner( 'Refreshing account…' );
		post( 'forme_seo_refresh' )
			.done( function ( res ) {
				hideSpinner();
				if ( res.success ) {
					renderAccount( res.data.me, res.data.usage );
					toast( 'Account refreshed.', 'success' );
				} else {
					toast( friendlyError( res.data && res.data.code, res.data && res.data.message ), 'error' );
				}
			} )
			.fail( function () { hideSpinner(); toast( 'Network error.', 'error' ); } )
			.always( function () { $btn.prop( 'disabled', false ); } );
	} );

	// ── Register / create key ─────────────────────────────────────────────────

	$( '#csa-create-key-btn' ).on( 'click', function () {
		var email = $( '#csa-reg-email' ).val().trim();
		if ( ! email ) { toast( 'Please enter your email address.', 'error' ); return; }

		var $btn = $( this ).prop( 'disabled', true );
		spinner( 'Creating your free API key…' );

		post( 'forme_seo_register', { email: email } )
			.done( function ( res ) {
				hideSpinner();
				if ( res.success ) {
					toast( 'API key created! Loading your dashboard…', 'success' );
					setTimeout( function () { location.reload(); }, 1100 );
				} else {
					toast( friendlyError( res.data && res.data.code, res.data && res.data.message ), 'error' );
					$btn.prop( 'disabled', false );
				}
			} )
			.fail( function () {
				hideSpinner();
				toast( 'Network error — please try again.', 'error' );
				$btn.prop( 'disabled', false );
			} );
	} );

	// ── Test connection ───────────────────────────────────────────────────────

	$( '#csa-test-btn' ).on( 'click', function () {
		spinner( 'Testing connection…' );
		post( 'forme_seo_test_connection' )
			.done( function ( res ) {
				hideSpinner();
				if ( res.success ) {
					toast( res.data.message || 'Connection successful!', 'success' );
					renderAccount( res.data.me, null );
				} else {
					toast( friendlyError( res.data && res.data.code, res.data && res.data.message ), 'error' );
					statusError( 'Connection failed' );
				}
			} )
			.fail( function () { hideSpinner(); toast( 'Network error.', 'error' ); } );
	} );

	// ── Upgrade buttons ───────────────────────────────────────────────────────

	$( document ).on( 'click', '.csa-upgrade-btn', function () {
		var plan = $( this ).data( 'plan' );
		spinner( 'Redirecting to Stripe checkout…' );
		post( 'forme_seo_checkout', { plan: plan } )
			.done( function ( res ) {
				hideSpinner();
				if ( res.success && res.data.checkout_url ) {
					window.location.href = res.data.checkout_url;
				} else {
					toast( friendlyError( res.data && res.data.code, res.data && res.data.message ), 'error' );
				}
			} )
			.fail( function () { hideSpinner(); toast( 'Network error — could not start checkout.', 'error' ); } );
	} );

	$( document ).on( 'click', '#csa-generate-plan-btn', function () {
			window.location.href = formeSEOAgent.websiteAuditUrl;
		} );

	$( '#csa-portal-btn' ).on( 'click', function () {
		spinner( 'Opening billing portal…' );
		post( 'forme_seo_portal' )
			.done( function ( res ) {
				hideSpinner();
				if ( res.success && res.data.portal_url ) {
					window.location.href = res.data.portal_url;
				} else {
					toast( friendlyError( res.data && res.data.code, res.data && res.data.message ), 'error' );
				}
			} )
			.fail( function () { hideSpinner(); toast( 'Network error — could not open portal.', 'error' ); } );
	} );

	// ── Report panel: copy / close ────────────────────────────────────────────

	$( '#csa-copy-btn' ).on( 'click', function () {
		var text = $( '#csa-result-viewer' ).text();
		if ( ! text ) return;
		if ( navigator.clipboard ) {
			navigator.clipboard.writeText( text ).then( function () {
				toast( 'JSON copied to clipboard.', 'success' );
			} );
		} else {
			var $ta = $( '<textarea>' ).val( text ).css( { position: 'fixed', opacity: 0 } ).appendTo( 'body' );
			$ta[0].select();
			try { document.execCommand( 'copy' ); toast( 'JSON copied to clipboard.', 'success' ); }
			catch ( e ) { toast( 'Copy failed — please copy manually.', 'warning' ); }
			$ta.remove();
		}
	} );

	$( '#csa-result-close' ).on( 'click', function () {
		$( '#csa-report-panel' ).hide();
		$( '#csa-report-content' ).hide().empty();
		$( '#csa-result-viewer' ).text( '' );
		$( '#csa-result-loading' ).hide();
	} );

	

	// ── Structured report rendering ───────────────────────────────────────────

	function showReportPanel( label, cached ) {
		$( '#csa-report-title' ).text( label + ' — Results' );
		$( '#csa-cached-badge' ).toggle( !! cached );
		$( '#csa-report-panel' ).show();
		$( 'html, body' ).animate(
			{ scrollTop: $( '#csa-report-panel' ).offset().top - 80 }, 280
		);
	}

	function showReportLoading( msg ) {
		$( '#csa-result-loading-msg' ).text( msg || 'Running analysis…' );
		$( '#csa-result-loading' ).show();
		$( '#csa-report-content' ).hide().empty();
	}

	function hideReportLoading() {
		$( '#csa-result-loading' ).hide();
	}

	function renderReport( tool, data ) {
		hideReportLoading();

		// Store raw for copy button
		_lastRaw  = data;
		_lastTool = tool;
		$( '#csa-result-viewer' ).text( prettyJSON( data ) );

		// Show cached badge
		$( '#csa-cached-badge' ).toggle( !! data.cached );

		if ( tool === 'content-pillars' ) {
			renderContentProject( data );
			$( '#csa-report-content' ).show();
			return;
		}

		var score   = data.score || 0;
		var summary = data.summary || '';
		var issues  = data.issues || [];
		var recs    = data.recommendations || [];
		var wins    = data.quick_wins || [];
		var tasks   = data.tasks || [];

		// Build HTML
		var html = '<div class="csa-report-grid">';

		// Left: score + summary
		html += '<div class="csa-report-left">';
		if ( score > 0 ) {
			html += '<div class="csa-score-circle" style="--score-color:' + scoreColor( score ) + '; --score:' + score + ';">' +
				'<div class="csa-score-num">' + score + '</div>' +
				'<div class="csa-score-lbl">/ 100</div>' +
				'</div>';
		}
		if ( summary ) {
			html += '<p class="csa-report-summary">' + escHtml( summary ) + '</p>';
		}
		// Metadata pills
		var meta = data.metadata || {};
		if ( meta.meta_title ) {
			html += '<div class="csa-meta-row"><span class="csa-meta-key">Title</span><span class="csa-meta-val">' + escHtml( meta.meta_title ) + '</span></div>';
		}
		if ( meta.meta_description ) {
			html += '<div class="csa-meta-row"><span class="csa-meta-key">Meta desc</span><span class="csa-meta-val">' + escHtml( meta.meta_description ) + '</span></div>';
		}
		html += '</div>'; // .csa-report-left

		// Right: issues, recs, quick wins
		html += '<div class="csa-report-right">';

		if ( issues.length ) {
			html += '<div class="csa-report-section">' +
				'<div class="csa-report-section-title"><i class="lni lni-warning"></i> Issues (' + issues.length + ')</div>' +
				'<ul class="csa-issues-list">';
			issues.forEach( function ( iss ) {
				var sev = severityClass( iss.severity );
				html += '<li class="csa-issue-item">' +
					'<span class="csa-sev-dot csa-sev-dot--' + sev + '"></span>' +
					'<span class="csa-issue-text">' + escHtml( iss.description ) + '</span>' +
					'<span class="csa-pill csa-pill--' + sev + '">' + escHtml( cap( iss.severity ) ) + '</span>' +
					'</li>';
			} );
			html += '</ul></div>';
		}

		if ( recs.length ) {
			html += '<div class="csa-report-section">' +
				'<div class="csa-report-section-title"><i class="lni lni-checkmark-circle"></i> Recommendations</div>' +
				'<ul class="csa-recs-list">';
			recs.slice( 0, 8 ).forEach( function ( r ) {
				html += '<li>' + escHtml( r ) + '</li>';
			} );
			html += '</ul></div>';
		}

		if ( wins.length ) {
			html += '<div class="csa-report-section">' +
				'<div class="csa-report-section-title"><i class="lni lni-bolt"></i> Quick Wins</div>' +
				'<ul class="csa-wins-list">';
			wins.forEach( function ( w ) {
				html += '<li><i class="lni lni-arrow-right"></i> ' + escHtml( w ) + '</li>';
			} );
			html += '</ul></div>';
		}

		html += '</div>'; // .csa-report-right
		html += '</div>'; // .csa-report-grid

		// Tasks section
		if ( tasks.length ) {
			html += '<div class="csa-report-tasks">' +
				'<div class="csa-report-section-title"><i class="lni lni-list"></i> Extracted Tasks (' + tasks.length + ')</div>' +
				'<div class="csa-task-rows">';
			tasks.forEach( function ( task ) {
				var pri = priorityClass( task.priority );
				html += '<div class="csa-task-row" data-task-id="' + task.id + '">' +
					'<span class="csa-task-dot csa-task-dot--' + pri + '"></span>' +
					'<div class="csa-task-row-body">' +
					'<span class="csa-task-row-title">' + escHtml( task.title ) + '</span>' +
					'<div class="csa-task-row-meta">' +
					'<span class="csa-pill csa-pill--' + pri + '">' + escHtml( cap( task.priority ) ) + '</span>' +
					'<span class="csa-pill csa-pill--cat">' + escHtml( cap( task.category ) ) + '</span>' +
					'<span class="csa-pill csa-pill--action">' + escHtml( task.action_type || 'fix' ) + '</span>' +
					'</div></div>' +
					'<button class="csa-btn csa-btn--ghost csa-btn--xs csa-task-done-btn" ' +
					'data-task-id="' + task.id + '" title="Mark done">✓</button>' +
					'</div>';
			} );
			html += '</div></div>';
		}

		$( '#csa-report-content' ).html( html ).show();

		// Refresh sidebar after new report
		setTimeout( function () {
			loadTasksSidebar();
			loadQuickWins();
			loadReportsHistory();
		}, 1200 );
	}

	// ── Content Pillars workflow rendering ────────────────────────────────────

	function renderContentProject( data ) {
		var meta    = data.metadata || {};
		var primary = meta.primary_topics || [];
		var gaps    = meta.content_gaps || [];
		var summary = data.summary || '';

		var infoHtml = '<p class="csa-report-summary">' + escHtml( summary ) + '</p>';
		if ( primary.length ) {
			infoHtml += '<div class="csa-topic-pills">';
			primary.slice( 0, 6 ).forEach( function ( t ) {
				infoHtml += '<span class="csa-pill csa-pill--topic">' + escHtml( t ) + '</span>';
			} );
			infoHtml += '</div>';
		}
		infoHtml += '<p class="csa-content-loading-msg">Loading content project…</p>';

		$( '#csa-content-project-info' ).html( infoHtml );
		$( '#csa-topic-grid' ).html( '<div class="csa-spinner-sm"></div>' );
		$( '#csa-content-card' ).show();

		// Load the auto-created project
		post( 'forme_seo_get_content_projects' )
			.done( function ( res ) {
				if ( ! res.success || ! ( res.data.projects || [] ).length ) {
					$( '#csa-topic-grid' ).html( '<p class="csa-muted">No content project created yet.</p>' );
					return;
				}
				var project = res.data.projects[0];
				_contentProjectId = project.id;
				$( '.csa-content-loading-msg' ).text( 'Project: ' + escHtml( project.title ) );
				loadTopicGrid( project.id );
			} )
			.fail( function () {
				$( '#csa-topic-grid' ).html( '<p class="csa-muted">Could not load content project.</p>' );
			} );
	}

	function loadTopicGrid( projectId ) {
		post( 'forme_seo_get_content_project', { project_id: projectId } )
			.done( function ( res ) {
				if ( ! res.success ) {
					$( '#csa-topic-grid' ).html( '<p class="csa-muted">Could not load topics.</p>' );
					return;
				}
				var topics = res.data.topics || [];
				if ( ! topics.length ) {
					$( '#csa-topic-grid' ).html( '<p class="csa-muted">No topics found.</p>' );
					return;
				}
				var html = '';
				topics.forEach( function ( t ) {
					var statusClass = 'csa-status--' + ( t.status || 'pending' ).replace( /_/g, '-' );
					html += '<div class="csa-topic-card" data-topic-id="' + escHtml( t.id ) + '">' +
						'<div class="csa-topic-card-head">' +
						'<span class="csa-topic-title">' + escHtml( t.title ) + '</span>' +
						'<span class="csa-badge ' + statusClass + '">' + escHtml( cap( t.status ) ) + '</span>' +
						'</div>' +
						'<div class="csa-topic-meta">';
					if ( t.keyword ) html += '<span class="csa-topic-kw"><i class="lni lni-keyword"></i> ' + escHtml( t.keyword ) + '</span>';
					if ( t.cluster ) html += '<span class="csa-topic-cluster">' + escHtml( t.cluster ) + '</span>';
					html += '</div>';

					// Outline section
					if ( t.status === 'outline_ready' || t.status === 'writing' || t.status === 'written' ) {
						html += '<div class="csa-topic-outline-preview">Outline ready.</div>';
					}
					if ( t.word_count > 0 ) {
						html += '<div class="csa-topic-wc">' + t.word_count + ' words · SEO score: ' + t.seo_score + '</div>';
					}

					html += '<div class="csa-topic-actions">' +
						'<button class="csa-btn csa-btn--outline csa-btn--xs csa-outline-btn" ' +
						'data-project-id="' + escHtml( projectId ) + '" data-topic-id="' + escHtml( t.id ) + '">' +
						'<i class="lni lni-pencil"></i> Outline</button>' +
						'<button class="csa-btn csa-btn--primary csa-btn--xs csa-write-btn" ' +
						'data-project-id="' + escHtml( projectId ) + '" data-topic-id="' + escHtml( t.id ) + '">' +
						'<i class="lni lni-write"></i> Write Article</button>' +
						'</div>' +
						'<div class="csa-article-preview" style="display:none;"></div>' +
						'</div>'; // .csa-topic-card
				} );
				$( '#csa-topic-grid' ).html( html );
			} )
			.fail( function () {
				$( '#csa-topic-grid' ).html( '<p class="csa-muted">Network error loading topics.</p>' );
			} );
	}

	function extractArticleTopicsFromContentPillars( raw ) {
		var topics = [];
		var inPhase2 = false;

		String( raw || '' ).split( '\n' ).forEach( function ( line ) {
			var t = line.trim();

			if ( /^Phase\s+2\b/i.test( t ) || /Phase\s+2\s+Expansion/i.test( t ) ) {
				inPhase2 = true;
				return;
			}

			if ( inPhase2 && /^Phase\s+[134]\b/i.test( t ) ) {
				inPhase2 = false;
				return;
			}

			if ( ! inPhase2 || ! /^\|/.test( t ) || t.indexOf( '---' ) > -1 ) {
				return;
			}

			var cols = t.split( '|' ).map( function ( c ) {
				return c.trim();
			} ).filter( Boolean );

			if ( cols.length < 3 ) return;

			var title = cols[1] || '';
			var keyword = cols[2] || '';

			if (
				! title ||
				/^Blog Post$/i.test( title ) ||
				/^Content$/i.test( title ) ||
				/^Month$/i.test( title ) ||
				/location page/i.test( title )
			) {
				return;
			}

			topics.push( {
				title: title.replace( /^"|"$/g, '' ),
				keyword: keyword.replace( /^`|`$/g, '' ),
				source: 'Content Strategy by AI',
				type: 'Blog Post',
				status: '-'
			} );
		} );

		return topics.slice( 0, 5 );
	}

	function extractArticleTopicsFromPlan( raw ) {

		var topics = [];

		if ( ! raw ) {
			return topics;
		}

		var lines = raw.split( '\n' );

		lines.forEach( function ( line ) {

			line = line.trim();

			// Skip separator rows
			if (
				/^\|\-+/.test( line ) ||
				line.indexOf( '|---' ) !== -1
			) {
				return;
			}

			// NEW BLOG STRATEGY FORMAT
			// | 1 | Title | Keyword | Intent | Pillar | Priority |

			var strategyMatch = line.match(
				/^\|\s*\d+\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|?$/
			);

			if ( strategyMatch ) {

				topics.push({
					title: strategyMatch[1].trim(),
					keyword: strategyMatch[2].trim(),
					intent: strategyMatch[3].trim(),
					pillar: strategyMatch[4].trim(),
					priority: strategyMatch[5].trim()
				});

				return;
			}

			// OLD CONTENT CALENDAR FORMAT
			// | 2 | Blog Title | Keyword |

			var calendarMatch = line.match(
				/^\|\s*\d+\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|?$/
			);

			if ( calendarMatch ) {

				topics.push({
					title: calendarMatch[1].trim(),
					keyword: calendarMatch[2].trim()
				});
			}

		} );

		return topics;
	}

	// Generate Outline button (now async — returns job_id)
	$( document ).on( 'click', '.csa-outline-btn', function () {
		var $btn      = $( this ).prop( 'disabled', true ).text( 'Queuing…' );
		var projectId = $btn.data( 'project-id' );
		var topicId   = $btn.data( 'topic-id' );
		var $card     = $btn.closest( '.csa-topic-card' );

		$( '#csa-content-job-progress' ).show();
		$( '#csa-content-loading-msg' ).text( 'Generating outline…' );

		post( 'forme_seo_generate_outline', { project_id: projectId, topic_id: topicId } )
			.done( function ( res ) {
				if ( ! res.success ) {
					$btn.prop( 'disabled', false ).html( '<i class="lni lni-pencil"></i> Outline' );
					$( '#csa-content-job-progress' ).hide();
					toast( ( res.data && res.data.message ) || 'Could not queue outline.', 'error' );
					return;
				}
				var d = res.data;
				if ( d.status === 'queued' && d.job_id ) {
					pollJob( d.job_id,
						function () {
							$( '#csa-content-job-progress' ).hide();
							$btn.prop( 'disabled', false ).html( '<i class="lni lni-pencil"></i> Outline' );
							$card.find( '.csa-badge' ).text( 'Outline Ready' ).attr( 'class', 'csa-badge csa-status--outline-ready' );
							$card.find( '.csa-topic-outline-preview' ).remove();
							$card.find( '.csa-topic-meta' ).after( '<div class="csa-topic-outline-preview">Outline ready — click Write Article to generate content.</div>' );
							toast( 'Outline generated!', 'success' );
						},
						function ( msg ) {
							$( '#csa-content-job-progress' ).hide();
							$btn.prop( 'disabled', false ).html( '<i class="lni lni-pencil"></i> Outline' );
							toast( msg || 'Outline generation failed.', 'error' );
						},
						function ( pct, msg ) {
							$( '#csa-content-progress-bar' ).css( 'width', pct + '%' );
							$( '#csa-content-loading-msg' ).text( msg || 'Generating outline…' );
						}
					);
				} else {
					$btn.prop( 'disabled', false ).html( '<i class="lni lni-pencil"></i> Outline' );
					$( '#csa-content-job-progress' ).hide();
				}
			} )
			.fail( function () {
				$btn.prop( 'disabled', false ).html( '<i class="lni lni-pencil"></i> Outline' );
				$( '#csa-content-job-progress' ).hide();
				toast( 'Network error generating outline.', 'error' );
			} );
	} );

	// Generate Article button (now async — returns job_id)
	$( document ).on( 'click', '.csa-write-btn', function () {
		var $btn      = $( this ).prop( 'disabled', true ).text( 'Queuing…' );
		var projectId = $btn.data( 'project-id' );
		var topicId   = $btn.data( 'topic-id' );
		var $card     = $btn.closest( '.csa-topic-card' );

		$( '#csa-content-job-progress' ).show();
		$( '#csa-content-loading-msg' ).text( 'Writing article…' );

		post( 'forme_seo_generate_article', { project_id: projectId, topic_id: topicId } )
			.done( function ( res ) {
				if ( ! res.success ) {
					$btn.prop( 'disabled', false ).html( '<i class="lni lni-write"></i> Write Article' );
					$( '#csa-content-job-progress' ).hide();
					toast( ( res.data && res.data.message ) || 'Could not queue article.', 'error' );
					return;
				}
				var d = res.data;
				if ( d.status === 'queued' && d.job_id ) {
					pollJob( d.job_id,
						function () {
							$( '#csa-content-job-progress' ).hide();
							$btn.prop( 'disabled', false ).html( '<i class="lni lni-write"></i> Write Article' );
							$card.find( '.csa-badge' ).text( 'Written' ).attr( 'class', 'csa-badge csa-status--written' );
							toast( 'Article written!', 'success' );
							// Reload topic grid to show updated stats
							if ( _contentProjectId ) { loadTopicGrid( _contentProjectId ); }
						},
						function ( msg ) {
							$( '#csa-content-job-progress' ).hide();
							$btn.prop( 'disabled', false ).html( '<i class="lni lni-write"></i> Write Article' );
							toast( msg || 'Article generation failed.', 'error' );
						},
						function ( pct, msg ) {
							$( '#csa-content-progress-bar' ).css( 'width', pct + '%' );
							$( '#csa-content-loading-msg' ).text( msg || 'Writing article…' );
						}
					);
				} else {
					$btn.prop( 'disabled', false ).html( '<i class="lni lni-write"></i> Write Article' );
					$( '#csa-content-job-progress' ).hide();
				}
			} )
			.fail( function () {
				$btn.prop( 'disabled', false ).html( '<i class="lni lni-write"></i> Write Article' );
				$( '#csa-content-job-progress' ).hide();
				toast( 'Network error writing article.', 'error' );
			} );
	} );

	// ── Job polling ───────────────────────────────────────────────────────────

	function pollJob( jobId, onDone, onError, onProgress ) {
		var attempts    = 0;
		var maxAttempts = 90;
		var netFails    = 0;
		var maxNetFails = 3;
		function tick() {
			if ( attempts++ >= maxAttempts ) {
				onError( 'Analysis timed out — please try again.' );
				return;
			}
			post( 'forme_seo_poll_job', { job_id: jobId } )
				.done( function ( res ) {
					netFails = 0;
					if ( ! res.success ) { onError( res.data && res.data.message ); return; }
					var d = res.data;
					if ( d.status === 'completed' ) { _reportCache = null; onDone( d ); return; }
					if ( d.status === 'failed' || d.status === 'rate_limited' ) {
						onError( d.error || d.reset_hint || 'Analysis failed.' );
						return;
					}
					var pct = d.progress || 0;
					var msg = d.message  || ( 'Running… (' + ( attempts * 2 ) + 's)' );
					if ( onProgress ) {
						onProgress( pct, msg );
					} else {
						$( '#csa-progress-bar' ).css( 'width', pct + '%' );
						$( '#csa-progress-wrap' ).toggle( pct > 0 );
						$( '#csa-result-loading-msg' ).text( msg );
					}
					setTimeout( tick, 2000 );
				} )
				.fail( function () {
					if ( ++netFails < maxNetFails ) {
						setTimeout( tick, 3000 );
					} else {
						onError( 'Network error while polling — the job may still be running. Refresh the page to check status.' );
					}
				} );
		}
		setTimeout( tick, 2000 );
	}

	// ── Tool execution ────────────────────────────────────────────────────────

	$( document ).on( 'click', '.csa-tool-btn', function () {
		var $btn   = $( this ).prop( 'disabled', true );
		var $card  = $btn.closest( '.csa-tool-card' );
		var action = $btn.data( 'action' );
		var label  = $btn.data( 'label' );
		var tool   = action.replace( 'forme_seo_run_', '' ).replace( /_/g, '-' );
		var url    = $( '#csa-tool-url' ).val().trim() || cfg.homeUrl;

		$card.addClass( 'is-running' );
		showReportPanel( label, false );
		showReportLoading( 'Running ' + label + '…' );

		function onDone( data ) {
			renderReport( tool, data );
			if ( page === 'claude-seo-agent-audits' ) {
				setTimeout( function () { loadAuditJobs(); }, 500 );
			}
		}

		function onErr( msg ) {
			hideReportLoading();
			$( '#csa-report-content' )
				.html( '<p class="csa-error-msg"><i class="lni lni-warning"></i> ' + escHtml( msg || 'Analysis failed.' ) + '</p>' )
				.show();
			toast( msg || 'Analysis failed.', 'error' );
		}

		post( action, { url: url } )
			.done( function ( res ) {
				if ( ! res.success ) {
					onErr( friendlyError( res.data && res.data.code, res.data && res.data.message ) );
					return;
				}
				var data = res.data;
				if ( data.status === 'queued' && data.job_id ) {
					$( '#csa-result-loading-msg' ).text( 'Queued — waiting for result…' );
					pollJob( data.job_id, onDone, onErr );
				} else {
					onDone( data );
				}
			} )
			.fail( function () { onErr( 'Network error — could not run ' + label + '.' ); } )
			.always( function () { $btn.prop( 'disabled', false ); $card.removeClass( 'is-running' ); } );
	} );

	// ── Mark task done ────────────────────────────────────────────────────────

	$( document ).on( 'click', '.csa-task-done-btn', function () {
		var taskId = $( this ).data( 'task-id' );
		var $row   = $( this ).closest( '.csa-task-row, .csa-task-item' );
		if ( ! taskId ) return;

		post( 'forme_seo_update_task', { task_id: taskId, status: 'done' } )
			.done( function ( res ) {
				if ( res.success ) {
					$row.addClass( 'is-done' ).find( '.csa-task-done-btn' ).prop( 'disabled', true ).text( '✓' );
					setTimeout( function () { $row.fadeOut( 400 ); }, 600 );
					loadTasksSidebar();
				}
			} );
	} );

	// ── Dynamic sidebar: Tasks ────────────────────────────────────────────────

	function loadTasksSidebar() {
		post( 'forme_seo_get_tasks', { status: 'open', limit: 5 } )
			.done( function ( res ) {
				var tasks = res.success && res.data ? ( res.data.tasks || [] ) : [];

				if ( tasks.length ) {
					var html = '';
					tasks.forEach( function ( task ) {
						var pri = priorityClass( task.priority );
						html += '<div class="csa-task-item" data-task-id="' + escHtml( task.id ) + '">' +
							'<span class="csa-task-dot csa-task-dot--' + pri + '"></span>' +
							'<div class="csa-task-body">' +
							'<div class="csa-task-title">' + escHtml( task.title ) + '</div>' +
							'<div class="csa-task-meta">' +
							'<span class="csa-pill csa-pill--' + pri + '">' + escHtml( cap( task.priority ) ) + '</span>' +
							'<span class="csa-pill csa-pill--cat">' + escHtml( cap( task.category ) ) + '</span>' +
							'</div></div>' +
							'<button class="csa-btn csa-btn--ghost csa-btn--xs csa-task-done-btn" data-task-id="' + escHtml( task.id ) + '" title="Mark done">✓</button>' +
							'</div>';
					} );

					$( '#csa-task-list' ).html( html );
					return;
				}

				getLatestReport( 'audit', function ( audit ) {
					var raw = audit && audit.result ? ( audit.result.raw || '' ) : '';
					var items = parseAuditActionPlan( raw );

					if ( ! items.length ) {
						$( '#csa-task-list' ).html(
							'<div class="csa-empty-state csa-empty-state--sm"><p>No action plan found in latest audit.</p></div>'
						);
						return;
					}

					var html = '';
					items.forEach( function ( item, i ) {
						html += '<div class="csa-task-item">' +
							'<span class="csa-task-dot csa-task-dot--' + ( i < 2 ? 'high' : 'medium' ) + '"></span>' +
							'<div class="csa-task-body">' +
							'<div class="csa-task-title">' + escHtml( item ) + '</div>' +
							'<div class="csa-task-meta">' +
							'<span class="csa-pill csa-pill--' + ( i < 2 ? 'high' : 'medium' ) + '">' + ( i < 2 ? 'High' : 'Medium' ) + '</span>' +
							'<span class="csa-pill csa-pill--cat">Audit</span>' +
							'</div></div>' +
							'</div>';
					} );

					$( '#csa-task-list' ).html( html );
				} );
			} )
			.fail( function () {
				getLatestReport( 'audit', function ( audit ) {
					var raw = audit && audit.result ? ( audit.result.raw || '' ) : '';
					var items = parseAuditActionPlan( raw );

					if ( ! items.length ) {
						$( '#csa-task-list' ).html(
							'<div class="csa-empty-state csa-empty-state--sm"><p>No action plan found in latest audit.</p></div>'
						);
						return;
					}

					$( '#csa-task-list' ).html(
						items.map( function ( item ) {
							return '<div class="csa-task-item"><div class="csa-task-body"><div class="csa-task-title">' + escHtml( item ) + '</div></div></div>';
						} ).join( '' )
					);
				} );
			} );
	}

	// ── Dynamic sidebar: Quick Wins ───────────────────────────────────────────

	function loadQuickWins() {
		post( 'forme_seo_get_tasks', { category: 'quick_win', status: 'open', limit: 3 } )
			.done( function ( res ) {
				var wins = res.success && res.data ? ( res.data.tasks || [] ) : [];

				if ( wins.length ) {
					var html = '';
					wins.forEach( function ( w ) {
						html += '<div class="csa-qw-item">' +
							'<div class="csa-qw-icon"></div>' +
							'<span class="csa-qw-label">' + escHtml( w.title ) + '</span>' +
							'<i class="lni lni-chevron-right csa-qw-arrow"></i>' +
							'</div>';
					} );

					$( '#csa-qw-list' ).html( html );
					return;
				}

				getLatestReport( 'audit', function ( audit ) {
					var raw = audit && audit.result ? ( audit.result.raw || '' ) : '';
					var items = parseQuickWins( raw );

					if ( ! items.length ) {
						$( '#csa-qw-list' ).html(
							'<div class="csa-empty-state csa-empty-state--sm"><p>No quick wins found in latest audit.</p></div>'
						);
						return;
					}

					var html = '';
					items.forEach( function ( item ) {
						html += '<div class="csa-qw-item">' +
							'<span class="csa-qw-dot"></span>' +
							'<span class="csa-qw-label">' + escHtml( item ) + '</span>' +
							'</div>';
					} );

					$( '#csa-qw-list' ).html( html );
				} );
			} );
	}

	// ── Reports History ───────────────────────────────────────────────────────

	function loadReportsHistory( limit ) {
		post( 'forme_seo_get_reports', { limit: limit || 5 } )
			.done( function ( res ) {
				if ( ! res.success ) return;
				var reports = res.data.reports || [];

				if ( ! reports.length ) {
					$( '#csa-reports-list' ).html(
						'<div class="csa-empty-state"><i class="lni lni-files"></i>' +
						'<p>No reports yet. Run an analysis above to get started.</p></div>'
					);
					return;
				}

				var html = '<table class="csa-reports-table"><thead><tr>' +
					'<th>Tool</th><th>URL</th><th>Score</th><th>Date</th><th></th>' +
					'</tr></thead><tbody>';

				reports.forEach( function ( r ) {
					var date   = r.created_at ? new Date( r.created_at ).toLocaleDateString() : '—';
					var reportScore = getReportScore( r );
					var score  = reportScore > 0 ? '<span class="csa-score-pill" style="background:' + scoreColor( reportScore ) + '">' + reportScore + '</span>' : '—';
					var cached = r.cached ? '<span class="csa-cached-badge">Cached</span>' : '';
					var fullUrl = r.target_url || r.input_url || r.url || '';
					var url = fullUrl ? ( fullUrl.length > 30 ? fullUrl.slice( 0, 30 ) + '…' : fullUrl ) : '—';

					html += '<tr>' +
						'<td><span class="csa-pill csa-pill--cat">' + escHtml( r.tool ) + '</span></td>' +
						'<td class="csa-reports-url" title="' + escHtml( fullUrl ) + '">' + escHtml( url ) + '</td>' +
						'<td>' + score + ' ' + cached + '</td>' +
						'<td class="csa-reports-date">' + escHtml( date ) + '</td>' +
						'<td><button class="csa-btn csa-btn--ghost csa-btn--xs csa-view-report-btn" ' +
						'data-report-id="' + escHtml( r.id ) + '" data-tool="' + escHtml( r.tool ) + '">' +
						'<i class="lni lni-eye"></i> View</button></td>' +
						'</tr>';
				} );

				html += '</tbody></table>';
				$( '#csa-reports-list' ).html( html );
			} );
	}

	$( '#csa-reports-refresh-btn' ).on( 'click', function () {
		loadReportsHistory();
	} );

	// View a saved report — unified drawer on all pages
	$( document ).on( 'click', '.csa-view-report-btn', function () {
		openReportDrawer(
			$( this ).data( 'report-id' ),
			$( this ).data( 'tool' )
		);
	} );

	$( document ).on( 'click', '.csa-view-article-source-btn', function ( e ) {
		e.preventDefault();

		console.log( 'Article source view clicked', {
			reportId: $( this ).attr( 'data-report-id' ),
			tool: $( this ).attr( 'data-tool' )
		} );

		openArticleTopicsDrawer(
			$( this ).attr( 'data-report-id' ),
			$( this ).attr( 'data-tool' )
		);
	} );

	$( document ).on( 'click', '#csa-report-detail-close, #csa-report-drawer-overlay', function () {
		$( '#csa-report-detail-card' ).hide();
		$( '#csa-report-drawer-overlay' ).hide();
		$( '#csa-report-detail-content' ).empty();
	} );

	// ── renderReportInto: build report HTML into a jQuery element ────────────────

	function renderReportInto( tool, data, $target ) {
		var report = data.result || data;
		var raw = report.raw || data.raw || '';

		var score = getReportScore( data );
		var summary =
			report.summary ||
			data.summary ||
			extractAuditSummary( raw );

		if ( raw ) {
			var html = '';

			if ( score > 0 || summary ) {
				html += '<div class="csa-report-hero">';

				if ( score > 0 ) {
					html += '<div class="csa-score-circle" style="--score-color:' + scoreColor( score ) + '; --score:' + score + ';">' +
						'<div class="csa-score-num">' + score + '</div>' +
						'<div class="csa-score-lbl">/ 100</div>' +
						'</div>';
				}

				if ( summary ) {
					html += '<div class="csa-report-hero-copy">' +
						'<h2>Audit Summary</h2>' +
						'<p>' + inlineMarkdown( escHtml( summary ) ) + '</p>' +
						'</div>';
				}

				html += '</div>';
			}

			raw = cleanAiFooter( raw );

			html += markdownToHtml( raw );

			$target.html( html );
			return;
		}
		
		if ( tool === 'content-pillars' ) {
			$target.html( '<p class="csa-report-summary">' + escHtml( data.summary || '' ) + '</p>' );
			return;
		}
		var score   = data.score || 0;
		var summary = data.summary || '';
		var issues  = data.issues || [];
		var recs    = data.recommendations || [];
		var wins    = data.quick_wins || [];
		var html = '<div class="csa-report-grid">';
		html += '<div class="csa-report-left">';
		if ( score > 0 ) {
			html += '<div class="csa-score-circle" style="--score-color:' + scoreColor( score ) + '; --score:' + score + ';">' +
				'<div class="csa-score-num">' + score + '</div><div class="csa-score-lbl">/ 100</div></div>';
		}
		if ( summary ) { html += '<p class="csa-report-summary">' + escHtml( summary ) + '</p>'; }
		html += '</div><div class="csa-report-right">';
		if ( issues.length ) {
			html += '<div class="csa-report-section"><div class="csa-report-section-title"><i class="lni lni-warning"></i> Issues (' + issues.length + ')</div><ul class="csa-issues-list">';
			issues.forEach( function ( iss ) {
				var sev = severityClass( iss.severity );
				html += '<li class="csa-issue-item"><span class="csa-sev-dot csa-sev-dot--' + sev + '"></span>' +
					'<span class="csa-issue-text">' + escHtml( iss.description ) + '</span>' +
					'<span class="csa-pill csa-pill--' + sev + '">' + escHtml( cap( iss.severity ) ) + '</span></li>';
			} );
			html += '</ul></div>';
		}
		if ( recs.length ) {
			html += '<div class="csa-report-section"><div class="csa-report-section-title"><i class="lni lni-checkmark-circle"></i> Recommendations</div><ul class="csa-recs-list">';
			recs.slice( 0, 8 ).forEach( function ( r ) { html += '<li>' + escHtml( r ) + '</li>'; } );
			html += '</ul></div>';
		}
		if ( wins.length ) {
			html += '<div class="csa-report-section"><div class="csa-report-section-title"><i class="lni lni-bolt"></i> Quick Wins</div><ul class="csa-wins-list">';
			wins.forEach( function ( w ) { html += '<li><i class="lni lni-arrow-right"></i> ' + escHtml( w ) + '</li>'; } );
			html += '</ul></div>';
		}
		html += '</div></div>';
		$target.html( html );
	}

	// ── Reports page ──────────────────────────────────────────────────────────

	var _reportsOffset = 0;
	var _reportsLimit  = 25;

	function loadReportsPage() {
		var tool   = $( '#csa-reports-filter-tool' ).val() || '';
		var $list  = $( '#csa-reports-page-list' );
		$list.html( '<div class="csa-empty-state"><div class="csa-spinner-sm"></div><p>Loading reports…</p></div>' );

		post( 'forme_seo_get_reports', { tool: tool, limit: _reportsLimit, offset: _reportsOffset } )
			.done( function ( res ) {
				if ( ! res.success ) { $list.html( '<p class="csa-error-msg">Could not load reports.</p>' ); return; }
				var reports = res.data.reports || [];
				var total   = res.data.total || 0;

				if ( ! reports.length ) {
					$list.html( '<div class="csa-empty-state"><i class="lni lni-files"></i><p>No reports yet.</p></div>' );
					$( '#csa-reports-pagination' ).hide();
					return;
				}

				var html = '<table class="csa-reports-table"><thead><tr>' +
					'<th>Tool</th><th>URL</th><th>Score</th><th>Date</th><th></th>' +
					'</tr></thead><tbody>';
				reports.forEach( function ( r ) {
					var date   = r.created_at ? new Date( r.created_at ).toLocaleDateString() : '—';
					var reportScore = getReportScore( r );
					var score  = reportScore > 0 ? '<span class="csa-score-pill" style="background:' + scoreColor( reportScore ) + '">' + reportScore + '</span>' : '—';
					var fullUrl = r.target_url || r.input_url || r.url || '';
					var url = fullUrl ? ( fullUrl.length > 40 ? fullUrl.slice( 0, 40 ) + '…' : fullUrl ) : '—';
					var cached = r.cached ? ' <span class="csa-cached-badge">Cached</span>' : '';
					html += '<tr>' +
						'<td><span class="csa-pill csa-pill--cat">' + escHtml( r.tool ) + '</span></td>' +
						'<td class="csa-reports-url" title="' + escHtml( fullUrl ) + '">' + escHtml( url ) + '</td>' +
						'<td>' + score + cached + '</td>' +
						'<td class="csa-reports-date">' + escHtml( date ) + '</td>' +
						'<td><button class="csa-btn csa-btn--ghost csa-btn--xs csa-view-report-btn" ' +
						'data-report-id="' + escHtml( r.id ) + '" data-tool="' + escHtml( r.tool ) + '">' +
						'<i class="lni lni-eye"></i> View</button></td>' +
						'</tr>';
				} );
				html += '</tbody></table>';
				$list.html( html );

				// Pagination
				var pages = Math.ceil( total / _reportsLimit );
				var curPg = Math.floor( _reportsOffset / _reportsLimit ) + 1;
				if ( pages > 1 ) {
					var pHtml = '<span class="csa-page-info">Page ' + curPg + ' of ' + pages + ' (' + total + ' total)</span>';
					if ( _reportsOffset > 0 ) {
						pHtml += ' <button class="csa-btn csa-btn--ghost csa-btn--xs" id="csa-page-prev">← Prev</button>';
					}
					if ( curPg < pages ) {
						pHtml += ' <button class="csa-btn csa-btn--ghost csa-btn--xs" id="csa-page-next">Next →</button>';
					}
					$( '#csa-reports-pagination' ).html( pHtml ).show();
				} else {
					$( '#csa-reports-pagination' ).hide();
				}
			} )
			.fail( function () { $list.html( '<p class="csa-error-msg">Network error loading reports.</p>' ); } );
	}

	$( document ).on( 'click', '#csa-reports-load-btn', function () { _reportsOffset = 0; loadReportsPage(); } );
	$( document ).on( 'change', '#csa-reports-filter-tool', function () { _reportsOffset = 0; loadReportsPage(); } );
	$( document ).on( 'click', '#csa-page-prev', function () { _reportsOffset = Math.max( 0, _reportsOffset - _reportsLimit ); loadReportsPage(); } );
	$( document ).on( 'click', '#csa-page-next', function () { _reportsOffset += _reportsLimit; loadReportsPage(); } );

	// ── Audits & Tools page ───────────────────────────────────────────────────

	function initAudits() {
		loadTasksSidebar();
		loadQuickWins();
		loadAuditJobs();
		startActiveJobPoller();
	}

	function loadAuditJobs( opts ) {
		opts = opts || {};
		if ( opts.offset !== undefined ) {
			_auditJobsOffset = opts.offset;
		} else if ( ! opts._paged ) {
			_auditJobsOffset = 0;
		}

		var status = opts.status !== undefined ? opts.status : $( '#csa-jobs-filter-status' ).val() || '';
		var tool   = opts.tool   !== undefined ? opts.tool   : $( '#csa-jobs-filter-tool'   ).val() || '';
		var search = opts.search !== undefined ? opts.search : ( $( '#csa-jobs-search' ).val() || '' ).trim();

		var $wrap = $( '#csa-jobs-table-wrap' );
		$wrap.html( '<div class="csa-empty-state"><div class="csa-spinner-sm"></div><p>Loading jobs…</p></div>' );

		post( 'forme_seo_get_jobs', {
			category: 'audit_tools',
			tool:     tool,
			limit:    _auditJobsLimit,
			offset:   _auditJobsOffset,
		} )
		.done( function ( res ) {
			if ( ! res.success ) { $wrap.html( '<p class="csa-error-msg">Could not load jobs.</p>' ); return; }
			var jobs  = res.data.jobs  || [];
			var total = res.data.total || 0;

			// Client-side filtering
			if ( status ) {
				jobs = jobs.filter( function ( j ) { return j.status === status; } );
			}
			if ( search ) {
				jobs = jobs.filter( function ( j ) {
					return ( j.input_url || '' ).toLowerCase().indexOf( search.toLowerCase() ) !== -1;
				} );
			}

			if ( ! jobs.length ) {
				$wrap.html( '<div class="csa-empty-state"><i class="lni lni-timer"></i><p>No jobs found.</p></div>' );
				$( '#csa-jobs-pagination' ).hide();
				return;
			}

			var html = '<table class="csa-reports-table csa-job-table"><thead><tr>' +
				'<th>Tool</th><th>URL</th><th>Status</th><th>Score</th><th>Started</th><th></th>' +
				'</tr></thead><tbody>';

			jobs.forEach( function ( j ) {
				var statusCls   = 'csa-status--' + j.status;
				var statusLabel = cap( j.status.replace( '_', ' ' ) );
				var statusBadge = '<span class="csa-badge ' + escHtml( statusCls ) + '">' + escHtml( statusLabel ) + '</span>';
				var score = '';
				if ( j.status === 'completed' ) {
					score = j.score > 0 ? '<span class="csa-score-pill" style="background:' + scoreColor( j.score ) + '">' + j.score + '</span>' : '—';
					if ( j.cached ) { score += ' <span class="csa-cached-badge">Cached</span>'; }
				} else if ( j.status === 'running' || j.status === 'queued' ) {
					score = '<div class="csa-spinner-xs"></div>';
				}
				var started    = j.started_at || j.created_at || '';
				var startedFmt = started ? new Date( started ).toLocaleString() : '—';
				var url        = j.input_url ? ( j.input_url.length > 35 ? j.input_url.slice( 0, 35 ) + '…' : j.input_url ) : '—';
				var actions    = '';
				if ( j.status === 'completed' && j.report_id ) {
					actions = '<button class="csa-btn csa-btn--ghost csa-btn--xs csa-view-report-btn" ' +
						'data-report-id="' + escHtml( j.report_id ) + '" data-tool="' + escHtml( j.tool ) + '">' +
						'<i class="lni lni-eye"></i> View</button>';
				}

				html += '<tr data-job-id="' + escHtml( j.job_id ) + '" data-job-status="' + escHtml( j.status ) + '">' +
					'<td><span class="csa-pill csa-pill--cat">' + escHtml( j.tool ) + '</span></td>' +
					'<td class="csa-job-url" title="' + escHtml( j.input_url || '' ) + '">' + escHtml( url ) + '</td>' +
					'<td>' + statusBadge + '</td>' +
					'<td class="csa-job-score">' + score + '</td>' +
					'<td class="csa-reports-date">' + escHtml( startedFmt ) + '</td>' +
					'<td>' + actions + '</td>' +
					'</tr>';
			} );
			html += '</tbody></table>';
			$wrap.html( html );

			// Pagination (only when no client-side filtering)
			if ( ! status && ! search ) {
				var pages = Math.ceil( total / _auditJobsLimit );
				var curPg = Math.floor( _auditJobsOffset / _auditJobsLimit ) + 1;
				if ( pages > 1 ) {
					var pHtml = '<span class="csa-page-info">Page ' + curPg + ' of ' + pages + ' (' + total + ' total)</span>';
					if ( _auditJobsOffset > 0 ) {
						pHtml += ' <button class="csa-btn csa-btn--ghost csa-btn--xs" id="csa-jobs-page-prev">← Prev</button>';
					}
					if ( curPg < pages ) {
						pHtml += ' <button class="csa-btn csa-btn--ghost csa-btn--xs" id="csa-jobs-page-next">Next →</button>';
					}
					$( '#csa-jobs-pagination' ).html( pHtml ).show();
				} else {
					$( '#csa-jobs-pagination' ).hide();
				}
			} else {
				$( '#csa-jobs-pagination' ).hide();
			}

			// Restart live poller for queued/running rows
			startActiveJobPoller();
		} )
		.fail( function () { $wrap.html( '<p class="csa-error-msg">Network error loading jobs.</p>' ); } );
	}

	function startActiveJobPoller() {
		stopActiveJobPoller();

		var hasActive =
			$( '#csa-jobs-table-wrap tr[data-job-status="queued"], #csa-jobs-table-wrap tr[data-job-status="running"]' ).length > 0;

		if ( ! hasActive ) {
			return;
		}

		_activeJobPoller = setInterval( function () {
			loadAuditJobs( {
				_paged: true,
				offset: _auditJobsOffset
			} );
		}, 5000 );
	}

	function stopActiveJobPoller() {
		if ( _activeJobPoller ) {
			clearInterval( _activeJobPoller );
			_activeJobPoller = null;
		}
	}

	$( document ).on( 'change', '#csa-jobs-filter-status', function () { loadAuditJobs( { status: $( this ).val() } ); } );
	$( document ).on( 'change', '#csa-jobs-filter-tool',   function () { loadAuditJobs( { tool:   $( this ).val() } ); } );
	$( document ).on( 'input',  '#csa-jobs-search', debounce( function () { loadAuditJobs( { search: $( this ).val() } ); }, 400 ) );
	$( document ).on( 'click',  '#csa-jobs-refresh-btn', function () { loadAuditJobs(); } );
	$( document ).on( 'click',  '#csa-jobs-page-prev', function () { loadAuditJobs( { offset: Math.max( 0, _auditJobsOffset - _auditJobsLimit ), _paged: true } ); } );
	$( document ).on( 'click',  '#csa-jobs-page-next', function () { loadAuditJobs( { offset: _auditJobsOffset + _auditJobsLimit, _paged: true } ); } );

	// ── Articles page — driven by content-pillars report ─────────────────────
	
	function loadArticlesPage() {
		var $body = $( '#csa-projects-body' );

		$body.html(
			'<div class="csa-empty-state"><div class="csa-spinner-sm"></div><p>Loading…</p></div>'
		);

		getReports( function ( reports ) {
			var sources = reports.filter( function ( r ) {
				return (
					r.status === 'completed' &&
					(
						r.tool === 'content_pillars' ||
						r.tool === 'blog_strategy' ||
						r.tool === 'blog_calendar'
					)
				);
			} );

			if ( ! sources.length ) {
				$body.html(
					'<div class="csa-empty-state"><i class="lni lni-layers"></i>' +
					'<p>No content strategy yet. <a href="' + ( cfg.contentPlanUrl || '#' ) + '">Run Content Plan →</a></p></div>'
				);
				return;
			}

			var html = '<table class="csa-reports-table csa-articles-table">' +
				'<thead><tr>' +
					'<th>Strategy Source</th>' +
					'<th>Date</th>' +
					'<th>Topics</th>' +
					'<th></th>' +
				'</tr></thead><tbody>';

			sources.forEach( function ( r ) {
				var raw = r.result && r.result.raw ? r.result.raw : '';
				var topics = [];

				if ( r.tool === 'content_pillars' ) {
					topics = extractArticleTopicsFromContentPillars( raw );
				} else if ( r.tool === 'blog_strategy' ) {
					topics = extractArticleTopicsFromBlogStrategy( raw );
				} else if ( r.tool === 'blog_calendar' ) {
					topics = extractArticleTopicsFromCalendar( raw );
				}

				var label = {
					content_pillars: 'Content Strategy by AI',
					blog_strategy: 'Blog Strategy',
					blog_calendar: 'Editorial Calendar'
				}[ r.tool ] || r.tool;

				var date = r.created_at ? new Date( r.created_at ).toLocaleDateString() : '—';

				html += '<tr>' +
					'<td><strong>' + escHtml( label ) + '</strong></td>' +
					'<td>' + escHtml( date ) + '</td>' +
					'<td>' + escHtml( topics.length ? topics.length + ' topics' : 'View details' ) + '</td>' +
					'<td>' +
						'<button class="csa-btn csa-btn--outline csa-btn--sm csa-view-article-source-btn" ' +
							'data-report-id="' + escHtml( r.id ) + '" ' +
							'data-tool="' + escHtml( r.tool ) + '">' +
							'<i class="lni lni-eye"></i> View' +
						'</button>' +
					'</td>' +
				'</tr>';
			} );

			html += '</tbody></table>';
			$body.html( html );
		} );
	}

	function openArticleTopicsDrawer( reportId, tool ) {

		if ( ! $( '#csa-report-detail-card' ).length ) {
			alert( 'Report drawer HTML missing on this page.' );
			return;
		}

		$( '#csa-report-detail-title' ).text( 'Article Topics' );
		$( '#csa-report-drawer-overlay' ).show();
		$( '#csa-report-detail-card' ).show();

		$( '#csa-report-detail-content' ).html(
			'<div class="csa-result-loading">' +
				'<div class="csa-spinner-sm"></div>' +
				'<span>Loading topics…</span>' +
			'</div>'
		);

		post( 'forme_seo_get_report', {
			report_id: reportId
		} )

		.done( function ( res ) {

			if ( ! res.success ) {
				$( '#csa-report-detail-content' ).html(
					'<p class="csa-error-msg">Could not load topics.</p>'
				);
				return;
			}

			var report = res.data || {};
			var result = report.result || report.data || {};
			var raw = '';

			if ( result.raw ) {
				raw = result.raw;
			} else if ( typeof result === 'string' ) {
				raw = result;
			} else if ( report.raw ) {
				raw = report.raw;
			} else if ( report.result_json && report.result_json.raw ) {
				raw = report.result_json.raw;
			}

			raw = cleanAiFooter( raw );

			var topics = [];

			if ( tool === 'content_pillars' ) {
				topics = extractArticleTopicsFromContentPillars( raw );
			} else if ( tool === 'blog_strategy' ) {
				topics = extractArticleTopicsFromBlogStrategy( raw );

				var calendarDates = extractCalendarDatesMap( raw );

				topics = topics.map( function ( t ) {
					var key = String( t.title || t.topic || '' )
						.trim()
						.toLowerCase();

					t.publish_date = calendarDates[ key ] || '';

					return t;
				} );
			} else if ( tool === 'blog_calendar' ) {
				topics = extractArticleTopicsFromCalendar( raw );
			}

			if ( ! topics.length ) {
				$( '#csa-report-detail-content' ).html(
					'<div class="csa-empty-state csa-empty-state--sm">' +
						'<p>No article topics found in this strategy.</p>' +
					'</div>'
				);
				return;
			}

			post( 'forme_seo_get_article_statuses' )

				.done( function ( statusRes ) {

					var statuses = (
						statusRes.success &&
						statusRes.data
					)
						? statusRes.data
						: {};

					renderTopicsTable( topics, statuses );

				} )

				.fail( function () {
					renderTopicsTable( topics, {} );
				} );

		} )

		.fail( function () {
			$( '#csa-report-detail-content' ).html(
				'<p class="csa-error-msg">Network error loading topics.</p>'
			);
		} );
	}

	function extractCalendarDatesMap( raw ) {

		var map = {};
		var inCalendar = false;

		String( raw || '' ).split( '\n' ).forEach( function ( line ) {

			var t = line.trim();

			if ( /^##\s+Editorial Calendar/i.test( t ) ) {
				inCalendar = true;
				return;
			}

			if ( inCalendar && /^##\s+/i.test( t ) ) {
				inCalendar = false;
				return;
			}

			if ( ! inCalendar || ! /^\|/.test( t ) || t.indexOf( '---' ) > -1 ) {
				return;
			}

			var cols = t.split( '|' )
				.map( function ( c ) {
					return c.trim();
				} )
				.filter( Boolean );

			if ( cols.length < 6 || /^Publish Date$/i.test( cols[0] ) ) {
				return;
			}

			var title = cols[2] || '';
			var date = cols[0] || '';

			if ( title ) {
				map[
					String( title ).trim().toLowerCase()
				] = date;
			}

		} );

		return map;
	}
	
	

	function renderTopicsTable( topics, statuses ) {

		var html =
			'<table class="csa-reports-table csa-article-topics-table">' +

				'<thead>' +
					'<tr>' +
						'<th>Topic</th>' +
						'<th>Keyword</th>' +
						'<th>Status</th>' +
						'<th></th>' +
					'</tr>' +
				'</thead>' +

				'<tbody>';

		topics.forEach( function ( t, i ) {

			var title =
				t.title ||
				t.topic ||
				'';

			var keyword =
				t.keyword ||
				'';

			var topicKey =
				'topic_' + md5Like( title );

			var wpStatus =
				statuses[ topicKey ] || null;

			if ( ! wpStatus ) {

				Object.keys( statuses ).forEach( function ( key ) {

					var s = statuses[ key ];

					if (
						s.topic &&
						String( s.topic ).trim().toLowerCase() ===
						String( title ).trim().toLowerCase()
					) {
						wpStatus = s;
					}

				} );

			}

			var badge =
				'-';

			var badgeClass =
				'csa-status--write';

			var actionHtml =
				'';

			if ( wpStatus ) {

				if ( wpStatus.status === 'publish' ) {

					badge =
						'Published';

					badgeClass =
						'csa-status--published';

					actionHtml =
						'<a href="' +
							escHtml( wpStatus.view_url || wpStatus.edit_url ) +
						'" ' +
						'class="csa-btn csa-btn--outline csa-btn--sm" ' +
						'target="_blank" rel="noopener noreferrer">' +
							'<i class="lni lni-eye"></i> View Post' +
						'</a>';

				} else {

					badge =
						'Draft';

					badgeClass =
						'csa-status--draft';

					actionHtml =
						'<a href="' +
							escHtml( wpStatus.edit_url ) +
						'" ' +
						'class="csa-btn csa-btn--outline csa-btn--sm" ' +
						'target="_blank" rel="noopener noreferrer">' +
							'<i class="lni lni-pencil"></i> Edit Draft' +
						'</a>';

				}

			} else {

				actionHtml =

					'<button class="csa-btn csa-btn--primary csa-btn--sm csa-write-topic-btn" ' +

						'data-topic-idx="' +
							escHtml( i ) +
						'" ' +

						'data-topic-title="' +
							escHtml( title ) +
						'" ' +

						'data-topic-keyword="' +
							escHtml( keyword ) +
						'">' +

						'Write →' +

					'</button>';

			}

			html +=

				'<tr>' +

					'<td>' +

						'<strong>' +
							escHtml( title ) +
						'</strong>' +

						(
							t.publish_date
								? '<div style="margin-top:4px; font-size:12px; color:#9ca3af;">' +
									escHtml( t.publish_date ) +
								'</div>'
								: ''
						) +

					'</td>' +

					'<td>' +
						escHtml( keyword || '—' ) +
					'</td>' +

					'<td>' +

						'<span class="csa-badge ' +
							badgeClass +
						'">' +

							escHtml( badge ) +

						'</span>' +

					'</td>' +

					'<td>' +

						actionHtml +

					'</td>' +

				'</tr>';

		} );

		html +=

				'</tbody>' +
			'</table>';

		$( '#csa-report-detail-content' )
			.html( html );
	}

	function extractArticleTopicsFromBlogStrategy( raw ) {
		var topics = [];

		String( raw || '' ).split( '\n' ).forEach( function ( line ) {
			var t = line.trim();

			if ( ! /^\|/.test( t ) || t.indexOf( '---' ) > -1 ) {
				return;
			}

			var cols = t.split( '|' ).map( function ( c ) {
				return c.trim();
			} ).filter( Boolean );

			if ( cols.length < 6 ) {
				return;
			}

			if (
				/^#$/i.test( cols[0] ) ||
				/^Title$/i.test( cols[1] ) ||
				/^Target Keyword$/i.test( cols[2] )
			) {
				return;
			}

			topics.push( {
				title: cols[1],
				keyword: cols[2],
				intent: cols[3],
				pillar: cols[4],
				priority: cols[5],
				source: 'Blog Strategy',
				type: 'Blog Post',
				status: '-'
			} );
		} );

		return topics.slice( 0, 12 );
	}

	function extractArticleTopicsFromCalendar( raw ) {
		return [];
	}

	function md5Like( text ) {
		return String( text || '' )
			.trim()
			.toLowerCase()
			.replace( /[^a-z0-9]+/g, '-' );
	}


	$( document ).on( 'click', '#csa-projects-refresh-btn', function () {
		_reportCache = null;
		loadArticlesPage();
	} );

	$( document ).on( 'click', '#csa-open-upgrade-modal', function () {
		$( '#csa-upgrade-modal-overlay' ).show();
		$( '#csa-upgrade-modal' ).show();
	} );

	$( document ).on( 'click', '#csa-close-upgrade-modal, #csa-upgrade-modal-overlay', function () {
		$( '#csa-upgrade-modal-overlay' ).hide();
		$( '#csa-upgrade-modal' ).hide();
	} );

	$( document ).on( 'click', '.csa-write-topic-btn', function () {
		var $btn = $( this );
		var topic = $btn.data( 'topic-title' ) || '';
		var keyword = $btn.data( 'topic-keyword' ) || '';

		if ( ! topic ) {
			toast( 'Missing topic title.', 'error' );
			return;
		}

		$btn.prop( 'disabled', true ).text( 'Writing…' );

		post( 'forme_seo_run_blog_write', {
			topic: keyword ? topic + ' | Target keyword: ' + keyword : topic
		} )
			.done( function ( res ) {

				if ( ! res.success ) {
					$btn.prop( 'disabled', false ).text( 'Write →' );

					toast(
						( res.data && ( res.data.message || res.data.detail || res.data.error ) ) || 'Could not write article.',
						'error'
					);

					return;
				}

				$btn.text( 'Writing…' );

				$btn
					.closest( 'tr' )
					.find( '.csa-badge' )
					.text( 'Writing' )
					.attr( 'class', 'csa-badge csa-status--writing' );

				toast(
					'Article generation started. Checking for completed draft…',
					'success'
				);

				pollBlogWriteReport( topic, function ( report ) {

					var raw = '';

					if ( report.result && report.result.raw ) {
						raw = report.result.raw;
					} else if ( report.result_json && report.result_json.raw ) {
						raw = report.result_json.raw;
					}

					$btn.text( 'Draft Ready' );

					$btn
						.closest( 'tr' )
						.find( '.csa-badge' )
						.text( 'Draft' )
						.attr( 'class', 'csa-badge csa-status--draft' );

					toast( 'Article draft generated.', 'success' );

					if ( raw ) {

						$( '#csa-article-preview-card' ).show();

						$( '#csa-article-preview-title' )
							.text( topic );

						raw = cleanAiFooter( raw );

						$( '#csa-article-preview-content' )
							.html( markdownToHtml( raw ) );

						post( 'forme_seo_create_draft_post', {
								title: topic,
								content: raw,
								report_id: report.id || ''
							} )
							.done( function ( createRes ) {

								if ( ! createRes.success ) {
									return;
								}

								var postData = createRes.data || {};

								$btn
									.closest( 'tr' )
									.find( '.csa-badge' )
									.text( postData.status === 'publish' ? 'Published' : 'Draft' )
									.attr(
										'class',
										'csa-badge ' + (
											postData.status === 'publish'
												? 'csa-status--published'
												: 'csa-status--draft'
										)
									);

								$btn
									.removeClass( 'csa-btn--primary' )
									.addClass( 'csa-btn--outline' )
									.text( 'Edit Draft →' )
									.prop( 'disabled', false )
									.off( 'click' )
									.on( 'click', function () {
										window.open( postData.edit_url, '_blank' );
									} );

							} );
					}

					_reportCache = null;
				} );
			} )

			.fail( function ( xhr ) {

				console.log(
					'blog write ajax failed',
					xhr.status,
					xhr.responseText
				);

				$btn.prop( 'disabled', false ).text( 'Write →' );

				toast(
					'Request timed out. The article may still complete in the background.',
					'warning'
				);
			} );
	} );

	function pollBlogWriteReport( topic, onDone ) {

		var attempts = 0;
		var maxAttempts = 90;

		function tick() {

			attempts++;

			post( 'forme_seo_get_reports', {
				tool: 'blog_write',
				limit: 20,
				offset: 0
			} )

				.done( function ( res ) {

					var reports = [];

					if ( res.success && res.data ) {
						reports = res.data.reports || [];
					}

					var found = reports.find( function ( r ) {

						return (
							r.status === 'completed' &&
							r.target_url &&
							r.target_url.indexOf( topic ) !== -1
						);

					} );

					if ( found ) {
						onDone( found );
						return;
					}

					if ( attempts < maxAttempts ) {
						setTimeout( tick, 5000 );
					}
				} )

				.fail( function () {

					if ( attempts < maxAttempts ) {
						setTimeout( tick, 5000 );
					}
				} );
		}

		setTimeout( tick, 5000 );
	}

	// ── GSC: Google Search Console ────────────────────────────────────────────

	var gscChart = null;

	function setGscBadge( connected ) {
		var $b = $( '#csa-gsc-badge' );
		if ( connected ) {
			$b.text( 'Connected' ).attr( 'class', 'csa-badge csa-badge--connected' );
		} else {
			$b.text( 'Not Connected' ).attr( 'class', 'csa-badge csa-badge--neutral' );
		}
	}

	function renderGscStats( data ) {
		$( '#csa-gsc-clicks'      ).text( ( data.clicks      || 0 ).toLocaleString() );
		$( '#csa-gsc-impressions' ).text( ( data.impressions  || 0 ).toLocaleString() );
		$( '#csa-gsc-ctr'         ).text( ( data.ctr          || 0 ).toFixed( 1 ) + '%' );
		$( '#csa-gsc-position'    ).text( ( data.position     || 0 ).toFixed( 1 ) );
		$( '#csa-gsc-stats' ).show();

		if ( data.daily && data.daily.length ) {
			$( '#csa-gsc-chart-wrap' ).show();
			var labels = data.daily.map( function ( d ) { return d.date; } );
			var clicks = data.daily.map( function ( d ) { return d.clicks; } );
			var impr   = data.daily.map( function ( d ) { return d.impressions; } );
			var ctx    = document.getElementById( 'csa-gsc-chart' ).getContext( '2d' );

			if ( gscChart ) { gscChart.destroy(); }
			gscChart = new Chart( ctx, {
				type: 'line',
				data: {
					labels: labels,
					datasets: [
						{
							label: 'Clicks',
							data: clicks,
							borderColor: '#2563eb',
							backgroundColor: 'rgba(37,99,235,0.08)',
							tension: 0.3, pointRadius: 0, fill: true,
						},
						{
							label: 'Impressions',
							data: impr,
							borderColor: '#10b981',
							backgroundColor: 'rgba(16,185,129,0.06)',
							tension: 0.3, pointRadius: 0, fill: true, yAxisID: 'y2',
						},
					],
				},
				options: {
					responsive: true, maintainAspectRatio: false,
					interaction: { intersect: false, mode: 'index' },
					plugins: { legend: { position: 'top', labels: { boxWidth: 12, font: { size: 11 } } } },
					scales: {
						x:  { ticks: { maxTicksLimit: 7, font: { size: 11 } }, grid: { display: false } },
						y:  { position: 'left',  ticks: { font: { size: 11 } } },
						y2: { position: 'right', ticks: { font: { size: 11 } }, grid: { drawOnChartArea: false } },
					},
				},
			} );
		}
	}

	function loadGscOverview() {
		post( 'forme_seo_gsc_overview' )
			.done( function ( res ) {
				if ( ! res.success || ! res.data || ! res.data.overview ) {
					return;
				}

				var overview = res.data.overview;

				$( '#csa-gsc-connect-state' ).hide();
				$( '#csa-gsc-connected-state' ).show();
				$( '#csa-gsc-stats' ).show();

				$( '#csa-gsc-badge' )
					.text( 'Connected' )
					.removeClass( 'csa-badge--warning' )
					.addClass( 'csa-badge--success' );

				$( '#csa-gsc-clicks' ).text( overview.clicks || 0 );
				$( '#csa-gsc-impressions' ).text( overview.impressions || 0 );
				$( '#csa-gsc-ctr' ).text( ( overview.ctr || '0.00' ) + '%' );
				$( '#csa-gsc-position' ).text( overview.position || '—' );
			} );
	}

	function loadGscProperties() {

		var $select = $( '#csa-gsc-property-select' );

		if ( ! $select.length ) {
			return;
		}

		$select.html( '<option value="">Loading properties…</option>' );

		post( 'forme_seo_gsc_properties' )
			.done( function ( res ) {

				if ( ! res.success ) {
					$select.html( '<option value="">Unable to load properties</option>' );
					return;
				}

				var properties = [];

				if ( res.data && Array.isArray( res.data.properties ) ) {
					properties = res.data.properties;
				}

				var current = formeSEOAgent.gscProperty || '';

				if ( ! properties.length ) {
					$select.html( '<option value="">No properties found</option>' );
					return;
				}

				var html = '<option value="">Select a property…</option>';

				properties.forEach( function ( p ) {

					var siteUrl = '';

					if ( typeof p === 'string' ) {
						siteUrl = p;
					} else if ( p && p.siteUrl ) {
						siteUrl = p.siteUrl;
					}

					if ( ! siteUrl ) {
						return;
					}

					var selected = siteUrl === current ? ' selected' : '';
					var label = siteUrl;

					if ( p.permissionLevel ) {
						label += ' (' + p.permissionLevel + ')';
					}

					html += '<option value="' + escHtml( siteUrl ) + '"' + selected + '>' +
						escHtml( label ) +
					'</option>';
				} );

				$select.html( html );

				// ── Existing selected property ─────────────────────

				if ( current ) {

					$select.val( current );

					$( '#csa-gsc-selected-note' )
						.text( 'Current property: ' + current );

					if ( typeof loadGscOverview === 'function' ) {
						loadGscOverview();
					}

					return;
				}

				// ── Auto-match current website ─────────────────────

				var homeUrl = '';

				if ( formeSEOAgent.homeUrl ) {
					homeUrl = formeSEOAgent.homeUrl;
				} else {
					homeUrl = window.location.origin;
				}

				var homeHost = '';

				try {
					homeHost = new URL( homeUrl )
						.hostname
						.replace( /^www\./, '' );
				} catch ( e ) {}

				if ( ! homeHost ) {
					return;
				}

				var matched = properties.find( function ( p ) {

					var siteUrl = '';

					if ( typeof p === 'string' ) {
						siteUrl = p;
					} else if ( p && p.siteUrl ) {
						siteUrl = p.siteUrl;
					}

					return (
						siteUrl === 'sc-domain:' + homeHost ||
						siteUrl.indexOf( homeHost ) !== -1
					);
				} );

				if ( matched && matched.siteUrl ) {

					$select.val( matched.siteUrl );

					post( 'forme_seo_gsc_select_property', {
						property: matched.siteUrl
					} )
						.done( function () {

							formeSEOAgent.gscProperty = matched.siteUrl;

							$( '#csa-gsc-selected-note' )
								.text( 'Auto-selected: ' + matched.siteUrl );

							toast( 'Search Console property auto-selected.', 'success' );

							if ( typeof loadGscOverview === 'function' ) {
								loadGscOverview();
							}
						} );
				}
			} )
			.fail( function () {
				$select.html( '<option value="">Network error loading properties</option>' );
			} );
	}

	$( document ).on( 'click', '#csa-gsc-save-property', function ( e ) {
		e.preventDefault();

		var property = $( '#csa-gsc-property-select' ).val();

		console.log( 'Selected GSC property:', property );

		if ( ! property ) {
			toast( 'Please select a Search Console property.', 'error' );
			return;
		}

		var $btn = $( this ).prop( 'disabled', true );

		post( 'forme_seo_gsc_select_property', {
			property: property
		} )
			.done( function ( res ) {
				console.log( 'Save property response:', res );

				if ( res.success ) {
					toast( 'Search Console property saved.', 'success' );
					$( '#csa-gsc-selected-note' ).text( 'Current property: ' + property );

					if ( typeof loadGscOverview === 'function' ) {
						loadGscOverview();
					}

					return;
				}

				toast(
					( res.data && res.data.message ) || 'Could not save property.',
					'error'
				);
			} )
			.fail( function ( xhr ) {
				console.log( 'Save property failed:', xhr.responseText );
				toast( 'Network error saving property.', 'error' );
			} )
			.always( function () {
				$btn.prop( 'disabled', false );
			} );
	} );

	$( document ).on( 'click', '#csa-gsc-reconnect-btn', function () {
		spinner( 'Reconnecting Google Search Console…' );

		post( 'forme_seo_gsc_auth_url', {
			return_url: window.location.href.split( '&gsc=' )[0]
		} )
			.done( function ( res ) {
				hideSpinner();

				if ( res.success && res.data.auth_url ) {
					window.location.href = res.data.auth_url;
					return;
				}

				toast( 'Could not start reconnection.', 'error' );
			} )
			.fail( function () {
				hideSpinner();
				toast( 'Network error starting reconnection.', 'error' );
			} );
	} );

	$( document ).on( 'click', '#csa-gsc-disconnect-btn', function () {
		if ( ! confirm( 'Disconnect Google Search Console?' ) ) {
			return;
		}

		post( 'forme_seo_gsc_disconnect' )
			.done( function ( res ) {
				if ( res.success ) {
					toast( 'Google Search Console disconnected.', 'success' );
					$( '#csa-gsc-property-select' ).html( '<option value="">Disconnected</option>' );
					$( '#csa-gsc-selected-note' ).text( '' );
					return;
				}

				toast( 'Could not disconnect.', 'error' );
			} )
			.fail( function () {
				toast( 'Network error disconnecting.', 'error' );
			} );
	} );

	if ( hasKey && $( '#csa-gsc-property-select' ).length ) {
		loadGscProperties();
	}

	function showGscConnected( selectedProperty ) {
		setGscBadge( true );
		$( '#csa-gsc-connect-state' ).hide();
		$( '#csa-gsc-connected-state' ).show();
		loadGscProperties( selectedProperty || '' );
	}

	if ( cfg.hasKey ) {
		if ( cfg.gscConnected && $( '#csa-card-ranking' ).length ) {
			showGscConnected( cfg.gscProperty || '' );
		}
		if ( window.location.search.indexOf( 'gsc=connected' ) !== -1 ) {
			toast( 'Google Search Console connected.', 'success' );

			if ( typeof refreshAccount === 'function' ) {
				refreshAccount();
			}

			if ( typeof loadGscProperties === 'function' ) {
				loadGscProperties();
			}
		}
	}

	$( '#csa-gsc-connect-btn' ).on( 'click', function () {
		var $btn = $( this ).prop( 'disabled', true ).text( 'Opening Google login…' );
		post( 'forme_seo_gsc_auth_url', { redirect: cfg.adminUrl } )
			.done( function ( res ) {
				if ( res.success && res.data.auth_url ) {
					window.location.href = res.data.auth_url;
				} else {
					toast( res.data && res.data.message || 'Could not get Google auth URL.', 'error' );
					$btn.prop( 'disabled', false ).text( 'Connect GSC' );
				}
			} )
			.fail( function () {
				toast( 'Network error.', 'error' );
				$btn.prop( 'disabled', false ).text( 'Connect GSC' );
			} );
	} );

	$( '#csa-gsc-set-property-btn' ).on( 'click', function () {
		var siteUrl = $( '#csa-gsc-property-select' ).val();
		if ( ! siteUrl ) { toast( 'Please select a property.', 'warning' ); return; }
		var $btn = $( this ).prop( 'disabled', true );
		post( 'forme_seo_gsc_select_property', { site_url: siteUrl } )
			.done( function ( res ) {
				$btn.prop( 'disabled', false );
				if ( res.success ) {
					toast( 'Property set: ' + escHtml( siteUrl ), 'success' );
					loadGscOverview();
				} else {
					toast( res.data && res.data.message || 'Could not set property.', 'error' );
				}
			} )
			.fail( function () { $btn.prop( 'disabled', false ); toast( 'Network error.', 'error' ); } );
	} );

	$( '#csa-gsc-disconnect-btn' ).on( 'click', function () {
		if ( ! window.confirm( 'Disconnect Google Search Console?' ) ) { return; }
		var $btn = $( this ).prop( 'disabled', true );
		post( 'forme_seo_gsc_disconnect' )
			.done( function ( res ) {
				$btn.prop( 'disabled', false );
				if ( res.success ) {
					setGscBadge( false );
					$( '#csa-gsc-connected-state' ).hide();
					$( '#csa-gsc-connect-state' ).show();
					$( '#csa-gsc-stats, #csa-gsc-chart-wrap' ).hide();
					if ( gscChart ) { gscChart.destroy(); gscChart = null; }
					toast( 'Google Search Console disconnected.', 'info' );
				} else {
					toast( res.data && res.data.message || 'Could not disconnect.', 'error' );
				}
			} )
			.fail( function () { $btn.prop( 'disabled', false ); toast( 'Network error.', 'error' ); } );
	} );

	// ── Settings page ─────────────────────────────────────────────────────────

	$( '#csa-save-btn' ).on( 'click', function () {
		spinner( 'Saving settings…' );
		post( 'forme_seo_save_settings', {
			api_base: $( '#csa-s-api-base' ).val().trim(),
			api_key:  $( '#csa-s-api-key'  ).val().trim(),
			email:    $( '#csa-s-email'     ).val().trim(),
		} )
		.done( function ( res ) {
			hideSpinner();
			toast(
				res.success ? 'Settings saved.' : ( res.data && res.data.message ) || 'Error saving settings.',
				res.success ? 'success' : 'error'
			);
		} )
		.fail( function () { hideSpinner(); toast( 'Network error.', 'error' ); } );
	} );

	$( '#csa-test-settings-btn' ).on( 'click', function () {
		spinner( 'Testing connection…' );
		post( 'forme_seo_test_connection', {
			api_base: $( '#csa-s-api-base' ).val().trim(),
			api_key:  $( '#csa-s-api-key'  ).val().trim(),
		} )
		.done( function ( res ) {
			hideSpinner();
			if ( res.success ) {
				toast( 'Connected! Account: ' + escHtml( ( res.data.me && res.data.me.email ) || 'OK' ), 'success' );
			} else {
				toast( friendlyError( res.data && res.data.code, res.data && res.data.message ), 'error' );
			}
		} )
		.fail( function () { hideSpinner(); toast( 'Network error.', 'error' ); } );
	} );

	var keyShown = false;
	$( '#csa-key-reveal' ).on( 'click', function () {
		keyShown = ! keyShown;
		$( '#csa-s-api-key' ).attr( 'type', keyShown ? 'text' : 'password' );
		$( this ).text( keyShown ? 'Hide' : 'Reveal' );
	} );

	$( '#csa-key-replace' ).on( 'click', function () {
		$( '#csa-s-api-key' ).val( '' ).attr( 'type', 'text' ).trigger( 'focus' );
		keyShown = true;
		$( '#csa-key-reveal' ).text( 'Hide' );
	} );

	$( '#csa-clear-key-btn' ).on( 'click', function () {
		if ( ! window.confirm( 'Clear your API key? You will need to re-enter or create a new one.' ) ) {
			return;
		}
		spinner( 'Clearing API key…' );
		post( 'forme_seo_save_settings', { clear_key: 1 } )
			.done( function ( res ) {
				hideSpinner();
				if ( res.success && res.data.cleared ) {
					location.reload();
				}
			} )
			.fail( function () { hideSpinner(); toast( 'Network error.', 'error' ); } );
	} );

	// ── Website Audit page ────────────────────────────────────────────────────

	function initWebsiteAudit() {
		loadAuditHistory();
		loadSiteProfileBadge();

		$( '#csa-run-audit-btn' ).on( 'click', function () {
			var url = $( '#csa-audit-url' ).val().trim();
			if ( ! url ) { toast( 'Please enter a URL.', 'error' ); return; }

			var $btn = $( this ).prop( 'disabled', true );
			$( '#csa-audit-progress' ).show();
			$( '#csa-audit-result-card' ).hide();

			post( 'forme_seo_start_audit_async', { url: url } )
				.done( function ( res ) {
					if ( ! res.success ) {
						$( '#csa-audit-progress' ).hide();
						$btn.prop( 'disabled', false );
						toast( friendlyError( res.data && res.data.code, res.data && res.data.message ), 'error' );
						return;
					}

					toast( 'Audit queued. History will update automatically.', 'success' );
					$( '#csa-audit-loading-msg' ).text( 'Audit queued. Waiting for server...' );

					loadAuditHistory();

					setTimeout( function () {
						$btn.prop( 'disabled', false );
					}, 1200 );
				} )
				.fail( function () {
					$( '#csa-audit-progress' ).hide();
					$btn.prop( 'disabled', false );
					toast( 'Could not queue audit.', 'error' );
				} );
		} );

		$( '#csa-audit-history-refresh' ).on( 'click', loadAuditHistory );

		$( '#csa-audit-clear-btn' ).on( 'click', function () {
			$( '#csa-audit-result-card' ).hide();
		} );

		$( '#csa-audit-copy-btn' ).on( 'click', function () {
			var txt = $( '#csa-audit-report-body' ).text();
			navigator.clipboard ? navigator.clipboard.writeText( txt ) : copyFallback( txt );
			toast( 'Copied to clipboard.', 'success' );
		} );
	}

	function loadSiteProfileBadge() {
		post( 'forme_seo_get_site_profile' )
			.done( function ( res ) {
				if ( res.success && res.data && res.data.industry ) {
					$( '#csa-audit-industry-badge' ).text( res.data.industry ).show();
				}
			} );
	}

	var _auditHistoryPoller = null;

	function _stopAuditHistoryPoller() {
		if ( _auditHistoryPoller ) { clearInterval( _auditHistoryPoller ); _auditHistoryPoller = null; }
	}

	function loadAuditHistory() {
		post( 'forme_seo_get_local_audit_jobs', { limit: 10 } )
			.done( function ( res ) {
				if ( ! res.success ) return;

				var jobs = res.data.jobs || [];

				if ( ! jobs.length ) {
					$( '#csa-audit-history-list' ).html(
						'<div class="csa-empty-state"><i class="lni lni-files"></i><p>No audits yet.</p></div>'
					);
					_stopAuditHistoryPoller();
					return;
				}

				var html = '<table class="csa-job-table"><thead><tr><th>Date</th><th>URL</th><th>Score</th><th>Status</th><th>Message</th></tr></thead><tbody>';
				var hasActive = false;

				jobs.forEach( function ( j ) {
					var score  = j.score || '—';
					var date   = j.created_at ? j.created_at.slice( 0, 19 ) : '—';
					var url    = j.input_url ? escHtml( j.input_url ) : '—';
					var status = j.status || '—';

					if ( status === 'queued' || status === 'running' ) {
						hasActive = true;
					}

					var statusDisplay = ( status === 'queued' || status === 'running' )
						? '<span class="csa-badge csa-status--' + escHtml( status ) + '"><span class="csa-spinner-xs"></span> ' + escHtml( status ) + '</span>'
						: '<span class="csa-badge csa-status--' + escHtml( status ) + '">' + escHtml( status ) + '</span>';

					html += '<tr data-job-id="' + escHtml( j.job_id ) + '" data-job-status="' + escHtml( status ) + '">' +
						'<td>' + escHtml( date ) + '</td>' +
						'<td><small>' + url + '</small></td>' +
						'<td>' + escHtml( String( score ) ) + '</td>' +
						'<td>' + statusDisplay + '</td>' +
						'<td><small>' + escHtml( j.message || '' ) + '</small></td>' +
					'</tr>';
				} );

				html += '</tbody></table>';
				$( '#csa-audit-history-list' ).html( html );

				if ( hasActive && ! _auditHistoryPoller ) {
					_auditHistoryPoller = setInterval( loadAuditHistory, 4000 );
				}

				if ( ! hasActive ) {
					_stopAuditHistoryPoller();
					$( '#csa-audit-progress' ).hide();
				}
			} );
	}

	function renderAuditResult( data ) {
		var score  = data.score || 0;
		var summ   = data.summary || '';
		var issues = data.issues  || [];
		var wins   = data.quick_wins || [];

		var html = '<div class="csa-report-grid">';
		html += '<div class="csa-report-left">';
		html += '<div class="csa-score-circle" style="--score-color:' + scoreColor( score ) + '">' + score + '</div>';
		html += '</div>';
		html += '<div class="csa-report-right">';
		if ( summ ) html += '<p style="margin-bottom:12px;">' + escHtml( summ ) + '</p>';

		if ( issues.length ) {
			html += '<h4 style="font-size:13px;font-weight:600;margin-bottom:6px;">Top Issues</h4><ul class="csa-issue-list">';
			issues.slice( 0, 5 ).forEach( function ( iss ) {
				html += '<li><span class="csa-sev-dot csa-sev-dot--' + escHtml( iss.severity || 'low' ) + '"></span> ' + escHtml( iss.description || iss.title || '' ) + '</li>';
			} );
			html += '</ul>';
		}
		if ( wins.length ) {
			html += '<h4 style="font-size:13px;font-weight:600;margin:12px 0 6px;">Quick Wins</h4><ul class="csa-issue-list">';
			wins.slice( 0, 3 ).forEach( function ( w ) {
				html += '<li>' + escHtml( w ) + '</li>';
			} );
			html += '</ul>';
		}
		html += '</div></div>';

		$( '#csa-audit-report-body' ).html( html );
		$( '#csa-audit-result-card' ).show();
		$( '#csa-audit-next-step' ).show();
	}

	// ── Content Plan page ─────────────────────────────────────────────────────

	var planData     = null;
	var strategyData = null;
	var calendarData = null;

	function initContentPlan() {
		loadContentPlanState();

		$( '#csa-generate-strategy-btn' ).on( 'click', function () {
			var $btn = $( this ).prop( 'disabled', true );

			$( '#csa-strategy-progress' ).show();
			$( '#csa-strategy-result' ).hide();
			$( '#csa-calendar-result' ).hide();

			$( '#csa-strategy-progress-bar' ).css( 'width', '15%' );
			$( '#csa-strategy-loading-msg' ).text( 'Generating blog plan…' );

			var industry = $( '#csa-plan-industry-tag' ).text().trim() || '';

			// If tag is generic, try extracting from latest audit report.
			if (
				! industry ||
				industry === 'Detected from latest audit' ||
				industry.length > 160
			) {
				var latestAudit = _reportCache && _reportCache.find( function ( r ) {
					return r.tool === 'audit' && r.status === 'completed';
				} );

				var raw =
					latestAudit &&
					latestAudit.result &&
					latestAudit.result.raw
						? latestAudit.result.raw
						: '';

				industry = extractBusinessTypeFromAudit( raw ) || 'Local Service';
			}

			var nicheParts = [
				industry,
				$( '#csa-strategy-audience' ).val().trim(),
				$( '#csa-strategy-location' ).val().trim(),
				$( '#csa-strategy-goals' ).val().trim()
			].filter( Boolean );

			var niche = nicheParts.join( ' | ' );

			if ( niche.length > 500 ) {
				niche = [
					industry,
					$( '#csa-strategy-location' ).val().trim(),
					$( '#csa-strategy-goals' ).val().trim()
				].filter( Boolean ).join( ' | ' ).substring( 0, 500 );
			}

			var startDate = $( '#csa-cal-start-date' ).val() || new Date().toISOString().slice( 0, 10 );

			var payload = {
				niche: niche,
				quarter: $( '#csa-cal-quarter' ).val() || 'Q2',
				frequency: parseInt( $( '#csa-cal-frequency' ).val(), 10 ) || 2,
				months: parseInt( $( '#csa-cal-months' ).val(), 10 ) || 3,
				start_date: startDate
			};

			post( 'forme_seo_run_blog_strategy', payload )
				.done( function ( res ) {
					if ( ! res.success ) {
						$( '#csa-strategy-progress' ).hide();
						$btn.prop( 'disabled', false );

						toast(
							friendlyError(
								res.data && res.data.code,
								res.data && res.data.message
							),
							'error'
						);

						return;
					}

					var d = res.data || {};

					function done( result ) {
						$( '#csa-strategy-progress-bar' ).css( 'width', '100%' );
						$( '#csa-strategy-loading-msg' ).text( 'Blog plan ready.' );

						setTimeout( function () {
							$( '#csa-strategy-progress' ).hide();
						}, 400 );

						$btn.prop( 'disabled', false );

						strategyData = result;
						calendarData = result;

						renderBlogPlan( result );

						unlockStep( 3 );
						loadContentPlanState();

						toast( 'Blog plan generated.', 'success' );
					}

					if ( d.job_id && d.status === 'queued' ) {
						pollJob(
							d.job_id,
							done,
							function ( err ) {
								$( '#csa-strategy-progress' ).hide();
								$btn.prop( 'disabled', false );
								toast( err || 'Blog plan generation failed.', 'error' );
							},
							function ( pct, msg ) {
								$( '#csa-strategy-progress-bar' ).css( 'width', pct + '%' );
								$( '#csa-strategy-loading-msg' ).text( msg || 'Generating blog plan…' );
							}
						);

						return;
					}

					done( d );
				} )
				.fail( function () {
					$( '#csa-strategy-progress' ).hide();
					$btn.prop( 'disabled', false );

					toast(
						'Blog plan is still generating. I’ll check Reports shortly.',
						'warning'
					);

					setTimeout( function () {
						loadContentPlanState();

						getLatestReport( 'blog_strategy', function ( report ) {
							if ( report ) {
								renderBlogPlan( report );
								unlockStep( 3 );
								toast( 'Blog plan completed and loaded.', 'success' );
							}
						} );
					}, 8000 );
				} );
		} );


		$( '#csa-generate-calendar-btn' ).on( 'click', function () {
			var $btn = $( this ).prop( 'disabled', true );
			$( '#csa-calendar-progress' ).show();
			$( '#csa-calendar-result' ).hide();

			var payload = {
				url:       formeSEOAgent.homeUrl,
				quarter:   $( '#csa-cal-quarter' ).val(),
				frequency: parseInt( $( '#csa-cal-frequency' ).val(), 10 ),
				months:    parseInt( $( '#csa-cal-months' ).val(), 10 ),
			};

			post( 'forme_seo_run_blog_calendar', payload )
				.done( function ( res ) {
					if ( ! res.success ) {
						$( '#csa-calendar-progress' ).hide();
						$btn.prop( 'disabled', false );
						toast( friendlyError( res.data && res.data.code, res.data && res.data.message ), 'error' );
						return;
					}
					var d = res.data;
					if ( d.job_id && d.status === 'queued' ) {
						pollJob( d.job_id,
							function ( result ) {
								$( '#csa-calendar-progress' ).hide();
								$btn.prop( 'disabled', false );
								calendarData = result;
								renderCalendar( result );
							},
							function ( err ) {
								$( '#csa-calendar-progress' ).hide();
								$btn.prop( 'disabled', false );
								toast( err || 'Calendar generation failed.', 'error' );
							},
							function ( pct, msg ) {
								$( '#csa-calendar-progress-bar' ).css( 'width', pct + '%' );
								$( '#csa-calendar-loading-msg' ).text( msg || 'Building…' );
							}
						);
					} else {
						$( '#csa-calendar-progress' ).hide();
						$btn.prop( 'disabled', false );
						calendarData = d;
						renderCalendar( d );
					}
				} )
				.fail( function () {
					$( '#csa-calendar-progress' ).hide();
					$btn.prop( 'disabled', false );
					toast( 'Network error.', 'error' );
				} );
		} );

		$( '#csa-add-to-queue-btn' ).on( 'click', function () {
			if ( ! calendarData ) return;
			var entries = calendarData.entries || calendarData.topics || calendarData.calendar || [];
			if ( ! entries.length ) { toast( 'No topics found in calendar.', 'error' ); return; }

			var $btn = $( this ).prop( 'disabled', true );
			spinner( 'Saving article queue…' );

			post( 'forme_seo_get_content_projects' )
				.done( function ( res ) {
					if ( res.success && res.data && res.data.projects && res.data.projects.length ) {
						hideSpinner();
						$btn.prop( 'disabled', false );
						toast( entries.length + ' topics already queued. View Articles to manage them.', 'success' );
					} else {
						hideSpinner();
						$btn.prop( 'disabled', false );
						toast( 'No project found. Generate a plan first.', 'error' );
					}
				} )
				.fail( function () {
					hideSpinner();
					$btn.prop( 'disabled', false );
					toast( 'Network error.', 'error' );
				} );
		} );
	}

	function extractBusinessTypeFromAudit( raw ) {
		raw = String( raw || '' );

		var match =
			raw.match( /Business Type:\s*([^\n\r]+)/i ) ||
			raw.match( /Business\/Industry:\s*([^\n\r]+)/i ) ||
			raw.match( /Industry:\s*([^\n\r]+)/i ) ||
			raw.match( /Niche:\s*([^\n\r]+)/i );

		if ( match && match[1] ) {
			return match[1]
				.replace( /\s*Audited Pages:.*/i, '' )
				.replace( /\s*Date:.*/i, '' )
				.trim();
		}

		return '';
	}

	function getRawResult( data ) {
		if ( ! data ) {
			return '';
		}

		if ( typeof data === 'string' ) {
			return data;
		}

		if ( data.result && data.result.raw ) {
			return data.result.raw;
		}

		if ( data.result && typeof data.result === 'string' ) {
			return data.result;
		}

		if ( data.raw ) {
			return data.raw;
		}

		if ( data.report && data.report.result && data.report.result.raw ) {
			return data.report.result.raw;
		}

		return '';
	}

	function renderBlogPlan( data ) {
		var raw = getRawResult( data );

		raw = cleanAiFooter( raw );

		if ( ! raw ) {
			$( '#csa-strategy-result' )
				.html( '<div class="csa-empty-state csa-empty-state--sm"><p>No blog plan found.</p></div>' )
				.show();

			return;
		}

		var topicsHtml = renderBlogPlanSection( raw, 'Article Topics' );
		var calendarHtml = renderBlogPlanSection( raw, 'Editorial Calendar' );

		$( '#csa-strategy-result' )
			.html(
				'<div class="csa-strategy-preview">' +
					'<div class="csa-strategy-preview__head">' +
						'<div>' +
							'<h3>Article Topics</h3>' +
							'<p>Generated from your blog plan.</p>' +
						'</div>' +
					'</div>' +
					topicsHtml +
				'</div>'
			)
			.show();

		$( '#csa-calendar-result' )
			.show();

		$( '#csa-calendar-table-wrap' )
			.html(
				'<div class="csa-strategy-preview">' +
					'<div class="csa-strategy-preview__head">' +
						'<div>' +
							'<h3>Editorial Calendar</h3>' +
							'<p>Scheduled dates from your blog plan.</p>' +
						'</div>' +
					'</div>' +
					calendarHtml +
				'</div>'
			);
	}

	function renderBlogPlanSection( raw, heading ) {

		var re = new RegExp(
			'##\\s+' + heading + '([\\s\\S]*?)(?=\\n##\\s+|$)',
			'i'
		);

		var match = String( raw || '' ).match( re );

		if ( ! match ) {

			return (
				'<div class="csa-empty-state csa-empty-state--sm">' +
					'<p>No ' + escHtml( heading ) + ' found.</p>' +
				'</div>'
			);

		}

		return (
			'<div class="csa-strategy-excerpt">' +
				markdownToHtml(
					cleanAiFooter(
						'## ' + heading + match[1]
					)
				) +
			'</div>'
		);

	}

	function renderCalendarTableFromRaw( raw ) {
		var match = String( raw || '' ).match( /## Editorial Calendar([\s\S]*)$/i );

		if ( ! match ) {
			return '<div class="csa-empty-state csa-empty-state--sm"><p>No calendar found in blog plan.</p></div>';
		}

		return markdownToHtml( '## Editorial Calendar' + match[1] );
	}

	function renderBlogPlanSection( raw, heading ) {
		var re = new RegExp(
			'##\\s+' + heading + '([\\s\\S]*?)(?=\\n##\\s+|$)',
			'i'
		);

		var match = String( raw || '' ).match( re );

		if ( ! match ) {
			return '<div class="csa-empty-state csa-empty-state--sm"><p>No ' + escHtml( heading ) + ' found.</p></div>';
		}

		return '<div class="csa-strategy-excerpt">' +
			markdownToHtml( '## ' + heading + match[1] ) +
		'</div>';
	}

	function loadContentPlanState() {
		_reportCache = null;

		getReports( function ( reports ) {
			var audit = reports.find( function ( r ) {
				return r.tool === 'audit' && r.status === 'completed';
			} );

			var strategy = reports.find( function ( r ) {
				return r.tool === 'blog_strategy' && r.status === 'completed';
			} );

			if ( ! audit ) {
				$( '#csa-plan-no-audit' ).show();
				$( '#csa-plan-step1' ).hide();
				return;
			}

			$( '#csa-plan-no-audit' ).hide();
			$( '#csa-plan-step1' ).show();

			var industry =
				audit.business_type ||
				( audit.result && audit.result.metadata && audit.result.metadata.business_type ) ||
				'Detected from latest audit';

			$( '#csa-plan-industry-tag' ).text( industry ).show();

			$( '#csa-plan-step1-desc' ).text(
				'SEO roadmap generated from your latest website audit.'
			);

			unlockStep( 2 );

			if ( audit && audit.result && audit.result.raw ) {
				renderAuditRoadmapPreview( audit );
			}

			if ( strategy ) {
				unlockStep( 3 );
				renderBlogStrategyPreview( strategy );
			}
		} );
	}

	function renderAuditRoadmapPreview( report ) {
		var raw = report.result && report.result.raw ? report.result.raw : '';

		if ( raw.indexOf( 'Phase 1' ) === -1 && raw.indexOf( '4-Phase' ) === -1 ) {
			return;
		}

		$( '#csa-plan-roadmap' )
			.html(
				'<div class="csa-roadmap-preview">' +
					'<div class="csa-roadmap-preview-head">' +
						'<div>' +
							'<h3>SEO Roadmap from Latest Audit</h3>' +
							'<p>Generated ' + escHtml( report.created_at || '' ) + '</p>' +
						'</div>' +
						'<button type="button" class="csa-btn csa-btn--outline csa-btn--sm csa-view-report-btn" ' +
							'data-report-id="' + escHtml( report.id ) + '" ' +
							'data-tool="' + escHtml( report.tool ) + '">' +
							'<i class="lni lni-eye"></i> View Full Audit' +
						'</button>' +
					'</div>' +
					renderRoadmapExcerpt( raw ) +
				'</div>'
			)
			.show();
	}

	function renderContentPlanPreview( report ) {
		var raw = report.result && report.result.raw ? report.result.raw : '';

		var roadmapHtml = renderRoadmapExcerpt( raw );
		var keywordHtml = renderKeywordStrategyPreview( raw );
		var calendarHtml = renderCalendarPreviewFromPlan( raw );

		$( '#csa-plan-roadmap' )
			.html(
				'<div class="csa-roadmap-preview">' +
					'<div class="csa-roadmap-preview-head">' +
						'<div>' +
							'<h3>Latest SEO Roadmap</h3>' +
							'<p>Generated ' + escHtml( report.created_at || '' ) + '</p>' +
						'</div>' +
						'<button type="button" class="csa-btn csa-btn--outline csa-btn--sm csa-view-report-btn" ' +
							'data-report-id="' + escHtml( report.id ) + '" ' +
							'data-tool="' + escHtml( report.tool ) + '">' +
							'<i class="lni lni-eye"></i> View Full Plan' +
						'</button>' +
					'</div>' +
					renderRoadmapExcerpt( raw ) +
				'</div>'
			)
			.show();

		// Step 2: Blog Strategy preview
		if ( keywordHtml ) {
			unlockStep( 2 );

			$( '#csa-blog-strategy-preview' )
				.html( keywordHtml )
				.show();
		}

		// Step 3: Editorial Calendar preview
		if ( calendarHtml ) {
			unlockStep( 3 );

			$( '#csa-editorial-calendar-preview' ).html( calendarHtml ).show();
		}
	}

	function renderCalendarPreviewFromPlan( raw ) {
		var src = String( raw || '' );
		var match = src.match(
			/(?:^|\n)7\.\s+Content Calendar[\s\S]*?(?=\n8\.|\n\d+\.\s+E-E-A-T|$)/i
		);

		if ( ! match ) {
			return '';
		}

		return '<div class="csa-strategy-preview">' +
			'<div class="csa-strategy-preview__head">' +
				'<div>' +
					'<h3>Editorial Calendar</h3>' +
					'<p>Extracted from latest SEO Plan</p>' +
				'</div>' +
			'</div>' +
			'<div class="csa-strategy-excerpt">' +
				markdownToHtml( cleanAiFooter( match[0] ) ) +
			'</div>' +
		'</div>';
	}

	function renderRoadmapExcerpt( raw ) {
		var src = String( raw || '' );

		var phases = [
			{ key: 'Phase 1', n: 1 },
			{ key: 'Phase 2', n: 2 },
			{ key: 'Phase 3', n: 3 },
			{ key: 'Phase 4', n: 4 }
		];

		function extractPhase( phaseNo ) {
			var rx = new RegExp(
				'(?:^|\\n)(?:#+\\s*)?' + phaseNo + '[^\\n]*\\n([\\s\\S]*?)(?=\\n(?:#+\\s*)?Phase\\s+[1-4]\\b|\\n\\d+\\.\\s+[A-Z]|$)',
				'i'
			);
			var match = src.match( rx );
			return match ? match[1].trim() : '';
		}

		function extractItems( text ) {
			var items = [];
			String( text || '' ).split( '\n' ).forEach( function ( line ) {
				var t = line.trim();
				if ( ! t || t.indexOf( '---' ) > -1 ) return;

				if ( /^\|/.test( t ) ) {
					var cols = t.split( '|' ).map( function ( c ) { return c.trim(); } ).filter( Boolean );
					if ( cols.length >= 2 && ! /^(Action|Goal|Phase|Timeline)$/i.test( cols[0] ) ) {
						items.push( { title: cols[0], meta: cols[1] || '' } );
					}
					return;
				}

				if ( /^[-*]\s+/.test( t ) || /^\d+\.\s+/.test( t ) ) {
					items.push( { title: cleanListItem( t ), meta: '' } );
				}
			} );
			return items.slice( 0, 6 );
		}

		var html = '<div class="csa-roadmap-grid">';

		phases.forEach( function ( phase ) {
			var section  = extractPhase( phase.key );
			var items    = extractItems( section );

			var headingMatch = src.match( new RegExp( phase.key + '[^\\n]*', 'i' ) );
			var heading      = headingMatch ? headingMatch[0].trim().replace( /^#+\s*/, '' ) : phase.key;

			// Extract subtitle (text between "Phase X — " and "(timeframe)")
			var subtitle = heading
				.replace( /^Phase\s+\d+\s*[—–\-]\s*/i, '' )
				.replace( /\s*\(.*?\)\s*/g, '' )
				.replace( /\s*:.*/, '' )
				.trim();

			// Extract timeframe from parens
			var timeMatch = heading.match( /\(([^)]+)\)/ );
			var timeframe = timeMatch ? timeMatch[1] : '';

			html += '<div class="csa-roadmap-phase-card" data-phase="' + phase.n + '">' +
				'<div class="csa-roadmap-phase-top">' +
					'<span class="csa-roadmap-phase-badge">' + escHtml( phase.key ) + '</span>' +
					( timeframe ? '<span class="csa-roadmap-phase-time">' + escHtml( timeframe ) + '</span>' : '' ) +
				'</div>';

			if ( subtitle && subtitle !== phase.key ) {
				html += '<div class="csa-roadmap-phase-title">' + escHtml( subtitle ) + '</div>';
			}

			if ( items.length ) {
				html += '<ul class="csa-roadmap-mini-list">';
				items.forEach( function ( item ) {
					html += '<li>' +
						'<span class="csa-roadmap-check" aria-hidden="true"></span>' +
						'<span class="csa-roadmap-item-text">' + escHtml( item.title ) + '</span>' +
						( item.meta ? '<em class="csa-roadmap-item-meta">' + escHtml( item.meta ) + '</em>' : '' ) +
					'</li>';
				} );
				html += '</ul>';
			} else {
				html += '<p class="csa-muted" style="font-size:12px;margin-top:10px;">No items found.</p>';
			}

			html += '</div>';
		} );

		html += '</div>';
		return html;
	}

	function renderPhaseList( text ) {
		var html = '';
		var current = '';

		String( text || '' ).split( '\n' ).forEach( function ( line ) {
			var t = line.trim();

			if ( ! t ) {
				return;
			}

			var phase = t.match( /^Phase\s+\d+:\s+(.+)/i );

			if ( phase ) {
				if ( current ) {
					html += '</ul></div>';
				}

				current = phase[0];

				html += '<div class="csa-roadmap-phase">' +
					'<h4>' + escHtml( current ) + '</h4>' +
					'<ul>';

				return;
			}

			if ( current && /^\[\s*\]\s+/.test( t ) ) {
				html += '<li>' + escHtml( t.replace( /^\[\s*\]\s+/, '' ) ) + '</li>';
			}
		} );

		if ( current ) {
			html += '</ul></div>';
		}

		if ( ! html ) {
			return '<div class="csa-strategy-excerpt">' +
				markdownToHtml( cleanAiFooter( text ) ) +
			'</div>';
		}

		return html;
	}

	function renderKeywordStrategyPreview( raw ) {
		var src = String( raw || '' );
		var match = src.match(
			/(?:^|\n)2\.\s+Keyword Strategy([\s\S]*?)(?:\n3\.|\n\d+\.\s+Site Architecture|$)/i
		);

		if ( ! match ) {
			return '';
		}

		return '<div class="csa-strategy-preview">' +
			'<div class="csa-strategy-preview__head">' +
				'<div>' +
					'<h3>Keyword & Blog Strategy</h3>' +
					'<p>Extracted from latest SEO Plan</p>' +
				'</div>' +
			'</div>' +
			'<div class="csa-strategy-excerpt">' +
				markdownToHtml(
					cleanAiFooter( 'Keyword Strategy' + match[1] )
				) +
			'</div>' +
		'</div>';
	}

	function unlockStep( step ) {
		if ( step >= 2 ) $( '#csa-plan-step2' ).css( { opacity: 1, 'pointer-events': 'auto' } );
		if ( step >= 3 ) $( '#csa-plan-step3' ).css( { opacity: 1, 'pointer-events': 'auto' } );
	}

	function renderRoadmap( data ) {
		var phases = [
			{ label: 'Phase 1', title: 'Foundation',  timeline: 'Weeks 1–4',   items: [ 'Technical setup', 'Core pages', 'Essential schema', 'Analytics & tracking' ] },
			{ label: 'Phase 2', title: 'Expansion',   timeline: 'Weeks 5–12',  items: [ 'Blog launch', 'Primary content creation', 'Internal linking', 'Local SEO setup' ] },
			{ label: 'Phase 3', title: 'Scale',       timeline: 'Weeks 13–24', items: [ 'Advanced content', 'Link building & outreach', 'GEO optimisation', 'Performance tuning' ] },
			{ label: 'Phase 4', title: 'Authority',   timeline: 'Months 7–12', items: [ 'Thought leadership', 'PR & media mentions', 'Advanced schema', 'Continuous optimisation' ] },
		];

		if ( data && data.metadata && data.metadata.phases ) {
			phases = data.metadata.phases;
		}

		var html = '';
		phases.forEach( function ( ph ) {
			var items = Array.isArray( ph.items ) ? ph.items : ( ph.focus || [] );
			html += '<div class="csa-roadmap-phase">' +
				'<div class="csa-roadmap-phase__label">' + escHtml( ph.label || '' ) + '</div>' +
				'<div class="csa-roadmap-phase__title">' + escHtml( ph.title || '' ) + '</div>' +
				'<div class="csa-roadmap-phase__timeline">' + escHtml( ph.timeline || '' ) + '</div>' +
				'<ul class="csa-roadmap-phase__items">';
			items.forEach( function ( item ) {
				html += '<li>' + escHtml( typeof item === 'string' ? item : ( item.text || item.label || '' ) ) + '</li>';
			} );
			html += '</ul></div>';
		} );

		$( '#csa-roadmap-phases' ).html( html );
		$( '#csa-plan-roadmap' ).show();
	}

	function renderStrategy( data ) {
		var pillars = data.primary_topics || data.content_pillars || data.pillars || [];
		var html    = '<div class="csa-strategy-result">';
		if ( data.summary ) html += '<p style="margin-bottom:12px;">' + escHtml( data.summary ) + '</p>';
		pillars.forEach( function ( p ) {
			var label = typeof p === 'string' ? p : ( p.topic || p.title || p.label || '' );
			var desc  = typeof p === 'object' ? ( p.description || p.subtopics || '' ) : '';
			html += '<div class="csa-strategy-pillar"><strong>' + escHtml( label ) + '</strong>';
			if ( desc ) html += '<span>' + escHtml( Array.isArray( desc ) ? desc.join( ', ' ) : desc ) + '</span>';
			html += '</div>';
		} );
		html += '</div>';
		$( '#csa-strategy-result' ).html( html ).show();
	}

	function renderCalendar( data ) {
		var entries = data.entries || data.topics || data.calendar || [];
		if ( ! entries.length ) {
			$( '#csa-calendar-table-wrap' ).html( '<p class="csa-muted">No calendar entries returned.</p>' );
			$( '#csa-calendar-result' ).show();
			return;
		}
		var html = '<table class="csa-calendar-table"><thead><tr>' +
			'<th>Week</th><th>Date</th><th>Topic</th><th>Intent</th><th>Cluster</th>' +
			'</tr></thead><tbody>';
		entries.forEach( function ( e ) {
			html += '<tr>' +
				'<td>' + escHtml( String( e.week || '—' ) ) + '</td>' +
				'<td>' + escHtml( e.publish_date || e.date || '—' ) + '</td>' +
				'<td>' + escHtml( e.topic || e.title || '—' ) + '</td>' +
				'<td>' + escHtml( e.intent || e.search_intent || '—' ) + '</td>' +
				'<td>' + escHtml( e.cluster || '—' ) + '</td>' +
				'</tr>';
		} );
		html += '</tbody></table>';
		$( '#csa-calendar-table-wrap' ).html( html );
		$( '#csa-calendar-result' ).show();
	}

	function getReportRaw( report ) {
		if ( ! report ) {
			return '';
		}

		if ( report.result && report.result.raw ) {
			return report.result.raw;
		}

		if ( report.result_json && report.result_json.raw ) {
			return report.result_json.raw;
		}

		if ( report.raw ) {
			return report.raw;
		}

		if ( typeof report.result === 'string' ) {
			return report.result;
		}

		return '';
	}

	function loadSeoHealthFromAudit() {
		getLatestReport( 'audit', function ( report ) {
			if ( ! report || ! report.id ) {
				renderEmptySeoHealth();
				renderDashboardQuickWinsFromAudit( [] );
				renderDashboardActionPlanFromAudit( [] );
				return;
			}

			post( 'forme_seo_get_report', {
				report_id: report.id
			} )
			.done( function ( res ) {
				if ( ! res.success ) {
					renderEmptySeoHealth();
					renderDashboardQuickWinsFromAudit( [] );
					renderDashboardActionPlanFromAudit( [] );
					return;
				}

				var fullReport = res.data || {};
				var raw = getReportRaw( fullReport );
				var data = parseSeoHealthFromAuditRaw( raw );

				if ( ! data ) {
					data = {};
				}

				data.summary =
					( fullReport.result && fullReport.result.summary ) ||
					fullReport.summary ||
					extractAuditSummary( raw );

				if ( report.created_at || fullReport.created_at ) {
					data.last_audit =
						'Last audit: ' +
						timeAgo( fullReport.created_at || report.created_at );
				}

				if ( data.score ) {
					renderSeoHealth( data );
				} else {
					renderEmptySeoHealth();
				}

				renderDashboardQuickWinsFromAudit(
					parseQuickWins( raw )
				);

				renderDashboardActionPlanFromAudit(
					parseAuditActionPlan( raw )
				);
			} )
			.fail( function () {
				renderEmptySeoHealth();
				renderDashboardQuickWinsFromAudit( [] );
				renderDashboardActionPlanFromAudit( [] );
			} );
		} );
	}

	function renderDashboardQuickWinsFromAudit( items ) {
		if ( ! items || ! items.length ) {
			$( '#csa-qw-list' ).html(
				'<div class="csa-empty-state csa-empty-state--sm"><p>No quick wins found in latest audit.</p></div>'
			);
			return;
		}

		var html = '<div class="csa-qw-list-inner">';
		items.slice( 0, 5 ).forEach( function ( item, i ) {
			html +=
				'<div class="csa-qw-row">' +
					'<span class="csa-qw-num">' + ( i + 1 ) + '</span>' +
					'<span class="csa-qw-text">' + escHtml( item ) + '</span>' +
				'</div>';
		} );
		html += '</div>';
		$( '#csa-qw-list' ).html( html );
	}

	function renderDashboardActionPlanFromAudit( items ) {
		if ( ! items || ! items.length ) {
			$( '#csa-task-list' ).html(
				'<div class="csa-empty-state csa-empty-state--sm"><p>No action plan found in latest audit.</p></div>'
			);
			return;
		}

		var priorities = [ 'high', 'high', 'medium', 'medium', 'medium' ];
		var html = '<div class="csa-ap-list">';

		items.slice( 0, 5 ).forEach( function ( item, i ) {
			var pri = priorities[ i ] || 'medium';
			html +=
				'<div class="csa-ap-row csa-ap-row--' + pri + '">' +
					'<span class="csa-ap-num csa-ap-num--' + pri + '">' + ( i + 1 ) + '</span>' +
					'<span class="csa-ap-text">' + escHtml( item ) + '</span>' +
					'<span class="csa-ap-tag csa-ap-tag--' + pri + '">' + ( pri === 'high' ? 'High' : 'Mid' ) + '</span>' +
				'</div>';
		} );

		html += '</div>';
		$( '#csa-task-list' ).html( html );
	}

	function timeAgo( dateStr ) {

		var diff =
			Math.floor(
				( Date.now() - new Date( dateStr ).getTime() ) / 1000
			);

		if ( diff < 60 ) {
			return 'just now';
		}

		if ( diff < 3600 ) {
			return Math.floor( diff / 60 ) + ' mins ago';
		}

		if ( diff < 86400 ) {
			return Math.floor( diff / 3600 ) + ' hours ago';
		}

		if ( diff < 604800 ) {
			return Math.floor( diff / 86400 ) + ' days ago';
		}

		return new Date( dateStr ).toLocaleDateString();

	}

	function extractAuditSummary( raw ) {

		raw = String( raw || '' );

		// Remove Claude thinking / agent chatter
		raw = raw.replace(
			/I have sufficient data[\s\S]*?full report\./gi,
			''
		);

		var match = raw.match(
			/(?:^|\n)(?:#+\s*)?(?:\d+\.\s*)?Executive Summary\s*\n([\s\S]*?)(?=\n(?:#+\s*)?(?:\d+\.\s*)?(Critical Issues|High Priority Issues|Medium Priority Issues|Quick Wins|Prioritized Action Plan|Strengths to Preserve|4-Phase Roadmap)|$)/i
		);

		if ( ! match ) {
			return '';
		}

		var summary = match[1]
			.replace(/^\s*[-*]\s*/gm, '')
			.replace(/\n{2,}/g, '\n')
			.trim();

		// Use first meaningful paragraph only
		summary = summary
			.split('\n')
			.filter(Boolean)
			.slice(0, 3)
			.join(' ');

		return summary;
	}
	function parseSeoHealthFromAuditRaw( raw ) {
		raw = String( raw || '' );

		var score = 0;

		var scoreMatch =
			raw.match( /SEO Health Score:\s*(\d+)\s*\/\s*100/i ) ||
			raw.match( /Overall Score:\s*(\d+)\s*\/\s*100/i ) ||
			raw.match( /SEO HEALTH SCORE[^0-9]*(\d+)\s*\/\s*100/i ) ||
			raw.match( /TOTAL\s*\|\s*100%\s*\|\s*\|\s*(\d+)\s*\/\s*100/i ) ||
			raw.match( /TOTAL\s*\|[^|]*\|[^|]*\|\s*[\d.]+\s*→\s*(\d+)\s*\|/i ) ||
			raw.match( /TOTAL[\s\S]{0,80}?(\d+)\s*\/\s*100/i );

		if ( scoreMatch ) {
			score = parseInt( scoreMatch[1], 10 ) || 0;
		}

		var categories = [];

		raw.split( '\n' ).forEach( function ( line ) {
			if ( line.indexOf( '|' ) === -1 ) {
				return;
			}

			if ( line.indexOf( '---' ) > -1 ) {
				return;
			}

			var cols = line.split( '|' ).map( function ( c ) {
				return c.trim();
			} ).filter( Boolean );

			if ( cols.length < 3 ) {
				return;
			}

			if ( /^Category$/i.test( cols[0] ) || /^Area$/i.test( cols[0] ) ) {
				return;
			}

			if ( /^TOTAL$/i.test( cols[0] ) || /^Total$/i.test( cols[0] ) ) {
				return;
			}

			var label = cols[0];
			var catScore = 0;

			cols.forEach( function ( col ) {
				var m = col.match( /(\d+)\s*\/\s*100/ );
				if ( m && ! catScore ) {
					catScore = parseInt( m[1], 10 ) || 0;
				}
			} );

			if ( ! catScore ) {
				cols.forEach( function ( col ) {
					if ( /^\d+$/.test( col ) && ! catScore ) {
						catScore = parseInt( col, 10 ) || 0;
					}
				} );
			}

			if ( catScore ) {
				categories.push( {
					label: label.replace( /\s*\(.*?\)\s*/g, '' ),
					score: catScore
				} );
			}
		} );

		return {
			score: score,
			categories: categories
		};
	}

	function renderSeoHealth( data ) {
		var score =
			data.score ||
			( data.result && data.result.score ) ||
			0;
		var circumference = 326.56;
		var offset = circumference - ( score / 100 ) * circumference;

		$( '.csa-score-ring__score' ).text( score );
		$( '.csa-score-ring__total' ).text( '/100' );
		updateScoreRing( score );

		if ( data.last_audit ) {
			$( '#csa-seo-last-audit' ).text( data.last_audit );
		}

		var html = '';

		data.categories.slice( 0, 6 ).forEach( function ( c ) {
			var cls = 'bad';

			if ( c.score >= 80 ) cls = 'good';
			else if ( c.score >= 60 ) cls = 'mid';
			else if ( c.score >= 40 ) cls = 'warn';

			html +=
				'<div class="csa-health-row">' +
					'<span>' + escHtml( c.label ) + '</span>' +
					'<strong class="' + cls + '">' + escHtml( c.score ) + '</strong>' +
				'</div>';
		} );

		$( '.csa-seo-health-breakdown' ).html( html );
	}

	function renderEmptySeoHealth() {
		$( '.csa-score-ring__score' ).text( '—' );
		$( '.csa-score-ring__total' ).text( '/100' );
		$( '.csa-score-ring__progress' ).css( 'stroke-dashoffset', 326.56 );

		$( '.csa-seo-health-breakdown' ).html(
			'<div class="csa-health-empty">Run an audit to generate your SEO health score.</div>'
		);
	}

	function updateScoreRing( score ) {

		var circumference = 326.56;

		var offset =
			circumference -
			( score / 100 ) * circumference;

		$( '.csa-score-ring__progress' )
			.css( 'stroke-dashoffset', offset );

	}

} )( jQuery );
