<?php
/**
 * Performance Optimized Layout Renderer
 *
 * This file contains the LayoutRenderer class which handles all layout component
 * rendering with proper CSS classes and performance optimization. The class provides
 * methods for rendering various layout components including containers, sections,
 * grids, tabs, accordions, wizards, and complete page structures with caching
 * mechanisms for improved performance.
 *
 * @package    UltraguardPro\renderers
 * @author     Ultraguard Pro Team <developers@ultraguardpro.com>
 * @copyright  2024 Ultraguard Pro
 * @license    GPL-2.0-or-later
 * @version    1.0.0
 * @link       https://ultraguardpro.com/docs/layout-renderer
 */

namespace UltraguardPro\view;

defined( 'ABSPATH' ) || exit;

/**
 * Performance Optimized Layout Renderer
 *
 * Handles all layout component rendering with proper CSS classes, performance
 * optimization, and caching mechanisms. This class provides methods for rendering
 * various layout components including containers, sections, grids, tabs, accordions,
 * wizards, and complete page structures.
 *
 * The renderer includes static caching for default schemes and CSS values to
 * improve performance during repeated rendering. It extends BaseRenderer to
 * leverage shared rendering functionality and provides a comprehensive API for
 * building complex user interfaces with consistent styling and behavior.
 *
 * @package    UltraguardPro\view
 * @author     Ultraguard Pro Team
 * @version    1.0.0
 * @since      1.0.0
 * @see        BaseRenderer
 * @see        GridRenderer
 * @see        WidgetRenderer
 * @see        ConditionalRenderer
 *
 * @example
 * // Render a section with title and content
 * $html = LayoutRenderer::render_section([
 *     'title' => 'My Section',
 *     'description' => 'This is a section description',
 *     'data' => [
 *         ['type' => 'text', 'content' => 'Section content here']
 *     ]
 * ], $context);
 */
class LayoutRenderer extends BaseRenderer {

    /**
     * Cached instance for static methods
     *
     * Stores a single instance of LayoutRenderer to be shared across
     * static method calls, reducing object creation overhead.
     *
     * @var self|null
     * @access private
     * @static
     */
    private static $cached_instance = null;

    /**
     * Default schemes for each layout type
     *
     * Caches default configuration schemes for all layout types
     * to avoid repeated array construction and improve performance.
     *
     * @var array<string, array>
     * @access private
     * @static
     */
    private static $default_schemes = [];

    /**
     * Per-type element counter for generating unique default IDs.
     *
     * uniqid() inside a statically-cached array is evaluated once and frozen,
     * causing every element of the same type that relies on a default id to
     * share the same HTML id attribute.  This counter is incremented each time
     * generate_element_id() is called, so each element gets a distinct id.
     *
     * @var array<string, int>
     * @access private
     * @static
     */
    private static $id_counters = [];

    /**
     * CSS unit validation cache
     *
     * Caches sanitized CSS unit values to prevent repeated processing
     * of identical CSS unit strings during rendering.
     *
     * @var array<string, string>
     * @access private
     * @static
     */
    private static $css_unit_cache = [];

    /**
     * Sanitized CSS cache
     *
     * Caches sanitized CSS style strings to avoid redundant processing
     * and improve rendering performance for repeated style declarations.
     *
     * @var array<string, string>
     * @access private
     * @static
     */
    private static $css_sanitization_cache = [];

    /**
     * Get cached instance
     *
     * Returns the shared instance of LayoutRenderer for use in static methods.
     * Creates a new instance if one doesn't exist, implementing a lightweight
     * singleton pattern for static method support.
     *
     * @return self The shared LayoutRenderer instance
     * @access private
     * @static
     * @since 1.0.0
     */
    private static function get_cached_instance(): self {
        if ( self::$cached_instance === null ) {
            self::$cached_instance = new self();
        }
        return self::$cached_instance;
    }

    /**
     * Initialize default schemes
     *
     * Populates the default schemes cache with configuration arrays
     * for all supported layout types. Called automatically when
     * default schemes are first accessed.
     *
     * @return void
     * @access private
     * @static
     * @since 1.0.0
     */
    /**
     * Generate a unique, predictable element ID for a given type prefix.
     *
     * Each call increments a per-type counter, guaranteeing uniqueness
     * across an entire PHP request without freezing on a static value.
     *
     * @param  string  $prefix  Human-readable type prefix, e.g. 'ultraguard-form'
     * @return string           e.g. 'ultraguard-form-1', 'ultraguard-form-2', …
     * @access private
     * @static
     */
    private static function generate_element_id( string $prefix ): string {
        if ( ! isset( self::$id_counters[ $prefix ] ) ) {
            self::$id_counters[ $prefix ] = 0;
        }
        self::$id_counters[ $prefix ]++;
        return $prefix . '-' . self::$id_counters[ $prefix ];
    }

    private static function init_default_schemes(): void {
        if ( ! empty( self::$default_schemes ) ) {
            return;
        }

        self::$default_schemes = [
            'container' => [
                'class' => '',
                'data' => [],
                'style' => '',
                'id' => '',
                'attributes' => []
            ],
            'large_container' => [
                'class' => '',
                'data' => [],
                'style' => '',
                'id' => '',
                'attributes' => []
            ],
            'section' => [
                'class' => '',
                'data' => [],
                'style' => '',
                'id' => '',
                'title' => '',
                'description' => '',
                'icon' => '',
                'actions' => [],
                'attributes' => []
            ],
            'mini_section' => [
                'class' => '',
                'data' => [],
                'style' => '',
                'id' => '',
                'title' => '',
                'attributes' => []
            ],
            'module' => [
                'class' => '',
                'data' => [],
                'style' => '',
                'id' => '',
                'attributes' => []
            ],
            'module_set' => [
                'class' => '',
                'modules' => [],
                'style' => '',
                'id' => '',
                'attributes' => []
            ],
            'grid' => [
                'class' => '',
                'data' => [],
                'style' => '',
                'id' => '',
                'columns' => 2,
                'gap' => '20px',
                'responsive' => true,
                'attributes' => []
            ],
            'masonry_grid' => [
                'class' => '',
                'data' => [],
                'style' => '',
                'id' => '',
                'columns' => 3,
                'gap' => '20px',
                'attributes' => []
            ],
            'tabs' => [
                'class' => '',
                'tabs' => [],
                'style' => '',
                'id' => '',
                'attributes' => []
            ],
            'vertical_tabs' => [
                'class' => '',
                'tabs' => [],
                'style' => '',
                'id' => '',
                'attributes' => []
            ],
            'accordion' => [
                'class' => '',
                'panels' => [],
                'style' => '',
                'id' => '',
                'attributes' => []
            ],
            'wizard' => [
                'steps' => [],
                'current_step' => 1,
                'id' => '',
                'attributes' => []
            ],
            'drawer' => [
                'position' => 'right',
                'title' => '',
                'data' => [],
                'id' => ''
            ],
            'card_deck' => [
                'cards' => [],
                'class' => ''
            ],
            'sticky_container' => [
                'position' => 'top',
                'offset' => 0,
                'data' => []
            ],
            'page' => [
                'class' => '',
                'data' => [],
                'style' => '',
                'id' => '',
                'header' => [],
                'sidebar' => [],
                'footer' => [],
                'form' => [
                    'enable' => false,
                    'method' => 'post',
                    'action' => '',
                    'ajax' => false,
                    'nonce' => false,
                    'class' => 'ultraguard-form',
                    'id' => '',
                    'nonce_action' => 'ultraguard_admin_nonce',
                    'hidden_fields' => []
                ],
                'layout' => [
                    'type' => 'default'
                ],
                'attributes' => []
            ],
            'form_start' => [
                'method' => 'post',
                'action' => '',
                'ajax' => false,
                'nonce' => false,
                'class' => 'ultraguard-form',
                'id' => '',
                'nonce_action' => 'ultraguard_admin_nonce',
                'hidden_fields' => [],
                'attributes' => []
            ],
            'page_header' => [
                'title' => '',
                'subtitle' => '',
                'icon' => '',
                'actions' => []
            ],
            'sidebar' => [
                'widgets' => []
            ],
            'page_footer' => [
                'actions' => [],
                'submit_button' => false,
                'submit_text' => __( 'Save Changes', 'ultraguard-security-suite' )
            ],
            'tab_config' => [
                'title' => '',
                'icon' => '',
                'badge' => 0,
                'data' => [],
                'capability' => '',
                'condition' => null
            ],
            'panel_config' => [
                'title' => '',
                'icon' => '',
                'data' => [],
                'capability' => '',
                'condition' => null
            ]
        ];
    }

    /**
     * Get default scheme for type
     *
     * Retrieves the default configuration scheme for a specific layout type.
     * Automatically initializes the schemes cache if not already populated.
     *
     * @param  string  $type  The layout type (e.g., 'container', 'section', 'grid')
     * @return array<string, mixed> The default configuration scheme for the type
     * @access private
     * @static
     * @since  1.0.0
     *
     * @example
     * $default = LayoutRenderer::get_default_scheme('section');
     * // Returns: ['class' => '', 'data' => [], ...]
     */
    private static function get_default_scheme( string $type ): array {
        self::init_default_schemes();
        $key     = str_replace( '-', '_', $type );
        $default = self::$default_schemes[ $key ] ?? [];

        // The default schemes array is initialised once (static cache).  Any
        // 'id' stored in it would be frozen to the value computed on the first
        // PHP request, causing every element of the same type that relies on
        // the fallback id to share a single HTML id attribute.
        // Fix: replace the static id with a freshly-generated counter-based one
        // on every call so each element gets a guaranteed-unique id.
        if ( array_key_exists( 'id', $default ) ) {
            // Derive a human-readable prefix from the type name.
            $prefix  = 'ultraguard-' . str_replace( '_', '-', $key );
            $default['id'] = self::generate_element_id( $prefix );
        }

        // Nested form default also carries an id that must be freshened.
        if ( isset( $default['form']['id'] ) ) {
            $default['form']['id'] = self::generate_element_id( 'ultraguard-form' );
        }

        return $default;
    }

