<?php

/**
 * Plugin Name: CítameIA
 * Plugin URI: https://citameia.com
 * Description: Optimiza tu sitio para que los motores de IA (ChatGPT, Gemini, Perplexity, Google AI Overviews) te encuentren y te citen. Genera schema.org, llms.txt y FAQs estructuradas, y te da un score de "citabilidad".
 * Version: 1.49.2
 * Author: Cítame.IA
 * Text Domain: citameia
 * Domain Path: /languages
 * License: GPL v2 or later
 */
if ( function_exists( 'citameia_fs' ) ) {
    citameia_fs()->set_basename( false, __FILE__ );
} else {
    // DO NOT REMOVE THIS IF, IT IS ESSENTIAL FOR THE `function_exists` LOGIC.
    function citameia_fs() {
        global $citameia_fs;
        if ( !isset( $citameia_fs ) ) {
            // Include Freemius SDK.
            require_once dirname( __FILE__ ) . '/vendor/freemius/start.php';
            $citameia_fs = fs_dynamic_init( array(
                'id'               => '36518',
                'slug'             => 'citameia',
                'type'             => 'plugin',
                'public_key'       => 'pk_be72719df373067b35988440f722f',
                'is_premium'       => false,
                'premium_suffix'   => 'Pro',
                'has_addons'       => false,
                'has_paid_plans'   => true,
                'is_org_compliant' => true,
                'menu'             => array(
                    'slug'       => 'citameia',
                    'first-path' => 'admin.php?page=citameia-bienvenida',
                    'support'    => false,
                ),
                'is_live'          => true,
            ) );
        }
        return $citameia_fs;
    }

    // Init Freemius.
    citameia_fs();
    // Signal that SDK was initiated.
    do_action( 'citameia_fs_loaded' );
}
if ( !defined( 'ABSPATH' ) ) {
    exit;
    // No acceso directo.
}
/**
 * Nota: no se necesita load_plugin_textdomain() aquí. Desde WordPress 4.6,
 * las traducciones se cargan automáticamente desde la carpeta indicada en
 * "Domain Path" (arriba, /languages), siempre que el Text Domain coincida
 * con el slug del plugin — ambas condiciones ya se cumplen en este archivo.
 */
define( 'CITAMEIA_VERSION', '1.49.2' );
define( 'CITAMEIA_PATH', plugin_dir_path( __FILE__ ) );
define( 'CITAMEIA_URL', plugin_dir_url( __FILE__ ) );
// Antes 'geo_radar_settings' (prefijo "geo_" señalado como muy corto por
// WordPress.org). El nombre nuevo se migra solo la primera vez que carga
// el plugin — ver citameia_maybe_migrate_option_key() — así que ningún
// sitio que ya tuviera el plugin instalado pierde su configuración.
define( 'CITAMEIA_OPTION', 'citameia_settings' );
/**
 * =========================================================
 * LICENCIA PRO
 * =========================================================
 * Punto único de verdad para saber si el sitio tiene licencia Pro
 * activa. Por ahora es un stub manual (útil para desarrollar y
 * probar el bloqueo de pantallas sin depender todavía del SDK de
 * Freemius). Cuando se integre Freemius, esta función pasa a llamar
 * a fs_is_premium() (o equivalente) y el resto del plugin no cambia,
 * porque todos los checks de Pro pasan siempre por aquí.
 *
 * Modo de prueba manual: define CITAMEIA_FORCE_PRO en wp-config.php
 * (true o false) para forzar el estado sin tocar código, útil para
 * ver cómo se ve cada pantalla en ambos modos.
 */
function citameia_is_pro() {
    if ( defined( 'CITAMEIA_FORCE_PRO' ) ) {
        return (bool) CITAMEIA_FORCE_PRO;
    }
    if ( function_exists( 'citameia_fs' ) ) {
        return citameia_fs()->can_use_premium_code();
    }
    return false;
}

/**
 * Tarjeta de bloqueo reutilizable para features Pro. Se usa en vez del
 * contenido real de la pantalla cuando citameia_is_pro() es false.
 * $titulo y $beneficios (lista de strings) son específicos de cada
 * feature, para que la persona entienda qué se está perdiendo, no solo
 * que "esto es de paga".
 */
function citameia_render_pro_lock(  $titulo, $beneficios = array()  ) {
    ?>
	<div class="citameia-pro-lock">
		<div class="citameia-pro-lock-icon">🔒</div>
		<h2 class="citameia-pro-lock-title"><?php 
    echo esc_html( $titulo );
    ?></h2>
		<p class="citameia-pro-lock-sub"><?php 
    esc_html_e( 'Esta función es parte de CítameIA Pro.', 'citameia' );
    ?></p>
		<?php 
    if ( !empty( $beneficios ) ) {
        ?>
			<ul class="citameia-pro-lock-beneficios">
				<?php 
        foreach ( $beneficios as $b ) {
            ?>
					<li><?php 
            echo esc_html( $b );
            ?></li>
				<?php 
        }
        ?>
			</ul>
		<?php 
    }
    ?>
		<a href="<?php 
    echo esc_url( admin_url( 'admin.php?page=citameia-pro' ) );
    ?>" class="button button-primary citameia-pro-lock-cta">
			<?php 
    esc_html_e( 'Ver planes de CítameIA Pro', 'citameia' );
    ?>
		</a>
	</div>
	<?php 
}

/**
 * Versión compacta del candado, para usarse dentro de una pantalla que
 * en general sí es gratis (ej. el Panel), cuando solo una sección
 * puntual de esa pantalla es Pro. A diferencia de citameia_render_pro_lock(),
 * no reemplaza toda la página, solo el bloque correspondiente.
 */
function citameia_render_pro_lock_inline(  $titulo, $descripcion  ) {
    ?>
	<div class="citameia-pro-lock-inline">
		<span class="citameia-pro-lock-inline-icon">🔒</span>
		<div class="citameia-pro-lock-inline-body">
			<strong><?php 
    echo esc_html( $titulo );
    ?></strong>
			<p><?php 
    echo esc_html( $descripcion );
    ?></p>
		</div>
		<a href="<?php 
    echo esc_url( admin_url( 'admin.php?page=citameia-pro' ) );
    ?>" class="button button-small citameia-pro-lock-cta">
			<?php 
    esc_html_e( 'Ver Pro', 'citameia' );
    ?>
		</a>
	</div>
	<?php 
}

/**
 * =========================================================
 * PANTALLA DE PLANES (CítameIA Pro)
 * =========================================================
 * Oculta del menú lateral; se llega desde los botones "Ver planes" /
 * "Ver Pro" de las pantallas bloqueadas. Los precios están
 * centralizados aquí arriba para no tener que buscar en toda la
 * función el día que cambien.
 *
 * El botón de compra abre el Overlay Checkout de Freemius directo
 * (vía su JS SDK), en vez de mandar primero a la pantalla de precios
 * genérica que el propio SDK genera en /wp-admin (esa pantalla
 * duplicaba la nuestra y no se puede personalizar). CITAMEIA_PRO_PLAN_ID
 * es el ID del plan "Pro" en Freemius (Stores > Plans).
 */
define( 'CITAMEIA_PRO_PRECIO_MENSUAL', 9 );
define( 'CITAMEIA_PRO_PRECIO_ANUAL', 69 );
define( 'CITAMEIA_PRO_PLAN_ID', '60484' );
define( 'CITAMEIA_PRO_CHECKOUT_URL', 'https://citameia.com/#contacto' );
function citameia_pro_checkout_url() {
    if ( function_exists( 'citameia_fs' ) ) {
        return citameia_fs()->get_upgrade_url();
    }
    return CITAMEIA_PRO_CHECKOUT_URL;
}

function citameia_render_pro_page() {
    $es_pro = citameia_is_pro();
    $precio_mensual = CITAMEIA_PRO_PRECIO_MENSUAL;
    $precio_anual = CITAMEIA_PRO_PRECIO_ANUAL;
    $equivalente_mes = round( $precio_anual / 12, 2 );
    $ahorro_pct = round( (1 - $precio_anual / ($precio_mensual * 12)) * 100 );
    $features_gratis = array(
        __( 'Datos del negocio y schema.org (Organization/LocalBusiness, WebSite)', 'citameia' ),
        __( '1 grupo de FAQ con schema FAQPage', 'citameia' ),
        __( 'Validar schema', 'citameia' ),
        __( 'llms.txt', 'citameia' ),
        __( 'Score de citabilidad (número actual)', 'citameia' ),
        __( 'Open Graph / Twitter Card', 'citameia' ),
        __( 'Presencia externa (checklist)', 'citameia' ),
        __( 'Pruebas en IA: 4 preguntas fijas, registro simple', 'citameia' )
    );
    $features_pro = array(
        __( 'Todo lo de la versión gratis', 'citameia' ),
        __( 'Monitoreo de bots de IA (historial completo)', 'citameia' ),
        __( 'Reportes: PDF, correo semanal automático, badge SVG', 'citameia' ),
        __( 'Historial y gráfica de tendencia del score', 'citameia' ),
        __( 'Grupos de FAQ ilimitados', 'citameia' ),
        __( 'Pruebas en IA: desglose por motor, por pregunta, historial completo', 'citameia' )
    );
    ?>
	<div class="wrap geo-radar-wrap">
		<?php 
    citameia_render_admin_header( 'citameia-pro' );
    ?>

		<div class="citameia-pro-hero">
			<div class="citameia-pro-hero-eyebrow"><?php 
    esc_html_e( 'CÍTAME.IA PRO', 'citameia' );
    ?></div>
			<h1 class="citameia-pro-hero-title"><?php 
    esc_html_e( 'Lo mismo que cobran cientos de dólares al mes en herramientas enterprise, por una fracción del precio.', 'citameia' );
    ?></h1>
			<p class="citameia-pro-hero-sub"><?php 
    esc_html_e( '1 licencia = 1 sitio. Sin permanencia forzosa: cancela cuando quieras.', 'citameia' );
    ?></p>
		</div>

		<?php 
    if ( $es_pro ) {
        ?>
			<div class="notice notice-success" style="padding:12px 14px;max-width:720px;margin:0 auto 24px;">
				<p style="margin:0;"><strong><?php 
        esc_html_e( 'Ya tienes CítameIA Pro activo en este sitio.', 'citameia' );
        ?></strong> <?php 
        esc_html_e( 'Todas las funciones de abajo ya están desbloqueadas.', 'citameia' );
        ?></p>
			</div>
		<?php 
    }
    ?>

		<div class="citameia-pricing-grid">
			<div class="citameia-pricing-card">
				<div class="citameia-pricing-card-name"><?php 
    esc_html_e( 'Gratis', 'citameia' );
    ?></div>
				<div class="citameia-pricing-card-price">
					<span class="amount">$0</span>
				</div>
				<p class="citameia-pricing-card-desc"><?php 
    esc_html_e( 'Para empezar a hablarle claro a los motores de IA, sin costo.', 'citameia' );
    ?></p>
				<ul class="citameia-pricing-features">
					<?php 
    foreach ( $features_gratis as $f ) {
        ?>
						<li><?php 
        echo esc_html( $f );
        ?></li>
					<?php 
    }
    ?>
				</ul>
			</div>

			<div class="citameia-pricing-card citameia-pricing-card-pro">
				<div class="citameia-pricing-card-badge"><?php 
    esc_html_e( 'Recomendado', 'citameia' );
    ?></div>
				<div class="citameia-pricing-card-name"><?php 
    esc_html_e( 'Pro', 'citameia' );
    ?></div>

				<div class="citameia-pricing-toggle" role="tablist">
					<button type="button" class="citameia-pricing-toggle-btn is-active" data-plan="mensual"><?php 
    esc_html_e( 'Mensual', 'citameia' );
    ?></button>
						<button type="button" class="citameia-pricing-toggle-btn" data-plan="anual"><?php 
    esc_html_e( 'Anual', 'citameia' );
    ?> <span class="citameia-pricing-toggle-save"><?php 
    /* translators: %s: porcentaje de descuento del plan anual */
    printf( esc_html__( '-%s%%', 'citameia' ), esc_html( $ahorro_pct ) );
    ?></span></button>
				</div>

				<div class="citameia-pricing-card-price" data-plan-price="mensual">
					<span class="amount">$<?php 
    echo esc_html( $precio_mensual );
    ?></span><span class="period"><?php 
    esc_html_e( '/mes', 'citameia' );
    ?></span>
				</div>
				<div class="citameia-pricing-card-price is-hidden" data-plan-price="anual">
					<span class="amount">$<?php 
    echo esc_html( $precio_anual );
    ?></span><span class="period"><?php 
    esc_html_e( '/año', 'citameia' );
    ?></span>
										<div class="citameia-pricing-card-price-sub"><?php 
    /* translators: %s: precio mensual equivalente del plan anual */
    printf( esc_html__( 'equivale a $%s/mes', 'citameia' ), esc_html( $equivalente_mes ) );
    ?></div>
				</div>

				<p class="citameia-pricing-card-desc"><?php 
    esc_html_e( 'Para negocios que quieren ver la tendencia, no solo la foto de hoy.', 'citameia' );
    ?></p>

				<a href="<?php 
    echo esc_url( citameia_pro_checkout_url() );
    ?>" id="citameia-pro-checkout-btn" class="button button-primary citameia-pricing-cta">
					<?php 
    echo ( $es_pro ? esc_html__( 'Ya tienes Pro activo', 'citameia' ) : esc_html__( 'Obtener CítameIA Pro', 'citameia' ) );
    ?>
				</a>

				<ul class="citameia-pricing-features">
					<?php 
    foreach ( $features_pro as $f ) {
        ?>
						<li><?php 
        echo esc_html( $f );
        ?></li>
					<?php 
    }
    ?>
				</ul>
			</div>
		</div>

		<p class="citameia-pro-footnote"><?php 
    esc_html_e( 'Precios en dólares americanos (USD). 1 licencia cubre 1 sitio.', 'citameia' );
    ?></p>
	</div>
	<?php 
    ob_start();
    ?>
	(function() {
		var toggleBtns  = document.querySelectorAll( '.citameia-pricing-toggle-btn' );
		var billingCycle = 'monthly';
		toggleBtns.forEach( function( btn ) {
			btn.addEventListener( 'click', function() {
				var plan = btn.dataset.plan;
				billingCycle = ( plan === 'anual' ) ? 'annual' : 'monthly';
				toggleBtns.forEach( function( b ) { b.classList.toggle( 'is-active', b === btn ); } );
				document.querySelectorAll( '[data-plan-price]' ).forEach( function( el ) {
					el.classList.toggle( 'is-hidden', el.dataset.planPrice !== plan );
				} );
			} );
		} );

		<?php 
    if ( !$es_pro ) {
        ?>
		<?php 
        // This IF block is stripped entirely from the free version by Freemius.
        ?>
		<?php 
        ?>
		<?php 
    }
    ?>
	})();
	<?php 
    $citameia_pricing_js = ob_get_clean();
    wp_register_script(
        'citameia-pricing-toggle',
        false,
        array(),
        CITAMEIA_VERSION,
        true
    );
    wp_enqueue_script( 'citameia-pricing-toggle' );
    wp_add_inline_script( 'citameia-pricing-toggle', $citameia_pricing_js );
    ?>
	<?php 
}

/**
 * =========================================================
 * DETECCIÓN DE OTROS PLUGINS DE SEO / SCHEMA (Yoast / Rank Math / Google para WooCommerce)
 * =========================================================
 * Yoast SEO y Rank Math generan su propio schema.org (Organization,
 * WebSite, Article/WebPage). Google Listings & Ads ("Google para
 * WooCommerce") genera su propio schema Product para Merchant Center.
 * Si están activos, CítameIA evita duplicar ese schema para no generar
 * datos estructurados contradictorios en la misma página, algo que
 * perjudica tanto SEO tradicional como GEO.
 */
function citameia_is_plugin_active_by_path(  $plugin_path  ) {
    $active_plugins = (array) get_option( 'active_plugins', array() );
    if ( in_array( $plugin_path, $active_plugins, true ) ) {
        return true;
    }
    if ( is_multisite() ) {
        $active_sitewide = (array) get_site_option( 'active_sitewide_plugins', array() );
        if ( array_key_exists( $plugin_path, $active_sitewide ) ) {
            return true;
        }
    }
    return false;
}

function citameia_detect_seo_plugins() {
    static $detected = null;
    if ( null !== $detected ) {
        return $detected;
    }
    $yoast_active = defined( 'WPSEO_VERSION' );
    $rankmath_active = defined( 'RANK_MATH_VERSION' ) || class_exists( 'RankMath' );
    // Addon específico de Yoast que sí agrega schema Product de WooCommerce.
    $yoast_woo_active = defined( 'WPSEO_WOOCOMMERCE_FILE' ) || class_exists( 'Yoast_WooCommerce_SEO' );
    // "Google para WooCommerce" (Google Listings & Ads) también genera schema Product.
    $google_listings_active = defined( 'WC_GLA_VERSION' ) || class_exists( 'Automattic\\WooCommerce\\GoogleListingsAndAds\\PluginFactory' ) || citameia_is_plugin_active_by_path( 'google-listings-and-ads/google-listings-and-ads.php' );
    $detected = array(
        'yoast'                => $yoast_active,
        'rankmath'             => $rankmath_active,
        'yoast_woo'            => $yoast_woo_active,
        'google_listings'      => $google_listings_active,
        'any'                  => $yoast_active || $rankmath_active,
        'any_product_conflict' => $rankmath_active || $yoast_woo_active || $google_listings_active,
    );
    return $detected;
}

/**
 * Nombres legibles de los plugins que ya generan schema Product, para mostrar en los avisos.
 */
function citameia_product_conflict_names() {
    $d = citameia_detect_seo_plugins();
    $names = array();
    if ( $d['rankmath'] ) {
        $names[] = 'Rank Math';
    }
    if ( $d['yoast_woo'] ) {
        $names[] = 'el addon de WooCommerce SEO de Yoast';
    }
    if ( $d['google_listings'] ) {
        $names[] = 'Google para WooCommerce (Google Listings & Ads)';
    }
    return $names;
}

/**
 * true si otro plugin ya cubre Organization/WebSite/Article, evita duplicar ese schema.
 */
function citameia_should_skip_core_schema() {
    $d = citameia_detect_seo_plugins();
    return $d['any'];
}

/**
 * true si otro plugin ya cubre schema Product de WooCommerce.
 */
function citameia_should_skip_product_schema() {
    $d = citameia_detect_seo_plugins();
    return $d['any_product_conflict'];
}

/**
 * =========================================================
 * ACTIVACIÓN / DESACTIVACIÓN
 * =========================================================
 */
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_activate() {
    $defaults = geo_radar_default_settings();
    $is_new = !get_option( CITAMEIA_OPTION );
    if ( $is_new ) {
        add_option( CITAMEIA_OPTION, $defaults );
    }
    geo_radar_register_rewrite();
    flush_rewrite_rules();
    // Fecha de activación, solo la primera vez — la usa el aviso de
    // reseña de más abajo para saber cuándo ya lleva suficiente tiempo
    // usando el plugin como para tener una opinión real que dar.
    if ( false === get_option( 'citameia_activado_en' ) ) {
        add_option( 'citameia_activado_en', current_time( 'mysql' ) );
    }
    // Solo en instalaciones nuevas mandamos al asistente de bienvenida, no en cada reactivación.
    // NOTA: este redirect ahora lo maneja Freemius (ver 'first-path' en la
    // configuración de fs_dynamic_init(), arriba del archivo), que manda a la
    // misma pantalla de Bienvenida pero DESPUÉS de mostrar su pantalla de
    // opt-in. Si dejáramos este redirect propio activo también, podría
    // dispararse antes que el de Freemius y saltarse el opt-in por completo.
    // if ( $is_new ) {
    // 	add_option( 'citameia_do_activation_redirect', true );
    // }
}

register_activation_hook( __FILE__, 'geo_radar_activate' );
/**
 * =========================================================
 * AVISO PIDIENDO RESEÑA
 * =========================================================
 * Aparece solo en las pantallas del propio plugin (no en todo
 * wp-admin), y solo después de 14 días de uso real — no tiene caso
 * pedir opinión el mismo día que alguien instala. Dos caminos: "Sí,
 * la dejo" manda directo a la página de reseñas de WordPress.org en
 * una pestaña nueva; "Ahora no" lo oculta para siempre (no vuelve a
 * insistir — un solo rechazo es suficiente, seguir preguntando
 * después de un "no" es justo el tipo de fricción que este mismo
 * aviso busca evitarle al usuario).
 */
function citameia_debe_mostrar_aviso_resena() {
    if ( get_option( 'citameia_resena_aviso_ocultado' ) ) {
        return false;
    }
    $activado_en = get_option( 'citameia_activado_en' );
    if ( !$activado_en ) {
        return false;
        // Instalaciones de antes de este cambio no tienen esta fecha — no le insistimos a nadie retroactivo.
    }
    $dias_activo = (time() - strtotime( $activado_en )) / DAY_IN_SECONDS;
    return $dias_activo >= 14;
}

add_action( 'admin_notices', 'citameia_render_aviso_resena' );
function citameia_render_aviso_resena() {
    if ( !current_user_can( 'manage_options' ) ) {
        return;
    }
    $pantalla = get_current_screen();
    // Solo en las pantallas del propio plugin — nada de aparecer en el
    // Escritorio general ni en pantallas de otros plugins.
    if ( !$pantalla || false === strpos( $pantalla->id, 'citameia' ) ) {
        return;
    }
    if ( !citameia_debe_mostrar_aviso_resena() ) {
        return;
    }
    $url_resena = 'https://wordpress.org/support/plugin/citameia/reviews/#new-post';
    $url_ocultar = wp_nonce_url( admin_url( 'admin-post.php?action=citameia_ocultar_aviso_resena' ), 'citameia_ocultar_aviso_resena' );
    ?>
	<div class="notice notice-info is-dismissible" style="padding:14px 16px;">
		<p style="font-size:14px;margin:0 0 10px;">
			<strong><?php 
    esc_html_e( '¿Te está gustando CítameIA?', 'citameia' );
    ?></strong>
			<?php 
    esc_html_e( 'Tu reseña nos ayudaría muchísimo.', 'citameia' );
    ?>
		</p>
		<p style="margin:0;">
			<a href="<?php 
    echo esc_url( $url_resena );
    ?>" target="_blank" rel="noopener" class="button button-primary">
				<?php 
    esc_html_e( '¡Sí, la dejo!', 'citameia' );
    ?>
			</a>
			<a href="<?php 
    echo esc_url( $url_ocultar );
    ?>" class="button" style="margin-left:8px;">
				<?php 
    esc_html_e( 'Ahora no', 'citameia' );
    ?>
			</a>
		</p>
	</div>
	<?php 
}

