<?php
if ( ! defined('ABSPATH') ) exit;

use Elementor\Widget_Base;
use Elementor\Controls_Manager;

class ProductW extends Widget_Base {

    public function get_name() { return 'productW'; }
    public function get_title() { return 'محصولات (منوی محصولات)'; }
    public function get_icon() { return 'eicon-products'; }
    public function get_categories() { return ['exclusive-widget']; }

    protected function register_controls() {
        $this->start_controls_section('help', [
            'label' => 'راهنما',
            'tab'   => Controls_Manager::TAB_CONTENT,
        ]);

        $url_general    = esc_url( admin_url('admin.php?page=caffito-general') );
        $url_categories = esc_url( admin_url('admin.php?page=caffito-categories') );
        $url_products   = esc_url( admin_url('admin.php?page=caffito-products') );

        $this->add_control('caffito_settings_note', [
            'type'  => Controls_Manager::RAW_HTML,
            'raw'   => '
            <div class="elementor-panel-alert elementor-panel-alert-info" dir="rtl" style="line-height:1.9">
                این ویجت فقط خروجی را نشان می‌دهد.برای تنظیم بخش‌های مختلف به موارد زیر مراجعه کنید:<br>
                • <a href="'.$url_general.'" target="_blank" rel="noopener">تنظیمات کلی کافیتو</a> (caffito-general.php)<br>
                • <a href="'.$url_categories.'" target="_blank" rel="noopener">مدیریت دسته‌بندی‌ها</a> (caffito-categories.php)<br>
                • <a href="'.$url_products.'" target="_blank" rel="noopener">ثبت و مدیریت محصولات</a> (caffito-products.php)
            </div>',
            'content_classes' => 'elementor-descriptor',
        ]);

        $this->end_controls_section();

        $this->start_controls_section('sort_section', [
            'label' => 'مرتب‌سازی',
            'tab'   => Controls_Manager::TAB_CONTENT,
        ]);

        $this->add_control('show_sort', [
            'label'        => 'نمایش دکمه مرتب‌سازی',
            'type'         => Controls_Manager::SWITCHER,
            'label_on'     => 'بله',
            'label_off'    => 'خیر',
            'return_value' => 'yes',
            'default'      => 'yes',
            'description'  => 'در صورت فعال بودن، دکمهٔ مرتب‌سازی در بالای محصولات نمایش داده می‌شود.',
        ]);

        $this->end_controls_section();
    }

    private function det(array $p): array {
        if (empty($p['details_accordion']) || !is_array($p['details_accordion'])) return [];
        $d = $p['details_accordion'];
        if (isset($d[0]) && is_array($d[0])) { $d = $d[0]; }
        if (isset($d['fields']) && is_array($d['fields'])) { $d = $d['fields']; }
        return is_array($d) ? $d : [];
    }

    private function build_blend_points(array $d): array {
        if (empty($d['blend_enable'])) return [];
        $labels = [0, 30, 50, 70, 100];
        $out = [];
        foreach ($labels as $lab) {
            $key  = 'blend_'.$lab;
            $item = isset($d[$key]) && is_array($d[$key]) ? $d[$key] : [];
            $mode = $item['mode'] ?? 'none';
            $price= isset($item['price']) && $item['price'] !== '' ? floatval($item['price']) : 0;
            $sign = ($mode==='plus' ? '+' : ($mode==='minus' ? '−' : ''));
            $out[] = [
                'label'  => $lab,
                'active' => ($mode!=='none'),
                'mode'   => $mode,
                'sign'   => $sign,
                'price'  => $price,
            ];
        }
        return $out;
    }

    private function svg_or_img( $media ) {
        if (empty($media['url'])) return '';
        $url = esc_url_raw($media['url']);
        return '<img src="'.esc_url($url).'" alt="" loading="lazy" decoding="async" />';
    }

    private function ensure_attachment_id_for_image( $media ) : int {
        $id  = 0;
        $url = '';

        if ( is_array($media) ) {
            $id  = !empty($media['id']) ? (int)$media['id'] : 0;
            $url = !empty($media['url']) ? $media['url'] : '';
        } elseif ( is_string($media) ) {
            $url = $media;
        }

        if ( $id && get_post($id) ) { return $id; }
        if ( ! $url ) { return 0; }

        $map = get_option('caffito_asset_map', []);
        if ( is_array($map) && isset($map[$url]) && get_post( (int)$map[$url] ) ) {
            return (int)$map[$url];
        }

        $maybe = attachment_url_to_postid( $url );
        if ( $maybe ) {
            $map[$url] = (int)$maybe;
            update_option('caffito_asset_map', $map);
            return (int)$maybe;
        }

        $theme_base = get_template_directory_uri();
        $ext = strtolower( pathinfo( parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION ) );
        if ( strpos($url, $theme_base) === 0 && in_array($ext, ['jpg','jpeg','png','webp','gif']) ) {
            if ( ! function_exists('media_sideload_image') ) {
                require_once ABSPATH . 'wp-admin/includes/media.php';
                require_once ABSPATH . 'wp-admin/includes/file.php';
                require_once ABSPATH . 'wp-admin/includes/image.php';
            }
            $sid = media_sideload_image( $url, 0, '', 'id' );
            if ( ! is_wp_error($sid) && $sid ) {
                $map[$url] = (int)$sid;
                update_option('caffito_asset_map', $map);
                return (int)$sid;
            }
        }

        return 0;
    }

    private function render_responsive_img( $media, string $alt = '', string $context = 'card' ) : string {
        $id = $this->ensure_attachment_id_for_image( $media );

        if ( $id ) {
            if ( $context === 'popup' ) {
                $size  = 'large';
                $sizes = '(max-width: 480px) 94vw, (max-width: 1024px) 70vw, 768px';
                $class = 'popup-img-el';
            } else {
                $size  = 'medium_large';
                $sizes = '(max-width: 480px) 92vw, (max-width: 768px) 44vw, (max-width: 1200px) 31vw, 360px';
                $class = 'product-card-img';
            }
            return wp_get_attachment_image(
                $id,
                $size,
                false,
                array(
                    'alt'      => $alt,
                    'class'    => $class,
                    'loading'  => 'lazy',
                    'decoding' => 'async',
                    'sizes'    => $sizes,
                )
            );
        }

        $url = is_array($media) ? ($media['url'] ?? '') : (is_string($media) ? $media : '');
        if ( ! $url ) return '';
        return '<img src="'.esc_url($url).'" alt="'.esc_attr($alt).'" loading="lazy" decoding="async" />';
    }

    private function o() {
        $gen = get_option('caffito_general', []);
        $gen = is_array($gen) ? $gen : [];

        $currency      = (isset($gen['currency_unit']) && $gen['currency_unit']==='rial') ? 'ریال' : 'تومان';
        $show_search   = ! empty($gen['show_search']);
        $show_filters  = ! empty($gen['show_filters']);
        $notes_enabled = ! empty($gen['enable_notes']);

        $btn_avail = isset($gen['btn_label_available'])  && $gen['btn_label_available']  !== '' ? sanitize_text_field($gen['btn_label_available'])  : 'مشاهده جزییات و افزودنی‌ها';
        $btn_unav  = isset($gen['btn_label_unavailable'])&& $gen['btn_label_unavailable']!== '' ? sanitize_text_field($gen['btn_label_unavailable']): 'ناموجود';

        $cats_opt = get_option('caffito_categories', []);
        $cats_opt = is_array($cats_opt) ? $cats_opt : [];
        $cats = isset($cats_opt['categories']) ? (array)$cats_opt['categories'] : [];
        if ( empty($cats) ) { $cats = [ ['label'=>'همه'] ]; }

        $prod_opt = get_option('caffito_products', []);
        $prod_opt = is_array($prod_opt) ? $prod_opt : [];
        $prods_raw = isset($prod_opt['products']) ? (array)$prod_opt['products'] : [];

        $ordered   = array_reverse($prods_raw, false);
        $available = []; $unavail = [];
        foreach ($ordered as $p) {
            if ( !is_array($p) ) { continue; }
            if (!empty($p['enabled'])) $available[] = $p; else $unavail[] = $p;
        }
        $prods = array_merge($available, $unavail);

        return compact('currency','show_search','show_filters','cats','prods','btn_avail','btn_unav','notes_enabled');
    }

