<?php
/**
 * A reusable Elementor trait and accompanying manager class for a comprehensive animation system.
 * This file encapsulates all logic for adding controls and rendering animation attributes,
 * avoiding global namespace pollution and promoting clean, maintainable code.
 *
 * @package Sifency\Traits
 */

namespace Sifency\Traits;

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

use Elementor\Controls_Manager;

// =============================================================================
// SECTION 1: THE ELEMENTOR CONTROLS TRAIT
// =============================================================================

if ( ! trait_exists('Sifency\Traits\Sifency_Animation_Controls') ) {
    /**
     * A reusable trait for adding a comprehensive animation control panel to Elementor widgets.
     * This should be used within your widget class.
     */
    trait Sifency_Animation_Controls {
        /**
         * Provides the option arrays for different animation libraries.
         * @param string $type The animation library type ('aos', 'wow', 'gsap').
         * @return array
         */
        protected function get_sifency_animation_options( $type ) {
            $options = [
                'aos' => [
                    '' => __('None', 'sifency-addons'), 'fade' => 'Fade', 'fade-up' => 'Fade Up', 'fade-down' => 'Fade Down', 'fade-left' => 'Fade Left', 'fade-right' => 'Fade Right', 'fade-up-right' => 'Fade Up Right', 'fade-up-left' => 'Fade Up Left', 'fade-down-right' => 'Fade Down Right', 'fade-down-left' => 'Fade Down Left', 'flip-up' => 'Flip Up', 'flip-down' => 'Flip Down', 'flip-left' => 'Flip Left', 'flip-right' => 'Flip Right', 'slide-up' => 'Slide Up', 'slide-down' => 'Slide Down', 'slide-left' => 'Slide Left', 'slide-right' => 'Slide Right', 'zoom-in' => 'Zoom In', 'zoom-in-up' => 'Zoom In Up', 'zoom-in-down' => 'Zoom In Down', 'zoom-in-left' => 'Zoom In Left', 'zoom-in-right' => 'Zoom In Right', 'zoom-out' => 'Zoom Out', 'zoom-out-up' => 'Zoom Out Up', 'zoom-out-down' => 'Zoom Out Down', 'zoom-out-left' => 'Zoom Out Left', 'zoom-out-right' => 'Zoom Out Right',
                ],
                'wow' => [
                    '' => __('None', 'sifency-addons'), 'bounce' => 'Bounce', 'flash' => 'Flash', 'pulse' => 'Pulse', 'rubberBand' => 'Rubber Band', 'shake' => 'Shake', 'swing' => 'Swing', 'tada' => 'Tada', 'wobble' => 'Wobble', 'jello' => 'Jello', 'heartBeat' => 'Heart Beat', 'bounceIn' => 'Bounce In', 'bounceInDown' => 'Bounce In Down', 'bounceInLeft' => 'Bounce In Left', 'bounceInRight' => 'Bounce In Right', 'bounceInUp' => 'Bounce In Up', 'fadeIn' => 'Fade In', 'fadeInDown' => 'Fade In Down', 'fadeInLeft' => 'Fade In Left', 'fadeInRight' => 'Fade In Right', 'fadeInUp' => 'Fade In Up', 'flip' => 'Flip', 'flipInX' => 'Flip In X', 'flipInY' => 'Flip In Y', 'lightSpeedIn' => 'Light Speed In', 'rotateIn' => 'Rotate In', 'rotateInDownLeft' => 'Rotate In Down Left', 'rotateInDownRight' => 'Rotate In Down Right', 'rotateInUpLeft' => 'Rotate In Up Left', 'rotateInUpRight' => 'Rotate In Up Right', 'slideInUp' => 'Slide In Up', 'slideInDown' => 'Slide In Down', 'slideInLeft' => 'Slide In Left', 'slideInRight' => 'Slide In Right', 'zoomIn' => 'Zoom In', 'zoomInDown' => 'Zoom In Down', 'zoomInLeft' => 'Zoom In Left', 'zoomInRight' => 'Zoom In Right', 'zoomInUp' => 'Zoom In Up', 'hinge' => 'Hinge', 'jackInTheBox' => 'Jack In The Box', 'rollIn' => 'Roll In',
                ],
                'gsap' => [
                    '' => __('None (Custom Only)', 'sifency-addons'),
                    'gsap-fade-in' => __('Fade In', 'sifency-addons'),
                    'gsap-fade-in-up' => __('Fade In Up', 'sifency-addons'),
                    'gsap-fade-in-down' => __('Fade In Down', 'sifency-addons'),
                    'gsap-fade-in-left' => __('Fade In Left', 'sifency-addons'),
                    'gsap-fade-in-right' => __('Fade In Right', 'sifency-addons'),
                    'gsap-slide-up' => __('Slide Up', 'sifency-addons'),
                    'gsap-slide-down' => __('Slide Down', 'sifency-addons'),
                    'gsap-slide-left' => __('Slide Left', 'sifency-addons'),
                    'gsap-slide-right' => __('Slide Right', 'sifency-addons'),
                    'gsap-clip-reveal-up' => __('Clip Reveal Up', 'sifency-addons'),
                    'gsap-clip-reveal-down' => __('Clip Reveal Down', 'sifency-addons'),
                    'gsap-clip-reveal-left' => __('Clip Reveal Left', 'sifency-addons'),
                    'gsap-clip-reveal-right' => __('Clip Reveal Right', 'sifency-addons'),
                    'gsap-scale-in' => __('Scale In', 'sifency-addons'),
                    'gsap-rotate-in' => __('Rotate In', 'sifency-addons'),
                    'gsap-blur-in' => __('Blur In', 'sifency-addons'),
                    'gsap-zoom-out' => __('Zoom Out', 'sifency-addons'),
                    'gsap-flip-in-x' => __('Flip In X', 'sifency-addons'),
                    'gsap-flip-in-y' => __('Flip In Y', 'sifency-addons'),
                    'gsap-skew-in-up' => __('Skew In Up', 'sifency-addons'),
                    'gsap-skew-in-down' => __('Skew In Down', 'sifency-addons'),
                    'gsap-clip-reveal-diag-tl' => __('Clip Reveal Diagonal (TL)', 'sifency-addons'),
                    'gsap-clip-reveal-diag-br' => __('Clip Reveal Diagonal (BR)', 'sifency-addons'),
                    'gsap-bounce-in' => __('Bounce In', 'sifency-addons'),
                    'gsap-bounce-in-up' => __('Bounce In Up', 'sifency-addons'),
                    'gsap-bounce-in-down' => __('Bounce In Down', 'sifency-addons'),
                    'gsap-bounce-in-left' => __('Bounce In Left', 'sifency-addons'),
                    'gsap-bounce-in-right' => __('Bounce In Right', 'sifency-addons'),
                    'gsap-rotate-in-top-left' => __('Rotate In (Top Left)', 'sifency-addons'),
                    'gsap-rotate-in-top-right' => __('Rotate In (Top Right)', 'sifency-addons'),
                    'gsap-rotate-in-bottom-left' => __('Rotate In (Bottom Left)', 'sifency-addons'),
                    'gsap-rotate-in-bottom-right' => __('Rotate In (Bottom Right)', 'sifency-addons'),
                ],
            ];
            return isset($options[$type]) ? $options[$type] : [];
        }

        /**
         * Adds the complete animation control panel to the current widget instance.
         */
        public function add_sifency_animation_controls() {
            $this->start_controls_section('sifency_animation_section', ['label' => __('Sifency Animations', 'sifency-addons'), 'tab' => Controls_Manager::TAB_ADVANCED,]);

            $aos_condition = ['sifency_animation_type' => 'aos'];
            $wow_condition = ['sifency_animation_type' => 'wow'];
            $gsap_condition = ['sifency_animation_type' => 'gsap'];
            $custom_condition = ['sifency_animation_type' => 'custom'];
            $this->add_control('sifency_animation_type', ['label' => __('Animation Library', 'sifency-addons'), 'type' => Controls_Manager::SELECT, 'options' => ['' => __('None', 'sifency-addons'), 'aos' => 'AOS', 'wow' => 'WOW.js', 'gsap' => 'GSAP (Advanced)', 'custom' => __('Custom Attributes', 'sifency-addons'),], 'default' => '',]);
            $this->add_control('sifency_animation_target', ['label' => __('Apply Animation To', 'sifency-addons'), 'type' => Controls_Manager::CHOOSE, 'options' => ['wrapper' => ['title' => __('Widget Wrapper', 'sifency-addons'), 'icon' => 'eicon-element-wrapper'], 'child' => ['title' => __('Child Items', 'sifency-addons'), 'icon' => 'eicon-bullet-list']], 'default' => 'wrapper', 'toggle' => false, 'description' => __('Animate the whole widget or individual items in a loop.', 'sifency-addons'), 'separator' => 'before',]);
            $this->add_control('sifency_animation_stagger_delay', ['label' => __('Stagger Delay (ms)', 'sifency-addons'), 'type' => Controls_Manager::NUMBER, 'min' => 0, 'step' => 10, 'default' => 50, 'description' => __('Delay between each child item animation (for AOS/WOW).', 'sifency-addons'), 'condition' => ['sifency_animation_target' => 'child', 'sifency_animation_type!' => ['', 'gsap']],]);
            $this->add_control('sifency_aos_animation', ['label' => __('AOS Animation', 'sifency-addons'), 'type' => Controls_Manager::SELECT, 'options' => $this->get_sifency_animation_options('aos'), 'default' => 'fade-up', 'condition' => $aos_condition]);
            $aos_sub_condition = array_merge($aos_condition, ['sifency_aos_animation!' => '']);
            $this->add_control('sifency_aos_duration', ['label' => __('Duration (ms)', 'sifency-addons'), 'type' => Controls_Manager::NUMBER, 'min' => 100, 'max' => 3000, 'step' => 50, 'condition' => $aos_sub_condition, 'selectors' => ['{{WRAPPER}}' => '--aos-duration: {{VALUE}}ms;']]);
            $this->add_control('sifency_aos_delay', ['label' => __('Delay (ms)', 'sifency-addons'), 'type' => Controls_Manager::NUMBER, 'min' => 0, 'step' => 50, 'condition' => $aos_sub_condition]);
            $this->add_control('sifency_aos_offset', ['label' => __('Offset (px)', 'sifency-addons'), 'type' => Controls_Manager::SLIDER, 'range' => ['px' => ['min' => 0, 'max' => 500, 'step' => 10]], 'condition' => $aos_sub_condition]);
            $this->add_control('aos_once_switch', ['label' => __('Animate Once', 'sifency-addons'), 'type' => Controls_Manager::SWITCHER, 'condition' => $aos_condition]);
            $this->add_control('sifency_aos_easing', ['label' => __('Easing', 'sifency-addons'), 'type' => Controls_Manager::SELECT, 'options' => ['ease' => 'Ease', 'linear' => 'Linear', 'ease-in-out' => 'Ease In Out', 'ease-in-back' => 'Ease In Back', 'ease-out-back' => 'Ease Out Back'], 'default' => 'ease-out-cubic', 'condition' => $aos_sub_condition]);
            $this->add_control('sifency_wow_animation', ['label' => __('WOW Animation', 'sifency-addons'), 'type' => Controls_Manager::SELECT, 'options' => $this->get_sifency_animation_options('wow'), 'default' => 'none', 'condition' => $wow_condition]);
            $wow_sub_condition = array_merge($wow_condition, ['sifency_wow_animation!' => '']);
            $this->add_control('sifency_wow_duration', ['label' => __('Duration (s)', 'sifency-addons'), 'type' => Controls_Manager::TEXT, 'default' => '1s', 'condition' => $wow_sub_condition]);
            $this->add_control('sifency_wow_delay', ['label' => __('Delay (s)', 'sifency-addons'), 'type' => Controls_Manager::TEXT, 'default' => '0.2s', 'condition' => $wow_sub_condition]);
            $this->add_control('sifency_wow_offset', ['label' => __('Offset', 'sifency-addons'), 'type' => Controls_Manager::NUMBER, 'placeholder' => '10', 'condition' => $wow_sub_condition]);
            $this->add_control('sifency_wow_iteration', ['label' => __('Iteration', 'sifency-addons'), 'type' => Controls_Manager::NUMBER, 'placeholder' => '1', 'condition' => $wow_sub_condition]);
            $this->add_control('sifency_gsap_animation', ['label' => __('GSAP Preset', 'sifency-addons'), 'type' => Controls_Manager::SELECT, 'options' => $this->get_sifency_animation_options('gsap'), 'condition' => $gsap_condition]);
            $this->add_control('sifency_gsap_type_heading', ['label' => __('Specialized Animations', 'sifency-addons'), 'type' => Controls_Manager::HEADING, 'separator' => 'before', 'condition' => $gsap_condition]);
            $this->add_control('sifency_gsap_stagger_children', ['label' => __('Stagger Children', 'sifency-addons'), 'type' => Controls_Manager::SWITCHER, 'condition' => $gsap_condition]);
            $this->add_control('sifency_gsap_split_text', ['label' => __('Split Text Animation', 'sifency-addons'), 'type' => Controls_Manager::SWITCHER, 'condition' => $gsap_condition]);
            $this->add_control('sifency_gsap_focus_text', ['label' => __('Focus In Text Effect', 'sifency-addons'), 'type' => Controls_Manager::SWITCHER, 'condition' => $gsap_condition]);
            $this->add_control('sifency_gsap_scale_text', ['label' => __('Scale Text on Scroll', 'sifency-addons'), 'type' => Controls_Manager::SWITCHER, 'condition' => $gsap_condition]);
            $this->add_control('sifency_gsap_settings_heading', ['label' => __('Core Animation Settings', 'sifency-addons'), 'type' => Controls_Manager::HEADING, 'separator' => 'before', 'condition' => $gsap_condition]);
            $this->add_control('sifency_gsap_duration', ['label' => __('Duration (s)', 'sifency-addons'), 'type' => Controls_Manager::NUMBER, 'min' => 0, 'max' => 10, 'step' => 0.1, 'default' => 1.2, 'condition' => $gsap_condition]);
            $this->add_control('sifency_gsap_delay', ['label' => __('Delay (s)', 'sifency-addons'), 'type' => Controls_Manager::NUMBER, 'min' => 0, 'max' => 10, 'step' => 0.1, 'default' => 0, 'condition' => $gsap_condition]);
            $this->add_control('sifency_gsap_ease', ['label' => __('Easing', 'sifency-addons'), 'type' => Controls_Manager::SELECT, 'default' => 'power4.out', 'options' => ['none' => 'none', 'linear' => 'linear', 'power0.in' => 'power0.in', 'power0.out' => 'power0.out', 'power0.inOut' => 'power0.inOut', 'power1.in' => 'power1.in', 'power1.out' => 'power1.out', 'power1.inOut' => 'power1.inOut', 'power2.in' => 'power2.in', 'power2.out' => 'power2.out', 'power2.inOut' => 'power2.inOut', 'power3.in' => 'power3.in', 'power3.out' => 'power3.out', 'power3.inOut' => 'power3.inOut', 'power4.in' => 'power4.in', 'power4.out' => 'power4.out', 'power4.inOut' => 'power4.inOut', 'back.in' => 'back.in', 'back.out' => 'back.out', 'back.inOut' => 'back.inOut', 'elastic.in' => 'elastic.in', 'elastic.out' => 'elastic.out', 'elastic.inOut' => 'elastic.inOut', 'bounce.in' => 'bounce.in', 'bounce.out' => 'bounce.out', 'bounce.inOut' => 'bounce.inOut', 'rough' => 'rough', 'slow' => 'slow', 'steps(5)' => 'steps(5)', 'circ.in' => 'circ.in', 'circ.out' => 'circ.out', 'circ.inOut' => 'circ.inOut', 'expo.in' => 'expo.in', 'expo.out' => 'expo.out', 'expo.inOut' => 'expo.inOut', 'sine.in' => 'sine.in', 'sine.out' => 'sine.out', 'sine.inOut' => 'sine.inOut',], 'condition' => ['sifency_animation_type' => 'gsap',], 'description' => __('Choose a GSAP easing function. For advanced cases like "elastic.out(1, 0.3)", use the custom JS field.', 'sifency-addons'),]);
            $this->add_control('sifency_gsap_scroll_heading', ['label' => __('ScrollTrigger Settings', 'sifency-addons'), 'type' => Controls_Manager::HEADING, 'separator' => 'before', 'condition' => $gsap_condition]);
            $this->add_control('sifency_gsap_start', ['label' => __('Trigger Start', 'sifency-addons'), 'type' => Controls_Manager::TEXT, 'default' => 'top 85%', 'condition' => $gsap_condition]);
            $this->add_control('sifency_gsap_scrub', ['label' => __('Scrub', 'sifency-addons'), 'type' => Controls_Manager::TEXT, 'placeholder' => 'true or 1', 'condition' => $gsap_condition]);
            $this->add_control('sifency_gsap_toggle_class', ['label' => __('Toggle Class', 'sifency-addons'), 'type' => Controls_Manager::TEXT, 'default' => 'is-active', 'condition' => $gsap_condition]);
            $this->add_control('sifency_gsap_markers', ['label' => __('Show Markers (Debug)', 'sifency-addons'), 'type' => Controls_Manager::SWITCHER, 'condition' => $gsap_condition]);
            $this->add_control('sifency_gsap_stagger_value', ['label' => __('Stagger Delay (s)', 'sifency-addons'), 'type' => Controls_Manager::NUMBER, 'min' => 0, 'max' => 2, 'step' => 0.05, 'default' => 0.1, 'condition' => array_merge($gsap_condition, ['sifency_gsap_stagger_children' => 'yes'])]);
            $this->add_control('sifency_gsap_split_by', ['label' => __('Split By', 'sifency-addons'), 'type' => Controls_Manager::SELECT, 'options' => ['chars' => __('Characters', 'sifency-addons'), 'words' => __('Words', 'sifency-addons'), 'lines' => __('Lines', 'sifency-addons'), 'chars,words,lines' => __('All (Chars)', 'sifency-addons')], 'default' => 'lines', 'condition' => array_merge($gsap_condition, ['sifency_gsap_split_text' => 'yes'])]);
            $this->add_control('sifency_gsap_focus_max_blur', ['label' => __('Max Blur (px)', 'sifency-addons'), 'type' => Controls_Manager::NUMBER, 'default' => 8, 'condition' => array_merge($gsap_condition, ['sifency_gsap_focus_text' => 'yes'])]);
            $this->add_control('sifency_gsap_focus_stagger', ['label' => __('Focus Duration (s)', 'sifency-addons'), 'type' => Controls_Manager::NUMBER, 'default' => 0.5, 'condition' => array_merge($gsap_condition, ['sifency_gsap_focus_text' => 'yes'])]);
            $this->add_control('sifency_gsap_focus_from', ['label' => __('Focus Direction', 'sifency-addons'), 'type' => Controls_Manager::CHOOSE, 'options' => ['start' => ['title' => 'Left to Right', 'icon' => 'eicon-h-align-left'], 'center' => ['title' => 'Center Out', 'icon' => 'eicon-h-align-center'], 'end' => ['title' => 'Right to Left', 'icon' => 'eicon-h-align-right']], 'default' => 'center', 'toggle' => false, 'condition' => ['sifency_animation_type' => 'gsap'],]);
            $this->add_control('sifency_gsap_parallax_y', ['label' => __('Parallax Y', 'sifency-addons'), 'type' => Controls_Manager::NUMBER, 'placeholder' => '-150', 'condition' => array_merge($gsap_condition, ['sifency_gsap_parallax' => 'yes'])]);
            $this->add_control('sifency_gsap_parallax_x', ['label' => __('Parallax X', 'sifency-addons'), 'type' => Controls_Manager::NUMBER, 'placeholder' => '100', 'condition' => array_merge($gsap_condition, ['sifency_gsap_parallax' => 'yes'])]);
            $this->add_control('sifency_gsap_start_size', ['label' => __('Start Font Size', 'sifency-addons'), 'type' => Controls_Manager::TEXT, 'default' => '2rem', 'condition' => array_merge($gsap_condition, ['sifency_gsap_scale_text' => 'yes'])]);
            $this->add_control('sifency_gsap_end_size', ['label' => __('End Font Size', 'sifency-addons'), 'type' => Controls_Manager::TEXT, 'default' => '15rem', 'condition' => array_merge($gsap_condition, ['sifency_gsap_scale_text' => 'yes'])]);
            $this->add_control('sifency_gsap_custom_heading', ['label' => __('Fully Custom Animation', 'sifency-addons'), 'type' => Controls_Manager::HEADING, 'separator' => 'before', 'condition' => $gsap_condition]);
            $this->add_control('sifency_gsap_from', ['label' => __('Custom "From" Properties', 'sifency-addons'), 'type' => Controls_Manager::TEXTAREA, 'placeholder' => '{"opacity": 0, "y": 50}', 'condition' => $gsap_condition]);
            $this->add_control('sifency_gsap_to', ['label' => __('Custom "To" Properties', 'sifency-addons'), 'type' => Controls_Manager::TEXTAREA, 'placeholder' => '{"opacity": 1, "y": 0}', 'condition' => $gsap_condition]);
            $this->add_control('sifency_custom_attributes', ['label' => __('Custom Attributes', 'sifency-addons'), 'type' => Controls_Manager::TEXTAREA, 'rows' => 5, 'description' => __('Enter pairs like: key="value" key2="value2"', 'sifency-addons'), 'condition' => $custom_condition]);

            $this->end_controls_section();
        }
    }
}


