<?php
/**
 * Dashboard Builder — FREE
 *
 * Renders a custom WordPress dashboard built from a saved JSON layout.
 * The layout is edited in the Panelra settings panel (tab: builder)
 * and stored as a serialised array in the option
 * 'pnlrdb_dashboard_layout'.
 *
 * Data structure of the layout option:
 * array(
 *   'enabled'            => bool,
 *   'hide_wp'            => bool,
 *   'hide_screen_opts'   => bool,
 *   'hide_help'          => bool,
 *   'hide_notices'       => bool,
 *   'hide_title'         => bool,
 *   'defaults_initialized' => bool,
 *   'sections'           => array(
 *     array(
 *       'id'      => string,
 *       'cols'    => int (1|2|3),
 *       'roles'   => array of role slugs, or ['all'],
 *       'blocks'  => array(
 *         array(
 *           'id'    => string,
 *           'type'  => string,
 *           'col'   => int (0-based column index),
 *           'roles' => array of role slugs, or ['all'],
 *           'data'  => array (type-specific settings),
 *         ),
 *       ),
 *     ),
 *   ),
 * )
 *
 * FREE blocks: heading, text, button, image, divider, video, stats, hero, link_list, checklist, quick_actions
 * PRO  blocks: file, form, html  (gated via filter)
 *
 * @package Panelra
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class Pnlrdb_Dashboard_Builder
 */
class Pnlrdb_Dashboard_Builder {

	/** Option key for the layout JSON. */
	const OPTION_KEY = 'pnlrdb_dashboard_layout';

	/** Nonce action for AJAX saves. */
	const NONCE_ACTION = 'pnlrdb_builder_save';

