
<?php
/**
 * Elementor Posts Widget.
 *
 * @package Zluck_Ajax_Posts_Filter_Elementor
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

// Check if Elementor is loaded
if ( ! class_exists( '\Elementor\Widget_Base' ) ) {
	return;
}

/**
 * Posts Widget class.
 */
class AAPF_Widget_Posts extends \Elementor\Widget_Base {

	/**
	 * Get widget name.
	 *
	 * @return string Widget name.
	 */
	public function get_name() {
		return 'aapf_posts';
	}

	/**
	 * Get widget title.
	 *
	 * @return string Widget title.
	 */
	public function get_title() {
		return esc_html__( 'Zluck Ajax Posts Filter For Elementor', 'zluck-ajax-posts-filter-for-elementor' );
	}

	/**
	 * Get widget icon.
	 *
	 * @return string Widget icon.
	 */
	public function get_icon() {
		return 'eicon-posts-grid';
	}

	/**
	 * Get widget categories.
	 *
	 * @return array Widget categories.
	 */
	public function get_categories() {
		return array( 'general' );
	}

	/**
	 * Get widget keywords.
	 *
	 * @return array Widget keywords.
	 */
	public function get_keywords() {
		return array( 'posts', 'blog', 'query', 'filter', 'taxonomy' );
	}

	/**
	 * Get script dependencies.
	 *
	 * @return array
	 */
	public function get_script_depends() {
		return array( 'aapf-frontend' );
	}

	/**
	 * Get style dependencies.
	 *
	 * @return array
	 */
	public function get_style_depends() {
		return array( 'aapf-frontend' );
	}

	/**
	 * Register widget controls.
	 */
	protected function register_controls() {
		$this->register_query_controls();
		$this->register_layout_controls();
		$this->register_pagination_controls();
		$this->register_filter_controls();
		$this->register_style_controls();
	}