// =============================================================================
// SECTION 2: THE ANIMATION MANAGER CLASS (REPLACES ALL GLOBAL FUNCTIONS)
// =============================================================================

if ( ! class_exists('Sifency\Traits\Sifency_Animation_Manager') ) {
    /**
     * Manages the generation of animation attributes for Elementor widgets.
     * This class is instantiated in the widget's render() method to handle all animation logic.
     * It is entirely self-contained and does not pollute the global namespace.
     */
    class Sifency_Animation_Manager {

        private $settings;
        private $target;
        private $base_attributes;
        private $index = 0;

        /**
         * Sifency_Animation_Manager constructor.
         * @param array $settings The widget's settings array from get_settings_for_display().
         */
        public function __construct( array $settings ) {
            $this->settings        = $settings;
            $this->target          = isset( $settings['sifency_animation_target'] ) ? $settings['sifency_animation_target'] : 'wrapper';
            $this->base_attributes = $this->generate_base_attributes();
        }

        /**
         * Returns the complete HTML attribute string for the main widget wrapper.
         * @param array $extra_classes Optional array of additional classes to merge.
         * @return string The HTML attribute string (e.g., ' class="..." data-aos="..."').
         */
        public function get_wrapper_attributes( array $extra_classes = [] ) {
            if ( $this->target !== 'wrapper' || empty( $this->base_attributes ) ) {
                return ! empty( $extra_classes ) ? ' class="' . esc_attr( implode( ' ', $extra_classes ) ) . '"' : '';
            }
            return $this->build_attributes_string( $this->base_attributes, $extra_classes );
        }

        /**
         * Returns the complete HTML attribute string for an individual item in a loop.
         * @param array $extra_classes Optional array of additional classes to merge.
         * @return string The HTML attribute string for the item.
         */
        public function get_item_attributes( array $extra_classes = [] ) {
            if ( $this->target !== 'child' || empty( $this->base_attributes ) ) {
                return ! empty( $extra_classes ) ? ' class="' . esc_attr( implode( ' ', $extra_classes ) ) . '"' : '';
            }
            $item_attributes = $this->get_staggered_attributes( $this->index );
            $this->index++;
            return $this->build_attributes_string( $item_attributes, $extra_classes );
        }

        /**
         * Generates the base array of HTML data attributes from the widget settings.
         */
        private function generate_base_attributes() {
            $attr = [];
            $type = isset( $this->settings['sifency_animation_type'] ) ? $this->settings['sifency_animation_type'] : '';

            if ( empty($type) ) {
                return $attr;
            }

            switch ($type) {
                case 'aos':
                    if (!empty($this->settings['sifency_aos_animation'])) {
                        $attr['data-aos'] = $this->settings['sifency_aos_animation'];
                        if (isset($this->settings['sifency_aos_delay']) && $this->settings['sifency_aos_delay'] !== '') $attr['data-aos-delay'] = $this->settings['sifency_aos_delay'];
                        if (!empty($this->settings['sifency_aos_offset']['size'])) $attr['data-aos-offset'] = $this->settings['sifency_aos_offset']['size'];
                        if (!empty($this->settings['sifency_aos_easing'])) $attr['data-aos-easing'] = $this->settings['sifency_aos_easing'];
                        $aos_once = isset($this->settings['aos_once_switch']) ? $this->settings['aos_once_switch'] : 'no';
                        if ($aos_once === 'yes') $attr['data-aos-once'] = 'true';
                    }
                    break;
    
                case 'wow':
                    if (!empty($this->settings['sifency_wow_animation'])) {
                        $attr['class'] = 'wow ' . $this->settings['sifency_wow_animation'];
                        if (!empty($this->settings['sifency_wow_duration'])) $attr['data-wow-duration'] = $this->settings['sifency_wow_duration'];
                        if (!empty($this->settings['sifency_wow_delay'])) $attr['data-wow-delay'] = $this->settings['sifency_wow_delay'];
                        if (isset($this->settings['sifency_wow_offset']) && $this->settings['sifency_wow_offset'] !== '') $attr['data-wow-offset'] = $this->settings['sifency_wow_offset'];
                        if (!empty($this->settings['sifency_wow_iteration'])) $attr['data-wow-iteration'] = $this->settings['sifency_wow_iteration'];
                    }
                    break;
    
                case 'gsap':
                    $gsap_classes = ['gsap-animate'];
                    if (!empty($this->settings['sifency_gsap_animation'])) $gsap_classes[] = $this->settings['sifency_gsap_animation'];
                    
                    $gsap_split_text = isset($this->settings['sifency_gsap_split_text']) ? $this->settings['sifency_gsap_split_text'] : 'no';
                    $gsap_focus_text = isset($this->settings['sifency_gsap_focus_text']) ? $this->settings['sifency_gsap_focus_text'] : 'no';
                    $gsap_stagger_children = isset($this->settings['sifency_gsap_stagger_children']) ? $this->settings['sifency_gsap_stagger_children'] : 'no';
                    $gsap_parallax = isset($this->settings['sifency_gsap_parallax']) ? $this->settings['sifency_gsap_parallax'] : 'no';
                    $gsap_scale_text = isset($this->settings['sifency_gsap_scale_text']) ? $this->settings['sifency_gsap_scale_text'] : 'no';
                    $gsap_markers = isset($this->settings['sifency_gsap_markers']) ? $this->settings['sifency_gsap_markers'] : 'no';
                    
                    $needs_text_split = ($gsap_split_text === 'yes' || $gsap_focus_text === 'yes');
                    if ($needs_text_split) {
                        $gsap_classes[] = 'gsap-split-text';
                        if (!empty($this->settings['sifency_gsap_split_by'])) $attr['data-split-type'] = $this->settings['sifency_gsap_split_by'];
                    }
                    if ($gsap_stagger_children === 'yes') {
                        $gsap_classes[] = 'gsap-stagger-children';
                        if (!empty($this->settings['sifency_gsap_stagger_value'])) $attr['data-stagger'] = $this->settings['sifency_gsap_stagger_value'];
                    }
                    if ($gsap_focus_text === 'yes') {
                        $gsap_classes[] = 'gsap-focus-in-text';
                        if (!empty($this->settings['sifency_gsap_focus_max_blur'])) $attr['data-max-blur'] = $this->settings['sifency_gsap_focus_max_blur'];
                        if (!empty($this->settings['sifency_gsap_focus_stagger'])) $attr['data-focus-stagger'] = $this->settings['sifency_gsap_focus_stagger'];
                        $focus_from = isset($this->settings['sifency_gsap_focus_from']) ? $this->settings['sifency_gsap_focus_from'] : 'center';
                        if ($focus_from !== 'center') $attr['data-focus-from'] = $focus_from;
                    }
                    if ($gsap_parallax === 'yes') {
                        if (isset($this->settings['sifency_gsap_parallax_y']) && is_numeric($this->settings['sifency_gsap_parallax_y'])) $attr['data-parallax-y'] = $this->settings['sifency_gsap_parallax_y'];
                        if (isset($this->settings['sifency_gsap_parallax_x']) && is_numeric($this->settings['sifency_gsap_parallax_x'])) $attr['data-parallax-x'] = $this->settings['sifency_gsap_parallax_x'];
                    }
                    if ($gsap_scale_text === 'yes') {
                        $attr['data-gsap-scale-text'] = 'true';
                        if (!empty($this->settings['sifency_gsap_start_size'])) $attr['data-start-size'] = $this->settings['sifency_gsap_start_size'];
                        if (!empty($this->settings['sifency_gsap_end_size'])) $attr['data-end-size'] = $this->settings['sifency_gsap_end_size'];
                        $text_align = isset($this->settings['sifency_gsap_scale_text_align']) ? $this->settings['sifency_gsap_scale_text_align'] : 'center';
                        if (!empty($text_align)) $gsap_classes[] = 'gsap-anchor-' . $text_align;
                    }
                    $attr['class'] = implode(' ', array_unique($gsap_classes));
                    if (!empty($this->settings['sifency_gsap_duration']) && $this->settings['sifency_gsap_duration'] != 1.2) $attr['data-duration'] = $this->settings['sifency_gsap_duration'];
                    if (isset($this->settings['sifency_gsap_delay']) && $this->settings['sifency_gsap_delay'] !== '') $attr['data-delay'] = $this->settings['sifency_gsap_delay'];
                    if (!empty($this->settings['sifency_gsap_ease']) && $this->settings['sifency_gsap_ease'] !== 'power4.out') $attr['data-ease'] = $this->settings['sifency_gsap_ease'];
                    if (!empty($this->settings['sifency_gsap_start']) && $this->settings['sifency_gsap_start'] !== 'top 85%') $attr['data-start'] = $this->settings['sifency_gsap_start'];
                    if (!empty($this->settings['sifency_gsap_scrub'])) $attr['data-scrub'] = $this->settings['sifency_gsap_scrub'];
                    if (!empty($this->settings['sifency_gsap_toggle_class']) && $this->settings['sifency_gsap_toggle_class'] !== 'is-active') $attr['data-toggle-class'] = $this->settings['sifency_gsap_toggle_class'];
                    if ($gsap_markers === 'yes') $attr['data-markers'] = 'true';
                    if (!empty($this->settings['sifency_gsap_from'])) $attr['data-from'] = str_replace('"', "'", $this->settings['sifency_gsap_from']);
                    if (!empty($this->settings['sifency_gsap_to'])) $attr['data-to'] = str_replace('"', "'", $this->settings['sifency_gsap_to']);
                    break;
                
                case 'custom':
                    if (!empty($this->settings['sifency_custom_attributes'])) {
                        preg_match_all('/(\S+)=["\']?((?:.(?!["\']?\s+(?:\S+)=|[>"\']))+.)["\']?/', $this->settings['sifency_custom_attributes'], $matches, PREG_SET_ORDER);
                        if (!empty($matches)) {
                            foreach ($matches as $match) {
                                if (isset($match[1], $match[2])) {
                                    $key = trim($match[1]);
                                    $value = trim($match[2]);
                                    if ($key === 'class') $attr['class'] = isset($attr['class']) ? $attr['class'] . ' ' . $value : $value;
                                    else $attr[$key] = $value;
                                }
                            }
                        }
                    }
                    break;
            }
            return $attr;
        }

        /**
         * Base attributes with a calculated stagger delay for child items.
         */
        private function get_staggered_attributes( $index ) {
            $attributes = $this->base_attributes;
            $type = isset( $this->settings['sifency_animation_type'] ) ? $this->settings['sifency_animation_type'] : '';

            $stagger_delay    = ! empty( $this->settings['sifency_animation_stagger_delay'] ) ? (int) $this->settings['sifency_animation_stagger_delay'] : 50;
            $calculated_delay = (int) $index * $stagger_delay;
            
            if ($calculated_delay === 0 && $index > 0) {
                 return $attributes;
            }

            switch ( $type ) {
                case 'aos':
                    $base_delay = ! empty( $this->settings['sifency_aos_delay'] ) ? (int) $this->settings['sifency_aos_delay'] : 0;
                    $attributes['data-aos-delay'] = $base_delay + $calculated_delay;
                    break;
                case 'wow':
                    $base_delay_str = isset( $this->settings['sifency_wow_delay'] ) ? $this->settings['sifency_wow_delay'] : '0s';
                    $base_delay_ms  = (float) $base_delay_str * 1000;
                    $total_delay_s  = ( $base_delay_ms + $calculated_delay ) / 1000;
                    $attributes['data-wow-delay'] = $total_delay_s . 's';
                    break;
                case 'custom':
                    $style = isset( $attributes['style'] ) ? $attributes['style'] : '';
                    $attributes['style'] = rtrim( $style, ';' ) . '; transition-delay: ' . $calculated_delay . 'ms;';
                    break;
            }
            return $attributes;
        }

        /**
         * Builds a clean, sanitized HTML attribute string from an array.
         */
        private function build_attributes_string( array $attributes_array, array $classes_array = [] ) {
            if ( isset( $attributes_array['class'] ) ) {
                $classes_array = array_merge( $classes_array, explode( ' ', $attributes_array['class'] ) );
                unset( $attributes_array['class'] );
            }

            $final_string = '';
            if ( ! empty( $classes_array ) ) {
                $unique_classes = array_unique( array_filter( $classes_array ) );
                $final_string .= ' class="' . esc_attr( implode( ' ', $unique_classes ) ) . '"';
            }
            
            foreach ( $attributes_array as $key => $value ) {
                if ( $value !== '' && $value !== null ) {
                    $final_string .= sprintf( ' %s="%s"', esc_attr( $key ), esc_attr( $value ) );
                }
            }
            return $final_string;
        }
    }
}