    protected function render() {
        $D = $this->o();
        $currency      = $D['currency'];
        $show_search   = $D['show_search'];
        $show_filters  = $D['show_filters'];
        $cats          = $D['cats'];
        $prods         = $D['prods'];
        $btn_avail     = $D['btn_avail'];
        $btn_unav      = $D['btn_unav'];
        $notes_enabled = !empty($D['notes_enabled']);

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

        $S             = $this->get_settings_for_display();
        $show_sort_btn = !empty($S['show_sort']);
        $wid           = $this->get_id();

        $unit_k       = ($currency === 'ریال') ? 'هزار ریال' : 'هزار تومان';
        ?>
        <section class="products-section" id="products" data-pw-id="<?php echo esc_attr( $wid ); ?>">
            <script>
                // --- Bootstrap global config (unit + toggle)
                (function(){
                    window.CAFFITO = window.CAFFITO || {};
                    window.CAFFITO.notesEnabled = <?php echo $notes_enabled ? 'true' : 'false'; ?>;
                    window.CAFFITO.unitPhrase   = <?php echo wp_json_encode($unit_k); ?>;
                    // [CHANGE #1]: expose admin-ajax URL to front-end
                    window.CAFFITO.ajaxURL     = "<?php echo esc_url( admin_url('admin-ajax.php') ); ?>";
                })();
            </script>

            <div class="search-and-filter-section">
                <?php if ( $show_filters ) : ?>
                    <div class="filter-menu">
                        <button class="filter-btn active" data-filter="all">همه</button>
                        <?php
                        $seen = [];
                        foreach ( $cats as $c ) {
                            $label = isset($c['label']) ? trim( sanitize_text_field($c['label']) ) : '';
                            if ($label === '' || $label === 'همه') continue;
                            $slug = sanitize_title( $label );
                            if ( isset($seen[$slug]) ) continue;
                            $seen[$slug] = true;
                            echo '<button class="filter-btn" data-filter="'.esc_attr($slug).'">'.esc_html($label).'</button>';
                        }
                        ?>
                    </div>
                <?php endif; ?>

                <?php if ( $show_search ) : ?>
                    <div class="search-section">
                        <form action="/search" method="get">
                            <input type="search" name="q" placeholder="<?php echo esc_attr('جستجو...'); ?>">
                            <button type="submit" class="search-section-button" aria-label="<?php echo esc_attr('جستجو'); ?>">
                                <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256" aria-hidden="true"><path d="M229.66,218.34l-50.07-50.06a88.11,88.11,0,1,0-11.31,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z"></path></svg>
                            </button>
                        </form>
                    </div>
                <?php endif; ?>

                <?php if ( $show_sort_btn ) : ?>
                    <div class="sort-wrap" dir="rtl">
                        <button
                                type="button"
                                class="sort-btn"
                                aria-expanded="false"
                                aria-controls="sort-dd-<?php echo esc_attr($wid); ?>"
                                aria-haspopup="listbox"
                                aria-label="مرتب‌سازی محصولات"
                                title="مرتب‌سازی محصولات"
                        >
                            <i class="ph-bold ph-sort-ascending" aria-hidden="true"></i>
                            <span>مرتب‌سازی</span>
                        </button>
                        <div class="sort-dropdown" id="sort-dd-<?php echo esc_attr($wid); ?>" hidden>
                            <button type="button" class="sort-opt" data-sort="default">پیش‌فرض</button>
                            <button type="button" class="sort-opt" data-sort="newest">جدیدترین</button>
                            <button type="button" class="sort-opt" data-sort="cheap">ارزان‌ترین</button>
                            <button type="button" class="sort-opt" data-sort="expensive">گران‌ترین</button>
                        </div>
                    </div>
                <?php endif; ?>
            </div>

            <div class="product-cards">
                <?php foreach ( $prods as $i => $p ) :
                    if ( !is_array($p) ) continue;
                    $enabled = ! empty($p['enabled']);
                    $title   = isset($p['title']) ? esc_html($p['title']) : '';
                    $img     = isset($p['image']) ? (array)$p['image'] : [];
                    $det     = $this->det($p);

                    $caption = isset($det['caption']) ? esc_html($det['caption']) : '';
                    $price_v = isset($det['price'])   ? floatval($det['price']) : 0;
                    $popup_id= 'popup-'.($i+1);

                    $pcats = [];
                    if ( isset($det['cats']) && is_array($det['cats']) ) {
                        if ( array_values($det['cats']) === $det['cats'] ) {
                            foreach ( $det['cats'] as $maybe_slug ) $pcats[] = sanitize_title( $maybe_slug );
                        } else {
                            foreach ( $det['cats'] as $slug => $on ) if ($on) $pcats[] = sanitize_title( $slug );
                        }
                    }
                    $pcats = array_slice( array_values( array_unique($pcats) ), 0, 5 );

                    $card_cls = 'product-card' . ( $enabled ? '' : ' outsell' );
                    $btn_attr = $enabled ? '' : ' disabled aria-disabled="true"';
                    $btn_text = $enabled ? $btn_avail : $btn_unav;

                    if ( empty($img['url']) ) {
                        $img = array(
                            'id'  => 0,
                            'url' => get_template_directory_uri() . '/assets/images/sizes/CoffeeSizeP.svg'
                        );
                    }

                    $price_k_card = number_format_i18n( $price_v );
                    ?>
                    <section class="<?php echo esc_attr($card_cls); ?>"
                             data-cats="<?php echo esc_attr(implode(' ', $pcats)); ?>"
                             data-price="<?php echo esc_attr( $price_v ); ?>"
                             data-index="<?php echo esc_attr( $i ); ?>">
                        <div class="product-card-upper">
                            <div class="product-image">
                                <?php echo $this->render_responsive_img( $img, $title, 'card' ); ?>
                            </div>
                            <div class="price-caption-section">
                                <div class="name-caption-section">
                                    <span class="name-phrase"><?php echo $title; ?></span>
                                    <span class="caption-phrase"><?php echo $caption; ?></span>
                                </div>
                                <div class="price-section">
                                    <span class="price-phrase">قیمت:</span>
                                    <div class="number-toman-section">
                                        <span class="number-phrase"><?php echo esc_html($price_k_card); ?></span>
                                        <span class="toman-phrase"><?php echo esc_html($unit_k); ?></span>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <button class="product-card-button" data-popup-id="<?php echo esc_attr($popup_id); ?>"<?php echo $btn_attr; ?>>
                            <?php echo esc_html($btn_text); ?>
                        </button>

                        <!-- پاپ‌آپ -->
                        <div class="popup" id="<?php echo esc_attr($popup_id); ?>" role="dialog" aria-modal="true" aria-labelledby="<?php echo esc_attr($popup_id); ?>-title">
                            <div class="popup-content container">
                                <div class="popup-container">
                                    <div class="popup-upper">
                                        <div class="popup-right">
                                            <div class="popup-img">
                                                <?php
                                                $popup_media = $img;
                                                if ( empty($popup_media['url']) || strpos($popup_media['url'], 'CoffeeSizeP') !== false ) {
                                                    $popup_media = array(
                                                        'id'  => 0,
                                                        'url' => get_template_directory_uri() . '/assets/images/sizes/CoffeeSizePG.svg'
                                                    );
                                                }
                                                echo $this->render_responsive_img( $popup_media, $title, 'popup' );
                                                ?>
                                            </div>
                                            <div class="popup-price-caption-section">
                                                <div class="popup-name-caption-section">
                                                    <span class="popup-name-phrase" id="<?php echo esc_attr($popup_id); ?>-title"><?php echo $title; ?></span>
                                                    <span class="popup-caption-phrase"><?php echo $caption; ?></span>
                                                </div>
                                                <div class="popup-price-section">
                                                    <span class="popup-price-phrase">قیمت:</span>
                                                    <div class="popup-number-toman-section">
                                                        <?php $price_k_popup = number_format_i18n( $price_v ); ?>
                                                        <span class="popup-number-phrase"><?php echo esc_html($price_k_popup); ?></span>
                                                        <span class="popup-toman-phrase"><?php echo esc_html($unit_k); ?></span>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                        <div class="popup-left">
                                            <div class="close-btn" role="button" tabindex="0" aria-label="<?php echo esc_attr('بستن'); ?>"><i class="ph ph-x" aria-hidden="true"></i></div>
                                        </div>
                                    </div>

                                    <div class="popup-mid">
                                        <?php
                                        if ( !empty($det['sizes_enable']) && !empty($det['sizes']) ) {
                                            echo '<div class="coffee-size"><span>سایز لیوان</span><div class="popup-mid-item">';
                                            foreach ( (array)$det['sizes'] as $sz ) {
                                                $name  = isset($sz['name']) ? esc_html($sz['name']) : '';
                                                $icon  = isset($sz['icon']) ? (array)$sz['icon'] : [];
                                                $mode  = isset($sz['price_mode']) ? $sz['price_mode'] : 'none';
                                                $delta = ($mode!=='none' && isset($sz['price_delta'])) ? floatval($sz['price_delta']) : 0;
                                                $sign  = ($mode==='plus' ? '+' : ($mode==='minus' ? '−' : ''));
                                                echo '<div class="popup-mid-container"
               data-name="'.esc_attr($name).'"
               data-price="'.esc_attr($delta).'"
               data-unit="'.esc_attr($currency).'"
               data-sign="'.esc_attr($mode==='none' ? '' : ($mode==='plus' ? '+' : '-')).'">';
                                                echo '<div class="icon">'.$this->svg_or_img($icon).'</div>';
                                                echo '<div class="hover-popup-mid-container">
                <span class="hover-popup-mid-container-toman">'.esc_html($currency).'</span>
                <div class="plus-price-name">
                  <div class="plus-price">
                    <span>'.esc_html($sign).'</span>
                    <span>'.($mode==='none' ? esc_html('رایگان') : esc_html($delta)).'</span>
                  </div>
                  <span>'.$name.'</span>
                </div>
              </div>';
                                                echo '</div>';
                                            }
                                            echo '</div></div>';
                                        }

                                        if ( !empty($det['companions_enable']) && !empty($det['companions']) ) {
                                            echo '<div class="coffee-ad"><span>آیتم‌های همراه</span><div class="popup-mid-item">';
                                            foreach ( (array)$det['companions'] as $cm ) {
                                                $name = isset($cm['name']) ? esc_html($cm['name']) : '';
                                                $icon = isset($cm['icon']) ? (array)$cm['icon'] : [];
                                                $pm   = isset($cm['price_mode']) ? $cm['price_mode'] : 'free';
                                                $val  = ($pm==='paid' && isset($cm['price'])) ? floatval($cm['price']) : 0;

                                                $icon_url = !empty($icon['url'])
                                                    ? esc_url($icon['url'])
                                                    : esc_url( get_template_directory_uri() . '/assets/images/coffeeAD/CoffeeAdP.svg' );

                                                echo '<div class="popup-mid-container"
               data-name="'.esc_attr($name).'"
               data-price="'.esc_attr($val).'"
               data-unit="'.esc_attr($currency).'"
               data-sign="'.esc_attr($pm==='paid' ? '+' : '').'">';
                                                echo '<div class="icon"><img src="'.$icon_url.'" alt="" loading="lazy" decoding="async" /></div>';
                                                echo '<div class="hover-popup-mid-container">
                <span class="hover-popup-mid-container-toman">'.esc_html($currency).'</span>
                <div class="plus-price-name">
                  <div class="plus-price">
                    <span>'.($pm==='paid' ? '+' : '').'</span>
                    <span>'.($pm==='paid' ? esc_html($val) : esc_html('رایگان')).'</span>
                  </div>
                  <span>'.$name.'</span>
                </div>
              </div>';
                                                echo '</div>';
                                            }
                                            echo '</div></div>';
                                        }

                                        if ( !empty($det['addons_enable']) && !empty($det['addons']) ) {
                                            echo '<div class="coffee-item"><span>افزودنی‌ها</span><div class="popup-mid-items">';
                                            foreach ( (array)$det['addons'] as $ad ) {
                                                $name = isset($ad['name']) ? esc_html($ad['name']) : '';
                                                $pm   = isset($ad['price_mode']) ? $ad['price_mode'] : 'paid';
                                                $val  = ($pm==='paid' && isset($ad['price'])) ? floatval($ad['price']) : 0;
                                                echo '<div class="popup-item-container"
               data-name="'.esc_attr($name).'"
               data-price="'.esc_attr($val).'"
               data-unit="'.esc_attr($currency).'"
               data-sign="'.esc_attr($pm==='paid' ? '+' : '').'">
                <div class="hover-popup-mid-container">
                  <span class="hover-popup-mid-container-toman">'.esc_html($currency).'</span>
                  <div class="plus-price-name">
                    <div class="plus-price">
                      <span>'.($pm==='paid' ? '+' : '').'</span>
                      <span>'.($pm==='paid' ? esc_html($val) : esc_html('رایگان')).'</span>
                    </div>
                    <span>'.$name.'</span>
                  </div>
                </div>
              </div>';
                                            }
                                            echo '</div></div>';
                                        }

                                        $blend_points = $this->build_blend_points($det);
                                        if ( !empty($det['blend_enable']) && !empty($blend_points) ) {
                                            echo '<div class="coffee-percent">
                                            <span>ترکیب قهوه</span>
                                            <div class="slider-container">
                                              <div class="slider-container-2">
                                                <div class="value-display" id="valueDisplay"></div>
                                                <div class="slider-track" id="sliderTrack">';
                                            foreach ($blend_points as $bp) {
                                                $cls = 'point point-'.$bp['label'].($bp['active'] ? '' : ' disabled');
                                                echo '<div class="'.$cls.'" data-name="'.esc_attr($bp['sign']).'" data-price="'.esc_attr($bp['price']).'"></div>';
                                            }
                                            echo '     <div class="slider-thumb" id="sliderThumb"></div>
                                                </div>
                                                <div class="labels"><span>عربیکا</span><span>روبوستا</span></div>
                                              </div>
                                              <div class="slider-container-price-toman">
                                                <div class="slider-container-price">
                                                  <span class="slider-container-price-price">۰</span>
                                                  <span class="slider-container-price-plus"></span>
                                                </div>
                                                <span class="slider-container-toman">'.esc_html($currency).'</span>
                                              </div>
                                            </div>
                                          </div>';
                                        }
                                        ?>
                                    </div>

                                    <div class="popup-lower"></div>
                                </div>
                            </div>
                        </div>
                    </section>
                <?php endforeach; ?>
            </div>
        </section>

        <!-- === Polyfills (iOS قدیمی) + Helpers === -->
        <script>
            (function(){
                if (!Element.prototype.matches) {
                    Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
                }
                if (!Element.prototype.closest) {
                    Element.prototype.closest = function(s) {
                        var el = this;
                        if (!document.documentElement.contains(el)) return null;
                        do { if (el.matches(s)) return el; el = el.parentElement || el.parentNode; }
                        while (el !== null && el.nodeType === 1);
                        return null;
                    };
                }
            })();
        </script>

        <!-- === 1) سورت کارت‌ها === -->
        <script>
            (function(){
                var root = document.querySelector('[data-pw-id="<?php echo esc_js($wid); ?>"]');
                if (!root) return;

                var cardsWrap = root.querySelector('.product-cards');
                var sortBtn   = root.querySelector('.sort-btn');
                var sortDD    = root.querySelector('#sort-dd-<?php echo esc_js($wid); ?>');

                function toNum(v){ v = parseFloat(v); return isNaN(v) ? 0 : v; }
                function toInt(v){ v = parseInt(v,10); return isNaN(v) ? 0 : v; }

                function getCards(){
                    if(!cardsWrap) return [];
                    var nodes = Array.prototype.slice.call(cardsWrap.children||[]);
                    var out = [];
                    for (var i=0;i<nodes.length;i++){
                        var el = nodes[i];
                        if (el && el.classList && el.classList.contains('product-card')) out.push(el);
                    }
                    return out;
                }

                function sortAndRender(mode){
                    var cards = getCards();
                    if(!cards.length) return;
                    var arr = cards.slice();

                    if(mode==='cheap'){
                        arr.sort(function(a,b){ return toNum(a.getAttribute('data-price')) - toNum(b.getAttribute('data-price')); });
                    }else if(mode==='expensive'){
                        arr.sort(function(a,b){ return toNum(b.getAttribute('data-price')) - toNum(a.getAttribute('data-price')); });
                    }else if(mode==='newest'){
                        arr.sort(function(a,b){ return toInt(b.getAttribute('data-index')) - toInt(a.getAttribute('data-index')); });
                    }else{
                        arr.sort(function(a,b){ return toInt(a.getAttribute('data-index')) - toInt(b.getAttribute('data-index')); });
                    }
                    for (var i=0;i<arr.length;i++) cardsWrap.appendChild(arr[i]);
                }

                if(sortBtn && sortDD){
                    var firstOpt = sortDD.querySelector('.sort-opt[data-sort="default"]');
                    if(firstOpt) firstOpt.classList.add('active');

                    sortBtn.addEventListener('click', function(){
                        var open = !sortDD.hasAttribute('hidden');
                        if(open){ sortDD.setAttribute('hidden',''); sortBtn.setAttribute('aria-expanded','false'); }
                        else    { sortDD.removeAttribute('hidden');  sortBtn.setAttribute('aria-expanded','true');  }
                    }, false);

                    document.addEventListener('click', function(ev){
                        if(!root.contains(ev.target)){
                            if(!sortDD.hasAttribute('hidden')){
                                sortDD.setAttribute('hidden',''); sortBtn.setAttribute('aria-expanded','false');
                            }
                        }
                    }, {capture:true, passive:true});

                    sortDD.addEventListener('click', function(ev){
                        var opt  = ev.target.closest('.sort-opt'); if(!opt) return;
                        var mode = opt.getAttribute('data-sort') || 'default';
                        sortAndRender(mode);
                        var actives = sortDD.querySelectorAll('.sort-opt.active');
                        for (var i=0;i<actives.length;i++) actives[i].classList.remove('active');
                        opt.classList.add('active');
                        sortDD.setAttribute('hidden',''); sortBtn.setAttribute('aria-expanded','false');
                    }, false);
                }
            })();
        </script>