	/**
	 * Register query controls.
	 */
	private function register_query_controls() {
		$this->start_controls_section(
			'section_query',
			array(
				'label' => esc_html__( 'Query', 'zluck-ajax-posts-filter-for-elementor' ),
				'tab'   => \Elementor\Controls_Manager::TAB_CONTENT,
			)
		);

		$this->add_control(
			'post_type',
			array(
				'label'   => esc_html__( 'Post Type', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'    => \Elementor\Controls_Manager::SELECT,
				'options' => aapf_get_post_types(),
				'default' => 'post',
			)
		);

		$this->add_control(
			'posts_per_page',
			array(
				'label'   => esc_html__( 'Posts Per Page', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'    => \Elementor\Controls_Manager::NUMBER,
				'default' => 6,
				'min'     => 1,
				'max'     => 100,
			)
		);

		$this->add_control(
			'orderby',
			array(
				'label'   => esc_html__( 'Order By', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'    => \Elementor\Controls_Manager::SELECT,
				'options' => array(
					'date'       => esc_html__( 'Date', 'zluck-ajax-posts-filter-for-elementor' ),
					'title'      => esc_html__( 'Title', 'zluck-ajax-posts-filter-for-elementor' ),
					'menu_order' => esc_html__( 'Menu Order', 'zluck-ajax-posts-filter-for-elementor' ),
					'random'     => esc_html__( 'Random', 'zluck-ajax-posts-filter-for-elementor' ),
				),
				'default' => 'date',
			)
		);

		$this->add_control(
			'order',
			array(
				'label'   => esc_html__( 'Order', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'    => \Elementor\Controls_Manager::SELECT,
				'options' => array(
					'ASC'  => esc_html__( 'ASC', 'zluck-ajax-posts-filter-for-elementor' ),
					'DESC' => esc_html__( 'DESC', 'zluck-ajax-posts-filter-for-elementor' ),
				),
				'default' => 'DESC',
			)
		);

		$this->add_control(
			'offset',
			array(
				'label'       => esc_html__( 'Offset', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'        => \Elementor\Controls_Manager::NUMBER,
				'default'     => 0,
				'min'         => 0,
				'description' => esc_html__( 'Number of posts to skip.', 'zluck-ajax-posts-filter-for-elementor' ),
			)
		);

		$this->add_control(
			'ignore_sticky_posts',
			array(
				'label'        => esc_html__( 'Ignore Sticky Posts', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'         => \Elementor\Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Yes', 'zluck-ajax-posts-filter-for-elementor' ),
				'label_off'    => esc_html__( 'No', 'zluck-ajax-posts-filter-for-elementor' ),
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->add_control(
			'include_ids',
			array(
				'label'       => esc_html__( 'Include Posts', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'        => \Elementor\Controls_Manager::TEXT,
				'description' => esc_html__( 'Enter post IDs separated by commas.', 'zluck-ajax-posts-filter-for-elementor' ),
			)
		);

		$this->add_control(
			'exclude_ids',
			array(
				'label'       => esc_html__( 'Exclude Posts', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'        => \Elementor\Controls_Manager::TEXT,
				'description' => esc_html__( 'Enter post IDs separated by commas.', 'zluck-ajax-posts-filter-for-elementor' ),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Register layout controls.
	 */
	private function register_layout_controls() {
		$this->start_controls_section(
			'section_layout',
			array(
				'label' => esc_html__( 'Layout', 'zluck-ajax-posts-filter-for-elementor' ),
				'tab'   => \Elementor\Controls_Manager::TAB_CONTENT,
			)
		);

		$this->add_control(
			'layout',
			array(
				'label'   => esc_html__( 'Layout', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'    => \Elementor\Controls_Manager::SELECT,
				'options' => array(
					'grid'     => esc_html__( 'Grid', 'zluck-ajax-posts-filter-for-elementor' ),
					'masonry'  => esc_html__( 'Masonry', 'zluck-ajax-posts-filter-for-elementor' ),
					'list'     => esc_html__( 'List', 'zluck-ajax-posts-filter-for-elementor' ),
					'card'     => esc_html__( 'Card', 'zluck-ajax-posts-filter-for-elementor' ),
				),
				'default' => 'grid',
			)
		);

		$this->add_control(
			'card_show_date_overlay',
			array(
				'label'        => esc_html__( 'Show Card Date', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'         => \Elementor\Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Show', 'zluck-ajax-posts-filter-for-elementor' ),
				'label_off'    => esc_html__( 'Hide', 'zluck-ajax-posts-filter-for-elementor' ),
				'return_value' => 'yes',
				'default'      => 'yes',
				'condition'    => array(
					'layout' => 'card',
				),
			)
		);

		$this->add_control(
			'card_show_category_overlay',
			array(
				'label'        => esc_html__( 'Show Card Category', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'         => \Elementor\Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Show', 'zluck-ajax-posts-filter-for-elementor' ),
				'label_off'    => esc_html__( 'Hide', 'zluck-ajax-posts-filter-for-elementor' ),
				'return_value' => 'yes',
				'default'      => 'yes',
				'condition'    => array(
					'layout' => 'card',
				),
			)
		);

		$this->add_responsive_control(
			'columns',
			array(
				'label'          => esc_html__( 'Columns', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'           => \Elementor\Controls_Manager::SELECT,
				'default'        => '3',
				'tablet_default' => '2',
				'mobile_default' => '1',
				'options'        => array(
					'1' => '1',
					'2' => '2',
					'3' => '3',
					'4' => '4',
					'5' => '5',
					'6' => '6',
				),
				'condition'      => array(
					'layout' => array( 'grid', 'masonry', 'card' ),
				),
			)
		);

		$this->add_control(
			'column_gap',
			array(
				'label'      => esc_html__( 'Column Gap', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::SLIDER,
				'size_units' => array( 'px' ),
				'range'      => array(
					'px' => array(
						'min'  => 0,
						'max'  => 100,
						'step' => 1,
					),
				),
				'default'    => array(
					'unit' => 'px',
					'size' => 20,
				),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-posts-grid' => 'gap: {{SIZE}}{{UNIT}};',
					'{{WRAPPER}} .aapf-posts-masonry' => 'column-gap: {{SIZE}}{{UNIT}};',
				),
				'condition'  => array(
					'layout' => array( 'grid', 'masonry', 'card' ),
				),
			)
		);

		$this->add_control(
			'row_gap',
			array(
				'label'      => esc_html__( 'Row Gap', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::SLIDER,
				'size_units' => array( 'px' ),
				'range'      => array(
					'px' => array(
						'min'  => 0,
						'max'  => 100,
						'step' => 1,
					),
				),
				'default'    => array(
					'unit' => 'px',
					'size' => 20,
				),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-posts-grid' => 'row-gap: {{SIZE}}{{UNIT}};',
					'{{WRAPPER}} .aapf-posts-masonry' => 'row-gap: {{SIZE}}{{UNIT}};',
				),
				'condition'  => array(
					'layout' => array( 'grid', 'masonry', 'card' ),
				),
			)
		);

		$this->add_control(
			'equal_height',
			array(
				'label'        => esc_html__( 'Equal Height', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'         => \Elementor\Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Yes', 'zluck-ajax-posts-filter-for-elementor' ),
				'label_off'    => esc_html__( 'No', 'zluck-ajax-posts-filter-for-elementor' ),
				'return_value' => 'yes',
				'default'      => 'no',
				'condition'    => array(
					'layout' => 'grid',
				),
			)
		);

		// Post Elements
		$this->add_control(
			'show_image',
			array(
				'label'        => esc_html__( 'Show Featured Image', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'         => \Elementor\Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Yes', 'zluck-ajax-posts-filter-for-elementor' ),
				'label_off'    => esc_html__( 'No', 'zluck-ajax-posts-filter-for-elementor' ),
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->add_control(
			'image_size',
			array(
				'label'     => esc_html__( 'Image Size', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::SELECT,
				'options'   => $this->get_image_sizes(),
				'default'   => 'medium',
				'condition' => array(
					'show_image' => 'yes',
				),
			)
		);

		$this->add_control(
			'show_title',
			array(
				'label'        => esc_html__( 'Show Title', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'         => \Elementor\Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Yes', 'zluck-ajax-posts-filter-for-elementor' ),
				'label_off'    => esc_html__( 'No', 'zluck-ajax-posts-filter-for-elementor' ),
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->add_control(
			'title_tag',
			array(
				'label'     => esc_html__( 'Title HTML Tag', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::SELECT,
				'options'   => array(
					'h1' => 'H1',
					'h2' => 'H2',
					'h3' => 'H3',
					'h4' => 'H4',
					'h5' => 'H5',
					'h6' => 'H6',
					'div' => 'DIV',
				),
				'default'   => 'h3',
				'condition' => array(
					'show_title' => 'yes',
				),
			)
		);

		$this->add_control(
			'show_excerpt',
			array(
				'label'        => esc_html__( 'Show Excerpt', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'         => \Elementor\Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Yes', 'zluck-ajax-posts-filter-for-elementor' ),
				'label_off'    => esc_html__( 'No', 'zluck-ajax-posts-filter-for-elementor' ),
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->add_control(
			'excerpt_length',
			array(
				'label'     => esc_html__( 'Excerpt Length', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::NUMBER,
				'default'   => 20,
				'min'       => 0,
				'max'       => 200,
				'condition' => array(
					'show_excerpt' => 'yes',
				),
			)
		);

		$this->add_control(
			'show_meta',
			array(
				'label'        => esc_html__( 'Show Meta', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'         => \Elementor\Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Yes', 'zluck-ajax-posts-filter-for-elementor' ),
				'label_off'    => esc_html__( 'No', 'zluck-ajax-posts-filter-for-elementor' ),
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->add_control(
			'meta_items',
			array(
				'label'       => esc_html__( 'Meta Items', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'        => \Elementor\Controls_Manager::SELECT2,
				'multiple'    => true,
				'options'     => array(
					'author'    => esc_html__( 'Author', 'zluck-ajax-posts-filter-for-elementor' ),
					'date'      => esc_html__( 'Date', 'zluck-ajax-posts-filter-for-elementor' ),
					'category'  => esc_html__( 'Categories', 'zluck-ajax-posts-filter-for-elementor' ),
					'comments'  => esc_html__( 'Comments', 'zluck-ajax-posts-filter-for-elementor' ),
				),
				'default'     => array( 'author', 'date' ),
				'condition'   => array(
					'show_meta' => 'yes',
				),
			)
		);

		$this->add_control(
			'meta_separator',
			array(
				'label'       => esc_html__( 'Meta Separator', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'        => \Elementor\Controls_Manager::TEXT,
				'default'     => '•',
				'placeholder' => esc_html__( 'e.g., |, •, /', 'zluck-ajax-posts-filter-for-elementor' ),
				'description' => esc_html__( 'Separator to show between meta items. Leave empty for no separator.', 'zluck-ajax-posts-filter-for-elementor' ),
				'condition'   => array(
					'show_meta' => 'yes',
				),
			)
		);

		$this->add_control(
			'show_read_more',
			array(
				'label'        => esc_html__( 'Show Read More', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'         => \Elementor\Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Yes', 'zluck-ajax-posts-filter-for-elementor' ),
				'label_off'    => esc_html__( 'No', 'zluck-ajax-posts-filter-for-elementor' ),
				'return_value' => 'yes',
				'default'      => 'yes',
			)
		);

		$this->add_control(
			'read_more_text',
			array(
				'label'     => esc_html__( 'Read More Text', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::TEXT,
				'default'   => esc_html__( 'Read More', 'zluck-ajax-posts-filter-for-elementor' ),
				'condition' => array(
					'show_read_more' => 'yes',
				),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Register pagination controls.
	 */
	private function register_pagination_controls() {
		$this->start_controls_section(
			'section_pagination',
			array(
				'label' => esc_html__( 'Pagination', 'zluck-ajax-posts-filter-for-elementor' ),
				'tab'   => \Elementor\Controls_Manager::TAB_CONTENT,
			)
		);

		$this->add_control(
			'pagination',
			array(
				'label'   => esc_html__( 'Pagination Type', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'    => \Elementor\Controls_Manager::SELECT,
				'options' => array(
					'none'          => esc_html__( 'None', 'zluck-ajax-posts-filter-for-elementor' ),
					'numbers'       => esc_html__( 'Numbers', 'zluck-ajax-posts-filter-for-elementor' ),
					'load_more'     => esc_html__( 'Load More', 'zluck-ajax-posts-filter-for-elementor' ),
					'infinite'      => esc_html__( 'Infinite Scroll', 'zluck-ajax-posts-filter-for-elementor' ),
				),
				'default' => 'none',
			)
		);

		$this->add_control(
			'load_more_text',
			array(
				'label'     => esc_html__( 'Load More Text', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::TEXT,
				'default'   => esc_html__( 'Load More', 'zluck-ajax-posts-filter-for-elementor' ),
				'condition' => array(
					'pagination' => 'load_more',
				),
			)
		);

		// Previous/Next controls for numbers pagination
		$this->add_control(
			'pagination_prev_next_heading',
			array(
				'label'     => esc_html__( 'Previous/Next Buttons', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::HEADING,
				'separator' => 'before',
				'condition' => array(
					'pagination' => 'numbers',
				),
			)
		);

		$this->add_control(
			'pagination_prev_text',
			array(
				'label'     => esc_html__( 'Previous Text', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::TEXT,
				'default'   => esc_html__( 'Previous', 'zluck-ajax-posts-filter-for-elementor' ),
				'condition' => array(
					'pagination' => 'numbers',
				),
			)
		);

		$this->add_control(
			'pagination_next_text',
			array(
				'label'     => esc_html__( 'Next Text', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::TEXT,
				'default'   => esc_html__( 'Next', 'zluck-ajax-posts-filter-for-elementor' ),
				'condition' => array(
					'pagination' => 'numbers',
				),
			)
		);

		$this->add_control(
			'pagination_show_icons',
			array(
				'label'        => esc_html__( 'Show Icons', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'         => \Elementor\Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Yes', 'zluck-ajax-posts-filter-for-elementor' ),
				'label_off'    => esc_html__( 'No', 'zluck-ajax-posts-filter-for-elementor' ),
				'return_value' => 'yes',
				'default'      => 'yes',
				'condition'    => array(
					'pagination' => 'numbers',
				),
			)
		);

		$this->add_control(
			'pagination_prev_icon',
			array(
				'label'     => esc_html__( 'Previous Icon', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::ICONS,
				'default'   => array(
					'value'   => 'fas fa-chevron-left',
					'library' => 'fa-solid',
				),
				'condition' => array(
					'pagination'        => 'numbers',
					'pagination_show_icons' => 'yes',
				),
			)
		);

		$this->add_control(
			'pagination_next_icon',
			array(
				'label'     => esc_html__( 'Next Icon', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::ICONS,
				'default'   => array(
					'value'   => 'fas fa-chevron-right',
					'library' => 'fa-solid',
				),
				'condition' => array(
					'pagination'        => 'numbers',
					'pagination_show_icons' => 'yes',
				),
			)
		);


		$this->end_controls_section();
	}

	/**
	 * Register filter controls.
	 */
	private function register_filter_controls() {
		$this->start_controls_section(
			'section_filter',
			array(
				'label' => esc_html__( 'Taxonomy Filter', 'zluck-ajax-posts-filter-for-elementor' ),
				'tab'   => \Elementor\Controls_Manager::TAB_CONTENT,
			)
		);

		$this->add_control(
			'enable_taxonomy_filter',
			array(
				'label'        => esc_html__( 'Enable Taxonomy Filter', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'         => \Elementor\Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Yes', 'zluck-ajax-posts-filter-for-elementor' ),
				'label_off'    => esc_html__( 'No', 'zluck-ajax-posts-filter-for-elementor' ),
				'return_value' => 'yes',
				'default'      => 'no',
			)
		);

		$this->add_control(
			'filter_taxonomy',
			array(
				'label'     => esc_html__( 'Taxonomy', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::SELECT,
				'options'   => aapf_get_taxonomies(),
				'default'   => 'category',
				'condition' => array(
					'enable_taxonomy_filter' => 'yes',
				),
			)
		);

		$this->add_control(
			'filter_include_terms',
			array(
				'label'       => esc_html__( 'Include Terms', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'        => \Elementor\Controls_Manager::SELECT2,
				'multiple'    => true,
				'options'     => $this->get_terms_for_taxonomy( 'category' ),
				'description' => esc_html__( 'Leave empty to show all terms.', 'zluck-ajax-posts-filter-for-elementor' ),
				'condition'   => array(
					'enable_taxonomy_filter' => 'yes',
				),
			)
		);

		$this->add_control(
			'filter_exclude_terms',
			array(
				'label'       => esc_html__( 'Exclude Terms', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'        => \Elementor\Controls_Manager::SELECT2,
				'multiple'    => true,
				'options'     => $this->get_terms_for_taxonomy( 'category' ),
				'description' => esc_html__( 'Terms to exclude from filter.', 'zluck-ajax-posts-filter-for-elementor' ),
				'condition'   => array(
					'enable_taxonomy_filter' => 'yes',
				),
			)
		);

		$this->add_control(
			'filter_show_all',
			array(
				'label'        => esc_html__( 'Show "All" Option', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'         => \Elementor\Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Yes', 'zluck-ajax-posts-filter-for-elementor' ),
				'label_off'    => esc_html__( 'No', 'zluck-ajax-posts-filter-for-elementor' ),
				'return_value' => 'yes',
				'default'      => 'yes',
				'condition'    => array(
					'enable_taxonomy_filter' => 'yes',
				),
			)
		);

		$this->add_control(
			'filter_multiselect',
			array(
				'label'        => esc_html__( 'Multi-select', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'         => \Elementor\Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Yes', 'zluck-ajax-posts-filter-for-elementor' ),
				'label_off'    => esc_html__( 'No', 'zluck-ajax-posts-filter-for-elementor' ),
				'return_value' => 'yes',
				'default'      => 'no',
				'condition'    => array(
					'enable_taxonomy_filter' => 'yes',
				),
			)
		);

		$this->add_control(
			'filter_style',
			array(
				'label'     => esc_html__( 'Filter Style', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::SELECT,
				'options'   => array(
					'tabs'      => esc_html__( 'Tabs (Horizontal)', 'zluck-ajax-posts-filter-for-elementor' ),
					'vertical' => esc_html__( 'Tabs (Vertical)', 'zluck-ajax-posts-filter-for-elementor' ),
				),
				'default'   => 'tabs',
				'condition' => array(
					'enable_taxonomy_filter' => 'yes',
				),
			)
		);

		$this->add_control(
			'filter_url_sync',
			array(
				'label'        => esc_html__( 'URL Sync', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'         => \Elementor\Controls_Manager::SWITCHER,
				'label_on'     => esc_html__( 'Yes', 'zluck-ajax-posts-filter-for-elementor' ),
				'label_off'    => esc_html__( 'No', 'zluck-ajax-posts-filter-for-elementor' ),
				'return_value' => 'yes',
				'default'      => 'no',
				'description'  => esc_html__( 'Sync filter state with URL parameters.', 'zluck-ajax-posts-filter-for-elementor' ),
				'condition'    => array(
					'enable_taxonomy_filter' => 'yes',
				),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Register style controls.
	 */
	private function register_style_controls() {
		$this->register_filter_style_controls();
		$this->register_post_card_style_controls();
		$this->register_image_style_controls();
		$this->register_title_style_controls();
		$this->register_excerpt_style_controls();
		$this->register_meta_style_controls();
		$this->register_read_more_style_controls();
		$this->register_card_overlay_style_controls();
		$this->register_pagination_style_controls();
	}

	/**
	 * Register card overlay style controls.
	 */
	private function register_card_overlay_style_controls() {
		// Date overlay.
		$this->start_controls_section(
			'section_card_date_style',
			array(
				'label'     => esc_html__( 'Card Date Overlay', 'zluck-ajax-posts-filter-for-elementor' ),
				'tab'       => \Elementor\Controls_Manager::TAB_STYLE,
				'condition' => array(
					'layout'                => 'card',
					'card_show_date_overlay' => 'yes',
				),
			)
		);

		$this->add_control(
			'card_date_bg_color',
			array(
				'label'     => esc_html__( 'Background Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'global'    => array( 'default' => \Elementor\Core\Kits\Documents\Tabs\Global_Colors::COLOR_ACCENT ),
				'selectors' => array(
					'{{WRAPPER}} .aapf-card-date-overlay' => 'background-color: {{VALUE}};',
				),
			)
		);

		$this->add_control(
			'card_date_text_color',
			array(
				'label'     => esc_html__( 'Text Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'default'   => '#ffffff',
				'selectors' => array(
					'{{WRAPPER}} .aapf-card-date-overlay' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			\Elementor\Group_Control_Typography::get_type(),
			array(
				'name'     => 'card_date_typography',
				'label'    => esc_html__( 'Typography', 'zluck-ajax-posts-filter-for-elementor' ),
				'selector' => '{{WRAPPER}} .aapf-card-date-overlay .aapf-card-date-day-month',
			)
		);

		$this->add_responsive_control(
			'card_date_padding',
			array(
				'label'      => esc_html__( 'Padding', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', 'em', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-card-date-overlay' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'card_date_width',
			array(
				'label'      => esc_html__( 'Width', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::SLIDER,
				'size_units' => array( 'px' ),
				'range'      => array(
					'px' => array(
						'min'  => 40,
						'max'  => 200,
						'step' => 1,
					),
				),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-card-date-overlay' => 'width: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'card_date_height',
			array(
				'label'      => esc_html__( 'Height', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::SLIDER,
				'size_units' => array( 'px' ),
				'range'      => array(
					'px' => array(
						'min'  => 40,
						'max'  => 200,
						'step' => 1,
					),
				),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-card-date-overlay' => 'height: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'card_date_border_radius',
			array(
				'label'      => esc_html__( 'Border Radius', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-card-date-overlay' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'card_date_position_top',
			array(
				'label'      => esc_html__( 'Position Top', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::SLIDER,
				'size_units' => array( 'px', '%' ),
				'range'      => array(
					'px' => array( 'min' => 0, 'max' => 300, 'step' => 1 ),
					'%'  => array( 'min' => 0, 'max' => 100, 'step' => 1 ),
				),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-card-date-overlay' => 'top: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'card_date_position_left',
			array(
				'label'      => esc_html__( 'Position Left', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::SLIDER,
				'size_units' => array( 'px', '%' ),
				'range'      => array(
					'px' => array( 'min' => 0, 'max' => 300, 'step' => 1 ),
					'%'  => array( 'min' => 0, 'max' => 100, 'step' => 1 ),
				),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-card-date-overlay' => 'left: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->end_controls_section();

		// Category overlay.
		$this->start_controls_section(
			'section_card_category_style',
			array(
				'label'     => esc_html__( 'Card Category Overlay', 'zluck-ajax-posts-filter-for-elementor' ),
				'tab'       => \Elementor\Controls_Manager::TAB_STYLE,
				'condition' => array(
					'layout'                     => 'card',
					'card_show_category_overlay' => 'yes',
				),
			)
		);

		$this->add_control(
			'card_category_bg_color',
			array(
				'label'     => esc_html__( 'Background Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'global'    => array( 'default' => \Elementor\Core\Kits\Documents\Tabs\Global_Colors::COLOR_PRIMARY ),
				'selectors' => array(
					'{{WRAPPER}} .aapf-card-category-overlay' => 'background-color: {{VALUE}};',
				),
			)
		);

		$this->add_control(
			'card_category_text_color',
			array(
				'label'     => esc_html__( 'Text Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'default'   => '#ffffff',
				'selectors' => array(
					'{{WRAPPER}} .aapf-card-category-overlay',
					'{{WRAPPER}} .aapf-card-category-overlay a' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			\Elementor\Group_Control_Typography::get_type(),
			array(
				'name'     => 'card_category_typography',
				'label'    => esc_html__( 'Typography', 'zluck-ajax-posts-filter-for-elementor' ),
				'selector' => '{{WRAPPER}} .aapf-card-category-overlay a',
			)
		);

		$this->add_responsive_control(
			'card_category_padding',
			array(
				'label'      => esc_html__( 'Padding', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', 'em', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-card-category-overlay' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'card_category_border_radius',
			array(
				'label'      => esc_html__( 'Border Radius', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-card-category-overlay' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'card_category_position_top',
			array(
				'label'      => esc_html__( 'Position Top', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::SLIDER,
				'size_units' => array( 'px', '%' ),
				'range'      => array(
					'px' => array( 'min' => 0, 'max' => 300, 'step' => 1 ),
					'%'  => array( 'min' => 0, 'max' => 100, 'step' => 1 ),
				),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-card-category-overlay' => 'top: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'card_category_position_left',
			array(
				'label'      => esc_html__( 'Position Left', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::SLIDER,
				'size_units' => array( 'px', '%' ),
				'range'      => array(
					'px' => array( 'min' => 0, 'max' => 300, 'step' => 1 ),
					'%'  => array( 'min' => 0, 'max' => 100, 'step' => 1 ),
				),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-card-category-overlay' => 'left: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Register filter style controls.
	 */
	private function register_filter_style_controls() {
		$this->start_controls_section(
			'section_filter_style',
			array(
				'label'     => esc_html__( 'Filter Tabs', 'zluck-ajax-posts-filter-for-elementor' ),
				'tab'       => \Elementor\Controls_Manager::TAB_STYLE,
				'condition' => array(
					'enable_taxonomy_filter' => 'yes',
				),
			)
		);

		// Horizontal Tabs
		$this->add_control(
			'filter_horizontal_heading',
			array(
				'label'     => esc_html__( 'Horizontal Tabs', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::HEADING,
				'separator' => 'before',
				'condition' => array(
					'filter_style' => 'tabs',
				),
			)
		);

		$this->add_control(
			'filter_item_color',
			array(
				'label'     => esc_html__( 'Text Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'default'   => '#ffffff',
				'selectors' => array(
					'{{WRAPPER}} .aapf-filter-item' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_control(
			'filter_item_bg_color',
			array(
				'label'     => esc_html__( 'Background Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'global'    => array(
					'default' => \Elementor\Core\Kits\Documents\Tabs\Global_Colors::COLOR_SECONDARY,
				),
				'selectors' => array(
					'{{WRAPPER}} .aapf-filter-item' => 'background-color: {{VALUE}};',
				),
			)
		);

		$this->add_control(
			'filter_item_border_color',
			array(
				'label'     => esc_html__( 'Border Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'global'    => array( 'default' => \Elementor\Core\Kits\Documents\Tabs\Global_Colors::COLOR_TEXT ),
				'selectors' => array(
					'{{WRAPPER}} .aapf-filter-item' => 'border-color: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			\Elementor\Group_Control_Typography::get_type(),
			array(
				'name'     => 'filter_item_typography',
				'label'    => esc_html__( 'Typography', 'zluck-ajax-posts-filter-for-elementor' ),
				'selector' => '{{WRAPPER}} .aapf-filter-item',
			)
		);

		$this->add_responsive_control(
			'filter_item_padding',
			array(
				'label'      => esc_html__( 'Padding', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', 'em', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-filter-item' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'filter_item_border_radius',
			array(
				'label'      => esc_html__( 'Border Radius', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-filter-item' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'filter_item_gap',
			array(
				'label'      => esc_html__( 'Gap', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::SLIDER,
				'size_units' => array( 'px' ),
				'range'      => array(
					'px' => array(
						'min'  => 0,
						'max'  => 50,
						'step' => 1,
					),
				),
				'default'    => array(
					'unit' => 'px',
					'size' => 10,
				),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-filter-tabs-horizontal' => 'gap: {{SIZE}}{{UNIT}};',
					'{{WRAPPER}} .aapf-filter-tabs-vertical' => 'gap: {{SIZE}}{{UNIT}};',
				),
			)
		);

		// Active/Hover State
		$this->add_control(
			'filter_item_active_heading',
			array(
				'label'     => esc_html__( 'Active/Hover State', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::HEADING,
				'separator' => 'before',
			)
		);

		$this->add_control(
			'filter_item_active_color',
			array(
				'label'     => esc_html__( 'Text Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'default'   => '#ffffff',
				'selectors' => array(
					'{{WRAPPER}} .aapf-filter-item:hover,
					{{WRAPPER}} .aapf-filter-item.active' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_control(
			'filter_item_active_bg_color',
			array(
				'label'     => esc_html__( 'Background Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'global'    => array( 'default' => \Elementor\Core\Kits\Documents\Tabs\Global_Colors::COLOR_PRIMARY ),
				'selectors' => array(
					'{{WRAPPER}} .aapf-filter-item:hover,
					{{WRAPPER}} .aapf-filter-item.active' => 'background-color: {{VALUE}};',
				),
			)
		);

		$this->add_control(
			'filter_item_active_border_color',
			array(
				'label'     => esc_html__( 'Border Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'global'    => array( 'default' => \Elementor\Core\Kits\Documents\Tabs\Global_Colors::COLOR_PRIMARY ),
				'selectors' => array(
					'{{WRAPPER}} .aapf-filter-item:hover,
					{{WRAPPER}} .aapf-filter-item.active' => 'border-color: {{VALUE}};',
				),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Register post card style controls.
	 */
	private function register_post_card_style_controls() {
		$this->start_controls_section(
			'section_post_card_style',
			array(
				'label' => esc_html__( 'Post Card', 'zluck-ajax-posts-filter-for-elementor' ),
				'tab'   => \Elementor\Controls_Manager::TAB_STYLE,
			)
		);

		$this->add_control(
			'post_card_bg_color',
			array(
				'label'     => esc_html__( 'Background Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'selectors' => array(
					'{{WRAPPER}} .aapf-post-card' => 'background-color: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			\Elementor\Group_Control_Border::get_type(),
			array(
				'name'     => 'post_card_border',
				'label'    => esc_html__( 'Border', 'zluck-ajax-posts-filter-for-elementor' ),
				'selector' => '{{WRAPPER}} .aapf-post-card',
			)
		);

		$this->add_responsive_control(
			'post_card_border_radius',
			array(
				'label'      => esc_html__( 'Border Radius', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-post-card' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->add_group_control(
			\Elementor\Group_Control_Box_Shadow::get_type(),
			array(
				'name'     => 'post_card_box_shadow',
				'label'    => esc_html__( 'Box Shadow', 'zluck-ajax-posts-filter-for-elementor' ),
				'selector' => '{{WRAPPER}} .aapf-post-card',
			)
		);

		$this->add_responsive_control(
			'post_card_padding',
			array(
				'label'      => esc_html__( 'Padding', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', 'em', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-post-content' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Register image style controls.
	 */
	private function register_image_style_controls() {
		$this->start_controls_section(
			'section_image_style',
			array(
				'label'     => esc_html__( 'Featured Image', 'zluck-ajax-posts-filter-for-elementor' ),
				'tab'       => \Elementor\Controls_Manager::TAB_STYLE,
				'condition' => array(
					'show_image' => 'yes',
				),
			)
		);

		$this->add_responsive_control(
			'image_border_radius',
			array(
				'label'      => esc_html__( 'Border Radius', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-post-thumbnail img' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'image_spacing',
			array(
				'label'      => esc_html__( 'Spacing', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::SLIDER,
				'size_units' => array( 'px' ),
				'range'      => array(
					'px' => array(
						'min'  => 0,
						'max'  => 100,
						'step' => 1,
					),
				),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-post-thumbnail' => 'margin-bottom: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'image_height',
			array(
				'label'      => esc_html__( 'Image Height', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::SLIDER,
				'size_units' => array( 'px', 'vh' ),
				'range'      => array(
					'px' => array(
						'min'  => 100,
						'max'  => 600,
						'step' => 5,
					),
					'vh' => array(
						'min'  => 20,
						'max'  => 80,
						'step' => 1,
					),
				),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-post-thumbnail img' => 'height: {{SIZE}}{{UNIT}}; object-fit: cover;',
				),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Register title style controls.
	 */
	private function register_title_style_controls() {
		$this->start_controls_section(
			'section_title_style',
			array(
				'label'     => esc_html__( 'Title', 'zluck-ajax-posts-filter-for-elementor' ),
				'tab'       => \Elementor\Controls_Manager::TAB_STYLE,
				'condition' => array(
					'show_title' => 'yes',
				),
			)
		);

		$this->add_control(
			'title_color',
			array(
				'label'     => esc_html__( 'Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'selectors' => array(
					'{{WRAPPER}} .aapf-post-title a' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			\Elementor\Group_Control_Typography::get_type(),
			array(
				'name'     => 'title_typography',
				'label'    => esc_html__( 'Typography', 'zluck-ajax-posts-filter-for-elementor' ),
				'selector' => '{{WRAPPER}} .aapf-post-title',
			)
		);

		$this->add_responsive_control(
			'title_spacing',
			array(
				'label'      => esc_html__( 'Spacing', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::SLIDER,
				'size_units' => array( 'px' ),
				'range'      => array(
					'px' => array(
						'min'  => 0,
						'max'  => 100,
						'step' => 1,
					),
				),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-post-title' => 'margin-bottom: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->add_control(
			'title_hover_color',
			array(
				'label'     => esc_html__( 'Hover Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'selectors' => array(
					'{{WRAPPER}} .aapf-post-title a:hover' => 'color: {{VALUE}};',
				),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Register excerpt style controls.
	 */
	private function register_excerpt_style_controls() {
		$this->start_controls_section(
			'section_excerpt_style',
			array(
				'label'     => esc_html__( 'Excerpt', 'zluck-ajax-posts-filter-for-elementor' ),
				'tab'       => \Elementor\Controls_Manager::TAB_STYLE,
				'condition' => array(
					'show_excerpt' => 'yes',
				),
			)
		);

		$this->add_control(
			'excerpt_color',
			array(
				'label'     => esc_html__( 'Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'selectors' => array(
					'{{WRAPPER}} .aapf-post-excerpt' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			\Elementor\Group_Control_Typography::get_type(),
			array(
				'name'     => 'excerpt_typography',
				'label'    => esc_html__( 'Typography', 'zluck-ajax-posts-filter-for-elementor' ),
				'selector' => '{{WRAPPER}} .aapf-post-excerpt',
			)
		);

		$this->add_responsive_control(
			'excerpt_spacing',
			array(
				'label'      => esc_html__( 'Spacing', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::SLIDER,
				'size_units' => array( 'px' ),
				'range'      => array(
					'px' => array(
						'min'  => 0,
						'max'  => 100,
						'step' => 1,
					),
				),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-post-excerpt' => 'margin-bottom: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Register meta style controls.
	 */
	private function register_meta_style_controls() {
		$this->start_controls_section(
			'section_meta_style',
			array(
				'label'     => esc_html__( 'Meta', 'zluck-ajax-posts-filter-for-elementor' ),
				'tab'       => \Elementor\Controls_Manager::TAB_STYLE,
				'condition' => array(
					'show_meta' => 'yes',
				),
			)
		);

		$this->add_control(
			'meta_color',
			array(
				'label'     => esc_html__( 'Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'global'    => array(
					'default' => \Elementor\Core\Kits\Documents\Tabs\Global_Colors::COLOR_TEXT,
				),
				'selectors' => array(
					'{{WRAPPER}} .aapf-post-meta' => 'color: {{VALUE}};',
					'{{WRAPPER}} .aapf-post-meta a' => 'color: {{VALUE}};',
					'{{WRAPPER}} .aapf-post-meta .aapf-meta-icon' => 'color: {{VALUE}};',
					'{{WRAPPER}} .aapf-post-meta .aapf-meta-icon i' => 'color: {{VALUE}};',
					'{{WRAPPER}} .aapf-post-meta .aapf-meta-icon svg' => 'fill: {{VALUE}}; color: {{VALUE}};',
					'{{WRAPPER}} .aapf-post-meta .aapf-meta-separator' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			\Elementor\Group_Control_Typography::get_type(),
			array(
				'name'     => 'meta_typography',
				'label'    => esc_html__( 'Typography', 'zluck-ajax-posts-filter-for-elementor' ),
				'global'   => array(
					'default' => \Elementor\Core\Kits\Documents\Tabs\Global_Typography::TYPOGRAPHY_TEXT,
				),
				'selector' => '{{WRAPPER}} .aapf-post-meta, {{WRAPPER}} .aapf-post-meta .aapf-meta-icon, {{WRAPPER}} .aapf-post-meta .aapf-meta-separator',
			)
		);

		$this->add_responsive_control(
			'meta_spacing',
			array(
				'label'      => esc_html__( 'Spacing', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::SLIDER,
				'size_units' => array( 'px' ),
				'range'      => array(
					'px' => array(
						'min'  => 0,
						'max'  => 100,
						'step' => 1,
					),
				),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-post-meta' => 'margin-bottom: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'meta_item_gap',
			array(
				'label'      => esc_html__( 'Item Gap', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::SLIDER,
				'size_units' => array( 'px' ),
				'range'      => array(
					'px' => array(
						'min'  => 0,
						'max'  => 50,
						'step' => 1,
					),
				),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-post-meta' => 'gap: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'meta_separator_spacing',
			array(
				'label'      => esc_html__( 'Separator Spacing', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::SLIDER,
				'size_units' => array( 'px' ),
				'range'      => array(
					'px' => array(
						'min'  => 0,
						'max'  => 30,
						'step' => 1,
					),
				),
				'default'    => array(
					'unit' => 'px',
					'size' => 10,
				),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-post-meta .aapf-meta-separator' => 'margin-left: {{SIZE}}{{UNIT}}; margin-right: {{SIZE}}{{UNIT}};',
				),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Register read more style controls.
	 */
	private function register_read_more_style_controls() {
		$this->start_controls_section(
			'section_read_more_style',
			array(
				'label'     => esc_html__( 'Read More', 'zluck-ajax-posts-filter-for-elementor' ),
				'tab'       => \Elementor\Controls_Manager::TAB_STYLE,
				'condition' => array(
					'show_read_more' => 'yes',
				),
			)
		);

		$this->add_control(
			'read_more_color',
			array(
				'label'     => esc_html__( 'Text Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'default'   => '#ffffff',
				'selectors' => array(
					'{{WRAPPER}} .aapf-read-more-link' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_control(
			'read_more_bg_color',
			array(
				'label'     => esc_html__( 'Background Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'global'    => array(
					'default' => \Elementor\Core\Kits\Documents\Tabs\Global_Colors::COLOR_ACCENT,
				),
				'selectors' => array(
					'{{WRAPPER}} .aapf-read-more-link' => 'background-color: {{VALUE}};',
				),
			)
		);

		$this->add_group_control(
			\Elementor\Group_Control_Typography::get_type(),
			array(
				'name'     => 'read_more_typography',
				'label'    => esc_html__( 'Typography', 'zluck-ajax-posts-filter-for-elementor' ),
				'selector' => '{{WRAPPER}} .aapf-read-more-link',
			)
		);

		$this->add_responsive_control(
			'read_more_padding',
			array(
				'label'      => esc_html__( 'Padding', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', 'em', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-read-more-link' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->add_responsive_control(
			'read_more_border_radius',
			array(
				'label'      => esc_html__( 'Border Radius', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-read-more-link' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
			)
		);

		$this->add_control(
			'read_more_hover_heading',
			array(
				'label'     => esc_html__( 'Hover State', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::HEADING,
				'separator' => 'before',
			)
		);

		$this->add_control(
			'read_more_hover_color',
			array(
				'label'     => esc_html__( 'Text Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'selectors' => array(
					'{{WRAPPER}} .aapf-read-more-link:hover' => 'color: {{VALUE}};',
				),
			)
		);

		$this->add_control(
			'read_more_hover_bg_color',
			array(
				'label'     => esc_html__( 'Background Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'selectors' => array(
					'{{WRAPPER}} .aapf-read-more-link:hover' => 'background-color: {{VALUE}};',
				),
			)
		);

		$this->end_controls_section();
	}

	/**
	 * Register pagination style controls.
	 */
	private function register_pagination_style_controls() {
		$this->start_controls_section(
			'section_pagination_style',
			array(
				'label'     => esc_html__( 'Pagination', 'zluck-ajax-posts-filter-for-elementor' ),
				'tab'       => \Elementor\Controls_Manager::TAB_STYLE,
				'condition' => array(
					'pagination!' => 'none',
				),
			)
		);

		// Number Pagination Controls
		$this->add_control(
			'pagination_numbers_heading',
			array(
				'label'     => esc_html__( 'Number Pagination', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::HEADING,
				'condition' => array(
					'pagination' => 'numbers',
				),
			)
		);

		// Default State for Numbers
		$this->add_control(
			'pagination_numbers_default_heading',
			array(
				'label'     => esc_html__( 'Default State', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::HEADING,
				'condition' => array(
					'pagination' => 'numbers',
				),
			)
		);

		$this->add_control(
			'pagination_color',
			array(
				'label'     => esc_html__( 'Text Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'default'   => '#ffffff',
				'selectors' => array(
					'{{WRAPPER}} .aapf-pagination .page-numbers' => 'color: {{VALUE}};',
				),
				'condition' => array(
					'pagination' => 'numbers',
				),
			)
		);

		$this->add_control(
			'pagination_bg_color',
			array(
				'label'     => esc_html__( 'Background Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'global'    => array(
					'default' => \Elementor\Core\Kits\Documents\Tabs\Global_Colors::COLOR_SECONDARY,
				),
				'selectors' => array(
					'{{WRAPPER}} .aapf-pagination .page-numbers' => 'background-color: {{VALUE}};',
				),
				'condition' => array(
					'pagination' => 'numbers',
				),
			)
		);

		// Active State for Numbers
		$this->add_control(
			'pagination_numbers_active_heading',
			array(
				'label'     => esc_html__( 'Active State', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::HEADING,
				'separator' => 'before',
				'condition' => array(
					'pagination' => 'numbers',
				),
			)
		);

		$this->add_control(
			'pagination_active_color',
			array(
				'label'     => esc_html__( 'Text Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'default'   => '#ffffff',
				'selectors' => array(
					'{{WRAPPER}} .aapf-pagination .page-numbers:hover,
					{{WRAPPER}} .aapf-pagination .page-numbers.current' => 'color: {{VALUE}};',
				),
				'condition' => array(
					'pagination' => 'numbers',
				),
			)
		);

		$this->add_control(
			'pagination_active_bg_color',
			array(
				'label'     => esc_html__( 'Background Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'global'    => array(
					'default' => \Elementor\Core\Kits\Documents\Tabs\Global_Colors::COLOR_PRIMARY,
				),
				'selectors' => array(
					'{{WRAPPER}} .aapf-pagination .page-numbers:hover,
					{{WRAPPER}} .aapf-pagination .page-numbers.current' => 'background-color: {{VALUE}};',
				),
				'condition' => array(
					'pagination' => 'numbers',
				),
			)
		);

		// Typography and Styling for Numbers
		$this->add_group_control(
			\Elementor\Group_Control_Typography::get_type(),
			array(
				'name'     => 'pagination_typography',
				'label'    => esc_html__( 'Typography', 'zluck-ajax-posts-filter-for-elementor' ),
				'selector' => '{{WRAPPER}} .aapf-pagination .page-numbers',
				'condition' => array(
					'pagination' => 'numbers',
				),
			)
		);

		$this->add_responsive_control(
			'pagination_padding',
			array(
				'label'      => esc_html__( 'Padding', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', 'em', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-pagination .page-numbers' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
				'condition' => array(
					'pagination' => 'numbers',
				),
			)
		);

		$this->add_responsive_control(
			'pagination_border_radius',
			array(
				'label'      => esc_html__( 'Border Radius', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-pagination .page-numbers' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
				'condition' => array(
					'pagination' => 'numbers',
				),
			)
		);

		// Load More Button Controls
		$this->add_control(
			'load_more_heading',
			array(
				'label'     => esc_html__( 'Load More Button', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::HEADING,
				'separator' => 'before',
				'condition' => array(
					'pagination' => 'load_more',
				),
			)
		);

		// Default State for Load More
		$this->add_control(
			'load_more_default_heading',
			array(
				'label'     => esc_html__( 'Default State', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::HEADING,
				'condition' => array(
					'pagination' => 'load_more',
				),
			)
		);

		$this->add_control(
			'load_more_text_color',
			array(
				'label'     => esc_html__( 'Text Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'default'   => '#ffffff',
				'selectors' => array(
					'{{WRAPPER}} .aapf-load-more-btn' => 'color: {{VALUE}};',
				),
				'condition' => array(
					'pagination' => 'load_more',
				),
			)
		);

		$this->add_control(
			'load_more_bg_color',
			array(
				'label'     => esc_html__( 'Background Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'global'    => array(
					'default' => \Elementor\Core\Kits\Documents\Tabs\Global_Colors::COLOR_PRIMARY,
				),
				'selectors' => array(
					'{{WRAPPER}} .aapf-load-more-btn' => 'background-color: {{VALUE}};',
				),
				'condition' => array(
					'pagination' => 'load_more',
				),
			)
		);

		// Hover State for Load More
		$this->add_control(
			'load_more_hover_heading',
			array(
				'label'     => esc_html__( 'Hover State', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::HEADING,
				'separator' => 'before',
				'condition' => array(
					'pagination' => 'load_more',
				),
			)
		);

		$this->add_control(
			'load_more_hover_text_color',
			array(
				'label'     => esc_html__( 'Text Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'default'   => '#ffffff',
				'selectors' => array(
					'{{WRAPPER}} .aapf-load-more-btn:hover' => 'color: {{VALUE}};',
				),
				'condition' => array(
					'pagination' => 'load_more',
				),
			)
		);

		$this->add_control(
			'load_more_hover_bg_color',
			array(
				'label'     => esc_html__( 'Background Color', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'      => \Elementor\Controls_Manager::COLOR,
				'global'    => array(
					'default' => \Elementor\Core\Kits\Documents\Tabs\Global_Colors::COLOR_SECONDARY,
				),
				'selectors' => array(
					'{{WRAPPER}} .aapf-load-more-btn:hover' => 'background-color: {{VALUE}};',
				),
				'condition' => array(
					'pagination' => 'load_more',
				),
			)
		);

		// Button Styling for Load More
		$this->add_group_control(
			\Elementor\Group_Control_Typography::get_type(),
			array(
				'name'     => 'load_more_typography',
				'label'    => esc_html__( 'Typography', 'zluck-ajax-posts-filter-for-elementor' ),
				'selector' => '{{WRAPPER}} .aapf-load-more-btn',
				'condition' => array(
					'pagination' => 'load_more',
				),
			)
		);

		$this->add_responsive_control(
			'load_more_padding',
			array(
				'label'      => esc_html__( 'Padding', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', 'em', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-load-more-btn' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
				'condition' => array(
					'pagination' => 'load_more',
				),
			)
		);

		$this->add_responsive_control(
			'load_more_border_radius',
			array(
				'label'      => esc_html__( 'Border Radius', 'zluck-ajax-posts-filter-for-elementor' ),
				'type'       => \Elementor\Controls_Manager::DIMENSIONS,
				'size_units' => array( 'px', '%' ),
				'selectors'  => array(
					'{{WRAPPER}} .aapf-load-more-btn' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
				),
				'condition' => array(
					'pagination' => 'load_more',
				),
			)
		);

		$this->end_controls_section();
	}


	/**
	 * Get image sizes.
	 *
	 * @return array
	 */
	private function get_image_sizes() {
		$sizes = get_intermediate_image_sizes();
		$options = array();

		foreach ( $sizes as $size ) {
			$options[ $size ] = ucfirst( str_replace( array( '-', '_' ), ' ', $size ) );
		}

		$options['full'] = esc_html__( 'Full', 'zluck-ajax-posts-filter-for-elementor' );

		return $options;
	}

	/**
	 * Get terms for a taxonomy.
	 *
	 * @param string $taxonomy Taxonomy name.
	 * @return array
	 */
	private function get_terms_for_taxonomy( $taxonomy ) {
		$terms = get_terms(
			array(
				'taxonomy'   => $taxonomy,
				'hide_empty' => false,
			)
		);

		if ( is_wp_error( $terms ) || empty( $terms ) ) {
			return array();
		}

		$options = array();
		foreach ( $terms as $term ) {
			$options[ $term->term_id ] = $term->name;
		}

		return $options;
	}

	/**
	 * Render widget output on the frontend.
	 */
	protected function render() {
		$settings = $this->get_settings_for_display();

		/**
		 * Action before widget render.
		 *
		 * @param array $settings Widget settings.
		 */
		do_action( 'aapf_before_render', $settings );

		// Check if vertical filter style is used
		$is_vertical = ! empty( $settings['enable_taxonomy_filter'] ) && 'yes' === $settings['enable_taxonomy_filter'] 
			&& isset( $settings['filter_style'] ) && 'vertical' === $settings['filter_style'];

		// Add wrapper for vertical layout
		if ( $is_vertical ) {
			echo '<div class="aapf-vertical-layout-wrapper">';
		}

		// Build query args
		$query_args = aapf_build_query_args( $settings );

		// Render filter if enabled and get first term ID if "All" is disabled
		$first_term_id = '';
		if ( ! empty( $settings['enable_taxonomy_filter'] ) && 'yes' === $settings['enable_taxonomy_filter'] ) {
			$first_term_id = $this->render_filter( $settings );
			
			// If "All" is disabled and we have a first term, filter by it
			$show_all = ! empty( $settings['filter_show_all'] ) && 'yes' === $settings['filter_show_all'];
			if ( ! $show_all && ! empty( $first_term_id ) && ! empty( $settings['filter_taxonomy'] ) ) {
				$taxonomy = sanitize_key( $settings['filter_taxonomy'] );
				if ( taxonomy_exists( $taxonomy ) ) {
					// Validate term exists
					$valid_term = get_term( absint( $first_term_id ), $taxonomy );
					if ( ! is_wp_error( $valid_term ) && ! empty( $valid_term ) ) {
						// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Required for default taxonomy filtering
						$query_args['tax_query'] = array(
							array(
								'taxonomy' => $taxonomy,
								'field'    => 'term_id',
								'terms'    => array( absint( $first_term_id ) ),
								'operator' => 'IN',
							),
						);
					}
				}
			}
		}

		// Get current page for pagination
		$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
		$query_args['paged'] = $paged;

		// Execute query
		$query = new WP_Query( $query_args );

		// For vertical layout, wrap posts and pagination together
		if ( $is_vertical ) {
			echo '<div class="aapf-posts-content-wrapper">';
		}

		// Render posts
		$this->render_posts( $query, $settings );

		// Render pagination
		if ( ! empty( $settings['pagination'] ) && 'none' !== $settings['pagination'] ) {
			$this->render_pagination( $query, $settings );
		}

		// Close posts content wrapper for vertical layout
		if ( $is_vertical ) {
			echo '</div>';
		}

		// Close vertical layout wrapper
		if ( $is_vertical ) {
			echo '</div>';
		}

		/**
		 * Action after widget render.
		 *
		 * @param array $settings Widget settings.
		 */
		do_action( 'aapf_after_render', $settings );

		// Reset post data
		wp_reset_postdata();
	}

	/**
	 * Render taxonomy filter.
	 *
	 * @param array $settings Widget settings.
	 */
	private function render_filter( $settings ) {
		$taxonomy = isset( $settings['filter_taxonomy'] ) ? $settings['filter_taxonomy'] : 'category';

		// Get terms
		$args = array(
			'taxonomy'   => $taxonomy,
			'hide_empty' => true, // Hide empty terms/categories
		);

		// Include/exclude terms
		if ( ! empty( $settings['filter_include_terms'] ) ) {
			$args['include'] = is_array( $settings['filter_include_terms'] )
				? array_map( 'absint', $settings['filter_include_terms'] )
				: array( absint( $settings['filter_include_terms'] ) );
		}

		if ( ! empty( $settings['filter_exclude_terms'] ) ) {
			// phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude -- Required for excluding specific terms from filter
			$args['exclude'] = is_array( $settings['filter_exclude_terms'] )
				? array_map( 'absint', $settings['filter_exclude_terms'] )
				: array( absint( $settings['filter_exclude_terms'] ) );
		}

		$terms = get_terms( $args );

		if ( is_wp_error( $terms ) || empty( $terms ) ) {
			return;
		}

		// Additional filter: Remove any terms with 0 count (double-check for empty terms)
		// This ensures empty terms are hidden even if hide_empty doesn't catch them in edge cases
		$terms = array_filter(
			$terms,
			function( $term ) {
				return isset( $term->count ) && $term->count > 0;
			}
		);

		// Re-index array after filtering
		$terms = array_values( $terms );

		if ( empty( $terms ) ) {
			return;
		}

		$style = isset( $settings['filter_style'] ) ? $settings['filter_style'] : 'tabs';
		$multiselect = ! empty( $settings['filter_multiselect'] ) && 'yes' === $settings['filter_multiselect'];
		$show_all = ! empty( $settings['filter_show_all'] ) && 'yes' === $settings['filter_show_all'];

		// Get first term ID when "All" is disabled
		$first_term_id = '';
		if ( ! $show_all && ! empty( $terms ) ) {
			$first_term = reset( $terms );
			$first_term_id = $first_term->term_id;
		}

		$widget_id = $this->get_id();
		$filter_class = 'aapf-filter aapf-filter-' . esc_attr( $style );
		if ( 'vertical' === $style ) {
			$filter_class .= ' aapf-filter-vertical';
		}
		if ( $multiselect ) {
			$filter_class .= ' aapf-filter-multiselect';
		}

		?>
		<div class="<?php echo esc_attr( $filter_class ); ?>" data-widget-id="<?php echo esc_attr( $widget_id ); ?>" data-taxonomy="<?php echo esc_attr( $taxonomy ); ?>">
			<?php if ( 'tabs' === $style ) : ?>
				<ul class="aapf-filter-tabs aapf-filter-tabs-horizontal">
					<?php if ( $show_all ) : ?>
						<li><a href="javascript:void(0)" class="aapf-filter-item active" data-term-id="" role="button" tabindex="0"><?php echo esc_html__( 'All', 'zluck-ajax-posts-filter-for-elementor' ); ?></a></li>
					<?php endif; ?>
					<?php foreach ( $terms as $index => $term ) : ?>
						<?php
						$is_active = ! $show_all && 0 === $index;
						$active_class = $is_active ? ' active' : '';
						?>
						<li><a href="javascript:void(0)" class="aapf-filter-item<?php echo esc_attr( $active_class ); ?>" data-term-id="<?php echo esc_attr( $term->term_id ); ?>" role="button" tabindex="0"><?php echo esc_html( $term->name ); ?></a></li>
					<?php endforeach; ?>
				</ul>
			<?php elseif ( 'vertical' === $style ) : ?>
				<ul class="aapf-filter-tabs aapf-filter-tabs-vertical">
					<?php if ( $show_all ) : ?>
						<li><a href="javascript:void(0)" class="aapf-filter-item active" data-term-id="" role="button" tabindex="0"><?php echo esc_html__( 'All', 'zluck-ajax-posts-filter-for-elementor' ); ?></a></li>
					<?php endif; ?>
					<?php foreach ( $terms as $index => $term ) : ?>
						<?php
						$is_active = ! $show_all && 0 === $index;
						$active_class = $is_active ? ' active' : '';
						?>
						<li><a href="javascript:void(0)" class="aapf-filter-item<?php echo esc_attr( $active_class ); ?>" data-term-id="<?php echo esc_attr( $term->term_id ); ?>" role="button" tabindex="0"><?php echo esc_html( $term->name ); ?></a></li>
					<?php endforeach; ?>
				</ul>
			<?php endif; ?>
		</div>
		<?php
		
		// Return first term ID for query modification
		return $first_term_id;
	}

	/**
	 * Render posts.
	 *
	 * @param WP_Query $query Query object.
	 * @param array    $settings Widget settings.
	 */
	private function render_posts( $query, $settings ) {
		if ( ! $query->have_posts() ) {
			include AAPF_PLUGIN_DIR . 'templates/no-posts.php';
			return;
		}

		$layout = isset( $settings['layout'] ) ? $settings['layout'] : 'grid';
		$columns = isset( $settings['columns'] ) ? $settings['columns'] : 3;
		$equal_height = ! empty( $settings['equal_height'] ) && 'yes' === $settings['equal_height'];

		$wrapper_class = 'aapf-posts-wrapper aapf-posts-' . esc_attr( $layout );
		
		// Add grid class for grid and card layouts to support columns
		if ( 'grid' === $layout || 'card' === $layout ) {
			$wrapper_class .= ' aapf-posts-grid';
		}
		
		if ( $equal_height ) {
			$wrapper_class .= ' aapf-posts-equal-height';
		}

		$widget_id = $this->get_id();

		// Get responsive columns
		$columns_desktop = isset( $settings['columns'] ) ? absint( $settings['columns'] ) : 3;
		$columns_tablet = isset( $settings['columns_tablet'] ) ? absint( $settings['columns_tablet'] ) : 2;
		$columns_mobile = isset( $settings['columns_mobile'] ) ? absint( $settings['columns_mobile'] ) : 1;

		// Sanitize settings for JSON - remove Elementor internal data
		$clean_settings = array();
		foreach ( $settings as $key => $value ) {
			// Skip Elementor internal keys
			if ( strpos( $key, '__' ) === 0 ) {
				continue;
			}
			$clean_settings[ $key ] = $value;
		}
		$json_settings = wp_json_encode( $clean_settings );
		$json_settings = esc_attr( $json_settings );

		?>
		<div class="<?php echo esc_attr( $wrapper_class ); ?>" 
			data-widget-id="<?php echo esc_attr( $widget_id ); ?>" 
			data-settings="<?php echo esc_attr( $json_settings ); ?>"
			style="--aapf-columns: <?php echo esc_attr( $columns_desktop ); ?>; --aapf-columns-tablet: <?php echo esc_attr( $columns_tablet ); ?>; --aapf-columns-mobile: <?php echo esc_attr( $columns_mobile ); ?>;">
			<?php
			while ( $query->have_posts() ) {
				$query->the_post();
				if ( 'card' === $layout ) {
					$this->render_card_layout( get_post(), $settings );
				} else {
					aapf_render_post_card( get_post(), $settings );
				}
			}
			?>
		</div>
		<?php
	}

	/**
	 * Render pagination.
	 *
	 * @param WP_Query $query Query object.
	 * @param array    $settings Widget settings.
	 */
	private function render_pagination( $query, $settings ) {
		$pagination_type = isset( $settings['pagination'] ) ? $settings['pagination'] : 'none';

		if ( 'numbers' === $pagination_type ) {
			$paged = max( 1, $query->get( 'paged' ) ? $query->get( 'paged' ) : 1 );
			$widget_id = $this->get_id();

			// Get prev/next text and icon settings
			$prev_text = isset( $settings['pagination_prev_text'] ) ? $settings['pagination_prev_text'] : esc_html__( 'Previous', 'zluck-ajax-posts-filter-for-elementor' );
			$next_text = isset( $settings['pagination_next_text'] ) ? $settings['pagination_next_text'] : esc_html__( 'Next', 'zluck-ajax-posts-filter-for-elementor' );
			$show_icons = ! empty( $settings['pagination_show_icons'] ) && 'yes' === $settings['pagination_show_icons'];

			// Build prev text with icon - if icons enabled, hide text
			$prev_text_final = '';
			if ( $show_icons && ! empty( $settings['pagination_prev_icon']['value'] ) ) {
				$prev_icon = $this->render_icon( $settings['pagination_prev_icon'] );
				$prev_text_final = '<span class="aapf-pagination-icon-wrapper">' . $prev_icon . '</span>';
			} else {
				$prev_text_final = $prev_text;
			}

			// Build next text with icon - if icons enabled, hide text
			$next_text_final = '';
			if ( $show_icons && ! empty( $settings['pagination_next_icon']['value'] ) ) {
				$next_icon = $this->render_icon( $settings['pagination_next_icon'] );
				$next_text_final = '<span class="aapf-pagination-icon-wrapper">' . $next_icon . '</span>';
			} else {
				$next_text_final = $next_text;
			}

			echo '<div class="aapf-pagination aapf-pagination-numbers" data-widget-id="' . esc_attr( $widget_id ) . '">';
			$pagination_links = paginate_links(
				array(
					'total'     => $query->max_num_pages,
					'current'   => $paged,
					'prev_text' => $prev_text_final,
					'next_text' => $next_text_final,
					'type'      => 'plain',
				)
			);

			// Add data attributes to pagination links for AJAX
			if ( $pagination_links ) {
				// Add classes to prev/next links - match links containing prev/next text (case insensitive, with HTML)
				$pagination_links = preg_replace_callback(
					'/<a([^>]*class=["\'])([^"\']*)(["\'][^>]*>)(.*?)(<\/a>)/is',
					function( $matches ) use ( $prev_text, $next_text, $show_icons ) {
						$full_link = $matches[0];
						$link_content_html = $matches[4];
						$link_content = wp_strip_all_tags( $link_content_html );
						
						// Check if it's a prev or next link
						$is_prev = false;
						$is_next = false;
						
						// Check by text content
						if ( stripos( $link_content, $prev_text ) !== false || stripos( $link_content, 'prev' ) !== false ) {
							$is_prev = true;
						} elseif ( stripos( $link_content, $next_text ) !== false || stripos( $link_content, 'next' ) !== false ) {
							$is_next = true;
						} elseif ( $show_icons && stripos( $link_content_html, 'aapf-pagination-icon-wrapper' ) !== false ) {
							// When icons are enabled, check icon classes
							if ( stripos( $link_content_html, 'chevron-left' ) !== false || 
								 stripos( $link_content_html, 'arrow-left' ) !== false ||
								 stripos( $link_content_html, 'angle-left' ) !== false ||
								 stripos( $link_content_html, 'fa-arrow-left' ) !== false ||
								 stripos( $link_content_html, 'fa-angle-left' ) !== false ||
								 stripos( $link_content_html, 'fa-chevron-left' ) !== false ) {
								$is_prev = true;
							} elseif ( stripos( $link_content_html, 'chevron-right' ) !== false || 
									   stripos( $link_content_html, 'arrow-right' ) !== false ||
									   stripos( $link_content_html, 'angle-right' ) !== false ||
									   stripos( $link_content_html, 'fa-arrow-right' ) !== false ||
									   stripos( $link_content_html, 'fa-angle-right' ) !== false ||
									   stripos( $link_content_html, 'fa-chevron-right' ) !== false ) {
								$is_next = true;
							}
						}
						
						if ( $is_prev ) {
							$full_link = str_replace( 'class="', 'class="prev ', $full_link );
							$full_link = str_replace( "class='", "class='prev ", $full_link );
						} elseif ( $is_next ) {
							$full_link = str_replace( 'class="', 'class="next ', $full_link );
							$full_link = str_replace( "class='", "class='next ", $full_link );
						}
						
						return $full_link;
					},
					$pagination_links
				);
				$pagination_links = str_replace( '<a ', '<a class="aapf-pagination-link page-numbers" ', $pagination_links );
				$pagination_links = preg_replace_callback(
					'/<a[^>]+href=["\']([^"\']*)["\'][^>]*>(.*?)<\/a>/is',
					function( $matches ) use ( $paged, $query, $prev_text, $next_text, $show_icons ) {
						$href = $matches[1];
						$link_content = $matches[2];
						$full_match = $matches[0];
						
						// Extract page number from URL
						$page = null;
						preg_match( '/page\/(\d+)\//', $href, $page_matches );
						if ( ! $page_matches ) {
							preg_match( '/paged=(\d+)/', $href, $page_matches );
						}
						if ( ! $page_matches ) {
							// Check if it's prev/next link
							$link_text_clean = wp_strip_all_tags( $link_content );
							
							// Check for prev/next by checking if link already has prev/next class (from previous processing)
							$is_prev = false;
							$is_next = false;
							
							// First check if link has prev/next class
							if ( preg_match( '/class=["\']([^"\']*)["\']/', $full_match, $class_matches ) ) {
								$classes = $class_matches[1];
								if ( stripos( $classes, ' prev ' ) !== false || stripos( $classes, ' prev"' ) !== false || stripos( $classes, " prev'" ) !== false || preg_match( '/\bprev\b/', $classes ) ) {
									$is_prev = true;
								} elseif ( stripos( $classes, ' next ' ) !== false || stripos( $classes, ' next"' ) !== false || stripos( $classes, " next'" ) !== false || preg_match( '/\bnext\b/', $classes ) ) {
									$is_next = true;
								}
							}
							
							// If not found by class, check by text content
							if ( ! $is_prev && ! $is_next ) {
								if ( stripos( $link_text_clean, 'prev' ) !== false || stripos( $link_content, '«' ) !== false ) {
									$is_prev = true;
								} elseif ( stripos( $link_text_clean, 'next' ) !== false || stripos( $link_content, '»' ) !== false ) {
									$is_next = true;
								} elseif ( $show_icons ) {
									// When icons are enabled, check for icon wrapper and determine direction
									if ( stripos( $link_content, 'aapf-pagination-icon-wrapper' ) !== false ) {
										// Check for prev icon class (usually contains 'left' or 'prev' or 'chevron-left')
										if ( stripos( $link_content, 'chevron-left' ) !== false || 
											 stripos( $link_content, 'arrow-left' ) !== false ||
											 stripos( $link_content, 'angle-left' ) !== false ||
											 stripos( $link_content, 'fa-arrow-left' ) !== false ||
											 stripos( $link_content, 'fa-angle-left' ) !== false ||
											 stripos( $link_content, 'fa-chevron-left' ) !== false ) {
											$is_prev = true;
										} elseif ( stripos( $link_content, 'chevron-right' ) !== false || 
												   stripos( $link_content, 'arrow-right' ) !== false ||
												   stripos( $link_content, 'angle-right' ) !== false ||
												   stripos( $link_content, 'fa-arrow-right' ) !== false ||
												   stripos( $link_content, 'fa-angle-right' ) !== false ||
												   stripos( $link_content, 'fa-chevron-right' ) !== false ) {
											$is_next = true;
										}
									}
								}
							}
							
							if ( $is_prev ) {
								$page = max( 1, $paged - 1 );
							} elseif ( $is_next ) {
								$page = min( $query->max_num_pages, $paged + 1 );
							} else {
								// Try to extract number from link text
								preg_match( '/\d+/', $link_text_clean, $text_matches );
								$page = ! empty( $text_matches[0] ) ? absint( $text_matches[0] ) : 1;
							}
						} else {
							$page = absint( $page_matches[1] );
						}
						
						// Replace href and add data-page - use javascript:void(0) to avoid Elementor editor selector errors
						$new_link = str_replace( 'href="' . esc_url( $href ) . '"', 'href="javascript:void(0)" data-page="' . esc_attr( $page ) . '" role="button" tabindex="0"', $full_match );
						return $new_link;
					},
					$pagination_links
				);
				// Handle current page span
				$pagination_links = str_replace( '<span class="page-numbers current">', '<span class="page-numbers current aapf-pagination-current" data-page="' . esc_attr( $paged ) . '">', $pagination_links );
				// paginate_links() returns escaped HTML, and we only modify it with sanitized values
				echo wp_kses_post( $pagination_links );
			}
			echo '</div>';
		} elseif ( 'load_more' === $pagination_type ) {
			$load_more_text = isset( $settings['load_more_text'] ) ? $settings['load_more_text'] : esc_html__( 'Load More', 'zluck-ajax-posts-filter-for-elementor' );
			$max_pages = $query->max_num_pages;
			$current_page = max( 1, get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1 );

			if ( $current_page < $max_pages ) {
				echo '<div class="aapf-pagination aapf-pagination-load-more">';
				echo '<button class="aapf-load-more-btn" data-page="' . esc_attr( $current_page ) . '" data-max-pages="' . esc_attr( $max_pages ) . '">';
				echo esc_html( $load_more_text );
				echo '</button>';
				echo '</div>';
			}
		} elseif ( 'infinite' === $pagination_type ) {
			$max_pages = $query->max_num_pages;
			$current_page = max( 1, get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1 );

			if ( $current_page < $max_pages ) {
				echo '<div class="aapf-pagination aapf-pagination-infinite" data-page="' . esc_attr( $current_page ) . '" data-max-pages="' . esc_attr( $max_pages ) . '"></div>';
			}
		}
	}

	/**
	 * Render card layout with overlays.
	 *
	 * @param WP_Post $post Post object.
	 * @param array   $settings Widget settings.
	 */
	private function render_card_layout( $post, $settings ) {
		?>
		<article id="post-<?php the_ID(); ?>" <?php post_class( 'aapf-post-card aapf-card-layout' ); ?>>
			<?php if ( ! empty( $settings['show_image'] ) && 'yes' === $settings['show_image'] && has_post_thumbnail() ) : ?>
				<div class="aapf-post-thumbnail aapf-card-thumbnail">
					<a href="<?php echo esc_url( get_permalink() ); ?>" aria-label="<?php echo esc_attr( get_the_title() ); ?>">
						<?php
						$image_size = isset( $settings['image_size'] ) ? $settings['image_size'] : 'medium';
						the_post_thumbnail(
							$image_size,
							array(
								'alt' => get_the_title(),
								'loading' => 'lazy',
							)
						);
						?>
					</a>
					
					<?php
					$show_card_date     = ! empty( $settings['card_show_date_overlay'] ) && 'yes' === $settings['card_show_date_overlay'];
					$show_card_category = ! empty( $settings['card_show_category_overlay'] ) && 'yes' === $settings['card_show_category_overlay'];

					if ( $show_card_date || $show_card_category ) {
						// Date overlay (top right).
						if ( $show_card_date ) {
							?>
							<div class="aapf-card-date-overlay">
								<span class="aapf-card-date-day-month"><?php echo esc_html( get_the_date( 'd M' ) ); ?></span>
								<span class="aapf-card-date-year"><?php echo esc_html( get_the_date( 'Y' ) ); ?></span>
							</div>
							<?php
						}

						
					}
					?>
				</div>
			<?php endif; ?>

			<div class="aapf-post-content aapf-card-content"><?php
				// Category overlay (bottom left).
						if ( $show_card_category ) {
							$categories = get_the_category();
							if ( ! empty( $categories ) ) {
								$first_category = $categories[0];
								?>
								<div class="aapf-card-category-overlay">
									<a href="<?php echo esc_url( get_category_link( $first_category->term_id ) ); ?>">
										<?php echo esc_html( strtoupper( $first_category->name ) ); ?>
									</a>
								</div>
								<?php
							}
						}?>
				<?php if ( ! empty( $settings['show_title'] ) && 'yes' === $settings['show_title'] ) : ?>
					<?php
					$title_tag = isset( $settings['title_tag'] ) ? $settings['title_tag'] : 'h3';
					?>
					<<?php echo esc_attr( $title_tag ); ?> class="aapf-post-title aapf-card-title">
						<a href="<?php echo esc_url( get_permalink() ); ?>"><?php echo esc_html( get_the_title() ); ?></a>
					</<?php echo esc_attr( $title_tag ); ?>>
				<?php endif; ?>

				<?php if ( ! empty( $settings['show_excerpt'] ) && 'yes' === $settings['show_excerpt'] ) : ?>
					<div class="aapf-post-excerpt aapf-card-excerpt">
						<?php
						$excerpt_length = isset( $settings['excerpt_length'] ) ? absint( $settings['excerpt_length'] ) : 20;
						$excerpt = get_the_excerpt();

						if ( $excerpt_length > 0 ) {
							$excerpt = wp_trim_words( $excerpt, $excerpt_length, '...' );
						}

						echo wp_kses_post( $excerpt );
						?>
					</div>
				<?php endif; ?>

				<?php if ( ! empty( $settings['show_read_more'] ) && 'yes' === $settings['show_read_more'] ) : ?>
					<div class="aapf-post-read-more aapf-card-read-more">
						<a href="<?php echo esc_url( get_permalink() ); ?>" class="aapf-read-more-link aapf-card-read-more-link">
							<?php
							$read_more_text = isset( $settings['read_more_text'] ) ? $settings['read_more_text'] : esc_html__( 'Read More', 'zluck-ajax-posts-filter-for-elementor' );
							echo esc_html( $read_more_text );
							?>
							<span class="aapf-read-more-arrow">&raquo;</span>
						</a>
					</div>
				<?php endif; ?>

				<?php if ( ! empty( $settings['show_meta'] ) && 'yes' === $settings['show_meta'] ) : ?>
					<div class="aapf-post-meta aapf-card-meta">
						<?php
						$meta_items = isset( $settings['meta_items'] ) ? $settings['meta_items'] : array();
						aapf_render_meta_items( $meta_items, $settings );
						?>
					</div>
				<?php endif; ?>
			</div>
		</article>
		<?php
	}

	/**
	 * Render icon for pagination.
	 *
	 * @param array $icon Icon settings.
	 * @return string Icon HTML.
	 */
	private function render_icon( $icon ) {
		if ( empty( $icon ) || ! is_array( $icon ) ) {
			return '';
		}
		$icon_value = isset( $icon['value'] ) ? $icon['value'] : '';
		if ( empty( $icon_value ) ) {
			return '';
		}
		$icon_library = isset( $icon['library'] ) ? $icon['library'] : '';
		$icon_html = '';
		if ( 'svg' === $icon_library && is_array( $icon_value ) ) {
			$width = isset( $icon_value['width'] ) ? absint( $icon_value['width'] ) : 24;
			$height = isset( $icon_value['height'] ) ? absint( $icon_value['height'] ) : 24;
			$path = isset( $icon_value['path'] ) ? $icon_value['path'] : '';
			$viewbox = isset( $icon_value['viewBox'] ) ? $icon_value['viewBox'] : "0 0 {$width} {$height}";
			
			// Sanitize SVG path - only allow safe SVG path characters
			// Note: SVG paths from Elementor are already validated, but we add extra safety
			$path = preg_replace( '/[^MmLlHhVvCcSsQqTtAaZz0-9\s,.-]/', '', $path );
			
			// Validate viewBox format (should be "x y width height")
			$viewbox = sanitize_text_field( $viewbox );
			if ( ! preg_match( '/^\d+\s+\d+\s+\d+\s+\d+$/', $viewbox ) ) {
				$viewbox = "0 0 {$width} {$height}";
			}
			
			$icon_html = '<svg class="aapf-pagination-icon" aria-hidden="true" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" width="' . esc_attr( $width ) . '" height="' . esc_attr( $height ) . '" viewBox="' . esc_attr( $viewbox ) . '"><path d="' . esc_attr( $path ) . '"></path></svg>';
		} else {
			$icon_class = is_string( $icon_value ) ? $icon_value : ( isset( $icon_value['url'] ) ? $icon_value['url'] : '' );
			if ( ! empty( $icon_class ) ) {
				$icon_html = '<i class="' . esc_attr( $icon_class ) . ' aapf-pagination-icon"></i>';
			}
		}
		return $icon_html;
	}
}