    /**
     * Render container
     *
     * Renders a basic container element with optional custom classes, styles,
     * and data content. Containers provide consistent spacing and layout
     * boundaries for grouped content.
     *
     * @param  array  $scheme   Container configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML container
     * @access public
     * @static
     * @since  1.0.0
     *
     * @example
     * $html = LayoutRenderer::render_container([
     *     'class' => 'my-custom-class',
     *     'style' => 'background: #f0f0f0;',
     *     'data' => [
     *         ['type' => 'text', 'content' => 'Container content']
     *     ]
     * ], $context);
     */
    public static function render_container( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'container' ) );

        if ( has_filter( 'ultraguard_container_scheme' ) ) {
            $scheme = apply_filters( 'ultraguard_container_scheme', $scheme, $context );
        }

        $scheme['class'] = ! empty( $scheme['class'] ) ?
            sanitize_html_class( $scheme['class'] ) . ' ultraguard-container' :
            'ultraguard-container';

        $scheme['style'] = self::sanitize_css_static( $scheme['style'] );

        $content = '';
        if ( ! empty( $scheme['data'] ) ) {
            $content = $instance->render_children( $scheme['data'], $context );
        }

        $output = $instance->render_wrapper( $content, $scheme, $context );
        return $instance->after_render( $output, $scheme, $context );
    }

    /**
     * Render form start
     *
     * Renders the opening form tag with all necessary attributes, nonce fields,
     * and hidden inputs. Supports AJAX forms and custom attributes.
     *
     * @param  array  $form_config  Form configuration array
     * @return string               Form start HTML including opening form tag
     * @access protected
     * @since  1.0.0
     *
     * @example
     * $form_start = $this->render_form_start([
     *     'method' => 'post',
     *     'action' => admin_url('admin-post.php'),
     *     'nonce' => true,
     *     'hidden_fields' => ['action' => 'my_action']
     * ]);
     */
    protected function render_form_start( $form_config ) {
        $form_config = wp_parse_args( $form_config, self::get_default_scheme( 'form_start' ) );

        if ( has_filter( 'ultraguard_form_config' ) ) {
            $form_config = apply_filters( 'ultraguard_form_config', $form_config );
        }

        // Separate the AJAX action name from the HTML form action URL.
        // When ajax=true the 'action' key in the scheme is the wp_ajax_{action} name,
        // NOT a URL — running it through esc_url() would produce an empty string and
        // JS would fall back to the wrong default handler.
        $ajax_action_name = '';
        if ( $form_config['ajax'] && ! empty( $form_config['action'] ) ) {
            $ajax_action_name = sanitize_key( $form_config['action'] );
        }

        $attributes = [
            'method' => in_array( strtolower( $form_config['method'] ), ['post', 'get'], true ) ? $form_config['method'] : 'post',
            // For AJAX forms use admin-ajax.php; for regular forms honour the scheme URL.
                'action' => $ajax_action_name ? esc_url( self_admin_url( 'admin-ajax.php' ) ) : esc_url( $form_config['action'] ),
            'class'  => sanitize_html_class( $form_config['class'] ),
            'id'     => sanitize_html_class( $form_config['id'] ),
        ];

        if ( ! empty( $form_config['attributes'] ) && is_array( $form_config['attributes'] ) ) {
            foreach ( $form_config['attributes'] as $key => $value ) {
                if ( ! is_array( $value ) && ! is_object( $value ) ) {
                    $attributes[ sanitize_key( $key ) ] = $this->escape( $value, 'attribute' );
                }
            }
        }

        if ( $form_config['ajax'] ) {
            $attributes['data-ajax'] = 'true';
            // Write the AJAX action name as data-ajax-action so JS reads it directly
            // instead of falling through to the wrong consolidated-settings fallback.
            if ( $ajax_action_name ) {
                $attributes['data-ajax-action'] = $ajax_action_name;
            }
        }

        $attributes_string = '';
        foreach ( $attributes as $key => $value ) {
            $attributes_string .= sprintf( ' %s="%s"', $key, $value );
        }

        $output = sprintf( '<form%s>', $attributes_string );

        // Emit a hidden <input name="action"> for the AJAX action — this acts as a
        // secondary lookup path (JS reads input[name="action"]) and is also used by
        // any non-JS fallback that submits the form normally.
        if ( $ajax_action_name ) {
            $output .= sprintf(
                '<input type="hidden" name="action" value="%s">',
                esc_attr( $ajax_action_name )
            );
        }

        // Nonce: emit a SINGLE field named `nonce` so JS picks it up without
        // the AjaxManager appending a second global nonce.
        //
        // Three accepted usages:
        //   'nonce' => true           → generate from 'nonce_action' (flag mode)
        //   'nonce' => 'some_string'  → value already computed by the page class; use as-is
        //   'nonce' => false          → omit the field entirely
        if ( $form_config['nonce'] === true ) {
            // Flag mode: generate fresh nonce from the declared nonce_action.
            $nonce_action = sanitize_key( $form_config['nonce_action'] ?: 'ultraguard_admin_nonce' );
            $nonce_value  = wp_create_nonce( $nonce_action );
            $output      .= sprintf(
                '<input type="hidden" id="_wpnonce" name="nonce" value="%s">',
                esc_attr( $nonce_value )
            );
        } elseif ( is_string( $form_config['nonce'] ) && $form_config['nonce'] !== '' ) {
            // Value mode: page already called wp_create_nonce(); honour it directly.
            $output .= sprintf(
                '<input type="hidden" id="_wpnonce" name="nonce" value="%s">',
                esc_attr( $form_config['nonce'] )
            );
        }
        // false / empty → no nonce field emitted.

        if ( ! empty( $form_config['hidden_fields'] ) && is_array( $form_config['hidden_fields'] ) ) {
            foreach ( $form_config['hidden_fields'] as $name => $value ) {
                if ( ! is_array( $value ) && ! is_object( $value ) ) {
                    $output .= sprintf(
                        '<input type="hidden" name="%s" value="%s">',
                        $this->escape( $name, 'attribute' ),
                        $this->escape( $value, 'attribute' )
                    );
                }
            }
        }

        if ( has_filter( 'ultraguard_form_start' ) ) {
            return apply_filters( 'ultraguard_form_start', $output, $form_config );
        }

        return $output;
    }

    /**
     * Render large container
     *
     * Renders a large container element with wider internal spacing and
     * maximum width constraints. Suitable for main content areas and
     * feature sections.
     *
     * @param  array  $scheme   Large container configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML large container
     * @access public
     * @static
     * @since  1.0.0
     *
     * @example
     * $html = LayoutRenderer::render_large_container([
     *     'class' => 'feature-section',
     *     'data' => [/* content array *\/]
     * ], $context);
     */
    public static function render_large_container( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'large_container' ) );

        if ( has_filter( 'ultraguard_large_container_scheme' ) ) {
            $scheme = apply_filters( 'ultraguard_large_container_scheme', $scheme, $context );
        }

        $scheme['class'] = ! empty( $scheme['class'] ) ?
            sanitize_html_class( $scheme['class'] ) . ' ultraguard-large-container' :
            'ultraguard-large-container';

        $scheme['style'] = self::sanitize_css_static( $scheme['style'] );

        $content = '';
        if ( ! empty( $scheme['data'] ) ) {
            $content = $instance->render_children( $scheme['data'], $context );
        }

        $output = $instance->render_wrapper( $content, $scheme, $context );
        return $instance->after_render( $output, $scheme, $context );
    }

    /**
     * Render section
     *
     * Renders a section element with optional header containing title,
     * description, icon, and action buttons. Sections provide visual
     * grouping for related content blocks.
     *
     * @param  array  $scheme   Section configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML section
     * @access public
     * @static
     * @since  1.0.0
     *
     * @example
     * $html = LayoutRenderer::render_section([
     *     'title' => 'Settings',
     *     'description' => 'Configure your settings below',
     *     'icon' => 'dashicons-admin-settings',
     *     'actions' => [
     *         ['type' => 'button', 'label' => 'Add New']
     *     ],
     *     'data' => [/* section content *\/]
     * ], $context);
     */
    public static function render_section( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'section' ) );

        if ( has_filter( 'ultraguard_section_scheme' ) ) {
            $scheme = apply_filters( 'ultraguard_section_scheme', $scheme, $context );
        }

        $scheme['class'] = ! empty( $scheme['class'] ) ?
            sanitize_html_class( $scheme['class'] ) . ' ultraguard-section' :
            'ultraguard-section';

        $scheme['style'] = self::sanitize_css_static( $scheme['style'] );

        $header = '';
        if ( ! empty( $scheme['title'] ) ) {
            $header = $instance->render_section_header( $scheme, $context );
        }

        $content = '';
        if ( ! empty( $scheme['data'] ) ) {
            $content = $instance->render_children( $scheme['data'], $context );
        }

        $output = $instance->render_wrapper( $header . $content, $scheme, $context );
        return $instance->after_render( $output, $scheme, $context );
    }

    /**
     * Render mini-section
     *
     * Renders a compact section element with minimal header and spacing.
     * Suitable for secondary content blocks, footnotes, or supplementary
     * information.
     *
     * @param  array  $scheme   Mini-section configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML mini-section
     * @access public
     * @static
     * @since  1.0.0
     *
     * @example
     * $html = LayoutRenderer::render_mini_section([
     *     'title' => 'Additional Notes',
     *     'data' => [
     *         ['type' => 'text', 'content' => 'These are additional notes.']
     *     ]
     * ], $context);
     */
    public static function render_mini_section( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'mini_section' ) );

        if ( has_filter( 'ultraguard_mini_section_scheme' ) ) {
            $scheme = apply_filters( 'ultraguard_mini_section_scheme', $scheme, $context );
        }

        $scheme['class'] = ! empty( $scheme['class'] ) ?
            sanitize_html_class( $scheme['class'] ) . ' ultraguard-mini-section' :
            'ultraguard-mini-section';

        $scheme['style'] = self::sanitize_css_static( $scheme['style'] );

        $header = '';
        if ( ! empty( $scheme['title'] ) ) {
            $header = sprintf(
                '<div class="ultraguard-mini-section-header"><h4>%s</h4></div>',
                $instance->escape( $scheme['title'] )
            );
        }

        $content = '';
        if ( ! empty( $scheme['data'] ) ) {
            $content = $instance->render_children( $scheme['data'], $context );
        }

        $output = $instance->render_wrapper( $header . $content, $scheme, $context );
        return $instance->after_render( $output, $scheme, $context );
    }

    /**
     * Render module
     *
     * Renders a modular content block with consistent styling and structure.
     * Modules are reusable components that can contain any type of content.
     *
     * @param  array  $scheme   Module configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML module
     * @access public
     * @static
     * @since  1.0.0
     *
     * @example
     * $html = LayoutRenderer::render_module([
     *     'class' => 'stats-module',
     *     'style' => 'border: 1px solid #ddd;',
     *     'data' => [/* module content *\/]
     * ], $context);
     */
    public static function render_module( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'module' ) );

        if ( has_filter( 'ultraguard_module_scheme' ) ) {
            $scheme = apply_filters( 'ultraguard_module_scheme', $scheme, $context );
        }

        $scheme['class'] = ! empty( $scheme['class'] ) ?
            sanitize_html_class( $scheme['class'] ) . ' module' :
            'module';

        $scheme['style'] = self::sanitize_css_static( $scheme['style'] );

        $content = '';
        if ( ! empty( $scheme['data'] ) ) {
            $content = $instance->render_children( $scheme['data'], $context );
        }

        $output = $instance->render_wrapper( $content, $scheme, $context );
        return $instance->after_render( $output, $scheme, $context );
    }

    /**
     * Render module set
     *
     * Renders a collection of modules grouped together with consistent
     * spacing and layout. Useful for displaying related modular components.
     *
     * @param  array  $scheme   Module set configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML module set
     * @access public
     * @static
     * @since  1.0.0
     *
     * @example
     * $html = LayoutRenderer::render_module_set([
     *     'class' => 'dashboard-widgets',
     *     'modules' => [
     *         ['type' => 'module', /* module config *\/],
     *         ['type' => 'module', /* module config *\/]
     *     ]
     * ], $context);
     */
    public static function render_module_set( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'module_set' ) );

        if ( has_filter( 'ultraguard_module_set_scheme' ) ) {
            $scheme = apply_filters( 'ultraguard_module_set_scheme', $scheme, $context );
        }

        $scheme['class'] = ! empty( $scheme['class'] ) ?
            sanitize_html_class( $scheme['class'] ) . ' module-set' :
            'module-set';

        $scheme['style'] = self::sanitize_css_static( $scheme['style'] );

        $content = '';
        if ( ! empty( $scheme['modules'] ) && is_array( $scheme['modules'] ) ) {
            foreach ( $scheme['modules'] as $index => $module ) {
                if ( has_filter( 'ultraguard_module_set_item' ) ) {
                    $module = apply_filters( 'ultraguard_module_set_item', $module, $index, $context );
                }
                $content .= $instance->engine->render( $module, $context );
            }
        }

        $output = $instance->render_wrapper( $content, $scheme, $context );
        return $instance->after_render( $output, $scheme, $context );
    }

    /**
     * Render grid
     *
     * Renders a CSS Grid layout with specified columns and gap spacing.
     * Supports responsive behavior with auto-fit columns for mobile devices.
     *
     * @param  array  $scheme   Grid configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML grid
     * @access public
     * @static
     * @since  1.0.0
     *
     * @example
     * $html = LayoutRenderer::render_grid([
     *     'columns' => 3,
     *     'gap' => '20px',
     *     'responsive' => true,
     *     'data' => [
     *         ['type' => 'card', /* card config *\/],
     *         ['type' => 'card', /* card config *\/],
     *         ['type' => 'card', /* card config *\/]
     *     ]
     * ], $context);
     */
    public static function render_grid( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'grid' ) );

        if ( has_filter( 'ultraguard_layout_grid_scheme' ) ) {
            $scheme = apply_filters( 'ultraguard_layout_grid_scheme', $scheme, $context );
        }

        $columns = max( 1, min( 12, absint( $scheme['columns'] ) ) );
        $gap = self::sanitize_css_unit_static( $scheme['gap'] );
        $responsive = (bool) $scheme['responsive'];

        $scheme['class'] = ! empty( $scheme['class'] ) ?
            sanitize_html_class( $scheme['class'] ) . ' ultraguard-grid' :
            'ultraguard-grid';

        $grid_style = sprintf(
            'display: grid; grid-template-columns: repeat(%d, 1fr); gap: %s;',
            $columns,
            $gap
        );

        if ( $responsive ) {
            $grid_style .= ' grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));';
        }

        $existing_style = ! empty( $scheme['style'] ) ? self::sanitize_css_static( $scheme['style'] ) . '; ' : '';
        $scheme['style'] = $existing_style . $grid_style;

        $content = '';
        if ( ! empty( $scheme['data'] ) ) {
            $content = $instance->render_children( $scheme['data'], $context );
        }

        $output = $instance->render_wrapper( $content, $scheme, $context );
        return $instance->after_render( $output, $scheme, $context );
    }

    /**
     * Render masonry grid
     *
     * Renders a masonry-style grid using CSS columns with variable height
     * items. Creates a Pinterest-like layout with optimal space utilization.
     *
     * @param  array  $scheme   Masonry grid configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML masonry grid
     * @access public
     * @static
     * @since  1.0.0
     *
     * @example
     * $html = LayoutRenderer::render_masonry_grid([
     *     'columns' => 3,
     *     'gap' => '20px',
     *     'data' => [
     *         ['type' => 'card', 'style' => 'height: 200px;'],
     *         ['type' => 'card', 'style' => 'height: 300px;'],
     *         ['type' => 'card', 'style' => 'height: 250px;']
     *     ]
     * ], $context);
     */
    public static function render_masonry_grid( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'masonry_grid' ) );

        if ( has_filter( 'ultraguard_masonry_grid_scheme' ) ) {
            $scheme = apply_filters( 'ultraguard_masonry_grid_scheme', $scheme, $context );
        }

        $scheme['class'] = ! empty( $scheme['class'] ) ?
            sanitize_html_class( $scheme['class'] ) . ' ultraguard-masonry-grid' :
            'ultraguard-masonry-grid';

        $columns = max( 1, min( 6, absint( $scheme['columns'] ) ) );
        $gap = self::sanitize_css_unit_static( $scheme['gap'] );

        $style = sprintf(
            'column-count: %d; column-gap: %s;',
            $columns,
            $gap
        );

        $existing_style = ! empty( $scheme['style'] ) ? self::sanitize_css_static( $scheme['style'] ) . '; ' : '';
        $scheme['style'] = $existing_style . $style;

        $content = '';
        if ( ! empty( $scheme['data'] ) ) {
            $content = $instance->render_children( $scheme['data'], $context );
        }

        $output = $instance->render_wrapper( $content, $scheme, $context );
        return $instance->after_render( $output, $scheme, $context );
    }

    /**
     * Render tabs
     *
     * Renders a tabbed interface with navigation and content panes.
     * Supports icons, badges, capability checks, and conditional rendering
     * for individual tabs.
     *
     * @param  array  $scheme   Tabs configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML tabs interface
     * @throws \Exception       If tabs configuration is missing or invalid
     * @access public
     * @static
     * @since  1.0.0
     *
     * @example
     * $html = LayoutRenderer::render_tabs([
     *     'tabs' => [
     *         'general' => [
     *             'title' => 'General',
     *             'icon' => 'dashicons-admin-generic',
     *             'data' => [/* tab content *\/]
     *         ],
     *         'advanced' => [
     *             'title' => 'Advanced',
     *             'badge' => 3,
     *             'capability' => 'manage_options'
     *         ]
     *     ]
     * ], $context);
     */
    public static function render_tabs( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'tabs' ) );

        if ( has_filter( 'ultraguard_tabs_scheme' ) ) {
            $scheme = apply_filters( 'ultraguard_tabs_scheme', $scheme, $context );
        }

        if ( empty( $scheme['tabs'] ) || ! is_array( $scheme['tabs'] ) ) {
            return $instance->handle_render_error( __( 'Tabs configuration missing', 'ultraguard-security-suite' ), $scheme );
        }

        $tabs_nav = [];
        $tabs_content = [];
        $first = true;

        foreach ( $scheme['tabs'] as $tab_id => $tab_config ) {
            $tab_config = wp_parse_args( $tab_config, self::get_default_scheme( 'tab_config' ) );

            if ( has_filter( 'ultraguard_tab_config' ) ) {
                $tab_config = apply_filters( 'ultraguard_tab_config', $tab_config, $tab_id, $context );
            }

            if ( ! $instance->should_render_tab( $tab_config, $context ) ) {
                continue;
            }

            $active_class = $first ? ' ultraguard-tab-active' : '';
            $first = false;

            $icon_html = '';
            if ( ! empty( $tab_config['icon'] ) ) {
                $icon_html = $instance->render_ui_icon( $tab_config['icon'] );
            }

            $badge_html = '';
            if ( ! empty( $tab_config['badge'] ) && $tab_config['badge'] > 0 ) {
                $badge_html = sprintf( '<span class="ultraguard-tab-badge">%d</span>', absint( $tab_config['badge'] ) );
            }

            // Resolve tab ID: prefer the 'id' field inside the config (supports indexed arrays
            // like DashboardSettings). Falls back to the array key for associative arrays.
            $resolved_id      = ! empty( $tab_config['id'] ) ? $tab_config['id'] : $tab_id;
            $sanitized_tab_id = sanitize_html_class( (string) $resolved_id );

            $tabs_nav[] = sprintf(
                '<li class="ultraguard-tab-nav-item%s">' .
                '<a href="#%s" class="ultraguard-tab-nav-link" data-tab="%s">%s%s%s</a>' .
                '</li>',
                $active_class,
                esc_attr( $sanitized_tab_id ),
                esc_attr( $sanitized_tab_id ),
                $icon_html,
                $instance->escape( $tab_config['title'] ),
                $badge_html
            );

            $tab_content = '';
            if ( ! empty( $tab_config['data'] ) ) {
                $tab_content = $instance->render_children( $tab_config['data'], $context );
            }

            $display_class = $active_class ? 'ultraguard-tab-active' : '';

            $tabs_content[] = sprintf(
                '<div id="%s" class="ultraguard-tab-pane %s">%s</div>',
                esc_attr( $sanitized_tab_id ),
                $display_class,
                $tab_content
            );
        }

        if ( empty( $tabs_nav ) ) {
            return '';
        }

        $output = sprintf(
            '<div class="ultraguard-tabs">' .
            '<ul class="ultraguard-tab-nav">%s</ul>' .
            '<div class="ultraguard-tab-content">%s</div>' .
            '</div>',
            implode( '', $tabs_nav ),
            implode( '', $tabs_content )
        );

        $output = $instance->render_wrapper( $output, $scheme, $context );
        $output = $instance->after_render( $output, $scheme, $context );

        if ( has_filter( 'ultraguard_tabs_output' ) ) {
            return apply_filters( 'ultraguard_tabs_output', $output, $scheme, $context );
        }

        return $output;
    }

    /**
     * Render vertical tabs
     *
     * Renders a vertical tabbed interface with sidebar navigation and
     * content panes. Suitable for settings pages and complex forms where
     * multiple related sections need clear visual separation.
     *
     * @param  array  $scheme   Vertical tabs configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML vertical tabs interface
     * @throws \Exception       If tabs configuration is missing or invalid
     * @access public
     * @static
     * @since  1.0.0
     *
     * @example
     * $html = LayoutRenderer::render_vertical_tabs([
     *     'tabs' => [
     *         'appearance' => [
     *             'title' => 'Appearance',
     *             'icon' => 'dashicons-admin-appearance'
     *         ],
     *         'functionality' => [
     *             'title' => 'Functionality',
     *             'icon' => 'dashicons-admin-tools'
     *         ]
     *     ]
     * ], $context);
     */
    public static function render_vertical_tabs( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'vertical_tabs' ) );

        if ( has_filter( 'ultraguard_vertical_tabs_scheme' ) ) {
            $scheme = apply_filters( 'ultraguard_vertical_tabs_scheme', $scheme, $context );
        }

        if ( empty( $scheme['tabs'] ) || ! is_array( $scheme['tabs'] ) ) {
            return $instance->handle_render_error( __( 'Vertical tabs configuration missing', 'ultraguard-security-suite' ), $scheme );
        }

        $tabs_nav = [];
        $tabs_content = [];
        $first = true;

        foreach ( $scheme['tabs'] as $tab_id => $tab_config ) {
            $tab_config = wp_parse_args( $tab_config, self::get_default_scheme( 'tab_config' ) );

            if ( has_filter( 'ultraguard_vertical_tab_config' ) ) {
                $tab_config = apply_filters( 'ultraguard_vertical_tab_config', $tab_config, $tab_id, $context );
            }

            if ( ! $instance->should_render_tab( $tab_config, $context ) ) {
                continue;
            }

            $active_class = $first ? ' ultraguard-tab-active' : '';
            $first = false;

            $icon_html = '';
            if ( ! empty( $tab_config['icon'] ) ) {
                $icon_html = $instance->render_ui_icon( $tab_config['icon'] );
            }

            $badge_html = '';
            if ( ! empty( $tab_config['badge'] ) && $tab_config['badge'] > 0 ) {
                $badge_html = sprintf( '<span class="ultraguard-tab-badge">%d</span>', absint( $tab_config['badge'] ) );
            }

            // Resolve tab ID: prefer the 'id' field inside the config (supports indexed arrays
            // like DashboardSettings). Falls back to the array key for associative arrays.
            $resolved_id      = ! empty( $tab_config['id'] ) ? $tab_config['id'] : $tab_id;
            $sanitized_tab_id = sanitize_html_class( (string) $resolved_id );

            $tabs_nav[] = sprintf(
                '<li class="ultraguard-tab-nav-item%s">' .
                '<a href="#%s" class="ultraguard-tab-nav-link" data-tab="%s">%s%s%s</a>' .
                '</li>',
                $active_class,
                esc_attr( $sanitized_tab_id ),
                esc_attr( $sanitized_tab_id ),
                $icon_html,
                $instance->escape( $tab_config['title'] ),
                $badge_html
            );

            $tab_content = '';
            if ( ! empty( $tab_config['data'] ) ) {
                $tab_content = $instance->render_children( $tab_config['data'], $context );
            }

            $display_class = $active_class ? 'ultraguard-tab-active' : '';

            $tabs_content[] = sprintf(
                '<div id="%s" class="ultraguard-tab-pane %s">%s</div>',
                esc_attr( $sanitized_tab_id ),
                $display_class,
                $tab_content
            );
        }

        if ( empty( $tabs_nav ) ) {
            return '';
        }

        $output = sprintf(
            '<div class="ultraguard-tabs ultraguard-tabs-vertical">' .
            '<div class="ultraguard-tabs-sidebar">' .
            '<ul class="ultraguard-tab-nav">%s</ul>' .
            '</div>' .
            '<div class="ultraguard-tabs-content">%s</div>' .
            '</div>',
            implode( '', $tabs_nav ),
            implode( '', $tabs_content )
        );

        $output = $instance->render_wrapper( $output, $scheme, $context );
        $output = $instance->after_render( $output, $scheme, $context );

        if ( has_filter( 'ultraguard_vertical_tabs_output' ) ) {
            return apply_filters( 'ultraguard_vertical_tabs_output', $output, $scheme, $context );
        }

        return $output;
    }

    /**
     * Render accordion
     *
     * Renders a collapsible accordion interface with expandable panels.
     * Each panel can have a title, icon, and content. Supports capability
     * checks and conditional rendering for individual panels.
     *
     * @param  array  $scheme   Accordion configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML accordion
     * @throws \Exception       If panels configuration is missing or invalid
     * @access public
     * @static
     * @since  1.0.0
     *
     * @example
     * $html = LayoutRenderer::render_accordion([
     *     'panels' => [
     *         'panel1' => [
     *             'title' => 'First Panel',
     *             'icon' => 'dashicons-info',
     *             'data' => [/* panel content *\/]
     *         ],
     *         'panel2' => [
     *             'title' => 'Second Panel',
     *             'capability' => 'edit_posts'
     *         ]
     *     ]
     * ], $context);
     */
    public static function render_accordion( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'accordion' ) );

        if ( has_filter( 'ultraguard_accordion_scheme' ) ) {
            $scheme = apply_filters( 'ultraguard_accordion_scheme', $scheme, $context );
        }

        if ( empty( $scheme['panels'] ) || ! is_array( $scheme['panels'] ) ) {
            return $instance->handle_render_error( __( 'Accordion panels configuration missing', 'ultraguard-security-suite' ), $scheme );
        }

        $panels_html = [];

        foreach ( $scheme['panels'] as $panel_id => $panel_config ) {
            $panel_config = wp_parse_args( $panel_config, self::get_default_scheme( 'panel_config' ) );

            if ( has_filter( 'ultraguard_accordion_panel_config' ) ) {
                $panel_config = apply_filters( 'ultraguard_accordion_panel_config', $panel_config, $panel_id, $context );
            }

            if ( ! $instance->should_render_panel( $panel_config, $context ) ) {
                continue;
            }

            $panel_content = '';
            if ( ! empty( $panel_config['data'] ) ) {
                $panel_content = $instance->render_children( $panel_config['data'], $context );
            }

            $icon_html = '';
            if ( ! empty( $panel_config['icon'] ) ) {
                $icon_html = $instance->render_ui_icon( $panel_config['icon'] );
            }

            $panels_html[] = sprintf(
                '<div class="ultraguard-accordion-panel">' .
                '<div class="ultraguard-accordion-header">' .
                '<h4>%s%s</h4>' .
                '<span class="ultraguard-accordion-toggle"></span>' .
                '</div>' .
                '<div class="ultraguard-accordion-content">%s</div>' .
                '</div>',
                $icon_html,
                $instance->escape( $panel_config['title'] ),
                $panel_content
            );
        }

        if ( empty( $panels_html ) ) {
            return '';
        }

        $output = $instance->render_wrapper( implode( '', $panels_html ), $scheme, $context );
        $output = $instance->after_render( $output, $scheme, $context );

        if ( has_filter( 'ultraguard_accordion_output' ) ) {
            return apply_filters( 'ultraguard_accordion_output', $output, $scheme, $context );
        }

        return $output;
    }

    /**
     * Render wizard (step-by-step process)
     *
     * Renders a multi-step wizard interface with progress indicator and
     * navigation controls. Useful for guided setup processes, multi-step
     * forms, or onboarding flows.
     *
     * @param  array  $scheme   Wizard configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML wizard
     * @access public
     * @static
     * @since  1.0.0
     *
     * @example
     * $html = LayoutRenderer::render_wizard([
     *     'current_step' => 1,
     *     'steps' => [
     *         ['label' => 'Step 1: Basic Info', 'data' => [/* step content *\/]],
     *         ['label' => 'Step 2: Configuration', 'data' => [/* step content *\/]],
     *         ['label' => 'Step 3: Review', 'data' => [/* step content *\/]]
     *     ]
     * ], $context);
     */
    public static function render_wizard( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'wizard' ) );

        $steps_count = count( $scheme['steps'] );
        if ( $steps_count === 0 ) {
            return '';
        }

        $current_step = absint( $scheme['current_step'] );

        $steps_html = '<div class="ultraguard-steps">';
        $content_html = '<div class="ultraguard-wizard-content">';

        foreach ( $scheme['steps'] as $index => $step ) {
            $step_number = $index + 1;
            $is_active = ( $step_number === $current_step );
            $is_completed = ( $step_number < $current_step );

            $class = 'ultraguard-step-item';
            if ( $is_active ) $class .= ' active';
            if ( $is_completed ) $class .= ' completed';

            $steps_html .= sprintf(
                '<div class="%s">' .
                '<div class="ultraguard-step-indicator">%s</div>' .
                '<div class="ultraguard-step-label">%s</div>' .
                '</div>',
                esc_attr( $class ),
                $is_completed ? $instance->render_ui_icon( 'dashicons-yes' ) : absint( $step_number ),
                esc_html( is_array( $step['label'] ) ? (string)( $step['label']['text'] ?? $step['label']['content'] ?? wp_json_encode( $step['label'] ) ) : (string)( $step['label'] ) )
            );

            if ( $is_active && ! empty( $step['data'] ) ) {
                $content_html .= $instance->render_children( $step['data'], $context );
            }
        }

        $steps_html .= '</div>';
        $content_html .= '</div>';

        $nav_html = sprintf(
            '<div class="ultraguard-wizard-actions">' .
            '<button class="button ultraguard-button-secondary" %s>%s</button>' .
            '<button class="button ultraguard-button-primary">%s</button>' .
            '</div>',
            ( $current_step === 1 ) ? 'disabled' : '',
            esc_html__( 'Previous', 'ultraguard-security-suite' ),
            ( $current_step === $steps_count ) ? esc_html__( 'Finish', 'ultraguard-security-suite' ) : esc_html__( 'Next', 'ultraguard-security-suite' )
        );

        $output = $instance->render_wrapper( $steps_html . $content_html . $nav_html, $scheme, $context );
        return $instance->after_render( $output, $scheme, $context );
    }

    /**
     * Render modal layout (alternative to widget modal)
     *
     * Delegates modal rendering to the WidgetRenderer class to maintain
     * consistency and reuse existing modal functionality.
     *
     * @param  array  $scheme   Modal configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML modal
     * @access public
     * @static
     * @since  1.0.0
     *
     * @see WidgetRenderer::render_modal()
     */
    public static function render_modal( $scheme, $context ) {
        return WidgetRenderer::render_modal( $scheme, $context );
    }

    /**
     * Render Drawer (Off-canvas panel)
     *
     * Renders a sliding drawer panel that appears from the edge of the screen.
     * Useful for settings panels, notifications, or secondary navigation.
     *
     * @param  array  $scheme   Drawer configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML drawer
     * @access public
     * @static
     * @since  1.0.0
     *
     * @example
     * $html = LayoutRenderer::render_drawer([
     *     'position' => 'right',
     *     'title' => 'Settings',
     *     'data' => [/* drawer content *\/]
     * ], $context);
     */
    public static function render_drawer( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'drawer' ) );

        $content = '';
        if ( ! empty( $scheme['data'] ) ) {
            $content = $instance->render_children( $scheme['data'], $context );
        }

        $position_class = 'ultraguard-drawer-' . sanitize_key( $scheme['position'] );

        $output = sprintf(
            '<div class="ultraguard-drawer-overlay" id="%s">' .
            '<div class="ultraguard-drawer %s">' .
            '<div class="ultraguard-drawer-header">' .
            '<h3>%s</h3>' .
            '<button class="ultraguard-drawer-close">&times;</button>' .
            '</div>' .
            '<div class="ultraguard-drawer-body">%s</div>' .
            '</div>' .
            '</div>',
            esc_attr( $scheme['id'] ),
            esc_attr( $position_class ),
            esc_html( is_array( $scheme['title'] ) ? (string)( $scheme['title']['text'] ?? $scheme['title']['content'] ?? wp_json_encode( $scheme['title'] ) ) : (string)( $scheme['title'] ) ),
            $content
        );

        return $output;
    }

    /**
     * Render Card Deck (Group of equal height cards)
     *
     * Renders a deck of cards with equal height and consistent spacing.
     * Cards automatically align vertically and maintain uniform appearance
     * across the deck.
     *
     * @param  array  $scheme   Card deck configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML card deck
     * @access public
     * @static
     * @since  1.0.0
     *
     * @example
     * $html = LayoutRenderer::render_card_deck([
     *     'cards' => [
     *         ['type' => 'card', 'title' => 'Card 1', 'content' => 'Content 1'],
     *         ['type' => 'card', 'title' => 'Card 2', 'content' => 'Content 2'],
     *         ['type' => 'card', 'title' => 'Card 3', 'content' => 'Content 3']
     *     ],
     *     'class' => 'my-card-deck'
     * ], $context);
     */
    public static function render_card_deck( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'card_deck' ) );

        $cards_html = '';
        if ( ! empty( $scheme['cards'] ) ) {
            foreach ( $scheme['cards'] as $card ) {
                $card['type'] = 'card';
                $cards_html .= $instance->engine->render( $card, $context );
            }
        }

        $scheme['class'] = trim( ( $scheme['class'] ?? '' ) . ' ultraguard-card-deck' );

        return $instance->render_wrapper( $cards_html, $scheme, $context );
    }

    /**
     * Render Sticky Container
     *
     * Renders a container that sticks to the viewport when scrolling.
     * Useful for navigation bars, action buttons, or important notices
     * that should remain visible.
     *
     * @param  array  $scheme   Sticky container configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML sticky container
     * @access public
     * @static
     * @since  1.0.0
     *
     * @example
     * $html = LayoutRenderer::render_sticky_container([
     *     'position' => 'top',
     *     'offset' => 20,
     *     'data' => [/* sticky content *\/],
     *     'style' => 'background: white; box-shadow: 0 2px 5px rgba(0,0,0,0.1);'
     * ], $context);
     */
    public static function render_sticky_container( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'sticky_container' ) );

        $content = $instance->render_children( $scheme['data'], $context );

        $style = sprintf(
            'position: sticky; %s: %dpx; z-index: 100;',
            sanitize_key( $scheme['position'] ),
            intval( $scheme['offset'] )
        );

        $existing_style = isset( $scheme['style'] ) ? self::sanitize_css_static( $scheme['style'] ) . '; ' : '';
        $scheme['style'] = $existing_style . $style;

        $existing_class = isset( $scheme['class'] ) ? $scheme['class'] . ' ' : '';
        $scheme['class'] = $existing_class . 'ultraguard-sticky-container';

        return $instance->render_wrapper( $content, $scheme, $context );
    }

    /**
     * Render page - UPDATED METHOD
     *
     * Renders a complete page structure with header, main content area,
     * sidebar, footer, and optional form wrapper. Supports different layout
     * types including vertical tabs for complex settings pages.
     *
     * @param  array  $scheme   Page configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered HTML page
     * @access public
     * @static
     * @since  1.0.0
     *
     * @example
     * $html = LayoutRenderer::render_page([
     *     'header' => ['title' => 'My Page', 'subtitle' => 'Page subtitle'],
     *     'layout' => ['type' => 'vertical_tabs'],
     *     'tabs' => [
     *         'tab1' => ['title' => 'Tab 1', 'data' => [/* content *\/]],
     *         'tab2' => ['title' => 'Tab 2', 'data' => [/* content *\/]]
     *     ],
     *     'form' => ['enable' => true, 'method' => 'post'],
     *     'footer' => ['submit_button' => true, 'submit_text' => 'Save']
     * ], $context);
     */
    public static function render_page( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'page' ) );

        if ( has_filter( 'ultraguard_page_scheme' ) ) {
            $scheme = apply_filters( 'ultraguard_page_scheme', $scheme, $context );
        }

        $framework_class = 'ultraguard-framework';
        if ( isset( $scheme['layout']['type'] ) && $scheme['layout']['type'] === 'vertical_tabs' ) {
            $framework_class .= ' with-vertical-tabs';
        }

        $header = '';
        if ( ! empty( $scheme['header'] ) ) {
            $header = $instance->render_page_header( $scheme['header'], $context );
        }

        $main_content = '';
        if ( ! empty( $scheme['data'] ) ) {
            $main_content = $instance->render_children( $scheme['data'], $context );
        } elseif ( isset( $scheme['tabs'] ) ) {
            $tabs_scheme = $scheme;
            $tabs_scheme['type'] = 'tabs';
            $main_content = $instance->engine->render( $tabs_scheme, $context );
        }

        $sidebar = '';
        if ( ! empty( $scheme['sidebar'] ) ) {
            $sidebar = $instance->render_sidebar( $scheme['sidebar'], $context );
        }

        // Build page footer.
        // Priority 1: explicit 'footer' key in the page scheme.
        // Priority 2: auto-generate from form['submit'] so that settings pages
        //             that define 'form' => ['submit' => [...]] always get a
        //             proper sticky footer with the save button — even when no
        //             explicit 'footer' key is present.
        $footer_config = [];
        if ( ! empty( $scheme['footer'] ) ) {
            $footer_config = $scheme['footer'];
        } elseif ( ! empty( $scheme['form']['enable'] ) && ! empty( $scheme['form']['submit'] ) ) {
            $submit_cfg    = $scheme['form']['submit'];
            $submit_text   = is_array( $submit_cfg ) ? ( $submit_cfg['text'] ?? __( 'Save Changes', 'ultraguard-security-suite' ) ) : (string) $submit_cfg;
            $footer_config = [
                'submit_button' => true,
                'submit_text'   => $submit_text,
            ];
        }

        $footer = '';
        if ( ! empty( $footer_config ) ) {
            $footer = $instance->render_page_footer( $footer_config, $context );
        }

        $footer_wrapper = '';
        if ( $footer ) {
            $footer_wrapper = sprintf( '<div class="ultraguard-page-footer-wrapper">%s</div>', $footer );
        }

        $form_start = '';
        $form_end   = '';
        if ( ! empty( $scheme['form']['enable'] ) ) {
            $form_start = $instance->render_form_start( $scheme['form'] );
            $form_end   = '</form>';
        }

        // render_page emits ONLY the page's inner content structure.
        // The outer .ultraguard-framework / .ultraguard-app-layout wrapper is
        // provided by Admin::render_app_shell() — do NOT double-wrap here.
        //
        // IMPORTANT: The form wrapper must encompass the footer so that submit
        // buttons inside the page footer are actually inside the <form> element.
        $page_class = $scheme['class'] ?? '';
        $page_id_attr = ! empty( $scheme['id'] ) ? ' id="' . esc_attr( $scheme['id'] ) . '"' : '';

        // Detect whether this is a settings/form page (has no sidebar) so we
        // can add a utility class for full-width layout.
        $has_sidebar   = ! empty( $scheme['sidebar'] );
        $extra_classes = ! $has_sidebar ? ' ultraguard-page-no-sidebar' : '';
        $page_class_attr = ' class="' . esc_attr( trim( $page_class . $extra_classes ) ) . '"';

        $output = sprintf(
            '%s' .
            '<div%s%s>' .
            '<div class="ultraguard-page-header-wrapper">%s</div>' .
            '<div id="ultraguard-page-notification-wrapper" class="ultraguard-page-notification-wrapper"></div>' .
            '<div class="ultraguard-page-content-wrapper">' .
            '<div class="ultraguard-main-content">%s</div>' .
            '%s' .
            '</div>' .
            '%s' .
            '</div>%s',
            $form_start,
            $page_id_attr,
            $page_class_attr,
            $header,
            $main_content,
            $sidebar,
            $footer_wrapper,
            $form_end
        );

        $output = $instance->after_render( $output, $scheme, $context );

        if ( has_filter( 'ultraguard_page_output' ) ) {
            return apply_filters( 'ultraguard_page_output', $output, $scheme, $context );
        }

        return $output;
    }

    /**
     * Render page header
     *
     * Renders the page header section with title, subtitle, icon, and
     * optional action buttons. Provides a consistent header area for
     * page-level content.
     *
     * @param  array  $header_config  Header configuration array
     * @param  array  $context        Context data for rendering
     * @return string                 Rendered page header HTML
     * @access protected
     * @since  1.0.0
     *
     * @example
     * $header = $this->render_page_header([
     *     'title' => 'Dashboard',
     *     'subtitle' => 'Welcome to your dashboard',
     *     'icon' => 'dashicons-dashboard',
     *     'actions' => [
     *         ['type' => 'button', 'label' => 'Add New', 'style' => 'primary']
     *     ]
     * ], $context);
     */
    protected function render_page_header( $header_config, $context ) {
        $header_config = wp_parse_args( $header_config, self::get_default_scheme( 'page_header' ) );

        if ( has_filter( 'ultraguard_page_header_config' ) ) {
            $header_config = apply_filters( 'ultraguard_page_header_config', $header_config, $context );
        }

        $title_html = '';
        if ( ! empty( $header_config['title'] ) ) {
            $icon_html = '';
            if ( ! empty( $header_config['icon'] ) ) {
                $icon_html = $this->render_ui_icon( $header_config['icon'] );
            }

            $subtitle_html = '';
            if ( ! empty( $header_config['subtitle'] ) ) {
                $subtitle_html = sprintf( '<p class="ultraguard-page-subtitle">%s</p>', $this->escape( $header_config['subtitle'] ) );
            }

            // Render optional header badge
            $header_badge_html = '';
            if ( ! empty( $header_config['badge'] ) ) {
                $badge_val = $header_config['badge'];
                if ( is_array( $badge_val ) ) {
                    $badge_text  = $badge_val['text']       ?? $badge_val['content'] ?? '';
                    $badge_type  = $badge_val['badge_type'] ?? 'info';
                    $badge_id    = ! empty( $badge_val['id'] ) ? ' id="' . esc_attr( $badge_val['id'] ) . '"' : '';
                    $header_badge_html = sprintf(
                        '<span%s class="ultraguard-header-badge ultraguard-badge ultraguard-badge-%s">%s</span>',
                        $badge_id,
                        esc_attr( sanitize_key( $badge_type ) ),
                        esc_html( is_scalar( $badge_text ) ? (string) $badge_text : '' )
                    );
                } elseif ( is_scalar( $badge_val ) && $badge_val !== '' ) {
                    $header_badge_html = sprintf(
                        '<span class="ultraguard-header-badge ultraguard-badge ultraguard-badge-info">%s</span>',
                        esc_html( (string) $badge_val )
                    );
                }
            }

            // Build icon box matching .ultraguard-page-title-icon CSS
            $icon_box_html = '';
            if ( ! empty( $icon_html ) ) {
                $icon_box_html = sprintf(
                    '<div class="ultraguard-page-title-icon">%s</div>',
                    $icon_html
                );
            }

            // Build text block matching .ultraguard-page-title-text CSS
            $title_text_html = sprintf(
                '<div class="ultraguard-page-title-text">'
                . '<h1>%s%s</h1>'
                . '%s'
                . '</div>',
                $this->escape( $header_config['title'] ),
                $header_badge_html,
                $subtitle_html
            );

            $title_html = sprintf(
                '<div class="ultraguard-page-title">'
                . '<div class="ultraguard-page-title-main">%s%s</div>'
                . '</div>',
                $icon_box_html,
                $title_text_html
            );
        }

        $actions_html = '';
        if ( ! empty( $header_config['actions'] ) && is_array( $header_config['actions'] ) ) {
            $actions_content = '';
            foreach ( $header_config['actions'] as $index => $action ) {
                if ( has_filter( 'ultraguard_page_header_action' ) ) {
                    $action = apply_filters( 'ultraguard_page_header_action', $action, $index, $context );
                }
                $actions_content .= $this->engine->render( $action, $context );
            }
            $actions_html = sprintf( '<div class="ultraguard-page-actions">%s</div>', $actions_content );
        }

        $header_output = sprintf(
            '<div class="ultraguard-page-header">%s%s</div>',
            $title_html,
            $actions_html
        );

        if ( has_filter( 'ultraguard_page_header_output' ) ) {
            return apply_filters( 'ultraguard_page_header_output', $header_output, $header_config, $context );
        }

        return $header_output;
    }

    /**
     * Render sidebar
     *
     * Renders a sidebar area containing widget components. Useful for
     * displaying supplementary information, navigation, or secondary
     * actions alongside main content.
     *
     * @param  array  $sidebar_config  Sidebar configuration array
     * @param  array  $context         Context data for rendering
     * @return string                  Rendered sidebar HTML
     * @access protected
     * @since  1.0.0
     *
     * @example
     * $sidebar = $this->render_sidebar([
     *     'widgets' => [
     *         ['type' => 'card', 'title' => 'Help', 'content' => 'Help content'],
     *         ['type' => 'list', 'items' => ['Item 1', 'Item 2']]
     *     ]
     * ], $context);
     */
    protected function render_sidebar( $sidebar_config, $context ) {
        $sidebar_config = wp_parse_args( $sidebar_config, self::get_default_scheme( 'sidebar' ) );

        if ( has_filter( 'ultraguard_sidebar_config' ) ) {
            $sidebar_config = apply_filters( 'ultraguard_sidebar_config', $sidebar_config, $context );
        }

        $widgets_html = '';
        if ( ! empty( $sidebar_config['widgets'] ) && is_array( $sidebar_config['widgets'] ) ) {
            foreach ( $sidebar_config['widgets'] as $index => $widget ) {
                if ( has_filter( 'ultraguard_sidebar_widget' ) ) {
                    $widget = apply_filters( 'ultraguard_sidebar_widget', $widget, $index, $context );
                }
                $widgets_html .= $this->engine->render( $widget, $context );
            }
        }

        $sidebar_output = sprintf(
            '<div class="ultraguard-sidebar">%s</div>',
            $widgets_html
        );

        if ( has_filter( 'ultraguard_sidebar_output' ) ) {
            return apply_filters( 'ultraguard_sidebar_output', $sidebar_output, $sidebar_config, $context );
        }

        return $sidebar_output;
    }

    /**
     * Render page footer - UPDATED METHOD
     *
     * Renders the page footer section with optional action buttons and
     * submit button. Typically used for form submission controls or
     * page-level navigation actions.
     *
     * @param  array  $footer_config  Footer configuration array
     * @param  array  $context        Context data for rendering
     * @return string                 Rendered page footer HTML
     * @access protected
     * @since  1.0.0
     *
     * @example
     * $footer = $this->render_page_footer([
     *     'actions' => [
     *         ['type' => 'button', 'label' => 'Cancel', 'style' => 'secondary'],
     *         ['type' => 'button', 'label' => 'Reset', 'style' => 'secondary']
     *     ],
     *     'submit_button' => true,
     *     'submit_text' => 'Save Changes'
     * ], $context);
     */
    protected function render_page_footer( $footer_config, $context ) {
        $footer_config = wp_parse_args( $footer_config, self::get_default_scheme( 'page_footer' ) );

        if ( has_filter( 'ultraguard_page_footer_config' ) ) {
            $footer_config = apply_filters( 'ultraguard_page_footer_config', $footer_config, $context );
        }

        $actions_html = '';
        if ( ! empty( $footer_config['actions'] ) && is_array( $footer_config['actions'] ) ) {
            $actions_content = '';
            foreach ( $footer_config['actions'] as $index => $action ) {
                if ( has_filter( 'ultraguard_page_footer_action' ) ) {
                    $action = apply_filters( 'ultraguard_page_footer_action', $action, $index, $context );
                }
                $actions_content .= $this->engine->render( $action, $context );
            }
            $actions_html = sprintf( '<div class="ultraguard-page-footer-actions">%s</div>', $actions_content );
        }

        $submit_html = '';
        if ( ! empty( $footer_config['submit_button'] ) ) {
            $submit_html = sprintf(
                '<div class="ultraguard-page-footer-submit">' .
                '<button type="submit" class="button button-primary ultraguard-button ultraguard-button-primary">%s</button>' .
                '</div>',
                $this->escape( $footer_config['submit_text'] )
            );
        }

        if ( $actions_html || $submit_html ) {
            $footer_output = sprintf(
                '<div class="ultraguard-page-footer">%s%s</div>',
                $actions_html,
                $submit_html
            );

            if ( has_filter( 'ultraguard_page_footer_output' ) ) {
                return apply_filters( 'ultraguard_page_footer_output', $footer_output, $footer_config, $context );
            }

            return $footer_output;
        }

        return '';
    }

    /**
     * Render section header
     *
     * Renders the header section for a content section with title,
     * description, icon, and optional action buttons.
     *
     * @param  array  $scheme   Section configuration scheme
     * @param  array  $context  Context data for rendering
     * @return string           Rendered section header HTML
     * @access protected
     * @since  1.0.0
     */
    protected function render_section_header( $scheme, $context ) {
        $scheme = wp_parse_args( $scheme, self::get_default_scheme( 'section' ) );

        if ( has_filter( 'ultraguard_section_header_scheme' ) ) {
            $scheme = apply_filters( 'ultraguard_section_header_scheme', $scheme, $context );
        }

        $icon_html = '';
        if ( ! empty( $scheme['icon'] ) ) {
            $icon_html = $this->render_ui_icon( $scheme['icon'] );
        }

        $description_html = '';
        if ( ! empty( $scheme['description'] ) ) {
            $description_html = sprintf( '<p class="ultraguard-section-description">%s</p>', $this->escape( $scheme['description'] ) );
        }

        $actions_html = '';
        if ( ! empty( $scheme['actions'] ) && is_array( $scheme['actions'] ) ) {
            $actions_content = '';
            foreach ( $scheme['actions'] as $index => $action ) {
                if ( has_filter( 'ultraguard_section_header_action' ) ) {
                    $action = apply_filters( 'ultraguard_section_header_action', $action, $index, $context );
                }
                $actions_content .= $this->engine->render( $action, $context );
            }
            $actions_html = sprintf( '<div class="ultraguard-section-actions">%s</div>', $actions_content );
        }

        $header_output = sprintf(
            '<div class="ultraguard-section-header">' .
            '<div class="ultraguard-section-title">%s<h3>%s</h3>%s</div>' .
            '%s' .
            '</div>',
            $icon_html,
            $this->escape( $scheme['title'] ),
            $description_html,
            $actions_html
        );

        if ( has_filter( 'ultraguard_section_header_output' ) ) {
            return apply_filters( 'ultraguard_section_header_output', $header_output, $scheme, $context );
        }

        return $header_output;
    }

    /**
     * Check if tab should be rendered
     *
     * Determines whether a tab should be rendered based on user capabilities
     * and conditional logic. Provides security and dynamic interface control.
     *
     * @param  array  $tab_config  Tab configuration array
     * @param  array  $context     Context data for evaluation
     * @return bool                True if tab should be rendered, false otherwise
     * @access protected
     * @since  1.0.0
     *
     * @see ConditionalRenderer::evaluate()
     */
    protected function should_render_tab( $tab_config, $context ) {
        if ( ! empty( $tab_config['capability'] ) ) {
            if ( ! current_user_can( $tab_config['capability'] ) ) {
                return false;
            }
        }

        if ( isset( $tab_config['condition'] ) ) {
            $conditional_renderer = ConditionalRenderer::get_instance();
            if ( ! $conditional_renderer->evaluate( $tab_config['condition'], $context ) ) {
                return false;
            }
        }

        return true;
    }

    /**
     * Check if accordion panel should be rendered
     *
     * Determines whether an accordion panel should be rendered based on
     * user capabilities and conditional logic.
     *
     * @param  array  $panel_config  Panel configuration array
     * @param  array  $context       Context data for evaluation
     * @return bool                  True if panel should be rendered, false otherwise
     * @access protected
     * @since  1.0.0
     *
     * @see ConditionalRenderer::evaluate()
     */
    protected function should_render_panel( $panel_config, $context ) {
        if ( ! empty( $panel_config['capability'] ) ) {
            if ( ! current_user_can( $panel_config['capability'] ) ) {
                return false;
            }
        }

        if ( isset( $panel_config['condition'] ) ) {
            $conditional_renderer = ConditionalRenderer::get_instance();
            if ( ! $conditional_renderer->evaluate( $panel_config['condition'], $context ) ) {
                return false;
            }
        }

        return true;
    }

    /**
     * Sanitize CSS unit values
     *
     * Validates and sanitizes CSS unit values (px, em, rem, %, vh, vw, etc.)
     * and calc() functions. Delegates to static version for caching benefits.
     *
     * @param  string  $value  CSS value to sanitize
     * @return string          Sanitized CSS value
     * @access protected
     * @since  1.0.0
     *
     * @see sanitize_css_unit_static()
     */
    protected function sanitize_css_unit( $value ) {
        return self::sanitize_css_unit_static( $value );
    }

    /**
     * Static version of sanitize_css_unit
     *
     * Validates and sanitizes CSS unit values with caching for performance.
     * Supports common CSS units and calc() functions with safe fallback.
     *
     * @param  string  $value  CSS value to sanitize
     * @return string          Sanitized CSS value
     * @access protected
     * @static
     * @since  1.0.0
     *
     * @example
     * $safe = LayoutRenderer::sanitize_css_unit_static('20px'); // '20px'
     * $safe = LayoutRenderer::sanitize_css_unit_static('calc(50% - 10px)'); // sanitized calc
     * $safe = LayoutRenderer::sanitize_css_unit_static('invalid'); // '20px' (fallback)
     */
    protected static function sanitize_css_unit_static( $value ) {
        if ( empty( $value ) ) {
            return '0';
        }

        if ( isset( self::$css_unit_cache[ $value ] ) ) {
            return self::$css_unit_cache[ $value ];
        }

        $result = '20px';

        if ( preg_match( '/^(\d*\.?\d+)(px|em|rem|%|vh|vw|vmin|vmax|fr|auto)$/', $value, $matches ) ) {
            $result = $matches[1] . $matches[2];
        } elseif ( strpos( $value, 'calc(' ) === 0 && substr( $value, -1 ) === ')' ) {
            $clean_value = preg_replace( '/[^0-9+\-*/().% pxemremvhvwvminvmax]/', '', $value );
            $result = $clean_value;
        }

        self::$css_unit_cache[ $value ] = $result;
        return $result;
    }

    /**
     * Sanitize CSS style string
     *
     * Removes dangerous patterns from CSS strings including expression(),
     * javascript:, vbscript:, @import, and url(). Delegates to static
     * version for caching benefits.
     *
     * @param  string  $css  CSS style string to sanitize
     * @return string        Sanitized CSS string
     * @access protected
     * @since  1.0.0
     *
     * @see sanitize_css_static()
     */
    protected function sanitize_css( $css ) {
        return self::sanitize_css_static( $css );
    }

    /**
     * Static version of sanitize_css
     *
     * Removes dangerous patterns from CSS strings with caching for performance.
     * Ensures safe CSS injection by stripping potentially harmful code.
     *
     * @param  string  $css  CSS style string to sanitize
     * @return string        Sanitized CSS string
     * @access protected
     * @static
     * @since  1.0.0
     *
     * @example
     * $safe = LayoutRenderer::sanitize_css_static('color: red; expression(alert(1));');
     * // Returns: 'color: red;'
     */
    protected static function sanitize_css_static( $css ) {
        if ( empty( $css ) ) {
            return '';
        }

        if ( isset( self::$css_sanitization_cache[ $css ] ) ) {
            return self::$css_sanitization_cache[ $css ];
        }

        $dangerous_patterns = [
            '/expression\s*\(/i',
            '/javascript\s*:/i',
            '/vbscript\s*:/i',
            '/@import/i',
            '/url\s*\([^)]*\)/i',
        ];

        $safe_css = $css;
        foreach ( $dangerous_patterns as $pattern ) {
            $safe_css = preg_replace( $pattern, '', $safe_css );
        }

        $result = wp_strip_all_tags( $safe_css );
        self::$css_sanitization_cache[ $css ] = $result;

        return $result;
    }

    /**
     * Escape output based on context
     *
     * Applies appropriate WordPress escaping functions based on the
     * output context (HTML, attribute, URL, JavaScript) to ensure
     * safe output and prevent XSS vulnerabilities.
     *
     * @param  mixed   $value    Value to escape
     * @param  string  $context  Escape context ('html', 'attribute', 'url', 'js')
     * @return string            Escaped value
     * @access protected
     * @since  1.0.0
     *
     * @see esc_html()
     * @see esc_attr()
     * @see esc_url()
     * @see esc_js()
     */
    protected function escape( $value, $context = 'html' ):string {
        switch ( $context ) {
            case 'attribute':
                return esc_attr( $value );
            case 'url':
                return esc_url( $value );
            case 'js':
                return esc_js( $value );
            case 'html':
            default:
                return esc_html( $value );
        }
    }

    /**
     * Render split-panel layout
     * Two-pane horizontal layout with configurable proportions.
     */
    public static function render_split_panel( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, [
            'left_width' => '50%',
            'gap'        => '24px',
            'left'       => [],
            'right'      => [],
            'id'         => '',
            'class'      => '',
        ] );

        $engine     = \UltraguardPro\view\RenderEngine::get_instance();
        $left_html  = ! empty( $scheme['left']  ) ? $engine->render( $scheme['left'],  $context ) : '';
        $right_html = ! empty( $scheme['right'] ) ? $engine->render( $scheme['right'], $context ) : '';

        $id_attr    = $scheme['id']    ? ' id="' . esc_attr( $scheme['id'] )    . '"' : '';
        $class_attr = $scheme['class'] ? ' class="ultraguard-split-panel ' . esc_attr( $scheme['class'] ) . '"' : ' class="ultraguard-split-panel"';
        $style      = 'display:flex;gap:' . esc_attr( $scheme['gap'] ) . ';align-items:start;';

        return sprintf(
            '<div%s%s style="%s">'
            . '<div class="ultraguard-split-left" style="flex:0 0 %s;min-width:0;">%s</div>'
            . '<div class="ultraguard-split-right" style="flex:1;min-width:0;">%s</div>'
            . '</div>',
            $id_attr, $class_attr, $style,
            esc_attr( $scheme['left_width'] ),
            $left_html, $right_html
        );
    }

    /**
     * Render panel-group layout
     * Stacked panel group — renders each child panel in sequence.
     */
    public static function render_panel_group( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, [
            'panels' => [],
            'gap'    => '16px',
            'id'     => '',
            'class'  => '',
        ] );

        $engine  = \UltraguardPro\view\RenderEngine::get_instance();
        $panels  = is_array( $scheme['panels'] ) ? $scheme['panels'] : [];
        $output  = '';

        foreach ( $panels as $panel ) {
            if ( is_array( $panel ) ) {
                $output .= $engine->render( $panel, $context );
            }
        }

        $id_attr    = $scheme['id']    ? ' id="' . esc_attr( $scheme['id'] )    . '"' : '';
        $class_attr = $scheme['class'] ? ' class="ultraguard-panel-group ' . esc_attr( $scheme['class'] ) . '"' : ' class="ultraguard-panel-group"';
        $style      = 'display:flex;flex-direction:column;gap:' . esc_attr( $scheme['gap'] ) . ';';

        return sprintf( '<div%s%s style="%s">%s</div>', $id_attr, $class_attr, $style, $output );
    }

    /**
     * Render carousel layout
     * Horizontal scrolling carousel of child components.
     */
    public static function render_carousel( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, [
            'items'      => [],
            'item_width' => '300px',
            'gap'        => '16px',
            'id'         => '',
            'class'      => '',
            'title'      => '',
        ] );

        $engine = \UltraguardPro\view\RenderEngine::get_instance();
        $items  = is_array( $scheme['items'] ) ? $scheme['items'] : [];
        $slides = '';

        foreach ( $items as $item ) {
            if ( is_array( $item ) ) {
                $slides .= sprintf(
                    '<div class="ultraguard-carousel-slide" style="flex:0 0 %s;min-width:0;">%s</div>',
                    esc_attr( $scheme['item_width'] ),
                    $engine->render( $item, $context )
                );
            }
        }

        $title_html = $scheme['title']
            ? '<h3 class="ultraguard-carousel-title">' . esc_html( $scheme['title'] ) . '</h3>'
            : '';

        $id_attr    = $scheme['id']    ? ' id="' . esc_attr( $scheme['id'] )    . '"' : '';
        $class_attr = $scheme['class'] ? ' class="ultraguard-carousel ' . esc_attr( $scheme['class'] ) . '"' : ' class="ultraguard-carousel"';
        $track_style = 'display:flex;gap:' . esc_attr( $scheme['gap'] ) . ';overflow-x:auto;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;scrollbar-width:thin;padding-bottom:8px;';

        return sprintf(
            '<div%s%s>%s<div class="ultraguard-carousel-track" style="%s">%s</div></div>',
            $id_attr, $class_attr, $title_html, $track_style, $slides
        );
    }

    /**
     * Render kanban-board layout
     * Multi-column Kanban board with column titles and card items.
     */
    public static function render_kanban_board( $scheme, $context ) {
        $instance = self::get_cached_instance();
        $scheme   = $instance->before_render( $scheme, $context );

        $scheme = wp_parse_args( $scheme, [
            'columns'      => [],
            'column_width' => '280px',
            'gap'          => '16px',
            'id'           => '',
            'class'        => '',
            'title'        => '',
        ] );

        $engine  = \UltraguardPro\view\RenderEngine::get_instance();
        $columns = is_array( $scheme['columns'] ) ? $scheme['columns'] : [];
        $cols_html = '';

        foreach ( $columns as $col ) {
            $col = wp_parse_args( $col, [ 'title' => '', 'items' => [], 'color' => '' ] );
            $items_html = '';

            foreach ( ( is_array( $col['items'] ) ? $col['items'] : [] ) as $item ) {
                if ( is_array( $item ) ) {
                    $items_html .= '<div class="ultraguard-kanban-card">' . $engine->render( $item, $context ) . '</div>';
                }
            }

            $col_header_style = $col['color'] ? 'border-top:3px solid ' . esc_attr( $col['color'] ) . ';' : '';
            $cols_html .= sprintf(
                '<div class="ultraguard-kanban-column" style="flex:0 0 %s;min-width:0;">'
                . '<div class="ultraguard-kanban-column-header" style="%s"><h4 class="ultraguard-kanban-column-title">%s</h4></div>'
                . '<div class="ultraguard-kanban-column-body">%s</div>'
                . '</div>',
                esc_attr( $scheme['column_width'] ),
                $col_header_style,
                esc_html( $col['title'] ),
                $items_html
            );
        }

        $title_html = $scheme['title']
            ? '<h3 class="ultraguard-kanban-title">' . esc_html( $scheme['title'] ) . '</h3>'
            : '';

        $id_attr    = $scheme['id']    ? ' id="' . esc_attr( $scheme['id'] )    . '"' : '';
        $class_attr = $scheme['class'] ? ' class="ultraguard-kanban-board ' . esc_attr( $scheme['class'] ) . '"' : ' class="ultraguard-kanban-board"';
        $board_style = 'display:flex;gap:' . esc_attr( $scheme['gap'] ) . ';overflow-x:auto;align-items:start;';

        return sprintf(
            '<div%s%s>%s<div class="ultraguard-kanban-track" style="%s">%s</div></div>',
            $id_attr, $class_attr, $title_html, $board_style, $cols_html
        );
    }

}