add_action( 'admin_post_citameia_ocultar_aviso_resena', 'citameia_manejar_ocultar_aviso_resena' );
function citameia_manejar_ocultar_aviso_resena() {
    if ( !current_user_can( 'manage_options' ) || !isset( $_GET['_wpnonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'citameia_ocultar_aviso_resena' ) ) {
        wp_die( esc_html__( 'No autorizado', 'citameia' ) );
    }
    update_option( 'citameia_resena_aviso_ocultado', true );
    wp_safe_redirect( ( wp_get_referer() ? wp_get_referer() : admin_url() ) );
    exit;
}

// El redirect a Bienvenida en la primera activación ahora lo maneja Freemius
// (ver 'first-path' en la configuración de fs_dynamic_init(), arriba del
// archivo) — manda a la misma pantalla, pero DESPUÉS de mostrar su pantalla
// de opt-in. La función propia que hacía esto (citameia_maybe_redirect_to_welcome)
// se eliminó por completo: quedaba sin usar desde que se desactivó su
// add_action, y dejarla como código muerto solo generaba advertencias del
// linter sobre código que nunca se ejecuta.
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_deactivate() {
    flush_rewrite_rules();
    wp_clear_scheduled_hook( 'citameia_prune_crawler_log' );
    wp_clear_scheduled_hook( 'citameia_weekly_score_snapshot' );
}

register_deactivation_hook( __FILE__, 'geo_radar_deactivate' );
/**
 * =========================================================
 * CONFIGURACIÓN POR DEFECTO
 * =========================================================
 */
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_default_settings() {
    return array(
        'business_name'     => get_bloginfo( 'name' ),
        'business_type'     => 'LocalBusiness',
        'business_niche'    => '',
        'physical_presence' => 'visita',
        'description'       => get_bloginfo( 'description' ),
        'street'            => '',
        'city'              => '',
        'state'             => '',
        'zip'               => '',
        'country'           => 'MX',
        'phone'             => '',
        'email'             => get_bloginfo( 'admin_email' ),
        'whatsapp'          => '',
        'price_range'       => '',
        'opening_hours'     => '',
        'logo_url'          => '',
        'social_facebook'   => '',
        'social_instagram'  => '',
        'social_gbp'        => '',
        'llms_intro'        => '',
    );
}

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_get_settings() {
    $saved = get_option( CITAMEIA_OPTION, array() );
    return wp_parse_args( $saved, geo_radar_default_settings() );
}

/**
 * =========================================================
 * TIPOS DE NEGOCIO DISPONIBLES (schema.org)
 * =========================================================
 */
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_business_types() {
    return array(
        __( 'General', 'citameia' )                 => array(
            'LocalBusiness' => __( 'Negocio local (genérico)', 'citameia' ),
            'Store'         => __( 'Tienda (genérico)', 'citameia' ),
        ),
        __( 'Tiendas', 'citameia' )                 => array(
            'BookStore'          => __( 'Librería', 'citameia' ),
            'ClothingStore'      => __( 'Tienda de ropa', 'citameia' ),
            'ShoeStore'          => __( 'Zapatería', 'citameia' ),
            'JewelryStore'       => __( 'Joyería', 'citameia' ),
            'ElectronicsStore'   => __( 'Tienda de electrónica', 'citameia' ),
            'FurnitureStore'     => __( 'Mueblería', 'citameia' ),
            'HardwareStore'      => __( 'Ferretería', 'citameia' ),
            'ToyStore'           => __( 'Juguetería', 'citameia' ),
            'SportingGoodsStore' => __( 'Tienda deportiva', 'citameia' ),
            'PetStore'           => __( 'Tienda de mascotas', 'citameia' ),
            'Florist'            => __( 'Florería', 'citameia' ),
            'BikeStore'          => __( 'Tienda de bicicletas', 'citameia' ),
            'GroceryStore'       => __( 'Abarrotes / mini súper', 'citameia' ),
            'LiquorStore'        => __( 'Vinatería', 'citameia' ),
            'ConvenienceStore'   => __( 'Tienda de conveniencia', 'citameia' ),
        ),
        __( 'Alimentos y bebidas', 'citameia' )     => array(
            'FoodEstablishment'  => __( 'Alimentos y bebidas (genérico)', 'citameia' ),
            'Restaurant'         => __( 'Restaurante', 'citameia' ),
            'CafeOrCoffeeShop'   => __( 'Cafetería', 'citameia' ),
            'Bakery'             => __( 'Panadería', 'citameia' ),
            'BarOrPub'           => __( 'Bar / cantina', 'citameia' ),
            'FastFoodRestaurant' => __( 'Comida rápida', 'citameia' ),
            'IceCreamShop'       => __( 'Heladería', 'citameia' ),
            'Winery'             => __( 'Vinícola / productor artesanal', 'citameia' ),
            'Brewery'            => __( 'Cervecería', 'citameia' ),
            'Distillery'         => __( 'Destilería (mezcal, tequila, etc.)', 'citameia' ),
        ),
        __( 'Servicios profesionales', 'citameia' ) => array(
            'ProfessionalService' => __( 'Servicio profesional (genérico)', 'citameia' ),
            'Attorney'            => __( 'Abogado / despacho legal', 'citameia' ),
            'AccountingService'   => __( 'Contador / despacho contable', 'citameia' ),
            'Notary'              => __( 'Notaría', 'citameia' ),
            'TravelAgency'        => __( 'Agencia de viajes', 'citameia' ),
            'RealEstateAgent'     => __( 'Inmobiliaria', 'citameia' ),
            'InsuranceAgency'     => __( 'Aseguradora', 'citameia' ),
            'EmploymentAgency'    => __( 'Agencia de empleo', 'citameia' ),
        ),
        __( 'Salud', 'citameia' )                   => array(
            'MedicalBusiness' => __( 'Consultorio / negocio de salud (genérico)', 'citameia' ),
            'Dentist'         => __( 'Dentista', 'citameia' ),
            'Physician'       => __( 'Médico', 'citameia' ),
            'VeterinaryCare'  => __( 'Veterinaria', 'citameia' ),
        ),
        __( 'Belleza y bienestar', 'citameia' )     => array(
            'BeautySalon'        => __( 'Salón de belleza', 'citameia' ),
            'HairSalon'          => __( 'Estética / peluquería', 'citameia' ),
            'NailSalon'          => __( 'Salón de uñas', 'citameia' ),
            'DaySpa'             => __( 'Spa', 'citameia' ),
            'GymOrFitnessCenter' => __( 'Gimnasio', 'citameia' ),
            'HealthClub'         => __( 'Club deportivo', 'citameia' ),
        ),
        __( 'Hospedaje', 'citameia' )               => array(
            'LodgingBusiness' => __( 'Hotel / hospedaje (genérico)', 'citameia' ),
        ),
        __( 'Automotriz', 'citameia' )              => array(
            'AutoRepair' => __( 'Taller mecánico', 'citameia' ),
            'AutoDealer' => __( 'Agencia de autos', 'citameia' ),
            'AutoRental' => __( 'Renta de autos', 'citameia' ),
            'AutoWash'   => __( 'Autolavado', 'citameia' ),
            'GasStation' => __( 'Gasolinera', 'citameia' ),
        ),
        __( 'Otros servicios', 'citameia' )         => array(
            'DryCleaningOrLaundry' => __( 'Tintorería / lavandería', 'citameia' ),
            'ChildCare'            => __( 'Guardería', 'citameia' ),
            'Electrician'          => __( 'Electricista', 'citameia' ),
            'Plumber'              => __( 'Plomero', 'citameia' ),
            'HousePainter'         => __( 'Pintor de casas / construcción', 'citameia' ),
            'MovingCompany'        => __( 'Empresa de mudanzas', 'citameia' ),
            'RoofingContractor'    => __( 'Contratista de techos', 'citameia' ),
            'GeneralContractor'    => __( 'Contratista general / construcción', 'citameia' ),
        ),
        __( 'Personas y creadores', 'citameia' )    => array(
            'Person'                 => __( 'Escritor / autor', 'citameia' ),
            'Person__editor'         => __( 'Editor', 'citameia' ),
            'Person__pintor_artista' => __( 'Pintor / artista visual', 'citameia' ),
            'Person__artista'        => __( 'Artista (otras disciplinas)', 'citameia' ),
            'Person__fotografo'      => __( 'Fotógrafo', 'citameia' ),
            'Person__musico'         => __( 'Músico', 'citameia' ),
        ),
        __( 'Digital', 'citameia' )                 => array(
            'Organization__productos_digitales'        => __( 'Negocio de productos digitales (cursos, ebooks, software)', 'citameia' ),
            'ProfessionalService__desarrollo_software' => __( 'Desarrollo de software', 'citameia' ),
            'ProfessionalService__marketing_digital'   => __( 'Marketing digital', 'citameia' ),
        ),
    );
}

/**
 * Algunas opciones del selector usan una clave con sufijo (después de "__")
 * para poder tener varias etiquetas distintas en el menú (ej. "Escritor",
 * "Editor", "Pintor / artista visual") aunque por dentro generen el mismo
 * @type real de schema.org (ej. "Person"). Esta función quita ese sufijo
 * para quedarnos solo con el tipo de schema.org válido de verdad.
 */
function citameia_schema_type_real(  $business_type  ) {
    $partes = explode( '__', (string) $business_type, 2 );
    return $partes[0];
}

/**
 * Versión "aplanada" (sin categorías) para código que solo necesita
 * validar una clave o buscar su etiqueta, sin importar el grupo.
 */
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_business_types_flat() {
    $flat = array();
    foreach ( geo_radar_business_types() as $group => $items ) {
        foreach ( $items as $key => $label ) {
            $flat[$key] = $label;
        }
    }
    return $flat;
}

/**
 * =========================================================
 * ADMIN: MENÚ
 * =========================================================
 */
add_action( 'admin_menu', 'geo_radar_admin_menu' );
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_admin_menu() {
    add_menu_page(
        'CítameIA',
        'CítameIA',
        'manage_options',
        'citameia',
        'geo_radar_render_dashboard',
        'dashicons-chart-area',
        58
    );
    add_submenu_page(
        'citameia',
        __( 'Panel', 'citameia' ),
        __( 'Panel', 'citameia' ),
        'manage_options',
        'citameia',
        'geo_radar_render_dashboard'
    );
    add_submenu_page(
        'citameia',
        __( 'Datos del negocio', 'citameia' ),
        __( 'Datos del negocio', 'citameia' ),
        'manage_options',
        'citameia-datos',
        'geo_radar_render_settings'
    );
    add_submenu_page(
        'citameia',
        __( 'FAQ y Schema', 'citameia' ),
        __( 'FAQ y Schema', 'citameia' ),
        'manage_options',
        'citameia-faq',
        'geo_radar_render_faq_help'
    );
    add_submenu_page(
        'citameia',
        'llms.txt',
        'llms.txt',
        'manage_options',
        'citameia-llms',
        'geo_radar_render_llms_page'
    );
    add_submenu_page(
        'citameia',
        __( 'Validar schema', 'citameia' ),
        __( 'Validar schema', 'citameia' ),
        'manage_options',
        'citameia-validar',
        'citameia_render_validate_page'
    );
    add_submenu_page(
        'citameia',
        __( 'Pruebas en IA', 'citameia' ),
        __( 'Pruebas en IA', 'citameia' ),
        'manage_options',
        'citameia-menciones',
        'citameia_render_mentions_page'
    );
    add_submenu_page(
        'citameia',
        __( 'Monitoreo de IA', 'citameia' ),
        __( 'Monitoreo de IA', 'citameia' ),
        'manage_options',
        'citameia-crawlers',
        'citameia_render_crawlers_page'
    );
    add_submenu_page(
        'citameia',
        __( 'Presencia externa', 'citameia' ),
        __( 'Presencia externa', 'citameia' ),
        'manage_options',
        'citameia-presencia',
        'citameia_render_external_presence_page'
    );
    add_submenu_page(
        'citameia',
        __( 'Reportes', 'citameia' ),
        __( 'Reportes', 'citameia' ),
        'manage_options',
        'citameia-reportes',
        'citameia_render_reportes_page'
    );
    add_submenu_page(
        'citameia',
        __( 'Vista previa al compartir', 'citameia' ),
        __( 'Compartir', 'citameia' ),
        'manage_options',
        'citameia-compartir',
        'citameia_render_og_page'
    );
    // Oculto del menú visible (sin título de menú); se llega por redirección o por el link "Ver de nuevo" en el Panel.
    add_submenu_page(
        null,
        __( 'Bienvenida a CítameIA', 'citameia' ),
        __( 'Bienvenida', 'citameia' ),
        'manage_options',
        'citameia-bienvenida',
        'citameia_render_welcome_page'
    );
    // Oculto del menú visible; se llega por los botones "Ver planes" de las pantallas Pro bloqueadas.
    add_submenu_page(
        null,
        __( 'CítameIA Pro', 'citameia' ),
        __( 'CítameIA Pro', 'citameia' ),
        'manage_options',
        'citameia-pro',
        'citameia_render_pro_page'
    );
}

add_action( 'admin_enqueue_scripts', 'geo_radar_admin_assets' );
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_admin_assets(  $hook  ) {
    if ( strpos( $hook, 'citameia' ) === false ) {
        return;
    }
    // Nota: antes se cargaba Poppins/JetBrains Mono desde Google Fonts
    // (fonts.googleapis.com). Se quitó porque WordPress.org no permite que
    // las pantallas de admin hagan peticiones a servicios de terceros sin
    // consentimiento explícito del usuario. El CSS ya declara fallbacks
    // ('sans-serif' y 'Liberation Mono', monospace), así que el admin cae
    // de forma natural a las tipografías del sistema, sin romper nada.
    wp_enqueue_style(
        'geo-radar-admin',
        CITAMEIA_URL . 'assets/admin.css',
        array(),
        CITAMEIA_VERSION
    );
    // Solo en "FAQ y Schema": el CSS real del sitio, para poder mostrar una
    // vista previa fiel del acordeón (el mismo shortcode, el mismo CSS que
    // ve un visitante), no una simulación aparte.
    if ( false !== strpos( $hook, 'citameia-faq' ) ) {
        wp_enqueue_style(
            'citameia-frontend',
            CITAMEIA_URL . 'assets/frontend.css',
            array(),
            CITAMEIA_VERSION
        );
    }
}

/**
 * Muchos plugins (Elementor, por ejemplo) registran sus propios avisos
 * ("admin_notices") sin limitarlos a sus propias pantallas, así que se
 * cuelan en cualquier otra página del admin, incluidas las de CítameIA.
 * Aquí quitamos esos avisos ajenos, pero solo dentro de nuestras propias
 * pantallas; en el resto del admin de WordPress siguen apareciendo
 * normal, no los desactivamos de forma global.
 *
 * Prioridad 1 a propósito (no la 10 por default): tiene que correr ANTES
 * de que nuestras propias funciones de guardado (más abajo en este
 * archivo) agreguen sus propios avisos de éxito ("Datos guardados",
 * "Grupo de FAQ guardado", etc.), para no quitarlos sin querer junto con
 * los ajenos. Si esto se registrara después, se llevaría también los
 * nuestros.
 */
add_action( 'admin_init', 'citameia_hide_foreign_admin_notices', 1 );
function citameia_hide_foreign_admin_notices() {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- solo lectura para detectar si estamos en una pantalla de CítameIA (oculta avisos de otros plugins ahí); no procesa ni cambia ningún dato.
    if ( !isset( $_GET['page'] ) || false === strpos( sanitize_text_field( wp_unslash( $_GET['page'] ) ), 'citameia' ) ) {
        return;
    }
    remove_all_actions( 'admin_notices' );
    remove_all_actions( 'all_admin_notices' );
}

/**
 * CSS del FAQ en el sitio público. Se carga siempre (es un archivo muy
 * ligero) para no depender de detectar el shortcode dentro de contenido
 * armado con Elementor u otros constructores de página.
 */
add_action( 'wp_enqueue_scripts', 'citameia_frontend_assets' );
function citameia_frontend_assets() {
    wp_enqueue_style(
        'citameia-frontend',
        CITAMEIA_URL . 'assets/frontend.css',
        array(),
        CITAMEIA_VERSION
    );
}

/**
 * =========================================================
 * GUARDAR CONFIGURACIÓN
 * =========================================================
 */
add_action( 'admin_init', 'geo_radar_handle_settings_save' );
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_handle_settings_save() {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- esta es justo la verificación del nonce: wp_verify_nonce(wp_unslash(...)) es el patrón correcto de WordPress, pero el analizador estático no reconoce wp_verify_nonce() como función "sanitizadora".
    if ( !isset( $_POST['geo_radar_nonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['geo_radar_nonce'] ) ), 'geo_radar_save_settings' ) ) {
        return;
    }
    if ( !current_user_can( 'manage_options' ) ) {
        return;
    }
    $defaults = geo_radar_default_settings();
    $new = array();
    foreach ( $defaults as $key => $val ) {
        if ( isset( $_POST[$key] ) ) {
            if ( 'description' === $key || 'opening_hours' === $key || 'llms_intro' === $key ) {
                $new[$key] = sanitize_textarea_field( wp_unslash( $_POST[$key] ) );
            } elseif ( 'email' === $key ) {
                $new[$key] = sanitize_email( wp_unslash( $_POST[$key] ) );
            } elseif ( in_array( $key, array('logo_url', 'social_gbp'), true ) ) {
                $new[$key] = esc_url_raw( wp_unslash( $_POST[$key] ) );
            } else {
                $new[$key] = sanitize_text_field( wp_unslash( $_POST[$key] ) );
            }
        } else {
            $new[$key] = $val;
        }
    }
    update_option( CITAMEIA_OPTION, $new );
    add_action( 'admin_notices', function () {
        echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__( 'Datos del negocio guardados. El schema.org de tu sitio ya se actualizó.', 'citameia' ) . '</p></div>';
    } );
}

/**
 * Imprime un bloque <script type="application/ld+json"> de forma segura.
 * wp_json_encode() con JSON_UNESCAPED_SLASHES deja las barras "/" tal
 * cual, lo que significa que si algún dato dinámico (respuesta de FAQ,
 * título de producto, nombre de negocio, etc.) contiene literalmente el
 * texto "</script>" (en cualquier combinación de mayúsculas/minúsculas,
 * como "</Script>"), ese texto cerraría el bloque JSON-LD antes de
 * tiempo y el resto se interpretaría como HTML/JS suelto en la página.
 * Se reemplaza "</script" por "<\/script" (comilla válida en JSON, pero
 * que un navegador ya no reconoce como el cierre real de la etiqueta),
 * sin importar cómo esté escrito el "script".
 */
function citameia_print_json_ld(  $data  ) {
    $json = wp_json_encode( $data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES );
    if ( false === $json ) {
        return;
    }
    $json = preg_replace( '#</(script)#i', '<\\/$1', $json );
    echo "\n<script type=\"application/ld+json\">" . $json . "</script>\n";
    // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $json ya viene de wp_json_encode() y se sanitiza contra el escape de </script (case-insensitive) arriba; no es HTML, es un bloque JSON-LD.
}

/**
 * wp_kses_post() no incluye <details>/<summary> en su lista de etiquetas
 * permitidas (no son parte del set estándar de contenido de post de
 * WordPress), así que usarlo tal cual rompería el acordeón visual de las
 * FAQ. Esta función parte de esa misma lista y le agrega justo esas dos
 * etiquetas con los atributos que usamos, sin abrir la puerta a nada más.
 */
function citameia_kses_faq_html(  $html  ) {
    $allowed = wp_kses_allowed_html( 'post' );
    $allowed['details'] = array(
        'class' => true,
        'open'  => true,
    );
    $allowed['summary'] = array(
        'class' => true,
    );
    if ( isset( $allowed['span'] ) && is_array( $allowed['span'] ) ) {
        $allowed['span']['aria-hidden'] = true;
    }
    return wp_kses( $html, $allowed );
}

function citameia_ai_bot_list() {
    return array(
        'gptbot'             => 'GPTBot (OpenAI)',
        'oai-searchbot'      => 'OAI-SearchBot (OpenAI)',
        'chatgpt-user'       => 'ChatGPT-User (OpenAI)',
        'claudebot'          => 'ClaudeBot (Anthropic)',
        'anthropic-ai'       => 'anthropic-ai (Anthropic)',
        'perplexitybot'      => 'PerplexityBot',
        'google-extended'    => 'Google-Extended (Gemini)',
        'ccbot'              => 'CCBot (Common Crawl)',
        'meta-externalagent' => 'Meta-ExternalAgent (Meta AI)',
        'youbot'             => 'YouBot (You.com)',
    );
}

/**
 * =========================================================
 * MONITOREO DE CRAWLERS DE IA
 * =========================================================
 * A diferencia del chequeo de robots.txt (que solo revisa si un bot
 * TIENE PERMITIDO leer el sitio), esto registra cuando un bot
 * REALMENTE visita una página, usando el encabezado User-Agent de
 * cada visita al frontend.
 *
 * Aviso importante para la persona que lee el código: el User-Agent lo
 * manda el propio visitante, así que se puede falsificar. Esto es una
 * señal útil, no una verificación criptográfica. El aviso equivalente
 * ya se muestra también en pantalla, en citameia_render_crawlers_page().
 */
function citameia_crawler_log_table() {
    global $wpdb;
    return $wpdb->prefix . 'citameia_crawler_log';
}

/**
 * Crea la tabla si no existe. register_activation_hook() no alcanza
 * para sitios donde el plugin ya estaba instalado antes de esta
 * versión (esa activación ya pasó y no se repite en una actualización
 * normal), así que además revisamos una bandera de versión de tabla
 * en cada carga del admin, y la creamos si falta.
 */
function citameia_maybe_create_crawler_table() {
    if ( '1' === get_option( 'citameia_crawler_table_v1' ) ) {
        return;
    }
    global $wpdb;
    $table = citameia_crawler_log_table();
    $charset_collate = $wpdb->get_charset_collate();
    $sql = "CREATE TABLE {$table} (\n\t\tid BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,\n\t\tbot_key VARCHAR(50) NOT NULL,\n\t\turl VARCHAR(500) NOT NULL,\n\t\tvisited_at DATETIME NOT NULL,\n\t\tPRIMARY KEY (id),\n\t\tKEY bot_key (bot_key),\n\t\tKEY visited_at (visited_at)\n\t) {$charset_collate};";
    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    dbDelta( $sql );
    update_option( 'citameia_crawler_table_v1', '1' );
}

add_action( 'admin_init', 'citameia_maybe_create_crawler_table' );
register_activation_hook( __FILE__, 'citameia_maybe_create_crawler_table' );
/**
 * Migra la configuración guardada bajo el nombre de opción viejo
 * ('geo_radar_settings', de antes de renombrar el plugin) al nuevo
 * ('citameia_settings', ver define CITAMEIA_OPTION). Corre una sola vez:
 * si ya existe algo bajo el nombre nuevo, no hace nada; si no existe pero
 * sí había algo bajo el nombre viejo, lo copia y lo marca como migrado.
 * Así ningún sitio que ya tuviera el plugin instalado pierde su
 * configuración guardada al actualizar a esta versión.
 */
function citameia_maybe_migrate_option_key() {
    if ( '1' === get_option( 'citameia_option_migrated_v1' ) ) {
        return;
    }
    if ( false === get_option( CITAMEIA_OPTION, false ) ) {
        $old = get_option( 'geo_radar_settings', false );
        if ( false !== $old ) {
            add_option( CITAMEIA_OPTION, $old );
        }
    }
    update_option( 'citameia_option_migrated_v1', '1' );
}

add_action( 'admin_init', 'citameia_maybe_migrate_option_key' );
register_activation_hook( __FILE__, 'citameia_maybe_migrate_option_key' );
/**
 * Revisa el User-Agent de cada visita al frontend (nunca en el admin,
 * para no registrar las visitas del propio dueño del sitio trabajando
 * en su panel). Es una sola comparación de texto contra una lista
 * corta, así que el costo para visitantes normales es mínimo.
 */
add_action( 'template_redirect', 'citameia_maybe_log_crawler_visit' );
function citameia_maybe_log_crawler_visit() {
    if ( is_admin() || empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
        return;
    }
}

/**
 * =========================================================
 * TRÁFICO DE REFERENCIA DESDE IA (visitas humanas)
 * =========================================================
 * Distinto a lo de arriba: eso son BOTS visitando (para indexar o
 * responder en vivo). Esto es gente REAL que llegó porque ChatGPT,
 * Perplexity, Gemini o Claude le dieron tu link y le dio clic — una
 * señal de negocio mucho más directa que "un bot pasó por aquí".
 *
 * Importante: esto NO puede medir todo. Varias plataformas (sobre
 * todo la app de ChatGPT, y Claude en general) no siempre mandan el
 * dato de referencia por privacidad — así que el número siempre va a
 * ser un estimado, nunca el total real. Y Google AI Overviews es
 * imposible de distinguir de una búsqueda normal de Google (el link
 * se ve idéntico), así que ni lo intentamos — preferimos no medir
 * algo a fingir que lo medimos bien.
 */
function citameia_ai_referral_platforms() {
    return array(
        'perplexity.ai'         => 'Perplexity',
        'chatgpt.com'           => 'ChatGPT',
        'chat.openai.com'       => 'ChatGPT',
        'gemini.google.com'     => 'Gemini',
        'claude.ai'             => 'Claude',
        'copilot.microsoft.com' => 'Copilot',
        'you.com'               => 'You.com',
        'deepseek.com'          => 'DeepSeek',
        'grok.com'              => 'Grok',
        'meta.ai'               => 'Meta AI',
    );
}

function citameia_ai_referral_log_table() {
    global $wpdb;
    return $wpdb->prefix . 'citameia_ai_referral_log';
}

function citameia_maybe_create_ai_referral_table() {
    if ( '1' === get_option( 'citameia_ai_referral_table_v1' ) ) {
        return;
    }
    global $wpdb;
    $table = citameia_ai_referral_log_table();
    $charset_collate = $wpdb->get_charset_collate();
    $sql = "CREATE TABLE {$table} (\n\t\tid BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,\n\t\tplatform VARCHAR(50) NOT NULL,\n\t\turl VARCHAR(500) NOT NULL,\n\t\tvisited_at DATETIME NOT NULL,\n\t\tPRIMARY KEY (id),\n\t\tKEY platform (platform),\n\t\tKEY visited_at (visited_at)\n\t) {$charset_collate};";
    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    dbDelta( $sql );
    update_option( 'citameia_ai_referral_table_v1', '1' );
}

add_action( 'admin_init', 'citameia_maybe_create_ai_referral_table' );
register_activation_hook( __FILE__, 'citameia_maybe_create_ai_referral_table' );
add_action( 'template_redirect', 'citameia_maybe_log_ai_referral_visit' );
function citameia_maybe_log_ai_referral_visit() {
    if ( is_admin() ) {
        return;
    }
}

/**
 * Limpieza diaria: borra registros de más de 30 días, para que la
 * tabla no crezca indefinidamente en sitios con mucho tráfico de bots.
 */
add_action( 'citameia_prune_crawler_log', 'citameia_do_prune_crawler_log' );
function citameia_do_prune_crawler_log() {
    global $wpdb;
    $table = citameia_crawler_log_table();
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- $table siempre viene de citameia_crawler_log_table() (nombre fijo, sin input de usuario); limpieza periódica (cron) de una tabla propia del plugin. El caché no aplica a un DELETE de mantenimiento que no se lee después.
    $wpdb->query( "DELETE FROM {$table} WHERE visited_at < DATE_SUB(NOW(), INTERVAL 30 DAY)" );
}

if ( !wp_next_scheduled( 'citameia_prune_crawler_log' ) ) {
    wp_schedule_event( time(), 'daily', 'citameia_prune_crawler_log' );
}
/**
 * Misma limpieza, para la tabla de tráfico de referencia desde IA.
 */
add_action( 'citameia_prune_ai_referral_log', 'citameia_do_prune_ai_referral_log' );
function citameia_do_prune_ai_referral_log() {
    global $wpdb;
    $table = citameia_ai_referral_log_table();
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- $table siempre viene de citameia_ai_referral_log_table() (nombre fijo, sin input de usuario); limpieza periódica (cron) de una tabla propia del plugin. El caché no aplica a un DELETE de mantenimiento que no se lee después.
    $wpdb->query( "DELETE FROM {$table} WHERE visited_at < DATE_SUB(NOW(), INTERVAL 30 DAY)" );
}

if ( !wp_next_scheduled( 'citameia_prune_ai_referral_log' ) ) {
    wp_schedule_event( time(), 'daily', 'citameia_prune_ai_referral_log' );
}
/**
 * WordPress no trae un intervalo "semanal" por defecto, solo horario,
 * dos veces al día, y diario. Lo agregamos nosotros.
 */
add_filter( 'cron_schedules', 'citameia_add_weekly_cron_interval' );
function citameia_add_weekly_cron_interval(  $schedules  ) {
    $schedules['weekly'] = array(
        'interval' => 7 * DAY_IN_SECONDS,
        'display'  => 'Una vez por semana',
    );
    return $schedules;
}

/**
 * Guarda un punto de historial del score una vez por semana, sin
 * depender de que alguien entre al Panel para que se registre. Si
 * ademas alguien visita el Panel entre semana, geo_radar_record_score_history()
 * ya sabe actualizar el punto del día en vez de duplicarlo.
 */
add_action( 'citameia_weekly_score_snapshot', 'citameia_do_weekly_score_snapshot' );
function citameia_do_weekly_score_snapshot() {
    $audit = geo_radar_run_audit();
    $history = geo_radar_record_score_history( $audit['score'] );
    // El historial se sigue registrando aunque el sitio no tenga Pro, para que
    // no empiece de cero el día que se active la licencia. El correo semanal
    // en sí (que es el feature de venta) solo se manda con Pro activo.
    if ( citameia_is_pro() ) {
        citameia_send_weekly_email( $audit['score'], $history );
    }
}

if ( !wp_next_scheduled( 'citameia_weekly_score_snapshot' ) ) {
    wp_schedule_event( time(), 'weekly', 'citameia_weekly_score_snapshot' );
}
function citameia_forzar_email_html() {
    return 'text/html';
}

/**
 * "no-reply@" + el dominio real del sitio (no citameia.com fijo, este
 * plugin se instala en muchos sitios distintos, tiene que adaptarse
 * al dominio de cada uno). Usar el mismo dominio del sitio, solo
 * cambiando la parte antes del @, no debería afectar la entregabilidad
 * respecto al remitente por default de WordPress.
 */
function citameia_remitente_no_reply() {
    $dominio = wp_parse_url( home_url(), PHP_URL_HOST );
    return 'no-reply@' . $dominio;
}

function citameia_remitente_nombre() {
    return 'CítameIA';
}

/**
 * Guarda el correo al que deben llegar los reportes automáticos. Si se
 * deja vacío, se vuelve a usar el correo de administrador del sitio
 * (comportamiento de antes).
 */
add_action( 'admin_post_citameia_save_reportes_email', 'citameia_handle_save_reportes_email' );
function citameia_handle_save_reportes_email() {
    if ( !current_user_can( 'manage_options' ) ) {
        wp_die( esc_html__( 'No autorizado', 'citameia' ) );
    }
    if ( !citameia_is_pro() ) {
        wp_die( esc_html__( 'Esta función es parte de CítameIA Pro.', 'citameia' ) );
    }
    check_admin_referer( 'citameia_save_reportes_email' );
}

/**
 * Envía un reporte de una vez, a cualquier correo que se escriba en el
 * momento, no cambia el correo guardado para los envíos automáticos,
 * a menos que sea el mismo. Útil para mandárselo a un socio, un jefe,
 * o probar que sí llega.
 */
add_action( 'admin_post_citameia_send_report_now', 'citameia_handle_send_report_now' );
function citameia_handle_send_report_now() {
    if ( !current_user_can( 'manage_options' ) ) {
        wp_die( esc_html__( 'No autorizado', 'citameia' ) );
    }
    if ( !citameia_is_pro() ) {
        wp_die( esc_html__( 'Esta función es parte de CítameIA Pro.', 'citameia' ) );
    }
    check_admin_referer( 'citameia_send_report_now' );
}

function citameia_render_reportes_page() {
    ?>
	<div class="wrap geo-radar-wrap">
		<?php 
    citameia_render_admin_header( 'citameia-reportes' );
    ?>
		<p class="citameia-page-intro"><?php 
    esc_html_e( 'El score, una vez que llega a 100, ya no se mueve. Por eso aquí la actividad real de bots de IA es lo primero que se muestra, no el score. Es lo que sigue dando información nueva semana a semana.', 'citameia' );
    ?></p>

		<?php 
    if ( !citameia_is_pro() ) {
        ?>
			<?php 
        citameia_render_pro_lock( __( 'Reportes automáticos', 'citameia' ), array(
            __( 'PDF descargable con tu score y actividad de bots de IA', 'citameia' ),
            __( 'Correo semanal automático a ti o a tu cliente', 'citameia' ),
            __( 'Badge SVG de "score verificado" para compartir', 'citameia' ),
            __( 'Historial de todos los reportes enviados', 'citameia' )
        ) );
        ?>
		<?php 
    }
    ?>
		<?php 
    // This IF block is stripped entirely from the free version by Freemius.
    ?>
		<?php 
    ?>
	</div>
	<?php 
}

function citameia_render_crawlers_page() {
    ?>
	<div class="wrap geo-radar-wrap">
		<?php 
    citameia_render_admin_header( 'citameia-crawlers' );
    ?>
		<p class="citameia-page-intro"><?php 
    esc_html_e( 'Esto registra cuándo un bot de IA visita de verdad una página de tu sitio, a diferencia de "Validar schema", que solo revisa si tienen permitido hacerlo.', 'citameia' );
    ?></p>

		<?php 
    if ( !citameia_is_pro() ) {
        ?>
			<?php 
        citameia_render_pro_lock( __( 'Monitoreo de bots de IA', 'citameia' ), array(
            __( 'Ve qué bots de IA visitan tu sitio de verdad, no solo si tienen permiso', 'citameia' ),
            __( 'Historial de actividad reciente, con filtro de escaneos de vulnerabilidad', 'citameia' ),
            __( 'Resumen de los últimos 30 días por motor de IA', 'citameia' ),
            __( 'Visitas humanas reales referidas desde ChatGPT, Perplexity, Gemini, Claude, Copilot y más', 'citameia' )
        ) );
        ?>
		<?php 
    }
    ?>
		<?php 
    // This IF block is stripped entirely from the free version by Freemius.
    ?>
		<?php 
    ?>
	</div>
	<?php 
}

/**
 * =========================================================
 * PRESENCIA EXTERNA
 * =========================================================
 * A diferencia de todos los demás checklists de este plugin, estos
 * puntos NO se pueden verificar por código: pasan fuera de WordPress
 * (en Google, en redes, en directorios). Por eso se marcan a mano, no
 * se auditan solos. La motivación es real: la mayoría de lo que un
 * motor de IA usa para confiar en un negocio viene de fuera de su
 * propio sitio, no solo del schema técnico que instala este plugin.
 */
define( 'CITAMEIA_EXTERNAL_PRESENCE_OPTION', 'citameia_external_presence' );
function citameia_get_external_presence() {
    return get_option( CITAMEIA_EXTERNAL_PRESENCE_OPTION, array() );
}

function citameia_external_presence_items(  $s  ) {
    $es_digital = isset( $s['physical_presence'] ) && 'digital' === $s['physical_presence'];
    $items = array();
    if ( $es_digital ) {
        $items['linkedin'] = array(
            'title'      => __( 'Perfil de LinkedIn de la empresa', 'citameia' ),
            'desc'       => __( 'Para un negocio 100% digital, muchos motores de IA lo usan como fuente de confianza.', 'citameia' ),
            'link'       => 'https://www.linkedin.com/company/setup/new/',
            'link_label' => __( 'Crear página de empresa', 'citameia' ),
            'howto'      => array(
                __( 'Entra a linkedin.com/company/setup/new con tu cuenta personal — necesitas una cuenta de LinkedIn normal primero, la página de empresa se crea desde ahí.', 'citameia' ),
                __( 'Completa nombre, sitio web, industria, tamaño y descripción — usa exactamente el mismo nombre y descripción que ya tienes en Datos del negocio, no una versión distinta.', 'citameia' ),
                __( 'Sube el logo y una imagen de portada — un perfil sin foto se ve abandonado antes de que nadie lea nada.', 'citameia' ),
                __( 'Pide a los fundadores o al equipo que enlacen la página como su lugar de trabajo — eso le da actividad y credibilidad desde el primer día, sin tener que publicar nada todavía.', 'citameia' )
            ),
        );
    } else {
        $items['gbp'] = array(
            'title'      => __( 'Ficha de Google Business Profile reclamada', 'citameia' ),
            'desc'       => __( 'Es una de las fuentes que más usan las IA para negocios con ubicación física o de servicio local.', 'citameia' ),
            'link'       => 'https://business.google.com/',
            'link_label' => __( 'Reclamar mi ficha', 'citameia' ),
            'howto'      => array(
                __( 'Entra a business.google.com con tu correo del negocio (o crea uno dedicado si usas uno personal).', 'citameia' ),
                __( 'Busca tu negocio por nombre y dirección — si ya existe una ficha sin reclamar, Google te la ofrece directo.', 'citameia' ),
                __( 'Verifica la ficha: normalmente por postal (una carta con código a tu dirección) o por teléfono, según tu tipo de negocio.', 'citameia' ),
                __( 'Una vez verificada, completa horario, categoría, fotos, y una descripción — una ficha a medias ayuda menos que una completa.', 'citameia' )
            ),
        );
        $items['reviews'] = array(
            'title'      => __( 'Al menos 5 reseñas reales en Google', 'citameia' ),
            'desc'       => __( 'Las reseñas son una señal fuerte de que un negocio existe de verdad y es confiable.', 'citameia' ),
            'link'       => '',
            'link_label' => '',
            'howto'      => array(
                __( 'Desde tu ficha de Google Business Profile, copia tu "link corto para reseñas" (Google te lo da una vez verificada la ficha).', 'citameia' ),
                __( 'Mándaselo directo a 5-10 clientes recientes contentos — por WhatsApp o correo, personal, no en redes.', 'citameia' ),
                __( 'El mejor momento para pedirlo: justo después de resolverles algo bien, no meses después.', 'citameia' ),
                __( 'Responde cada reseña que recibas, buena o mala — Google y las IA lo interpretan como que el negocio está activo y atento.', 'citameia' )
            ),
        );
    }
    $items['social'] = array(
        'title'      => __( 'Redes sociales activas y enlazadas', 'citameia' ),
        'desc'       => __( 'Con publicaciones recientes, no solo un perfil creado y abandonado. Ya deberían estar ligadas en "Datos del negocio".', 'citameia' ),
        'link'       => admin_url( 'admin.php?page=citameia-datos' ),
        'link_label' => __( 'Revisar mis redes', 'citameia' ),
        'howto'      => array(__( 'Enlázalas primero en Datos del negocio, si no lo has hecho — sin eso, ni cuenta para el schema.org.', 'citameia' ), __( '"Activa" no significa mucho: 1-2 publicaciones al mes ya marca la diferencia frente a un perfil abandonado desde hace un año.', 'citameia' ), __( 'Prioriza la red donde de verdad esté tu cliente — no necesitas las 5 activas, con 1-2 bien llevadas es más creíble que 5 abandonadas.', 'citameia' )),
    );
    $items['directorio'] = array(
        'title'      => __( 'Presencia en al menos un directorio relevante de tu giro', 'citameia' ),
        'desc'       => __( 'Cámaras de comercio, directorios de tu industria, o marketplaces relacionados con lo que vendes.', 'citameia' ),
        'link'       => '',
        'link_label' => '',
        'howto'      => array(__( 'Busca en Google "directorio de [tu giro] en [tu ciudad/país]" — casi todas las industrias tienen al menos uno.', 'citameia' ), __( 'Revisa si tu cámara de comercio local tiene directorio de socios en su sitio web.', 'citameia' ), __( 'Si vendes productos, considera marketplaces del sector (no solo los genéricos como Amazon/MercadoLibre).', 'citameia' )),
    );
    $items['nap'] = array(
        'title'      => __( 'Nombre, dirección y teléfono idénticos en todos lados', 'citameia' ),
        'desc'       => __( 'Si tu negocio aparece con datos distintos en tu sitio, Google Business, y redes, eso le resta confianza a las IA. Se llama consistencia NAP.', 'citameia' ),
        'link'       => '',
        'link_label' => '',
        'howto'      => array(
            __( 'Junta en un solo lugar cómo aparece tu negocio en: tu sitio, Google Business, Facebook, Instagram, y cualquier directorio donde estés.', 'citameia' ),
            __( 'Compáralos letra por letra — "Av." vs "Avenida", con o sin número de suite, "Tel." vs "WhatsApp", son las inconsistencias más comunes.', 'citameia' ),
            __( 'Elige una sola versión "oficial" (la misma que uses en Datos del negocio) y corrige el resto para que coincida exacto.', 'citameia' ),
            __( 'Revísalo cada pocos meses — es fácil que quede desactualizado si cambias de número o local.', 'citameia' )
        ),
    );
    $items['mencion'] = array(
        'title'      => __( 'Al menos una mención o enlace desde otro sitio', 'citameia' ),
        'desc'       => __( 'Un blog, un cliente, un socio, una nota de prensa: cualquier lugar fuera del tuyo que te mencione con un enlace.', 'citameia' ),
        'link'       => '',
        'link_label' => '',
        'howto'      => array(
            __( 'Empieza por lo obvio: proveedores, clientes frecuentes, o socios con quienes ya tienes relación — pídeles que te mencionen en su sitio.', 'citameia' ),
            __( 'Ofrece un testimonio a cambio del de ellos — muchos negocios tienen página de "clientes" o "casos de éxito" donde caben ambos.', 'citameia' ),
            __( 'Si participas en algún evento, cámara, o asociación de tu industria, confirma que tu negocio aparezca listado con enlace, no solo mencionado.', 'citameia' ),
            __( 'Un artículo de invitado (guest post) en un blog relacionado a tu giro también cuenta, y no necesitas ser escritor — muchos aceptan que tú des las ideas y ellos redacten.', 'citameia' )
        ),
    );
    return $items;
}

add_action( 'admin_post_citameia_save_external_presence', 'citameia_handle_save_external_presence' );
function citameia_handle_save_external_presence() {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- verificación del nonce; mismo caso documentado arriba (wp_verify_nonce no lo reconoce el analizador estático como sanitizador).
    if ( !current_user_can( 'manage_options' ) || !isset( $_POST['citameia_presencia_nonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['citameia_presencia_nonce'] ) ), 'citameia_save_external_presence' ) ) {
        wp_die( esc_html__( 'No autorizado', 'citameia' ) );
    }
    $s = geo_radar_get_settings();
    $item_keys = array_keys( citameia_external_presence_items( $s ) );
    // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- (array) wp_unslash() está bien aquí: los valores nunca se guardan tal cual, solo se usan con in_array() contra $item_keys (una lista fija nuestra); lo que se guarda en la opción siempre es un booleano, nunca el valor crudo del usuario.
    $marcados = ( isset( $_POST['presencia'] ) ? (array) wp_unslash( $_POST['presencia'] ) : array() );
    $guardar = array();
    foreach ( $item_keys as $key ) {
        $guardar[$key] = in_array( $key, $marcados, true );
    }
    update_option( CITAMEIA_EXTERNAL_PRESENCE_OPTION, $guardar );
    wp_safe_redirect( admin_url( 'admin.php?page=citameia-presencia&guardado=1' ) );
    exit;
}

function citameia_render_external_presence_page() {
    $s = geo_radar_get_settings();
    $items = citameia_external_presence_items( $s );
    $estado = citameia_get_external_presence();
    $total = count( $items );
    $hechos = 0;
    foreach ( $items as $key => $item ) {
        if ( !empty( $estado[$key] ) ) {
            $hechos++;
        }
    }
    $pct = ( $total > 0 ? round( $hechos / $total * 100 ) : 0 );
    ?>
	<div class="wrap geo-radar-wrap">
		<?php 
    citameia_render_admin_header( 'citameia-presencia' );
    ?>
		<p class="citameia-page-intro"><?php 
    esc_html_e( 'La mayoría de lo que un motor de IA usa para confiar en un negocio viene de fuera de su propio sitio: reseñas, directorios, menciones. El schema técnico que instala este plugin es solo una parte de la ecuación, la parte que si controlas por completo. Esto es la otra parte.', 'citameia' );
    ?></p>

		<div class="notice notice-info" style="padding:12px 14px;">
			<p style="margin:0;"><strong><?php 
    esc_html_e( 'Esta lista no se audita sola.', 'citameia' );
    ?></strong> <?php 
    esc_html_e( 'Pasa fuera de WordPress, así que la vas marcando tú mismo conforme la completes.', 'citameia' );
    ?></p>
		</div>

		<?php 
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- solo lectura para decidir qué aviso mostrar tras un redirect; no se procesa ningún dato.
    ?>
		<?php 
    if ( isset( $_GET['guardado'] ) ) {
        ?>
			<div class="notice notice-success is-dismissible" style="padding:12px 14px;"><p style="margin:0;"><?php 
        esc_html_e( 'Guardado.', 'citameia' );
        ?></p></div>
		<?php 
    }
    ?>

		<div class="citameia-step-card">
			<div class="citameia-step-head"><span class="citameia-step-num">1</span><h2><?php 
    esc_html_e( 'Tu presencia fuera del sitio', 'citameia' );
    ?></h2></div>

			<div class="progress-row">
				<div class="progress-track"><div class="progress-fill" style="width:<?php 
    echo esc_attr( $pct );
    ?>%;"></div></div>
								<div class="progress-label"><?php 
    /* translators: %1$s: tareas completadas, %2$s: total de tareas */
    printf( esc_html__( '%1$s de %2$s completados', 'citameia' ), esc_html( $hechos ), esc_html( $total ) );
    ?></div>
			</div>

			<form method="post" action="<?php 
    echo esc_url( admin_url( 'admin-post.php' ) );
    ?>">
				<input type="hidden" name="action" value="citameia_save_external_presence">
				<?php 
    wp_nonce_field( 'citameia_save_external_presence', 'citameia_presencia_nonce' );
    ?>

				<div class="task-list">
					<?php 
    foreach ( $items as $key => $item ) {
        $marcado = !empty( $estado[$key] );
        ?>
						<div class="task-row<?php 
        echo ( $marcado ? '' : ' warn' );
        ?>">
							<label style="display:flex;align-items:flex-start;gap:16px;width:100%;cursor:pointer;">
								<input type="checkbox" name="presencia[]" value="<?php 
        echo esc_attr( $key );
        ?>" <?php 
        checked( $marcado );
        ?> style="margin-top:4px;">
								<span class="task-body">
									<span class="task-title"><?php 
        echo esc_html( $item['title'] );
        ?></span>
									<span class="task-desc">
										<?php 
        echo esc_html( $item['desc'] );
        ?>
										<?php 
        if ( !empty( $item['link'] ) ) {
            ?>
											<br><a href="<?php 
            echo esc_url( $item['link'] );
            ?>" target="_blank" rel="noopener"><?php 
            echo esc_html( $item['link_label'] );
            ?> ↗</a>
										<?php 
        }
        ?>
									</span>
									<?php 
        if ( !empty( $item['howto'] ) ) {
            ?>
										<button type="button" class="citameia-howto-toggle" onclick="event.preventDefault(); event.stopPropagation(); citameiaToggleHowto(this);">
											<span class="citameia-howto-chev">▾</span> <?php 
            esc_html_e( '¿Cómo lo consigo?', 'citameia' );
            ?>
										</button>
									<?php 
        }
        ?>
								</span>
							</label>
							<?php 
        if ( !empty( $item['howto'] ) ) {
            ?>
								<div class="citameia-howto-body">
									<ol>
										<?php 
            foreach ( $item['howto'] as $paso ) {
                ?>
											<li><?php 
                echo esc_html( $paso );
                ?></li>
										<?php 
            }
            ?>
									</ol>
									<?php 
            if ( !empty( $item['link'] ) ) {
                ?>
										<a href="<?php 
                echo esc_url( $item['link'] );
                ?>" target="_blank" rel="noopener" class="citameia-howto-cta"><?php 
                echo esc_html( $item['link_label'] );
                ?> ↗</a>
									<?php 
            }
            ?>
								</div>
							<?php 
        }
        ?>
						</div>
					<?php 
    }
    ?>
				</div>

				<div class="btn-row" style="margin-top:16px;">
					<?php 
    submit_button(
        __( 'Guardar avance', 'citameia' ),
        'primary',
        'submit',
        false
    );
    ?>
				</div>
			</form>
		</div>
	</div>
	<?php 
    $citameia_howto_js = "function citameiaToggleHowto( btn ) {\n" . "\tbtn.classList.toggle( 'is-open' );\n" . "\tvar row = btn.closest( '.task-row' );\n" . "\tvar howto = row ? row.querySelector( '.citameia-howto-body' ) : null;\n" . "\tif ( howto ) { howto.classList.toggle( 'is-open' ); }\n" . '}';
    wp_register_script(
        'citameia-howto-toggle',
        false,
        array(),
        CITAMEIA_VERSION,
        true
    );
    wp_enqueue_script( 'citameia-howto-toggle' );
    wp_add_inline_script( 'citameia-howto-toggle', $citameia_howto_js );
    ?>
	<?php 
}

function citameia_fetch_robots_txt() {
    $resp = wp_remote_get( home_url( '/robots.txt' ), array(
        'timeout'     => 8,
        'redirection' => 3,
    ) );
    if ( is_wp_error( $resp ) ) {
        return '';
    }
    if ( wp_remote_retrieve_response_code( $resp ) >= 400 ) {
        return '';
    }
    return (string) wp_remote_retrieve_body( $resp );
}

/**
 * Agrupa un robots.txt en bloques User-agent / Disallow / Allow,
 * respetando que varias líneas "User-agent:" seguidas pertenecen al
 * mismo grupo (como indica el estándar).
 */
function citameia_parse_robots_groups(  $content  ) {
    $lines = preg_split( '/\\r\\n|\\r|\\n/', (string) $content );
    $groups = array();
    $current_index = -1;
    $prev_was_agent = false;
    foreach ( $lines as $raw_line ) {
        $line = trim( $raw_line );
        if ( '' === $line || '#' === substr( $line, 0, 1 ) ) {
            $prev_was_agent = false;
            continue;
        }
        if ( 0 === stripos( $line, 'user-agent:' ) ) {
            $agent = strtolower( trim( substr( $line, strlen( 'user-agent:' ) ) ) );
            if ( !$prev_was_agent ) {
                $groups[] = array(
                    'agents'   => array(),
                    'disallow' => array(),
                    'allow'    => array(),
                );
                $current_index = count( $groups ) - 1;
            }
            $groups[$current_index]['agents'][] = $agent;
            $prev_was_agent = true;
        } elseif ( 0 === stripos( $line, 'disallow:' ) && $current_index >= 0 ) {
            $groups[$current_index]['disallow'][] = trim( substr( $line, strlen( 'disallow:' ) ) );
            $prev_was_agent = false;
        } elseif ( 0 === stripos( $line, 'allow:' ) && $current_index >= 0 ) {
            $groups[$current_index]['allow'][] = trim( substr( $line, strlen( 'allow:' ) ) );
            $prev_was_agent = false;
        } else {
            $prev_was_agent = false;
        }
    }
    return $groups;
}

function citameia_group_blocks_root(  $group  ) {
    $blocks_all = false;
    foreach ( $group['disallow'] as $path ) {
        if ( '/' === $path ) {
            $blocks_all = true;
        }
    }
    foreach ( $group['allow'] as $path ) {
        if ( '/' === $path || '' === $path ) {
            $blocks_all = false;
        }
    }
    return $blocks_all;
}

function citameia_bot_is_blocked(  $groups, $bot_name_lower  ) {
    foreach ( $groups as $g ) {
        if ( in_array( $bot_name_lower, $g['agents'], true ) ) {
            return citameia_group_blocks_root( $g );
        }
    }
    foreach ( $groups as $g ) {
        if ( in_array( '*', $g['agents'], true ) ) {
            return citameia_group_blocks_root( $g );
        }
    }
    return false;
}

/**
 * Resultado cacheado por 6 horas para no golpear el robots.txt en cada carga del Panel.
 */
function citameia_check_ai_bots() {
    $cached = get_transient( 'citameia_ai_bots_check' );
    if ( false !== $cached ) {
        return $cached;
    }
    $content = citameia_fetch_robots_txt();
    if ( '' === trim( $content ) ) {
        $result = array(
            'checked'       => false,
            'blocked'       => array(),
            'content_found' => false,
        );
        set_transient( 'citameia_ai_bots_check', $result, 6 * HOUR_IN_SECONDS );
        return $result;
    }
    $groups = citameia_parse_robots_groups( $content );
    $blocked = array();
    foreach ( citameia_ai_bot_list() as $key => $label ) {
        if ( citameia_bot_is_blocked( $groups, $key ) ) {
            $blocked[] = $label;
        }
    }
    $result = array(
        'checked'       => true,
        'blocked'       => $blocked,
        'content_found' => true,
    );
    set_transient( 'citameia_ai_bots_check', $result, 6 * HOUR_IN_SECONDS );
    return $result;
}

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_run_audit() {
    $s = geo_radar_get_settings();
    $checks = array();
    $checks['nombre_desc'] = array(
        'label'    => __( 'Nombre y descripción del negocio configurados', 'citameia' ),
        'pass'     => !empty( $s['business_name'] ) && !empty( $s['description'] ),
        'weight'   => 10,
        'category' => 'datos',
        'effort'   => 'bajo',
        'tip'      => __( 'Ve a "Datos del negocio" y completa nombre y descripción. Es la base de todo el schema.', 'citameia' ),
    );
    $presence = ( isset( $s['physical_presence'] ) ? $s['physical_presence'] : 'visita' );
    $is_digital = 'digital' === $presence;
    $is_reparto = 'reparto' === $presence;
    if ( !$is_digital ) {
        $checks['direccion'] = array(
            'label'    => __( 'Dirección completa (calle, ciudad, estado)', 'citameia' ),
            'pass'     => !empty( $s['street'] ) && !empty( $s['city'] ) && !empty( $s['state'] ),
            'weight'   => 15,
            'category' => 'datos',
            'effort'   => 'bajo',
            'tip'      => ( $is_reparto ? __( 'Aunque no recibas visitas, tu ciudad y estado ayudan al schema y a que la IA te ubique geográficamente para búsquedas locales.', 'citameia' ) : __( 'Sin dirección, no puedes usar schema LocalBusiness completo ni aparecer en búsquedas locales con IA.', 'citameia' ) ),
        );
    }
    $checks['telefono'] = array(
        'label'    => __( 'Teléfono de contacto configurado', 'citameia' ),
        'pass'     => !empty( $s['phone'] ),
        'weight'   => 10,
        'category' => 'datos',
        'effort'   => 'bajo',
        'tip'      => __( 'Agrega un teléfono visible; los motores de IA lo usan para validar que el negocio es real.', 'citameia' ),
    );
    $checks['logo'] = array(
        'label'    => __( 'Logo configurado (URL de imagen)', 'citameia' ),
        'pass'     => !empty( $s['logo_url'] ),
        'weight'   => 5,
        'category' => 'datos',
        'effort'   => 'bajo',
        'tip'      => __( 'Sube el logo en "Datos del negocio" para que aparezca en el schema Organization.', 'citameia' ),
    );
    $checks['redes'] = array(
        'label'    => __( 'Al menos una red social o Google Business Profile vinculado', 'citameia' ),
        'pass'     => !empty( $s['social_facebook'] ) || !empty( $s['social_instagram'] ) || !empty( $s['social_gbp'] ),
        'weight'   => 10,
        'category' => 'datos',
        'effort'   => 'bajo',
        'tip'      => __( 'Vincula tus perfiles para reforzar la propiedad "sameAs" del schema. Ayuda a que la IA confirme que es la misma marca.', 'citameia' ),
    );
    if ( !$is_digital ) {
        $checks['gbp'] = array(
            'label'    => __( 'Google Business Profile vinculado', 'citameia' ),
            'pass'     => !empty( $s['social_gbp'] ),
            'weight'   => 10,
            'category' => 'datos',
            'effort'   => 'medio',
            'tip'      => ( $is_reparto ? __( 'Aunque no tengas local visitable, puedes crear tu ficha como "negocio de área de servicio" y ocultar tu dirección exacta. Sigue siendo una de las fuentes que más usa la IA para negocios locales.', 'citameia' ) : __( 'Cuando alguien pregunta a una IA por un negocio en su ciudad, tu ficha de Google Business es una de las fuentes principales.', 'citameia' ) ),
        );
    }
    $faq_count = geo_radar_count_faq_blocks();
    $faq_detail = '';
    if ( $faq_count > 0 ) {
        /* translators: %s: número de publicaciones donde se encontró el FAQ */
        $faq_detail = sprintf( __( 'Encontrados en %s publicación(es).', 'citameia' ), $faq_count );
    }
    $checks['faq'] = array(
        'label'    => __( 'Al menos un bloque de preguntas frecuentes (FAQ) publicado', 'citameia' ),
        'pass'     => $faq_count > 0,
        'weight'   => 20,
        'category' => 'contenido',
        'effort'   => 'medio',
        'tip'      => __( 'Usa el shortcode [geo_faq] en tus páginas clave. Ve a "FAQ y Schema" para ver cómo.', 'citameia' ),
        'detail'   => $faq_detail,
    );
    $checks['ssl'] = array(
        'label'    => __( 'El sitio usa HTTPS', 'citameia' ),
        'pass'     => is_ssl() || 0 === strpos( home_url(), 'https' ),
        'weight'   => 5,
        'category' => 'tecnico',
        'effort'   => 'alto',
        'tip'      => __( 'Sin HTTPS, los motores de IA confían menos en tu contenido como fuente.', 'citameia' ),
    );
    $llms_exists = file_exists( ABSPATH . 'llms.txt' );
    $checks['llms_txt'] = array(
        'label'    => __( 'Archivo llms.txt generado', 'citameia' ),
        'pass'     => $llms_exists,
        'weight'   => 15,
        'category' => 'tecnico',
        'effort'   => 'bajo',
        'tip'      => __( 'Ve a la sección "llms.txt" y da clic en "Generar / actualizar ahora".', 'citameia' ),
    );
    $bots_result = citameia_check_ai_bots();
    if ( $bots_result['checked'] && !empty( $bots_result['blocked'] ) ) {
        /* translators: %s: lista de bots bloqueados, separados por coma */
        $bots_detail = sprintf( __( 'Bloqueados: %s.', 'citameia' ), implode( ', ', $bots_result['blocked'] ) );
        $checks['robots_bots'] = array(
            'label'    => __( 'Tu robots.txt no bloquea a los motores de IA', 'citameia' ),
            'pass'     => false,
            'weight'   => 15,
            'category' => 'tecnico',
            'effort'   => 'medio',
            'tip'      => __( 'Tu robots.txt está bloqueando a estos motores; ni el mejor schema del mundo sirve si no pueden leer tu sitio. Revisa tu archivo robots.txt (o el plugin de seguridad que lo controle) y quítales el bloqueo.', 'citameia' ),
            'detail'   => $bots_detail,
        );
    } else {
        $checks['robots_bots'] = array(
            'label'    => __( 'Tu robots.txt no bloquea a los motores de IA', 'citameia' ),
            'pass'     => true,
            'weight'   => 15,
            'category' => 'tecnico',
            'effort'   => 'medio',
            'tip'      => __( 'Revisamos tu robots.txt buscando bloqueos a GPTBot, ClaudeBot, PerplexityBot y Google-Extended. Es la base de todo: si un motor no puede leer tu sitio, nada más de esta lista importa.', 'citameia' ),
        );
    }
    if ( class_exists( 'WooCommerce' ) ) {
        $total_products = geo_radar_woo_products_with_data();
        /* translators: %1$s: productos con datos completos, %2$s: total de productos */
        $woo_detail = sprintf( __( '%1$s de %2$s productos listos.', 'citameia' ), $total_products['con_datos'], $total_products['total'] );
        $checks['woo'] = array(
            'label'    => __( 'Productos de WooCommerce con datos completos (precio + descripción)', 'citameia' ),
            'pass'     => $total_products['con_datos'] > 0,
            'weight'   => 10,
            'category' => 'contenido',
            'effort'   => 'medio',
            'tip'      => __( 'Completa precio y descripción en tus productos para que generen schema Product automáticamente.', 'citameia' ),
            'detail'   => $woo_detail,
        );
    }
    $total_weight = 0;
    $earned = 0;
    foreach ( $checks as $c ) {
        $total_weight += $c['weight'];
        if ( $c['pass'] ) {
            $earned += $c['weight'];
        }
    }
    $score = ( $total_weight > 0 ? (int) round( $earned / $total_weight * 100 ) : 0 );
    return array(
        'score'  => $score,
        'checks' => $checks,
    );
}

/**
 * Agrupa el checklist en sub-dimensiones con su propio mini-score, en
 * vez de una sola lista plana. Mismo dato que ya calculamos, solo
 * organizado para que se entienda de un vistazo dónde está más fuerte
 * o más débil el sitio.
 */
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_audit_categories(  $checks  ) {
    $labels = array(
        'datos'     => __( 'Datos del negocio', 'citameia' ),
        'contenido' => __( 'Contenido para IA', 'citameia' ),
        'tecnico'   => __( 'Base técnica', 'citameia' ),
    );
    $grupos = array();
    foreach ( $checks as $key => $c ) {
        $cat = ( isset( $c['category'] ) ? $c['category'] : 'tecnico' );
        if ( !isset( $grupos[$cat] ) ) {
            $grupos[$cat] = array(
                'label'  => ( isset( $labels[$cat] ) ? $labels[$cat] : ucfirst( $cat ) ),
                'weight' => 0,
                'earned' => 0,
            );
        }
        $grupos[$cat]['weight'] += $c['weight'];
        if ( $c['pass'] ) {
            $grupos[$cat]['earned'] += $c['weight'];
        }
    }
    foreach ( $grupos as $cat => $g ) {
        $grupos[$cat]['score'] = ( $g['weight'] > 0 ? round( $g['earned'] / $g['weight'] * 100 ) : 0 );
    }
    return $grupos;
}

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_count_faq_blocks() {
    global $wpdb;
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- parte del cálculo del score de citabilidad, corre cuando el usuario carga el Panel o Valida schema; debe reflejar el estado actual (si acaba de agregar un FAQ, espera ver el cambio de inmediato, no una versión cacheada).
    $count = $wpdb->get_var( "SELECT COUNT(ID) FROM {$wpdb->posts}\n\t\t WHERE post_status = 'publish'\n\t\t AND post_content LIKE '%[geo_faq%'" );
    $count = (int) $count;
    // Además de buscar el shortcode guardado en posts/páginas, revisamos
    // si el schema FAQ ya se imprimió de verdad en alguna carga de página
    // reciente. Esto cubre el caso de un shortcode llamado directo desde
    // un archivo del theme (con do_shortcode()), que nunca queda guardado
    // en post_content aunque el schema sí se esté generando de verdad.
    if ( 0 === $count && get_option( 'citameia_faq_schema_detectado' ) ) {
        $count = 1;
    }
    return $count;
}

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_woo_products_with_data() {
    global $wpdb;
    $result = array(
        'total'     => 0,
        'con_datos' => 0,
    );
    if ( !class_exists( 'WooCommerce' ) ) {
        return $result;
    }
    // Consulta SQL directa: cuenta TODOS los productos, sin importar si son 20 o 20,000.
    // Evita cargar objetos de producto en memoria uno por uno.
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- también parte del cálculo del score, mismo razonamiento que geo_radar_count_faq_blocks() arriba: debe reflejar inventario/datos actuales, no cacheados.
    $total = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(ID) FROM {$wpdb->posts} WHERE post_type = %s AND post_status = %s", 'product', 'publish' ) );
    $result['total'] = (int) $total;
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- misma razón que la consulta anterior en esta función: debe reflejar el inventario actual, no una versión cacheada.
    $con_datos = $wpdb->get_var( $wpdb->prepare(
        "SELECT COUNT(DISTINCT p.ID) FROM {$wpdb->posts} p\n\t\t\t INNER JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID AND pm.meta_key = %s\n\t\t\t WHERE p.post_type = %s AND p.post_status = %s\n\t\t\t AND pm.meta_value != ''\n\t\t\t AND ( TRIM( p.post_excerpt ) != '' OR TRIM( p.post_content ) != '' )",
        '_price',
        'product',
        'publish'
    ) );
    $result['con_datos'] = (int) $con_datos;
    return $result;
}

/**
 * =========================================================
 * HISTORIAL DEL SCORE
 * =========================================================
 * Guarda una entrada por día (se sobrescribe si ya se registró hoy) para
 * poder mostrar la tendencia real, no solo el número del momento.
 */
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_record_score_history(  $score  ) {
    $history = get_option( 'geo_radar_score_history', array() );
    return $history;
}

/**
 * =========================================================
 * PANTALLA: PANEL (dashboard con score)
 * =========================================================
 */
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_render_kpi_cards(  $audit, $history, $score  ) {
    $dias_midiendo = count( $history );
    $delta = 0;
    if ( $dias_midiendo >= 2 ) {
        $delta = end( $history )['score'] - $history[0]['score'];
    }
    $delta_txt = (( $delta > 0 ? '+' : '' )) . $delta;
    $delta_color = ( $delta > 0 ? '#1E7A4C' : (( $delta < 0 ? '#B3261E' : '#818B92' )) );
    $delta_arrow = ( $delta > 0 ? '↑' : (( $delta < 0 ? '↓' : '→' )) );
    $faq_count = geo_radar_count_faq_blocks();
    $pass_count = count( array_filter( $audit['checks'], function ( $c ) {
        return $c['pass'];
    } ) );
    $total_count = count( $audit['checks'] );
    $fourth_label = __( 'Días monitoreando', 'citameia' );
    $fourth_value = (string) $dias_midiendo;
    if ( class_exists( 'WooCommerce' ) ) {
        $wc = geo_radar_woo_products_with_data();
        if ( $wc['total'] > 0 ) {
            $fourth_label = __( 'Productos listos', 'citameia' );
            $fourth_value = $wc['con_datos'] . '/' . $wc['total'];
        }
    }
    ?>
	<div class="geo-radar-kpi-grid">
		<div class="geo-radar-kpi-card">
			<div class="geo-radar-kpi-num" style="color:<?php 
    echo esc_attr( ( $score >= 80 ? '#1E7A4C' : (( $score >= 50 ? '#8A6529' : '#B3261E' )) ) );
    ?>;"><?php 
    echo esc_html( $score );
    ?><span class="unit">/100</span></div>
			<div class="geo-radar-kpi-label"><?php 
    esc_html_e( 'Score actual', 'citameia' );
    ?></div>
		</div>
		<div class="geo-radar-kpi-card">
			<div class="geo-radar-kpi-num" style="color:<?php 
    echo esc_attr( $delta_color );
    ?>;"><?php 
    echo esc_html( $delta_arrow . ' ' . $delta_txt );
    ?></div>
						<div class="geo-radar-kpi-label"><?php 
    /* translators: %s: número de mediciones de score registradas */
    printf( esc_html__( 'Tendencia (%s mediciones)', 'citameia' ), esc_html( $dias_midiendo ) );
    ?></div>
		</div>
		<div class="geo-radar-kpi-card">
			<div class="geo-radar-kpi-num"><?php 
    echo esc_html( $pass_count . '/' . $total_count );
    ?></div>
			<div class="geo-radar-kpi-label"><?php 
    esc_html_e( 'Tareas completadas', 'citameia' );
    ?></div>
		</div>
		<div class="geo-radar-kpi-card">
			<div class="geo-radar-kpi-num"><?php 
    echo esc_html( $fourth_value );
    ?></div>
			<div class="geo-radar-kpi-label"><?php 
    echo esc_html( $fourth_label );
    ?></div>
		</div>
	</div>
	<?php 
}

/**
 * =========================================================
 * ENCABEZADO DE MARCA (compartido por todas las pantallas)
 * =========================================================
 * Barra superior con el logo, las pestañas de navegación entre
 * secciones, y un enlace de soporte hacia citameia.com. Se llama al
 * principio de cada función de render de abajo, para que las 6
 * pantallas del plugin se sientan como un solo producto, no como
 * páginas sueltas de ajustes de WordPress.
 */
function citameia_render_admin_header(  $active_slug  ) {
    $tabs = array(
        'citameia'           => __( 'Panel', 'citameia' ),
        'citameia-datos'     => __( 'Datos del negocio', 'citameia' ),
        'citameia-faq'       => __( 'FAQ y Schema', 'citameia' ),
        'citameia-validar'   => __( 'Validar schema', 'citameia' ),
        'citameia-menciones' => __( 'Pruebas en IA', 'citameia' ),
        'citameia-crawlers'  => __( 'Monitoreo de IA', 'citameia' ),
        'citameia-presencia' => __( 'Presencia externa', 'citameia' ),
        'citameia-reportes'  => __( 'Reportes', 'citameia' ),
        'citameia-compartir' => __( 'Compartir', 'citameia' ),
        'citameia-llms'      => __( 'llms.txt', 'citameia' ),
    );
    ?>
	<div class="citameia-admin-header">
		<div class="citameia-admin-header-top">
			<div class="citameia-brand"><span class="c">Cítame</span><span class="ia">.IA</span></div>
			<a href="https://citameia.com/#contacto" target="_blank" rel="noopener" class="citameia-support-link"><?php 
    esc_html_e( '¿Necesitas ayuda? Agenda soporte →', 'citameia' );
    ?></a>
		</div>
		<div class="citameia-tabs">
			<?php 
    foreach ( $tabs as $slug => $label ) {
        ?>
				<a href="<?php 
        echo esc_url( admin_url( 'admin.php?page=' . $slug ) );
        ?>" class="citameia-tab<?php 
        echo ( $slug === $active_slug ? ' active' : '' );
        ?>"><?php 
        echo esc_html( $label );
        ?></a>
			<?php 
    }
    ?>
		</div>
	</div>
	<?php 
}

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_render_dashboard() {
    $audit = geo_radar_run_audit();
    $score = $audit['score'];
    $color = ( $score >= 80 ? '#1E7A4C' : (( $score >= 50 ? '#8A6529' : '#B3261E' )) );
    $history = geo_radar_record_score_history( $score );
    $deg = round( $score / 100 * 360 );
    ?>
	<div class="wrap geo-radar-wrap">
		<?php 
    citameia_render_admin_header( 'citameia' );
    ?>
		<p class="citameia-page-intro"><?php 
    esc_html_e( 'Este score estima qué tan listo está tu sitio para ser encontrado y citado por buscadores de IA (ChatGPT, Gemini, Perplexity, Google AI Overviews), además de mejorar tu SEO tradicional.', 'citameia' );
    ?></p>


		<?php 
    $seo_plugins = citameia_detect_seo_plugins();
    $core_conflict = $seo_plugins['any'];
    $product_conflict = citameia_should_skip_product_schema();
    ?>
		<?php 
    if ( $core_conflict || $product_conflict ) {
        ?>
			<div class="notice notice-info" style="padding:12px 14px;">
				<p style="margin:0;">
					<?php 
        if ( $core_conflict ) {
            ?>
												<strong><?php 
            /* translators: %s: nombre del plugin de SEO detectado (Yoast SEO o Rank Math) */
            printf( esc_html__( 'Detectamos %s activo.', 'citameia' ), esc_html( ( $seo_plugins['yoast'] ? 'Yoast SEO' : 'Rank Math' ) ) );
            ?></strong>
						<?php 
            /* translators: %s: nombre corto del plugin de SEO detectado */
            printf( esc_html__( 'Para no generar schema.org duplicado o contradictorio, CítameIA desactivó automáticamente su propio schema de Organization, WebSite y Article, eso ya lo cubre %s.', 'citameia' ), esc_html( ( $seo_plugins['yoast'] ? 'Yoast' : 'Rank Math' ) ) );
            ?>
					<?php 
        }
        ?>
					<?php 
        if ( $product_conflict ) {
            ?>
						<?php 
            echo ( $core_conflict ? esc_html__( 'También se desactivó', 'citameia' ) : '<strong>' . esc_html__( 'Se desactivó automáticamente', 'citameia' ) . '</strong>' );
            ?>
						<?php 
            /* translators: %s: nombre(s) del/los plugin(s) que ya generan schema de Producto */
            printf( esc_html__( 'el schema de Producto de WooCommerce, porque ya lo genera %s.', 'citameia' ), esc_html( implode( ' y ', citameia_product_conflict_names() ) ) );
            ?>
					<?php 
        }
        ?>
					<?php 
        esc_html_e( 'Las FAQs con [geo_faq] y el archivo llms.txt siguen funcionando igual, son independientes.', 'citameia' );
        ?>
				</p>
			</div>
		<?php 
    }
    ?>

		<div class="score-section">
			<div class="score-dial" style="background:conic-gradient(<?php 
    echo esc_attr( $color );
    ?> 0deg <?php 
    echo esc_attr( $deg );
    ?>deg, var(--bg-alt) <?php 
    echo esc_attr( $deg );
    ?>deg 360deg);">
				<span style="color:<?php 
    echo esc_attr( $color );
    ?>;"><?php 
    echo esc_html( $score );
    ?></span>
				<small>/100</small>
			</div>
			<div class="score-copy">
				<h2>
					<?php 
    if ( 100 === $score ) {
        ?>
						<?php 
        esc_html_e( 'Score técnico completo', 'citameia' );
        ?>
					<?php 
    } elseif ( $score >= 80 ) {
        ?>
						<?php 
        esc_html_e( 'Muy bien', 'citameia' );
        ?>
					<?php 
    } elseif ( $score >= 50 ) {
        ?>
						<?php 
        esc_html_e( 'Vas por buen camino', 'citameia' );
        ?>
					<?php 
    } else {
        ?>
						<?php 
        esc_html_e( 'Hay trabajo por hacer', 'citameia' );
        ?>
					<?php 
    }
    ?>
				</h2>
				<p>
					<?php 
    if ( 100 === $score ) {
        ?>
						<?php 
        printf( 
            /* translators: 1: enlace a Pruebas en IA, 2: enlace a Presencia externa */
            esc_html__( 'Completaste todo lo que este checklist audita. Esto no garantiza que las IA te citen mañana, eso no lo puede prometer ninguna herramienta. Sigue registrando pruebas reales en %1$s y trabajando tu %2$s para confirmarlo con el tiempo.', 'citameia' ),
            '<a href="' . esc_url( admin_url( 'admin.php?page=citameia-menciones' ) ) . '">' . esc_html__( 'Pruebas en IA', 'citameia' ) . '</a>',
            '<a href="' . esc_url( admin_url( 'admin.php?page=citameia-presencia' ) ) . '">' . esc_html__( 'presencia externa', 'citameia' ) . '</a>'
         );
        ?>
					<?php 
    } elseif ( $score >= 80 ) {
        ?>
						<?php 
        esc_html_e( 'Tu sitio tiene las señales técnicas que los motores de IA buscan para citar una fuente.', 'citameia' );
        ?>
					<?php 
    } elseif ( $score >= 50 ) {
        ?>
						<?php 
        esc_html_e( 'Hay tareas pendientes abajo que suman puntos importantes.', 'citameia' );
        ?>
					<?php 
    } else {
        ?>
						<?php 
        esc_html_e( 'Completa primero las tareas marcadas con advertencia, son las de mayor peso.', 'citameia' );
        ?>
					<?php 
    }
    ?>
				</p>
			</div>
		</div>

		<?php 
    geo_radar_render_kpi_cards( $audit, $history, $score );
    ?>

		<div class="citameia-section-title"><?php 
    esc_html_e( 'Tendencia del score', 'citameia' );
    ?></div>
		<?php 
    if ( !citameia_is_pro() ) {
        ?>
			<?php 
        citameia_render_pro_lock_inline( __( 'Gráfica de tendencia', 'citameia' ), __( 'Ve cómo cambió tu score a lo largo del tiempo, no solo el número de hoy. Disponible en CítameIA Pro.', 'citameia' ) );
        ?>
		<?php 
    }
    ?>
		<?php 
    // This IF block is stripped entirely from the free version by Freemius.
    ?>
		<?php 
    ?>

		<div class="citameia-section-title"><?php 
    esc_html_e( 'Por categoría', 'citameia' );
    ?></div>
		<?php 
    $categorias = geo_radar_audit_categories( $audit['checks'] );
    ?>
		<div class="geo-radar-kpi-grid" style="margin-bottom:26px;">
			<?php 
    foreach ( $categorias as $cat ) {
        $cat_color = ( $cat['score'] >= 80 ? '#1E7A4C' : (( $cat['score'] >= 50 ? '#8A6529' : '#B3261E' )) );
        ?>
				<div class="geo-radar-kpi-card">
					<div class="geo-radar-kpi-num" style="color:<?php 
        echo esc_attr( $cat_color );
        ?>;"><?php 
        echo esc_html( $cat['score'] );
        ?><span class="unit">/100</span></div>
					<div class="geo-radar-kpi-label"><?php 
        echo esc_html( $cat['label'] );
        ?></div>
				</div>
			<?php 
    }
    ?>
		</div>

		<div class="citameia-section-title"><?php 
    esc_html_e( 'Checklist de citabilidad', 'citameia' );
    ?></div>
		<?php 
    $pass_count = count( array_filter( $audit['checks'], function ( $c ) {
        return $c['pass'];
    } ) );
    $total_count = count( $audit['checks'] );
    $pct = ( $total_count > 0 ? round( $pass_count / $total_count * 100 ) : 0 );
    ?>
		<div class="progress-row">
			<div class="progress-track"><div class="progress-fill" style="width:<?php 
    echo esc_attr( $pct );
    ?>%;"></div></div>
			<div class="progress-label"><?php 
    /* translators: %1$d: número de tareas completadas, %2$d: total de tareas */
    printf( esc_html__( '%1$d de %2$d tareas completadas', 'citameia' ), esc_html( $pass_count ), esc_html( $total_count ) );
    ?></div>
		</div>

		<div class="task-list">
			<?php 
    foreach ( $audit['checks'] as $c ) {
        $effort = ( isset( $c['effort'] ) ? $c['effort'] : 'medio' );
        $effort_label = array(
            'bajo'  => __( 'Esfuerzo bajo', 'citameia' ),
            'medio' => __( 'Esfuerzo medio', 'citameia' ),
            'alto'  => __( 'Esfuerzo alto', 'citameia' ),
        );
        ?>
				<div class="task-row<?php 
        echo ( $c['pass'] ? '' : ' warn' );
        ?>">
					<div class="task-icon <?php 
        echo ( $c['pass'] ? 'ok' : 'warn' );
        ?>"><?php 
        echo ( $c['pass'] ? '✓' : '!' );
        ?></div>
					<div class="task-body">
						<div class="task-title">
							<?php 
        echo esc_html( $c['label'] );
        ?>
							<?php 
        if ( !$c['pass'] ) {
            ?>
								<span class="citameia-effort-badge citameia-effort-<?php 
            echo esc_attr( $effort );
            ?>"><?php 
            echo esc_html( ( isset( $effort_label[$effort] ) ? $effort_label[$effort] : $effort ) );
            ?></span>
							<?php 
        }
        ?>
						</div>
						<div class="task-desc">
							<?php 
        echo esc_html( $c['tip'] );
        ?>
							<?php 
        if ( !empty( $c['detail'] ) ) {
            ?>
								<br><em><?php 
            echo esc_html( $c['detail'] );
            ?></em>
							<?php 
        }
        ?>
						</div>
					</div>
				</div>
			<?php 
    }
    ?>
		</div>

		<div class="btn-row">
			<a href="<?php 
    echo esc_url( admin_url( 'admin.php?page=citameia-datos' ) );
    ?>" class="btn-primary"><?php 
    esc_html_e( 'Completar datos del negocio', 'citameia' );
    ?></a>
			<a href="<?php 
    echo esc_url( admin_url( 'admin.php?page=citameia-faq' ) );
    ?>" class="btn-secondary"><?php 
    esc_html_e( 'Agregar FAQ', 'citameia' );
    ?></a>
			<a href="<?php 
    echo esc_url( admin_url( 'admin.php?page=citameia-llms' ) );
    ?>" class="btn-secondary"><?php 
    esc_html_e( 'Generar llms.txt', 'citameia' );
    ?></a>
			<a href="<?php 
    echo esc_url( admin_url( 'admin.php?page=citameia-bienvenida' ) );
    ?>" class="btn-secondary"><?php 
    esc_html_e( 'Ver asistente de primeros pasos', 'citameia' );
    ?></a>
		</div>

		<p class="description" style="margin-top:14px;">
			<?php 
    printf( 
        /* translators: %s: enlace a la pantalla de Reportes */
        esc_html__( '¿Quieres un reporte descargable o la insignia compartible? Ve a %s, ahí también está el historial de lo que ya se ha generado.', 'citameia' ),
        '<a href="' . esc_url( admin_url( 'admin.php?page=citameia-reportes' ) ) . '">' . esc_html__( 'Reportes', 'citameia' ) . '</a>'
     );
    ?>
		</p>
	</div>
	<?php 
}

/**
 * =========================================================
 * PANTALLA: BIENVENIDA (asistente de primeros pasos)
 * =========================================================
 */
function citameia_render_welcome_page() {
    $s = geo_radar_get_settings();
    $faq_groups = citameia_get_faq_groups();
    $step1_done = !empty( $s['business_name'] ) && !empty( $s['description'] ) && !empty( $s['street'] );
    $step2_done = !empty( $faq_groups );
    $step3_done = file_exists( trailingslashit( ABSPATH ) . 'llms.txt' );
    $steps = array(
        array(
            'num'   => 1,
            'title' => __( 'Completa los datos de tu negocio', 'citameia' ),
            'desc'  => __( 'Nombre, dirección, teléfono y redes, es la base de todo el schema que genera el plugin.', 'citameia' ),
            'done'  => $step1_done,
            'url'   => admin_url( 'admin.php?page=citameia-datos' ),
            'cta'   => __( 'Completar datos del negocio', 'citameia' ),
        ),
        array(
            'num'   => 2,
            'title' => __( 'Crea tu primer grupo de FAQ', 'citameia' ),
            'desc'  => __( 'Preguntas y respuestas reales de tus clientes, sin escribir código.', 'citameia' ),
            'done'  => $step2_done,
            'url'   => admin_url( 'admin.php?page=citameia-faq' ),
            'cta'   => __( 'Crear grupo de FAQ', 'citameia' ),
        ),
        array(
            'num'   => 3,
            'title' => __( 'Genera tu llms.txt', 'citameia' ),
            'desc'  => __( 'El resumen de tu negocio pensado para que lo lean los modelos de IA.', 'citameia' ),
            'done'  => $step3_done,
            'url'   => admin_url( 'admin.php?page=citameia-llms' ),
            'cta'   => __( 'Generar llms.txt', 'citameia' ),
        ),
        array(
            'num'   => 4,
            'title' => __( 'Revisa tu score de citabilidad', 'citameia' ),
            'desc'  => __( 'Un número de 0 a 100 y un checklist claro de qué falta.', 'citameia' ),
            'done'  => false,
            'url'   => admin_url( 'admin.php?page=citameia' ),
            'cta'   => __( 'Ver mi Panel', 'citameia' ),
        )
    );
    ?>
	<div class="wrap geo-radar-wrap">
		<?php 
    citameia_render_admin_header( 'citameia-bienvenida' );
    ?>
		<p class="citameia-page-intro"><?php 
    esc_html_e( 'Este asistente te guía por los primeros pasos para que tu sitio empiece a hablarle claro a los motores de IA. Puedes completarlos en cualquier orden, y volver a esta pantalla cuando quieras, nada se pierde si cierras esta página.', 'citameia' );
    ?></p>

		<div class="citameia-welcome-steps">
			<?php 
    foreach ( $steps as $step ) {
        ?>
				<div class="citameia-welcome-step <?php 
        echo ( $step['done'] ? 'is-done' : '' );
        ?>">
					<div class="citameia-welcome-step-badge">
						<?php 
        echo ( $step['done'] ? '✅' : esc_html( $step['num'] ) );
        ?>
					</div>
					<div class="citameia-welcome-step-body">
						<h3><?php 
        echo esc_html( $step['title'] );
        ?></h3>
						<p><?php 
        echo esc_html( $step['desc'] );
        ?></p>
						<a href="<?php 
        echo esc_url( $step['url'] );
        ?>" class="button <?php 
        echo ( $step['done'] ? '' : 'button-primary' );
        ?>">
							<?php 
        echo esc_html( ( $step['done'] ? __( 'Revisar de nuevo', 'citameia' ) : $step['cta'] ) );
        ?>
						</a>
					</div>
				</div>
			<?php 
    }
    ?>
		</div>

		<p style="margin-top:24px;">
			<a href="<?php 
    echo esc_url( admin_url( 'admin.php?page=citameia' ) );
    ?>"><?php 
    esc_html_e( 'Saltar el asistente e ir directo al Panel →', 'citameia' );
    ?></a>
		</p>
	</div>
	<?php 
}

/**
 * =========================================================
 * PANTALLA: DATOS DEL NEGOCIO
 * =========================================================
 */
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_render_settings() {
    $s = geo_radar_get_settings();
    $types = geo_radar_business_types();
    ?>
	<div class="wrap geo-radar-wrap">
		<?php 
    citameia_render_admin_header( 'citameia-datos' );
    ?>
		<p class="citameia-page-intro"><?php 
    esc_html_e( 'Esta información alimenta automáticamente el schema.org (Organization / LocalBusiness) que se inserta en cada página de tu sitio.', 'citameia' );
    ?></p>
		<form method="post">
			<?php 
    wp_nonce_field( 'geo_radar_save_settings', 'geo_radar_nonce' );
    ?>
			<table class="form-table">
				<tr>
					<th><label for="business_name"><?php 
    esc_html_e( 'Nombre del negocio', 'citameia' );
    ?></label></th>
					<td><input type="text" class="regular-text" id="business_name" name="business_name" value="<?php 
    echo esc_attr( $s['business_name'] );
    ?>"></td>
				</tr>
				<tr>
					<th><label for="business_type"><?php 
    esc_html_e( 'Tipo de negocio (para el schema)', 'citameia' );
    ?></label></th>
					<td>
						<select id="business_type" name="business_type">
							<?php 
    foreach ( $types as $group_label => $group_items ) {
        ?>
								<optgroup label="<?php 
        echo esc_attr( $group_label );
        ?>">
									<?php 
        foreach ( $group_items as $key => $label ) {
            ?>
										<option value="<?php 
            echo esc_attr( $key );
            ?>" <?php 
            selected( $s['business_type'], $key );
            ?>><?php 
            echo esc_html( $label );
            ?></option>
									<?php 
        }
        ?>
								</optgroup>
							<?php 
    }
    ?>
						</select>
						<p class="description"><?php 
    esc_html_e( 'Esta categoría es técnica, para el schema.org que leen los motores de IA. Para las preguntas de prueba en IA, usa el campo de abajo.', 'citameia' );
    ?></p>
					</td>
				</tr>
				<tr>
					<th><label for="business_niche"><?php 
    esc_html_e( 'Giro específico (para las pruebas en IA)', 'citameia' );
    ?></label></th>
					<td>
						<input type="text" class="large-text" id="business_niche" name="business_niche" value="<?php 
    echo esc_attr( $s['business_niche'] );
    ?>" placeholder="<?php 
    esc_attr_e( 'Ej. librería y editorial independiente, especializada en poesía', 'citameia' );
    ?>">
						<p class="description"><?php 
    esc_html_e( 'Descríbelo como lo diría un cliente real. Esto se usa para generar preguntas de prueba más específicas en "Pruebas en IA", mientras más concreto, mejor la prueba.', 'citameia' );
    ?></p>
					</td>
				</tr>
				<tr>
					<th><?php 
    esc_html_e( '¿Tu negocio tiene una ubicación física que el público visita?', 'citameia' );
    ?></th>
					<td>
						<label style="display:block;margin-bottom:8px;">
							<input type="radio" name="physical_presence" value="visita" <?php 
    checked( $s['physical_presence'], 'visita' );
    ?> class="citameia-presence-radio">
							<?php 
    esc_html_e( 'Sí, el público visita mi ubicación (tienda, oficina, consultorio)', 'citameia' );
    ?>
						</label>
						<label style="display:block;margin-bottom:8px;">
							<input type="radio" name="physical_presence" value="reparto" <?php 
    checked( $s['physical_presence'], 'reparto' );
    ?> class="citameia-presence-radio">
							<?php 
    esc_html_e( 'No, trabajo por envíos o en línea, pero sí tengo una dirección (área de servicio)', 'citameia' );
    ?>
						</label>
						<label style="display:block;">
							<input type="radio" name="physical_presence" value="digital" <?php 
    checked( $s['physical_presence'], 'digital' );
    ?> class="citameia-presence-radio">
							<?php 
    esc_html_e( 'No, mi negocio es 100% digital, sin dirección relevante', 'citameia' );
    ?>
						</label>
						<p class="description"><?php 
    esc_html_e( 'Esto ajusta automáticamente tu schema (Organization en vez de LocalBusiness si no aplica) y qué tareas del checklist son obligatorias para ti.', 'citameia' );
    ?></p>
					</td>
				</tr>
				<tr>
					<th><label for="description"><?php 
    esc_html_e( 'Descripción (2-3 frases claras)', 'citameia' );
    ?></label></th>
					<td><textarea id="description" name="description" rows="3" class="large-text"><?php 
    echo esc_textarea( $s['description'] );
    ?></textarea></td>
				</tr>
				<tr class="citameia-address-row">
					<th><label for="street"><?php 
    esc_html_e( 'Calle y número', 'citameia' );
    ?></label></th>
					<td><input type="text" class="regular-text" id="street" name="street" value="<?php 
    echo esc_attr( $s['street'] );
    ?>"></td>
				</tr>
				<tr class="citameia-address-row">
					<th><label for="city"><?php 
    esc_html_e( 'Ciudad', 'citameia' );
    ?></label></th>
					<td><input type="text" class="regular-text" id="city" name="city" value="<?php 
    echo esc_attr( $s['city'] );
    ?>"></td>
				</tr>
				<tr class="citameia-address-row">
					<th><label for="state"><?php 
    esc_html_e( 'Estado', 'citameia' );
    ?></label></th>
					<td><input type="text" class="regular-text" id="state" name="state" value="<?php 
    echo esc_attr( $s['state'] );
    ?>"></td>
				</tr>
				<tr class="citameia-address-row">
					<th><label for="zip"><?php 
    esc_html_e( 'Código postal', 'citameia' );
    ?></label></th>
					<td><input type="text" class="regular-text" id="zip" name="zip" value="<?php 
    echo esc_attr( $s['zip'] );
    ?>"></td>
				</tr>
				<tr>
					<th><label for="phone"><?php 
    esc_html_e( 'Teléfono', 'citameia' );
    ?></label></th>
					<td><input type="text" class="regular-text" id="phone" name="phone" value="<?php 
    echo esc_attr( $s['phone'] );
    ?>"></td>
				</tr>
				<tr>
					<th><label for="whatsapp"><?php 
    esc_html_e( 'WhatsApp (con lada, sin espacios, ej. 528112345678)', 'citameia' );
    ?></label></th>
					<td><input type="text" class="regular-text" id="whatsapp" name="whatsapp" value="<?php 
    echo esc_attr( $s['whatsapp'] );
    ?>"></td>
				</tr>
				<tr>
					<th><label for="email"><?php 
    esc_html_e( 'Correo de contacto', 'citameia' );
    ?></label></th>
					<td><input type="email" class="regular-text" id="email" name="email" value="<?php 
    echo esc_attr( $s['email'] );
    ?>"></td>
				</tr>
				<tr>
					<th><label for="price_range"><?php 
    esc_html_e( 'Rango de precio (ej. $$, $$$)', 'citameia' );
    ?></label></th>
					<td><input type="text" class="regular-text" id="price_range" name="price_range" value="<?php 
    echo esc_attr( $s['price_range'] );
    ?>"></td>
				</tr>
				<tr>
					<th><label for="opening_hours"><?php 
    esc_html_e( 'Horario (texto libre, ej. "Lun-Sáb 9:00-19:00")', 'citameia' );
    ?></label></th>
					<td><textarea id="opening_hours" name="opening_hours" rows="2" class="large-text"><?php 
    echo esc_textarea( $s['opening_hours'] );
    ?></textarea></td>
				</tr>
				<tr>
					<th><label for="logo_url"><?php 
    esc_html_e( 'URL del logo', 'citameia' );
    ?></label></th>
					<td><input type="url" class="regular-text" id="logo_url" name="logo_url" value="<?php 
    echo esc_attr( $s['logo_url'] );
    ?>" placeholder="https://tusitio.com/logo.png"></td>
				</tr>
				<tr>
					<th><label for="social_facebook"><?php 
    esc_html_e( 'Facebook (URL)', 'citameia' );
    ?></label></th>
					<td><input type="url" class="regular-text" id="social_facebook" name="social_facebook" value="<?php 
    echo esc_attr( $s['social_facebook'] );
    ?>"></td>
				</tr>
				<tr>
					<th><label for="social_instagram"><?php 
    esc_html_e( 'Instagram (URL)', 'citameia' );
    ?></label></th>
					<td><input type="url" class="regular-text" id="social_instagram" name="social_instagram" value="<?php 
    echo esc_attr( $s['social_instagram'] );
    ?>"></td>
				</tr>
				<tr>
					<th><label for="social_gbp"><?php 
    esc_html_e( 'Google Business Profile (URL)', 'citameia' );
    ?></label></th>
					<td><input type="url" class="regular-text" id="social_gbp" name="social_gbp" value="<?php 
    echo esc_attr( $s['social_gbp'] );
    ?>"></td>
				</tr>
			</table>
			<?php 
    submit_button( __( 'Guardar datos', 'citameia' ) );
    ?>
		</form>

		<?php 
    $citameia_presence_js = "(function() {\n" . "\tvar radios = document.querySelectorAll('.citameia-presence-radio');\n" . "\tvar addressRows = document.querySelectorAll('.citameia-address-row');\n" . "\tfunction updateVisibility() {\n" . "\t\tvar selected = document.querySelector('.citameia-presence-radio:checked');\n" . "\t\tvar isDigital = selected && selected.value === 'digital';\n" . "\t\taddressRows.forEach(function(row) {\n" . "\t\t\trow.style.display = isDigital ? 'none' : '';\n" . "\t\t});\n" . "\t}\n" . "\tradios.forEach(function(r) { r.addEventListener('change', updateVisibility); });\n" . "\tupdateVisibility();\n" . '})();';
    wp_register_script(
        'citameia-presence-toggle',
        false,
        array(),
        CITAMEIA_VERSION,
        true
    );
    wp_enqueue_script( 'citameia-presence-toggle' );
    wp_add_inline_script( 'citameia-presence-toggle', $citameia_presence_js );
    ?>

		<hr style="margin:32px 0;">
		<h2 style="color:#c0392b;"><?php 
    esc_html_e( 'Zona de riesgo', 'citameia' );
    ?></h2>
		<p><?php 
    esc_html_e( 'Esto borra por completo los datos del negocio, el historial de score, los grupos de FAQ y las pruebas en IA guardadas en este sitio, para dejarlo como una instalación nueva.', 'citameia' );
    ?> <strong><?php 
    esc_html_e( 'No se puede deshacer.', 'citameia' );
    ?></strong> <?php 
    esc_html_e( 'Solo tiene sentido si quieres reiniciar una demo o empezar de cero a propósito.', 'citameia' );
    ?></p>
		<form method="post" action="<?php 
    echo esc_url( admin_url( 'admin-post.php' ) );
    ?>" onsubmit="return confirm('<?php 
    echo esc_js( __( '¿Seguro que quieres borrar TODOS los datos de CítameIA en este sitio? Esto no se puede deshacer.', 'citameia' ) );
    ?>');">
			<input type="hidden" name="action" value="citameia_reset_all_data">
			<?php 
    wp_nonce_field( 'citameia_reset_all_data', 'citameia_reset_nonce' );
    ?>
			<p>
				<label>
					<?php 
    /* translators: %s: la palabra BORRAR que hay que escribir, en formato código */
    printf( esc_html__( 'Escribe %s para confirmar:', 'citameia' ), '<code>BORRAR</code>' );
    ?>
					<input type="text" name="confirm_text" required pattern="BORRAR" title="<?php 
    esc_attr_e( 'Escribe BORRAR en mayúsculas para confirmar', 'citameia' );
    ?>">
				</label>
			</p>
			<?php 
    submit_button( __( 'Borrar todos los datos de este sitio', 'citameia' ), 'delete' );
    ?>
		</form>
	</div>
	<?php 
}

/**
 * =========================================================
 * PANTALLA: AYUDA FAQ / SCHEMA
 * =========================================================
 */
/**
 * =========================================================
 * GESTOR DE GRUPOS DE FAQ (con formulario, sin escribir shortcode a mano)
 * =========================================================
 */
define( 'CITAMEIA_FAQ_GROUPS_OPTION', 'geo_radar_faq_groups' );
function citameia_get_faq_groups() {
    return get_option( CITAMEIA_FAQ_GROUPS_OPTION, array() );
}

function citameia_save_faq_group(  $slug, $title, $items  ) {
    $groups = citameia_get_faq_groups();
    $groups[$slug] = array(
        'title' => $title,
        'items' => $items,
    );
    update_option( CITAMEIA_FAQ_GROUPS_OPTION, $groups );
}

function citameia_delete_faq_group(  $slug  ) {
    $groups = citameia_get_faq_groups();
    unset($groups[$slug]);
    update_option( CITAMEIA_FAQ_GROUPS_OPTION, $groups );
}

/**
 * Busca en qué páginas/entradas publicadas está pegado el shortcode de un
 * grupo en particular, cubriendo los 3 formatos válidos de comillas que
 * WordPress acepta en un shortcode ("...", '...', o sin comillas).
 */
function citameia_faq_group_usage(  $slug  ) {
    global $wpdb;
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- se muestra en la pantalla de administración de FAQ, debe reflejar en qué páginas está el shortcode ahora mismo, no una versión cacheada que podría quedar desactualizada tras editar una página.
    $esc = $wpdb->esc_like( $slug );
    $sql = $wpdb->prepare(
        "SELECT ID, post_title, post_type FROM {$wpdb->posts}\n\t\t WHERE post_status = 'publish'\n\t\t AND ( post_content LIKE %s OR post_content LIKE %s OR post_content LIKE %s )\n\t\t LIMIT 10",
        '%[geo_faq_group id="' . $esc . '"%',
        "%[geo_faq_group id='" . $esc . "'%",
        '%[geo_faq_group id=' . $esc . ']%'
    );
    // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- $sql ya viene de $wpdb->prepare() arriba, con esc_like() aplicado antes de armar los placeholders %s; debe reflejar en qué páginas está el shortcode ahora mismo, no una versión cacheada.
    return $wpdb->get_results( $sql );
}

/**
 * Duplica un grupo existente completo (título + preguntas) bajo un slug
 * nuevo, para no tener que volver a escribir todo desde cero cuando varios
 * grupos se parecen entre sí (ej. uno por categoría de producto).
 */
add_action( 'admin_post_citameia_duplicate_faq_group', 'citameia_handle_duplicate_faq_group' );
function citameia_handle_duplicate_faq_group() {
    if ( !current_user_can( 'manage_options' ) ) {
        wp_die( esc_html__( 'No autorizado', 'citameia' ) );
    }
    $slug = ( isset( $_GET['slug'] ) ? sanitize_title( wp_unslash( $_GET['slug'] ) ) : '' );
    check_admin_referer( 'citameia_duplicate_faq_group_' . $slug );
    $groups = citameia_get_faq_groups();
    if ( empty( $slug ) || empty( $groups[$slug] ) ) {
        wp_safe_redirect( admin_url( 'admin.php?page=citameia-faq' ) );
        exit;
    }
    $original = $groups[$slug];
    $nuevo_title = $original['title'] . ' (copia)';
    $nuevo_slug = sanitize_title( $nuevo_title );
    // Por si ya existe una copia previa, aseguramos un slug único.
    $sufijo = 2;
    while ( isset( $groups[$nuevo_slug] ) ) {
        $nuevo_slug = sanitize_title( $nuevo_title ) . '-' . $sufijo;
        $sufijo++;
    }
    citameia_save_faq_group( $nuevo_slug, $nuevo_title, $original['items'] );
    wp_safe_redirect( admin_url( 'admin.php?page=citameia-faq&edit=' . $nuevo_slug ) );
    exit;
}

// 'geo_faq_group' renombrado a 'citameia_faq_group' (prefijo "geo_" señalado
// como muy corto por WordPress.org). El nombre viejo se conserva como alias
// de compatibilidad, por si ya está escrito en el contenido de algún sitio
// donde el plugin estuviera instalado antes de este cambio.
add_shortcode( 'citameia_faq_group', 'citameia_shortcode_faq_group' );
add_shortcode( 'geo_faq_group', 'citameia_shortcode_faq_group' );
function citameia_shortcode_faq_group(  $atts  ) {
    $atts = shortcode_atts( array(
        'id' => '',
    ), $atts, 'geo_faq_group' );
    $groups = citameia_get_faq_groups();
    $slug = sanitize_title( $atts['id'] );
    if ( empty( $slug ) || empty( $groups[$slug] ) ) {
        return '';
    }
    $html = '<div class="citameia-faq-block">';
    foreach ( $groups[$slug]['items'] as $item ) {
        // Reutiliza el mismo shortcode de siempre para no duplicar lógica de render + schema.
        $html .= geo_radar_shortcode_faq_item( array(
            'pregunta' => $item['pregunta'],
        ), $item['respuesta'] );
    }
    $html .= '</div>';
    return citameia_kses_faq_html( $html );
}

/**
 * Guardar / eliminar grupo desde el formulario del admin.
 */
add_action( 'admin_init', 'citameia_handle_faq_group_save' );
function citameia_handle_faq_group_save() {
    if ( !current_user_can( 'manage_options' ) ) {
        return;
    }
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- verificación del nonce, mismo caso documentado arriba.
    if ( isset( $_POST['citameia_faq_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['citameia_faq_nonce'] ) ), 'citameia_save_faq_group' ) ) {
        $title = ( isset( $_POST['group_title'] ) ? sanitize_text_field( wp_unslash( $_POST['group_title'] ) ) : '' );
        $slug_in = ( isset( $_POST['group_slug'] ) ? sanitize_title( wp_unslash( $_POST['group_slug'] ) ) : '' );
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- estos dos son solo el (array) wp_unslash() a nivel de arreglo; cada elemento se sanitiza individualmente con sanitize_text_field()/sanitize_textarea_field() en el foreach de abajo, antes de guardarse.
        $preguntas = ( isset( $_POST['faq_pregunta'] ) ? (array) wp_unslash( $_POST['faq_pregunta'] ) : array() );
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- mismo caso que $preguntas justo arriba.
        $respuestas = ( isset( $_POST['faq_respuesta'] ) ? (array) wp_unslash( $_POST['faq_respuesta'] ) : array() );
        if ( '' === $title ) {
            return;
        }
        $items = array();
        foreach ( $preguntas as $i => $p ) {
            $p = sanitize_text_field( $p );
            $r = ( isset( $respuestas[$i] ) ? sanitize_textarea_field( $respuestas[$i] ) : '' );
            if ( '' !== $p && '' !== $r ) {
                $items[] = array(
                    'pregunta'  => $p,
                    'respuesta' => $r,
                );
            }
        }
        if ( empty( $items ) ) {
            return;
        }
        $slug = ( '' !== $slug_in ? $slug_in : sanitize_title( $title ) );
        citameia_save_faq_group( $slug, $title, $items );
        add_action( 'admin_notices', function () use($slug) {
            printf( '<div class="notice notice-success is-dismissible"><p>%s</p></div>', wp_kses_post( sprintf( 
                /* translators: %s: shortcode con el id del grupo */
                __( 'Grupo de FAQ guardado. Usa el shortcode %s en la página donde quieras mostrarlo.', 'citameia' ),
                '<code>[geo_faq_group id="' . esc_html( $slug ) . '"]</code>'
             ) ) );
        } );
    }
}

add_action( 'admin_post_citameia_delete_faq_group', 'citameia_handle_faq_group_delete' );
function citameia_handle_faq_group_delete() {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- verificación del nonce, mismo caso documentado arriba.
    if ( !current_user_can( 'manage_options' ) || !isset( $_GET['slug'], $_GET['_wpnonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'citameia_delete_faq_group_' . sanitize_title( wp_unslash( $_GET['slug'] ) ) ) ) {
        wp_die( esc_html__( 'No autorizado', 'citameia' ) );
    }
    citameia_delete_faq_group( sanitize_title( wp_unslash( $_GET['slug'] ) ) );
    wp_safe_redirect( admin_url( 'admin.php?page=citameia-faq&deleted=1' ) );
    exit;
}

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_render_faq_help() {
    $groups = citameia_get_faq_groups();
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- solo lectura, decide qué grupo mostrar en el formulario de edición; ya sanitizado con sanitize_title(wp_unslash()).
    $editing = ( isset( $_GET['edit'] ) ? sanitize_title( wp_unslash( $_GET['edit'] ) ) : '' );
    $edit_data = ( $editing && isset( $groups[$editing] ) ? $groups[$editing] : null );
    $form_title = ( $edit_data ? $edit_data['title'] : '' );
    $form_items = ( $edit_data ? $edit_data['items'] : array(array(
        'pregunta'  => '',
        'respuesta' => '',
    ), array(
        'pregunta'  => '',
        'respuesta' => '',
    )) );
    ?>
	<div class="wrap geo-radar-wrap">
		<?php 
    citameia_render_admin_header( 'citameia-faq' );
    ?>
		<p class="citameia-page-intro">
			<?php 
    printf( 
        /* translators: %s: la palabra "y" en negrita */
        esc_html__( 'Escribe tus preguntas frecuentes en campos normales, nada de código. El plugin las muestra bien en pantalla %s genera automáticamente el schema FAQPage que buscan los motores de IA.', 'citameia' ),
        '<strong>' . esc_html__( 'y', 'citameia' ) . '</strong>'
     );
    ?>
		</p>

		<?php 
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- solo lectura para decidir qué aviso mostrar tras un redirect; no se procesa ningún dato.
    ?>
		<?php 
    if ( isset( $_GET['deleted'] ) ) {
        ?>
			<div class="notice notice-success is-dismissible"><p><?php 
        esc_html_e( 'Grupo de FAQ eliminado.', 'citameia' );
        ?></p></div>
		<?php 
    }
    ?>
		<?php 
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- misma razón.
    ?>
		<?php 
    if ( isset( $_GET['autosuggested'] ) ) {
        ?>
			<div class="notice notice-success is-dismissible"><p><?php 
        esc_html_e( 'Grupo generado. Revisa las preguntas y respuestas antes de que se muestren en tu sitio — puedes editarlas todas abajo.', 'citameia' );
        ?></p></div>
		<?php 
    }
    ?>

		<div class="citameia-step-card">
			<div class="citameia-step-head"><span class="citameia-step-num">0</span><h2><?php 
    esc_html_e( 'Sugerir preguntas automáticamente', 'citameia' );
    ?></h2></div>
			<?php 
    if ( !citameia_is_pro() ) {
        ?>
				<?php 
        citameia_render_pro_lock_inline( __( 'Genera un grupo de FAQ completo', 'citameia' ), __( 'A partir de tus Datos del negocio, genera un grupo de preguntas y respuestas listo para revisar y publicar. Disponible en CítameIA Pro.', 'citameia' ) );
        ?>
			<?php 
    }
    ?>
			<?php 
    // This IF block is stripped entirely from the free version by Freemius.
    ?>
			<?php 
    ?>
		</div>

		<?php 
    if ( !empty( $groups ) ) {
        ?>
			<div class="citameia-step-card">
				<div class="citameia-step-head"><span class="citameia-step-num">1</span><h2><?php 
        esc_html_e( 'Tus grupos de FAQ', 'citameia' );
        ?></h2></div>
				<div class="geo-radar-faq-groups-list">
					<?php 
        foreach ( $groups as $slug => $g ) {
            $usados_en = citameia_faq_group_usage( $slug );
            ?>
						<div class="geo-radar-faq-group-card">
							<div class="geo-radar-faq-group-head">
								<strong><?php 
            echo esc_html( $g['title'] );
            ?></strong>
																<span class="geo-radar-faq-group-count"><?php 
            /* translators: %s: número de preguntas en el grupo de FAQ */
            printf( esc_html__( '%s pregunta(s)', 'citameia' ), esc_html( count( $g['items'] ) ) );
            ?></span>
							</div>
							<code class="geo-radar-faq-group-shortcode">[geo_faq_group id="<?php 
            echo esc_attr( $slug );
            ?>"]</code>

							<div class="citameia-faq-usage">
								<?php 
            if ( empty( $usados_en ) ) {
                ?>
									<span class="citameia-faq-usage-empty"><?php 
                esc_html_e( 'Todavía no se usa en ninguna página publicada.', 'citameia' );
                ?></span>
								<?php 
            } else {
                ?>
									<span class="citameia-faq-usage-label"><?php 
                esc_html_e( 'Se usa en:', 'citameia' );
                ?></span>
									<?php 
                foreach ( $usados_en as $p ) {
                    ?>
										<a href="<?php 
                    echo esc_url( get_edit_post_link( $p->ID ) );
                    ?>" class="citameia-faq-usage-link"><?php 
                    echo esc_html( ( $p->post_title ? $p->post_title : __( '(sin título)', 'citameia' ) ) );
                    ?></a>
									<?php 
                }
                ?>
								<?php 
            }
            ?>
							</div>

							<details class="citameia-faq-preview-toggle">
								<summary><?php 
            esc_html_e( 'Vista previa', 'citameia' );
            ?></summary>
								<div class="citameia-faq-preview-frame">
									<?php 
            echo do_shortcode( '[geo_faq_group id="' . esc_attr( $slug ) . '"]' );
            ?>
								</div>
							</details>

							<p>
								<a href="<?php 
            echo esc_url( admin_url( 'admin.php?page=citameia-faq&edit=' . $slug ) );
            ?>" class="button button-small"><?php 
            esc_html_e( 'Editar', 'citameia' );
            ?></a>
								<a href="<?php 
            echo esc_url( wp_nonce_url( admin_url( 'admin-post.php?action=citameia_duplicate_faq_group&slug=' . $slug ), 'citameia_duplicate_faq_group_' . $slug ) );
            ?>" class="button button-small"><?php 
            esc_html_e( 'Duplicar', 'citameia' );
            ?></a>
								<a href="<?php 
            echo esc_url( wp_nonce_url( admin_url( 'admin-post.php?action=citameia_delete_faq_group&slug=' . $slug ), 'citameia_delete_faq_group_' . $slug ) );
            ?>"
									class="button button-small button-link-delete"
									onclick="return confirm('<?php 
            echo esc_js( __( '¿Eliminar este grupo de FAQ? Esto no borra el shortcode de tus páginas, pero dejará de mostrar nada.', 'citameia' ) );
            ?>');"><?php 
            esc_html_e( 'Eliminar', 'citameia' );
            ?></a>
							</p>
						</div>
					<?php 
        }
        ?>
				</div>
			</div>
		<?php 
    }
    ?>

		<div class="citameia-step-card">
			<div class="citameia-step-head"><span class="citameia-step-num">2</span><h2><?php 
    echo ( $edit_data ? esc_html__( 'Editar grupo de FAQ', 'citameia' ) : esc_html__( 'Crear nuevo grupo de FAQ', 'citameia' ) );
    ?></h2></div>
			<form method="post">
				<?php 
    wp_nonce_field( 'citameia_save_faq_group', 'citameia_faq_nonce' );
    ?>
				<input type="hidden" name="group_slug" value="<?php 
    echo esc_attr( $editing );
    ?>">

				<table class="form-table">
					<tr>
						<th><label for="group_title"><?php 
    esc_html_e( 'Nombre del grupo', 'citameia' );
    ?></label></th>
						<td>
							<input type="text" id="group_title" name="group_title" class="regular-text" value="<?php 
    echo esc_attr( $form_title );
    ?>" placeholder="<?php 
    esc_attr_e( 'Ej. Preguntas de envíos y horarios', 'citameia' );
    ?>">
							<p class="description"><?php 
    esc_html_e( 'Solo para identificarlo tú, no se muestra en el sitio.', 'citameia' );
    ?></p>
						</td>
					</tr>
				</table>

				<div id="geo-radar-faq-rows">
					<?php 
    foreach ( $form_items as $i => $item ) {
        ?>
						<div class="geo-radar-faq-row">
														<div class="citameia-faq-row-num"><?php 
        /* translators: %s: número de la pregunta dentro del grupo */
        printf( esc_html__( 'Pregunta %s', 'citameia' ), '<span class="num">' . esc_html( $i + 1 ) . '</span>' );
        ?></div>
							<table class="form-table">
								<tr>
									<th><?php 
        esc_html_e( 'Pregunta', 'citameia' );
        ?></th>
									<td><input type="text" name="faq_pregunta[]" class="large-text" value="<?php 
        echo esc_attr( $item['pregunta'] );
        ?>" placeholder="<?php 
        esc_attr_e( '¿Cuál es su horario de atención?', 'citameia' );
        ?>"></td>
								</tr>
								<tr>
									<th><?php 
        esc_html_e( 'Respuesta', 'citameia' );
        ?></th>
									<td>
										<textarea name="faq_respuesta[]" rows="2" class="large-text" placeholder="<?php 
        esc_attr_e( 'Respuesta clara en 2-3 oraciones.', 'citameia' );
        ?>"><?php 
        echo esc_textarea( $item['respuesta'] );
        ?></textarea>
										<p><button type="button" class="button button-small geo-radar-remove-row"><?php 
        esc_html_e( 'Quitar esta pregunta', 'citameia' );
        ?></button></p>
									</td>
								</tr>
							</table>
							<hr>
						</div>
					<?php 
    }
    ?>
				</div>

				<p>
					<button type="button" id="geo-radar-add-row" class="button">+ <?php 
    esc_html_e( 'Agregar otra pregunta', 'citameia' );
    ?></button>
				</p>

				<?php 
    submit_button( ( $edit_data ? __( 'Guardar cambios', 'citameia' ) : __( 'Guardar grupo de FAQ', 'citameia' ) ) );
    ?>
			</form>
		</div>

		<?php 
    $citameia_faq_rows_js = <<<'CITAMEIA_FAQ_ROWS_JS'
(function() {
	var container = document.getElementById('geo-radar-faq-rows');
	var addBtn    = document.getElementById('geo-radar-add-row');

	function renumerar() {
		container.querySelectorAll('.geo-radar-faq-row').forEach(function(row, i) {
			var badge = row.querySelector('.citameia-faq-row-num .num');
			if (badge) { badge.textContent = i + 1; }
		});
	}

	function attachRemove(row) {
		var btn = row.querySelector('.geo-radar-remove-row');
		if (!btn) { return; }
		btn.addEventListener('click', function() {
			if (container.querySelectorAll('.geo-radar-faq-row').length > 1) {
				row.parentNode.removeChild(row);
				renumerar();
			} else {
				row.querySelectorAll('input, textarea').forEach(function(el) { el.value = ''; });
			}
		});
	}

	addBtn.addEventListener('click', function() {
		var rows = container.querySelectorAll('.geo-radar-faq-row');
		var last = rows[rows.length - 1];
		var clone = last.cloneNode(true);
		clone.querySelectorAll('input, textarea').forEach(function(el) { el.value = ''; });
		container.appendChild(clone);
		attachRemove(clone);
		renumerar();
	});

	container.querySelectorAll('.geo-radar-faq-row').forEach(attachRemove);
})();
CITAMEIA_FAQ_ROWS_JS;
    wp_register_script(
        'citameia-faq-rows',
        false,
        array(),
        CITAMEIA_VERSION,
        true
    );
    wp_enqueue_script( 'citameia-faq-rows' );
    wp_add_inline_script( 'citameia-faq-rows', $citameia_faq_rows_js );
    ?>

		<div class="citameia-step-card">
			<div class="citameia-step-head"><span class="citameia-step-num">3</span><h2><?php 
    esc_html_e( '¿Prefieres escribir el shortcode a mano?', 'citameia' );
    ?></h2></div>
						<p><?php 
    /* translators: %1$s: shortcode [geo_faq], %2$s: shortcode [geo_faq_item] */
    printf( esc_html__( 'También puedes seguir usando %1$s con %2$s directamente en el editor, si ya lo conoces:', 'citameia' ), '<code>[geo_faq]</code>', '<code>[geo_faq_item]</code>' );
    ?></p>
			<pre class="geo-radar-code">[geo_faq]
[geo_faq_item pregunta="<?php 
    echo esc_html__( '¿Cuál es su horario de atención?', 'citameia' );
    ?>"]
<?php 
    echo esc_html__( 'Atendemos de lunes a sábado de 9:00 a 19:00 horas.', 'citameia' );
    ?>
[/geo_faq_item]
[/geo_faq]</pre>
		</div>

		<div class="citameia-step-card">
			<div class="citameia-step-head"><span class="citameia-step-num">4</span><h2><?php 
    esc_html_e( 'Qué más genera este plugin automáticamente', 'citameia' );
    ?></h2></div>
			<ul class="geo-radar-tips">
								<li><strong>Organization / LocalBusiness:</strong> <?php 
    /* translators: %s: nombre de la pantalla "Datos del negocio", entre comillas */
    printf( esc_html__( 'en todas las páginas, con los datos de %s.', 'citameia' ), '"' . esc_html__( 'Datos del negocio', 'citameia' ) . '"' );
    ?></li>
				<li><strong>WebSite con SearchAction:</strong> <?php 
    esc_html_e( 'para que los motores entiendan cómo se busca en tu sitio.', 'citameia' );
    ?></li>
				<li><strong>Article:</strong> <?php 
    esc_html_e( 'en cada entrada de blog (título, fecha, autor, imagen destacada).', 'citameia' );
    ?></li>
				<li><strong>BreadcrumbList:</strong> <?php 
    esc_html_e( 'Inicio > Categoría > Página, en todo el sitio.', 'citameia' );
    ?></li>
				<?php 
    if ( class_exists( 'WooCommerce' ) ) {
        ?>
					<li><strong>Product:</strong> <?php 
        esc_html_e( 'en cada producto de WooCommerce (precio, disponibilidad, descripción, y reseñas si ya tienes).', 'citameia' );
        ?></li>
				<?php 
    }
    ?>
			</ul>
		</div>
	</div>
	<?php 
}

/**
 * =========================================================
 * SHORTCODES: [geo_faq] y [geo_faq_item]
 * =========================================================
 */
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- mismo prefijo legacy 'geo_radar_' que las funciones de arriba, dejado sin cambiar por la misma razón (riesgo vs. beneficio puramente cosmético).
// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- mismo prefijo legacy 'geo_radar_' que las funciones de arriba, dejado sin cambiar por la misma razón (riesgo vs. beneficio puramente cosmético).
$GLOBALS['geo_radar_faq_items'] = array();
// phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
// 'geo_faq_item' renombrado a 'citameia_faq_item', mismo caso que arriba.
add_shortcode( 'citameia_faq_item', 'geo_radar_shortcode_faq_item' );
add_shortcode( 'geo_faq_item', 'geo_radar_shortcode_faq_item' );
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_shortcode_faq_item(  $atts, $content = ''  ) {
    $atts = shortcode_atts( array(
        'pregunta' => '',
    ), $atts, 'geo_faq_item' );
    $pregunta = trim( $atts['pregunta'] );
    $respuesta_html = wpautop( do_shortcode( $content ) );
    $respuesta_plain = trim( wp_strip_all_tags( $content ) );
    if ( '' !== $pregunta && '' !== $respuesta_plain ) {
        $GLOBALS['geo_radar_faq_items'][] = array(
            'pregunta'  => $pregunta,
            'respuesta' => $respuesta_plain,
        );
    }
    $html = '<details class="citameia-faq-item">';
    $html .= '<summary class="citameia-faq-q"><span>' . esc_html( $pregunta ) . '</span><span class="citameia-faq-icon" aria-hidden="true"></span></summary>';
    $html .= '<div class="citameia-faq-a">' . $respuesta_html . '</div>';
    $html .= '</details>';
    return citameia_kses_faq_html( $html );
}

// 'geo_faq' renombrado a 'citameia_faq', mismo caso que arriba.
add_shortcode( 'citameia_faq', 'geo_radar_shortcode_faq_wrapper' );
add_shortcode( 'geo_faq', 'geo_radar_shortcode_faq_wrapper' );
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_shortcode_faq_wrapper(  $atts, $content = ''  ) {
    $inner = do_shortcode( $content );
    return citameia_kses_faq_html( '<div class="citameia-faq-block">' . $inner . '</div>' );
}

/**
 * Imprime el schema FAQPage acumulado durante el render de la página actual.
 */
add_action( 'wp_footer', 'geo_radar_output_faq_schema' );
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_output_faq_schema() {
    if ( empty( $GLOBALS['geo_radar_faq_items'] ) ) {
        return;
    }
    $main_entity = array();
    foreach ( $GLOBALS['geo_radar_faq_items'] as $item ) {
        $main_entity[] = array(
            '@type'          => 'Question',
            'name'           => $item['pregunta'],
            'acceptedAnswer' => array(
                '@type' => 'Answer',
                'text'  => $item['respuesta'],
            ),
        );
    }
    $schema = array(
        '@context'   => 'https://schema.org',
        '@type'      => 'FAQPage',
        'mainEntity' => $main_entity,
    );
    citameia_print_json_ld( $schema );
    // Guardamos que el schema FAQ de verdad se imprimió en esta carga de
    // página. El checklist del Panel usa esta bandera además de buscar el
    // shortcode en el contenido de posts/páginas, porque un shortcode
    // llamado directo desde un archivo del theme (por ejemplo, con
    // do_shortcode() dentro de front-page.php) nunca aparece guardado en
    // post_content, aunque el schema sí se esté generando de verdad.
    update_option( 'citameia_faq_schema_detectado', 1, false );
}

/**
 * =========================================================
 * SCHEMA: Organization / LocalBusiness + WebSite (sitewide)
 * =========================================================
 */
function citameia_build_business_schema_array(  $s  ) {
    if ( empty( $s['business_name'] ) ) {
        return null;
    }
    $same_as = array_filter( array($s['social_facebook'], $s['social_instagram'], $s['social_gbp']) );
    $is_digital = isset( $s['physical_presence'] ) && 'digital' === $s['physical_presence'];
    $tipo_real = citameia_schema_type_real( $s['business_type'] );
    $es_persona = 'Person' === $tipo_real;
    // Un negocio 100% digital no tiene "ubicación de negocio local"; Organization es el tipo correcto
    // según schema.org para este caso, en vez de forzar LocalBusiness sin sentido.
    // A una persona (escritor, editor, artista...) no la forzamos a Organization aunque sea "digital",
    // porque Person ya es justo el tipo correcto para alguien sin negocio ni local físico.
    $schema_type = ( $is_digital && !$es_persona ? 'Organization' : $tipo_real );
    $business = array(
        '@context'    => 'https://schema.org',
        '@type'       => $schema_type,
        'name'        => $s['business_name'],
        'description' => $s['description'],
        'url'         => home_url(),
    );
    if ( !empty( $s['logo_url'] ) ) {
        $business['image'] = $s['logo_url'];
        if ( !$es_persona ) {
            // "logo" no es una propiedad válida de schema.org Person; ahí solo usamos "image".
            $business['logo'] = $s['logo_url'];
        }
    }
    if ( !empty( $s['phone'] ) ) {
        $business['telephone'] = $s['phone'];
    }
    if ( !$is_digital && !$es_persona && !empty( $s['price_range'] ) ) {
        // "priceRange" tampoco aplica a una persona individual.
        $business['priceRange'] = $s['price_range'];
    }
    if ( !$is_digital && (!empty( $s['street'] ) || !empty( $s['city'] )) ) {
        $business['address'] = array(
            '@type'           => 'PostalAddress',
            'streetAddress'   => $s['street'],
            'addressLocality' => $s['city'],
            'addressRegion'   => $s['state'],
            'postalCode'      => $s['zip'],
            'addressCountry'  => $s['country'],
        );
    }
    if ( !empty( $same_as ) ) {
        $business['sameAs'] = array_values( $same_as );
    }
    return $business;
}

function citameia_build_website_schema_array(  $s  ) {
    if ( empty( $s['business_name'] ) ) {
        return null;
    }
    return array(
        '@context'        => 'https://schema.org',
        '@type'           => 'WebSite',
        'name'            => $s['business_name'],
        'url'             => home_url(),
        'potentialAction' => array(
            '@type'       => 'SearchAction',
            'target'      => home_url( '/?s={search_term_string}' ),
            'query-input' => 'required name=search_term_string',
        ),
    );
}

/**
 * =========================================================
 * META DESCRIPCIÓN
 * =========================================================
 * Usa la descripción del negocio ya guardada en "Datos del negocio"
 * para la portada, y el extracto o contenido de cada entrada/página
 * para el resto del sitio. Se omite si Yoast/Rank Math ya generan la
 * suya, para no duplicar la etiqueta.
 */
add_action( 'wp_head', 'citameia_output_meta_description', 1 );
function citameia_output_meta_description() {
    if ( citameia_should_skip_core_schema() ) {
        return;
        // Yoast/Rank Math ya generan su propia meta descripción.
    }
    $s = geo_radar_get_settings();
    $desc = '';
    if ( is_singular() && !is_front_page() ) {
        global $post;
        if ( $post ) {
            $desc = ( has_excerpt( $post ) ? $post->post_excerpt : wp_strip_all_tags( $post->post_content ) );
        }
    }
    if ( empty( trim( (string) $desc ) ) ) {
        $desc = ( !empty( $s['description'] ) ? $s['description'] : get_bloginfo( 'description' ) );
    }
    $desc = wp_strip_all_tags( (string) $desc );
    $desc = trim( preg_replace( '/\\s+/', ' ', $desc ) );
    if ( '' === $desc ) {
        return;
    }
    if ( mb_strlen( $desc ) > 160 ) {
        $desc = mb_substr( $desc, 0, 157 ) . '...';
    }
    echo "\n" . '<meta name="description" content="' . esc_attr( $desc ) . '">' . "\n";
}

add_action( 'wp_head', 'geo_radar_output_business_schema' );
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_output_business_schema() {
    if ( citameia_should_skip_core_schema() ) {
        return;
        // Yoast o Rank Math ya generan Organization/WebSite, evitamos duplicar.
    }
    $s = geo_radar_get_settings();
    $business = citameia_build_business_schema_array( $s );
    $website = citameia_build_website_schema_array( $s );
    if ( !$business ) {
        return;
    }
    citameia_print_json_ld( $business );
    citameia_print_json_ld( $website );
}

/**
 * =========================================================
 * VISTA PREVIA ENRIQUECIDA AL COMPARTIR (Open Graph + Twitter Card)
 * =========================================================
 * Lo que hace que un enlace se vea bien al compartirlo en WhatsApp,
 * Facebook, Slack, etc. (título, descripción, imagen), en vez de un
 * enlace pelón. Yoast y Rank Math YA generan esto por su cuenta, así
 * que reutilizamos exactamente la misma detección que usamos para no
 * duplicar schema.org, para no duplicar esto tampoco.
 */
add_action( 'wp_head', 'citameia_output_og_tags', 5 );
function citameia_output_og_tags() {
    if ( citameia_should_skip_core_schema() ) {
        return;
        // Yoast o Rank Math ya generan Open Graph y Twitter Card, evitamos duplicar.
    }
    if ( '1' !== get_option( 'citameia_og_enabled' ) ) {
        return;
        // Apagado por default; el usuario lo activa a propósito en su propia pantalla.
    }
    $s = geo_radar_get_settings();
    $titulo = '';
    $desc = '';
    $imagen = ( !empty( $s['logo_url'] ) ? $s['logo_url'] : '' );
    // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- envuelto en sanitize_text_field(wp_unslash()); el resultado se escapa de nuevo con esc_url()/esc_attr() donde se imprime en las etiquetas OG.
    $url = home_url( add_query_arg( array(), sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ?? '/' ) ) ) );
    $tipo = 'website';
    $es_producto = false;
    if ( is_front_page() ) {
        $titulo = ( !empty( $s['business_name'] ) ? $s['business_name'] : get_bloginfo( 'name' ) );
        $desc = ( !empty( $s['description'] ) ? $s['description'] : get_bloginfo( 'description' ) );
    } elseif ( function_exists( 'is_product' ) && is_product() ) {
        // Producto de WooCommerce: título, descripción corta, precio, e imagen real del producto.
        // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- variable global propia de WooCommerce, no la definimos nosotros.
        global $product;
        // phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
        if ( !$product instanceof WC_Product ) {
            $product = wc_get_product( get_the_ID() );
        }
        if ( $product ) {
            $es_producto = true;
            $tipo = 'product';
            $titulo = $product->get_name();
            $desc = wp_strip_all_tags( ( $product->get_short_description() ? $product->get_short_description() : $product->get_description() ) );
            $img_id = $product->get_image_id();
            if ( $img_id ) {
                $img_src = wp_get_attachment_image_src( $img_id, 'large' );
                if ( $img_src ) {
                    $imagen = $img_src[0];
                }
            }
        }
    } elseif ( is_singular() ) {
        global $post;
        if ( $post ) {
            $titulo = get_the_title( $post );
            $desc = ( has_excerpt( $post ) ? $post->post_excerpt : wp_strip_all_tags( $post->post_content ) );
            if ( has_post_thumbnail( $post ) ) {
                $img_src = wp_get_attachment_image_src( get_post_thumbnail_id( $post ), 'large' );
                if ( $img_src ) {
                    $imagen = $img_src[0];
                }
            }
            $tipo = 'article';
        }
    }
    if ( '' === trim( (string) $titulo ) ) {
        $titulo = get_bloginfo( 'name' );
    }
    $desc = wp_strip_all_tags( (string) $desc );
    $desc = trim( preg_replace( '/\\s+/', ' ', $desc ) );
    if ( mb_strlen( $desc ) > 200 ) {
        $desc = mb_substr( $desc, 0, 197 ) . '...';
    }
    echo "\n";
    echo '<meta property="og:type" content="' . esc_attr( $tipo ) . '">' . "\n";
    echo '<meta property="og:title" content="' . esc_attr( $titulo ) . '">' . "\n";
    if ( '' !== $desc ) {
        echo '<meta property="og:description" content="' . esc_attr( $desc ) . '">' . "\n";
    }
    echo '<meta property="og:url" content="' . esc_url( $url ) . '">' . "\n";
    echo '<meta property="og:site_name" content="' . esc_attr( get_bloginfo( 'name' ) ) . '">' . "\n";
    if ( '' !== $imagen ) {
        echo '<meta property="og:image" content="' . esc_url( $imagen ) . '">' . "\n";
    }
    if ( $es_producto && $product ) {
        echo '<meta property="product:price:amount" content="' . esc_attr( $product->get_price() ) . '">' . "\n";
        echo '<meta property="product:price:currency" content="' . esc_attr( get_woocommerce_currency() ) . '">' . "\n";
    }
    // Twitter Card: casi repite lo mismo, pero X/Twitter no siempre respeta
    // las etiquetas og:, así que se ponen explícitas también.
    echo '<meta name="twitter:card" content="summary_large_image">' . "\n";
    echo '<meta name="twitter:title" content="' . esc_attr( $titulo ) . '">' . "\n";
    if ( '' !== $desc ) {
        echo '<meta name="twitter:description" content="' . esc_attr( $desc ) . '">' . "\n";
    }
    if ( '' !== $imagen ) {
        echo '<meta name="twitter:image" content="' . esc_url( $imagen ) . '">' . "\n";
    }
}

/**
 * Prende o apaga la vista previa enriquecida al compartir. A propósito
 * no es automática: el usuario la activa desde su propia pantalla,
 * viendo primero de qué se trata.
 */
add_action( 'admin_post_citameia_toggle_og', 'citameia_handle_toggle_og' );
function citameia_handle_toggle_og() {
    if ( !current_user_can( 'manage_options' ) ) {
        wp_die( esc_html__( 'No autorizado', 'citameia' ) );
    }
    check_admin_referer( 'citameia_toggle_og' );
    if ( citameia_should_skip_core_schema() ) {
        wp_safe_redirect( admin_url( 'admin.php?page=citameia-compartir' ) );
        exit;
    }
    $actual = get_option( 'citameia_og_enabled' );
    update_option( 'citameia_og_enabled', ( '1' === $actual ? '0' : '1' ) );
    wp_safe_redirect( admin_url( 'admin.php?page=citameia-compartir&cambiado=1' ) );
    exit;
}

function citameia_render_og_page() {
    $conflicto = citameia_should_skip_core_schema();
    $nombres = citameia_product_conflict_names();
    // citameia_product_conflict_names() está pensado para el conflicto de
    // Producto; aquí usamos directo cuál de los dos (Yoast/Rank Math) causó
    // el conflicto general, para el aviso.
    $d = citameia_detect_seo_plugins();
    $plugin_conflicto = ( $d['yoast'] ? 'Yoast SEO' : (( $d['rankmath'] ? 'Rank Math' : __( 'otro plugin de SEO', 'citameia' ) )) );
    $activado = '1' === get_option( 'citameia_og_enabled' );
    $s = geo_radar_get_settings();
    $nombre_negocio = ( !empty( $s['business_name'] ) ? $s['business_name'] : get_bloginfo( 'name' ) );
    $desc_negocio = ( !empty( $s['description'] ) ? $s['description'] : get_bloginfo( 'description' ) );
    $tiene_logo = !empty( $s['logo_url'] );
    ?>
	<div class="wrap geo-radar-wrap">
		<?php 
    citameia_render_admin_header( 'citameia-compartir' );
    ?>
		<p class="citameia-page-intro"><?php 
    esc_html_e( 'Cuando alguien comparte un enlace de tu sitio en WhatsApp, Facebook, o Slack, esto es lo que decide si se ve con título, descripción e imagen, o como un enlace pelón.', 'citameia' );
    ?></p>

		<?php 
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- solo lectura para decidir qué aviso mostrar tras un redirect; no se procesa ningún dato.
    ?>
		<?php 
    if ( isset( $_GET['cambiado'] ) ) {
        ?>
			<div class="notice notice-success" style="padding:12px 14px;"><p style="margin:0;"><?php 
        esc_html_e( 'Cambio guardado.', 'citameia' );
        ?></p></div>
		<?php 
    }
    ?>

		<div class="citameia-step-card">
			<div class="citameia-step-head"><span class="citameia-step-num">1</span><h2><?php 
    esc_html_e( 'Qué hace esto', 'citameia' );
    ?></h2></div>
			<p><?php 
    esc_html_e( 'Genera las etiquetas Open Graph y Twitter Card de tu sitio: en tu portada usa el nombre y descripción de tu negocio; en entradas y páginas usa el título, extracto, e imagen destacada; en productos de WooCommerce usa el nombre, descripción corta, la imagen real del producto, y el precio.', 'citameia' );
    ?></p>
			<?php 
    if ( $tiene_logo ) {
        ?>
				<p class="description">
					<?php 
        printf( 
            /* translators: 1: nombre del negocio en negrita, 2: descripción del negocio */
            esc_html__( 'Con tus datos actuales, tu portada se compartiría así: %1$s, %2$s, con tu logo como imagen.', 'citameia' ),
            '<strong>' . esc_html( $nombre_negocio ) . '</strong>',
            esc_html( $desc_negocio )
         );
        ?>
				</p>
			<?php 
    } else {
        ?>
				<div class="notice notice-warning inline" style="padding:12px 14px;">
					<p style="margin:0;">
						<strong><?php 
        esc_html_e( 'Todavía no tienes un logo cargado.', 'citameia' );
        ?></strong>
						<?php 
        printf( 
            /* translators: %s: enlace a "Datos del negocio" */
            esc_html__( 'Sin una imagen, tu portada se compartiría sin foto, con solo el nombre y la descripción, mucho menos llamativo. Ve a %s y sube tu logo antes de activar esto, para que se vea completo. En entradas y páginas con imagen destacada propia, esto no aplica, esas sí se verían bien de todos modos.', 'citameia' ),
            '<a href="' . esc_url( admin_url( 'admin.php?page=citameia-datos' ) ) . '">' . esc_html__( 'Datos del negocio', 'citameia' ) . '</a>'
         );
        ?>
					</p>
				</div>
			<?php 
    }
    ?>
		</div>

		<div class="citameia-step-card">
			<div class="citameia-step-head"><span class="citameia-step-num">2</span><h2><?php 
    esc_html_e( 'Activar o desactivar', 'citameia' );
    ?></h2></div>
			<?php 
    if ( $conflicto ) {
        ?>
				<div class="notice notice-warning inline" style="padding:12px 14px;">
					<p style="margin:0;">
						<?php 
        printf( 
            /* translators: %1$s: nombre del plugin de SEO detectado (en negritas), %2$s: el mismo nombre en texto plano */
            esc_html__( 'Ya tienes esto cubierto por %1$s. Detectamos que ya está activo, y genera sus propias etiquetas Open Graph y Twitter Card. Para no duplicarlas, este botón está deshabilitado mientras %2$s siga activo.', 'citameia' ),
            '<strong>' . esc_html( $plugin_conflicto ) . '</strong>',
            esc_html( $plugin_conflicto )
         );
        ?>
					</p>
				</div>
				<div class="btn-row">
					<button type="button" class="btn-primary" disabled style="opacity:0.5;cursor:not-allowed;"><?php 
        esc_html_e( 'Activar vista previa enriquecida', 'citameia' );
        ?></button>
				</div>
			<?php 
    } else {
        ?>
				<form method="post" action="<?php 
        echo esc_url( admin_url( 'admin-post.php' ) );
        ?>">
					<input type="hidden" name="action" value="citameia_toggle_og">
					<?php 
        wp_nonce_field( 'citameia_toggle_og' );
        ?>
					<div class="btn-row">
						<?php 
        if ( $activado ) {
            ?>
							<?php 
            submit_button(
                __( 'Desactivar vista previa enriquecida', 'citameia' ),
                'secondary',
                'submit',
                false
            );
            ?>
							<span style="align-self:center;color:#1E7A4C;font-weight:600;font-size:13px;">✓ <?php 
            esc_html_e( 'Activa ahora mismo', 'citameia' );
            ?></span>
						<?php 
        } else {
            ?>
							<?php 
            submit_button(
                __( 'Activar vista previa enriquecida', 'citameia' ),
                'primary',
                'submit',
                false
            );
            ?>
						<?php 
        }
        ?>
					</div>
				</form>
			<?php 
    }
    ?>
		</div>
	</div>
	<?php 
}

/**
 * =========================================================
 * SCHEMA: Article (entradas de blog)
 * =========================================================
 */
add_action( 'wp_head', 'geo_radar_output_article_schema' );
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_output_article_schema() {
    if ( citameia_should_skip_core_schema() ) {
        return;
        // Yoast o Rank Math ya generan Article/WebPage, evitamos duplicar.
    }
    if ( !is_single() || 'post' !== get_post_type() ) {
        return;
    }
    $post_id = get_the_ID();
    $image = get_the_post_thumbnail_url( $post_id, 'full' );
    $schema = array(
        '@context'         => 'https://schema.org',
        '@type'            => 'Article',
        'headline'         => get_the_title( $post_id ),
        'datePublished'    => get_the_date( 'c', $post_id ),
        'dateModified'     => get_the_modified_date( 'c', $post_id ),
        'author'           => array(
            '@type' => 'Person',
            'name'  => get_the_author_meta( 'display_name', get_post_field( 'post_author', $post_id ) ),
        ),
        'mainEntityOfPage' => get_permalink( $post_id ),
    );
    if ( $image ) {
        $schema['image'] = $image;
    }
    citameia_print_json_ld( $schema );
}

/**
 * =========================================================
 * SCHEMA: Product (WooCommerce)
 * =========================================================
 */
add_action( 'wp_head', 'geo_radar_output_product_schema' );
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_output_product_schema() {
    if ( citameia_should_skip_product_schema() ) {
        return;
        // Rank Math o el addon de WooCommerce SEO de Yoast ya generan schema Product.
    }
    if ( !function_exists( 'is_product' ) || !is_product() ) {
        return;
    }
    // Todo lo de aquí depende de WooCommerce y de cómo esté configurada
    // cada tienda (página de tienda asignada o no, producto con o sin
    // imagen, reseñas, etc.). Si algo falla, preferimos que esta pieza de
    // schema simplemente no se imprima, en vez de tumbar el sitio entero
    // con un error fatal, sobre todo pensando en que este plugin se
    // instala en tiendas de terceros con configuraciones que no controlamos.
    try {
        // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- variable global propia de WooCommerce, mismo caso que arriba.
        global $product;
        // phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
        if ( !is_a( $product, 'WC_Product' ) ) {
            return;
        }
        $image_id = $product->get_image_id();
        $image_url = ( $image_id ? wp_get_attachment_image_url( $image_id, 'full' ) : '' );
        $schema = array(
            '@context'    => 'https://schema.org',
            '@type'       => 'Product',
            'name'        => $product->get_name(),
            'description' => wp_strip_all_tags( ( $product->get_short_description() ? $product->get_short_description() : $product->get_description() ) ),
            'sku'         => $product->get_sku(),
            'offers'      => array(
                '@type'         => 'Offer',
                'url'           => get_permalink( $product->get_id() ),
                'priceCurrency' => get_woocommerce_currency(),
                'price'         => $product->get_price(),
                'availability'  => ( $product->is_in_stock() ? 'https://schema.org/InStock' : 'https://schema.org/OutOfStock' ),
            ),
        );
        if ( $image_url ) {
            $schema['image'] = $image_url;
        }
        // AggregateRating + Review: solo si el producto tiene reseñas reales, nunca inventadas.
        if ( $product->get_review_count() > 0 ) {
            $schema['aggregateRating'] = array(
                '@type'       => 'AggregateRating',
                'ratingValue' => (string) $product->get_average_rating(),
                'reviewCount' => (string) $product->get_review_count(),
            );
            $comments = get_comments( array(
                'post_id' => $product->get_id(),
                'status'  => 'approve',
                'type'    => 'review',
                'number'  => 5,
            ) );
            $reviews = array();
            foreach ( $comments as $c ) {
                $rating = get_comment_meta( $c->comment_ID, 'rating', true );
                $body = trim( wp_strip_all_tags( $c->comment_content ) );
                if ( '' === $body ) {
                    continue;
                }
                $reviews[] = array(
                    '@type'         => 'Review',
                    'author'        => array(
                        '@type' => 'Person',
                        'name'  => ( $c->comment_author ? $c->comment_author : 'Cliente' ),
                    ),
                    'datePublished' => get_comment_date( 'c', $c ),
                    'reviewBody'    => $body,
                    'reviewRating'  => array(
                        '@type'       => 'Rating',
                        'ratingValue' => ( $rating ? (string) $rating : '5' ),
                        'bestRating'  => '5',
                    ),
                );
            }
            if ( !empty( $reviews ) ) {
                $schema['review'] = $reviews;
            }
        }
        citameia_print_json_ld( $schema );
    } catch ( \Throwable $e ) {
        // No hacemos nada más: mejor sin este schema puntual que tumbar el sitio.
        return;
    }
}

/**
 * =========================================================
 * SCHEMA: BreadcrumbList
 * =========================================================
 * Ayuda a que Google y los motores de IA entienden la posición de una
 * página dentro de la estructura del sitio (Inicio > Categoría > Página).
 * Se omite si Yoast/Rank Math ya están activos, porque su schema de
 * WebPage normalmente ya incluye su propio breadcrumb.
 */
/**
 * URL de la página de tienda de WooCommerce, de forma segura. Si la
 * tienda no tiene una página asignada en Ajustes > Productos (algo que
 * pasa cuando se instala WooCommerce sin terminar el asistente), regresa
 * una cadena vacía en vez de pasarle un ID inválido a get_permalink().
 */
function citameia_wc_shop_url() {
    if ( !function_exists( 'wc_get_page_id' ) ) {
        return '';
    }
    $shop_id = wc_get_page_id( 'shop' );
    if ( $shop_id <= 0 ) {
        return '';
    }
    $url = get_permalink( $shop_id );
    return ( $url ? $url : '' );
}

function citameia_build_breadcrumb_items() {
    // En el inicio no hace falta breadcrumb.
    if ( is_front_page() ) {
        return array();
    }
    $items = array();
    $items[] = array(
        'name' => 'Inicio',
        'url'  => home_url( '/' ),
    );
    if ( function_exists( 'is_shop' ) && is_shop() ) {
        $items[] = array(
            'name' => 'Tienda',
            'url'  => '',
        );
    } elseif ( function_exists( 'is_product' ) && is_product() ) {
        $items[] = array(
            'name' => 'Tienda',
            'url'  => citameia_wc_shop_url(),
        );
        $terms = get_the_terms( get_the_ID(), 'product_cat' );
        if ( $terms && !is_wp_error( $terms ) ) {
            $term = $terms[0];
            $items[] = array(
                'name' => $term->name,
                'url'  => get_term_link( $term ),
            );
        }
        $items[] = array(
            'name' => get_the_title(),
            'url'  => '',
        );
    } elseif ( function_exists( 'is_product_category' ) && is_product_category() ) {
        $items[] = array(
            'name' => 'Tienda',
            'url'  => citameia_wc_shop_url(),
        );
        $items[] = array(
            'name' => single_term_title( '', false ),
            'url'  => '',
        );
    } elseif ( is_category() ) {
        $items[] = array(
            'name' => single_cat_title( '', false ),
            'url'  => '',
        );
    } elseif ( is_single() && 'post' === get_post_type() ) {
        $cats = get_the_category();
        if ( !empty( $cats ) ) {
            $items[] = array(
                'name' => $cats[0]->name,
                'url'  => get_category_link( $cats[0] ),
            );
        }
        $items[] = array(
            'name' => get_the_title(),
            'url'  => '',
        );
    } elseif ( is_page() ) {
        $post_id = get_the_ID();
        $ancestors = array_reverse( get_post_ancestors( $post_id ) );
        foreach ( $ancestors as $ancestor_id ) {
            $items[] = array(
                'name' => get_the_title( $ancestor_id ),
                'url'  => get_permalink( $ancestor_id ),
            );
        }
        $items[] = array(
            'name' => get_the_title(),
            'url'  => '',
        );
    } elseif ( is_single() ) {
        // Otros tipos de contenido personalizados (ej. Eventos, Talleres).
        $items[] = array(
            'name' => get_the_title(),
            'url'  => '',
        );
    } else {
        return array();
        // Búsquedas, 404, etc., no aplica breadcrumb.
    }
    return $items;
}

add_action( 'wp_head', 'citameia_output_breadcrumb_schema' );
function citameia_output_breadcrumb_schema() {
    if ( citameia_should_skip_core_schema() ) {
        return;
        // Yoast/Rank Math ya incluyen su propio breadcrumb en el schema de WebPage.
    }
    try {
        $items = citameia_build_breadcrumb_items();
        if ( count( $items ) < 2 ) {
            return;
            // No vale la pena un breadcrumb de un solo nivel.
        }
        $list_items = array();
        foreach ( $items as $i => $item ) {
            $entry = array(
                '@type'    => 'ListItem',
                'position' => $i + 1,
                'name'     => $item['name'],
            );
            if ( !empty( $item['url'] ) ) {
                $entry['item'] = $item['url'];
            }
            $list_items[] = $entry;
        }
        $schema = array(
            '@context'        => 'https://schema.org',
            '@type'           => 'BreadcrumbList',
            'itemListElement' => $list_items,
        );
        citameia_print_json_ld( $schema );
    } catch ( \Throwable $e ) {
        return;
    }
}

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_register_rewrite() {
    add_rewrite_rule( '^llms\\.txt$', 'index.php?geo_radar_llms=1', 'top' );
}

add_action( 'init', 'geo_radar_register_rewrite' );
add_filter( 'query_vars', function ( $vars ) {
    $vars[] = 'geo_radar_llms';
    return $vars;
} );
add_action( 'template_redirect', 'geo_radar_maybe_serve_llms_virtual' );
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_maybe_serve_llms_virtual() {
    if ( '1' !== get_query_var( 'geo_radar_llms' ) ) {
        return;
    }
    // Si existe el archivo físico, que lo sirva el servidor web directamente (no debería llegar aquí).
    // Esta ruta es respaldo por si el archivo físico no se pudo crear por permisos.
    header( 'Content-Type: text/plain; charset=utf-8' );
    // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- respuesta text/plain, no HTML; el navegador nunca la interpreta como marcado, y todos los valores ya se sanitizaron al guardarse en Datos del negocio.
    echo geo_radar_build_llms_content();
    exit;
}

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_build_llms_content() {
    $s = geo_radar_get_settings();
    $lines = array();
    $lines[] = '# ' . $s['business_name'];
    $lines[] = '';
    // El estándar llms.txt pide que el resumen vaya en formato blockquote,
    // justo después del H1 — así lo hacen todos los ejemplos oficiales
    // (incluido el de Anthropic).
    if ( !empty( $s['llms_intro'] ) ) {
        $lines[] = '> ' . str_replace( "\n", ' ', $s['llms_intro'] );
    } elseif ( !empty( $s['description'] ) ) {
        $lines[] = '> ' . str_replace( "\n", ' ', $s['description'] );
    }
    $lines[] = '';
    $lines[] = '## ' . __( 'Información del negocio', 'citameia' );
    if ( !empty( $s['street'] ) || !empty( $s['city'] ) ) {
        $lines[] = '- ' . __( 'Dirección:', 'citameia' ) . ' ' . trim( $s['street'] . ', ' . $s['city'] . ', ' . $s['state'] . ' ' . $s['zip'] );
    }
    if ( !empty( $s['phone'] ) ) {
        $lines[] = '- ' . __( 'Teléfono:', 'citameia' ) . ' ' . $s['phone'];
    }
    if ( !empty( $s['email'] ) ) {
        $lines[] = '- ' . __( 'Correo:', 'citameia' ) . ' ' . $s['email'];
    }
    if ( !empty( $s['opening_hours'] ) ) {
        $lines[] = '- ' . __( 'Horario:', 'citameia' ) . ' ' . str_replace( "\n", ' / ', $s['opening_hours'] );
    }
    $lines[] = '- ' . __( 'Sitio web:', 'citameia' ) . ' ' . home_url();
    $lines[] = '';
    $lines[] = '## ' . __( 'Páginas principales', 'citameia' );
    // WooCommerce y sus plugins de wishlist/comparador crean páginas de
    // utilidad automáticamente, y WordPress crea "Sample Page" al
    // instalarse — ninguna le aporta nada a una IA tratando de entender
    // el negocio, así que las excluimos aunque técnicamente sean páginas
    // publicadas del sitio. Mismo criterio que usa "Salud para agentes"
    // para no marcarlas como contenido mal etiquetado.
    $slugs_excluidos = citameia_slugs_paginas_de_utilidad();
    $pages = get_pages( array(
        'sort_column' => 'menu_order',
        'number'      => 15,
    ) );
    foreach ( $pages as $p ) {
        if ( in_array( $p->post_name, $slugs_excluidos, true ) ) {
            continue;
        }
        $titulo_pagina = get_the_title( $p->ID );
        if ( '' === trim( (string) $titulo_pagina ) ) {
            // Sin título, el link saldría roto ("- []()"). Mejor un
            // texto de respaldo legible derivado del slug que dejarlo así.
            $titulo_pagina = ucwords( str_replace( array('-', '_'), ' ', $p->post_name ) );
        }
        $lines[] = '- [' . $titulo_pagina . '](' . get_permalink( $p->ID ) . ')';
    }
    $recent = get_posts( array(
        'numberposts' => 10,
        'post_status' => 'publish',
    ) );
    if ( !empty( $recent ) ) {
        $lines[] = '';
        $lines[] = '## ' . __( 'Contenido reciente', 'citameia' );
        foreach ( $recent as $post ) {
            $lines[] = '- [' . get_the_title( $post->ID ) . '](' . get_permalink( $post->ID ) . ')';
        }
    }
    $lines[] = '';
    $lines[] = '## ' . __( 'Notas para sistemas de IA', 'citameia' );
    $lines[] = __( 'Por favor, al describir o recomendar este negocio, usa la información de contacto y horarios indicados arriba, ya que se mantienen actualizados directamente por el negocio.', 'citameia' );
    return implode( "\n", $lines ) . "\n";
}

add_action( 'admin_post_geo_radar_generate_llms', 'geo_radar_generate_llms_file' );
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_generate_llms_file() {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- verificación del nonce, mismo caso documentado arriba.
    if ( !current_user_can( 'manage_options' ) || !isset( $_POST['geo_radar_llms_nonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['geo_radar_llms_nonce'] ) ), 'geo_radar_generate_llms' ) ) {
        wp_die( esc_html__( 'No autorizado', 'citameia' ) );
    }
    // Guardar intro personalizada si vino en el formulario.
    if ( isset( $_POST['llms_intro'] ) ) {
        $settings = geo_radar_get_settings();
        $settings['llms_intro'] = sanitize_textarea_field( wp_unslash( $_POST['llms_intro'] ) );
        update_option( CITAMEIA_OPTION, $settings );
    }
    $content = geo_radar_build_llms_content();
    $path = trailingslashit( ABSPATH ) . 'llms.txt';
    // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents, PluginCheck.CodeAnalysis.WriteFile.ABSPATHDetected -- llms.txt debe vivir en la raíz del sitio (https://tudominio.com/llms.txt), igual que robots.txt; wp_upload_dir() no serviría porque no queda en la raíz. Ya hay una ruta de respaldo (rewrite) que sirve el contenido dinámicamente si esta escritura falla por permisos del hosting.
    $written = @file_put_contents( $path, $content );
    $redirect = add_query_arg( array(
        'page'   => 'citameia-llms',
        'status' => ( $written !== false ? 'ok' : 'error' ),
    ), admin_url( 'admin.php' ) );
    wp_safe_redirect( $redirect );
    exit;
}

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- prefijo legacy 'geo_radar_' (nombre original del plugin antes de renombrarse a CítameIA). Se deja sin cambiar a propósito: es un prefijo lo bastante específico para no chocar con otros plugins, y renombrar ~29 funciones usadas en todo el archivo tendría un riesgo real de romper algo por un solo nombre mal escrito, a cambio de un beneficio puramente cosmético.
function geo_radar_render_llms_page() {
    $s = geo_radar_get_settings();
    $path = trailingslashit( ABSPATH ) . 'llms.txt';
    $exists = file_exists( $path );
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- solo lectura, decide qué aviso mostrar (?status=ok/error) tras un redirect; ya sanitizado con sanitize_text_field(wp_unslash()).
    $status = ( isset( $_GET['status'] ) ? sanitize_text_field( wp_unslash( $_GET['status'] ) ) : '' );
    ?>
	<div class="wrap geo-radar-wrap">
		<?php 
    citameia_render_admin_header( 'citameia-llms' );
    ?>
				<p class="citameia-page-intro"><?php 
    /* translators: %s: el nombre del archivo llms.txt, en formato código */
    printf( esc_html__( 'El archivo %s es un estándar emergente: un resumen en texto plano de tu negocio pensado para que los sistemas de IA lo lean directamente, en vez de tener que interpretar todo tu HTML.', 'citameia' ), '<code>llms.txt</code>' );
    ?></p>

		<?php 
    if ( 'ok' === $status ) {
        ?>
			<div class="notice notice-success"><p><?php 
        esc_html_e( 'Archivo generado correctamente en la raíz del sitio.', 'citameia' );
        ?></p></div>
		<?php 
    } elseif ( 'error' === $status ) {
        ?>
						<div class="notice notice-error"><p><?php 
        /* translators: %s: la URL donde se sigue sirviendo el archivo llms.txt, en formato código */
        printf( esc_html__( 'No se pudo escribir el archivo directamente (permisos del hosting). Se sigue sirviendo la versión dinámica en %s.', 'citameia' ), '<code>' . esc_html( home_url( '/llms.txt' ) ) . '</code>' );
        ?></p></div>
		<?php 
    }
    ?>

		<div class="citameia-step-card">
			<div class="citameia-step-head"><span class="citameia-step-num">1</span><h2><?php 
    esc_html_e( 'Estado del archivo', 'citameia' );
    ?></h2></div>
			<?php 
    if ( $exists ) {
        ?>
				<div class="notice notice-success" style="padding:12px 14px;">
					<p style="margin:0;"><strong><?php 
        esc_html_e( 'Archivo físico generado.', 'citameia' );
        ?></strong> <a href="<?php 
        echo esc_url( home_url( '/llms.txt' ) );
        ?>" target="_blank"><?php 
        esc_html_e( 'Verlo', 'citameia' );
        ?></a></p>
				</div>
			<?php 
    } else {
        ?>
				<div class="notice notice-warning inline" style="padding:12px 14px;">
					<p style="margin:0;">
						<strong><?php 
        esc_html_e( 'Aún no generado como archivo físico.', 'citameia' );
        ?></strong>
						<?php 
        printf( 
            /* translators: %s: enlace a la URL dinámica de llms.txt */
            esc_html__( 'Ya es accesible dinámicamente en %s, pero conviene generarlo como archivo real abajo.', 'citameia' ),
            '<a href="' . esc_url( home_url( '/llms.txt' ) ) . '" target="_blank">' . esc_html( home_url( '/llms.txt' ) ) . '</a>'
         );
        ?>
					</p>
				</div>
			<?php 
    }
    ?>
		</div>

		<form method="post" action="<?php 
    echo esc_url( admin_url( 'admin-post.php' ) );
    ?>">
			<input type="hidden" name="action" value="geo_radar_generate_llms">
			<?php 
    wp_nonce_field( 'geo_radar_generate_llms', 'geo_radar_llms_nonce' );
    ?>

			<div class="citameia-step-card">
				<div class="citameia-step-head"><span class="citameia-step-num">2</span><h2><?php 
    esc_html_e( 'Introducción personalizada (opcional)', 'citameia' );
    ?></h2></div>
				<p class="description"><?php 
    esc_html_e( 'Si la dejas vacía, se usa la descripción del negocio.', 'citameia' );
    ?></p>
				<textarea name="llms_intro" rows="4" class="large-text"><?php 
    echo esc_textarea( $s['llms_intro'] );
    ?></textarea>
			</div>

			<div class="citameia-step-card">
				<div class="citameia-step-head"><span class="citameia-step-num">3</span><h2><?php 
    esc_html_e( 'Vista previa del contenido actual', 'citameia' );
    ?></h2></div>
				<pre class="geo-radar-code"><?php 
    echo esc_html( geo_radar_build_llms_content() );
    ?></pre>
				<div class="btn-row" style="margin-top:16px;">
					<?php 
    submit_button(
        __( 'Generar / actualizar ahora', 'citameia' ),
        'primary',
        'submit',
        false
    );
    ?>
				</div>
			</div>
		</form>
	</div>
	<?php 
}

/**
 * =========================================================
 * PANTALLA: VALIDAR SCHEMA
 * =========================================================
 */
function citameia_render_validate_page() {
    $s = geo_radar_get_settings();
    $seo_plugins = citameia_detect_seo_plugins();
    $skip_core = citameia_should_skip_core_schema();
    // URL a probar: viene del formulario (GET) o por defecto la portada.
    $test_url = ( isset( $_GET['citameia_test_url'] ) ? esc_url_raw( wp_unslash( $_GET['citameia_test_url'] ) ) : home_url() );
    if ( empty( $test_url ) ) {
        $test_url = home_url();
    }
    $rich_results_link = 'https://search.google.com/test/rich-results?url=' . rawurlencode( $test_url );
    $schema_org_link = 'https://validator.schema.org/#url=' . rawurlencode( $test_url );
    // Atajos: portada + últimas entradas + últimos productos.
    $shortcuts = array(array(
        'label' => __( 'Inicio', 'citameia' ),
        'url'   => home_url(),
    ));
    $recent_post = get_posts( array(
        'numberposts' => 3,
        'post_status' => 'publish',
    ) );
    foreach ( $recent_post as $p ) {
        /* translators: %s: título de la entrada */
        $label_entrada = sprintf( __( 'Entrada: %s', 'citameia' ), get_the_title( $p->ID ) );
        $shortcuts[] = array(
            'label' => $label_entrada,
            'url'   => get_permalink( $p->ID ),
        );
    }
    if ( class_exists( 'WooCommerce' ) ) {
        $recent_products = wc_get_products( array(
            'limit'  => 3,
            'status' => 'publish',
        ) );
        foreach ( $recent_products as $prod ) {
            /* translators: %s: nombre del producto */
            $label_producto = sprintf( __( 'Producto: %s', 'citameia' ), $prod->get_name() );
            $shortcuts[] = array(
                'label' => $label_producto,
                'url'   => get_permalink( $prod->get_id() ),
            );
        }
    }
    // Construimos el mismo schema que se inyectaría en la portada, para previsualizarlo aquí.
    $business = ( $skip_core ? null : citameia_build_business_schema_array( $s ) );
    $website = ( $skip_core ? null : citameia_build_website_schema_array( $s ) );
    // Chequeo de campos requeridos/recomendados por Google para LocalBusiness.
    $field_checks = array(
        'name'       => array(
            'label' => __( 'Nombre', 'citameia' ),
            'ok'    => !empty( $s['business_name'] ),
        ),
        'telephone'  => array(
            'label' => __( 'Teléfono', 'citameia' ),
            'ok'    => !empty( $s['phone'] ),
        ),
        'image/logo' => array(
            'label' => __( 'Logo / imagen', 'citameia' ),
            'ok'    => !empty( $s['logo_url'] ),
        ),
    );
    if ( !isset( $s['physical_presence'] ) || 'digital' !== $s['physical_presence'] ) {
        $field_checks = array(
            'address' => array(
                'label' => __( 'Dirección', 'citameia' ),
                'ok'    => !empty( $s['street'] ) && !empty( $s['city'] ),
            ),
        ) + $field_checks;
    }
    ?>
	<div class="wrap geo-radar-wrap">
		<?php 
    citameia_render_admin_header( 'citameia-validar' );
    ?>
		<p class="citameia-page-intro"><?php 
    esc_html_e( 'Revisa que el schema.org que se genera sea válido para Google y para los motores de IA, sin salir de WordPress.', 'citameia' );
    ?></p>

		<?php 
    if ( $skip_core ) {
        ?>
			<div class="notice notice-info" style="padding:12px 14px;">
				<p style="margin:0;">
					<?php 
        printf( 
            /* translators: %s: nombre del plugin de SEO detectado (Yoast SEO o Rank Math) */
            esc_html__( 'CítameIA no está generando su propio schema de Organization/WebSite en este sitio porque detectamos %s activo. Valida el schema usando los enlaces de abajo. Vas a estar probando el que genera ese plugin, no el de CítameIA.', 'citameia' ),
            '<strong>' . esc_html( ( $seo_plugins['yoast'] ? 'Yoast SEO' : 'Rank Math' ) ) . '</strong>'
         );
        ?>
				</p>
			</div>
		<?php 
    }
    ?>

		<?php 
    if ( citameia_should_skip_product_schema() ) {
        ?>
			<div class="notice notice-info" style="padding:12px 14px;">
				<p style="margin:0;">
					<?php 
        printf( 
            /* translators: %s: nombre del plugin que ya genera schema de Producto */
            esc_html__( 'CítameIA tampoco está generando schema de Producto en las páginas de WooCommerce, porque detectamos %s activo. Ese plugin ya lo cubre. Si validas una página de producto y ves dos bloques Product en el código fuente, revisa que no tengas ambos generándolo a la vez.', 'citameia' ),
            '<strong>' . esc_html( implode( ' y ', citameia_product_conflict_names() ) ) . '</strong>'
         );
        ?>
				</p>
			</div>
		<?php 
    }
    ?>

		<?php 
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- verificación del nonce, mismo caso documentado arriba.
    if ( isset( $_GET['citameia_recheck_bots'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'citameia_recheck_bots' ) ) {
        delete_transient( 'citameia_ai_bots_check' );
    }
    $bots_check = citameia_check_ai_bots();
    ?>
		<div class="citameia-step-card">
			<div class="citameia-step-head"><span class="citameia-step-num">0</span><h2><?php 
    esc_html_e( '¿Pueden los motores de IA leer tu sitio?', 'citameia' );
    ?></h2></div>
			<p><?php 
    esc_html_e( 'Antes que cualquier otra cosa: revisamos tu archivo robots.txt para confirmar que no estés bloqueando a los propios motores de IA sin darte cuenta. Si un motor no puede leer tu sitio, el schema y el llms.txt no sirven de nada.', 'citameia' );
    ?></p>
			<?php 
    if ( !$bots_check['checked'] ) {
        ?>
				<div class="notice notice-warning inline" style="padding:12px 14px;">
										<p style="margin:0;"><?php 
        /* translators: %s: la URL de tu archivo robots.txt */
        printf( esc_html__( 'No pudimos leer tu robots.txt en este momento. Esto no necesariamente es un problema, pero vale la pena confirmarlo manualmente visitando %s en tu navegador.', 'citameia' ), esc_html( home_url( '/robots.txt' ) ) );
        ?></p>
				</div>
			<?php 
    } elseif ( !empty( $bots_check['blocked'] ) ) {
        ?>
				<div class="notice notice-error" style="padding:12px 14px;">
					<p style="margin:0 0 6px;"><strong><?php 
        esc_html_e( 'Tu robots.txt está bloqueando a estos motores de IA:', 'citameia' );
        ?></strong> <?php 
        echo esc_html( implode( ', ', $bots_check['blocked'] ) );
        ?>.</p>
					<p style="margin:0;"><?php 
        esc_html_e( 'Revisa tu archivo robots.txt directamente, o algún plugin de seguridad (como Wordfence o Sucuri) o el firewall de tu hosting, que a veces bloquean estos bots por error al confundirlos con tráfico malicioso.', 'citameia' );
        ?></p>
				</div>
			<?php 
    } else {
        ?>
				<div class="notice notice-success" style="padding:12px 14px;">
					<p style="margin:0;"><?php 
        esc_html_e( 'Ningún motor de IA conocido está bloqueado en tu robots.txt. Bien ahí.', 'citameia' );
        ?></p>
				</div>
			<?php 
    }
    ?>
			<div class="btn-row" style="margin-top:14px;">
				<a class="btn-secondary" href="<?php 
    echo esc_url( wp_nonce_url( add_query_arg( array(
        'page'                  => 'citameia-validar',
        'citameia_recheck_bots' => '1',
    ), admin_url( 'admin.php' ) ), 'citameia_recheck_bots' ) );
    ?>"><?php 
    esc_html_e( 'Revisar de nuevo', 'citameia' );
    ?></a>
				<a class="btn-secondary" target="_blank" rel="noopener" href="<?php 
    echo esc_url( home_url( '/robots.txt' ) );
    ?>"><?php 
    esc_html_e( 'Ver mi robots.txt', 'citameia' );
    ?></a>
			</div>
		</div>

		<div class="citameia-step-card">
			<div class="citameia-step-head"><span class="citameia-step-num">1</span><h2><?php 
    esc_html_e( 'Elige qué página probar', 'citameia' );
    ?></h2></div>
			<form method="get">
				<input type="hidden" name="page" value="citameia-validar">
				<div class="citameia-url-row">
					<input type="url" name="citameia_test_url" class="regular-text" value="<?php 
    echo esc_attr( $test_url );
    ?>" placeholder="https://tusitio.com/pagina-a-probar">
					<?php 
    submit_button(
        __( 'Usar esta URL', 'citameia' ),
        'primary',
        'submit',
        false
    );
    ?>
				</div>
			</form>
			<div class="citameia-shortcuts">
				<span class="citameia-shortcuts-label"><?php 
    esc_html_e( 'Atajos', 'citameia' );
    ?></span>
				<?php 
    foreach ( $shortcuts as $sc ) {
        ?>
					<a class="citameia-shortcut-pill"
						href="<?php 
        echo esc_url( add_query_arg( array(
            'page'              => 'citameia-validar',
            'citameia_test_url' => rawurlencode( $sc['url'] ),
        ), admin_url( 'admin.php' ) ) );
        ?>">
						<?php 
        echo esc_html( $sc['label'] );
        ?>
					</a>
				<?php 
    }
    ?>
			</div>
		</div>

		<div class="citameia-step-card">
			<div class="citameia-step-head"><span class="citameia-step-num">2</span><h2><?php 
    esc_html_e( 'Pruébalo en las herramientas oficiales', 'citameia' );
    ?></h2></div>
			<p class="description">
				<?php 
    printf( 
        /* translators: %s: la palabra "localhost" en formato de código */
        esc_html__( 'Importante: estos validadores necesitan leer tu sitio ya publicado en internet, no funcionan con %s, con un sitio en mantenimiento, ni detrás de un login. Si tu sitio todavía no es público, esta parte no va a funcionar todavía.', 'citameia' ),
        '<code>localhost</code>'
     );
    ?>
			</p>
			<div class="btn-row">
				<a class="btn-primary" target="_blank" rel="noopener" href="<?php 
    echo esc_url( $rich_results_link );
    ?>">
					<?php 
    esc_html_e( 'Probar en Google Rich Results Test ↗', 'citameia' );
    ?>
				</a>
				<a class="btn-secondary" target="_blank" rel="noopener" href="<?php 
    echo esc_url( $schema_org_link );
    ?>">
					<?php 
    esc_html_e( 'Probar en el validador de Schema.org ↗', 'citameia' );
    ?>
				</a>
			</div>
		</div>

		<div class="citameia-step-card">
			<div class="citameia-step-head"><span class="citameia-step-num">3</span><h2><?php 
    esc_html_e( 'Campos clave para LocalBusiness', 'citameia' );
    ?></h2></div>
			<div class="task-list">
				<?php 
    foreach ( $field_checks as $check ) {
        ?>
					<div class="task-row<?php 
        echo ( $check['ok'] ? '' : ' warn' );
        ?>">
						<div class="task-icon <?php 
        echo ( $check['ok'] ? 'ok' : 'warn' );
        ?>"><?php 
        echo ( $check['ok'] ? '✓' : '!' );
        ?></div>
						<div class="task-body"><div class="task-title"><?php 
        echo esc_html( $check['label'] );
        ?></div></div>
					</div>
				<?php 
    }
    ?>
			</div>
						<p class="description"><?php 
    /* translators: %s: nombre de la pantalla "Datos del negocio", entre comillas */
    printf( esc_html__( 'Esto revisa los datos en %s, no sustituye la validación oficial de arriba, solo te dice si te falta algo antes de probar.', 'citameia' ), '"' . esc_html__( 'Datos del negocio', 'citameia' ) . '"' );
    ?></p>
		</div>

		<div class="citameia-step-card">
			<div class="citameia-step-head"><span class="citameia-step-num">4</span><h2><?php 
    esc_html_e( 'Vista previa del JSON que se genera en tu portada', 'citameia' );
    ?></h2></div>
			<?php 
    if ( !$business ) {
        ?>
				<p class="description">
					<?php 
        echo ( $skip_core ? esc_html__( 'No aplica: otro plugin de SEO está generando este schema.', 'citameia' ) : esc_html__( 'Aún no hay suficiente información en "Datos del negocio" para generar el schema.', 'citameia' ) );
        ?>
				</p>
			<?php 
    } else {
        ?>
				<p><strong><?php 
        echo esc_html( ( isset( $business['@type'] ) ? $business['@type'] : 'Organization' ) );
        ?></strong></p>
				<pre class="geo-radar-code"><?php 
        echo esc_html( wp_json_encode( $business, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES ) );
        ?></pre>
				<p><strong>WebSite</strong></p>
				<pre class="geo-radar-code"><?php 
        echo esc_html( wp_json_encode( $website, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES ) );
        ?></pre>
			<?php 
    }
    ?>
		</div>
	</div>
	<?php 
}

add_action( 'admin_post_citameia_reset_all_data', 'citameia_handle_reset_all_data' );
function citameia_handle_reset_all_data() {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- verificación del nonce, mismo caso documentado arriba.
    if ( !current_user_can( 'manage_options' ) || !isset( $_POST['citameia_reset_nonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['citameia_reset_nonce'] ) ), 'citameia_reset_all_data' ) || !isset( $_POST['confirm_text'] ) || 'BORRAR' !== sanitize_text_field( wp_unslash( $_POST['confirm_text'] ) ) ) {
        wp_die( esc_html__( 'No autorizado o confirmación incorrecta.', 'citameia' ) . ' <a href="' . esc_url( admin_url( 'admin.php?page=citameia-datos' ) ) . '">' . esc_html__( 'Volver', 'citameia' ) . '</a>' );
    }
    delete_option( CITAMEIA_OPTION );
    delete_option( 'geo_radar_score_history' );
    delete_option( CITAMEIA_FAQ_GROUPS_OPTION );
    delete_option( CITAMEIA_MENTION_TESTS_OPTION );
    delete_option( 'citameia_faq_schema_detectado' );
    global $wpdb;
    // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- no hay dato de usuario en esta consulta; citameia_crawler_log_table() regresa siempre $wpdb->prefix . 'citameia_crawler_log', un nombre de tabla fijo. $wpdb->prepare() no aplica a nombres de tabla, y el caché no aplica a un TRUNCATE (acción destructiva manual, de un solo uso).
    $wpdb->query( 'TRUNCATE TABLE ' . citameia_crawler_log_table() );
    delete_option( CITAMEIA_EXTERNAL_PRESENCE_OPTION );
    delete_option( 'citameia_reportes_log' );
    delete_option( 'citameia_reportes_email' );
    delete_option( 'citameia_og_enabled' );
    add_option( 'citameia_do_activation_redirect', true );
    wp_safe_redirect( admin_url( 'admin.php?page=citameia-bienvenida' ) );
    exit;
}

/**
 * =========================================================
 * PRUEBAS DE MENCIÓN EN IA (consulta a ciegas, registrada a mano)
 * =========================================================
 * No llama a ninguna API de pago ni requiere llaves. Genera la pregunta
 * sugerida, tú la pruebas directamente en ChatGPT/Gemini/Perplexity/Google,
 * y registras aquí si te mencionó o no. Con eso se construye un historial
 * real y honesto de citabilidad, igual que se hizo a mano para Funámbulo.
 */
define( 'CITAMEIA_MENTION_TESTS_OPTION', 'citameia_mention_tests' );
function citameia_get_mention_tests() {
    return get_option( CITAMEIA_MENTION_TESTS_OPTION, array() );
}

function citameia_business_type_noun(  $type  ) {
    $flat = geo_radar_business_types_flat();
    if ( !isset( $flat[$type] ) ) {
        return __( 'negocio', 'citameia' );
    }
    // Quita calificadores entre paréntesis, ej. "(genérico)", para que quede natural en una pregunta.
    $label = trim( preg_replace( '/\\s*\\([^)]*\\)/', '', $flat[$type] ) );
    return mb_strtolower( $label, 'UTF-8' );
}

function citameia_spanish_guess_feminine(  $noun  ) {
    $first_word = strtolower( trim( (string) strtok( trim( $noun ), ' ' ) ) );
    // Quita puntuación pegada (comas, puntos, etc.) que rompería la comparación de la última letra.
    $first_word = trim( $first_word, ",.;:!¡¿?()\"'" );
    $masculine_exceptions = array(
        'dia',
        'día',
        'mapa',
        'problema',
        'sistema',
        'programa',
        'idioma',
        'planeta',
        'clima',
        'tema',
        'poema',
        'panorama',
        'drama',
        'aroma',
        'cometa',
        'negocio',
        'despacho',
        'consultorio',
        'estudio',
        'taller',
        'restaurante',
        'hotel'
    );
    if ( in_array( $first_word, $masculine_exceptions, true ) ) {
        return false;
    }
    return substr( $first_word, -1 ) === 'a';
}

function citameia_generate_suggested_queries(  $s  ) {
    $noun = ( !empty( $s['business_niche'] ) ? trim( $s['business_niche'] ) : citameia_business_type_noun( $s['business_type'] ) );
    $nombre = ( !empty( $s['business_name'] ) ? $s['business_name'] : __( 'tu negocio', 'citameia' ) );
    // Quita punto, coma o signo final que la persona haya dejado en su
    // "giro específico" (ej. "...de México."), para no terminar con algo
    // como "México.?" al pegarle el signo de interrogación de la plantilla.
    $noun = rtrim( $noun, ".,;: " );
    // Un negocio 100% digital no tiene ciudad relevante; en vez de forzar
    // el texto genérico "en tu ciudad" (que no tiene sentido ahí), no se
    // agrega ningún lugar a la pregunta.
    $es_digital = isset( $s['physical_presence'] ) && 'digital' === $s['physical_presence'];
    if ( $es_digital ) {
        $lugar = '';
    } else {
        /* translators: %s: la ciudad del negocio, o "tu ciudad" si no está configurada */
        $lugar = ' ' . sprintf( __( 'en %s', 'citameia' ), ( !empty( $s['city'] ) ? $s['city'] : __( 'tu ciudad', 'citameia' ) ) );
    }
    $es_femenino = citameia_spanish_guess_feminine( $noun );
    $articulo = ( $es_femenino ? 'una' : 'un' );
    $adjetivo = ( $es_femenino ? 'buena' : 'buen' );
    // Las 4 preguntas se calculan aquí, en variables simples, en vez de
    // escribirlas directo dentro del array de abajo: el proceso de build
    // de Freemius reformatea arrays multilínea y en ese proceso puede
    // perder comentarios "translators:" que estén posicionados como
    // elemento de un array — como variable suelta, sí sobreviven.
    // El formato (__()) también se separa del sprintf() cuando tiene
    // varios argumentos: si la llamada es larga, Freemius a veces la
    // reparte en varias líneas y aleja el comentario de donde debe ir.
    /* translators: %1$s: artículo (ej. "el"), %2$s: adjetivo (ej. "mejor"), %3$s: giro del negocio, %4$s: ubicación */
    $fmt_1 = __( '¿Cuál es %1$s %2$s %3$s%4$s?', 'citameia' );
    $query_1 = sprintf(
        $fmt_1,
        $articulo,
        $adjetivo,
        $noun,
        $lugar
    );
    /* translators: %1$s: artículo, %2$s: giro del negocio, %3$s: ubicación */
    $fmt_2 = __( 'Recomiéndame %1$s %2$s%3$s', 'citameia' );
    $query_2 = sprintf(
        $fmt_2,
        $articulo,
        $noun,
        $lugar
    );
    /* translators: %1$s: giro del negocio, %2$s: ubicación */
    $query_3 = sprintf( __( '¿Qué opciones hay de %1$s%2$s?', 'citameia' ), $noun, $lugar );
    /* translators: %s: nombre del negocio */
    $query_4 = sprintf( __( '¿Conoces %s? Cuéntame de qué se trata.', 'citameia' ), $nombre );
    return array(
        array(
            'label' => __( 'Pregunta ciega (sin decir el nombre)', 'citameia' ),
            'query' => $query_1,
        ),
        array(
            'label' => __( 'Pregunta ciega, variante', 'citameia' ),
            'query' => $query_2,
        ),
        array(
            'label' => __( 'Pregunta ciega, sin artículo (evita errores de género)', 'citameia' ),
            'query' => $query_3,
        ),
        array(
            'label' => __( 'Verificación directa (línea base)', 'citameia' ),
            'query' => $query_4,
        )
    );
}

/**
 * =========================================================
 * PREGUNTAS FIJAS DE PRUEBA (para que el historial sea comparable)
 * =========================================================
 * Sin esto, cada visita regeneraba las preguntas a partir de los datos
 * actuales del negocio, y si cambiabas el "giro específico" a mitad de
 * camino, la redacción cambiaba y el historial dejaba de ser comparable
 * entre una fecha y otra. Ahora las preguntas se generan una sola vez,
 * se guardan, y se reutilizan siempre igual hasta que decidas
 * regenerarlas a propósito.
 */
define( 'CITAMEIA_MENTION_PROMPTS_OPTION', 'citameia_mention_prompts' );
function citameia_get_locked_prompts() {
    return get_option( CITAMEIA_MENTION_PROMPTS_OPTION, array() );
}

/**
 * Huella de los datos que alimentan la generación de preguntas. Se guarda
 * junto con las preguntas fijas cada vez que se generan, para poder avisar
 * después si esos datos cambiaron, sin regenerar nada solo.
 */
function citameia_datos_negocio_hash(  $s  ) {
    return md5( ($s['business_name'] ?? '') . '|' . ($s['business_niche'] ?? '') . '|' . ($s['business_type'] ?? '') . '|' . ($s['city'] ?? '') );
}

function citameia_lock_prompts(  $queries, $s = null  ) {
    $locked = array();
    foreach ( $queries as $q ) {
        $locked[] = array(
            'id'    => substr( md5( $q['query'] . microtime() . wp_rand() ), 0, 10 ),
            'label' => $q['label'],
            'query' => $q['query'],
        );
    }
    update_option( CITAMEIA_MENTION_PROMPTS_OPTION, $locked );
    if ( null !== $s ) {
        update_option( 'citameia_mention_prompts_hash', citameia_datos_negocio_hash( $s ) );
    }
    return $locked;
}

/**
 * Compara los datos actuales del negocio contra la huella guardada la
 * última vez que se generaron las preguntas fijas. Si no coinciden, quiere
 * decir que cambiaste nombre, giro, tipo o ciudad desde entonces, y las
 * preguntas actuales ya no reflejan esos datos. No las regenera solo
 * (rompería la comparación de tu historial); solo permite avisarte.
 */
function citameia_prompts_desactualizadas(  $s  ) {
    $guardado = get_option( 'citameia_mention_prompts_hash', '' );
    if ( '' === $guardado ) {
        return false;
        // Nunca se guardó huella (instalación previa a esta versión); no molestamos con el aviso.
    }
    return $guardado !== citameia_datos_negocio_hash( $s );
}

/**
 * Regresa las preguntas fijas ya guardadas. Si todavía no existen
 * (primera vez que se visita la pantalla), las genera y las guarda
 * automáticamente, para que queden fijas desde el primer momento.
 */
function citameia_ensure_locked_prompts(  $s  ) {
    $locked = citameia_get_locked_prompts();
    if ( !empty( $locked ) ) {
        return $locked;
    }
    return citameia_lock_prompts( citameia_generate_suggested_queries( $s ), $s );
}

add_action( 'admin_post_citameia_regenerate_prompts', 'citameia_handle_regenerate_prompts' );
function citameia_handle_regenerate_prompts() {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- verificación del nonce, mismo caso documentado arriba.
    if ( !current_user_can( 'manage_options' ) || !isset( $_POST['citameia_regen_nonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['citameia_regen_nonce'] ) ), 'citameia_regenerate_prompts' ) ) {
        wp_die( esc_html__( 'No autorizado', 'citameia' ) );
    }
    $s = geo_radar_get_settings();
    citameia_lock_prompts( citameia_generate_suggested_queries( $s ), $s );
    wp_safe_redirect( admin_url( 'admin.php?page=citameia-menciones&regenerated=1' ) );
    exit;
}

/**
 * Normaliza una pregunta para poder agrupar el historial por pregunta,
 * aunque haya variado un poco en mayúsculas o espacios.
 */
function citameia_normalize_query(  $query  ) {
    return trim( mb_strtolower( preg_replace( '/\\s+/', ' ', $query ), 'UTF-8' ) );
}

function citameia_get_ai_engines() {
    return array(
        'chatgpt'    => array(
            'label' => 'ChatGPT',
            'url'   => 'https://chat.openai.com/',
        ),
        'claude'     => array(
            'label' => 'Claude',
            'url'   => 'https://claude.ai/',
        ),
        'gemini'     => array(
            'label' => 'Gemini',
            'url'   => 'https://gemini.google.com/',
        ),
        'perplexity' => array(
            'label' => 'Perplexity',
            'url'   => 'https://www.perplexity.ai/',
        ),
        'google_ai'  => array(
            'label' => 'Google AI Overviews',
            'url'   => 'https://www.google.com/',
        ),
        'otro'       => array(
            'label' => __( 'Otro', 'citameia' ),
            'url'   => '',
        ),
    );
}

add_action( 'admin_init', 'citameia_handle_mention_test_save' );
function citameia_handle_mention_test_save() {
    if ( !current_user_can( 'manage_options' ) ) {
        return;
    }
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- verificación del nonce, mismo caso documentado arriba.
    if ( !isset( $_POST['citameia_mention_nonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['citameia_mention_nonce'] ) ), 'citameia_save_mention_test' ) ) {
        return;
    }
    $engine = ( isset( $_POST['mention_engine'] ) ? sanitize_text_field( wp_unslash( $_POST['mention_engine'] ) ) : '' );
    $query = ( isset( $_POST['mention_query'] ) ? sanitize_text_field( wp_unslash( $_POST['mention_query'] ) ) : '' );
    $mentioned = isset( $_POST['mention_result'] ) && 'si' === sanitize_text_field( wp_unslash( $_POST['mention_result'] ) );
    // "Citado con enlace" solo tiene sentido si sí te mencionó; si no te mencionó, no aplica.
    $linked = $mentioned && isset( $_POST['mention_linked'] ) && 'si' === sanitize_text_field( wp_unslash( $_POST['mention_linked'] ) );
    $notes = ( isset( $_POST['mention_notes'] ) ? sanitize_textarea_field( wp_unslash( $_POST['mention_notes'] ) ) : '' );
    if ( '' === $query ) {
        return;
    }
    $tests = citameia_get_mention_tests();
    $tests[] = array(
        'id'        => uniqid( 'mt_' ),
        'date'      => current_time( 'Y-m-d' ),
        'engine'    => $engine,
        'query'     => $query,
        'mentioned' => $mentioned,
        'linked'    => $linked,
        'notes'     => $notes,
    );
    if ( count( $tests ) > 200 ) {
        $tests = array_slice( $tests, -200 );
    }
    update_option( CITAMEIA_MENTION_TESTS_OPTION, $tests );
    add_action( 'admin_notices', function () {
        echo '<div class="notice notice-success is-dismissible"><p>Prueba registrada. Ya suma a tu historial de menciones en IA.</p></div>';
    } );
}

add_action( 'admin_post_citameia_delete_mention_test', 'citameia_handle_mention_test_delete' );
function citameia_handle_mention_test_delete() {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- verificación del nonce, mismo caso documentado arriba.
    if ( !current_user_can( 'manage_options' ) || !isset( $_GET['id'], $_GET['_wpnonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'citameia_delete_mention_' . sanitize_text_field( wp_unslash( $_GET['id'] ) ) ) ) {
        wp_die( esc_html__( 'No autorizado', 'citameia' ) );
    }
    $id = sanitize_text_field( wp_unslash( $_GET['id'] ) );
    $tests = citameia_get_mention_tests();
    foreach ( $tests as $i => $t ) {
        if ( $t['id'] === $id ) {
            unset($tests[$i]);
        }
    }
    update_option( CITAMEIA_MENTION_TESTS_OPTION, array_values( $tests ) );
    wp_safe_redirect( admin_url( 'admin.php?page=citameia-menciones&deleted=1' ) );
    exit;
}

/**
 * Pestaña "Menciones" dentro de Pruebas en IA — el registro manual y
 * honesto de pruebas que ya existía antes de agregar pestañas.
 */
function citameia_render_mentions_tab_menciones() {
    $citameia_ai_engines = citameia_get_ai_engines();
    $s = geo_radar_get_settings();
    $tests = array_reverse( citameia_get_mention_tests() );
    // más reciente primero
    $queries = citameia_ensure_locked_prompts( $s );
    $total = count( $tests );
    $mentioned = count( array_filter( $tests, function ( $t ) {
        return $t['mentioned'];
    } ) );
    $pct = ( $total > 0 ? round( $mentioned / $total * 100 ) : null );
    // isset() por si son pruebas guardadas antes de que existiera esta pregunta.
    $linked = count( array_filter( $tests, function ( $t ) {
        return !empty( $t['linked'] );
    } ) );
    $linked_pct = ( $mentioned > 0 ? round( $linked / $mentioned * 100 ) : null );
    // Conteo simple de motores distintos probados, solo para el KPI libre de
    // arriba. El desglose completo por motor/pregunta (con su detalle de
    // cuántas veces mencionó cada uno) es Pro y se calcula más abajo, justo
    // antes de usarse, dentro de su propio bloque is__premium_only().
    $engines_probados = count( array_unique( array_map( function ( $t ) {
        return ( $t['engine'] ? $t['engine'] : 'otro' );
    }, $tests ) ) );
    ?>
	<p class="citameia-page-intro"><?php 
    esc_html_e( 'Aquí no hay ninguna API automática consultando en tu nombre. Tú pruebas la pregunta directamente en cada IA y registras lo que encontraste. Así queda un historial real y honesto, no una simulación.', 'citameia' );
    ?></p>

	<?php 
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- solo lectura para decidir qué avisos mostrar tras un redirect; no se procesa ningún dato.
    ?>
	<?php 
    if ( isset( $_GET['deleted'] ) ) {
        ?>
		<div class="notice notice-success is-dismissible"><p><?php 
        esc_html_e( 'Prueba eliminada.', 'citameia' );
        ?></p></div>
	<?php 
    }
    ?>
	<?php 
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- misma razón: solo lectura para decidir qué aviso mostrar.
    ?>
	<?php 
    if ( isset( $_GET['regenerated'] ) ) {
        ?>
		<div class="notice notice-success is-dismissible"><p><?php 
        esc_html_e( 'Preguntas regeneradas. A partir de ahora se usarán estas nuevas versiones de forma fija.', 'citameia' );
        ?></p></div>
	<?php 
    }
    ?>


		<?php 
    if ( null !== $pct ) {
        ?>
			<div class="geo-radar-kpi-grid">
				<div class="geo-radar-kpi-card">
					<div class="geo-radar-kpi-num" style="color:<?php 
        echo esc_attr( ( $pct >= 50 ? '#1E7A4C' : (( $pct > 0 ? '#8A6529' : '#B3261E' )) ) );
        ?>;"><?php 
        echo esc_html( $pct );
        ?><span class="unit">%</span></div>
					<div class="geo-radar-kpi-label"><?php 
        esc_html_e( 'Menciones detectadas', 'citameia' );
        ?></div>
				</div>
				<div class="geo-radar-kpi-card">
					<div class="geo-radar-kpi-num"><?php 
        echo esc_html( $total );
        ?></div>
					<div class="geo-radar-kpi-label"><?php 
        esc_html_e( 'Pruebas registradas', 'citameia' );
        ?></div>
				</div>
				<div class="geo-radar-kpi-card">
					<div class="geo-radar-kpi-num"><?php 
        echo esc_html( $mentioned );
        ?></div>
					<div class="geo-radar-kpi-label"><?php 
        esc_html_e( 'Veces que sí apareciste', 'citameia' );
        ?></div>
				</div>
				<div class="geo-radar-kpi-card">
					<div class="geo-radar-kpi-num"><?php 
        echo esc_html( $engines_probados );
        ?></div>
					<div class="geo-radar-kpi-label"><?php 
        esc_html_e( 'Motores distintos probados', 'citameia' );
        ?></div>
				</div>
				<?php 
        if ( null !== $linked_pct ) {
            ?>
					<div class="geo-radar-kpi-card">
						<div class="geo-radar-kpi-num" style="color:<?php 
            echo esc_attr( ( $linked_pct >= 50 ? '#1E7A4C' : (( $linked_pct > 0 ? '#8A6529' : '#B3261E' )) ) );
            ?>;"><?php 
            echo esc_html( $linked );
            ?><span class="unit">/<?php 
            echo esc_html( $mentioned );
            ?></span></div>
						<div class="geo-radar-kpi-label"><?php 
            esc_html_e( 'Veces citado con enlace (de las que te mencionaron)', 'citameia' );
            ?></div>
					</div>
				<?php 
        }
        ?>
			</div>
		<?php 
    }
    ?>

		<?php 
    if ( citameia_prompts_desactualizadas( $s ) ) {
        ?>
			<div class="notice notice-warning inline" style="padding:12px 14px;">
				<p style="margin:0;"><strong><?php 
        esc_html_e( 'Cambiaste el nombre, giro, tipo o ciudad del negocio', 'citameia' );
        ?></strong> <?php 
        esc_html_e( 'desde que se generaron estas preguntas. Si quieres que las preguntas reflejen los datos nuevos, dale clic a "Regenerar preguntas sugeridas" más abajo. Si lo dejas así, las preguntas actuales se quedan igual a propósito, para que tu historial siga siendo comparable.', 'citameia' );
        ?></p>
			</div>
		<?php 
    }
    ?>

		<div class="citameia-step-card">
			<div class="citameia-step-head"><span class="citameia-step-num">1</span><h2><?php 
    esc_html_e( 'Tus preguntas fijas de prueba', 'citameia' );
    ?></h2></div>
			<p><?php 
    esc_html_e( 'Se generaron una sola vez, a partir de los datos de tu negocio, y se quedan fijas para que tu historial sea comparable de una fecha a otra. Puedes editar el texto aquí mismo antes de copiarlo, pero eso no cambia lo que queda guardado como "tu pregunta oficial".', 'citameia' );
    ?></p>
			<div class="citameia-prompts-grid">
				<?php 
    foreach ( $queries as $q ) {
        ?>
					<div class="geo-radar-faq-group-card">
						<div class="geo-radar-faq-group-head"><strong><?php 
        echo esc_html( $q['label'] );
        ?></strong></div>
						<textarea class="large-text geo-radar-editable-query" id="query-<?php 
        echo esc_attr( $q['id'] );
        ?>" rows="2"><?php 
        echo esc_textarea( $q['query'] );
        ?></textarea>
						<p>
							<button type="button" class="button button-small citameia-copy-query" data-target="query-<?php 
        echo esc_attr( $q['id'] );
        ?>"><?php 
        esc_html_e( 'Copiar', 'citameia' );
        ?></button>
							<button type="button" class="button button-small citameia-use-query" data-target="query-<?php 
        echo esc_attr( $q['id'] );
        ?>"><?php 
        esc_html_e( 'Usar en el formulario ↓', 'citameia' );
        ?></button>
						</p>
					</div>
				<?php 
    }
    ?>
			</div>
			<p class="description"><?php 
    esc_html_e( 'Si editas el cuadro de texto, es solo para copiar una variante puntual; no se guarda como cambio permanente. Para eso está el botón de regenerar de abajo.', 'citameia' );
    ?></p>

			<form method="post" action="<?php 
    echo esc_url( admin_url( 'admin-post.php' ) );
    ?>"
				onsubmit="return confirm('<?php 
    echo esc_js( __( 'Regenerar las preguntas crea una versión nueva. Las pruebas que ya registraste con la redacción anterior se quedan en tu historial, pero dejarán de ser directamente comparables con las nuevas. ¿Seguro que quieres regenerarlas?', 'citameia' ) );
    ?>');">
				<input type="hidden" name="action" value="citameia_regenerate_prompts">
				<?php 
    wp_nonce_field( 'citameia_regenerate_prompts', 'citameia_regen_nonce' );
    ?>
				<?php 
    submit_button(
        __( 'Regenerar preguntas sugeridas', 'citameia' ),
        'secondary',
        'submit',
        false
    );
    ?>
			</form>

			<div class="citameia-shortcuts" style="margin-top:16px;">
				<span class="citameia-shortcuts-label"><?php 
    esc_html_e( 'Ábrelas directamente en', 'citameia' );
    ?></span>
				<?php 
    foreach ( $citameia_ai_engines as $key => $eng ) {
        ?>
					<?php 
        if ( $eng['url'] ) {
            ?>
						<a href="<?php 
            echo esc_url( $eng['url'] );
            ?>" target="_blank" rel="noopener" class="citameia-shortcut-pill"><?php 
            echo esc_html( $eng['label'] );
            ?> ↗</a>
					<?php 
        }
        ?>
				<?php 
    }
    ?>
			</div>
		</div>

		<div class="citameia-step-card">
			<div class="citameia-step-head"><span class="citameia-step-num">2</span><h2><?php 
    esc_html_e( 'Registra lo que encontraste', 'citameia' );
    ?></h2></div>
			<form method="post">
			<?php 
    wp_nonce_field( 'citameia_save_mention_test', 'citameia_mention_nonce' );
    ?>
			<table class="form-table">
				<tr>
					<th><label for="mention_engine"><?php 
    esc_html_e( 'Motor de IA', 'citameia' );
    ?></label></th>
					<td>
						<select name="mention_engine" id="mention_engine">
							<?php 
    foreach ( $citameia_ai_engines as $key => $eng ) {
        ?>
								<option value="<?php 
        echo esc_attr( $key );
        ?>"><?php 
        echo esc_html( $eng['label'] );
        ?></option>
							<?php 
    }
    ?>
						</select>
					</td>
				</tr>
				<tr>
					<th><label for="mention_query"><?php 
    esc_html_e( 'Pregunta que usaste', 'citameia' );
    ?></label></th>
					<td><input type="text" id="mention_query" name="mention_query" class="large-text"></td>
				</tr>
				<tr>
					<th><?php 
    esc_html_e( '¿Te mencionó?', 'citameia' );
    ?></th>
					<td>
						<label><input type="radio" name="mention_result" id="mention_result_si" value="si" checked> <?php 
    esc_html_e( 'Sí', 'citameia' );
    ?></label>
						&nbsp;&nbsp;
						<label><input type="radio" name="mention_result" id="mention_result_no" value="no"> <?php 
    esc_html_e( 'No', 'citameia' );
    ?></label>
					</td>
				</tr>
				<tr id="mention_linked_row">
					<th><?php 
    esc_html_e( '¿Te citó con un enlace directo a tu sitio?', 'citameia' );
    ?></th>
					<td>
						<label><input type="radio" name="mention_linked" value="si"> <?php 
    esc_html_e( 'Sí, puso un enlace', 'citameia' );
    ?></label>
						&nbsp;&nbsp;
						<label><input type="radio" name="mention_linked" value="no" checked> <?php 
    esc_html_e( 'No, solo te nombró', 'citameia' );
    ?></label>
						<p class="description"><?php 
    esc_html_e( 'Un enlace directo vale más que solo aparecer nombrado: es lo que de verdad puede traerte visitas.', 'citameia' );
    ?></p>
					</td>
				</tr>
				<tr>
					<th><label for="mention_notes"><?php 
    esc_html_e( 'Notas (opcional)', 'citameia' );
    ?></label></th>
					<td><textarea id="mention_notes" name="mention_notes" rows="2" class="large-text" placeholder="<?php 
    esc_attr_e( 'Ej. mencionó a la competencia primero, o citó mi página de inicio directamente.', 'citameia' );
    ?>"></textarea></td>
				</tr>
			</table>
			<?php 
    submit_button( __( 'Registrar prueba', 'citameia' ) );
    ?>
		</form>
		</div>

		<?php 
    ob_start();
    ?>
		document.querySelectorAll('.citameia-copy-query').forEach(function(btn) {
			btn.addEventListener('click', function() {
				var el = document.getElementById(btn.dataset.target);
				navigator.clipboard.writeText(el.value).then(function() {
					var original = btn.textContent;
					btn.textContent = '<?php 
    echo esc_js( __( '¡Copiado!', 'citameia' ) );
    ?>';
					setTimeout(function() { btn.textContent = original; }, 1500);
				});
			});
		});
		document.querySelectorAll('.citameia-use-query').forEach(function(btn) {
			btn.addEventListener('click', function() {
				var el = document.getElementById(btn.dataset.target);
				document.getElementById('mention_query').value = el.value;
				document.getElementById('mention_query').scrollIntoView({ behavior: 'smooth', block: 'center' });
			});
		});

		// La pregunta de "¿te citó con enlace?" solo tiene sentido si sí te mencionó.
		(function() {
			var siRadio = document.getElementById('mention_result_si');
			var noRadio = document.getElementById('mention_result_no');
			var fila    = document.getElementById('mention_linked_row');
			function actualizar() {
				fila.style.display = (noRadio && noRadio.checked) ? 'none' : '';
			}
			if (siRadio) { siRadio.addEventListener('change', actualizar); }
			if (noRadio) { noRadio.addEventListener('change', actualizar); }
			actualizar();
		})();
		<?php 
    $citameia_mentions_js = ob_get_clean();
    wp_register_script(
        'citameia-mentions-page',
        false,
        array(),
        CITAMEIA_VERSION,
        true
    );
    wp_enqueue_script( 'citameia-mentions-page' );
    wp_add_inline_script( 'citameia-mentions-page', $citameia_mentions_js );
    ?>

		<?php 
    if ( !citameia_is_pro() ) {
        ?>

			<?php 
        citameia_render_pro_lock( __( 'Desglose e historial de pruebas', 'citameia' ), array(__( 'Desglose de menciones por motor de IA (ChatGPT, Gemini, Perplexity...)', 'citameia' ), __( 'Desglose por pregunta, para comparar qué redacción funciona mejor', 'citameia' ), __( 'Historial completo de todas las pruebas registradas', 'citameia' )) );
        ?>

		<?php 
    }
    ?>
		<?php 
    // This IF block is stripped entirely from the free version by Freemius.
    ?>
		<?php 
    ?>
	<?php 
}

/**
 * Despachador de "Pruebas en IA": pinta el header y la navegación de
 * pestañas una sola vez, y delega el contenido a la pestaña activa.
 * El nombre de la función se queda igual (citameia_render_mentions_page)
 * porque así está registrada en add_submenu_page().
 */
function citameia_render_mentions_page() {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- solo decide qué pestaña pintar, no procesa ni guarda nada.
    $tab_actual = ( isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'menciones' );
    $tabs_validas = array('menciones', 'citabilidad', 'salud');
    if ( !in_array( $tab_actual, $tabs_validas, true ) ) {
        $tab_actual = 'menciones';
    }
    $tabs = array(
        'menciones'   => __( 'Menciones', 'citameia' ),
        'citabilidad' => __( 'Citabilidad', 'citameia' ),
        'salud'       => __( 'Salud para agentes', 'citameia' ),
    );
    ?>
	<div class="wrap geo-radar-wrap">
		<?php 
    citameia_render_admin_header( 'citameia-menciones' );
    ?>

		<div class="citameia-tabs citameia-tabs-sub">
			<?php 
    foreach ( $tabs as $slug => $label ) {
        ?>
				<a href="<?php 
        echo esc_url( admin_url( 'admin.php?page=citameia-menciones&tab=' . $slug ) );
        ?>"
					class="citameia-tab<?php 
        echo ( $slug === $tab_actual ? ' active' : '' );
        ?>">
					<?php 
        echo esc_html( $label );
        ?>
				</a>
			<?php 
    }
    ?>
		</div>

		<?php 
    switch ( $tab_actual ) {
        case 'citabilidad':
            citameia_render_mentions_tab_citabilidad();
            break;
        case 'salud':
            citameia_render_mentions_tab_salud();
            break;
        default:
            citameia_render_mentions_tab_menciones();
            break;
    }
    ?>
	</div>
	<?php 
}

/* =========================================================
 * PESTAÑA: CITABILIDAD (Capa 3 del roadmap)
 * =========================================================
 *
 * Analiza un texto (pegado directo, o el contenido de una URL) contra
 * 3 señales heurísticas, calculadas todas en PHP puro, sin llamar a
 * ningún servicio externo. La 4ta señal (especificidad, con IA) queda
 * pendiente para una fase posterior — por ahora se muestra bloqueada.
 */
/**
 * Señal 1 — Respuesta directa.
 * Penaliza frases de relleno típicas al inicio del texto, y da un
 * bono si las primeras ~150 palabras ya contienen una definición o
 * un número (señal de que responde algo concreto, no solo preámbulo).
 */
function citameia_citabilidad_score_respuesta_directa(  $texto_plano  ) {
    $inicio = trim( mb_substr( $texto_plano, 0, 400 ) );
    $frases_relleno = array(
        '/en (este|el presente) art[íi]culo/iu',
        '/hoy en d[íi]a/iu',
        '/en un mundo (cada vez )?m[áa]s/iu',
        '/nuestra empresa se dedica a/iu',
        '/vivimos en una era/iu',
        '/es importante (mencionar|destacar|se[ñn]alar)/iu',
        '/en la actualidad/iu',
        '/cabe (destacar|mencionar|se[ñn]alar)/iu',
        '/sin lugar a dudas/iu'
    );
    $ocurrencias = 0;
    foreach ( $frases_relleno as $patron ) {
        if ( preg_match( $patron, $inicio ) ) {
            $ocurrencias++;
        }
    }
    $score = 100 - $ocurrencias * 22;
    $primeras_150 = mb_substr( $texto_plano, 0, 150 );
    if ( preg_match( '/\\b\\d+([.,]\\d+)?\\b/u', $primeras_150 ) ) {
        $score += 10;
        // Trae un número pronto: buena señal de concreción.
    }
    if ( preg_match( '/\\b\\w+\\s+es\\s+(un|una|el|la|lo)\\b/iu', $primeras_150 ) ) {
        $score += 8;
        // Empieza con una definición directa tipo "X es un/una...".
    }
    return (int) max( 0, min( 100, $score ) );
}

/**
 * Señal 2 — Estructura escaneable.
 * Funciona tanto con HTML (detecta <h2>-<h4>, <li>, <p> de verdad)
 * como con texto plano pegado (usa una heurística de líneas cortas
 * sueltas como posibles subtítulos, y párrafos separados por línea
 * en blanco).
 */
function citameia_citabilidad_score_estructura(  $texto_original  ) {
    $es_html = $texto_original !== wp_strip_all_tags( $texto_original );
    $palabras_totales = str_word_count( wp_strip_all_tags( $texto_original ) );
    if ( $palabras_totales < 1 ) {
        $palabras_totales = 1;
    }
    $headers = array();
    $parrafos = array();
    $tiene_listas = false;
    if ( $es_html ) {
        if ( preg_match_all( '/<h[2-4][^>]*>(.*?)<\\/h[2-4]>/is', $texto_original, $m ) ) {
            $headers = $m[1];
        }
        $tiene_listas = (bool) preg_match( '/<li[^>]*>/i', $texto_original );
        if ( preg_match_all( '/<p[^>]*>(.*?)<\\/p>/is', $texto_original, $m ) ) {
            $parrafos = $m[1];
        }
    } else {
        $lineas = preg_split( '/\\r\\n|\\r|\\n/', $texto_original );
        $buffer = '';
        foreach ( $lineas as $linea ) {
            $linea_trim = trim( $linea );
            if ( '' === $linea_trim ) {
                if ( '' !== trim( $buffer ) ) {
                    $parrafos[] = $buffer;
                    $buffer = '';
                }
                continue;
            }
            $palabras_linea = str_word_count( $linea_trim );
            // Línea corta (≤10 palabras), sin puntuación de cierre, sola en su
            // propio párrafo: se trata como posible subtítulo.
            $es_posible_header = $palabras_linea > 0 && $palabras_linea <= 10 && !preg_match( '/[.,;:]$/u', $linea_trim );
            if ( $es_posible_header && '' === trim( $buffer ) ) {
                $headers[] = $linea_trim;
            } else {
                $buffer .= ' ' . $linea_trim;
            }
        }
        if ( '' !== trim( $buffer ) ) {
            $parrafos[] = $buffer;
        }
        $tiene_listas = (bool) preg_match( '/^\\s*[-•*]\\s+/mu', $texto_original ) || (bool) preg_match( '/^\\s*\\d+[\\.\\)]\\s+/mu', $texto_original );
    }
    $num_headers = count( $headers );
    $headers_pregunta = 0;
    foreach ( $headers as $h ) {
        $h_limpio = trim( wp_strip_all_tags( $h ) );
        if ( '' === $h_limpio ) {
            continue;
        }
        $termina_en_pregunta = '?' === mb_substr( $h_limpio, -1 );
        $empieza_pregunta = preg_match( '/^(qu[ée]|c[óo]mo|por qu[ée]|cu[áa]ndo|cu[áa]l|d[óo]nde)\\b/iu', $h_limpio );
        if ( $termina_en_pregunta || $empieza_pregunta ) {
            $headers_pregunta++;
        }
    }
    // Densidad ideal: ~1 subtítulo cada 300 palabras.
    $densidad_ideal = max( 0.5, $palabras_totales / 300 );
    $densidad_score = min( 100, $num_headers / $densidad_ideal * 100 );
    // Longitud de párrafo promedio: ideal 40-80 palabras.
    $long_parrafo_score = 55;
    // neutro si no se detectaron párrafos.
    if ( !empty( $parrafos ) ) {
        $total_palabras_p = 0;
        foreach ( $parrafos as $p ) {
            $total_palabras_p += str_word_count( wp_strip_all_tags( $p ) );
        }
        $promedio = $total_palabras_p / count( $parrafos );
        if ( $promedio >= 40 && $promedio <= 80 ) {
            $long_parrafo_score = 100;
        } elseif ( $promedio < 40 ) {
            $long_parrafo_score = 75;
        } else {
            $exceso = $promedio - 80;
            $long_parrafo_score = max( 20, 100 - $exceso / 2 );
        }
    }
    $lista_bonus = ( $tiene_listas ? 15 : 0 );
    $pregunta_bonus = ( $num_headers > 0 ? $headers_pregunta / $num_headers * 20 : 0 );
    $score = $densidad_score * 0.4 + $long_parrafo_score * 0.4 + $lista_bonus + $pregunta_bonus;
    return array(
        'score'            => (int) max( 0, min( 100, round( $score ) ) ),
        'num_headers'      => $num_headers,
        'headers_pregunta' => $headers_pregunta,
        'tiene_listas'     => $tiene_listas,
    );
}

/**
 * Señal 3 — Longitud adecuada, calibrada según el tipo de contenido
 * que el usuario elija (una FAQ corta no debe castigarse por no tener
 * 1000 palabras).
 */
function citameia_citabilidad_score_longitud(  $texto_plano, $tipo  ) {
    $palabras = str_word_count( $texto_plano );
    $rangos = array(
        'respuesta' => array(
            'min'       => 40,
            'ideal_min' => 100,
            'ideal_max' => 300,
            'max'       => 450,
        ),
        'guia'      => array(
            'min'       => 200,
            'ideal_min' => 500,
            'ideal_max' => 1500,
            'max'       => 2200,
        ),
        'articulo'  => array(
            'min'       => 400,
            'ideal_min' => 1000,
            'ideal_max' => 2500,
            'max'       => 3500,
        ),
    );
    $r = ( isset( $rangos[$tipo] ) ? $rangos[$tipo] : $rangos['guia'] );
    if ( $palabras >= $r['ideal_min'] && $palabras <= $r['ideal_max'] ) {
        $score = 100;
    } elseif ( $palabras < $r['ideal_min'] ) {
        $rango_bajo = max( 1, $r['ideal_min'] - $r['min'] );
        $score = round( ($palabras - $r['min']) / $rango_bajo * 100 );
    } else {
        $rango_alto = max( 1, $r['max'] - $r['ideal_max'] );
        $score = round( 100 - ($palabras - $r['ideal_max']) / $rango_alto * 100 );
    }
    return array(
        'score'    => (int) max( 0, min( 100, $score ) ),
        'palabras' => $palabras,
    );
}

/**
 * Junta las 3 señales heurísticas en un score general (promedio simple)
 * y arma la lista de sugerencias accionables según qué falló.
 */
function citameia_citabilidad_analizar(  $texto_original, $tipo  ) {
    $texto_plano = wp_strip_all_tags( $texto_original );
    $directa = citameia_citabilidad_score_respuesta_directa( $texto_plano );
    $estructura = citameia_citabilidad_score_estructura( $texto_original );
    $longitud = citameia_citabilidad_score_longitud( $texto_plano, $tipo );
    $score_general = (int) round( ($directa + $estructura['score'] + $longitud['score']) / 3 );
    $sugerencias = array();
    if ( $directa < 60 ) {
        $sugerencias[] = array(
            'titulo' => __( 'Responde directo, sin rodeos', 'citameia' ),
            'texto'  => __( 'Tu primer párrafo tiene rodeos antes de responder algo concreto. Un motor de IA que resume tu página tiende a citar las primeras líneas — si empiezan con contexto o introducción en vez de la respuesta, es más fácil que te salte y cite a otra fuente que sí responde directo.', 'citameia' ),
            'pasos'  => array(__( 'Escribe la respuesta directa (una definición, un número, un sí/no) en la primera o segunda línea.', 'citameia' ), __( 'Mueve el contexto, la historia o la justificación a los párrafos siguientes.', 'citameia' ), __( 'Si es una guía paso a paso, adelanta el resultado final antes de explicar cómo se llega a él.', 'citameia' )),
        );
    }
    if ( $estructura['num_headers'] < 2 && str_word_count( $texto_plano ) > 300 ) {
        $sugerencias[] = array(
            'titulo' => __( 'Agrega más subtítulos', 'citameia' ),
            'texto'  => __( 'Con un texto de este largo, un motor de IA escanea mejor el contenido si está dividido en bloques temáticos claros, en vez de un solo bloque continuo de texto.', 'citameia' ),
            'pasos'  => array(__( 'Divide el texto en bloques según de qué trata cada parte.', 'citameia' ), __( 'Ponle un subtítulo (H2 o H3) a cada bloque — como regla general, uno cada 300 palabras aproximadamente.', 'citameia' ), __( 'Que cada subtítulo resuma el bloque en pocas palabras, no una frase genérica como "Más información".', 'citameia' )),
        );
    }
    if ( 0 === $estructura['headers_pregunta'] && $estructura['num_headers'] > 0 ) {
        $sugerencias[] = array(
            'titulo' => __( 'Convierte subtítulos en preguntas', 'citameia' ),
            'texto'  => __( 'Ninguno de tus subtítulos está en forma de pregunta. Un motor de IA que responde a una pregunta del usuario reconoce más fácil un subtítulo que ya está formulado como esa misma pregunta.', 'citameia' ),
            'pasos'  => array(
                /* translators: %1$s: ejemplo de subtítulo genérico, %2$s: el mismo subtítulo convertido a pregunta */
                sprintf( __( 'Por ejemplo, cambia "%1$s" por "%2$s".', 'citameia' ), __( 'Beneficios', 'citameia' ), __( '¿Cuáles son los beneficios?', 'citameia' ) ),
                __( 'No hace falta cambiarlos todos — con uno o dos en formato pregunta ya ayuda.', 'citameia' ),
                __( 'Usa las preguntas que de verdad hacen tus clientes, no una genérica inventada.', 'citameia' ),
            ),
        );
    }
    if ( !$estructura['tiene_listas'] && str_word_count( $texto_plano ) > 200 ) {
        $sugerencias[] = array(
            'titulo' => __( 'Usa listas para pasos o características', 'citameia' ),
            'texto'  => __( 'No se detectaron listas. Si tu texto incluye una secuencia de pasos, una serie de características, o varios ejemplos seguidos, una lista es mucho más fácil de escanear — para una IA y para una persona — que ese mismo contenido escrito como párrafo.', 'citameia' ),
            'pasos'  => array(__( 'Busca en tu texto frases donde enumeras cosas dentro de un párrafo ("primero... luego... después...").', 'citameia' ), __( 'Sepáralas en una lista numerada si el orden importa (pasos), o con viñetas si no importa el orden (características).', 'citameia' ), __( 'Cada punto de la lista debe poder leerse solo, sin depender de la frase anterior.', 'citameia' )),
        );
    }
    if ( $longitud['score'] < 60 && $longitud['palabras'] < 100 ) {
        $sugerencias[] = array(
            'titulo' => __( 'Amplía el contenido', 'citameia' ),
            'texto'  => __( 'El texto es muy corto para el tipo de contenido que elegiste — es posible que no alcance a responder la pregunta completa, y un motor de IA suele preferir una fuente que cubra el tema con más profundidad.', 'citameia' ),
            'pasos'  => array(__( 'Agrega un ejemplo concreto o un caso real que ilustre lo que estás explicando.', 'citameia' ), __( 'Cubre las preguntas de seguimiento obvias que le quedarían a alguien después de leer esto.', 'citameia' ), __( 'Si de verdad no hay más que decir, considera si el "Tipo de contenido" elegido es el correcto — quizás es una respuesta rápida, no una guía.', 'citameia' )),
        );
    } elseif ( $longitud['score'] < 60 ) {
        $sugerencias[] = array(
            'titulo' => __( 'Recorta o divide el contenido', 'citameia' ),
            'texto'  => __( 'El texto es más largo de lo ideal para este tipo de contenido. No es necesariamente un problema — pero si mezcla varios temas en una sola página, un motor de IA puede tener más trabajo para encontrar la parte exacta que responde una pregunta específica.', 'citameia' ),
            'pasos'  => array(__( 'Revisa si el texto responde más de una pregunta distinta — si es así, considera dividirlo en varias páginas enfocadas.', 'citameia' ), __( 'Resume o elimina las partes menos esenciales, sobre todo introducciones largas antes de llegar al punto.', 'citameia' ), __( 'Si es una página tipo FAQ con muchas preguntas juntas, cada pregunta importante podría vivir en su propia página o sección claramente delimitada.', 'citameia' )),
        );
    }
    if ( empty( $sugerencias ) ) {
        $sugerencias[] = array(
            'titulo' => __( '¡Buen trabajo!', 'citameia' ),
            'texto'  => __( 'No se detectaron problemas importantes en estas 3 señales.', 'citameia' ),
            'pasos'  => array(),
        );
    }
    return array(
        'score_general' => $score_general,
        'senales'       => array(
            'respuesta_directa' => array(
                'score' => $directa,
            ),
            'estructura'        => $estructura,
            'longitud'          => $longitud,
        ),
        'sugerencias'   => $sugerencias,
    );
}

/**
 * Extrae el contenido principal legible de una página HTML completa,
 * descartando navegación, scripts, estilos y otros bloques que no son
 * el contenido en sí. Conserva las etiquetas relevantes (h1-h6, listas,
 * párrafos) mediante wp_kses_post() — el mismo filtro que ya se usa
 * cuando el usuario pega HTML a mano — para que las heurísticas de
 * estructura de citameia_citabilidad_analizar() sigan funcionando igual
 * sin importar si el texto vino de un textarea o de una URL.
 */
function citameia_extraer_contenido_de_html(  $html  ) {
    // Bloques que nunca son el contenido principal de una página.
    $html = preg_replace( '#<(script|style|noscript|nav|header|footer|aside|form)\\b[^>]*>.*?</\\1>#is', '', $html );
    $html = preg_replace( '/<!--.*?-->/s', '', $html );
    if ( null === $html ) {
        return '';
    }
    // Prioriza el contenedor más específico disponible.
    if ( preg_match( '#<article\\b[^>]*>(.*?)</article>#is', $html, $coincidencia ) ) {
        $html = $coincidencia[1];
    } elseif ( preg_match( '#<main\\b[^>]*>(.*?)</main>#is', $html, $coincidencia ) ) {
        $html = $coincidencia[1];
    } elseif ( preg_match( '#<body\\b[^>]*>(.*?)</body>#is', $html, $coincidencia ) ) {
        $html = $coincidencia[1];
    }
    return wp_kses_post( $html );
}

function citameia_render_mentions_tab_citabilidad() {
    $resultado = null;
    $texto_enviado = '';
    $tipo_enviado = 'guia';
    $modo_enviado = 'texto';
    $url_enviada = '';
    $error_url = '';
    // phpcs:ignore WordPress.Security.NonceVerification.Missing -- se verifica dos líneas abajo, antes de usar cualquier otro campo de $_POST.
    if ( isset( $_POST['citameia_citabilidad_submit'] ) && isset( $_POST['citameia_citabilidad_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['citameia_citabilidad_nonce'] ) ), 'citameia_citabilidad_analizar' ) ) {
        $modo_enviado = ( isset( $_POST['citameia_citabilidad_modo'] ) ? sanitize_key( wp_unslash( $_POST['citameia_citabilidad_modo'] ) ) : 'texto' );
        $tipo_enviado = ( isset( $_POST['citameia_citabilidad_tipo'] ) ? sanitize_key( wp_unslash( $_POST['citameia_citabilidad_tipo'] ) ) : 'guia' );
        if ( 'url' === $modo_enviado ) {
            $url_enviada = ( isset( $_POST['citameia_citabilidad_url'] ) ? esc_url_raw( wp_unslash( $_POST['citameia_citabilidad_url'] ) ) : '' );
            if ( '' === $url_enviada || !wp_http_validate_url( $url_enviada ) ) {
                $error_url = __( 'Esa URL no parece válida. Revisa que empiece con http:// o https://', 'citameia' );
            } else {
                // wp_safe_remote_get() (no wp_remote_get()) a propósito: bloquea
                // automáticamente IPs internas/privadas, necesario porque la URL
                // la escribe el usuario y no queremos que el servidor la use como
                // puerta para escanear la red interna del hosting.
                $respuesta_http = wp_safe_remote_get( $url_enviada, array(
                    'timeout'     => 12,
                    'redirection' => 3,
                    'user-agent'  => 'CitameIA/' . CITAMEIA_VERSION . ' (+https://citameia.com)',
                ) );
                if ( is_wp_error( $respuesta_http ) ) {
                    /* translators: %s: mensaje de error devuelto por WordPress al intentar obtener la URL */
                    $error_url = sprintf( __( 'No se pudo obtener esa URL: %s', 'citameia' ), $respuesta_http->get_error_message() );
                } elseif ( 200 !== (int) wp_remote_retrieve_response_code( $respuesta_http ) ) {
                    /* translators: %s: código de respuesta HTTP recibido, por ejemplo 404 */
                    $error_url = sprintf( __( 'El sitio respondió con un error (código %s). Revisa que la URL sea correcta y esté accesible públicamente.', 'citameia' ), wp_remote_retrieve_response_code( $respuesta_http ) );
                } else {
                    $html_crudo = wp_remote_retrieve_body( $respuesta_http );
                    if ( '' === trim( $html_crudo ) ) {
                        $error_url = __( 'La página respondió, pero llegó vacía. Si el contenido se carga con JavaScript, mejor copia y pega el texto directamente.', 'citameia' );
                    } else {
                        $texto_enviado = citameia_extraer_contenido_de_html( $html_crudo );
                        if ( '' === trim( wp_strip_all_tags( $texto_enviado ) ) ) {
                            $error_url = __( 'No se encontró contenido de texto legible en esa URL.', 'citameia' );
                        }
                    }
                }
            }
        } else {
            // wp_kses_post() en vez de sanitize_textarea_field(): si el usuario pega
            // HTML (copiado de su editor), lo necesitamos para detectar <h2>/<li>/<p>
            // de verdad en vez de caer siempre al modo heurístico de texto plano.
            $texto_enviado = ( isset( $_POST['citameia_citabilidad_texto'] ) ? wp_kses_post( wp_unslash( $_POST['citameia_citabilidad_texto'] ) ) : '' );
        }
        if ( '' === $error_url && '' !== trim( wp_strip_all_tags( $texto_enviado ) ) ) {
            // Límite de tamaño: no tiene caso analizar textos gigantes pegados/traídos por error.
            $texto_enviado = mb_substr( $texto_enviado, 0, 20000 );
            $resultado = citameia_citabilidad_analizar( $texto_enviado, $tipo_enviado );
        }
    }
    ?>
	<p class="citameia-page-intro"><?php 
    esc_html_e( 'Pega el texto de una página, o dale la URL, y revisa qué tan citable es su estructura — sin necesidad de IA, solo con patrones que sabemos que un motor de IA prefiere.', 'citameia' );
    ?></p>

	<form method="post" class="citameia-citabilidad-form">
		<?php 
    wp_nonce_field( 'citameia_citabilidad_analizar', 'citameia_citabilidad_nonce' );
    ?>
		<input type="hidden" name="citameia_citabilidad_submit" value="1">
		<input type="hidden" name="citameia_citabilidad_modo" id="citameia_citabilidad_modo" value="<?php 
    echo esc_attr( $modo_enviado );
    ?>">

		<div class="citameia-citabilidad-modos" role="tablist">
			<button type="button" class="citameia-modo-btn<?php 
    echo ( 'texto' === $modo_enviado ? ' active' : '' );
    ?>" data-modo="texto"><?php 
    esc_html_e( 'Pegar texto', 'citameia' );
    ?></button>
			<button type="button" class="citameia-modo-btn<?php 
    echo ( 'url' === $modo_enviado ? ' active' : '' );
    ?>" data-modo="url"><?php 
    esc_html_e( 'Analizar URL', 'citameia' );
    ?></button>
		</div>

		<div class="citameia-tipo-cards" role="radiogroup" aria-label="<?php 
    esc_attr_e( 'Tipo de contenido', 'citameia' );
    ?>">
			<p style="margin:0 0 8px;"><strong><?php 
    esc_html_e( 'Tipo de contenido', 'citameia' );
    ?></strong></p>

			<label class="citameia-tipo-card">
				<input type="radio" name="citameia_citabilidad_tipo" value="respuesta" <?php 
    checked( $tipo_enviado, 'respuesta' );
    ?>>
				<span class="citameia-tipo-card-texto">
					<span class="citameia-tipo-card-title"><?php 
    esc_html_e( 'Respuesta rápida / definición', 'citameia' );
    ?></span>
					<span class="citameia-tipo-card-desc"><?php 
    esc_html_e( 'Una definición corta y directa — ideal para preguntas frecuentes o fichas de producto. Rango ideal: 100-300 palabras.', 'citameia' );
    ?></span>
				</span>
			</label>

			<label class="citameia-tipo-card">
				<input type="radio" name="citameia_citabilidad_tipo" value="guia" <?php 
    checked( $tipo_enviado, 'guia' );
    ?>>
				<span class="citameia-tipo-card-texto">
					<span class="citameia-tipo-card-title"><?php 
    esc_html_e( 'Guía / how-to', 'citameia' );
    ?></span>
					<span class="citameia-tipo-card-desc"><?php 
    esc_html_e( 'Instrucciones paso a paso para lograr algo concreto — un how-to o tutorial. Rango ideal: 500-1500 palabras.', 'citameia' );
    ?></span>
				</span>
			</label>

			<label class="citameia-tipo-card">
				<input type="radio" name="citameia_citabilidad_tipo" value="articulo" <?php 
    checked( $tipo_enviado, 'articulo' );
    ?>>
				<span class="citameia-tipo-card-texto">
					<span class="citameia-tipo-card-title"><?php 
    esc_html_e( 'Artículo de fondo', 'citameia' );
    ?></span>
					<span class="citameia-tipo-card-desc"><?php 
    esc_html_e( 'Contenido más completo que explora un tema a fondo, con contexto y varios ángulos. Rango ideal: 1000-2500 palabras.', 'citameia' );
    ?></span>
				</span>
			</label>
		</div>

		<?php 
    $citameia_citabilidad_js = <<<'CITAMEIA_CITABILIDAD_JS'
(function() {
	var modoInput  = document.getElementById('citameia_citabilidad_modo');
	var botones    = document.querySelectorAll('.citameia-modo-btn');
	var bloqueTexto = document.getElementById('citameia_citabilidad_bloque_texto');
	var bloqueUrl   = document.getElementById('citameia_citabilidad_bloque_url');
	if (!modoInput || !bloqueTexto || !bloqueUrl) { return; }

	function activar(modo) {
		modoInput.value = modo;
		botones.forEach(function(btn) {
			btn.classList.toggle('active', btn.getAttribute('data-modo') === modo);
		});
		bloqueTexto.style.display = (modo === 'texto') ? '' : 'none';
		bloqueUrl.style.display   = (modo === 'url') ? '' : 'none';
	}

	botones.forEach(function(btn) {
		btn.addEventListener('click', function() { activar(btn.getAttribute('data-modo')); });
	});

	activar(modoInput.value || 'texto');
})();
CITAMEIA_CITABILIDAD_JS;
    wp_register_script(
        'citameia-citabilidad-modo',
        false,
        array(),
        CITAMEIA_VERSION,
        true
    );
    wp_enqueue_script( 'citameia-citabilidad-modo' );
    wp_add_inline_script( 'citameia-citabilidad-modo', $citameia_citabilidad_js );
    ?>

		<div id="citameia_citabilidad_bloque_texto">
			<p>
				<label for="citameia_citabilidad_texto"><strong><?php 
    esc_html_e( 'Texto a analizar', 'citameia' );
    ?></strong></label><br>
				<textarea name="citameia_citabilidad_texto" id="citameia_citabilidad_texto" rows="10" style="width:100%;max-width:700px;" placeholder="<?php 
    esc_attr_e( 'Pega aquí el texto...', 'citameia' );
    ?>"><?php 
    echo esc_textarea( wp_strip_all_tags( ( 'texto' === $modo_enviado ? $texto_enviado : '' ) ) );
    ?></textarea>
			</p>
		</div>

		<div id="citameia_citabilidad_bloque_url">
			<p>
				<label for="citameia_citabilidad_url"><strong><?php 
    esc_html_e( 'URL a analizar', 'citameia' );
    ?></strong></label><br>
				<input type="url" name="citameia_citabilidad_url" id="citameia_citabilidad_url" style="width:100%;max-width:500px;" placeholder="https://" value="<?php 
    echo esc_attr( $url_enviada );
    ?>">
				<p class="description"><?php 
    esc_html_e( 'Traemos el contenido de la página automáticamente. Solo funciona con páginas públicas y no funciona si el contenido se carga por JavaScript.', 'citameia' );
    ?></p>
			</p>
		</div>

		<p><button type="submit" class="button button-primary"><?php 
    esc_html_e( 'Analizar citabilidad', 'citameia' );
    ?></button></p>
	</form>

	<?php 
    if ( '' !== $error_url ) {
        ?>
		<div class="notice notice-error" style="margin-top:16px;"><p><?php 
        echo esc_html( $error_url );
        ?></p></div>
	<?php 
    }
    ?>

	<?php 
    if ( null !== $resultado ) {
        ?>
		<div class="citameia-step-card" style="margin-top:24px;">
			<div class="citameia-step-head"><h2><?php 
        esc_html_e( 'Resultado', 'citameia' );
        ?></h2></div>

			<p style="font-size:28px;font-weight:600;margin:0 0 4px;">
				<?php 
        echo esc_html( $resultado['score_general'] );
        ?><span style="font-size:14px;font-weight:400;"> / 100</span>
			</p>

			<table class="widefat" style="max-width:600px;margin-top:12px;">
				<tbody>
					<tr>
						<td><?php 
        esc_html_e( 'Respuesta directa', 'citameia' );
        ?></td>
						<td><?php 
        echo esc_html( $resultado['senales']['respuesta_directa']['score'] );
        ?> / 100</td>
					</tr>
					<tr>
						<td><?php 
        esc_html_e( 'Estructura escaneable', 'citameia' );
        ?></td>
						<td><?php 
        echo esc_html( $resultado['senales']['estructura']['score'] );
        ?> / 100</td>
					</tr>
					<tr>
						<td><?php 
        esc_html_e( 'Longitud adecuada', 'citameia' );
        ?></td>
						<td><?php 
        echo esc_html( $resultado['senales']['longitud']['score'] );
        ?> / 100 <span style="color:#787c82;">(<?php 
        echo esc_html( $resultado['senales']['longitud']['palabras'] );
        ?> <?php 
        esc_html_e( 'palabras', 'citameia' );
        ?>)</span></td>
					</tr>
					<tr style="opacity:0.55;">
						<td>
							<?php 
        esc_html_e( 'Especificidad', 'citameia' );
        ?>
							<span style="font-size:11px;background:#f0e6d8;color:#8a6529;padding:1px 8px;border-radius:3px;margin-left:6px;"><?php 
        esc_html_e( 'Pro — próximamente', 'citameia' );
        ?></span>
						</td>
						<td>—</td>
					</tr>
				</tbody>
			</table>

			<h3 style="margin-top:20px;"><?php 
        esc_html_e( 'Sugerencias', 'citameia' );
        ?></h3>
			<div class="citameia-sugerencias-list">
				<?php 
        foreach ( $resultado['sugerencias'] as $s ) {
            ?>
					<?php 
            if ( empty( $s['pasos'] ) ) {
                ?>
						<div class="citameia-sugerencia-card">
							<div class="citameia-sugerencia-titulo"><?php 
                echo esc_html( $s['titulo'] );
                ?></div>
							<div class="citameia-sugerencia-texto"><?php 
                echo esc_html( $s['texto'] );
                ?></div>
						</div>
					<?php 
            } else {
                ?>
						<details class="citameia-sugerencia-card citameia-sugerencia-expandible">
							<summary>
								<span class="citameia-sugerencia-titulo"><?php 
                echo esc_html( $s['titulo'] );
                ?></span>
								<span class="citameia-sugerencia-chev">▾</span>
							</summary>
							<div class="citameia-sugerencia-texto"><?php 
                echo esc_html( $s['texto'] );
                ?></div>
							<p class="citameia-sugerencia-como"><strong><?php 
                esc_html_e( 'Cómo corregirlo:', 'citameia' );
                ?></strong></p>
							<ol>
								<?php 
                foreach ( $s['pasos'] as $paso ) {
                    ?>
									<li><?php 
                    echo esc_html( $paso );
                    ?></li>
								<?php 
                }
                ?>
							</ol>
						</details>
					<?php 
            }
            ?>
				<?php 
        }
        ?>
			</div>
		</div>
	<?php 
    }
    ?>
	<?php 
}

/* =========================================================
 * PESTAÑA: SALUD PARA AGENTES (Capa 3 del roadmap)
 * =========================================================
 *
 * Espeja los criterios reales de la categoría "Navegación con agentes"
 * de Google PageSpeed Insights, revisados aquí mismo, sin salir del
 * WordPress: imágenes sin alt, imágenes sin width/height (causa típica
 * de un CLS alto), y si existe llms.txt. WebMCP queda como próximamente,
 * porque todavía no hay nada que registrar ahí.
 *
 * El escaneo corre solo cuando el usuario lo pide (botón "Analizar mi
 * sitio"), nunca automático en cada carga de página — recorrer todo el
 * contenido publicado en cada visita sería lento e innecesario. El
 * resultado se guarda 12 horas en un transient para no repetir el
 * trabajo si el usuario solo está viendo la pestaña de nuevo.
 */
/**
 * Revisa un solo bloque de HTML (el contenido de un post/página/producto)
 * y cuenta imágenes sin alt y sin dimensiones declaradas.
 */
function citameia_salud_revisar_imagenes(  $html  ) {
    $sin_alt = 0;
    $sin_dimensiones = 0;
    if ( !preg_match_all( '/<img\\b[^>]*>/i', $html, $imgs ) ) {
        return array(
            'sin_alt'         => 0,
            'sin_dimensiones' => 0,
        );
    }
    foreach ( $imgs[0] as $img_tag ) {
        // alt="" (vacío) es válido para imágenes puramente decorativas —
        // solo contamos cuando el atributo no existe en absoluto.
        if ( !preg_match( '/\\balt\\s*=\\s*["\'][^"\']*["\']/i', $img_tag ) ) {
            $sin_alt++;
        }
        $tiene_width = preg_match( '/\\bwidth\\s*=\\s*["\']?\\d+/i', $img_tag );
        $tiene_height = preg_match( '/\\bheight\\s*=\\s*["\']?\\d+/i', $img_tag );
        if ( !$tiene_width || !$tiene_height ) {
            $sin_dimensiones++;
        }
    }
    return array(
        'sin_alt'         => $sin_alt,
        'sin_dimensiones' => $sin_dimensiones,
    );
}

/**
 * Confirma si llms.txt de verdad responde para un visitante, sin
 * asumir que la única forma válida es el archivo físico. Muchos
 * hostings no dejan escribir en la raíz del sitio; en esos casos el
 * rewrite de respaldo (geo_radar_maybe_serve_llms_virtual) sirve el
 * contenido igual, y el chequeo de salud debe reflejar eso — no
 * marcar en rojo algo que en realidad sí funciona para quien lo pide.
 */
function citameia_llms_txt_funciona() {
    if ( file_exists( trailingslashit( ABSPATH ) . 'llms.txt' ) ) {
        return true;
    }
    // Camino lento solo si el archivo físico no existe: confirmamos con
    // una petición real a la URL pública, igual que la vería un bot.
    $respuesta = wp_safe_remote_get( home_url( '/llms.txt' ), array(
        'timeout' => 5,
    ) );
    if ( is_wp_error( $respuesta ) || 200 !== (int) wp_remote_retrieve_response_code( $respuesta ) ) {
        return false;
    }
    return '' !== trim( wp_remote_retrieve_body( $respuesta ) );
}

/**
 * Recorre el contenido publicado (posts, páginas, y productos si hay
 * WooCommerce activo) buscando los mismos problemas que reprueban en
 * la categoría "Navegación con agentes" de Google.
 */
/**
 * Compara las palabras del slug de una publicación contra las de su
 * título. Un slug que quedó de una plantilla o de contenido de
 * demostración (muy común al importar temas de WooCommerce/Elementor)
 * casi nunca comparte ninguna palabra real con el título que se le
 * puso después — por ejemplo "Época de cerezos" viviendo en
 * /70-deal-on-clothing-this-summer/. No es un error técnico, pero sí
 * una mala señal tanto para SEO como para que una IA entienda el
 * contenido, así que vale la pena señalarlo para revisión manual.
 */
function citameia_slug_no_coincide_con_titulo(  $titulo, $slug  ) {
    if ( '' === trim( (string) $titulo ) || '' === trim( (string) $slug ) ) {
        return false;
    }
    // Acrónimos/abreviaciones que son un link válido aunque no compartan
    // ninguna letra con el título — son convención reconocida incluso en
    // sitios en español, no una señal de contenido mal etiquetado.
    $acronimos_validos = array('faq', 'faqs');
    if ( in_array( strtolower( trim( $slug, '/' ) ), $acronimos_validos, true ) ) {
        return false;
    }
    // Quita acentos para comparar limpio ("época" vs "epoca").
    $normalizar = function ( $texto ) {
        $texto = remove_accents( $texto );
        $texto = strtolower( $texto );
        $palabras = preg_split(
            '/[^a-z0-9]+/',
            $texto,
            -1,
            PREG_SPLIT_NO_EMPTY
        );
        // Palabras de relleno que no cuentan como coincidencia real.
        $relleno = array(
            'de',
            'la',
            'el',
            'los',
            'las',
            'y',
            'a',
            'en',
            'un',
            'una',
            'the',
            'a',
            'an',
            'and',
            'of'
        );
        return array_values( array_diff( $palabras, $relleno ) );
    };
    $palabras_titulo = $normalizar( $titulo );
    $palabras_slug = $normalizar( str_replace( '-', ' ', $slug ) );
    if ( empty( $palabras_titulo ) || empty( $palabras_slug ) ) {
        return false;
    }
    $coincidencias = array_intersect( $palabras_titulo, $palabras_slug );
    return empty( $coincidencias );
}

/**
 * Junta los slugs de páginas de utilidad conocidas — del core de
 * WooCommerce y de plugins de terceros comunes (wishlist, comparador)
 * — que no le aportan nada a una IA ni tienen caso revisar como
 * "contenido mal etiquetado", porque las genera el plugin
 * automáticamente y no están pensadas para editarse a mano. Se usa
 * tanto para armar "Páginas principales" en llms.txt como para no
 * marcarlas falsamente en el chequeo de links que no combinan con su
 * título.
 */
function citameia_slugs_paginas_de_utilidad() {
    $slugs = array('sample-page');
    if ( function_exists( 'wc_get_page_id' ) ) {
        foreach ( array(
            'cart',
            'checkout',
            'myaccount',
            'shop'
        ) as $clave_wc ) {
            $id_pagina_wc = wc_get_page_id( $clave_wc );
            if ( $id_pagina_wc > 0 ) {
                $pagina_wc = get_post( $id_pagina_wc );
                if ( $pagina_wc ) {
                    $slugs[] = $pagina_wc->post_name;
                }
            }
        }
    }
    // Wishlist (YITH / TI WooCommerce Wishlist) y Comparador (YITH
    // WooCommerce Compare) guardan el ID de su página en su propia
    // opción, cada uno con su propio nombre.
    foreach ( array('yith_wcwl_wishlist_page_id', 'tinvwl_wishlist_page_id', 'yith_woocompare_compare_page_id') as $opcion_utilidad ) {
        $id_pagina_utilidad = (int) get_option( $opcion_utilidad );
        if ( $id_pagina_utilidad > 0 ) {
            $pagina_utilidad = get_post( $id_pagina_utilidad );
            if ( $pagina_utilidad ) {
                $slugs[] = $pagina_utilidad->post_name;
            }
        }
    }
    // Respaldo por si la opción no existe o cambia de nombre entre
    // versiones del plugin: estos slugs son los que usan por defecto y
    // casi nunca se personalizan.
    $slugs[] = 'yith-compare';
    $slugs[] = 'wishlist';
    return array_unique( $slugs );
}

function citameia_salud_agentes_analizar() {
    $tipos = array('post', 'page');
    if ( class_exists( 'WooCommerce' ) ) {
        $tipos[] = 'product';
    }
    $query = new WP_Query(array(
        'post_type'      => $tipos,
        'post_status'    => 'publish',
        'posts_per_page' => 300,
        'fields'         => 'ids',
        'no_found_rows'  => true,
    ));
    $por_pagina = array();
    $slugs_sospechosos = array();
    $total_sin_alt = 0;
    $total_sin_dim = 0;
    $paginas_revisadas = 0;
    $paginas_de_utilidad = citameia_slugs_paginas_de_utilidad();
    foreach ( $query->posts as $post_id ) {
        $contenido = get_post_field( 'post_content', $post_id );
        if ( empty( $contenido ) ) {
            continue;
        }
        $paginas_revisadas++;
        $rev = citameia_salud_revisar_imagenes( $contenido );
        $total_sin_alt += $rev['sin_alt'];
        $total_sin_dim += $rev['sin_dimensiones'];
        if ( $rev['sin_alt'] > 0 || $rev['sin_dimensiones'] > 0 ) {
            $por_pagina[] = array(
                'id'      => $post_id,
                'titulo'  => get_the_title( $post_id ),
                'editar'  => get_edit_post_link( $post_id, 'raw' ),
                'sin_alt' => $rev['sin_alt'],
                'sin_dim' => $rev['sin_dimensiones'],
            );
        }
        $titulo = get_the_title( $post_id );
        $slug = get_post_field( 'post_name', $post_id );
        if ( !in_array( $slug, $paginas_de_utilidad, true ) && citameia_slug_no_coincide_con_titulo( $titulo, $slug ) ) {
            $slugs_sospechosos[] = array(
                'id'     => $post_id,
                'titulo' => $titulo,
                'slug'   => $slug,
                'editar' => get_edit_post_link( $post_id, 'raw' ),
                'ver'    => get_permalink( $post_id ),
            );
        }
    }
    usort( $por_pagina, function ( $a, $b ) {
        return $b['sin_alt'] + $b['sin_dim'] - ($a['sin_alt'] + $a['sin_dim']);
    } );
    return array(
        'fecha'             => current_time( 'mysql' ),
        'paginas_revisadas' => $paginas_revisadas,
        'total_sin_alt'     => $total_sin_alt,
        'total_sin_dim'     => $total_sin_dim,
        'llms_txt_existe'   => citameia_llms_txt_funciona(),
        'peores_paginas'    => array_slice( $por_pagina, 0, 10 ),
        'slugs_sospechosos' => array_slice( $slugs_sospechosos, 0, 15 ),
    );
}

function citameia_render_mentions_tab_salud() {
    // phpcs:ignore WordPress.Security.NonceVerification.Missing -- se verifica dos líneas abajo, antes de correr el análisis.
    if ( isset( $_POST['citameia_salud_submit'] ) && isset( $_POST['citameia_salud_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['citameia_salud_nonce'] ) ), 'citameia_salud_analizar' ) && current_user_can( 'manage_options' ) ) {
        $resultado = citameia_salud_agentes_analizar();
        set_transient( 'citameia_salud_agentes_resultado', $resultado, 12 * HOUR_IN_SECONDS );
    } else {
        $resultado = get_transient( 'citameia_salud_agentes_resultado' );
    }
    ?>
	<p class="citameia-page-intro"><?php 
    esc_html_e( 'Los mismos criterios que revisa Google en su categoría "Navegación con agentes" de PageSpeed Insights, sin salir de tu WordPress.', 'citameia' );
    ?></p>

	<form method="post">
		<?php 
    wp_nonce_field( 'citameia_salud_analizar', 'citameia_salud_nonce' );
    ?>
		<input type="hidden" name="citameia_salud_submit" value="1">
		<p><button type="submit" class="button button-primary"><?php 
    echo ( $resultado ? esc_html__( 'Volver a analizar mi sitio', 'citameia' ) : esc_html__( 'Analizar mi sitio', 'citameia' ) );
    ?></button></p>
	</form>

	<?php 
    if ( false === $resultado || null === $resultado ) {
        ?>
		<p class="description"><?php 
        esc_html_e( 'Aún no se ha analizado tu sitio. Da clic en el botón de arriba — puede tardar unos segundos según cuánto contenido tengas publicado.', 'citameia' );
        ?></p>
	<?php 
    } else {
        ?>
		<p class="description">
			<?php 
        printf( 
            /* translators: 1: fecha del último análisis, 2: número de páginas revisadas */
            esc_html__( 'Último análisis: %1$s — %2$d páginas/productos revisados.', 'citameia' ),
            esc_html( mysql2date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $resultado['fecha'] ) ),
            (int) $resultado['paginas_revisadas']
         );
        ?>
		</p>

		<div class="geo-radar-kpi-grid" style="max-width:600px;">
			<div class="geo-radar-kpi-card">
				<div class="geo-radar-kpi-num" style="color:<?php 
        echo ( $resultado['total_sin_alt'] > 0 ? '#B3261E' : '#1E7A4C' );
        ?>;"><?php 
        echo esc_html( $resultado['total_sin_alt'] );
        ?></div>
				<div class="geo-radar-kpi-label"><?php 
        esc_html_e( 'Imágenes sin alt', 'citameia' );
        ?></div>
			</div>
			<div class="geo-radar-kpi-card">
				<div class="geo-radar-kpi-num" style="color:<?php 
        echo ( $resultado['total_sin_dim'] > 0 ? '#B3261E' : '#1E7A4C' );
        ?>;"><?php 
        echo esc_html( $resultado['total_sin_dim'] );
        ?></div>
				<div class="geo-radar-kpi-label"><?php 
        esc_html_e( 'Riesgo de CLS', 'citameia' );
        ?></div>
			</div>
			<div class="geo-radar-kpi-card">
				<div class="geo-radar-kpi-num" style="color:<?php 
        echo ( $resultado['llms_txt_existe'] ? '#1E7A4C' : '#B3261E' );
        ?>;"><?php 
        echo ( $resultado['llms_txt_existe'] ? '1/1' : '0/1' );
        ?></div>
				<div class="geo-radar-kpi-label">llms.txt</div>
			</div>
		</div>

		<?php 
        if ( !$resultado['llms_txt_existe'] ) {
            ?>
			<div class="notice notice-warning inline" style="padding:10px 14px;margin-bottom:20px;">
				<p>
					<?php 
            esc_html_e( 'No se encontró llms.txt en tu sitio.', 'citameia' );
            ?>
					<a href="<?php 
            echo esc_url( admin_url( 'admin.php?page=citameia-llms' ) );
            ?>"><?php 
            esc_html_e( 'Generarlo ahora →', 'citameia' );
            ?></a>
				</p>
			</div>
		<?php 
        }
        ?>

		<?php 
        if ( !empty( $resultado['peores_paginas'] ) ) {
            ?>
			<h3><?php 
            esc_html_e( 'Páginas con más problemas', 'citameia' );
            ?></h3>
			<table class="widefat striped" style="max-width:700px;">
				<thead>
					<tr>
						<th><?php 
            esc_html_e( 'Página', 'citameia' );
            ?></th>
						<th><?php 
            esc_html_e( 'Sin alt', 'citameia' );
            ?></th>
						<th><?php 
            esc_html_e( 'Riesgo de CLS', 'citameia' );
            ?></th>
						<th></th>
					</tr>
				</thead>
				<tbody>
					<?php 
            foreach ( $resultado['peores_paginas'] as $p ) {
                ?>
						<tr>
							<td><?php 
                echo esc_html( $p['titulo'] );
                ?></td>
							<td><?php 
                echo esc_html( $p['sin_alt'] );
                ?></td>
							<td><?php 
                echo esc_html( $p['sin_dim'] );
                ?></td>
							<td>
								<?php 
                if ( $p['editar'] ) {
                    ?>
									<a href="<?php 
                    echo esc_url( $p['editar'] );
                    ?>"><?php 
                    esc_html_e( 'Editar →', 'citameia' );
                    ?></a>
								<?php 
                }
                ?>
							</td>
						</tr>
					<?php 
            }
            ?>
				</tbody>
			</table>
		<?php 
        } elseif ( 0 === $resultado['total_sin_alt'] && 0 === $resultado['total_sin_dim'] ) {
            ?>
			<p class="description"><?php 
            esc_html_e( '¡Buen trabajo! No se encontraron imágenes con estos problemas en tu contenido publicado.', 'citameia' );
            ?></p>
		<?php 
        }
        ?>

		<?php 
        if ( !empty( $resultado['slugs_sospechosos'] ) ) {
            ?>
			<h3><?php 
            esc_html_e( 'Links que no combinan con su título', 'citameia' );
            ?></h3>
			<p class="description">
				<?php 
            esc_html_e( 'El link de estas páginas no comparte ninguna palabra con su título — típico de contenido que viene de una plantilla o demo (por ejemplo, de un tema de tienda) y nunca se le actualizó el link al ponerle su título real. No es un error técnico, pero sí una mala señal tanto para SEO como para que una IA entienda de qué trata cada página.', 'citameia' );
            ?>
			</p>
			<table class="widefat striped" style="max-width:800px;">
				<thead>
					<tr>
						<th><?php 
            esc_html_e( 'Título', 'citameia' );
            ?></th>
						<th><?php 
            esc_html_e( 'Link actual', 'citameia' );
            ?></th>
						<th></th>
					</tr>
				</thead>
				<tbody>
					<?php 
            foreach ( $resultado['slugs_sospechosos'] as $s ) {
                ?>
						<tr>
							<td><?php 
                echo esc_html( $s['titulo'] );
                ?></td>
							<td><a href="<?php 
                echo esc_url( $s['ver'] );
                ?>" target="_blank" rel="noopener">/<?php 
                echo esc_html( $s['slug'] );
                ?>/</a></td>
							<td>
								<?php 
                if ( $s['editar'] ) {
                    ?>
									<a href="<?php 
                    echo esc_url( $s['editar'] );
                    ?>"><?php 
                    esc_html_e( 'Editar →', 'citameia' );
                    ?></a>
								<?php 
                }
                ?>
							</td>
						</tr>
					<?php 
            }
            ?>
				</tbody>
			</table>
		<?php 
        }
        ?>

	<?php 
    }
    ?>

	<div class="citameia-step-card" style="margin-top:24px;opacity:0.6;">
		<div class="citameia-step-head">
			<h2>
				WebMCP
				<span style="font-size:11px;background:#f0e6d8;color:#8a6529;padding:1px 8px;border-radius:3px;margin-left:6px;"><?php 
    esc_html_e( 'Próximamente', 'citameia' );
    ?></span>
			</h2>
		</div>
		<p class="description"><?php 
    esc_html_e( 'El protocolo que le permite a un agente de IA ejecutar acciones directamente en tu sitio (como enviar un formulario) todavía es muy nuevo. Cuando la adopción real empiece, esta sección va a ayudarte a exponer esas acciones.', 'citameia' );
    ?></p>
	</div>
	<?php 
}