	/**
	 * Constructor — register hooks.
	 */
	public function __construct() {
		add_action( 'wp_dashboard_setup', array( $this, 'setup_dashboard' ), 999 );
		add_action( 'admin_head', array( $this, 'maybe_hide_screen_options' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'print_dashboard_builder_css' ), 20 );
		add_action( 'in_admin_header', array( $this, 'render_full_dashboard_container' ) );

		add_action( 'wp_ajax_pnlrdb_save_layout', array( $this, 'ajax_save_layout' ) );
		add_action( 'wp_ajax_pnlrdb_get_layout', array( $this, 'ajax_get_layout' ) );
		add_action( 'admin_post_pnlrdb_apply_dashboard_template', array( $this, 'handle_apply_dashboard_template' ) );
		add_action( 'admin_post_pnlrdb_disable_custom_dashboard', array( $this, 'handle_disable_custom_dashboard' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_builder_assets' ) );
	}

	/* ------------------------------------------------------------------
	 * Public helpers
	 * ---------------------------------------------------------------- */

	/**
	 * Return the saved layout array, or a sensible empty default.
	 *
	 * @return array
	 */
	public static function get_layout() {
		$raw = get_option( self::OPTION_KEY, array() );

		if ( ! is_array( $raw ) ) {
			$raw = array();
		}

		return wp_parse_args(
			$raw,
			array(
				'enabled'              => false,
				'hide_wp'              => false,
				'hide_screen_opts'     => false,
				'hide_help'            => false,
				'hide_notices'         => false,
				'hide_title'           => false,
				'defaults_initialized' => ! empty( $raw['enabled'] ),
				'sections'             => array(),
			)
		);
	}

	/**
	 * Return the list of FREE block type definitions.
	 * PRO adds its own types via the 'pnlrdb_builder_block_types' filter.
	 *
	 * @return array slug => array( label, icon_svg, category )
	 */
	public static function get_block_types() {
		$types = array(
			'heading' => array(
				'label'    => __( 'Heading', 'panelra-dashboard-builder' ),
				'category' => 'content',
				'icon'     => '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M4 12h16M4 6h16M4 18h16"/></svg>',
			),
			'text'    => array(
				'label'    => __( 'Paragraph', 'panelra-dashboard-builder' ),
				'category' => 'content',
				'icon'     => '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M7 8h10M7 12h10M7 16h6"/></svg>',
			),
			'button'  => array(
				'label'    => __( 'Button / Link', 'panelra-dashboard-builder' ),
				'category' => 'content',
				'icon'     => '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="8" width="18" height="8" rx="4"/><path d="M9 12h6"/></svg>',
			),
			'image'   => array(
				'label'    => __( 'Image', 'panelra-dashboard-builder' ),
				'category' => 'content',
				'icon'     => '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="9" cy="9" r="2"/><path d="M21 15l-5-5L5 21"/></svg>',
			),
			'divider' => array(
				'label'    => __( 'Divider', 'panelra-dashboard-builder' ),
				'category' => 'content',
				'icon'     => '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="12" x2="21" y2="12"/></svg>',
			),
			'video'   => array(
				'label'    => __( 'Video embed', 'panelra-dashboard-builder' ),
				'category' => 'media',
				'icon'     => '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="6" width="15" height="12" rx="2"/><path d="M17 9l5-3v12l-5-3V9z"/></svg>',
			),
			'stats'   => array(
				'label'    => __( 'Site stats', 'panelra-dashboard-builder' ),
				'category' => 'widget',
				'icon'     => '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 20V10M12 20V4M6 20v-6"/></svg>',
			),
			'hero'    => array(
				'label'    => __( 'Hero card', 'panelra-dashboard-builder' ),
				'category' => 'widget',
				'icon'     => '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="5" width="18" height="14" rx="3"/><path d="M7 10h7M7 14h5"/><circle cx="17" cy="12" r="2"/></svg>',
			),
			'link_list' => array(
				'label'    => __( 'Link list', 'panelra-dashboard-builder' ),
				'category' => 'widget',
				'icon'     => '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10 13a5 5 0 0 0 7.07 0l2.12-2.12a5 5 0 0 0-7.07-7.07L11 4.93"/><path d="M14 11a5 5 0 0 0-7.07 0L4.81 13.12a5 5 0 0 0 7.07 7.07L13 19.07"/></svg>',
			),
			'checklist' => array(
				'label'    => __( 'Checklist / status', 'panelra-dashboard-builder' ),
				'category' => 'widget',
				'icon'     => '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>',
			),
			'quick_actions' => array(
				'label'    => __( 'Quick actions', 'panelra-dashboard-builder' ),
				'category' => 'widget',
				'icon'     => '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7" rx="2"/><rect x="14" y="3" width="7" height="7" rx="2"/><rect x="3" y="14" width="7" height="7" rx="2"/><rect x="14" y="14" width="7" height="7" rx="2"/></svg>',
			),
		);

		/**
		 * Filters the available block types.
		 * Pro adds: file, form, html.
		 *
		 * @param array $types Existing block type definitions.
		 */
		return apply_filters( 'pnlrdb_builder_block_types', $types );
	}


	/**
	 * Return ready-to-install dashboard templates.
	 *
	 * Templates use the same layout schema as the Dashboard Builder so installed
	 * sections remain fully editable after import.
	 *
	 * @return array
	 */
	public static function get_dashboard_templates() {
		$admin_url  = admin_url();
		$assets_url = trailingslashit( PNLRDB_PLUGIN_URL . 'assets' );

		$templates = array(
			'from_scratch' => array(
				'id'          => 'from_scratch',
				'name'        => __( 'From Scratch', 'panelra-dashboard-builder' ),
				'eyebrow'     => __( 'Blank canvas', 'panelra-dashboard-builder' ),
				'description' => __( 'Start with an empty custom dashboard and build your own layout section by section.', 'panelra-dashboard-builder' ),
				'best_for'    => __( 'Custom dashboards and advanced setups', 'panelra-dashboard-builder' ),
				'accent'      => 'blue',
				'icon'        => '+',
				'sections'    => array(),
			),
			'tutorial'   => array(
				'id'          => 'tutorial',
				'name'        => __( 'Tutorial Dashboard', 'panelra-dashboard-builder' ),
				'eyebrow'     => __( 'Video-based onboarding', 'panelra-dashboard-builder' ),
				'description' => __( 'Help clients and users learn how to manage their website with videos, useful links and next steps.', 'panelra-dashboard-builder' ),
				'best_for'    => __( 'Developers, agencies and educators', 'panelra-dashboard-builder' ),
				'accent'      => 'purple',
				'icon'        => '▶',
				'sections'    => array(
					array(
						'id'     => 'pnlrdb_tpl_tutorial_hero',
						'cols'   => 1,
						'layout' => 'grid12',
						'gap'    => 'compact',
						'roles'  => array( 'all' ),
						'blocks' => array(
							array( 'id' => 'pnlrdb_tpl_tutorial_hero1', 'span' => 12, 'type' => 'hero', 'col' => 0, 'data' => array( 'eyebrow' => __( 'Tutorials & Guides', 'panelra-dashboard-builder' ), 'title' => __( 'Welcome! Learn your website step by step.', 'panelra-dashboard-builder' ), 'content' => __( 'Use this dashboard to collect the most important video tutorials, guides and support links for your website.', 'panelra-dashboard-builder' ), 'theme' => 'purple', 'icon' => 'play', 'image_url' => $assets_url . 'tutorial.png' ) ),
						),
					),
					array(
						'id'        => 'pnlrdb_tpl_tutorial_video',
						'title'     => __( 'VIDEO TUTORIAL', 'panelra-dashboard-builder' ),
						'cta_label' => __( 'View all videos →', 'panelra-dashboard-builder' ),
						'cta_url'   => 'https://www.youtube.com/@DavelabsWP',
						'cols'      => 3,
						'layout' => 'grid12',
						'gap'    => 'compact',
						'roles'  => array( 'all' ),
						'blocks' => array(
							array( 'id' => 'pnlrdb_tpl_tutorial_video1', 'span' => 4, 'type' => 'video', 'col' => 0, 'data' => array( 'url' => 'https://www.youtube.com/watch?v=O-Xx98nyBu4', 'align' => 'center', 'title' => __( 'Getting Started', 'panelra-dashboard-builder' ), 'subtitle' => __( 'Learn the basics and discover your new dashboard.', 'panelra-dashboard-builder' ), 'duration' => __( '3:45', 'panelra-dashboard-builder' ) ) ),
							array( 'id' => 'pnlrdb_tpl_tutorial_video2', 'span' => 4, 'type' => 'video', 'col' => 1, 'data' => array( 'url' => 'https://www.youtube.com/watch?v=O-Xx98nyBu4', 'align' => 'center', 'title' => __( 'Edit Pages', 'panelra-dashboard-builder' ), 'subtitle' => __( 'Update your pages quickly and safely.', 'panelra-dashboard-builder' ), 'duration' => __( '4:21', 'panelra-dashboard-builder' ) ) ),
							array( 'id' => 'pnlrdb_tpl_tutorial_video3', 'span' => 4, 'type' => 'video', 'col' => 2, 'data' => array( 'url' => 'https://www.youtube.com/watch?v=O-Xx98nyBu4', 'align' => 'center', 'title' => __( 'Create a Blog Post', 'panelra-dashboard-builder' ), 'subtitle' => __( 'Publish fresh content without confusion.', 'panelra-dashboard-builder' ), 'duration' => __( '5:12', 'panelra-dashboard-builder' ) ) ),
						),
					),
					array(
						'id'     => 'pnlrdb_tpl_tutorial_cards',
						'cols'   => 2,
						'layout' => 'grid12',
						'gap'    => 'normal',
						'roles'  => array( 'all' ),
						'blocks' => array(
							array( 'id' => 'pnlrdb_tpl_tutorial_links', 'span' => 6, 'type' => 'link_list', 'col' => 0, 'data' => array( 'title' => __( 'Useful Links', 'panelra-dashboard-builder' ), 'items_data' => array( array( 'icon' => '📄', 'label' => __( 'Documentation', 'panelra-dashboard-builder' ), 'url' => home_url( '/' ) ), array( 'icon' => '❓', 'label' => __( 'FAQ', 'panelra-dashboard-builder' ), 'url' => home_url( '/' ) ), array( 'icon' => '💬', 'label' => __( 'Support Center', 'panelra-dashboard-builder' ), 'url' => home_url( '/' ) ), array( 'icon' => '🔌', 'label' => __( 'Useful Plugins', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'plugins.php' ) ) ) ),
							array( 'id' => 'pnlrdb_tpl_tutorial_steps', 'span' => 6, 'type' => 'checklist', 'col' => 1, 'data' => array( 'title' => __( 'Next Steps', 'panelra-dashboard-builder' ), 'items' => __( 'Watch the welcome video', 'panelra-dashboard-builder' ) . "\n" . __( 'Update your pages', 'panelra-dashboard-builder' ) . "\n" . __( 'Add your logo', 'panelra-dashboard-builder' ) . "\n" . __( 'Create your first blog post', 'panelra-dashboard-builder' ), 'style' => 'check' ) ),
						),
					),
					array(
						'id'     => 'pnlrdb_tpl_tutorial_support',
						'cols'   => 1,
						'layout' => 'grid12',
						'gap'    => 'compact',
						'roles'  => array( 'all' ),
						'blocks' => array(
							array( 'id' => 'pnlrdb_tpl_tutorial_support1', 'span' => 12, 'type' => 'hero', 'col' => 0, 'data' => array( 'eyebrow' => __( 'Need Help?', 'panelra-dashboard-builder' ), 'title' => __( 'Your support team is here for you.', 'panelra-dashboard-builder' ), 'content' => __( 'Add your support email, documentation link or client help desk here.', 'panelra-dashboard-builder' ), 'theme' => 'purple', 'icon' => 'support' ) ),
						),
					),
				),
			),
			'statistics' => array(
				'id'          => 'statistics',
				'name'        => __( 'Statistics Dashboard', 'panelra-dashboard-builder' ),
				'eyebrow'     => __( 'Site control center', 'panelra-dashboard-builder' ),
				'description' => __( 'Create a practical overview with site counters, quick actions and useful admin shortcuts.', 'panelra-dashboard-builder' ),
				'best_for'    => __( 'Site owners, developers and admins', 'panelra-dashboard-builder' ),
				'accent'      => 'blue',
				'icon'        => '▥',
				'sections'    => array(
					array(
						'id'     => 'pnlrdb_tpl_stats_hero',
						'layout' => 'grid12',
						'gap'    => 'compact',
						'cols'   => 1,
						'roles'  => array( 'all' ),
						'blocks' => array(
							array( 'id' => 'pnlrdb_tpl_stats_hero1', 'span' => 12, 'type' => 'hero', 'col' => 0, 'data' => array( 'eyebrow' => __( 'Site Statistics', 'panelra-dashboard-builder' ), 'title' => __( 'Your website control center.', 'panelra-dashboard-builder' ), 'content' => __( 'Get a clear overview of content, activity and useful admin actions from one clean dashboard.', 'panelra-dashboard-builder' ), 'theme' => 'blue', 'icon' => 'chart', 'image_url' => $assets_url . 'statistiche.png' ) ),
						),
					),
					array(
						'id'     => 'pnlrdb_tpl_stats_counters',
						'layout' => 'grid12',
						'gap'    => 'compact',
						'cols'   => 1,
						'roles'  => array( 'all' ),
						'blocks' => array(
							array( 'id' => 'pnlrdb_tpl_stats_stats1', 'span' => 12, 'type' => 'stats', 'col' => 0, 'data' => array( 'show_posts' => true, 'show_pages' => true, 'show_comments' => true, 'show_users' => true, 'show_media' => false, 'align' => 'left' ) ),
						),
					),
					array(
						'id'     => 'pnlrdb_tpl_stats_main',
						'layout' => 'grid12',
						'gap'    => 'normal',
						'cols'   => 2,
						'roles'  => array( 'all' ),
						'blocks' => array(
							array( 'id' => 'pnlrdb_tpl_stats_overview', 'span' => 6, 'type' => 'checklist', 'col' => 0, 'data' => array( 'title' => __( 'Site Overview', 'panelra-dashboard-builder' ), 'items' => __( 'WordPress updated', 'panelra-dashboard-builder' ) . "\n" . __( 'Plugins checked', 'panelra-dashboard-builder' ) . "\n" . __( 'Backups active', 'panelra-dashboard-builder' ) . "\n" . __( 'Site health reviewed', 'panelra-dashboard-builder' ), 'style' => 'status' ) ),
							array( 'id' => 'pnlrdb_tpl_stats_activity', 'span' => 6, 'type' => 'link_list', 'col' => 1, 'data' => array( 'title' => __( 'Recent Activity', 'panelra-dashboard-builder' ), 'items_data' => array( array( 'icon' => '📝', 'label' => __( 'New post: 10 Tips for a Faster Website', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'edit.php' ), array( 'icon' => '📄', 'label' => __( 'Page updated: About Us', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'edit.php?post_type=page' ), array( 'icon' => '👤', 'label' => __( 'New user: john@example.com', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'users.php' ), array( 'icon' => '💬', 'label' => __( 'Comment on: Hello World!', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'edit-comments.php' ) ) ) ),
						),
					),
					array(
						'id'     => 'pnlrdb_tpl_stats_content',
						'layout' => 'grid12',
						'gap'    => 'normal',
						'cols'   => 2,
						'roles'  => array( 'all' ),
						'blocks' => array(
							array( 'id' => 'pnlrdb_tpl_stats_top_content', 'span' => 6, 'type' => 'link_list', 'col' => 0, 'data' => array( 'title' => __( 'Top Content', 'panelra-dashboard-builder' ), 'items_data' => array( array( 'icon' => '🏆', 'label' => __( '10 Tips for a Faster Website', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'edit.php' ), array( 'icon' => '📘', 'label' => __( 'How to Choose the Right Theme', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'edit.php' ), array( 'icon' => '✨', 'label' => __( 'Beginner’s Guide to WordPress', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'edit.php' ) ) ) ),
							array( 'id' => 'pnlrdb_tpl_stats_actions', 'span' => 6, 'type' => 'quick_actions', 'col' => 1, 'data' => array( 'title' => __( 'Quick Actions', 'panelra-dashboard-builder' ), 'items_data' => array( array( 'icon' => '✏️', 'label' => __( 'Add New Post', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'post-new.php' ), array( 'icon' => '📄', 'label' => __( 'Add New Page', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'post-new.php?post_type=page' ), array( 'icon' => '🖼️', 'label' => __( 'Upload Media', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'media-new.php' ), array( 'icon' => '🧩', 'label' => __( 'Manage Plugins', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'plugins.php' ) ) ) ),
						),
					),
					array(
						'id'     => 'pnlrdb_tpl_stats_footer',
						'layout' => 'grid12',
						'gap'    => 'compact',
						'cols'   => 2,
						'roles'  => array( 'all' ),
						'blocks' => array(
							array( 'id' => 'pnlrdb_tpl_stats_notes', 'span' => 6, 'type' => 'hero', 'col' => 0, 'data' => array( 'eyebrow' => __( 'Performance', 'panelra-dashboard-builder' ), 'title' => __( 'Good', 'panelra-dashboard-builder' ), 'content' => __( 'Your site is running smoothly. Add performance, backup or security notes here.', 'panelra-dashboard-builder' ), 'theme' => 'blue', 'icon' => 'spark' ) ),
							array( 'id' => 'pnlrdb_tpl_stats_database', 'span' => 6, 'type' => 'hero', 'col' => 1, 'data' => array( 'eyebrow' => __( 'Database', 'panelra-dashboard-builder' ), 'title' => __( 'Optimized', 'panelra-dashboard-builder' ), 'content' => __( 'Last optimized: 2 days ago. Replace this with your maintenance notes.', 'panelra-dashboard-builder' ), 'theme' => 'softgreen', 'icon' => 'shield' ) ),
						),
					),
					array(
						'id'     => 'pnlrdb_tpl_stats_links_row',
						'layout' => 'grid12',
						'gap'    => 'compact',
						'cols'   => 1,
						'roles'  => array( 'all' ),
						'blocks' => array(
							array( 'id' => 'pnlrdb_tpl_stats_links', 'span' => 12, 'type' => 'link_list', 'col' => 0, 'data' => array( 'title' => __( 'Useful Admin Links', 'panelra-dashboard-builder' ), 'items_data' => array( array( 'icon' => '🧩', 'label' => __( 'Plugins', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'plugins.php' ), array( 'icon' => '🎨', 'label' => __( 'Customize', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'customize.php' ), array( 'icon' => '👥', 'label' => __( 'Users', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'users.php' ), array( 'icon' => '⚙️', 'label' => __( 'Settings', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'options-general.php' ) ) ) ),
						),
					),
				),
			),
			'welcome'    => array(
				'id'          => 'welcome',
				'name'        => __( 'Welcome Dashboard', 'panelra-dashboard-builder' ),
				'eyebrow'     => __( 'Client onboarding', 'panelra-dashboard-builder' ),
				'description' => __( 'Give clients a friendly dashboard with useful links, support details, maintenance status and next actions.', 'panelra-dashboard-builder' ),
				'best_for'    => __( 'Agencies, freelancers and client websites', 'panelra-dashboard-builder' ),
				'accent'      => 'green',
				'icon'        => '👋',
				'sections'    => array(
					array(
						'id'     => 'pnlrdb_tpl_welcome_hero',
						'layout' => 'grid12',
						'gap'    => 'compact',
						'cols'   => 1,
						'roles'  => array( 'all' ),
						'blocks' => array(
							array( 'id' => 'pnlrdb_tpl_welcome_hero1', 'span' => 12, 'type' => 'hero', 'col' => 0, 'data' => array( 'eyebrow' => __( 'Welcome to Your Website!', 'panelra-dashboard-builder' ), 'title' => __( 'Welcome, John!', 'panelra-dashboard-builder' ), 'content' => __( 'Thank you for choosing us to build your website. Here you will find everything you need to manage and grow your online presence.', 'panelra-dashboard-builder' ), 'theme' => 'green', 'icon' => 'user', 'image_url' => $assets_url . 'welcome.png' ) ),
						),
					),
					array(
						'id'     => 'pnlrdb_tpl_welcome_cards',
						'layout' => 'grid12',
						'gap'    => 'normal',
						'cols'   => 2,
						'roles'  => array( 'all' ),
						'blocks' => array(
							array( 'id' => 'pnlrdb_tpl_welcome_links', 'span' => 6, 'type' => 'link_list', 'col' => 0, 'data' => array( 'title' => __( 'Important Links', 'panelra-dashboard-builder' ), 'items_data' => array( array( 'icon' => '🌐', 'label' => __( 'Visit Website', 'panelra-dashboard-builder' ), 'url' => home_url( '/' ) ), array( 'icon' => '✏️', 'label' => __( 'Edit Pages', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'edit.php?post_type=page' ), array( 'icon' => '📝', 'label' => __( 'Manage Posts', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'edit.php' ), array( 'icon' => '⚙️', 'label' => __( 'General Settings', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'options-general.php' ), array( 'icon' => '🧩', 'label' => __( 'Installed Plugins', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'plugins.php' ) ) ) ),
							array( 'id' => 'pnlrdb_tpl_welcome_help', 'span' => 6, 'type' => 'hero', 'col' => 1, 'data' => array( 'eyebrow' => __( 'Need Help?', 'panelra-dashboard-builder' ), 'title' => __( 'We are here for you.', 'panelra-dashboard-builder' ), 'content' => __( 'If you have any questions or need assistance, do not hesitate to contact us.', 'panelra-dashboard-builder' ), 'theme' => 'green', 'icon' => 'support', 'button_label' => __( 'Contact Support', 'panelra-dashboard-builder' ), 'button_url' => 'mailto:support@example.com', 'support_email' => 'support@example.com', 'support_phone' => '+1 (555) 123-4567' ) ),
						),
					),
					array(
						'id'     => 'pnlrdb_tpl_welcome_status',
						'layout' => 'grid12',
						'gap'    => 'normal',
						'cols'   => 2,
						'roles'  => array( 'all' ),
						'blocks' => array(
							array( 'id' => 'pnlrdb_tpl_welcome_status1', 'span' => 6, 'type' => 'checklist', 'col' => 0, 'data' => array( 'title' => __( 'Maintenance Status', 'panelra-dashboard-builder' ), 'items' => __( 'WordPress updated', 'panelra-dashboard-builder' ) . "\n" . __( 'Plugins updated', 'panelra-dashboard-builder' ) . "\n" . __( 'Backup status active', 'panelra-dashboard-builder' ) . "\n" . __( 'Security monitoring active', 'panelra-dashboard-builder' ), 'style' => 'status' ) ),
							array( 'id' => 'pnlrdb_tpl_welcome_actions', 'span' => 6, 'type' => 'quick_actions', 'col' => 1, 'data' => array( 'title' => __( 'Quick Actions', 'panelra-dashboard-builder' ), 'items_data' => array( array( 'icon' => '✏️', 'label' => __( 'Add New Post', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'post-new.php' ), array( 'icon' => '📄', 'label' => __( 'Add New Page', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'post-new.php?post_type=page' ), array( 'icon' => '🖼️', 'label' => __( 'Upload Media', 'panelra-dashboard-builder' ), 'url' => $admin_url . 'media-new.php' ), array( 'icon' => '🌐', 'label' => __( 'View Site', 'panelra-dashboard-builder' ), 'url' => home_url( '/' ) ) ) ) ),
						),
					),
					array(
						'id'     => 'pnlrdb_tpl_welcome_tip',
						'layout' => 'grid12',
						'gap'    => 'compact',
						'cols'   => 1,
						'roles'  => array( 'all' ),
						'blocks' => array(
							array( 'id' => 'pnlrdb_tpl_welcome_tip1', 'span' => 12, 'type' => 'hero', 'col' => 0, 'data' => array( 'eyebrow' => __( 'A Tip for You', 'panelra-dashboard-builder' ), 'title' => __( 'Keep your website safe and fresh.', 'panelra-dashboard-builder' ), 'content' => __( 'Regularly update your content and keep your site backed up. This helps protect your visitors and your work.', 'panelra-dashboard-builder' ), 'theme' => 'softgreen', 'icon' => 'shield' ) ),
						),
					),
				),
			),
		);

		return apply_filters( 'pnlrdb_dashboard_templates', $templates );
	}

	/**
	 * Apply one bundled dashboard template from the front dashboard picker.
	 *
	 * @return void
	 */
	public function handle_apply_dashboard_template() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have permission to perform this action.', 'panelra-dashboard-builder' ) );
		}

		check_admin_referer( 'pnlrdb_apply_dashboard_template' );

		$template_id = isset( $_GET['template'] ) ? sanitize_key( wp_unslash( $_GET['template'] ) ) : '';
		$templates   = self::get_dashboard_templates();

		if ( ! isset( $templates[ $template_id ] ) ) {
			wp_safe_redirect( admin_url( 'index.php' ) );
			exit;
		}

		$layout = self::get_layout();
		$layout['enabled']              = true;
		$layout['hide_wp']              = true;
		$layout['hide_screen_opts']     = true;
		$layout['hide_help']            = true;
		$layout['hide_notices']         = true;
		$layout['hide_title']           = true;
		$layout['defaults_initialized'] = true;
		$layout['sections']             = isset( $templates[ $template_id ]['sections'] ) && is_array( $templates[ $template_id ]['sections'] ) ? $templates[ $template_id ]['sections'] : array();

		update_option( self::OPTION_KEY, $layout );

		wp_safe_redirect( admin_url( 'index.php?pnlrdb_template_applied=1' ) );
		exit;
	}

	/**
	 * Disable the custom dashboard and return to the native WordPress dashboard.
	 *
	 * @return void
	 */
	public function handle_disable_custom_dashboard() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have permission to perform this action.', 'panelra-dashboard-builder' ) );
		}

		check_admin_referer( 'pnlrdb_disable_custom_dashboard' );

		$layout            = self::get_layout();
		$layout['enabled'] = false;
		update_option( self::OPTION_KEY, $layout );

		wp_safe_redirect( admin_url( 'index.php?pnlrdb_classic_dashboard=1' ) );
		exit;
	}


	/* ------------------------------------------------------------------
	 * Dashboard setup
	 * ---------------------------------------------------------------- */

	/**
	 * Clean up the native dashboard when the custom builder is enabled.
	 *
	 * @return void
	 */
	public function setup_dashboard() {
		$layout = self::get_layout();

		if ( empty( $layout['enabled'] ) ) {
			return;
		}

		remove_action( 'welcome_panel', 'wp_welcome_panel' );
		update_user_meta( get_current_user_id(), 'show_welcome_panel', 0 );

		if ( ! empty( $layout['hide_wp'] ) ) {
			global $wp_meta_boxes;

			if ( isset( $wp_meta_boxes['dashboard'] ) && is_array( $wp_meta_boxes['dashboard'] ) ) {
				$wp_meta_boxes['dashboard'] = array();
			}

			if ( method_exists( $this, 'remove_all_default_widgets' ) ) {
				$this->remove_all_default_widgets();
			}
		}
	}

	/**
	 * Remove all known default WordPress dashboard widgets.
	 *
	 * @return void
	 */
	private function remove_all_default_widgets() {
		$defaults = array(
			array( 'dashboard_right_now', 'dashboard', 'normal' ),
			array( 'dashboard_activity', 'dashboard', 'normal' ),
			array( 'dashboard_quick_press', 'dashboard', 'side' ),
			array( 'dashboard_primary', 'dashboard', 'side' ),
			array( 'dashboard_site_health', 'dashboard', 'normal' ),
		);

		foreach ( $defaults as $item ) {
			remove_meta_box( $item[0], $item[1], $item[2] );
		}

		remove_action( 'welcome_panel', 'wp_welcome_panel' );
		update_user_meta( get_current_user_id(), 'show_welcome_panel', 0 );

		/**
		 * Fires after default widgets are removed.
		 * Use this hook to also remove third-party plugin widgets.
		 *
		 * @since 1.0.0
		 */
		do_action( 'pnlrdb_after_remove_default_widgets' );
	}

	/**
	 * Hide "Screen Options" and/or "Help" tabs on the dashboard if configured.
	 *
	 * @return void
	 */
	public function maybe_hide_screen_options() {
		$layout = self::get_layout();
		$screen = get_current_screen();

		if ( ! $screen || 'dashboard' !== $screen->id ) {
			return;
		}

		if ( empty( $layout['enabled'] ) ) {
			return;
		}

		$css = '';

		if ( ! empty( $layout['hide_screen_opts'] ) ) {
			$css .= '#screen-options-link-wrap{display:none!important;}';
		}

		if ( ! empty( $layout['hide_help'] ) ) {
			$css .= '#contextual-help-link-wrap{display:none!important;}';
		}

		if ( $css ) {
			wp_register_style( 'pnlrdb-dashboard-ui', false, array(), PNLRDB_VERSION );
			wp_enqueue_style( 'pnlrdb-dashboard-ui' );
			wp_add_inline_style( 'pnlrdb-dashboard-ui', $css );
		}
	}

	/**
	 * Hide native dashboard columns/placeholders and make room for the builder canvas.
	 *
	 * @return void
	 */
	public function print_dashboard_builder_css( $hook ) {
		if ( 'index.php' !== $hook ) {
			return;
		}

		$layout = self::get_layout();

		if ( empty( $layout['enabled'] ) ) {
			return;
		}

		$pnlrdb_css = '';

		if ( ! empty( $layout['hide_wp'] ) ) {
			$pnlrdb_css .= '
			#dashboard-widgets-wrap,
			#dashboard-widgets,
			#postbox-container-1,
			#postbox-container-2,
			#postbox-container-3,
			#postbox-container-4,
			#normal-sortables,
			#side-sortables,
			#column3-sortables,
			#column4-sortables,
			#dashboard-widgets .meta-box-sortables,
			#dashboard-widgets .postbox-container {
				display: none !important;
			}
';
		}

		$pnlrdb_css .= '
		#pnlrdb-dashboard-builder-page {
			box-sizing: border-box;
			margin: 20px 20px 0 0;
			max-width: none !important;
			width: auto;
		}

		#pnlrdb-dashboard-builder-page .ap773-custom-dashboard {
			box-sizing: border-box;
			width: 100%;
			max-width: 1240px;
		}

		.ap773-custom-dashboard {
			--pnlrdb-surface: #ffffff;
			--pnlrdb-surface-soft: #f8fafc;
			--pnlrdb-border: rgba(148, 163, 184, 0.22);
			--pnlrdb-text: #0f172a;
			--pnlrdb-muted: #64748b;
			--pnlrdb-shadow: 0 18px 42px rgba(15, 23, 42, 0.07);
			--pnlrdb-shadow-hover: 0 24px 60px rgba(15, 23, 42, 0.12);
			--pnlrdb-radius: 18px;
		}

		.ap773-custom-dashboard .ap773-db-col {
			display:flex;
			flex-direction:column;
			gap:16px;
			min-width:0;
		}

		.ap773-custom-dashboard .ap773-db-text-group {
			background:rgba(255,255,255,.92);
			border:1px solid var(--pnlrdb-border);
			border-radius:var(--pnlrdb-radius);
			box-shadow:var(--pnlrdb-shadow);
			padding:22px 24px;
			display:flex;
			flex-direction:column;
			gap:8px;
		}

		.ap773-custom-dashboard .ap773-db-text-group .ap773-db-block {
			background: transparent !important;
			border: none !important;
			padding: 0 !important;
			margin: 0 !important;
		}

		.ap773-custom-dashboard .ap773-db-block--button,
		.ap773-custom-dashboard .ap773-db-block--image,
		.ap773-custom-dashboard .ap773-db-block--video,
		.ap773-custom-dashboard .ap773-db-block--divider,
		.ap773-custom-dashboard .ap773-db-block--stats,
		.ap773-custom-dashboard .ap773-db-block--hero,
		.ap773-custom-dashboard .ap773-db-block--link_list,
		.ap773-custom-dashboard .ap773-db-block--checklist,
		.ap773-custom-dashboard .ap773-db-block--quick_actions {
			background: transparent;
			border: none;
			padding: 0;
		}

		#wpbody-content > .wrap > h1:first-child {
			display: none !important;
		}

		.ap773-dashboard-title {
			font-size: 23px;
			font-weight: 400;
			margin: 0 0 20px 0;
			padding: 9px 0 4px;
			line-height: 1.3;
			color: #1d2327;
		}

		.ap773-empty-dashboard {
			background: #fff;
			border: 1px solid #dcdcde;
			border-radius: 12px;
			box-shadow: 0 1px 2px rgba(0,0,0,0.04);
			box-sizing: border-box;
			margin-top: 8px;
			max-width: 760px;
			padding: 28px 30px;
		}

		.ap773-empty-dashboard h2 {
			font-size: 22px;
			line-height: 1.3;
			margin: 0 0 8px;
		}

		.ap773-empty-dashboard p {
			color: #50575e;
			font-size: 14px;
			margin: 0 0 18px;
			max-width: 560px;
		}

		.ap773-empty-dashboard .button {
			min-height: 36px;
		}

		#ap773-preview-bar {
			position: fixed;
			top: 32px;
			left: 0;
			right: 0;
			z-index: 99998;
			background: #ea580c;
			color: #fff;
			padding: 0 20px;
			height: 40px;
			display: flex;
			align-items: center;
			justify-content: space-between;
			font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
			font-size: 13px;
			font-weight: 500;
			box-shadow: 0 2px 8px rgba(234,88,12,0.35);
		}
		#ap773-preview-bar a {
			background: rgba(255,255,255,0.2);
			color: #fff;
			padding: 5px 14px;
			border-radius: 6px;
			text-decoration: none;
			font-size: 12px;
			font-weight: 600;
			border: 1px solid rgba(255,255,255,0.35);
			white-space: nowrap;
		}
		#ap773-preview-bar a:hover { background: rgba(255,255,255,0.3); }
		body.ap773-preview-mode #wpcontent,
		body.ap773-preview-mode #wpfooter { margin-top: 40px !important; }
		body.ap773-preview-mode #wpadminbar { top: 40px !important; }

		.ap773-custom-dashboard {
			display: flex;
			flex-direction: column;
			gap: 20px;
			letter-spacing: -.01em;
		}

		.ap773-custom-dashboard .ap773-db-section {
			display: grid;
			gap: 18px;
			width: 100%;
		}

		.ap773-custom-dashboard .ap773-db-cols-1 { grid-template-columns: minmax(0, 1fr); }
		.ap773-custom-dashboard .ap773-db-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
		.ap773-custom-dashboard .ap773-db-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

		.ap773-custom-dashboard .ap773-db-section--grid12 {
			display: grid;
			grid-template-columns: repeat(12, minmax(0, 1fr));
			grid-auto-flow: row dense;
		}
		.ap773-custom-dashboard .ap773-db-section-gap--compact { gap: 14px; }
		.ap773-custom-dashboard .ap773-db-section-gap--normal { gap: 18px; }
		.ap773-custom-dashboard .ap773-db-section-gap--large { gap: 24px; }
		.ap773-custom-dashboard .ap773-db-section--grid12 > .ap773-db-block { min-width: 0; }
		.ap773-custom-dashboard .ap773-db-span-1 { grid-column: span 1; }
		.ap773-custom-dashboard .ap773-db-span-2 { grid-column: span 2; }
		.ap773-custom-dashboard .ap773-db-span-3 { grid-column: span 3; }
		.ap773-custom-dashboard .ap773-db-span-4 { grid-column: span 4; }
		.ap773-custom-dashboard .ap773-db-span-5 { grid-column: span 5; }
		.ap773-custom-dashboard .ap773-db-span-6 { grid-column: span 6; }
		.ap773-custom-dashboard .ap773-db-span-7 { grid-column: span 7; }
		.ap773-custom-dashboard .ap773-db-span-8 { grid-column: span 8; }
		.ap773-custom-dashboard .ap773-db-span-9 { grid-column: span 9; }
		.ap773-custom-dashboard .ap773-db-span-10 { grid-column: span 10; }
		.ap773-custom-dashboard .ap773-db-span-11 { grid-column: span 11; }
		.ap773-custom-dashboard .ap773-db-span-12 { grid-column: span 12; }

		.ap773-custom-dashboard .ap773-db-hero,
		.ap773-custom-dashboard .ap773-db-panel,
		.ap773-custom-dashboard .ap773-db-video,
		.ap773-custom-dashboard .ap773-db-stat {
			transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease, background .18s ease;
		}

		.ap773-custom-dashboard .ap773-db-hero,
		.ap773-custom-dashboard .ap773-db-panel {
			background: rgba(255,255,255,.94);
			border: 1px solid var(--pnlrdb-border);
			border-radius: var(--pnlrdb-radius);
			box-shadow: var(--pnlrdb-shadow);
			box-sizing: border-box;
			padding: 18px;
		}

		.ap773-custom-dashboard .ap773-db-panel:hover,
		.ap773-custom-dashboard .ap773-db-video:hover,
		.ap773-custom-dashboard .ap773-db-stat:hover {
			box-shadow: var(--pnlrdb-shadow-hover);
			transform: translateY(-2px);
		}

		.ap773-custom-dashboard .ap773-db-hero {
			align-items: center;
			display: flex;
			gap: 18px;
			justify-content: space-between;
			min-height: 104px;
			overflow: hidden;
			position: relative;
		}

		.ap773-custom-dashboard .ap773-db-hero:before,
		.ap773-custom-dashboard .ap773-db-hero:after {
			border-radius: 999px;
			content: "";
			position: absolute;
			pointer-events:none;
		}

		.ap773-custom-dashboard .ap773-db-hero:before {
			background: rgba(255,255,255,.12);
			height: 210px;
			right: -72px;
			top: -96px;
			width: 210px;
		}

		.ap773-custom-dashboard .ap773-db-hero:after {
			background: rgba(255,255,255,.09);
			height: 120px;
			right: -32px;
			bottom: -72px;
			width: 120px;
		}

		.ap773-custom-dashboard .ap773-db-hero--purple { background: radial-gradient(circle at 88% 20%,rgba(255,255,255,.28),transparent 26%), linear-gradient(135deg,#9b5cff 0%,#6d28d9 54%,#5b21b6 100%); border-color: rgba(124,58,237,.28); color:#fff; box-shadow:0 22px 60px rgba(109,40,217,.22); }
		.ap773-custom-dashboard .ap773-db-hero--blue { background: radial-gradient(circle at 88% 20%,rgba(255,255,255,.25),transparent 26%), linear-gradient(135deg,#3b82f6 0%,#2563eb 52%,#1d4ed8 100%); border-color: rgba(37,99,235,.28); color:#fff; box-shadow:0 22px 60px rgba(37,99,235,.20); }
		.ap773-custom-dashboard .ap773-db-hero--green { background: radial-gradient(circle at 88% 20%,rgba(255,255,255,.25),transparent 26%), linear-gradient(135deg,#22c55e 0%,#16a34a 52%,#15803d 100%); border-color: rgba(22,163,74,.28); color:#fff; box-shadow:0 22px 60px rgba(22,163,74,.18); }
		.ap773-custom-dashboard .ap773-db-hero--softgreen { background: radial-gradient(circle at 92% 50%,rgba(34,197,94,.14),transparent 30%), linear-gradient(135deg,#ecfdf5,#dcfce7); border-color:#bbf7d0; color:#14532d; box-shadow:0 20px 52px rgba(22,163,74,.10); }

		.ap773-custom-dashboard .ap773-db-hero-content { max-width: 760px; position: relative; z-index: 1; }
		.ap773-custom-dashboard .ap773-db-hero-eyebrow { color:inherit; font-size: 12px; font-weight: 900; letter-spacing: .095em; margin:0 0 9px; opacity:.82; text-transform: uppercase; }
		.ap773-custom-dashboard .ap773-db-hero-title { color: inherit !important; font-size: 22px; font-weight: 900; line-height: 1.08; margin: 0 0 12px; max-width:780px; }
		.ap773-custom-dashboard .ap773-db-hero-text { color: inherit !important; font-size: 14px; font-weight:600; line-height: 1.7; margin: 0; max-width: 670px; opacity: .94; }
		.ap773-custom-dashboard .ap773-db-hero-icon { align-items:center; backdrop-filter: blur(10px); background:rgba(255,255,255,.18); border:1px solid rgba(255,255,255,.30); border-radius:24px; box-shadow: inset 0 1px 0 rgba(255,255,255,.28), 0 18px 36px rgba(15,23,42,.12); display:flex; flex:0 0 78px; height:78px; justify-content:center; position:relative; z-index:1; }
		.ap773-custom-dashboard .ap773-db-hero--softgreen .ap773-db-hero-icon { background:#fff; border-color:#bbf7d0; }
		.ap773-custom-dashboard .ap773-db-hero-icon svg { height:30px; width:30px; }

		.ap773-custom-dashboard .ap773-db-panel-title {
			align-items:center;
			color: var(--pnlrdb-text);
			display:flex;
			font-size:14px;
			font-weight:900;
			gap:8px;
			letter-spacing:-.02em;
			margin:0 0 14px;
		}

		.ap773-custom-dashboard .ap773-db-link-list,
		.ap773-custom-dashboard .ap773-db-checklist {
			display:flex;
			flex-direction:column;
			gap:10px;
			margin:0;
		}

		.ap773-custom-dashboard .ap773-db-link-item,
		.ap773-custom-dashboard .ap773-db-check-item {
			align-items:center;
			background: linear-gradient(180deg,#fbfdff,#f8fafc);
			border:1px solid rgba(148,163,184,.20);
			border-radius:14px;
			color: var(--pnlrdb-text);
			display:flex;
			gap:12px;
			padding:11px 13px;
			text-decoration:none;
		}
		.ap773-custom-dashboard .ap773-db-link-item:hover { background:#fff; border-color:#c7d2fe; color:#4338ca; transform: translateY(-2px); box-shadow:0 14px 30px rgba(15,23,42,.08); }
		.ap773-custom-dashboard .ap773-db-link-item, .ap773-custom-dashboard .ap773-db-action-card { transition: background .18s ease, border-color .18s ease, color .18s ease, transform .18s ease, box-shadow .18s ease; }
		.ap773-custom-dashboard .ap773-db-item-icon { align-items:center; background:#fff; border:1px solid rgba(148,163,184,.24); border-radius:10px; box-shadow:0 8px 18px rgba(15,23,42,.04); display:flex; flex:0 0 30px; height:30px; justify-content:center; }
		.ap773-custom-dashboard .ap773-db-item-label { font-weight:800; }
		.ap773-custom-dashboard .ap773-db-check-mark { color:#16a34a; font-weight:900; margin-left:auto; }

		.ap773-custom-dashboard .ap773-db-actions-grid {
			display:grid;
			gap:12px;
			grid-template-columns: repeat(2, minmax(0, 1fr));
		}
		.ap773-custom-dashboard .ap773-db-action-card {
			align-items:center;
			background: linear-gradient(180deg,#fbfdff,#f8fafc);
			border:1px solid rgba(148,163,184,.24);
			border-radius:16px;
			color: var(--pnlrdb-text);
			display:flex;
			flex-direction:column;
			font-weight:900;
			gap:10px;
			min-height:86px;
			justify-content:center;
			padding:14px;
			text-align:center;
			text-decoration:none;
		}
		.ap773-custom-dashboard .ap773-db-action-card:hover { background:#fff; border-color:#c7d2fe; color:#4338ca; transform: translateY(-3px); box-shadow:0 18px 40px rgba(15,23,42,.10); }
		.ap773-custom-dashboard .ap773-db-action-icon { align-items:center; background:rgba(99,102,241,.08); border-radius:16px; display:flex; font-size:22px; height:42px; justify-content:center; line-height:1; width:42px; }

		.ap773-custom-dashboard .ap773-db-video {
			background:#0f172a;
			border:1px solid rgba(15,23,42,.14);
			border-radius:16px;
			box-shadow:var(--pnlrdb-shadow);
			overflow:hidden;
			padding:0;
		}
		.ap773-custom-dashboard .ap773-db-video iframe {
			aspect-ratio: 16 / 9;
			border-radius: 16px;
			box-shadow: none;
			display:block;
			height: auto !important;
			max-width: 100%;
			width: 100% !important;
		}

		.ap773-custom-dashboard .ap773-db-stats { gap: 12px !important; width: 100%; }
		.ap773-custom-dashboard .ap773-db-stat {
			background:#fff;
			border:1px solid rgba(148,163,184,.18);
			border-radius:16px;
			box-shadow:0 14px 32px rgba(15,23,42,.06);
			min-width:108px;
			padding:14px 16px 13px;
			position:relative;
			overflow:hidden;
		}
		.ap773-custom-dashboard .ap773-db-stat:before { border-radius:14px; content:""; height:34px; position:absolute; right:14px; top:14px; width:34px; opacity:.9; }
		.ap773-custom-dashboard .ap773-db-stat:nth-child(1) { background:linear-gradient(135deg,#eff6ff,#fff); }
		.ap773-custom-dashboard .ap773-db-stat:nth-child(1):before { background:#dbeafe; }
		.ap773-custom-dashboard .ap773-db-stat:nth-child(2) { background:linear-gradient(135deg,#f0fdf4,#fff); }
		.ap773-custom-dashboard .ap773-db-stat:nth-child(2):before { background:#dcfce7; }
		.ap773-custom-dashboard .ap773-db-stat:nth-child(3) { background:linear-gradient(135deg,#fefce8,#fff); }
		.ap773-custom-dashboard .ap773-db-stat:nth-child(3):before { background:#fef3c7; }
		.ap773-custom-dashboard .ap773-db-stat:nth-child(4) { background:linear-gradient(135deg,#f5f3ff,#fff); }
		.ap773-custom-dashboard .ap773-db-stat:nth-child(4):before { background:#ede9fe; }
		.ap773-custom-dashboard .ap773-db-stat:nth-child(5) { background:linear-gradient(135deg,#ecfeff,#fff); }
		.ap773-custom-dashboard .ap773-db-stat:nth-child(5):before { background:#cffafe; }
		.ap773-custom-dashboard .ap773-db-stat-n { color:var(--pnlrdb-text); display:block; font-size:24px !important; font-weight:900; letter-spacing:-.04em; line-height:1; position:relative; z-index:1; }
		.ap773-custom-dashboard .ap773-db-stat-l { color:var(--pnlrdb-muted); display:block; font-size:11px; font-weight:700; margin-top:8px; position:relative; z-index:1; }


		/* Premium template layout layer: applies only to Panelra template IDs/classes. */
		.ap773-template-tutorial,
		.ap773-template-statistics,
		.ap773-template-welcome {
			max-width: 1360px !important;
			margin-left: auto;
			margin-right: auto;
		}

		.ap773-template-tutorial .ap773-db-hero,
		.ap773-template-statistics .ap773-db-hero,
		.ap773-template-welcome .ap773-db-hero {
			min-height: 132px;
			padding: 24px 28px;
		}

		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video {
			gap: 26px;
		}

		.ap773-template-tutorial .ap773-db-video {
			border-radius: 22px;
			box-shadow: 0 24px 52px rgba(15,23,42,.13);
			position: relative;
		}

		.ap773-template-tutorial .ap773-db-video iframe {
			border-radius: 22px;
		}

		.ap773-db-video-meta {
			background: linear-gradient(180deg,#fff,#f8fafc);
			border-top: 1px solid rgba(148,163,184,.18);
			padding: 14px 16px 15px;
		}

		.ap773-db-video-title {
			color: #0f172a;
			font-size: 13px;
			font-weight: 900;
			line-height: 1.35;
			margin: 0;
		}

		.ap773-db-video-duration {
			color: #64748b;
			display: block;
			font-size: 11px;
			font-weight: 800;
			margin-top: 4px;
		}

		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_counters .ap773-db-stats {
			display: grid !important;
			gap: 18px !important;
			grid-template-columns: repeat(5, minmax(122px, 1fr)) !important;
			justify-content: stretch !important;
			width: 100%;
		}

		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_counters .ap773-db-stat {
			min-height: 88px;
			min-width: 0;
			padding: 18px 18px 16px;
		}

		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_counters .ap773-db-stat-n {
			font-size: 29px !important;
		}

		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_content .ap773-db-panel,
		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_main .ap773-db-panel,
		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_cards .ap773-db-panel,
		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_status .ap773-db-panel {
			min-height: 100%;
		}

		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_tip .ap773-db-hero {
			min-height: 126px;
		}

		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_cards .ap773-db-hero {
			min-height: 100%;
		}

		.ap773-custom-dashboard .ap773-db-panel {
			padding: 18px;
		}

		.ap773-custom-dashboard .ap773-db-link-item,
		.ap773-custom-dashboard .ap773-db-check-item {
			min-height: 54px;
			padding: 16px 17px;
		}

		.ap773-custom-dashboard .ap773-db-actions-grid {
			gap: 16px;
		}

		.ap773-custom-dashboard .ap773-db-action-card {
			min-height: 122px;
		}

		.ap773-custom-dashboard .ap773-db-action-card span:last-child,
		.ap773-custom-dashboard .ap773-db-link-item .ap773-db-item-label,
		.ap773-custom-dashboard .ap773-db-check-item .ap773-db-item-label {
			line-height: 1.28;
		}

		.ap773-custom-dashboard .ap773-db-hero--purple .ap773-db-hero-title,
		.ap773-custom-dashboard .ap773-db-hero--purple .ap773-db-hero-text,
		.ap773-custom-dashboard .ap773-db-hero--blue .ap773-db-hero-title,
		.ap773-custom-dashboard .ap773-db-hero--blue .ap773-db-hero-text,
		.ap773-custom-dashboard .ap773-db-hero--green .ap773-db-hero-title,
		.ap773-custom-dashboard .ap773-db-hero--green .ap773-db-hero-text {
			text-shadow: 0 1px 1px rgba(0,0,0,.08);
		}


		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_links_row .ap773-db-link-list {
			display: grid;
			grid-template-columns: repeat(4, minmax(0, 1fr));
		}

		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_links_row .ap773-db-panel {
			padding: 24px 28px;
		}



		/* Flexible grid tuning for bundled premium templates. */
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_cards,
		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_cards,
		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_status,
		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_main,
		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_content,
		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_footer { align-items: stretch; }

		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_links_row .ap773-db-link-list { grid-template-columns: repeat(4, minmax(0, 1fr)); }

		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video .ap773-db-video iframe { max-height: 210px; }
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_support .ap773-db-hero { min-height: 118px; }
		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_tip .ap773-db-hero { min-height: 118px; }

		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_cards .ap773-db-hero { min-height: 100%; }
		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_cards .ap773-db-block--hero,
		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_status .ap773-db-block--quick_actions { align-self: stretch; }

		.ap773-template-statistics .ap773-db-actions-grid,
		.ap773-template-welcome .ap773-db-actions-grid { gap: 14px; }
		.ap773-template-statistics .ap773-db-action-card,
		.ap773-template-welcome .ap773-db-action-card { min-height: 118px; }


		/* Preset composition layer for bundled templates: compact, dense and closer to the visual mockups. */
		.ap773-template-tutorial,
		.ap773-template-statistics,
		.ap773-template-welcome {
			max-width: 1180px !important;
			margin-left: auto;
			margin-right: auto;
		}

		.ap773-template-tutorial .ap773-db-section,
		.ap773-template-statistics .ap773-db-section,
		.ap773-template-welcome .ap773-db-section {
			gap: 18px;
		}

		.ap773-template-tutorial .ap773-db-hero,
		.ap773-template-statistics .ap773-db-hero,
		.ap773-template-welcome .ap773-db-hero {
			min-height: 104px;
			padding: 20px 24px;
		}

		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video {
			gap: 18px;
		}

		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video .ap773-db-video iframe {
			max-height: 142px;
			object-fit: cover;
		}

		.ap773-template-tutorial .ap773-db-video-meta {
			padding: 10px 12px 11px;
		}

		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_cards .ap773-db-block--link_list { grid-column: span 5; }
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_cards .ap773-db-block--checklist { grid-column: span 7; }
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_support .ap773-db-hero { min-height: 96px; }

		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_counters .ap773-db-block--stats { grid-column: span 12; }
		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_counters .ap773-db-stats {
			display: grid !important;
			grid-template-columns: repeat(5, minmax(0, 1fr)) !important;
			gap: 12px !important;
			width: 100%;
		}
		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_counters .ap773-db-stat {
			min-height: 72px;
			padding: 14px 15px 12px;
		}
		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_main .ap773-db-block,
		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_content .ap773-db-block,
		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_footer .ap773-db-block { grid-column: span 6; }
		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_links_row .ap773-db-link-list {
			display: grid;
			grid-template-columns: repeat(4, minmax(0, 1fr));
			gap: 10px;
		}
		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_links_row .ap773-db-link-item {
			min-height: 48px;
		}

		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_cards .ap773-db-block--link_list { grid-column: span 7; }
		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_cards .ap773-db-block--hero { grid-column: span 5; }
		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_status .ap773-db-block { grid-column: span 6; }
		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_cards .ap773-db-hero { min-height: 100%; }
		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_tip .ap773-db-hero { min-height: 98px; }

		.ap773-template-tutorial .ap773-db-panel,
		.ap773-template-statistics .ap773-db-panel,
		.ap773-template-welcome .ap773-db-panel {
			padding: 18px;
		}
		.ap773-template-tutorial .ap773-db-link-item,
		.ap773-template-tutorial .ap773-db-check-item,
		.ap773-template-statistics .ap773-db-link-item,
		.ap773-template-statistics .ap773-db-check-item,
		.ap773-template-welcome .ap773-db-link-item,
		.ap773-template-welcome .ap773-db-check-item {
			min-height: 46px;
			padding: 11px 13px;
		}
		.ap773-template-statistics .ap773-db-action-card,
		.ap773-template-welcome .ap773-db-action-card {
			min-height: 96px;
		}


		/* Final premium preset alignment: compact mockup-like proportions without touching user data. */
		#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-tutorial,
		#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-statistics,
		#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-welcome {
			max-width: 980px !important;
			gap: 16px;
			margin-left: auto;
			margin-right: auto;
		}

		.ap773-template-tutorial .ap773-db-section,
		.ap773-template-statistics .ap773-db-section,
		.ap773-template-welcome .ap773-db-section {
			gap: 14px !important;
		}

		.ap773-template-tutorial .ap773-db-hero,
		.ap773-template-statistics .ap773-db-hero,
		.ap773-template-welcome .ap773-db-hero {
			border-radius: 14px;
			min-height: 92px;
			padding: 18px 22px;
		}

		.ap773-template-tutorial .ap773-db-hero-title,
		.ap773-template-statistics .ap773-db-hero-title,
		.ap773-template-welcome .ap773-db-hero-title {
			font-size: 20px;
			margin-bottom: 8px;
		}

		.ap773-template-tutorial .ap773-db-hero-text,
		.ap773-template-statistics .ap773-db-hero-text,
		.ap773-template-welcome .ap773-db-hero-text {
			font-size: 12px;
			line-height: 1.55;
			max-width: 560px;
		}

		.ap773-template-tutorial .ap773-db-hero-eyebrow,
		.ap773-template-statistics .ap773-db-hero-eyebrow,
		.ap773-template-welcome .ap773-db-hero-eyebrow {
			font-size: 11px;
			margin-bottom: 7px;
		}

		.ap773-template-tutorial .ap773-db-hero-icon,
		.ap773-template-statistics .ap773-db-hero-icon,
		.ap773-template-welcome .ap773-db-hero-icon {
			border-radius: 18px;
			flex-basis: 64px;
			height: 64px;
			width: 64px;
		}

		.ap773-template-tutorial .ap773-db-panel,
		.ap773-template-statistics .ap773-db-panel,
		.ap773-template-welcome .ap773-db-panel {
			border-radius: 14px;
			box-shadow: 0 12px 30px rgba(15, 23, 42, .055);
			padding: 16px;
		}

		.ap773-template-tutorial .ap773-db-panel-title,
		.ap773-template-statistics .ap773-db-panel-title,
		.ap773-template-welcome .ap773-db-panel-title {
			font-size: 13px;
			margin-bottom: 12px;
		}

		.ap773-template-tutorial .ap773-db-link-list,
		.ap773-template-tutorial .ap773-db-checklist,
		.ap773-template-statistics .ap773-db-link-list,
		.ap773-template-statistics .ap773-db-checklist,
		.ap773-template-welcome .ap773-db-link-list,
		.ap773-template-welcome .ap773-db-checklist {
			gap: 8px;
		}

		.ap773-template-tutorial .ap773-db-link-item,
		.ap773-template-tutorial .ap773-db-check-item,
		.ap773-template-statistics .ap773-db-link-item,
		.ap773-template-statistics .ap773-db-check-item,
		.ap773-template-welcome .ap773-db-link-item,
		.ap773-template-welcome .ap773-db-check-item {
			border-radius: 11px;
			font-size: 12px;
			min-height: 36px;
			padding: 8px 10px;
		}

		.ap773-template-tutorial .ap773-db-item-icon,
		.ap773-template-statistics .ap773-db-item-icon,
		.ap773-template-welcome .ap773-db-item-icon {
			border-radius: 9px;
			flex-basis: 26px;
			height: 26px;
			width: 26px;
		}

		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video {
			background: #fff;
			border: 1px solid rgba(148,163,184,.16);
			border-radius: 14px;
			box-shadow: 0 14px 32px rgba(15,23,42,.055);
			padding: 16px;
			position: relative;
		}

		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video:before {
			content: "Video Tutorials";
			color: #0f172a;
			display: block;
			font-size: 14px;
			font-weight: 900;
			grid-column: 1 / -1;
			letter-spacing: -.02em;
			line-height: 1;
			margin: 0 0 2px;
		}

		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video:after {
			content: "View all videos →";
			color: #7c3aed;
			font-size: 11px;
			font-weight: 800;
			position: absolute;
			right: 18px;
			top: 16px;
		}

		.ap773-template-tutorial .ap773-db-video--thumb {
			background: transparent;
			border: 0;
			box-shadow: none;
			color: #0f172a;
			display: block;
			text-decoration: none;
		}

		.ap773-template-tutorial .ap773-db-video-thumb {
			aspect-ratio: 16 / 9;
			background-position: center;
			background-size: cover;
			border-radius: 10px;
			display: block;
			overflow: hidden;
			position: relative;
		}

		.ap773-template-tutorial .ap773-db-video-thumb:before {
			background: rgba(124,58,237,.33);
			content: "";
			inset: 0;
			position: absolute;
		}

		.ap773-template-tutorial .ap773-db-video-play {
			align-items: center;
			background: #7c3aed;
			border-radius: 999px;
			box-shadow: 0 10px 24px rgba(76,29,149,.25);
			color: #fff;
			display: flex;
			font-size: 15px;
			height: 42px;
			justify-content: center;
			left: 50%;
			line-height: 1;
			position: absolute;
			top: 50%;
			transform: translate(-50%, -50%);
			width: 42px;
		}

		.ap773-template-tutorial .ap773-db-video-meta {
			align-items: center;
			display: flex;
			gap: 8px;
			justify-content: space-between;
			padding: 8px 2px 0;
		}

		.ap773-template-tutorial .ap773-db-video-title,
		.ap773-template-tutorial .ap773-db-video-duration {
			font-size: 12px;
			font-weight: 800;
		}

		.ap773-template-tutorial .ap773-db-video-duration { color: #64748b; font-weight: 700; }

		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_cards .ap773-db-block--link_list,
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_cards .ap773-db-block--checklist,
		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_cards .ap773-db-block,
		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_status .ap773-db-block,
		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_main .ap773-db-block,
		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_content .ap773-db-block,
		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_footer .ap773-db-block {
			grid-column: span 6 !important;
		}

		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_counters .ap773-db-stats {
			grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
			gap: 12px !important;
		}

		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_counters .ap773-db-stat {
			min-height: 92px;
			padding: 16px 18px;
		}

		.ap773-template-statistics .ap773-db-stat-n { font-size: 30px !important; }
		.ap773-template-statistics .ap773-db-stat-l { font-size: 12px; }

		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_links_row .ap773-db-link-list {
			grid-template-columns: repeat(4, minmax(0, 1fr));
		}

		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_links_row .ap773-db-link-item {
			min-height: 44px;
		}

		.ap773-template-welcome .ap773-db-block--id-pnlrdb_tpl_welcome_help .ap773-db-hero {
			background: #fff;
			border-color: rgba(148,163,184,.18);
			box-shadow: 0 12px 30px rgba(15,23,42,.055);
			color: #0f172a;
			min-height: 100%;
		}

		.ap773-template-welcome .ap773-db-block--id-pnlrdb_tpl_welcome_help .ap773-db-hero:before,
		.ap773-template-welcome .ap773-db-block--id-pnlrdb_tpl_welcome_help .ap773-db-hero:after { display: none; }
		.ap773-template-welcome .ap773-db-block--id-pnlrdb_tpl_welcome_help .ap773-db-hero-icon { color: #16a34a; background: #dcfce7; border-color: #bbf7d0; }

		.ap773-template-welcome .ap773-db-actions-grid {
			grid-template-columns: repeat(2, minmax(0, 1fr));
			gap: 14px;
		}

		.ap773-template-welcome .ap773-db-action-card {
			background: linear-gradient(180deg,#fbfdff,#f8fafc);
			border: 1px solid rgba(148,163,184,.24);
			border-radius: 16px;
			box-shadow: 0 14px 32px rgba(15,23,42,.06);
			font-size: 13px;
			min-height: 96px;
			padding: 16px 12px;
		}

		.ap773-template-welcome .ap773-db-action-icon {
			background: rgba(99,102,241,.08);
			border-radius: 16px;
			color: inherit;
			font-size: 24px;
			height: 46px;
			width: 46px;
		}

		.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_tip .ap773-db-hero {
			min-height: 92px;
		}

		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_support .ap773-db-hero {
			min-height: 88px;
		}


		/* Panelra 1.1.0 — final template alignment pass: wider premium shell, configurable video section header, richer cards. */
		#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-tutorial,
		#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-statistics,
		#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-welcome {
			background: #fff;
			border: 1px solid rgba(148,163,184,.16);
			border-radius: 24px;
			box-shadow: 0 28px 80px rgba(15,23,42,.09);
			box-sizing: border-box;
			gap: 16px;
			max-width: 1220px !important;
			padding: 26px;
		}

		#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-tutorial { max-width: 1160px !important; }
		#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-statistics { max-width: 1140px !important; }
		#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-welcome { max-width: 1120px !important; }

		.ap773-template-tutorial .ap773-db-section,
		.ap773-template-statistics .ap773-db-section,
		.ap773-template-welcome .ap773-db-section { gap: 16px !important; }

		.ap773-db-section-head {
			align-items: center;
			display: flex;
			grid-column: 1 / -1;
			justify-content: space-between;
			margin: 0 0 2px;
			min-width: 0;
		}
		.ap773-db-section-title { color:#0f172a; font-size:16px; font-weight:900; line-height:1.2; margin:0; }
		.ap773-db-section-cta { color:#6d28d9; font-size:12px; font-weight:800; text-decoration:none; white-space:nowrap; }
		.ap773-db-section-cta:hover { color:#4c1d95; text-decoration:underline; }

		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video {
			align-items:start;
			background:#fff;
			border:1px solid rgba(148,163,184,.16);
			border-radius:18px;
			box-shadow:0 18px 46px rgba(15,23,42,.07);
			box-sizing:border-box;
			padding:18px;
		}
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video:before,
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video:after { content:none !important; display:none !important; }
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video .ap773-db-block--video { grid-column: span 4 !important; }
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video .ap773-db-video-thumb { aspect-ratio: 16 / 9; }
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video .ap773-db-video-meta { padding:9px 2px 0; }

		.ap773-template-welcome .ap773-db-block--id-pnlrdb_tpl_welcome_help .ap773-db-hero {
			align-items:flex-start;
			background:#fff;
			border-color:rgba(148,163,184,.16);
			color:#0f172a;
			flex-direction:column;
			justify-content:flex-start;
			padding:22px 24px;
		}
		.ap773-template-welcome .ap773-db-block--id-pnlrdb_tpl_welcome_help .ap773-db-hero-content { max-width:100%; }
		.ap773-template-welcome .ap773-db-block--id-pnlrdb_tpl_welcome_help .ap773-db-hero-title { color:#0f172a!important; font-size:20px; }
		.ap773-template-welcome .ap773-db-block--id-pnlrdb_tpl_welcome_help .ap773-db-hero-text { color:#334155!important; font-size:14px; font-weight:600; max-width:340px; }
		.ap773-template-welcome .ap773-db-block--id-pnlrdb_tpl_welcome_help .ap773-db-hero-icon { position:absolute; right:24px; top:50%; transform:translateY(-50%); }
		.ap773-db-hero-actions { margin:16px 0 12px; }
		.ap773-db-hero-button { background:#16a34a; border:1px solid rgba(22,163,74,.24); border-radius:8px; box-shadow:0 10px 22px rgba(22,163,74,.18); color:#fff!important; display:inline-flex; font-weight:900; padding:9px 16px; text-decoration:none; }
		.ap773-db-hero-button:hover { background:#15803d; color:#fff!important; transform:translateY(-1px); }
		.ap773-db-hero-contact { color:#334155; display:flex; flex-direction:column; gap:8px; font-size:13px; font-weight:700; }
		.ap773-db-hero-contact span { display:block; }

		.ap773-template-welcome .ap773-db-actions-panel { min-height: 214px; }
		.ap773-template-welcome .ap773-db-actions-grid { align-items:center; grid-template-columns: repeat(4,minmax(0,1fr)); height: calc(100% - 34px); }
		.ap773-template-welcome .ap773-db-action-card { min-height:116px; padding:14px 8px; }
		.ap773-template-welcome .ap773-db-action-icon { font-size:24px; height:48px; width:48px; }

		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_counters .ap773-db-stats { grid-template-columns: repeat(4,minmax(0,1fr)) !important; }
		.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_counters .ap773-db-stat {
			min-height:112px;
			padding:18px 20px 16px;
		}
		.ap773-template-statistics .ap773-db-stat-l { color:#1e3a8a; font-size:13px; font-weight:900; margin:0 0 8px; }
		.ap773-template-statistics .ap773-db-stat-n { color:#020617; font-size:34px !important; margin:0 0 10px; }
		.ap773-db-stat-a { color:#334155; display:block; font-size:12px; font-weight:800; position:relative; z-index:1; }
		.ap773-db-stat-icon { align-items:center; border-radius:14px; display:flex; height:42px; justify-content:center; position:absolute; right:16px; top:16px; width:42px; z-index:1; }
		.ap773-db-stat-icon svg { height:23px; width:23px; }
		.ap773-db-stat--post .ap773-db-stat-icon { background:#dbeafe; color:#2563eb; }
		.ap773-db-stat--page .ap773-db-stat-icon { background:#dcfce7; color:#16a34a; }
		.ap773-db-stat--comment .ap773-db-stat-icon { background:#f3e8ff; color:#7c3aed; }
		.ap773-db-stat--user .ap773-db-stat-icon { background:#fef3c7; color:#d97706; }
		.ap773-db-stat--media .ap773-db-stat-icon { background:#cffafe; color:#0891b2; }
		.ap773-db-stat:before { display:none !important; }

		.ap773-template-tutorial .ap773-db-link-item,
		.ap773-template-tutorial .ap773-db-check-item,
		.ap773-template-statistics .ap773-db-link-item,
		.ap773-template-statistics .ap773-db-check-item,
		.ap773-template-welcome .ap773-db-link-item,
		.ap773-template-welcome .ap773-db-check-item { background:#fff; }

		@media (max-width: 1320px) {
			#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-tutorial,
			#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-statistics,
			#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-welcome { max-width: calc(100vw - 80px) !important; }
		}

		@media (max-width: 1200px) {
			#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-tutorial,
			#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-statistics,
			#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-welcome { max-width: 940px !important; }
		}

		@media (max-width: 1100px) {
			.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_counters .ap773-db-stats { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
			.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_links_row .ap773-db-link-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
		}


		.ap773-template-welcome .ap773-db-actions-grid { grid-template-columns: repeat(2,minmax(0,1fr)) !important; gap:14px !important; height:auto !important; }
		.ap773-template-welcome .ap773-db-action-card { background:linear-gradient(180deg,#fbfdff,#f8fafc) !important; border:1px solid rgba(148,163,184,.24) !important; border-radius:16px !important; box-shadow:0 14px 32px rgba(15,23,42,.06) !important; min-height:110px !important; padding:16px 12px !important; }
		.ap773-template-welcome .ap773-db-action-icon { background:rgba(99,102,241,.08) !important; border-radius:16px !important; font-size:26px !important; height:52px !important; width:52px !important; }
		.ap773-template-tutorial .ap773-db-section-title { font-size:22px; }
		.ap773-db-hero-visual img { filter: drop-shadow(0 22px 34px rgba(15,23,42,.16)); }
		@media (max-width: 782px) {
			.ap773-custom-dashboard .ap773-db-cols-2,
			.ap773-custom-dashboard .ap773-db-cols-3,
			.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_main,
			.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_content,
			.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_footer,
			.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_cards,
			.ap773-template-welcome .ap773-db-section--pnlrdb_tpl_welcome_status { grid-template-columns: 1fr; }
			.ap773-custom-dashboard .ap773-db-hero { align-items:flex-start; flex-direction:column; }
			.ap773-custom-dashboard .ap773-db-hero-title { font-size:22px; }
			.ap773-custom-dashboard .ap773-db-actions-grid { grid-template-columns: 1fr; }
			.ap773-custom-dashboard .ap773-db-stats { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
			.ap773-custom-dashboard .ap773-db-section--grid12 > .ap773-db-block { grid-column: 1 / -1 !important; }
			.ap773-template-statistics .ap773-db-section--pnlrdb_tpl_stats_links_row .ap773-db-link-list { grid-template-columns: 1fr; }
		}
';

		
		$pnlrdb_css .= '
		.ap773-db-block { border:none !important; box-shadow:0 2px 14px rgba(15,23,42,.04); border-radius:18px; }
		.ap773-db-panel-title, .ap773-db-heading { font-size:24px; font-weight:700; letter-spacing:-.02em; }
		.ap773-db-item-label { font-size:14px; font-weight:600; }
		.ap773-template-welcome .ap773-db-actions-grid { grid-template-columns:repeat(2,minmax(0,1fr)); gap:18px; }
		.ap773-template-welcome .ap773-db-action { min-height:120px; }
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video:before { content:"Video Tutorials"; font-size:28px; font-weight:700; color:#111827; display:block; margin-bottom:18px; }
		.ap773-db-video-title { font-size:18px !important; }
		.ap773-db-video-duration { font-size:13px !important; }
		.ap773-db-hero { position:relative; overflow:hidden; min-height:210px; }
		.ap773-db-hero:after { content:""; position:absolute; right:30px; bottom:0; width:260px; height:180px; opacity:.14; background-size:contain; background-repeat:no-repeat; background-position:center; }
		.ap773-template-tutorial .ap773-db-hero:after { background-image:none; }
		.ap773-template-welcome .ap773-db-hero:after { background-image:none; opacity:.18; }
		.ap773-template-statistics .ap773-db-hero:after { background-image:none; opacity:.15; }
		.ap773-template-welcome .ap773-db-panel-title,
		.ap773-template-statistics .ap773-db-panel-title,
		.ap773-template-tutorial .ap773-db-panel-title { margin-bottom:18px; }
		.ap773-template-welcome .ap773-db-check-item,
		.ap773-template-welcome .ap773-db-link-item,
		.ap773-template-welcome .ap773-db-action,
		.ap773-template-statistics .ap773-db-check-item,
		.ap773-template-statistics .ap773-db-link-item,
		.ap773-template-tutorial .ap773-db-check-item,
		.ap773-template-tutorial .ap773-db-link-item { border:none !important; box-shadow:0 1px 10px rgba(15,23,42,.04); }
		.ap773-video-modal { position:fixed; inset:0; background:rgba(2,6,23,.78); z-index:999999; display:none; align-items:center; justify-content:center; padding:40px; }
		.ap773-video-modal.is-open { display:flex; }
		.ap773-video-modal-inner { width:min(980px,100%); position:relative; }
		.ap773-video-modal-frame iframe { width:100%; aspect-ratio:16/9; border:none; border-radius:20px; }
		.ap773-video-modal-close { position:absolute; right:-12px; top:-12px; width:42px; height:42px; border:none; border-radius:999px; background:#fff; font-size:28px; cursor:pointer; }';


		$pnlrdb_css .= '
		/* Panelra template full-page refinement — remove sheet effect and use bundled hero images. */
		body.wp-admin.index-php,
		body.wp-admin.index-php #wpwrap,
		body.wp-admin.index-php #wpcontent,
		body.wp-admin.index-php #wpbody,
		body.wp-admin.index-php #wpbody-content { background:#f7f8fb !important; }
		#pnlrdb-dashboard-builder-page { margin: 28px 42px 0 24px; width:auto; background:transparent; }
		#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-tutorial,
		#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-statistics,
		#pnlrdb-dashboard-builder-page .ap773-custom-dashboard.ap773-template-welcome {
			background: transparent !important;
			border: 0 !important;
			border-radius: 0 !important;
			box-shadow: none !important;
			max-width: none !important;
			padding: 0 !important;
			width: 100% !important;
		}
		.ap773-template-tutorial .ap773-db-hero,
		.ap773-template-statistics .ap773-db-hero,
		.ap773-template-welcome .ap773-db-hero { min-height: 170px; padding: 30px 34px; }
		.ap773-db-hero-visual { align-items:flex-end; align-self:stretch; display:flex; flex:0 0 300px; justify-content:center; max-width:34%; position:relative; z-index:1; }
		.ap773-db-hero-visual img { display:block; height:100%; max-height:160px; max-width:100%; object-fit:contain; width:auto; }
		.ap773-template-tutorial .ap773-db-hero:after,
		.ap773-template-statistics .ap773-db-hero:after,
		.ap773-template-welcome .ap773-db-hero:after { background-image:none !important; }
		.ap773-template-tutorial .ap773-db-hero-icon,
		.ap773-template-statistics .ap773-db-hero-icon,
		.ap773-template-welcome .ap773-db-hero-icon { display:none; }
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video { padding:24px; }
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video .ap773-db-block--video { grid-column: span 4 !important; }
		.ap773-db-section-title { font-size:24px; text-transform:uppercase; letter-spacing:.02em; }
		.ap773-template-tutorial .ap773-db-video-meta { align-items:flex-start; gap:10px; }
		.ap773-db-video-copy { display:flex; flex-direction:column; gap:3px; min-width:0; text-align:left; }
		.ap773-db-video-subtitle { color:#64748b; display:block; font-size:12px; font-weight:700; line-height:1.35; }
		.ap773-template-welcome .ap773-db-block--id-pnlrdb_tpl_welcome_help .ap773-db-hero { gap:18px; justify-content:space-between; min-height:100%; padding:30px 34px; }
		.ap773-template-welcome .ap773-db-block--id-pnlrdb_tpl_welcome_help .ap773-db-hero-content { display:flex; flex-direction:column; gap:12px; }
		.ap773-template-welcome .ap773-db-block--id-pnlrdb_tpl_welcome_help .ap773-db-hero-text { line-height:1.8; }
		.ap773-template-welcome .ap773-db-block--id-pnlrdb_tpl_welcome_help .ap773-db-hero-actions { margin:10px 0 4px; }
		.ap773-template-welcome .ap773-db-actions-panel { min-height: 300px; }
		.ap773-template-welcome .ap773-db-actions-grid { grid-template-columns: repeat(2,minmax(0,1fr)); gap:24px; height:calc(100% - 46px); }
		.ap773-template-welcome .ap773-db-action-card { min-height:120px; padding:20px 12px; }
		.ap773-template-welcome .ap773-db-action-icon { border-radius:20px; font-size:34px; height:74px; width:74px; }

		.ap773-template-welcome .ap773-db-actions-grid { grid-template-columns: repeat(2,minmax(0,1fr)) !important; gap:14px !important; height:auto !important; }
		.ap773-template-welcome .ap773-db-action-card { background:linear-gradient(180deg,#fbfdff,#f8fafc) !important; border:1px solid rgba(148,163,184,.24) !important; border-radius:16px !important; box-shadow:0 14px 32px rgba(15,23,42,.06) !important; min-height:110px !important; padding:16px 12px !important; }
		.ap773-template-welcome .ap773-db-action-icon { background:rgba(99,102,241,.08) !important; border-radius:16px !important; font-size:26px !important; height:52px !important; width:52px !important; }
		.ap773-template-tutorial .ap773-db-section-title { font-size:22px; }
		.ap773-db-hero-visual img { filter: drop-shadow(0 22px 34px rgba(15,23,42,.16)); }
		@media (max-width: 782px) {
			#pnlrdb-dashboard-builder-page { margin: 20px 16px 0 12px; }
			.ap773-db-hero-visual { flex-basis:auto; max-width:100%; width:100%; }
			.ap773-db-hero-visual img { max-height:150px; }
			.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video .ap773-db-block--video { grid-column: 1 / -1 !important; }
		}
		';



		$pnlrdb_css .= '
		/* Panelra 1.1.x — tutorial video sizing and visible subtitles. */
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video {
			padding: 22px !important;
		}
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video .ap773-db-block--video {
			align-self: start !important;
		}
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video .ap773-db-video-thumb {
			aspect-ratio: auto !important;
			height: 168px !important;
			max-height: 168px !important;
		}
		.ap773-template-tutorial .ap773-db-video-meta {
			align-items: flex-start !important;
			background: transparent !important;
			border-top: 0 !important;
			display: flex !important;
			gap: 10px !important;
			justify-content: space-between !important;
			min-height: 48px !important;
			padding: 10px 2px 0 !important;
			width: 100% !important;
		}
		.ap773-template-tutorial .ap773-db-video-copy {
			display: flex !important;
			flex: 1 1 auto !important;
			flex-direction: column !important;
			gap: 4px !important;
			min-width: 0 !important;
			text-align: left !important;
		}
		.ap773-template-tutorial .ap773-db-video-title {
			color: #0f172a !important;
			display: block !important;
			font-size: 14px !important;
			font-weight: 900 !important;
			line-height: 1.25 !important;
		}
		.ap773-template-tutorial .ap773-db-video-subtitle {
			color: #64748b !important;
			display: block !important;
			font-size: 12px !important;
			font-weight: 700 !important;
			line-height: 1.35 !important;
			max-width: 100% !important;
		}
		.ap773-template-tutorial .ap773-db-video-duration {
			color: #64748b !important;
			display: block !important;
			font-size: 12px !important;
			font-weight: 800 !important;
			margin-top: 1px !important;
			white-space: nowrap !important;
		}
		@media (max-width: 1280px) {
			.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video .ap773-db-video-thumb { height: 150px !important; max-height:150px !important; }
		}
		@media (max-width: 782px) {
			.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video .ap773-db-video-thumb { height:auto !important; max-height:none !important; aspect-ratio:16/9 !important; }
		}
		';


		$pnlrdb_css .= '
		/* Panelra 1.1.x — remove preset heading blocks and open tutorial video section. */
		.ap773-template-tutorial .ap773-db-block--id-pnlrdb_tpl_tutorial_heading,
		.ap773-template-statistics .ap773-db-block--id-pnlrdb_tpl_stats_heading,
		.ap773-template-welcome .ap773-db-block--id-pnlrdb_tpl_welcome_heading {
			display: none !important;
		}
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video {
			background: transparent !important;
			border: 0 !important;
			box-shadow: none !important;
			border-radius: 0 !important;
			padding: 14px 0 8px !important;
			gap: 18px !important;
		}
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video:before,
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video:after {
			content: none !important;
			display: none !important;
		}
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video .ap773-db-section-head {
			grid-column: 1 / -1 !important;
			margin: 0 0 -2px !important;
			padding: 0 2px !important;
		}
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video .ap773-db-block--video {
			background: transparent !important;
			box-shadow: none !important;
			padding: 0 !important;
		}
		.ap773-template-tutorial .ap773-db-video--thumb {
			background: rgba(255,255,255,.78) !important;
			border: 0 !important;
			border-radius: 18px !important;
			box-shadow: 0 16px 34px rgba(15,23,42,.07) !important;
			overflow: hidden !important;
			padding: 0 0 12px !important;
		}
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video .ap773-db-video-thumb {
			aspect-ratio: 16 / 9 !important;
			background-position: center center !important;
			background-size: cover !important;
			border-radius: 18px 18px 0 0 !important;
			height: auto !important;
			max-height: none !important;
			min-height: 0 !important;
		}
		.ap773-template-tutorial .ap773-db-video-meta {
			padding: 12px 4px 0 !important;
		}
		@media (min-width: 783px) {
			.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video {
				align-items: start !important;
			}
			.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video .ap773-db-block--video {
				grid-column: span 4 !important;
			}
		}
		';



		$pnlrdb_css .= '
		/* Panelra 1.1.x — definitive tutorial video card fix. */
		.ap773-template-tutorial .ap773-db-section--pnlrdb_tpl_tutorial_video .ap773-db-block--video { overflow: visible !important; }
		.ap773-template-tutorial .ap773-db-video--thumb {
			display: flex !important;
			flex-direction: column !important;
			height: auto !important;
			min-height: 0 !important;
			overflow: visible !important;
			text-decoration: none !important;
		}
		.ap773-template-tutorial .ap773-db-video-thumb {
			align-items: center !important;
			aspect-ratio: 16 / 9 !important;
			background: #0f172a !important;
			border-radius: 18px !important;
			display: flex !important;
			height: auto !important;
			justify-content: center !important;
			max-height: none !important;
			min-height: 0 !important;
			overflow: hidden !important;
			position: relative !important;
			width: 100% !important;
		}
		.ap773-template-tutorial .ap773-db-video-thumb img {
			display: block !important;
			height: 100% !important;
			object-fit: contain !important;
			width: 100% !important;
		}
		.ap773-template-tutorial .ap773-db-video-meta {
			display: flex !important;
			flex: 0 0 auto !important;
			gap: 10px !important;
			justify-content: space-between !important;
			overflow: visible !important;
			padding: 10px 2px 0 !important;
			position: static !important;
			visibility: visible !important;
		}
		.ap773-template-tutorial .ap773-db-video-title,
		.ap773-template-tutorial .ap773-db-video-subtitle,
		.ap773-template-tutorial .ap773-db-video-duration { display: block !important; opacity: 1 !important; visibility: visible !important; }
		';


		$pnlrdb_css .= '
		/* Panelra 1.1.x — final tutorial video spacing and thumbnail ratio fix. */
		.ap773-template-tutorial .ap773-db-video--thumb {
			box-sizing: border-box !important;
			overflow: hidden !important;
			padding: 0 0 14px !important;
		}
		.ap773-template-tutorial .ap773-db-video-thumb {
			aspect-ratio: 16 / 9 !important;
			background: transparent !important;
			border-radius: 18px 18px 0 0 !important;
			display: block !important;
			height: auto !important;
			max-height: none !important;
			min-height: 0 !important;
			overflow: hidden !important;
			width: 100% !important;
		}
		.ap773-template-tutorial .ap773-db-video-thumb img {
			display: block !important;
			height: 100% !important;
			object-fit: cover !important;
			object-position: center center !important;
			width: 100% !important;
		}
		.ap773-template-tutorial .ap773-db-video-meta {
			box-sizing: border-box !important;
			padding: 12px 16px 0 !important;
		}
		.ap773-template-tutorial .ap773-db-video-copy {
			padding-right: 10px !important;
		}
		.ap773-template-tutorial .ap773-db-video-duration {
			padding-left: 8px !important;
		}
		';


		$pnlrdb_css .= '
		/* Panelra first-run dashboard template picker. */
		.ap773-template-picker-dashboard {
			background: transparent !important;
			border: 0 !important;
			box-shadow: none !important;
			max-width: 1180px;
			padding: 0 !important;
		}
		.ap773-template-picker-hero {
			align-items: center;
			background: #fff;
			border: 1px solid rgba(148,163,184,.22);
			border-radius: 22px;
			box-shadow: 0 20px 48px rgba(15,23,42,.06);
			display: flex;
			gap: 24px;
			justify-content: space-between;
			margin-bottom: 20px;
			padding: 28px 30px;
		}
		.ap773-template-picker-kicker {
			color: #6366f1;
			display: block;
			font-size: 12px;
			font-weight: 900;
			letter-spacing: .08em;
			margin-bottom: 9px;
			text-transform: uppercase;
		}
		.ap773-template-picker-hero h2 {
			color: #0f172a;
			font-size: 28px;
			font-weight: 900;
			letter-spacing: -.04em;
			line-height: 1.08;
			margin: 0 0 10px;
		}
		.ap773-template-picker-hero p {
			color: #475569;
			font-size: 15px;
			font-weight: 600;
			line-height: 1.65;
			margin: 0;
			max-width: 720px;
		}
		.ap773-template-picker-classic {
			background: #f8fafc;
			border: 1px solid #e2e8f0;
			border-radius: 999px;
			color: #334155;
			font-size: 12px;
			font-weight: 800;
			padding: 10px 14px;
			text-decoration: none;
			white-space: nowrap;
		}
		.ap773-template-picker-classic:hover { background:#eef2ff; color:#4338ca; }
		.ap773-front-template-grid {
			display: grid;
			gap: 16px;
			grid-template-columns: repeat(4,minmax(0,1fr));
		}
		.ap773-front-template-card {
			background: #fff;
			border: 1px solid rgba(148,163,184,.22);
			border-radius: 22px;
			box-shadow: 0 18px 44px rgba(15,23,42,.06);
			display: flex;
			flex-direction: column;
			overflow: hidden;
			min-width: 0;
		}
		.ap773-front-template-preview {
			background: linear-gradient(135deg,#f8fafc,#eef2ff);
			border-bottom: 1px solid #e2e8f0;
			min-height: 168px;
			padding: 16px;
		}
		.ap773-front-template-card--green .ap773-front-template-preview { background: linear-gradient(135deg,#ecfdf5,#dcfce7); }
		.ap773-front-template-card--purple .ap773-front-template-preview { background: linear-gradient(135deg,#f5f3ff,#ede9fe); }
		.ap773-front-template-card--blue .ap773-front-template-preview { background: linear-gradient(135deg,#eff6ff,#dbeafe); }
		.ap773-front-preview-bar { display:flex; gap:6px; margin-bottom:12px; }
		.ap773-front-preview-bar span { background:rgba(255,255,255,.9); border-radius:999px; height:7px; width:26%; }
		.ap773-front-preview-bar span:nth-child(2){width:36%;}.ap773-front-preview-bar span:nth-child(3){width:18%;}
		.ap773-front-preview-hero { background:linear-gradient(135deg,#22c55e,#15803d); border-radius:14px; height:54px; margin-bottom:12px; }
		.ap773-front-template-preview--tutorial .ap773-front-preview-hero { background:linear-gradient(135deg,#8b5cf6,#6d28d9); }
		.ap773-front-template-preview--statistics .ap773-front-preview-hero { background:linear-gradient(135deg,#3b82f6,#2563eb); }
		.ap773-front-template-preview--from_scratch .ap773-front-preview-hero { background:linear-gradient(135deg,#dbeafe,#bfdbfe); }
		.ap773-front-preview-grid { display:grid; gap:8px; grid-template-columns:repeat(2,minmax(0,1fr)); }
		.ap773-front-preview-grid span { background:rgba(255,255,255,.88); border-radius:12px; height:34px; }
		.ap773-front-template-body { display:flex; flex:1; flex-direction:column; gap:9px; padding:18px; }
		.ap773-front-template-eyebrow { color:#64748b; font-size:11px; font-weight:900; letter-spacing:.07em; text-transform:uppercase; }
		.ap773-front-template-body h3 { color:#0f172a; font-size:18px; font-weight:900; letter-spacing:-.02em; line-height:1.2; margin:0; }
		.ap773-front-template-body p { color:#475569; font-size:13px; font-weight:600; line-height:1.55; margin:0; }
		.ap773-front-template-best { background:#f8fafc; border:1px solid #e2e8f0; border-radius:12px; color:#334155; font-size:12px; line-height:1.4; margin-top:auto; padding:9px 10px; }
		.ap773-front-template-button { align-items:center; display:flex !important; justify-content:center; min-height:38px; width:100%; }
		.ap773-template-picker-note { color:#64748b; font-size:13px; font-weight:600; margin:18px 4px 0; }
		@media (max-width: 1320px) { .ap773-front-template-grid { grid-template-columns: repeat(2,minmax(0,1fr)); } }
		@media (max-width: 782px) { .ap773-template-picker-hero { align-items:flex-start; flex-direction:column; } .ap773-front-template-grid { grid-template-columns: 1fr; } .ap773-template-picker-classic { white-space:normal; } }
		';

		wp_add_inline_style( 'pnlrdb-dashboard', $pnlrdb_css );

		wp_add_inline_script( 'jquery-core', 'document.addEventListener("click",function(e){const t=e.target.closest(".ap773-video-popup-trigger");if(t){e.preventDefault();const m=document.getElementById("ap773-video-modal");const f=m.querySelector(".ap773-video-modal-frame");let u=t.dataset.videoUrl||"";if(u.includes("watch?v=")){u=u.replace("watch?v=","embed/");}f.innerHTML=`<iframe src="${u}?autoplay=1" allowfullscreen allow="autoplay"></iframe>`;m.classList.add("is-open");}if(e.target.closest(".ap773-video-modal-close")||e.target.classList.contains("ap773-video-modal")){const m=document.getElementById("ap773-video-modal");if(m){m.classList.remove("is-open");m.querySelector(".ap773-video-modal-frame").innerHTML="";}}});' );

	}

	/* ------------------------------------------------------------------
	 * Render dashboard output
	 * ---------------------------------------------------------------- */

	/**
	 * Print the full-width builder container directly on the Dashboard page.
	 *
	 * @return void
	 */
	public function render_full_dashboard_container() {
		if ( ! function_exists( 'get_current_screen' ) ) {
			return;
		}

		$screen = get_current_screen();
		$layout = self::get_layout();

		if ( ! $screen || 'dashboard' !== $screen->base || empty( $layout['enabled'] ) ) {
			return;
		}

		$is_preview = isset( $_GET['ap773_preview'] ) && '1' === sanitize_key( wp_unslash( $_GET['ap773_preview'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended

		if ( $is_preview ) {
			$builder_url = admin_url( 'admin.php?page=pnlrdb-settings&tab=dashboard' );

			echo '<div id="ap773-preview-bar">';
			echo '<span>&#128065; ' . esc_html__( 'Dashboard Preview — this is how it looks to your users.', 'panelra-dashboard-builder' ) . '</span>';
			echo '<a href="' . esc_url( $builder_url ) . '">&larr; ' . esc_html__( 'Back to Builder', 'panelra-dashboard-builder' ) . '</a>';
			echo '</div>';

			add_filter(
				'admin_body_class',
				static function( $classes ) {
					return $classes . ' ap773-preview-mode';
				}
			);
		}

		echo '<div id="pnlrdb-dashboard-builder-page" class="wrap">';

		if ( empty( $layout['hide_title'] ) ) {
			echo '<h1 class="ap773-dashboard-title">' . esc_html__( 'Dashboard', 'panelra-dashboard-builder' ) . '</h1>';
		}

		$this->render_dashboard();
		echo '</div>';
		echo '<div class="ap773-video-modal" id="ap773-video-modal"><div class="ap773-video-modal-inner"><button type="button" class="ap773-video-modal-close">×</button><div class="ap773-video-modal-frame"></div></div></div>';
	}


	/**
	 * Render the first-run template picker directly on the WordPress dashboard.
	 *
	 * @return void
	 */
	private function render_template_picker_dashboard() {
		$templates   = self::get_dashboard_templates();
		$builder_url = admin_url( 'admin.php?page=pnlrdb-settings&tab=dashboard' );
		$classic_url = wp_nonce_url( admin_url( 'admin-post.php?action=pnlrdb_disable_custom_dashboard' ), 'pnlrdb_disable_custom_dashboard' );
		$order       = array( 'welcome', 'statistics', 'tutorial', 'from_scratch' );

		echo '<div class="ap773-custom-dashboard ap773-empty-dashboard ap773-template-picker-dashboard">';
		echo '<div class="ap773-template-picker-hero">';
		echo '<div>';
		echo '<span class="ap773-template-picker-kicker">' . esc_html__( 'Panelra Dashboard Builder', 'panelra-dashboard-builder' ) . '</span>';
		echo '<h2>' . esc_html__( 'Choose how your new dashboard should look.', 'panelra-dashboard-builder' ) . '</h2>';
		echo '<p>' . esc_html__( 'Start with a ready-made dashboard template, preview the style, then customize every block from the Dashboard Builder.', 'panelra-dashboard-builder' ) . '</p>';
		echo '</div>';
		echo '<a class="ap773-template-picker-classic" href="' . esc_url( $classic_url ) . '">' . esc_html__( 'Return to the classic WordPress dashboard', 'panelra-dashboard-builder' ) . '</a>';
		echo '</div>';

		echo '<div class="ap773-front-template-grid">';

		foreach ( $order as $template_id ) {
			if ( ! isset( $templates[ $template_id ] ) ) {
				continue;
			}

			$template  = $templates[ $template_id ];
			$accent    = isset( $template['accent'] ) ? sanitize_html_class( $template['accent'] ) : 'blue';
			$name      = isset( $template['name'] ) ? $template['name'] : '';
			$eyebrow   = isset( $template['eyebrow'] ) ? $template['eyebrow'] : '';
			$desc      = isset( $template['description'] ) ? $template['description'] : '';
			$best_for  = isset( $template['best_for'] ) ? $template['best_for'] : '';
			$apply_url = wp_nonce_url( admin_url( 'admin-post.php?action=pnlrdb_apply_dashboard_template&template=' . rawurlencode( $template_id ) ), 'pnlrdb_apply_dashboard_template' );
			$button_label = __( 'Use this template', 'panelra-dashboard-builder' );

			if ( 'from_scratch' === $template_id ) {
				$apply_url    = $builder_url;
				$button_label = __( 'Start from scratch', 'panelra-dashboard-builder' );
			}

			echo '<div class="ap773-front-template-card ap773-front-template-card--' . esc_attr( $accent ) . '">';
			echo '<div class="ap773-front-template-preview ap773-front-template-preview--' . esc_attr( $template_id ) . '">';
			echo '<div class="ap773-front-preview-bar"><span></span><span></span><span></span></div>';
			echo '<div class="ap773-front-preview-hero"></div>';
			echo '<div class="ap773-front-preview-grid"><span></span><span></span><span></span><span></span></div>';
			echo '</div>';
			echo '<div class="ap773-front-template-body">';
			echo '<span class="ap773-front-template-eyebrow">' . esc_html( $eyebrow ) . '</span>';
			echo '<h3>' . esc_html( $name ) . '</h3>';
			echo '<p>' . esc_html( $desc ) . '</p>';
			echo '<div class="ap773-front-template-best"><strong>' . esc_html__( 'Best for:', 'panelra-dashboard-builder' ) . '</strong> ' . esc_html( $best_for ) . '</div>';
			echo '<a class="button button-primary ap773-front-template-button" href="' . esc_url( $apply_url ) . '">' . esc_html( $button_label ) . '</a>';
			echo '</div>';
			echo '</div>';
		}

		echo '</div>';
		echo '<p class="ap773-template-picker-note">' . esc_html__( 'Prefer the traditional WordPress dashboard? You can switch back anytime from Panelra → Dashboard Builder.', 'panelra-dashboard-builder' ) . '</p>';
		echo '</div>';
	}


	/**
	 * Infer a template class from known bundled template section IDs.
	 *
	 * @param array $sections Saved dashboard sections.
	 * @return string
	 */
	private function get_template_class_from_sections( $sections ) {
		if ( empty( $sections ) || ! is_array( $sections ) ) {
			return '';
		}

		foreach ( $sections as $section ) {
			$id = isset( $section['id'] ) ? (string) $section['id'] : '';

			if ( false !== strpos( $id, 'pnlrdb_tpl_tutorial_' ) ) {
				return 'ap773-template-tutorial';
			}

			if ( false !== strpos( $id, 'pnlrdb_tpl_stats_' ) ) {
				return 'ap773-template-statistics';
			}

			if ( false !== strpos( $id, 'pnlrdb_tpl_welcome_' ) ) {
				return 'ap773-template-welcome';
			}
		}

		return '';
	}

	/**
	 * Render the full custom dashboard (all sections).
	 *
	 * @return void
	 */
	public function render_dashboard() {
		$layout = self::get_layout();
		$user   = wp_get_current_user();
		$roles  = (array) $user->roles;

		if ( empty( $layout['sections'] ) || ! is_array( $layout['sections'] ) ) {
			$this->render_template_picker_dashboard();
			return;
		}

		$pnlrdb_template_class = $this->get_template_class_from_sections( $layout['sections'] );

		echo '<div class="ap773-custom-dashboard ' . esc_attr( $pnlrdb_template_class ) . '">';

		foreach ( $layout['sections'] as $section ) {
			$pnlrdb_section_roles = isset( $section['roles'] ) ? $section['roles'] : array( 'all' );

			if ( ! $this->is_visible_for_roles( $pnlrdb_section_roles, $roles ) ) {
				continue;
			}

			$cols = max( 1, min( 3, absint( isset( $section['cols'] ) ? $section['cols'] : 1 ) ) );

			$pnlrdb_section_id    = isset( $section['id'] ) ? sanitize_html_class( $section['id'] ) : '';
			$pnlrdb_section_class = $pnlrdb_section_id ? ' ap773-db-section--' . $pnlrdb_section_id : '';

			$pnlrdb_section_layout = isset( $section['layout'] ) && 'grid12' === $section['layout'] ? 'grid12' : 'columns';
			$pnlrdb_section_gap    = isset( $section['gap'] ) ? sanitize_html_class( $section['gap'] ) : 'normal';

			if ( 'grid12' === $pnlrdb_section_layout ) {
				echo '<div class="ap773-db-section ap773-db-section--grid12 ap773-db-section-gap--' . esc_attr( $pnlrdb_section_gap ) . esc_attr( $pnlrdb_section_class ) . '">';

				$this->render_section_header( $section );

				if ( ! empty( $section['blocks'] ) && is_array( $section['blocks'] ) ) {
					foreach ( $section['blocks'] as $block ) {
						$this->render_block( $block );
					}
				}

				echo '</div>';
				continue;
			}

			echo '<div class="ap773-db-section ap773-db-cols-' . esc_attr( $cols ) . ' ap773-db-section-gap--' . esc_attr( $pnlrdb_section_gap ) . esc_attr( $pnlrdb_section_class ) . '">';

			$this->render_section_header( $section );

			$by_col = array();

			if ( ! empty( $section['blocks'] ) && is_array( $section['blocks'] ) ) {
				foreach ( $section['blocks'] as $block ) {
					$col = absint( isset( $block['col'] ) ? $block['col'] : 0 );
					$by_col[ $col ][] = $block;
				}
			}

			for ( $col_index = 0; $col_index < $cols; $col_index++ ) {
				echo '<div class="ap773-db-col">';

				$col_blocks  = isset( $by_col[ $col_index ] ) ? $by_col[ $col_index ] : array();
				$text_types  = array( 'heading', 'text' );
				$in_text_grp = false;

				foreach ( $col_blocks as $idx => $block ) {
					$type    = sanitize_key( isset( $block['type'] ) ? $block['type'] : '' );
					$is_text = in_array( $type, $text_types, true );

					$next_is_text = false;

					for ( $j = $idx + 1; $j < count( $col_blocks ); $j++ ) {
						$next_type    = sanitize_key( isset( $col_blocks[ $j ]['type'] ) ? $col_blocks[ $j ]['type'] : '' );
						$next_is_text = in_array( $next_type, $text_types, true );
						break;
					}

					if ( $is_text && ! $in_text_grp ) {
						echo '<div class="ap773-db-text-group">';
						$in_text_grp = true;
					}

					if ( ! $is_text && $in_text_grp ) {
						echo '</div><!-- /.ap773-db-text-group -->';
						$in_text_grp = false;
					}

					$this->render_block( $block );

					if ( $is_text && $in_text_grp && ! $next_is_text ) {
						echo '</div><!-- /.ap773-db-text-group -->';
						$in_text_grp = false;
					}
				}

				if ( $in_text_grp ) {
					echo '</div><!-- /.ap773-db-text-group -->';
				}

				echo '</div>';
			}

			echo '</div>';
		}

		echo '</div>';
	}

	/**
	 * Render an optional section header used by premium preset sections.
	 *
	 * @param array $section Section data.
	 * @return void
	 */
	private function render_section_header( $section ) {
		$title     = isset( $section['title'] ) ? trim( (string) $section['title'] ) : '';
		$cta_label = isset( $section['cta_label'] ) ? trim( (string) $section['cta_label'] ) : '';
		$cta_url   = isset( $section['cta_url'] ) ? trim( (string) $section['cta_url'] ) : '';
		$section_id = isset( $section['id'] ) ? (string) $section['id'] : '';

		// Backward compatibility for layouts imported before section headers were saved.
		if ( '' === $title && 'pnlrdb_tpl_tutorial_video' === $section_id ) {
			$title = __( 'VIDEO TUTORIAL', 'panelra-dashboard-builder' );
		}
		if ( '' === $cta_label && 'pnlrdb_tpl_tutorial_video' === $section_id ) {
			$cta_label = __( 'View all videos →', 'panelra-dashboard-builder' );
			$cta_url   = 'https://www.youtube.com/@DavelabsWP';
		}

		if ( '' === $title && '' === $cta_label ) {
			return;
		}

		echo '<div class="ap773-db-section-head">';
		if ( '' !== $title ) {
			echo '<h2 class="ap773-db-section-title">' . esc_html( $title ) . '</h2>';
		}
		if ( '' !== $cta_label && '' !== $cta_url ) {
			echo '<a class="ap773-db-section-cta" href="' . esc_url( $cta_url ) . '" target="_blank" rel="noopener noreferrer">' . esc_html( $cta_label ) . '</a>';
		}
		echo '</div>';
	}

	/**
	 * Render a single block.
	 *
	 * @param array $block Block array from the layout.
	 * @return void
	 */
	private function render_block( $block ) {
		$type = sanitize_key( isset( $block['type'] ) ? $block['type'] : '' );
		$data = ( isset( $block['data'] ) && is_array( $block['data'] ) ) ? $block['data'] : array();
		$block_id_class = isset( $block['id'] ) ? ' ap773-db-block--id-' . sanitize_html_class( $block['id'] ) : '';
		$block_span     = max( 1, min( 12, absint( isset( $block['span'] ) ? $block['span'] : 12 ) ) );

		echo '<div class="ap773-db-block ap773-db-block--' . esc_attr( $type ) . ' ap773-db-span-' . esc_attr( $block_span ) . esc_attr( $block_id_class ) . '">';

		switch ( $type ) {
			case 'heading':
				$allowed_heading_tags = array( 'h1', 'h2', 'h3', 'h4' );
				$tag                  = isset( $data['level'] ) && in_array( $data['level'], $allowed_heading_tags, true ) ? $data['level'] : 'h2';
				$align                = isset( $data['align'] ) && in_array( $data['align'], array( 'left', 'center', 'right' ), true ) ? $data['align'] : 'left';
				$text                 = isset( $data['text'] ) ? $data['text'] : '';

				printf(
					'<%1$s class="ap773-db-heading" style="text-align:%2$s">%3$s</%1$s>',
					tag_escape( $tag ),
					esc_attr( $align ),
					esc_html( $text )
				);
				break;

			case 'text':
				$align_t = isset( $data['align'] ) && in_array( $data['align'], array( 'left', 'center', 'right' ), true ) ? $data['align'] : 'left';
				$content = isset( $data['content'] ) ? $data['content'] : '';

				printf(
					'<div class="ap773-db-text" style="text-align:%1$s">%2$s</div>',
					esc_attr( $align_t ),
					wp_kses_post( wpautop( $content ) )
				);
				break;

			case 'button':
				$url       = isset( $data['url'] ) ? $data['url'] : '#';
				$label     = isset( $data['label'] ) && '' !== $data['label'] ? $data['label'] : __( 'Click here', 'panelra-dashboard-builder' );
				$style     = isset( $data['style'] ) && in_array( $data['style'], array( 'primary', 'secondary', 'link' ), true ) ? $data['style'] : 'primary';
				$align_btn = isset( $data['align'] ) && in_array( $data['align'], array( 'left', 'center', 'right' ), true ) ? $data['align'] : 'left';
				$new_tab   = ! empty( $data['new_tab'] );

				printf(
					'<div class="ap773-db-button-wrap" style="text-align:%1$s">',
					esc_attr( $align_btn )
				);

				printf(
					'<a href="%1$s" class="ap773-db-btn ap773-db-btn--%2$s"%3$s>%4$s</a>',
					esc_url( $url ),
					esc_attr( $style ),
					$new_tab ? ' target="_blank" rel="noopener noreferrer"' : '',
					esc_html( $label )
				);

				echo '</div>';
				break;

			case 'image':
				$src       = isset( $data['url'] ) ? $data['url'] : '';
				$alt       = isset( $data['alt'] ) ? $data['alt'] : '';
				$align_img = isset( $data['align'] ) && in_array( $data['align'], array( 'left', 'center', 'right' ), true ) ? $data['align'] : 'left';
				$caption   = isset( $data['caption'] ) ? $data['caption'] : '';

				if ( ! empty( $src ) ) {
					printf(
						'<div class="ap773-db-image" style="text-align:%1$s">',
						esc_attr( $align_img )
					);

					printf(
						'<img src="%1$s" alt="%2$s" style="max-width:100%%;height:auto;border-radius:6px;display:inline-block;" />',
						esc_url( $src ),
						esc_attr( $alt )
					);

					if ( '' !== $caption ) {
						printf(
							'<p class="ap773-db-caption" style="text-align:%1$s">%2$s</p>',
							esc_attr( $align_img ),
							esc_html( $caption )
						);
					}

					echo '</div>';
				}
				break;

			case 'divider':
				echo '<hr class="ap773-db-divider">';
				break;

			case 'video':
				$url       = isset( $data['url'] ) ? $data['url'] : '';
				$align_vid = isset( $data['align'] ) && in_array( $data['align'], array( 'left', 'center', 'right' ), true ) ? $data['align'] : 'left';

				if ( $url ) {
					$video_title    = isset( $data['title'] ) ? trim( (string) $data['title'] ) : '';
					$video_duration = isset( $data['duration'] ) ? trim( (string) $data['duration'] ) : '';
					$video_subtitle = isset( $data['subtitle'] ) ? trim( (string) $data['subtitle'] ) : '';
					$video_block_id = isset( $block['id'] ) ? (string) $block['id'] : '';

					// Backward compatibility for tutorial blocks imported before title/subtitle/duration fields existed.
					if ( false !== strpos( $video_block_id, 'tutorial_video1' ) ) {
						if ( '' === $video_title ) {
							$video_title = __( 'Getting Started', 'panelra-dashboard-builder' );
						}
						if ( '' === $video_subtitle ) {
							$video_subtitle = __( 'Learn the basics and discover your new dashboard.', 'panelra-dashboard-builder' );
						}
						if ( '' === $video_duration ) {
							$video_duration = __( '3:45', 'panelra-dashboard-builder' );
						}
					} elseif ( false !== strpos( $video_block_id, 'tutorial_video2' ) ) {
						if ( '' === $video_title ) {
							$video_title = __( 'Edit Pages', 'panelra-dashboard-builder' );
						}
						if ( '' === $video_subtitle ) {
							$video_subtitle = __( 'Update your pages quickly and safely.', 'panelra-dashboard-builder' );
						}
						if ( '' === $video_duration ) {
							$video_duration = __( '4:21', 'panelra-dashboard-builder' );
						}
					} elseif ( false !== strpos( $video_block_id, 'tutorial_video3' ) ) {
						if ( '' === $video_title ) {
							$video_title = __( 'Create a Blog Post', 'panelra-dashboard-builder' );
						}
						if ( '' === $video_subtitle ) {
							$video_subtitle = __( 'Publish fresh content without confusion.', 'panelra-dashboard-builder' );
						}
						if ( '' === $video_duration ) {
							$video_duration = __( '5:12', 'panelra-dashboard-builder' );
						}
					}

					$thumbnail      = $this->get_video_thumbnail_url( $url );

					if ( '' !== $video_title && $thumbnail ) {
						echo '<div class="ap773-db-video ap773-db-video--thumb" style="text-align:' . esc_attr( $align_vid ) . '">';
						echo '<a class="ap773-db-video-thumb ap773-video-popup-trigger" href="#" data-video-url="' . esc_attr( $url ) . '">';
						echo '<img src="' . esc_url( $thumbnail ) . '" alt="' . esc_attr( $video_title ) . '" loading="lazy" />';
						echo '<span class="ap773-db-video-play">▶</span></a>';
						echo '<div class="ap773-db-video-meta">';
						echo '<span class="ap773-db-video-copy"><span class="ap773-db-video-title">' . esc_html( $video_title ) . '</span>';
						if ( '' !== $video_subtitle ) {
							echo '<span class="ap773-db-video-subtitle">' . esc_html( $video_subtitle ) . '</span>';
						}
						echo '</span>';
						if ( '' !== $video_duration ) {
							echo '<span class="ap773-db-video-duration">' . esc_html( $video_duration ) . '</span>';
						}
						echo '</div></div>';
					} else {
						$embed = wp_oembed_get( esc_url( $url ), array( 'width' => 800 ) );

						if ( $embed ) {
							printf(
								'<div class="ap773-db-video" style="text-align:%1$s">',
								esc_attr( $align_vid )
							);

							// wp_oembed_get() returns trusted provider HTML (often an iframe).
							// Do not run it through wp_kses_post() or the iframe may be stripped.
							echo $embed; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
							echo '</div>';
						} else {
							printf(
								'<p class="ap773-db-text" style="text-align:%1$s"><a href="%2$s" target="_blank" rel="noopener noreferrer">%3$s</a></p>',
								esc_attr( $align_vid ),
								esc_url( $url ),
								esc_html( $url )
							);
						}
					}
				}
				break;

			case 'stats':
				$align_st = isset( $data['align'] ) && in_array( $data['align'], array( 'left', 'center', 'right' ), true ) ? $data['align'] : 'left';
				$this->render_stats_block( $data, $align_st );
				break;

			case 'hero':
				$this->render_hero_block( $data, $block );
				break;

			case 'link_list':
				$this->render_link_list_block( $data );
				break;

			case 'checklist':
				$this->render_checklist_block( $data );
				break;

			case 'quick_actions':
				$this->render_quick_actions_block( $data );
				break;

			default:
				/**
				 * Render a Pro (or third-party) block type.
				 *
				 * @param array $data  Block data.
				 * @param array $block Full block array.
				 */
				do_action( 'pnlrdb_render_builder_block_' . $type, $data, $block );
				break;
		}

		echo '</div>';
	}

	/**
	 * Render a visual hero card block.
	 *
	 * @param array $data Block data.
	 * @return void
	 */
	private function render_hero_block( $data, $block = array() ) {
		$eyebrow = isset( $data['eyebrow'] ) ? $data['eyebrow'] : '';
		$title   = isset( $data['title'] ) ? $data['title'] : '';
		$text    = isset( $data['content'] ) ? $data['content'] : '';
		$theme   = isset( $data['theme'] ) && in_array( $data['theme'], array( 'purple', 'blue', 'green', 'softgreen' ), true ) ? $data['theme'] : 'blue';
		$icon      = isset( $data['icon'] ) ? sanitize_key( $data['icon'] ) : 'spark';
		$image_url = isset( $data['image_url'] ) ? trim( (string) $data['image_url'] ) : '';
		$block_id  = isset( $block['id'] ) ? (string) $block['id'] : '';

		if ( '' === $image_url ) {
			$assets_url = trailingslashit( PNLRDB_PLUGIN_URL . 'assets' );
			if ( false !== strpos( $block_id, 'pnlrdb_tpl_tutorial_hero' ) ) {
				$image_url = $assets_url . 'tutorial.png';
			} elseif ( false !== strpos( $block_id, 'pnlrdb_tpl_stats_hero' ) ) {
				$image_url = $assets_url . 'statistiche.png';
			} elseif ( false !== strpos( $block_id, 'pnlrdb_tpl_welcome_hero' ) ) {
				$image_url = $assets_url . 'welcome.png';
			}
		}

		echo '<div class="ap773-db-hero ap773-db-hero--' . esc_attr( $theme ) . '">';
		echo '<div class="ap773-db-hero-content">';
		if ( '' !== $eyebrow ) {
			echo '<p class="ap773-db-hero-eyebrow">' . esc_html( $eyebrow ) . '</p>';
		}
		if ( '' !== $title ) {
			echo '<h2 class="ap773-db-hero-title">' . esc_html( $title ) . '</h2>';
		}
		if ( '' !== $text ) {
			echo '<p class="ap773-db-hero-text">' . wp_kses_post( $text ) . '</p>';
		}

		$button_label  = isset( $data['button_label'] ) ? trim( (string) $data['button_label'] ) : '';
		$button_url    = isset( $data['button_url'] ) ? trim( (string) $data['button_url'] ) : '';
		$support_email = isset( $data['support_email'] ) ? trim( (string) $data['support_email'] ) : '';
		$support_phone = isset( $data['support_phone'] ) ? trim( (string) $data['support_phone'] ) : '';

		if ( '' !== $button_label && '' !== $button_url ) {
			echo '<p class="ap773-db-hero-actions"><a class="ap773-db-hero-button" href="' . esc_url( $button_url ) . '">' . esc_html( $button_label ) . '</a></p>';
		}

		if ( '' !== $support_email || '' !== $support_phone ) {
			echo '<div class="ap773-db-hero-contact">';
			if ( '' !== $support_email ) {
				echo '<span>✉ ' . esc_html( $support_email ) . '</span>';
			}
			if ( '' !== $support_phone ) {
				echo '<span>☎ ' . esc_html( $support_phone ) . '</span>';
			}
			echo '</div>';
		}
		echo '</div>';
		if ( '' !== $image_url ) {
			echo '<div class="ap773-db-hero-visual" aria-hidden="true"><img src="' . esc_url( $image_url ) . '" alt="" /></div>';
		} else {
			echo '<div class="ap773-db-hero-icon" aria-hidden="true">' . $this->get_dashboard_icon_svg( $icon ) . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		}
		echo '</div>';
	}

	/**
	 * Render a list of links.
	 *
	 * @param array $data Block data.
	 * @return void
	 */
	private function render_link_list_block( $data ) {
		$title = isset( $data['title'] ) ? $data['title'] : '';
		$items = $this->parse_dashboard_items( $data );

		echo '<div class="ap773-db-panel ap773-db-link-panel">';
		if ( '' !== $title ) {
			echo '<h2 class="ap773-db-panel-title">' . esc_html( $title ) . '</h2>';
		}
		echo '<div class="ap773-db-link-list">';
		foreach ( $items as $item ) {
			$url = ! empty( $item['url'] ) ? $item['url'] : '#';
			echo '<a class="ap773-db-link-item" href="' . esc_url( $url ) . '">';
			echo '<span class="ap773-db-item-icon">' . esc_html( $item['icon'] ) . '</span>';
			echo '<span class="ap773-db-item-label">' . esc_html( $item['label'] ) . '</span>';
			echo '</a>';
		}
		echo '</div></div>';
	}

	/**
	 * Render a checklist/status block.
	 *
	 * @param array $data Block data.
	 * @return void
	 */
	private function render_checklist_block( $data ) {
		$title = isset( $data['title'] ) ? $data['title'] : '';
		$items = $this->parse_dashboard_items( $data );

		echo '<div class="ap773-db-panel ap773-db-check-panel">';
		if ( '' !== $title ) {
			echo '<h2 class="ap773-db-panel-title">' . esc_html( $title ) . '</h2>';
		}
		echo '<div class="ap773-db-checklist">';
		foreach ( $items as $item ) {
			echo '<div class="ap773-db-check-item">';
			echo '<span class="ap773-db-item-icon">' . esc_html( $item['icon'] ?: '✓' ) . '</span>';
			echo '<span class="ap773-db-item-label">' . esc_html( $item['label'] ) . '</span>';
			echo '<span class="ap773-db-check-mark">✓</span>';
			echo '</div>';
		}
		echo '</div></div>';
	}

	/**
	 * Render a quick actions grid.
	 *
	 * @param array $data Block data.
	 * @return void
	 */
	private function render_quick_actions_block( $data ) {
		$title = isset( $data['title'] ) ? $data['title'] : '';
		$items = $this->parse_dashboard_items( $data );

		echo '<div class="ap773-db-panel ap773-db-actions-panel">';
		if ( '' !== $title ) {
			echo '<h2 class="ap773-db-panel-title">' . esc_html( $title ) . '</h2>';
		}
		echo '<div class="ap773-db-actions-grid">';
		foreach ( $items as $item ) {
			$url = ! empty( $item['url'] ) ? $item['url'] : '#';
			echo '<a class="ap773-db-action-card" href="' . esc_url( $url ) . '">';
			echo '<span class="ap773-db-action-icon">' . esc_html( $item['icon'] ) . '</span>';
			echo '<span>' . esc_html( $item['label'] ) . '</span>';
			echo '</a>';
		}
		echo '</div></div>';
	}

	/**
	 * Parse textarea rows in the format icon|label|url.
	 *
	 * @param string $raw Raw items string.
	 * @return array
	 */
	private function parse_dashboard_items( $raw ) {
		$items = array();

		if ( is_array( $raw ) ) {
			if ( ! empty( $raw['items_data'] ) && is_array( $raw['items_data'] ) ) {
				foreach ( $raw['items_data'] as $item ) {
					if ( ! is_array( $item ) ) {
						continue;
					}

					$label = isset( $item['label'] ) ? trim( (string) $item['label'] ) : '';
					if ( '' === $label ) {
						continue;
					}

					$items[] = array(
						'icon'   => isset( $item['icon'] ) && '' !== trim( (string) $item['icon'] ) ? trim( (string) $item['icon'] ) : '•',
						'label'  => $label,
						'url'    => isset( $item['url'] ) ? (string) $item['url'] : '',
						'source' => isset( $item['source'] ) ? (string) $item['source'] : 'manual',
						'choice' => isset( $item['choice'] ) ? (string) $item['choice'] : '',
					);
				}

				return $items;
			}

			$raw = isset( $raw['items'] ) ? $raw['items'] : '';
		}

		$lines = preg_split( '/\r\n|\r|\n/', (string) $raw );

		foreach ( $lines as $line ) {
			$line = trim( $line );
			if ( '' === $line ) {
				continue;
			}

			$parts = array_map( 'trim', explode( '|', $line ) );
			if ( 1 === count( $parts ) ) {
				$items[] = array( 'icon' => '✓', 'label' => $parts[0], 'url' => '', 'source' => 'manual', 'choice' => '' );
			} else {
				$items[] = array(
					'icon'   => isset( $parts[0] ) && '' !== $parts[0] ? $parts[0] : '•',
					'label'  => isset( $parts[1] ) ? $parts[1] : '',
					'url'    => isset( $parts[2] ) ? $parts[2] : '',
					'source' => 'manual',
					'choice' => '',
				);
			}
		}

		return $items;
	}

	/**
	 * Return a thumbnail URL for supported video providers.
	 * Used only for the bundled premium template video cards.
	 *
	 * @param string $url Video URL.
	 * @return string
	 */
	private function get_video_thumbnail_url( $url ) {
		$video_id = '';

		if ( preg_match( '~(?:youtube\.com/(?:watch\?v=|embed/|shorts/)|youtu\.be/)([A-Za-z0-9_-]{6,})~', (string) $url, $matches ) ) {
			$video_id = $matches[1];
		}

		if ( '' === $video_id ) {
			return '';
		}

		return 'https://i.ytimg.com/vi/' . rawurlencode( $video_id ) . '/hqdefault.jpg';
	}

	/**
	 * Return a small safe SVG icon for dashboard hero blocks.
	 *
	 * @param string $icon Icon slug.
	 * @return string
	 */
	private function get_dashboard_icon_svg( $icon ) {
		$icons = array(
			'play'    => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><circle cx="12" cy="12" r="10"/><path d="M10 8l6 4-6 4V8z" fill="currentColor" stroke="none"/></svg>',
			'chart'   => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M4 19V5"/><path d="M4 19h16"/><rect x="7" y="10" width="3" height="6" rx="1"/><rect x="12" y="7" width="3" height="9" rx="1"/><rect x="17" y="4" width="3" height="12" rx="1"/></svg>',
			'user'    => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0"/></svg>',
			'support' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M4 12a8 8 0 0 1 16 0"/><path d="M4 12v4a2 2 0 0 0 2 2h2v-6H4zM20 12v4a2 2 0 0 1-2 2h-2v-6h4z"/><path d="M9 21h6"/></svg>',
			'shield'  => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M12 3l8 4v5c0 5-3.5 8.5-8 10-4.5-1.5-8-5-8-10V7l8-4z"/><path d="M9 12l2 2 4-5"/></svg>',
			'spark'   => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M13 2L3 14h8l-1 8 11-13h-8l0-7z"/></svg>',
		);

		return isset( $icons[ $icon ] ) ? $icons[ $icon ] : $icons['spark'];
	}

	/**
	 * Return a small stat-card SVG icon.
	 *
	 * @param string $icon Icon slug.
	 * @return string
	 */
	private function get_stat_icon_svg( $icon ) {
		$icons = array(
			'post'    => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 3h8l4 4v14H6z"/><path d="M14 3v5h5"/></svg>',
			'page'    => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 4h14v16H5z"/><path d="M8 8h8M8 12h8M8 16h5"/></svg>',
			'comment' => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12a8 8 0 0 1-8 8H7l-4 3v-6a8 8 0 1 1 18-5z"/></svg>',
			'user'    => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="9" cy="8" r="4"/><path d="M2 21a7 7 0 0 1 14 0"/><path d="M17 11h5M19.5 8.5v5"/></svg>',
			'media'   => '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="5" width="18" height="14" rx="2"/><circle cx="9" cy="10" r="2"/><path d="M21 15l-4-4-6 6-3-3-5 5"/></svg>',
		);

		return isset( $icons[ $icon ] ) ? $icons[ $icon ] : $icons['post'];
	}

	/**
	 * Render the site stats widget block.
	 *
	 * @param array  $data  Block data.
	 * @param string $align Text alignment.
	 * @return void
	 */
	private function render_stats_block( $data, $align = 'left' ) {
		$show = array(
			'posts'    => ! isset( $data['show_posts'] ) || ! empty( $data['show_posts'] ),
			'pages'    => ! isset( $data['show_pages'] ) || ! empty( $data['show_pages'] ),
			'comments' => ! isset( $data['show_comments'] ) || ! empty( $data['show_comments'] ),
			'users'    => ! empty( $data['show_users'] ),
			'media'    => ! empty( $data['show_media'] ),
		);

		$stats = array();

		if ( $show['posts'] ) {
			$count   = wp_count_posts();
			$stats[] = array(
				'n' => number_format_i18n( isset( $count->publish ) ? $count->publish : 0 ),
				'l' => __( 'Posts', 'panelra-dashboard-builder' ),
				'a' => __( 'View all posts', 'panelra-dashboard-builder' ),
				'i' => 'post',
			);
		}

		if ( $show['pages'] ) {
			$count   = wp_count_posts( 'page' );
			$stats[] = array(
				'n' => number_format_i18n( isset( $count->publish ) ? $count->publish : 0 ),
				'l' => __( 'Pages', 'panelra-dashboard-builder' ),
				'a' => __( 'View all pages', 'panelra-dashboard-builder' ),
				'i' => 'page',
			);
		}

		if ( $show['comments'] ) {
			$count   = wp_count_comments();
			$stats[] = array(
				'n' => number_format_i18n( isset( $count->approved ) ? $count->approved : 0 ),
				'l' => __( 'Comments', 'panelra-dashboard-builder' ),
				'a' => __( 'View all comments', 'panelra-dashboard-builder' ),
				'i' => 'comment',
			);
		}

		if ( $show['users'] ) {
			$count_users = count_users();
			$stats[]     = array(
				'n' => number_format_i18n( isset( $count_users['total_users'] ) ? $count_users['total_users'] : 0 ),
				'l' => __( 'Users', 'panelra-dashboard-builder' ),
				'a' => __( 'View all users', 'panelra-dashboard-builder' ),
				'i' => 'user',
			);
		}

		if ( $show['media'] ) {
			$count   = wp_count_posts( 'attachment' );
			$stats[] = array(
				'n' => number_format_i18n( isset( $count->inherit ) ? $count->inherit : 0 ),
				'l' => __( 'Media files', 'panelra-dashboard-builder' ),
				'a' => __( 'View all media', 'panelra-dashboard-builder' ),
				'i' => 'media',
			);
		}

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

		$cols = count( $stats );
		$jc   = 'left' === $align ? 'start' : ( 'right' === $align ? 'end' : 'center' );

		printf(
			'<div class="ap773-db-stats" style="grid-template-columns:repeat(%1$s,auto);justify-content:%2$s">',
			esc_attr( $cols ),
			esc_attr( $jc )
		);

		foreach ( $stats as $stat ) {
			$icon_class = isset( $stat['i'] ) ? sanitize_html_class( $stat['i'] ) : 'default';
			echo '<div class="ap773-db-stat ap773-db-stat--' . esc_attr( $icon_class ) . '">';
			echo '<span class="ap773-db-stat-l">' . esc_html( $stat['l'] ) . '</span>';
			echo '<span class="ap773-db-stat-n">' . esc_html( $stat['n'] ) . '</span>';
			if ( ! empty( $stat['a'] ) ) {
				echo '<span class="ap773-db-stat-a">' . esc_html( $stat['a'] ) . '</span>';
			}
			echo '<span class="ap773-db-stat-icon" aria-hidden="true">' . $this->get_stat_icon_svg( $icon_class ) . '</span>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
			echo '</div>';
		}

		echo '</div>';
	}

	/* ------------------------------------------------------------------
	 * Visibility helper
	 * ---------------------------------------------------------------- */

	/**
	 * Check whether an element with a roles list is visible to the current user.
	 *
	 * @param array $element_roles Roles configured on the element.
	 * @param array $user_roles    Current user's roles.
	 * @return bool
	 */
	private function is_visible_for_roles( $element_roles, $user_roles ) {
		if ( empty( $element_roles ) || in_array( 'all', (array) $element_roles, true ) ) {
			return true;
		}

		foreach ( $user_roles as $role ) {
			if ( in_array( $role, (array) $element_roles, true ) ) {
				return true;
			}
		}

		return false;
	}

	/* ------------------------------------------------------------------
	 * Assets
	 * ---------------------------------------------------------------- */

	/**
	 * Enqueue the builder CSS on the dashboard page.
	 *
	 * @param string $hook Current admin page hook.
	 * @return void
	 */
	public function enqueue_builder_assets( $hook ) {
		if ( 'index.php' === $hook ) {
			wp_enqueue_style(
				'pnlrdb-dashboard',
				PNLRDB_PLUGIN_URL . 'admin/css/pnlrdb-dashboard.css',
				array(),
				PNLRDB_VERSION
			);
		}
	}

	/* ------------------------------------------------------------------
	 * AJAX handlers
	 * ---------------------------------------------------------------- */

	/**
	 * Save the layout sent by the builder JS.
	 *
	 * @return void
	 */
	public function ajax_save_layout() {
		check_ajax_referer( self::NONCE_ACTION, 'nonce' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Permission denied.', 'panelra-dashboard-builder' ),
				)
			);
		}

		$pnlrdb_raw = isset( $_POST['layout'] ) ? wp_unslash( $_POST['layout'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized deeply after JSON decode.

		if ( empty( $pnlrdb_raw ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'No layout data received.', 'panelra-dashboard-builder' ),
				)
			);
		}

		$layout = json_decode( $pnlrdb_raw, true );

		if ( JSON_ERROR_NONE !== json_last_error() || ! is_array( $layout ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Invalid layout data.', 'panelra-dashboard-builder' ),
				)
			);
		}

		$clean = $this->sanitize_layout( $layout );
		update_option( self::OPTION_KEY, $clean );

		wp_send_json_success(
			array(
				'message' => __( 'Layout saved.', 'panelra-dashboard-builder' ),
			)
		);
	}

	/**
	 * Return the current layout as JSON.
	 *
	 * @return void
	 */
	public function ajax_get_layout() {
		check_ajax_referer( self::NONCE_ACTION, 'nonce' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( 'Permission denied.' );
		}

		wp_send_json_success( self::get_layout() );
	}

	/* ------------------------------------------------------------------
	 * Sanitize layout
	 * ---------------------------------------------------------------- */

	/**
	 * Deeply sanitize the layout array received from the builder.
	 *
	 * @param array $raw Raw layout from AJAX request.
	 * @return array Sanitized layout.
	 */
	private function sanitize_layout( $raw ) {
		$layout = array(
			'enabled'              => ! empty( $raw['enabled'] ),
			'hide_wp'              => ! empty( $raw['hide_wp'] ),
			'hide_screen_opts'     => ! empty( $raw['hide_screen_opts'] ),
			'hide_help'            => ! empty( $raw['hide_help'] ),
			'hide_notices'         => ! empty( $raw['hide_notices'] ),
			'hide_title'           => ! empty( $raw['hide_title'] ),
			'defaults_initialized' => ! empty( $raw['defaults_initialized'] ),
			'sections'             => array(),
		);

		$allowed_block_types = array_keys( self::get_block_types() );

		foreach ( $raw['sections'] ?? array() as $section ) {
			$clean_section = array(
				'id'     => sanitize_key( isset( $section['id'] ) ? $section['id'] : uniqid( 's_', false ) ),
				'cols'   => max( 1, min( 3, absint( isset( $section['cols'] ) ? $section['cols'] : 1 ) ) ),
				'layout' => isset( $section['layout'] ) && in_array( sanitize_key( $section['layout'] ), array( 'columns', 'grid12' ), true ) ? sanitize_key( $section['layout'] ) : 'columns',
				'gap'       => isset( $section['gap'] ) && in_array( sanitize_key( $section['gap'] ), array( 'compact', 'normal', 'large' ), true ) ? sanitize_key( $section['gap'] ) : 'normal',
				'title'     => sanitize_text_field( isset( $section['title'] ) ? $section['title'] : '' ),
				'cta_label' => sanitize_text_field( isset( $section['cta_label'] ) ? $section['cta_label'] : '' ),
				'cta_url'   => esc_url_raw( isset( $section['cta_url'] ) ? $section['cta_url'] : '' ),
				'roles'     => $this->sanitize_roles( isset( $section['roles'] ) ? $section['roles'] : array( 'all' ) ),
				'blocks' => array(),
			);

			foreach ( $section['blocks'] ?? array() as $block ) {
				$type = sanitize_key( isset( $block['type'] ) ? $block['type'] : '' );

				if ( ! in_array( $type, $allowed_block_types, true ) ) {
					continue;
				}

				$clean_section['blocks'][] = array(
					'id'   => sanitize_key( isset( $block['id'] ) ? $block['id'] : uniqid( 'b_', false ) ),
					'type' => $type,
					'col'  => max( 0, min( 2, absint( isset( $block['col'] ) ? $block['col'] : 0 ) ) ),
					'span' => max( 1, min( 12, absint( isset( $block['span'] ) ? $block['span'] : 12 ) ) ),
					'data' => $this->sanitize_block_data( $type, isset( $block['data'] ) ? $block['data'] : array() ),
				);
			}

			$layout['sections'][] = $clean_section;
		}

		return $layout;
	}

	/**
	 * Sanitize a roles array — only allows valid WP role slugs plus 'all'.
	 *
	 * @param mixed $roles Raw roles value.
	 * @return array
	 */
	private function sanitize_roles( $roles ) {
		if ( ! is_array( $roles ) ) {
			return array( 'all' );
		}

		if ( in_array( 'all', $roles, true ) ) {
			return array( 'all' );
		}

		$valid = array_keys( get_editable_roles() );
		$out   = array();

		foreach ( $roles as $role ) {
			$role = sanitize_key( $role );

			if ( in_array( $role, $valid, true ) ) {
				$out[] = $role;
			}
		}

		return $out ? $out : array( 'all' );
	}

	/**
	 * Sanitize editable dashboard action/link items.
	 *
	 * Keeps backward compatibility with the old textarea format while saving
	 * the new visual action editor structure used by link_list and quick_actions.
	 *
	 * @param array $data Raw block data.
	 * @return array
	 */
	private function sanitize_dashboard_action_items( $data ) {
		$clean = array(
			'title'      => sanitize_text_field( isset( $data['title'] ) ? $data['title'] : '' ),
			'items'      => '',
			'items_data' => array(),
		);

		$raw_items = array();

		if ( ! empty( $data['items_data'] ) && is_array( $data['items_data'] ) ) {
			$raw_items = $data['items_data'];
		} elseif ( ! empty( $data['items'] ) ) {
			$lines = preg_split( '/\r\n|\r|\n/', (string) $data['items'] );
			foreach ( $lines as $line ) {
				$line = trim( $line );
				if ( '' === $line ) {
					continue;
				}

				$parts       = array_map( 'trim', explode( '|', $line ) );
				$raw_items[] = array(
					'icon'   => isset( $parts[0] ) ? $parts[0] : '•',
					'label'  => isset( $parts[1] ) ? $parts[1] : ( isset( $parts[0] ) ? $parts[0] : '' ),
					'url'    => isset( $parts[2] ) ? $parts[2] : '',
					'source' => 'manual',
					'choice' => '',
				);
			}
		}

		foreach ( $raw_items as $item ) {
			if ( ! is_array( $item ) ) {
				continue;
			}

			$label = sanitize_text_field( isset( $item['label'] ) ? $item['label'] : '' );
			if ( '' === $label ) {
				continue;
			}

			$icon   = sanitize_text_field( isset( $item['icon'] ) ? $item['icon'] : '•' );
			$url    = esc_url_raw( isset( $item['url'] ) ? $item['url'] : '#' );
			$source = sanitize_key( isset( $item['source'] ) ? $item['source'] : 'manual' );
			$choice = sanitize_text_field( isset( $item['choice'] ) ? $item['choice'] : '' );

			if ( '' === $url ) {
				$url = '#';
			}

			$clean['items_data'][] = array(
				'icon'   => '' !== $icon ? $icon : '•',
				'label'  => $label,
				'url'    => $url,
				'source' => '' !== $source ? $source : 'manual',
				'choice' => $choice,
			);
		}

		$clean['items'] = implode(
			"\n",
			array_map(
				static function ( $item ) {
					return $item['icon'] . '|' . $item['label'] . '|' . $item['url'];
				},
				$clean['items_data']
			)
		);

		return $clean;
	}

	/**
	 * Sanitize block data fields by block type.
	 *
	 * @param string $type Block type slug.
	 * @param array  $data Raw data.
	 * @return array Sanitized data.
	 */
	private function sanitize_block_data( $type, $data ) {
		if ( ! is_array( $data ) ) {
			return array();
		}

		switch ( $type ) {
			case 'heading':
				return array(
					'text'  => sanitize_text_field( isset( $data['text'] ) ? $data['text'] : '' ),
					'level' => isset( $data['level'] ) && in_array( $data['level'], array( 'h1', 'h2', 'h3', 'h4' ), true ) ? $data['level'] : 'h2',
					'align' => isset( $data['align'] ) && in_array( $data['align'], array( 'left', 'center', 'right' ), true ) ? $data['align'] : 'left',
				);

			case 'text':
				return array(
					'content' => wp_kses_post( isset( $data['content'] ) ? $data['content'] : '' ),
					'align'   => isset( $data['align'] ) && in_array( $data['align'], array( 'left', 'center', 'right' ), true ) ? $data['align'] : 'left',
				);

			case 'button':
				return array(
					'label'   => sanitize_text_field( isset( $data['label'] ) ? $data['label'] : '' ),
					'url'     => esc_url_raw( isset( $data['url'] ) ? $data['url'] : '#' ),
					'style'   => isset( $data['style'] ) && in_array( $data['style'], array( 'primary', 'secondary', 'link' ), true ) ? $data['style'] : 'primary',
					'new_tab' => ! empty( $data['new_tab'] ),
					'align'   => isset( $data['align'] ) && in_array( $data['align'], array( 'left', 'center', 'right' ), true ) ? $data['align'] : 'left',
				);

			case 'image':
				return array(
					'url'     => esc_url_raw( isset( $data['url'] ) ? $data['url'] : '' ),
					'alt'     => sanitize_text_field( isset( $data['alt'] ) ? $data['alt'] : '' ),
					'caption' => sanitize_text_field( isset( $data['caption'] ) ? $data['caption'] : '' ),
					'align'   => isset( $data['align'] ) && in_array( $data['align'], array( 'left', 'center', 'right' ), true ) ? $data['align'] : 'left',
				);

			case 'video':
				return array(
					'url'      => esc_url_raw( isset( $data['url'] ) ? $data['url'] : '' ),
					'align'    => isset( $data['align'] ) && in_array( $data['align'], array( 'left', 'center', 'right' ), true ) ? $data['align'] : 'left',
					'title'    => sanitize_text_field( isset( $data['title'] ) ? $data['title'] : '' ),
					'duration' => sanitize_text_field( isset( $data['duration'] ) ? $data['duration'] : '' ),
				);

			case 'stats':
				return array(
					'show_posts'    => ! empty( $data['show_posts'] ),
					'show_pages'    => ! empty( $data['show_pages'] ),
					'show_comments' => ! empty( $data['show_comments'] ),
					'show_users'    => ! empty( $data['show_users'] ),
					'show_media'    => ! empty( $data['show_media'] ),
					'align'         => isset( $data['align'] ) && in_array( $data['align'], array( 'left', 'center', 'right' ), true ) ? $data['align'] : 'left',
				);

			case 'hero':
				return array(
					'eyebrow' => sanitize_text_field( isset( $data['eyebrow'] ) ? $data['eyebrow'] : '' ),
					'title'   => sanitize_text_field( isset( $data['title'] ) ? $data['title'] : '' ),
					'content' => wp_kses_post( isset( $data['content'] ) ? $data['content'] : '' ),
					'theme'   => isset( $data['theme'] ) && in_array( $data['theme'], array( 'purple', 'blue', 'green', 'softgreen' ), true ) ? $data['theme'] : 'blue',
					'icon'          => sanitize_key( isset( $data['icon'] ) ? $data['icon'] : 'spark' ),
					'button_label'  => sanitize_text_field( isset( $data['button_label'] ) ? $data['button_label'] : '' ),
					'button_url'    => esc_url_raw( isset( $data['button_url'] ) ? $data['button_url'] : '' ),
					'support_email' => sanitize_email( isset( $data['support_email'] ) ? $data['support_email'] : '' ),
					'support_phone' => sanitize_text_field( isset( $data['support_phone'] ) ? $data['support_phone'] : '' ),
				);

			case 'link_list':
			case 'quick_actions':
				return $this->sanitize_dashboard_action_items( $data );

			case 'checklist':
				return array(
					'title' => sanitize_text_field( isset( $data['title'] ) ? $data['title'] : '' ),
					'items' => sanitize_textarea_field( isset( $data['items'] ) ? $data['items'] : '' ),
					'style' => isset( $data['style'] ) && in_array( $data['style'], array( 'check', 'status' ), true ) ? $data['style'] : 'check',
				);

			case 'divider':
				return array();

			default:
				/**
				 * Sanitize data for a Pro (or third-party) block type.
				 *
				 * @param array  $data Raw block data.
				 * @param string $type Block type slug.
				 * @return array Sanitized data.
				 */
				return apply_filters( 'pnlrdb_sanitize_builder_block_' . $type, $data, $type );
		}
	}
}