        <!-- === 2) پاپ‌آپ‌ها + جمع نهایی + iOS-safe scroll lock === -->
        <script>
            (function(){
                var root = document.querySelector('[data-pw-id="<?php echo esc_js($wid); ?>"]');
                if(!root) return;

                var notesOn = !(window.CAFFITO && window.CAFFITO.notesEnabled === false);

                function qsa(sel, ctx){ return Array.prototype.slice.call((ctx||document).querySelectorAll(sel)); }
                function qs(sel, ctx){ return (ctx||document).querySelector(sel); }
                function normSign(s){ if(!s) return ''; s=(''+s).trim(); return (s==='−'||s==='–')?'-':(s==='+'?'+':(s==='-'?'-':'')); }
                function fmt(n){ try{ return Math.round(n).toLocaleString('fa-IR'); }catch(e){ return String(Math.round(n)); } }
                function toNum(v){ v = parseFloat(v); return isNaN(v) ? 0 : v; }
                function toNumText(s){
                    if(s==null) return 0;
                    s = String(s).replace(/[۰-۹٠-٩]/g, function(d){
                        var map = {'۰':'0','۱':'1','۲':'2','۳':'3','۴':'4','۵':'5','۶':'6','۷':'7','۸':'8','۹':'9','٠':'0','١':'1','٢':'2','٣':'3','٤':'4','٥':'5','٦':'6','٧':'7','٨':'8','٩':'9'};
                        return map[d] || d;
                    }).replace(/[,٬\s]/g,'');
                    var n = parseFloat(s); return isNaN(n)?0:n;
                }
                function getUnitPhrase(popup){
                    if (window.CAFFITO && window.CAFFITO.unitPhrase) return String(window.CAFFITO.unitPhrase);
                    var node = qs('.popup-toman-phrase', popup) || qs('.slider-container-toman', popup);
                    return node ? node.textContent.replace(/\s+/g,' ').trim() : 'هزار تومان';
                }

                // --- iOS-safe scroll lock helpers
                var _guard = null, _locked = false, _saved = {};
                function lockScroll(container){
                    if (_locked) return;
                    _saved.bodyOverflow = document.body.style.overflow;
                    _saved.htmlOverflow = document.documentElement.style.overflow;
                    document.body.style.overflow = 'hidden';
                    document.documentElement.style.overflow = 'hidden';
                    _guard = function(e){ if (!container.contains(e.target)) e.preventDefault(); };
                    document.addEventListener('touchmove', _guard, {passive:false});
                    _locked = true;
                }
                function unlockScroll(){
                    if (!_locked) return;
                    document.body.style.overflow = _saved.bodyOverflow || '';
                    document.documentElement.style.overflow = _saved.htmlOverflow || '';
                    document.removeEventListener('touchmove', _guard, {passive:false});
                    _guard = null; _locked = false;
                }

                function updateTotal(card, popup){
                    var base = toNum(card.getAttribute('data-price'));
                    var total = base;

                    var sizeSel = qs('.coffee-size .popup-mid-container.activeX', popup);
                    if(sizeSel){
                        var sgn = normSign(sizeSel.getAttribute('data-sign'));
                        var val = toNum(sizeSel.getAttribute('data-price'));
                        if(sgn === '+') total += val;
                        else if(sgn === '-') total -= val;
                    }

                    var comps = qsa('.coffee-ad .popup-mid-container.activeX', popup);
                    for (var i=0;i<comps.length;i++){
                        var sgnC = normSign(comps[i].getAttribute('data-sign'));
                        var valC = toNum(comps[i].getAttribute('data-price'));
                        if(sgnC === '+') total += valC;
                    }
                    var adds = qsa('.coffee-item .popup-item-container.activeX', popup);
                    for (var j=0;j<adds.length;j++){
                        var sgnA = normSign(adds[j].getAttribute('data-sign'));
                        var valA = toNum(adds[j].getAttribute('data-price'));
                        if(sgnA === '+') total += valA;
                    }

                    var dispNum = qs('.slider-container-price-price', popup);
                    var dispSign= qs('.slider-container-price-plus',  popup);
                    var usedBlend = false;
                    if(dispNum){
                        var valD = toNumText(dispNum.textContent);
                        var sgnD = normSign(dispSign ? dispSign.textContent : '');
                        if(sgnD==='+' || sgnD==='-'){
                            total += (sgnD==='+') ? valD : -valD;
                            usedBlend = true;
                        }
                    }
                    if(!usedBlend){
                        var blendSel = qs('.coffee-percent .point.activeX', popup);
                        if(blendSel){
                            var s2 = normSign(blendSel.getAttribute('data-name'));
                            var v2 = toNum(blendSel.getAttribute('data-price'));
                            if(s2 === '+') total += v2;
                            else if(s2 === '-') total -= v2;
                        }
                    }

                    var numEl = qs('.wishlist-cta .wishlist-cta-price-number', popup);
                    if(numEl) numEl.textContent = fmt(total);
                }

                function resetSelections(card, popup){
                    var act = qsa('.coffee-size .popup-mid-container.activeX, .coffee-ad .popup-mid-container.activeX, .coffee-item .popup-item-container.activeX, .coffee-percent .point.activeX', popup);
                    for (var i=0;i<act.length;i++){ act[i].classList.remove('activeX'); act[i].removeAttribute('aria-checked'); }
                    var dispNum = qs('.slider-container-price-price', popup);
                    var dispSign= qs('.slider-container-price-plus', popup);
                    if(dispNum) dispNum.textContent = fmt(0);
                    if(dispSign) dispSign.textContent = '';
                    updateTotal(card, popup);
                }

                function addToWishlist(card, popup, idx){
                    var title = (qs('.popup-name-phrase', popup) || {}).textContent || '';
                    var base  = toNum(card.getAttribute('data-price'));
                    var unit  = getUnitPhrase(popup);
                    var wid   = root.getAttribute('data-pw-id') || '';
                    var pid   = card.getAttribute('data-index') || String(idx);

                    function pickName(el){ return el ? (el.getAttribute('data-name') || '').trim() : ''; }

                    var sizeSel = qs('.coffee-size .popup-mid-container.activeX', popup);
                    var size = sizeSel ? {
                        name: pickName(sizeSel),
                        sign: normSign(sizeSel.getAttribute('data-sign')),
                        delta: toNum(sizeSel.getAttribute('data-price'))
                    } : null;

                    var companions = qsa('.coffee-ad .popup-mid-container.activeX', popup).map(function(el){
                        return { name: pickName(el), sign: normSign(el.getAttribute('data-sign')), delta: toNum(el.getAttribute('data-price')) };
                    });

                    var addons = qsa('.coffee-item .popup-item-container.activeX', popup).map(function(el){
                        return { name: pickName(el), sign: normSign(el.getAttribute('data-sign')), delta: toNum(el.getAttribute('data-price')) };
                    });

                    var dispNum  = qs('.slider-container-price-price', popup);
                    var dispSign = qs('.slider-container-price-plus',  popup);
                    var blend = null;
                    if(dispNum){
                        var valD = toNumText(dispNum.textContent);
                        var sgnD = normSign(dispSign ? dispSign.textContent : '');
                        var act  = qs('.coffee-percent .point.activeX', popup);
                        var lbl  = '';
                        if(act){ var m = (act.className||'').match(/point-(\d+)/); lbl = m ? m[1] : ''; }
                        blend = { point: lbl, sign: sgnD, delta: valD };
                    }

                    var thumbUrl = '';
                    var imgEl = popup.querySelector('.popup-img .popup-img-el, .popup-img img')
                        || card.querySelector('.product-image .product-card-img, .product-image img');
                    if(imgEl){ thumbUrl = imgEl.currentSrc || imgEl.src || ''; }

                    var total = base;
                    if(size) total += (size.sign==='+'? size.delta : size.sign==='-'? -size.delta : 0);
                    for (var i=0;i<companions.length;i++){ if(companions[i].sign==='+') total += companions[i].delta; }
                    for (var j=0;j<addons.length;j++){ if(addons[j].sign==='+') total += addons[j].delta; }
                    if(blend){
                        if(blend.sign==='+') total += blend.delta;
                        else if(blend.sign==='-') total -= blend.delta;
                    }

                    try{
                        var key = 'caffito_wishlist';
                        var list = [];
                        try{ list = JSON.parse(localStorage.getItem(key) || '[]'); }catch(e){}
                        list.push({
                            id: 'productW:'+wid+':'+pid+':'+Date.now(),
                            widgetId: wid,
                            index: pid,
                            title: (title||'').trim(),
                            base: base,
                            currency: unit.trim(),
                            size: size,
                            companions: companions,
                            addons: addons,
                            blend: blend,
                            total: total,
                            thumb: thumbUrl,
                            ts: Date.now()
                        });
                        localStorage.setItem(key, JSON.stringify(list));
                        try { window.dispatchEvent(new Event('caffito_wishlist_changed')); } catch(e){}

                        var btn = qs('.wishlist-add-btn', popup);
                        if(btn){
                            var old = btn.innerHTML;
                            btn.classList.add('activeX');
                            btn.innerHTML = '<span>به یادداشت اضافه شد</span>';
                            resetSelections(card, popup);
                            setTimeout(function(){ btn.classList.remove('activeX'); btn.innerHTML = old; }, 1200);
                        }else{
                            resetSelections(card, popup);
                        }
                    }catch(e){ /* ignore */ }
                }

                // --- اتصال رفتار باز/بستن پاپ‌آپ‌ها (با قفل اسکرول iOS)
                (function bindPopups(){
                    var cards = qsa('.product-card', root);
                    for (var i=0;i<cards.length;i++){
                        (function(card, idx){
                            var popup = card.querySelector('.popup'); if(!popup) return;
                            var opener = card.querySelector('.product-card-button');
                            var closer = popup.querySelector('.close-btn');

                            function open(){
                                popup.classList.add('open');
                                popup.setAttribute('aria-hidden','false');
                                lockScroll(popup);
                                // یک‌بار CTA تزریق نشده باشد هم‌زمان انجام می‌شود
                                if (!popup.__ctaInjected && notesOn) {
                                    var lower = qs('.popup-lower', popup);
                                    if (lower){
                                        var unitText = getUnitPhrase(popup);
                                        var cta = document.createElement('div');
                                        cta.className = 'wishlist-cta';
                                        cta.setAttribute('dir','rtl');
                                        cta.innerHTML =
                                            '<button type="button" class="wishlist-add-btn" aria-label="افزودن به یادداشت">'
                                            + '<span class="wishlist-cta-price-label">قیمت نهایی </span>'
                                            + '<span class="wishlist-cta-price-number">0</span> '
                                            + '<span class="wishlist-cta-price-unit">'+ unitText +'</span>'
                                            + (notesOn?'<span class="wishlist-cta-sep"> - </span><span class="wishlist-cta-add">افزودن به یادداشت</span>':'')
                                            + '</button>';
                                        lower.appendChild(cta);
                                        popup.__ctaInjected = true;
                                    }
                                }
                                updateTotal(card, popup);
                            }
                            function close(){
                                popup.classList.remove('open');
                                popup.setAttribute('aria-hidden','true');
                                unlockScroll();
                            }

                            if (opener && !opener.__bound){
                                opener.addEventListener('click', function(){
                                    if (opener.hasAttribute('disabled')) return;
                                    open();
                                }, {passive:true});
                                opener.__bound = true;
                            }
                            if (closer && !closer.__bound){
                                closer.addEventListener('click', function(){ close(); }, false);
                                closer.__bound = true;
                            }
                            // کلیک روی بیرون محتوای پاپ‌آپ
                            popup.addEventListener('click', function(e){
                                if (e.target === popup) close();
                            }, false);
                            // ESC
                            document.addEventListener('keydown', function(e){
                                if (e.key === 'Escape' && popup.classList.contains('open')) close();
                            }, false);

                            // انتخاب‌ها و تغییر قیمت‌ها
                            popup.addEventListener('click', function(ev){
                                var t = ev.target;

                                var sizeItem = t.closest('.coffee-size .popup-mid-container');
                                if(sizeItem && popup.contains(sizeItem)){
                                    var sel = qsa('.coffee-size .popup-mid-container.activeX', popup);
                                    for (var k=0;k<sel.length;k++){ sel[k].classList.remove('activeX'); sel[k].setAttribute('aria-checked','false'); }
                                    sizeItem.classList.add('activeX'); sizeItem.setAttribute('aria-checked','true');
                                    updateTotal(card, popup);
                                    return;
                                }

                                var compItem = t.closest('.coffee-ad .popup-mid-container');
                                if(compItem && popup.contains(compItem)){
                                    compItem.classList.toggle('activeX');
                                    compItem.setAttribute('aria-checked', compItem.classList.contains('activeX') ? 'true':'false');
                                    updateTotal(card, popup);
                                    return;
                                }

                                var addonItem = t.closest('.coffee-item .popup-item-container');
                                if(addonItem && popup.contains(addonItem)){
                                    addonItem.classList.toggle('activeX');
                                    addonItem.setAttribute('aria-checked', addonItem.classList.contains('activeX') ? 'true':'false');
                                    updateTotal(card, popup);
                                    return;
                                }

                                var point = t.closest('.coffee-percent .point');
                                if(point && popup.contains(point) && !point.classList.contains('disabled')){
                                    var act2 = qsa('.coffee-percent .point.activeX', popup);
                                    for (var j=0;j<act2.length;j++){ act2[j].classList.remove('activeX'); act2[j].removeAttribute('aria-checked'); }
                                    point.classList.add('activeX'); point.setAttribute('aria-checked','true');

                                    var pNum = qs('.slider-container-price-price', popup);
                                    var pSign= qs('.slider-container-price-plus',  popup);
                                    if(pNum)  pNum.textContent  = fmt( toNum(point.getAttribute('data-price')) );
                                    if(pSign) pSign.textContent = (point.getAttribute('data-name')||'').trim();
                                    updateTotal(card, popup);
                                    return;
                                }

                                if(t.closest('.wishlist-add-btn')){
                                    if (notesOn) addToWishlist(card, popup, idx);
                                }
                            }, false);

                            // همگام‌سازی روی حرکت اسلایدر
                            var track = qs('.slider-track', popup);
                            if(track && !track.__boundMove){
                                var safeMove = function(){ updateTotal(card, popup); };
                                track.addEventListener('pointermove', safeMove, {passive:true});
                                track.addEventListener('mousemove',   safeMove, {passive:true});
                                track.addEventListener('touchmove',   safeMove, {passive:true});
                                track.__boundMove = true;
                            }
                        })(cards[i], i);
                    }
                })();

            })();
        </script>

        <?php if ( $notes_enabled ) : ?>
            <!-- === استایل‌های اختصاصی دکمه «فراخوان گارسون» (افکت سبز + پیام ریز) === -->
            <style>
                .notes-toggle-btn{ z-index: 2147483000; }
                .notes-drawer .notes-footer .notes-call{
                    position: relative;
                    transition: box-shadow .25s ease, transform .07s ease;
                    will-change: box-shadow, transform;
                }
                .notes-drawer .notes-footer .notes-call.flash-success{
                    box-shadow: 0 0 0 0 rgba(16,185,129,.55);
                    animation: caffitoCallGlow 900ms ease-out;
                }
                @keyframes caffitoCallGlow{
                    0%{ box-shadow: 0 0 0 0 rgba(16,185,129,.55); transform: translateY(0); }
                    60%{ box-shadow: 0 0 0 18px rgba(16,185,129,0); transform: translateY(-1px); }
                    100%{ box-shadow: 0 0 0 0 rgba(16,185,129,0); transform: translateY(0); }
                }
                .notes-drawer .notes-footer .notes-call.warn{
                    background: #fff7ed; border-color:#f59e0b; color:#92400e;
                }
                .notes-drawer .notes-footer .notes-call .btn-hint{
                    display:block; font-size:12px; line-height:1.3; opacity:.9; margin-top:2px;
                }
                .notes-first{
                    font-size: 12px;
                    font-weight: 500;
                    margin-top: 8px;

                }
            </style>

            <!-- === 3) دراور «یادداشت‌ها» + قفل اسکرول iOS === -->
            <script>
                (function(){
                    if(document.getElementById('caffito-notes-toggle')) return;

                    var btn = document.createElement('button');
                    btn.id = 'caffito-notes-toggle';
                    btn.type = 'button';
                    btn.className = 'notes-toggle-btn';
                    btn.setAttribute('aria-expanded','false');
                    btn.setAttribute('aria-controls','caffito-notes-drawer');
                    btn.innerHTML = '<span class="notes-toggle-label">یادداشت‌ها</span>';
                    document.body.appendChild(btn);

                    var drawer = document.createElement('div');
                    drawer.id = 'caffito-notes-drawer';
                    drawer.className = 'notes-drawer';
                    drawer.setAttribute('aria-hidden','true');

                    var overlay = document.createElement('div'); overlay.className='notes-overlay'; drawer.appendChild(overlay);

                    var panel = document.createElement('div');
                    panel.className = 'notes-panel';
                    panel.setAttribute('role','dialog'); panel.setAttribute('aria-modal','true'); panel.setAttribute('aria-label','یادداشت‌ها'); panel.tabIndex=-1;

                    var header = document.createElement('div');
                    header.className='notes-header';
                    header.innerHTML = '<span class="notes-title">یادداشت‌ها</span><button type="button" class="notes-close" aria-label="بستن">&times;</button>';

                    var body  = document.createElement('div'); body.className = 'notes-body';
                    panel.appendChild(header); panel.appendChild(body); drawer.appendChild(panel); document.body.appendChild(drawer);

                    // iOS-safe scroll lock for drawer
                    var guard = null, locked = false, saved = {};
                    function lock(){
                        if (locked) return;
                        saved.bodyOverflow = document.body.style.overflow;
                        saved.htmlOverflow = document.documentElement.style.overflow;
                        document.body.style.overflow='hidden';
                        document.documentElement.style.overflow='hidden';
                        guard = function(e){ if (!panel.contains(e.target)) e.preventDefault(); };
                        document.addEventListener('touchmove', guard, {passive:false});
                        locked = true;
                    }
                    function unlock(){
                        if (!locked) return;
                        document.body.style.overflow = saved.bodyOverflow || '';
                        document.documentElement.style.overflow = saved.htmlOverflow || '';
                        document.removeEventListener('touchmove', guard, {passive:false});
                        guard = null; locked = false;
                    }

                    function open(){
                        lock();
                        drawer.classList.add('open','activeX');
                        btn.classList.add('activeX');
                        drawer.setAttribute('aria-hidden','false');
                        btn.setAttribute('aria-expanded','true');
                        try{ window.dispatchEvent(new Event('caffito_wishlist_changed')); }catch(e){}
                        panel.focus();
                    }
                    function close(){
                        drawer.classList.remove('open','activeX');
                        btn.classList.remove('activeX');
                        drawer.setAttribute('aria-hidden','true');
                        btn.setAttribute('aria-expanded','false');
                        unlock();
                    }

                    btn.addEventListener('click', function(){ if (drawer.classList.contains('open')) close(); else open(); }, false);
                    overlay.addEventListener('click', close, false);
                    drawer.addEventListener('click', function(e){ if (e.target.closest && e.target.closest('.notes-close')) close(); }, false);
                    document.addEventListener('keydown', function(e){ if (e.key==='Escape') close(); }, false);
                })();
            </script>

            <!-- === 4) «یادداشت‌ها»: رندر + جمع کل + حذف + ریت‌لیمیت + پیام روی خود دکمه === -->
            <script>
                (function(){
                    var key = 'caffito_wishlist';

                    // (اختیاری) افکت صدا
                    (function(){
                        var AC = window.AudioContext || window.webkitAudioContext;
                        if(!AC) return;
                        var __ctx;
                        function ctx(){ return __ctx || (__ctx = new AC()); }
                        window.playBellDing = window.playBellDing || function(base){
                            var c = ctx(), t0 = c.currentTime, baseFreq = (typeof base==='number' && base>80)?base:520;
                            var master = c.createGain(); master.gain.value = 0.5; master.connect(c.destination);
                            var lp = c.createBiquadFilter(); lp.type='lowpass'; lp.frequency.setValueAtTime(9000,t0); lp.frequency.exponentialRampToValueAtTime(2500,t0+1.2); lp.connect(master);
                            var partials=[{r:0.56,g:0.95,d:1.7},{r:0.92,g:0.60,d:1.4},{r:1.19,g:0.50,d:1.2},{r:1.71,g:0.35,d:1.0},{r:2.00,g:0.25,d:0.9},{r:2.74,g:0.20,d:0.8}];
                            for(var i=0;i<partials.length;i++){ var p=partials[i]; var o=c.createOscillator();o.type='sine'; var g=c.createGain();g.gain.setValueAtTime(0.0001,t0);
                                var f=baseFreq*p.r; o.frequency.setValueAtTime(f*1.03,t0); o.frequency.exponentialRampToValueAtTime(f,t0+0.12);
                                g.gain.exponentialRampToValueAtTime(0.001+p.g,t0+0.012); g.gain.exponentialRampToValueAtTime(0.0001,t0+p.d);
                                o.connect(g); g.connect(lp); o.start(t0); o.stop(t0+p.d+0.05);}
                        };
                        window.playDenyBeep = window.playDenyBeep || function(){
                            var c=ctx(),t=c.currentTime,o=c.createOscillator(),g=c.createGain();o.type='square';o.frequency.setValueAtTime(240,t);
                            g.gain.setValueAtTime(0.001,t); g.gain.exponentialRampToValueAtTime(0.25,t+0.01); g.gain.exponentialRampToValueAtTime(0.0001,t+0.18);
                            o.connect(g); g.connect(c.destination); o.start(t); o.stop(t+0.2);
                        };
                    })();

                    function readList(){ try{ return JSON.parse(localStorage.getItem(key)||'[]'); }catch(e){ return []; } }
                    function writeList(list){ localStorage.setItem(key, JSON.stringify(list||[])); }
                    function fmt(n){ try{ return Math.round(+n||0).toLocaleString('fa-IR'); }catch(e){ return String(Math.round(+n||0)); } }
                    function byId(id){ return document.getElementById(id); }
                    function esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#039;'); }
                    function getSiteUnitPhrase(items){
                        if (window.CAFFITO && window.CAFFITO.unitPhrase) return String(window.CAFFITO.unitPhrase);
                        if (items && items[0] && items[0].currency) return String(items[0].currency);
                        return 'هزار تومان';
                    }

                    function renderNotes(){
                        var drawer = byId('caffito-notes-drawer');
                        var btn    = byId('caffito-notes-toggle');
                        if(!drawer) return;
                        var bodyEl = drawer.querySelector('.notes-body');
                        if(!bodyEl) return;

                        if(!drawer.__notesBound){
                            drawer.addEventListener('click', onDrawerClick, false);
                            drawer.__notesBound = true;
                        }

                        var items = readList();

                        if(btn){
                            var cnt = btn.querySelector('.notes-count'); if(!cnt){ cnt=document.createElement('span'); cnt.className='notes-count'; btn.appendChild(cnt); }
                            cnt.textContent = items.length ? '('+items.length+')' : '';
                        }

                        var unit = getSiteUnitPhrase(items);

                        var html = '';
                        if(!items.length){
                            html += '<div class="notes-scroll" dir="rtl"><div class="notes-empty">هنوز یادداشتی اضافه نشده است.</div></div>';
                        } else {
                            html += '<div class="notes-scroll" dir="rtl"><div class="notes-list">';
                            for (var k=0;k<items.length;k++){
                                var it = items[k];
                                var lines = [];
                                if(it.size && it.size.name){
                                    var sgn = it.size.sign==='-' ? '−' : (it.size.sign==='+' ? '+' : '');
                                    var val = it.size.delta ? fmt(it.size.delta) : '۰';
                                    lines.push('<li class="note-line"><span class="note-line-title">سایز لیوان '+ esc(it.size.name) +'</span><span class="note-dots"></span><span class="note-line-price">'+ sgn + val +'</span> <span class="note-unit">'+ unit +'</span></li>');
                                }
                                var arr = (it.companions||[]).concat(it.addons||[]);
                                for (var z=0; z<arr.length; z++){
                                    var row = arr[z], sgn2 = row.sign==='-' ? '−' : (row.sign==='+' ? '+' : ''), val2 = row.delta ? fmt(row.delta) : '۰';
                                    lines.push('<li class="note-line"><span class="note-line-title">'+ esc(row.name||'') +'</span><span class="note-dots"></span><span class="note-line-price">'+ sgn2 + val2 +'</span> <span class="note-unit">'+ unit +'</span></li>');
                                }
                                if(it.blend && (it.blend.sign==='+' || it.blend.sign==='-')){
                                    var sgnB = it.blend.sign==='-' ? '−' : '+';
                                    var valB = fmt(it.blend.delta||0);
                                    var lbl  = it.blend.point ? ('ترکیب قهوه '+ it.blend.point +'%') : 'ترکیب قهوه';
                                    lines.push('<li class="note-line"><span class="note-line-title">'+ lbl +'</span><span class="note-dots"></span><span class="note-line-price">'+ sgnB + valB +'</span> <span class="note-unit">'+ unit +'</span></li>');
                                }

                                var base  = fmt(it.base||0);
                                var tot   = fmt(it.total||0);
                                var thumb = it.thumb ? '<img class="note-thumb" src="'+ esc(it.thumb) +'" alt="" loading="lazy"/>' : '';

                                var showFinalRow = (lines.length>0) || (+it.total !== +it.base);
                                html += '<div class="note-item" data-id="'+ esc(it.id||'') +'">'
                                    +   '<div class="note-head"><div class="note-title-wrap"><strong class="note-title">'+ esc(it.title||'محصول') +'</strong>'+ thumb +'</div><button class="note-remove" type="button" aria-label="حذف">×</button></div>'
                                    +   '<div class="note-row note-base" dir="rtl"><span class="note-row-title">قیمت پایه</span><span class="note-dots"></span><span class="note-row-price"><b>'+ base +'</b> <span class="note-unit">'+ unit +'</span></span></div>'
                                    +   '<ul class="note-lines">'+ lines.join('') +'</ul>'
                                    +   (showFinalRow ? '<div class="note-row note-total" dir="rtl"><span class="note-row-title">قیمت نهایی</span><span class="note-dots"></span><span class="note-row-price"><b>'+ tot +'</b> <span class="note-unit">'+ unit +'</span></span></div>' : '')
                                    +   '<hr class="note-sep"/>'
                                    + '</div>';
                            }
                            html += '</div></div>';
                        }

                        var totalAll = 0; for (var i=0;i<items.length;i++) totalAll += (+items[i].total||0);
                        html += '<div class="notes-footer" dir="rtl">'
                            +    '<div class="notes-grand">قیمت نهایی سفارش: <b>'+ fmt(totalAll) +'</b> <span class="note-unit">'+ unit +'</span></div>'
                            +    '<div class="notes-controls"><label class="table-label" for="notes-table-input">شماره میز</label><input id="notes-table-input" class="notes-table-input" type="number" inputmode="numeric" pattern="[0-9]*" placeholder="شماره میز" min="1" /><button type="button" class="notes-call" disabled>فراخوان گارسون</button></div>'
                            +    '<div class="notes-status" aria-live="polite"></div>'
                            +    '<div class="notes-first" > ابتدا شماره میز را وارد کنید.</div>'
                            +  '</div>';

                        bodyEl.innerHTML = html;
                        bindFooter(unit);
                    }

                    function onDrawerClick(e){
                        var rm = e.target.closest ? e.target.closest('.note-remove') : null;
                        if(rm){
                            var wrap = rm.closest('.note-item');
                            var id   = wrap ? wrap.getAttribute('data-id') : '';
                            if(!id) return;
                            var list = readList().filter(function(x){ return x.id !== id; });
                            writeList(list);
                            try{ window.dispatchEvent(new Event('caffito_wishlist_changed')); }catch(_){}
                            renderNotes();
                        }
                    }

                    function bindFooter(unit){
                        var drawer  = document.getElementById('caffito-notes-drawer'); if(!drawer) return;
                        var tableIn = drawer.querySelector('#notes-table-input');
                        var callBtn = drawer.querySelector('.notes-call');
                        var status  = drawer.querySelector('.notes-status');

                        // helper: پیام کوچک روی خود دکمه
                        function showOnBtn(msg, extraCls, dur){
                            if(!callBtn) return;
                            if(!callBtn.__baseHTML){ callBtn.__baseHTML = callBtn.innerHTML; }
                            var baseText = (callBtn.__baseText || callBtn.textContent || 'فراخوان گارسون').trim();
                            callBtn.__baseText = baseText;
                            callBtn.innerHTML = '<span class="btn-main">'+ baseText +'</span><small class="btn-hint">'+ (msg||'') +'</small>';
                            if(extraCls){ callBtn.classList.add(extraCls); }
                            var t = setTimeout(function(){
                                if(extraCls) callBtn.classList.remove(extraCls);
                                callBtn.innerHTML = callBtn.__baseHTML;
                            }, dur || 1600);
                            return t;
                        }

                        function fa2en(s){
                            var map = {'۰':'0','۱':'1','۲':'2','۳':'3','۴':'4','۵':'5','۶':'6','۷':'7','۸':'8','۹':'9','٠':'0','١':'1','٢':'2','٣':'3','٤':'4','٥':'5','٦':'6','٧':'7','٨':'8','٩':'9'};
                            return String(s||'').replace(/[۰-۹٠-٩]/g,function(d){return map[d]||d;});
                        }

                        if(tableIn && callBtn){
                            // Enable/disable با نرمال‌سازی رقم‌های فارسی/عربی
                            var enableIfValid = function(){
                                var ascii = fa2en(tableIn.value).replace(/\D+/g,'');
                                if (tableIn.value !== ascii) tableIn.value = ascii;
                                callBtn.disabled = !(parseInt(ascii,10) > 0);
                            };
                            tableIn.addEventListener('input', enableIfValid, false);
                            tableIn.addEventListener('keyup',  enableIfValid, false);
                            enableIfValid();

                            callBtn.addEventListener('click', function(){
                                var n = parseInt(fa2en(tableIn.value),10);

                                // (۲) اگر شماره میز وارد نشده باشد → پیام روی خود دکمه
                                if(!(n>0)){
                                    showOnBtn('اول شماره میز را وارد کنید', 'warn', 1700);
                                    if(window.playDenyBeep) window.playDenyBeep();
                                    if(status){ status.textContent = 'اول شماره میز را وارد کنید.'; }
                                    return;
                                }

                                // (۳) ریت‌لیمیت ۶۰ ثانیه (بیشتر از دوبار در دقیقه = اسپم)
                                var last=null; try{ last = JSON.parse(localStorage.getItem('caffito_waiter_last') || 'null'); }catch(_){}
                                var now = Date.now();
                                if(last && last.ts && (now - last.ts) < 60000){
                                    var left = Math.ceil((60000 - (now - last.ts))/1000);
                                    showOnBtn('لطفاً '+ left +' ثانیه دیگر تلاش کنید', 'warn', 1900);
                                    if(window.playDenyBeep) window.playDenyBeep();
                                    if(status){ status.textContent = 'درخواست قبلی ثبت شده. لطفاً '+ left +' ثانیه دیگر تلاش کنید.'; }
                                    return;
                                }

                                // ذخیرهٔ زمان آخرین فراخوان
                                var code = 'T' + n + '-' + now.toString(36).toUpperCase();
                                try{ localStorage.setItem('caffito_waiter_last', JSON.stringify({table:n, code:code, ts:now})); }catch(_){}

                                // (۱) افکت سبز هنگام فعال شدن
                                callBtn.classList.add('flash-success');
                                setTimeout(function(){ callBtn.classList.remove('flash-success'); }, 1000);

                                // پیام موفقیت روی خود دکمه
                                showOnBtn('درخواست ثبت شد ✓', null, 2200);
                                if(window.playBellDing) window.playBellDing(520);
                                if(status){ status.textContent = 'درخواست شما ثبت شد. کد: ' + code; }

                                // ارسال به سرور: اگر سبد خالی بود، یک آیتم «فراخوان گارسون» بفرست
                                try {
                                    var list = [];
                                    try { list = JSON.parse(localStorage.getItem(key) || '[]'); } catch(e){}
                                    if (!Array.isArray(list)) list = [];
                                    var totalAll = 0; for (var q=0;q<list.length;q++) totalAll += (+list[q].total||0);

                                    if (list.length === 0) {
                                        list = [{
                                            id: 'call:'+Date.now(),
                                            title: 'فراخوانی گارسون',
                                            base: 0,
                                            total: 0,
                                            currency: (window.CAFFITO && CAFFITO.unitPhrase) ? CAFFITO.unitPhrase : 'هزار تومان',
                                            companions: [],
                                            addons: [],
                                            ts: Date.now()
                                        }];
                                    }

                                    var payload = {
                                        table_no: n,
                                        total: Math.round(totalAll),
                                        items: list
                                    };

                                    var ajaxURL = (window.CAFFITO && CAFFITO.ajaxURL) ? CAFFITO.ajaxURL : '/wp-admin/admin-ajax.php';
                                    fetch(ajaxURL, {
                                        method: 'POST',
                                        credentials: 'same-origin',
                                        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                                        body: new URLSearchParams({
                                            action: 'caffito_submit_order',
                                            payload: JSON.stringify(payload)
                                        })
                                    })
                                        .then(function(r){ return r.json(); })
                                        .then(function(j){
                                            if (j && j.success) {
                                                try { localStorage.setItem(key, '[]'); } catch(e){}
                                                try { window.dispatchEvent(new Event('caffito_wishlist_changed')); } catch(e){}
                                            } else {
                                                // اگر سرور رد کرد، پیام خطا روی دکمه (بدون تغییرات دیگر)
                                                showOnBtn('ارسال ناموفق شد', 'warn', 2000);
                                            }
                                        })
                                        .catch(function(e){
                                            showOnBtn('مشکل در ارتباط', 'warn', 2000);
                                        });
                                } catch(e) {
                                    /* ignore */
                                }
                            }, false);
                        }
                    }
                    renderNotes();
                    window.addEventListener('storage', function(e){ if (e.key===key) renderNotes(); }, false);
                    window.addEventListener('caffito_wishlist_changed', renderNotes, false);
                })();
            </script>
        <?php endif; ?>
        <?php
    }

    public function get_script_depends(){ return ['jquery']; }
    public function get_style_depends(){ return []; }
}

add_action('elementor/widgets/register', function($widgets_manager){
    $widgets_manager->register( new \ProductW() );
});