/* ============================================
   RSL Date Picker Component
   Version: 2.0.0
   Description: Premium accessible date picker with
   single date, date range, and multiple date selection.
   Full ADA/WCAG 2.1 AA compliant with keyboard navigation,
   screen reader support, and live announcements.

   FilterBus Integration (v2.0.0):
   - Publishes date selection to FilterBus for cross-component filtering
   - Use data-filterbus-publish="key" to enable publishing
   - Published value includes: date/dateRange/dates, formatted, mode
   ============================================ */

(function() {
    'use strict';

    // Initialize RSL namespace
    window.RSL = window.RSL || {};

    /**
     * Date Picker Component
     * A fully accessible date picker supporting single, range, and multiple selection modes
     */
    window.RSL.DatePicker = {

        /** Store all initialized instances */
        instances: new Map(),

        /** Default configuration */
        defaults: {
            mode: 'single',           // 'single', 'range', 'multiple'
            format: 'MM/DD/YYYY',     // Display format
            outputFormat: 'YYYY-MM-DD', // Value format
            locale: 'en-US',
            firstDayOfWeek: 0,        // 0 = Sunday, 1 = Monday
            minDate: null,
            maxDate: null,
            disabledDates: [],
            disabledDays: [],         // 0-6 for days of week
            showDualCalendar: false,
            showPresets: false,
            presets: ['today', 'yesterday', 'last7', 'last30', 'thisMonth', 'lastMonth'],
            inline: false,
            closeOnSelect: true,      // Auto-close after selection (single mode)
            autoApply: true,          // Auto-apply selection without clicking Apply
            linkedTo: null,           // ID of another date picker to link
            placeholder: 'Select date',
            placeholderStart: 'Start date',
            placeholderEnd: 'End date',
            required: false,
            disabled: false,
            readOnly: false,
            showWeekNumbers: false,
            numberOfMonths: 1,
            minRange: null,           // Minimum days in range
            maxRange: null,           // Maximum days in range
            ariaLabel: 'Date picker',
            ariaLabelStart: 'Start date',
            ariaLabelEnd: 'End date',
            clearable: false              // Show clear button in input field
        },

        /** Preset configurations */
        presetDefinitions: {
            today: {
                label: 'Today',
                getRange: function() {
                    var today = new Date();
                    return { start: today, end: today };
                }
            },
            yesterday: {
                label: 'Yesterday',
                getRange: function() {
                    var yesterday = new Date();
                    yesterday.setDate(yesterday.getDate() - 1);
                    return { start: yesterday, end: yesterday };
                }
            },
            last7: {
                label: 'Last 7 days',
                getRange: function() {
                    var end = new Date();
                    var start = new Date();
                    start.setDate(start.getDate() - 6);
                    return { start: start, end: end };
                }
            },
            last30: {
                label: 'Last 30 days',
                getRange: function() {
                    var end = new Date();
                    var start = new Date();
                    start.setDate(start.getDate() - 29);
                    return { start: start, end: end };
                }
            },
            thisWeek: {
                label: 'This week',
                getRange: function() {
                    var today = new Date();
                    var start = new Date(today);
                    start.setDate(today.getDate() - today.getDay());
                    var end = new Date(start);
                    end.setDate(start.getDate() + 6);
                    return { start: start, end: end };
                }
            },
            lastWeek: {
                label: 'Last week',
                getRange: function() {
                    var today = new Date();
                    var start = new Date(today);
                    start.setDate(today.getDate() - today.getDay() - 7);
                    var end = new Date(start);
                    end.setDate(start.getDate() + 6);
                    return { start: start, end: end };
                }
            },
            thisMonth: {
                label: 'This month',
                getRange: function() {
                    var today = new Date();
                    var start = new Date(today.getFullYear(), today.getMonth(), 1);
                    var end = new Date(today.getFullYear(), today.getMonth() + 1, 0);
                    return { start: start, end: end };
                }
            },
            lastMonth: {
                label: 'Last month',
                getRange: function() {
                    var today = new Date();
                    var start = new Date(today.getFullYear(), today.getMonth() - 1, 1);
                    var end = new Date(today.getFullYear(), today.getMonth(), 0);
                    return { start: start, end: end };
                }
            },
            thisQuarter: {
                label: 'This quarter',
                getRange: function() {
                    var today = new Date();
                    var quarter = Math.floor(today.getMonth() / 3);
                    var start = new Date(today.getFullYear(), quarter * 3, 1);
                    var end = new Date(today.getFullYear(), quarter * 3 + 3, 0);
                    return { start: start, end: end };
                }
            },
            thisYear: {
                label: 'This year',
                getRange: function() {
                    var today = new Date();
                    var start = new Date(today.getFullYear(), 0, 1);
                    var end = new Date(today.getFullYear(), 11, 31);
                    return { start: start, end: end };
                }
            },
            custom: {
                label: 'Custom range',
                getRange: function() {
                    return null;
                }
            }
        },

        /** Month names for different locales */
        monthNames: {
            'en-US': ['January', 'February', 'March', 'April', 'May', 'June',
                      'July', 'August', 'September', 'October', 'November', 'December'],
            'en-GB': ['January', 'February', 'March', 'April', 'May', 'June',
                      'July', 'August', 'September', 'October', 'November', 'December']
        },

        /** Short month names */
        monthNamesShort: {
            'en-US': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                      'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
        },

        /** Day names for different locales */
        dayNames: {
            'en-US': ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
        },

        /** Short day names */
        dayNamesShort: {
            'en-US': ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']
        },

        /**
         * Initialize all date pickers on the page
         */
        init: function() {
            var self = this;
            var elements = document.querySelectorAll('[data-rsl-date-picker]');

            elements.forEach(function(element) {
                if (!self.instances.has(element)) {
                    self.create(element);
                }
            });

            return this;
        },

        /**
         * Create a single date picker instance
         * @param {HTMLElement} element - Container element
         * @param {Object} options - Configuration options
         * @returns {Object} Instance object
         */
        create: function(element, options) {
            var self = this;

            if (this.instances.has(element)) {
                return this.instances.get(element);
            }

            // Parse options from data attributes and merge with defaults
            var config = this._parseConfig(element, options);

            // Create instance object
            var instance = {
                element: element,
                config: config,
                isOpen: false,
                viewDate: new Date(),
                selectedDates: [],
                startDate: null,
                endDate: null,
                focusedDate: null,
                hoverDate: null,
                currentView: 'days', // 'days', 'months', 'years'
                triggerElement: null,
                popover: null,
                liveRegion: null,
                focusableElements: [],
                _announceTimeout: null
            };

            // Build the DOM structure
            this._buildDOM(instance);

            // Attach event listeners
            this._attachEvents(instance);

            // Set initial value if provided
            if (config.value) {
                this._setInitialValue(instance, config.value);
            }

            // Store instance - store by both original element AND container for easy lookup
            this.instances.set(element, instance);
            if (instance.originalInput && instance.element !== element) {
                // Also store by container element for lookups
                this.instances.set(instance.element, instance);
            }

            // If inline mode, render immediately
            if (config.inline) {
                this._renderCalendar(instance);
            }

            return instance;
        },

        /**
         * Parse configuration from element data attributes
         */
        _parseConfig: function(element, options) {
            var config = Object.assign({}, this.defaults, options || {});

            // Parse data attributes
            var dataset = element.dataset;

            if (dataset.mode) config.mode = dataset.mode;
            if (dataset.format) config.format = dataset.format;
            if (dataset.locale) config.locale = dataset.locale;
            if (dataset.minDate) config.minDate = this._parseDate(dataset.minDate);
            if (dataset.maxDate) config.maxDate = this._parseDate(dataset.maxDate);
            if (dataset.disabledDates) config.disabledDates = dataset.disabledDates.split(',').map(function(d) { return d.trim(); });
            if (dataset.disabledDays) config.disabledDays = dataset.disabledDays.split(',').map(function(d) { return parseInt(d.trim(), 10); });
            // Support both data-first-day and data-first-day-of-week
            if (dataset.firstDay) config.firstDayOfWeek = parseInt(dataset.firstDay, 10);
            if (dataset.firstDayOfWeek) config.firstDayOfWeek = parseInt(dataset.firstDayOfWeek, 10);
            if (dataset.showDualCalendar !== undefined) config.showDualCalendar = dataset.showDualCalendar === 'true';
            // Support data-show-presets="true" and data-presets="today,last7,..."
            if (dataset.showPresets !== undefined) config.showPresets = dataset.showPresets === 'true';
            if (dataset.presets) {
                config.showPresets = true;
                config.presets = dataset.presets.split(',').map(function(p) { return p.trim(); });
            }
            if (dataset.inline !== undefined) config.inline = dataset.inline === 'true';
            if (dataset.closeOnSelect !== undefined) config.closeOnSelect = dataset.closeOnSelect === 'true';
            if (dataset.autoClose !== undefined) config.closeOnSelect = dataset.autoClose === 'true';
            if (dataset.placeholder) config.placeholder = dataset.placeholder;
            if (dataset.placeholderStart) config.placeholderStart = dataset.placeholderStart;
            if (dataset.placeholderEnd) config.placeholderEnd = dataset.placeholderEnd;
            if (dataset.required !== undefined) config.required = dataset.required === 'true';
            if (dataset.disabled !== undefined) config.disabled = dataset.disabled === 'true';
            if (dataset.value) config.value = dataset.value;
            if (dataset.linkedTo) config.linkedTo = dataset.linkedTo;
            // Support both data-months and data-number-of-months
            if (dataset.months) config.numberOfMonths = parseInt(dataset.months, 10);
            if (dataset.numberOfMonths) config.numberOfMonths = parseInt(dataset.numberOfMonths, 10);
            if (dataset.ariaLabel) config.ariaLabel = dataset.ariaLabel;

            // FilterBus integration
            if (dataset.filterbusPublish) config.filterBusPublish = dataset.filterbusPublish;

            // Clearable option - show clear button in input
            if (dataset.clearable !== undefined) config.clearable = dataset.clearable === 'true';

            // Auto-enable dual calendar for range mode on larger screens
            if (config.mode === 'range' && !dataset.showDualCalendar && window.innerWidth >= 768) {
                config.showDualCalendar = true;
            }

            return config;
        },

        /**
         * Build the DOM structure for the date picker
         */
        _buildDOM: function(instance) {
            var self = this;
            var element = instance.element;
            var config = instance.config;

            // Check if element is an input - if so, we need to wrap it
            var container;
            var originalInput = null;

            if (element.tagName.toLowerCase() === 'input') {
                // Store reference to original input
                originalInput = element;

                // Create a container div to wrap everything
                container = document.createElement('div');
                container.className = 'rsl-date-picker';
                if (config.showDualCalendar) {
                    container.setAttribute('data-show-dual-calendar', 'true');
                }

                // Insert container before the original input
                originalInput.parentNode.insertBefore(container, originalInput);

                // Hide the original input (we'll sync values to it)
                originalInput.style.display = 'none';
                originalInput.setAttribute('data-rsl-date-picker-original', '');

                // Update instance element to the container
                instance.element = container;
                instance.originalInput = originalInput;
            } else {
                container = element;
                // Add base class
                container.classList.add('rsl-date-picker');
                if (config.showDualCalendar) {
                    container.setAttribute('data-show-dual-calendar', 'true');
                }
            }

            // Create wrapper
            var wrapper = document.createElement('div');
            wrapper.className = 'rsl-date-picker-wrapper';

            // Create input field(s) based on mode
            if (config.mode === 'range') {
                // Start date field
                var startField = this._createInputField(instance, 'start', config.placeholderStart, config.ariaLabelStart);
                wrapper.appendChild(startField);

                // Separator
                var separator = document.createElement('span');
                separator.className = 'rsl-date-picker-separator';
                separator.setAttribute('aria-hidden', 'true');
                separator.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14M12 5l7 7-7 7"/></svg>';
                wrapper.appendChild(separator);

                // End date field
                var endField = this._createInputField(instance, 'end', config.placeholderEnd, config.ariaLabelEnd);
                wrapper.appendChild(endField);

                instance.startInput = startField.querySelector('input');
                instance.endInput = endField.querySelector('input');
            } else {
                // Single input field
                var field = this._createInputField(instance, 'single', config.placeholder, config.ariaLabel);
                wrapper.appendChild(field);
                instance.input = field.querySelector('input');
            }

            container.appendChild(wrapper);

            // Create popover
            var popover = this._createPopover(instance);
            container.appendChild(popover);
            instance.popover = popover;

            // Create live region for screen reader announcements
            var liveRegion = document.createElement('div');
            liveRegion.className = 'rsl-date-picker-sr-only';
            liveRegion.setAttribute('role', 'status');
            liveRegion.setAttribute('aria-live', 'polite');
            liveRegion.setAttribute('aria-atomic', 'true');
            container.appendChild(liveRegion);
            instance.liveRegion = liveRegion;

            // Create error container
            var errorContainer = document.createElement('div');
            errorContainer.className = 'rsl-date-picker-error';
            errorContainer.setAttribute('role', 'alert');
            errorContainer.setAttribute('aria-live', 'assertive');
            container.appendChild(errorContainer);
            instance.errorContainer = errorContainer;

            // Add format hint
            var hint = document.createElement('div');
            hint.className = 'rsl-date-picker-hint';
            hint.id = this._generateId('hint');
            hint.textContent = 'Format: ' + this._getFormatHint(config.format);
            container.appendChild(hint);
            instance.hintId = hint.id;

            // Update aria-describedby for inputs
            if (instance.input) {
                instance.input.setAttribute('aria-describedby', hint.id);
            }
            if (instance.startInput) {
                instance.startInput.setAttribute('aria-describedby', hint.id);
            }
            if (instance.endInput) {
                instance.endInput.setAttribute('aria-describedby', hint.id);
            }
        },

        /**
         * Create an input field with trigger button
         */
        _createInputField: function(instance, type, placeholder, ariaLabel) {
            var self = this;
            var config = instance.config;

            var field = document.createElement('div');
            field.className = 'rsl-date-picker-field';

            var inputGroup = document.createElement('div');
            inputGroup.className = 'rsl-date-picker-input-group';

            // Input
            var input = document.createElement('input');
            input.type = 'text';
            input.className = 'rsl-date-picker-input';
            input.placeholder = placeholder;
            input.setAttribute('autocomplete', 'off');
            input.setAttribute('inputmode', 'none');
            input.setAttribute('aria-label', ariaLabel);
            input.setAttribute('data-rsl-date-' + type, '');

            if (config.required) {
                input.setAttribute('required', '');
                input.setAttribute('aria-required', 'true');
            }
            if (config.disabled) {
                input.disabled = true;
            }
            if (config.readOnly) {
                input.readOnly = true;
            }

            inputGroup.appendChild(input);

            // Trigger button
            var trigger = document.createElement('button');
            trigger.type = 'button';
            trigger.className = 'rsl-date-picker-trigger';
            trigger.setAttribute('aria-label', 'Open calendar');
            trigger.setAttribute('aria-expanded', 'false');
            trigger.setAttribute('aria-haspopup', 'dialog');
            trigger.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg>';

            if (config.disabled) {
                trigger.disabled = true;
            }

            inputGroup.appendChild(trigger);

            // Clear button (shown when clearable and has value)
            if (config.clearable) {
                var clearBtn = document.createElement('button');
                clearBtn.type = 'button';
                clearBtn.className = 'rsl-date-picker-clear';
                clearBtn.setAttribute('aria-label', 'Clear date');
                clearBtn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
                clearBtn.style.display = 'none'; // Hidden until there's a value

                if (config.disabled) {
                    clearBtn.disabled = true;
                }

                inputGroup.appendChild(clearBtn);

                // Store reference for later
                if (type === 'start' || type === 'single') {
                    instance.clearButton = clearBtn;
                }
            }

            // Store trigger reference
            if (type === 'start' || type === 'single') {
                instance.triggerElement = trigger;
            }

            field.appendChild(inputGroup);

            return field;
        },

        /**
         * Create the calendar popover
         */
        _createPopover: function(instance) {
            var self = this;
            var config = instance.config;

            var popover = document.createElement('div');
            popover.className = 'rsl-date-picker-popover';
            popover.setAttribute('role', 'dialog');
            popover.setAttribute('aria-modal', 'true');
            popover.setAttribute('aria-label', 'Choose ' + (config.mode === 'range' ? 'date range' : 'date'));
            popover.id = this._generateId('popover');

            // Store popover ID for aria-controls
            if (instance.triggerElement) {
                instance.triggerElement.setAttribute('aria-controls', popover.id);
            }

            // Close button for keyboard accessibility
            var closeBtn = document.createElement('button');
            closeBtn.type = 'button';
            closeBtn.className = 'rsl-date-picker-close';
            closeBtn.setAttribute('aria-label', 'Close calendar, press Enter to close');
            closeBtn.setAttribute('data-action', 'close');
            closeBtn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
            popover.appendChild(closeBtn);

            // Presets panel (if enabled)
            if (config.showPresets && config.presets.length > 0) {
                var presetsPanel = this._createPresetsPanel(instance);
                popover.appendChild(presetsPanel);
            }

            // Calendar panel
            var calendarPanel = document.createElement('div');
            calendarPanel.className = 'rsl-date-picker-calendar-panel';

            // Calendar container
            var calendarsContainer = document.createElement('div');
            calendarsContainer.className = 'rsl-date-picker-calendars';

            // Create calendar(s)
            var numCalendars = config.showDualCalendar ? 2 : config.numberOfMonths;
            for (var i = 0; i < numCalendars; i++) {
                var calendar = this._createCalendar(instance, i);
                calendarsContainer.appendChild(calendar);
            }

            calendarPanel.appendChild(calendarsContainer);
            popover.appendChild(calendarPanel);

            // Footer with summary and actions (for range mode)
            if (config.mode === 'range' || !config.autoApply) {
                var footer = this._createFooter(instance);
                popover.appendChild(footer);
            }

            return popover;
        },

        /**
         * Create the presets panel
         */
        _createPresetsPanel: function(instance) {
            var self = this;
            var config = instance.config;

            var panel = document.createElement('div');
            panel.className = 'rsl-date-picker-presets';
            panel.setAttribute('role', 'group');
            panel.setAttribute('aria-label', 'Quick selection presets');

            var title = document.createElement('div');
            title.className = 'rsl-date-picker-presets-title';
            title.textContent = 'Quick Select';
            panel.appendChild(title);

            config.presets.forEach(function(presetKey) {
                var presetDef = self.presetDefinitions[presetKey];
                if (!presetDef) return;

                var btn = document.createElement('button');
                btn.type = 'button';
                btn.className = 'rsl-date-picker-preset';
                btn.setAttribute('data-preset', presetKey);
                btn.setAttribute('aria-pressed', 'false');
                btn.textContent = presetDef.label;

                panel.appendChild(btn);
            });

            return panel;
        },

        /**
         * Create a single calendar
         */
        _createCalendar: function(instance, monthOffset) {
            var config = instance.config;

            var calendar = document.createElement('div');
            calendar.className = 'rsl-date-picker-calendar';
            calendar.setAttribute('data-month-offset', monthOffset);

            // Header with navigation
            var header = document.createElement('div');
            header.className = 'rsl-date-picker-header';

            // Previous navigation (only on first calendar)
            var navPrev = document.createElement('div');
            navPrev.className = 'rsl-date-picker-nav';

            if (monthOffset === 0) {
                var prevYearBtn = document.createElement('button');
                prevYearBtn.type = 'button';
                prevYearBtn.className = 'rsl-date-picker-nav-btn';
                prevYearBtn.setAttribute('aria-label', 'Previous year');
                prevYearBtn.setAttribute('data-nav', 'prev-year');
                prevYearBtn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="11 17 6 12 11 7"></polyline><polyline points="18 17 13 12 18 7"></polyline></svg>';
                navPrev.appendChild(prevYearBtn);

                var prevMonthBtn = document.createElement('button');
                prevMonthBtn.type = 'button';
                prevMonthBtn.className = 'rsl-date-picker-nav-btn';
                prevMonthBtn.setAttribute('aria-label', 'Previous month');
                prevMonthBtn.setAttribute('data-nav', 'prev-month');
                prevMonthBtn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"></polyline></svg>';
                navPrev.appendChild(prevMonthBtn);
            }

            header.appendChild(navPrev);

            // Month/Year title
            var titleContainer = document.createElement('div');
            titleContainer.className = 'rsl-date-picker-title';

            var monthYearBtn = document.createElement('button');
            monthYearBtn.type = 'button';
            monthYearBtn.className = 'rsl-date-picker-month-year';
            monthYearBtn.setAttribute('aria-label', 'Select month and year');
            monthYearBtn.setAttribute('data-month-offset', monthOffset);

            titleContainer.appendChild(monthYearBtn);
            header.appendChild(titleContainer);

            // Next navigation (only on last calendar)
            var navNext = document.createElement('div');
            navNext.className = 'rsl-date-picker-nav';

            var numCalendars = config.showDualCalendar ? 2 : config.numberOfMonths;
            if (monthOffset === numCalendars - 1) {
                var nextMonthBtn = document.createElement('button');
                nextMonthBtn.type = 'button';
                nextMonthBtn.className = 'rsl-date-picker-nav-btn';
                nextMonthBtn.setAttribute('aria-label', 'Next month');
                nextMonthBtn.setAttribute('data-nav', 'next-month');
                nextMonthBtn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"></polyline></svg>';
                navNext.appendChild(nextMonthBtn);

                var nextYearBtn = document.createElement('button');
                nextYearBtn.type = 'button';
                nextYearBtn.className = 'rsl-date-picker-nav-btn';
                nextYearBtn.setAttribute('aria-label', 'Next year');
                nextYearBtn.setAttribute('data-nav', 'next-year');
                nextYearBtn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="13 17 18 12 13 7"></polyline><polyline points="6 17 11 12 6 7"></polyline></svg>';
                navNext.appendChild(nextYearBtn);
            }

            header.appendChild(navNext);
            calendar.appendChild(header);

            // Calendar grid
            var grid = document.createElement('table');
            grid.className = 'rsl-date-picker-grid';
            grid.setAttribute('role', 'grid');
            grid.id = this._generateId('grid');

            // Weekday headers
            var thead = document.createElement('thead');
            var weekdayRow = document.createElement('tr');
            weekdayRow.className = 'rsl-date-picker-weekdays';

            var dayNames = this.dayNamesShort[config.locale] || this.dayNamesShort['en-US'];
            var fullDayNames = this.dayNames[config.locale] || this.dayNames['en-US'];

            for (var d = 0; d < 7; d++) {
                var dayIndex = (d + config.firstDayOfWeek) % 7;
                var th = document.createElement('th');
                th.className = 'rsl-date-picker-weekday';
                th.setAttribute('scope', 'col');
                th.setAttribute('abbr', fullDayNames[dayIndex]);
                th.textContent = dayNames[dayIndex];
                weekdayRow.appendChild(th);
            }

            thead.appendChild(weekdayRow);
            grid.appendChild(thead);

            // Calendar body (will be populated by _renderCalendar)
            var tbody = document.createElement('tbody');
            tbody.className = 'rsl-date-picker-days';
            grid.appendChild(tbody);

            calendar.appendChild(grid);

            return calendar;
        },

        /**
         * Create the footer with summary and action buttons
         */
        _createFooter: function(instance) {
            var config = instance.config;

            var footer = document.createElement('div');
            footer.className = 'rsl-date-picker-footer';

            // Summary
            var summary = document.createElement('div');
            summary.className = 'rsl-date-picker-summary';
            summary.innerHTML = '<span class="rsl-date-picker-summary-range">No dates selected</span>';
            footer.appendChild(summary);
            instance.summaryElement = summary;

            // Actions
            var actions = document.createElement('div');
            actions.className = 'rsl-date-picker-actions';

            var clearBtn = document.createElement('button');
            clearBtn.type = 'button';
            clearBtn.className = 'rsl-date-picker-btn';
            clearBtn.textContent = 'Clear';
            clearBtn.setAttribute('data-action', 'clear');
            actions.appendChild(clearBtn);

            if (!config.autoApply) {
                var applyBtn = document.createElement('button');
                applyBtn.type = 'button';
                applyBtn.className = 'rsl-date-picker-btn rsl-date-picker-btn-primary';
                applyBtn.textContent = 'Apply';
                applyBtn.setAttribute('data-action', 'apply');
                actions.appendChild(applyBtn);
            }

            footer.appendChild(actions);

            return footer;
        },

        /**
         * Attach event listeners
         */
        _attachEvents: function(instance) {
            var self = this;
            var element = instance.element;
            var config = instance.config;

            // Trigger button click
            element.querySelectorAll('.rsl-date-picker-trigger').forEach(function(trigger) {
                trigger.addEventListener('mousedown', function(e) {
                    e.stopPropagation();
                });
                trigger.addEventListener('click', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    self._togglePopover(instance);
                });
            });

            // Clear button click
            element.querySelectorAll('.rsl-date-picker-clear').forEach(function(clearBtn) {
                clearBtn.addEventListener('click', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    self.clear(instance);
                });
            });

            // Input focus/click
            element.querySelectorAll('.rsl-date-picker-input').forEach(function(input) {
                // Stop mousedown from bubbling to document handler
                input.addEventListener('mousedown', function(e) {
                    e.stopPropagation();
                });

                input.addEventListener('click', function(e) {
                    e.stopPropagation(); // Prevent outside click handler from closing
                    if (!config.inline) {
                        self.open(instance);
                    }
                });

                input.addEventListener('keydown', function(e) {
                    if (e.key === 'Enter' || e.key === ' ') {
                        e.preventDefault();
                        self.open(instance);
                    }
                    if (e.key === 'Escape' && instance.isOpen) {
                        e.preventDefault();
                        self.close(instance);
                    }
                });

                // Manual date entry
                input.addEventListener('blur', function(e) {
                    self._handleManualInput(instance, input);
                });
            });

            // Popover events
            var popover = instance.popover;

            // Navigation buttons
            popover.addEventListener('click', function(e) {
                e.stopPropagation(); // Prevent outside click handler from closing
                var target = e.target.closest('button');
                if (!target) return;

                var nav = target.getAttribute('data-nav');
                if (nav) {
                    e.preventDefault();
                    self._handleNavigation(instance, nav);
                    return;
                }

                var preset = target.getAttribute('data-preset');
                if (preset) {
                    e.preventDefault();
                    self._handlePresetSelection(instance, preset);
                    return;
                }

                var action = target.getAttribute('data-action');
                if (action) {
                    e.preventDefault();
                    if (action === 'clear') {
                        self.clear(instance);
                    } else if (action === 'apply') {
                        self._applySelection(instance);
                    } else if (action === 'close') {
                        self.close(instance);
                    }
                    return;
                }

                // Day button click
                if (target.classList.contains('rsl-date-picker-day-btn')) {
                    e.preventDefault();
                    var dateStr = target.getAttribute('data-date');
                    if (dateStr && !target.hasAttribute('aria-disabled')) {
                        self._handleDateSelection(instance, self._parseISOLocal(dateStr));
                    }
                }

                // Month/year button
                if (target.classList.contains('rsl-date-picker-month-year')) {
                    e.preventDefault();
                    // TODO: Implement month/year picker
                }
            });

            // Keyboard navigation in calendar
            popover.addEventListener('keydown', function(e) {
                self._handleKeydown(instance, e);
            });

            // Mouse hover for range preview
            if (config.mode === 'range') {
                popover.addEventListener('mouseover', function(e) {
                    var dayBtn = e.target.closest('.rsl-date-picker-day-btn');
                    if (dayBtn && !dayBtn.hasAttribute('aria-disabled')) {
                        var dateStr = dayBtn.getAttribute('data-date');
                        if (dateStr) {
                            instance.hoverDate = self._parseISOLocal(dateStr);
                            self._updateRangeHighlight(instance);
                        }
                    }
                });

                popover.addEventListener('mouseleave', function(e) {
                    instance.hoverDate = null;
                    self._updateRangeHighlight(instance);
                });
            }

            // Close on outside click
            // Use a flag to prevent immediate reopening when focus returns to input
            if (!config.inline) {
                instance._justClosed = false;

                document.addEventListener('click', function(e) {
                    // Skip if we just closed (prevents race condition when focus returns to input)
                    if (instance._justClosed) {
                        instance._justClosed = false;
                        return;
                    }

                    if (instance.isOpen && !element.contains(e.target)) {
                        self.close(instance);
                    }
                });

                // Close on escape
                document.addEventListener('keydown', function(e) {
                    if (e.key === 'Escape' && instance.isOpen) {
                        self.close(instance);
                    }
                });
            }

            // Window resize
            window.addEventListener('resize', function() {
                if (instance.isOpen && !config.inline) {
                    self._positionPopover(instance);
                }
            });
        },

        /**
         * Handle keyboard navigation
         */
        _handleKeydown: function(instance, e) {
            var self = this;
            var config = instance.config;
            var focusedDate = instance.focusedDate || instance.viewDate;
            var newDate = new Date(focusedDate);
            var handled = false;

            switch (e.key) {
                case 'ArrowLeft':
                    newDate.setDate(newDate.getDate() - 1);
                    handled = true;
                    break;
                case 'ArrowRight':
                    newDate.setDate(newDate.getDate() + 1);
                    handled = true;
                    break;
                case 'ArrowUp':
                    newDate.setDate(newDate.getDate() - 7);
                    handled = true;
                    break;
                case 'ArrowDown':
                    newDate.setDate(newDate.getDate() + 7);
                    handled = true;
                    break;
                case 'PageUp':
                    if (e.shiftKey) {
                        newDate.setFullYear(newDate.getFullYear() - 1);
                    } else {
                        newDate.setMonth(newDate.getMonth() - 1);
                    }
                    handled = true;
                    break;
                case 'PageDown':
                    if (e.shiftKey) {
                        newDate.setFullYear(newDate.getFullYear() + 1);
                    } else {
                        newDate.setMonth(newDate.getMonth() + 1);
                    }
                    handled = true;
                    break;
                case 'Home':
                    // Go to start of week
                    newDate.setDate(newDate.getDate() - newDate.getDay() + config.firstDayOfWeek);
                    handled = true;
                    break;
                case 'End':
                    // Go to end of week
                    newDate.setDate(newDate.getDate() + (6 - newDate.getDay() + config.firstDayOfWeek) % 7);
                    handled = true;
                    break;
                case 'Enter':
                case ' ':
                    var activeElement = document.activeElement;
                    if (activeElement && activeElement.classList.contains('rsl-date-picker-day-btn')) {
                        e.preventDefault();
                        var dateStr = activeElement.getAttribute('data-date');
                        if (dateStr && !activeElement.hasAttribute('aria-disabled')) {
                            this._handleDateSelection(instance, this._parseISOLocal(dateStr));
                        }
                        return;
                    }
                    break;
                case 'Tab':
                    // Handle focus trap
                    this._handleTabKey(instance, e);
                    return;
                case 'Escape':
                    e.preventDefault();
                    this.close(instance);
                    return;
            }

            if (handled) {
                e.preventDefault();

                // Check boundaries
                if (config.minDate && newDate < config.minDate) {
                    newDate = new Date(config.minDate);
                }
                if (config.maxDate && newDate > config.maxDate) {
                    newDate = new Date(config.maxDate);
                }

                // Skip disabled dates
                while (this._isDateDisabled(instance, newDate)) {
                    var direction = e.key.includes('Left') || e.key.includes('Up') || e.key === 'PageUp' ? -1 : 1;
                    newDate.setDate(newDate.getDate() + direction);

                    // Prevent infinite loop
                    if ((config.minDate && newDate < config.minDate) ||
                        (config.maxDate && newDate > config.maxDate)) {
                        return;
                    }
                }

                instance.focusedDate = newDate;

                // Update view if needed
                if (newDate.getMonth() !== instance.viewDate.getMonth() ||
                    newDate.getFullYear() !== instance.viewDate.getFullYear()) {
                    instance.viewDate = new Date(newDate.getFullYear(), newDate.getMonth(), 1);
                    this._renderCalendar(instance);
                }

                // Focus the new date
                this._focusDate(instance, newDate);

                // Announce navigation
                this._announce(instance, this._formatDateLong(newDate, config.locale));
            }
        },

        /**
         * Handle Tab key for focus trapping
         */
        _handleTabKey: function(instance, e) {
            var popover = instance.popover;
            var focusableSelectors = 'button:not([disabled]):not([tabindex="-1"]), [tabindex="0"]';
            var focusables = Array.from(popover.querySelectorAll(focusableSelectors));

            if (focusables.length === 0) return;

            var firstFocusable = focusables[0];
            var lastFocusable = focusables[focusables.length - 1];

            if (e.shiftKey) {
                if (document.activeElement === firstFocusable) {
                    e.preventDefault();
                    lastFocusable.focus();
                }
            } else {
                if (document.activeElement === lastFocusable) {
                    e.preventDefault();
                    firstFocusable.focus();
                }
            }
        },

        /**
         * Handle navigation button clicks
         */
        _handleNavigation: function(instance, direction) {
            var viewDate = instance.viewDate;

            switch (direction) {
                case 'prev-month':
                    viewDate.setMonth(viewDate.getMonth() - 1);
                    break;
                case 'next-month':
                    viewDate.setMonth(viewDate.getMonth() + 1);
                    break;
                case 'prev-year':
                    viewDate.setFullYear(viewDate.getFullYear() - 1);
                    break;
                case 'next-year':
                    viewDate.setFullYear(viewDate.getFullYear() + 1);
                    break;
            }

            this._renderCalendar(instance);

            // Announce month change
            var monthNames = this.monthNames[instance.config.locale] || this.monthNames['en-US'];
            this._announce(instance, 'Now showing ' + monthNames[viewDate.getMonth()] + ' ' + viewDate.getFullYear());
        },

        /**
         * Handle preset selection
         */
        _handlePresetSelection: function(instance, presetKey) {
            var presetDef = this.presetDefinitions[presetKey];
            if (!presetDef) return;

            var range = presetDef.getRange();
            if (range && range.start && range.end) {
                instance.startDate = range.start;
                instance.endDate = range.end;
                instance.viewDate = new Date(range.start);

                this._renderCalendar(instance);
                this._updateInputValues(instance);
                this._updateSummary(instance);
                this._updatePresetButtons(instance, presetKey);

                // Announce selection
                var announcement = presetDef.label + ' selected. ' +
                    this._formatDateLong(range.start, instance.config.locale) + ' to ' +
                    this._formatDateLong(range.end, instance.config.locale);
                this._announce(instance, announcement);

                if (instance.config.autoApply) {
                    this._applySelection(instance);
                }
            }
        },

        /**
         * Handle date selection
         */
        _handleDateSelection: function(instance, date) {
            var self = this;
            var config = instance.config;

            if (config.mode === 'single') {
                instance.selectedDates = [date];
                this._updateInputValues(instance);
                this._renderCalendar(instance);

                // Announce selection
                this._announce(instance, 'Selected ' + this._formatDateLong(date, config.locale));

                // Publish to FilterBus for single mode
                this.publishToFilterBus(instance);

                if (config.closeOnSelect && !config.inline) {
                    this.close(instance);
                }
            } else if (config.mode === 'range') {
                if (!instance.startDate || (instance.startDate && instance.endDate)) {
                    // Start new selection
                    instance.startDate = date;
                    instance.endDate = null;
                    this._announce(instance, 'Start date selected: ' + this._formatDateLong(date, config.locale) + '. Now choose an end date.');
                } else {
                    // Complete selection
                    if (date < instance.startDate) {
                        instance.endDate = instance.startDate;
                        instance.startDate = date;
                    } else {
                        instance.endDate = date;
                    }

                    var days = Math.ceil((instance.endDate - instance.startDate) / (1000 * 60 * 60 * 24)) + 1;
                    this._announce(instance, 'End date selected: ' + this._formatDateLong(instance.endDate, config.locale) +
                        '. Range is ' + this._formatDateShort(instance.startDate, config.locale) + ' to ' +
                        this._formatDateShort(instance.endDate, config.locale) + ', ' + days + ' days.');

                    if (config.autoApply) {
                        this._applySelection(instance);
                        if (config.closeOnSelect && !config.inline) {
                            this.close(instance);
                        }
                    }
                }

                this._updateInputValues(instance);
                this._updateSummary(instance);
                this._renderCalendar(instance);
            } else if (config.mode === 'multiple') {
                var dateStr = this._formatDateISO(date);
                var index = instance.selectedDates.findIndex(function(d) {
                    return self._formatDateISO(d) === dateStr;
                });

                if (index > -1) {
                    instance.selectedDates.splice(index, 1);
                    this._announce(instance, this._formatDateLong(date, config.locale) + ' deselected.');
                } else {
                    instance.selectedDates.push(date);
                    this._announce(instance, this._formatDateLong(date, config.locale) + ' selected. ' +
                        instance.selectedDates.length + ' dates selected.');
                }

                this._updateInputValues(instance);
                this._updateSummary(instance);
                this._renderCalendar(instance);

                // Publish to FilterBus for multiple mode
                this.publishToFilterBus(instance);
            }

            // Clear any preset selection
            this._updatePresetButtons(instance, null);
        },

        /**
         * Handle manual input
         */
        _handleManualInput: function(instance, input) {
            // Skip validation if we just programmatically set the value
            if (instance._skipBlurValidation) {
                instance._skipBlurValidation = false;
                return;
            }

            var value = input.value.trim();
            if (!value) return;

            var self = this;
            var config = instance.config;

            // For multiple mode, the input contains comma-separated dates
            if (config.mode === 'multiple') {
                var dateStrings = value.split(',').map(function(s) { return s.trim(); });
                var validDates = [];
                var hasInvalid = false;

                dateStrings.forEach(function(dateStr) {
                    if (dateStr) {
                        var date = self._parseDate(dateStr);
                        if (date && !isNaN(date.getTime())) {
                            validDates.push(date);
                        } else {
                            hasInvalid = true;
                        }
                    }
                });

                if (validDates.length > 0 && !hasInvalid) {
                    instance.selectedDates = validDates;
                    instance.viewDate = new Date(validDates[0]);
                    this._renderCalendar(instance);
                    this._updateInputValues(instance);
                    this._clearError(instance);
                } else if (hasInvalid) {
                    this._showError(instance, 'Invalid date format. Please use ' + this._getFormatHint(config.format));
                }
                return;
            }

            var date = this._parseDate(value);
            if (date && !isNaN(date.getTime())) {
                var isStart = input.hasAttribute('data-rsl-date-start') || input.hasAttribute('data-rsl-date-single');

                if (config.mode === 'range') {
                    if (isStart) {
                        instance.startDate = date;
                    } else {
                        instance.endDate = date;
                    }
                } else {
                    instance.selectedDates = [date];
                }

                instance.viewDate = new Date(date);
                this._renderCalendar(instance);
                this._updateInputValues(instance);
                this._clearError(instance);
            } else {
                this._showError(instance, 'Invalid date format. Please use ' + this._getFormatHint(config.format));
            }
        },

        /**
         * Render the calendar grid
         */
        _renderCalendar: function(instance) {
            var self = this;
            var config = instance.config;
            var viewDate = instance.viewDate;

            var calendars = instance.popover.querySelectorAll('.rsl-date-picker-calendar');

            calendars.forEach(function(calendar, index) {
                var monthOffset = parseInt(calendar.getAttribute('data-month-offset'), 10) || 0;
                var displayDate = new Date(viewDate.getFullYear(), viewDate.getMonth() + monthOffset, 1);

                // Update month/year title
                var monthYearBtn = calendar.querySelector('.rsl-date-picker-month-year');
                var monthNames = self.monthNames[config.locale] || self.monthNames['en-US'];
                monthYearBtn.textContent = monthNames[displayDate.getMonth()] + ' ' + displayDate.getFullYear();

                // Update grid aria-label
                var grid = calendar.querySelector('.rsl-date-picker-grid');
                grid.setAttribute('aria-label', monthNames[displayDate.getMonth()] + ' ' + displayDate.getFullYear());

                // Render days
                var tbody = calendar.querySelector('.rsl-date-picker-days');
                tbody.innerHTML = '';

                var firstDay = new Date(displayDate.getFullYear(), displayDate.getMonth(), 1);
                var lastDay = new Date(displayDate.getFullYear(), displayDate.getMonth() + 1, 0);

                // Adjust for first day of week
                var startOffset = (firstDay.getDay() - config.firstDayOfWeek + 7) % 7;
                var startDate = new Date(firstDay);
                startDate.setDate(startDate.getDate() - startOffset);

                var today = new Date();
                today.setHours(0, 0, 0, 0);

                var currentDate = new Date(startDate);
                var focusedDateStr = instance.focusedDate ? self._formatDateISO(instance.focusedDate) : null;

                for (var week = 0; week < 6; week++) {
                    var tr = document.createElement('tr');
                    tr.className = 'rsl-date-picker-week';
                    tr.setAttribute('role', 'row');

                    for (var day = 0; day < 7; day++) {
                        var td = document.createElement('td');
                        td.className = 'rsl-date-picker-day';
                        td.setAttribute('role', 'gridcell');

                        var btn = document.createElement('button');
                        btn.type = 'button';
                        btn.className = 'rsl-date-picker-day-btn';
                        btn.textContent = currentDate.getDate();
                        btn.setAttribute('data-date', self._formatDateISO(currentDate));

                        var dateStr = self._formatDateISO(currentDate);
                        var isToday = dateStr === self._formatDateISO(today);
                        var isOtherMonth = currentDate.getMonth() !== displayDate.getMonth();
                        var isDisabled = self._isDateDisabled(instance, currentDate);
                        var isSelected = self._isDateSelected(instance, currentDate);
                        var isInRange = self._isDateInRange(instance, currentDate);
                        var isRangeStart = instance.startDate && dateStr === self._formatDateISO(instance.startDate);
                        var isRangeEnd = instance.endDate && dateStr === self._formatDateISO(instance.endDate);

                        // Accessible date label
                        var fullDayNames = self.dayNames[config.locale] || self.dayNames['en-US'];
                        var dayName = fullDayNames[currentDate.getDay()];
                        var ariaLabel = self._formatDateLong(currentDate, config.locale);
                        btn.setAttribute('aria-label', ariaLabel);

                        if (isToday) {
                            btn.setAttribute('aria-current', 'date');
                            ariaLabel += ', today';
                        }

                        if (isSelected || isRangeStart || isRangeEnd) {
                            btn.setAttribute('aria-selected', 'true');
                            if (isRangeStart) ariaLabel += ', range start';
                            if (isRangeEnd) ariaLabel += ', range end';
                        }

                        if (isDisabled) {
                            btn.setAttribute('aria-disabled', 'true');
                            btn.setAttribute('tabindex', '-1');
                            ariaLabel += ', unavailable';
                        } else {
                            // Roving tabindex
                            var shouldFocus = focusedDateStr === dateStr ||
                                (!focusedDateStr && isToday && !isOtherMonth) ||
                                (!focusedDateStr && !isToday && currentDate.getDate() === 1 && !isOtherMonth);
                            btn.setAttribute('tabindex', shouldFocus ? '0' : '-1');
                        }

                        if (isOtherMonth) {
                            td.classList.add('other-month');
                        }

                        if (isInRange && !isRangeStart && !isRangeEnd) {
                            td.classList.add('in-range');
                            ariaLabel += ', in selected range';
                        }

                        if (isRangeStart) {
                            td.classList.add('range-start');
                        }

                        if (isRangeEnd) {
                            td.classList.add('range-end');
                        }

                        btn.setAttribute('aria-label', ariaLabel);

                        td.appendChild(btn);
                        tr.appendChild(td);

                        currentDate.setDate(currentDate.getDate() + 1);
                    }

                    tbody.appendChild(tr);

                    // Stop if we've passed the last day of the month and completed the row
                    if (currentDate > lastDay && day === 6) {
                        break;
                    }
                }
            });

            // Update navigation button states
            this._updateNavigationButtons(instance);
        },

        /**
         * Update navigation button disabled states
         */
        _updateNavigationButtons: function(instance) {
            var config = instance.config;
            var viewDate = instance.viewDate;
            var popover = instance.popover;

            // Previous buttons
            if (config.minDate) {
                var minMonth = new Date(config.minDate.getFullYear(), config.minDate.getMonth(), 1);
                var canGoPrev = viewDate > minMonth;
                var canGoPrevYear = viewDate.getFullYear() > config.minDate.getFullYear();

                var prevMonthBtn = popover.querySelector('[data-nav="prev-month"]');
                var prevYearBtn = popover.querySelector('[data-nav="prev-year"]');

                if (prevMonthBtn) prevMonthBtn.disabled = !canGoPrev;
                if (prevYearBtn) prevYearBtn.disabled = !canGoPrevYear;
            }

            // Next buttons
            if (config.maxDate) {
                var numCalendars = config.showDualCalendar ? 2 : config.numberOfMonths;
                var lastVisibleMonth = new Date(viewDate.getFullYear(), viewDate.getMonth() + numCalendars - 1, 1);
                var maxMonth = new Date(config.maxDate.getFullYear(), config.maxDate.getMonth(), 1);
                var canGoNext = lastVisibleMonth < maxMonth;
                var canGoNextYear = viewDate.getFullYear() < config.maxDate.getFullYear();

                var nextMonthBtn = popover.querySelector('[data-nav="next-month"]');
                var nextYearBtn = popover.querySelector('[data-nav="next-year"]');

                if (nextMonthBtn) nextMonthBtn.disabled = !canGoNext;
                if (nextYearBtn) nextYearBtn.disabled = !canGoNextYear;
            }
        },

        /**
         * Check if a date is disabled
         */
        _isDateDisabled: function(instance, date) {
            var config = instance.config;

            // Normalize the date to midnight for comparison
            var normalizedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());

            // Check min/max (compare date portions only)
            if (config.minDate) {
                var minNormalized = new Date(config.minDate.getFullYear(), config.minDate.getMonth(), config.minDate.getDate());
                if (normalizedDate < minNormalized) return true;
            }
            if (config.maxDate) {
                var maxNormalized = new Date(config.maxDate.getFullYear(), config.maxDate.getMonth(), config.maxDate.getDate());
                if (normalizedDate > maxNormalized) return true;
            }

            // Check disabled days of week
            if (config.disabledDays.indexOf(date.getDay()) > -1) return true;

            // Check disabled dates
            var dateStr = this._formatDateISO(date);
            if (config.disabledDates.indexOf(dateStr) > -1) return true;

            return false;
        },

        /**
         * Check if a date is selected
         */
        _isDateSelected: function(instance, date) {
            var dateStr = this._formatDateISO(date);

            if (instance.config.mode === 'single' || instance.config.mode === 'multiple') {
                return instance.selectedDates.some(function(d) {
                    return window.RSL.DatePicker._formatDateISO(d) === dateStr;
                });
            }

            if (instance.config.mode === 'range') {
                if (instance.startDate && this._formatDateISO(instance.startDate) === dateStr) return true;
                if (instance.endDate && this._formatDateISO(instance.endDate) === dateStr) return true;
            }

            return false;
        },

        /**
         * Check if a date is in the selected range
         */
        _isDateInRange: function(instance, date) {
            if (instance.config.mode !== 'range') return false;

            var start = instance.startDate;
            var end = instance.endDate || instance.hoverDate;

            if (!start || !end) return false;

            // Normalize order
            if (end < start) {
                var temp = start;
                start = end;
                end = temp;
            }

            return date > start && date < end;
        },

        /**
         * Update range highlight on hover
         */
        _updateRangeHighlight: function(instance) {
            if (instance.config.mode !== 'range') return;
            if (!instance.startDate || instance.endDate) return; // Only highlight when selecting end date

            var self = this;
            var hoverDate = instance.hoverDate;
            var startDate = instance.startDate;

            // Get all day cells and update their classes without re-rendering
            var dayCells = instance.popover.querySelectorAll('.rsl-date-picker-day');
            dayCells.forEach(function(td) {
                var btn = td.querySelector('.rsl-date-picker-day-btn');
                if (!btn) return;

                var dateStr = btn.getAttribute('data-date');
                if (!dateStr) return;

                var date = self._parseISOLocal(dateStr);
                if (!date) return;

                // Remove existing range classes
                td.classList.remove('in-range', 'range-start', 'range-end');

                // Add range classes based on hover
                if (hoverDate && startDate) {
                    var rangeStart = startDate < hoverDate ? startDate : hoverDate;
                    var rangeEnd = startDate < hoverDate ? hoverDate : startDate;

                    var dateTime = date.getTime();
                    var startTime = startDate.getTime();
                    var hoverTime = hoverDate.getTime();
                    var rangeStartTime = rangeStart.getTime();
                    var rangeEndTime = rangeEnd.getTime();

                    if (dateTime === startTime) {
                        td.classList.add('range-start');
                    }
                    if (dateTime === hoverTime && hoverTime !== startTime) {
                        td.classList.add('range-end');
                    }
                    if (dateTime > rangeStartTime && dateTime < rangeEndTime) {
                        td.classList.add('in-range');
                    }
                }
            });
        },

        /**
         * Focus a specific date in the calendar
         */
        _focusDate: function(instance, date) {
            var dateStr = this._formatDateISO(date);
            var btn = instance.popover.querySelector('.rsl-date-picker-day-btn[data-date="' + dateStr + '"]');

            if (btn && !btn.hasAttribute('aria-disabled')) {
                // Update roving tabindex
                instance.popover.querySelectorAll('.rsl-date-picker-day-btn[tabindex="0"]').forEach(function(b) {
                    b.setAttribute('tabindex', '-1');
                });
                btn.setAttribute('tabindex', '0');
                btn.focus();
            }
        },

        /**
         * Update clear button visibility
         */
        _updateClearButton: function(instance) {
            if (!instance.clearButton) return;

            var hasValue = false;
            var config = instance.config;

            if (config.mode === 'single') {
                hasValue = instance.selectedDates.length > 0;
            } else if (config.mode === 'range') {
                hasValue = instance.startDate !== null;
            } else if (config.mode === 'multiple') {
                hasValue = instance.selectedDates.length > 0;
            }

            instance.clearButton.style.display = hasValue ? '' : 'none';
        },

        /**
         * Update input field values
         */
        _updateInputValues: function(instance) {
            var config = instance.config;

            // Set flag to skip blur validation since we're setting values programmatically
            instance._skipBlurValidation = true;

            if (config.mode === 'single') {
                if (instance.input && instance.selectedDates.length > 0) {
                    instance.input.value = this._formatDate(instance.selectedDates[0], config.format, config.locale);
                }
            } else if (config.mode === 'range') {
                if (instance.startInput && instance.startDate) {
                    instance.startInput.value = this._formatDate(instance.startDate, config.format, config.locale);
                }
                if (instance.endInput && instance.endDate) {
                    instance.endInput.value = this._formatDate(instance.endDate, config.format, config.locale);
                }
            } else if (config.mode === 'multiple') {
                if (instance.input) {
                    var formatted = instance.selectedDates.map(function(d) {
                        return window.RSL.DatePicker._formatDate(d, config.format, config.locale);
                    });
                    instance.input.value = formatted.join(', ');
                }
            }

            // Also sync to original input if it exists
            if (instance.originalInput) {
                if (config.mode === 'range' && instance.startDate && instance.endDate) {
                    instance.originalInput.value = this._formatDateISO(instance.startDate) + ',' + this._formatDateISO(instance.endDate);
                } else if (config.mode === 'single' && instance.selectedDates.length > 0) {
                    instance.originalInput.value = this._formatDateISO(instance.selectedDates[0]);
                } else if (config.mode === 'multiple' && instance.selectedDates.length > 0) {
                    instance.originalInput.value = instance.selectedDates.map(function(d) {
                        return window.RSL.DatePicker._formatDateISO(d);
                    }).join(',');
                }
            }

            // Update clear button visibility
            this._updateClearButton(instance);

            // Trigger change event
            this._triggerEvent(instance, 'change', {
                dates: instance.selectedDates,
                startDate: instance.startDate,
                endDate: instance.endDate
            });
        },

        /**
         * Update the summary in the footer
         */
        _updateSummary: function(instance) {
            if (!instance.summaryElement) return;

            var config = instance.config;
            var html = '';

            if (config.mode === 'range') {
                if (instance.startDate && instance.endDate) {
                    var days = Math.ceil((instance.endDate - instance.startDate) / (1000 * 60 * 60 * 24)) + 1;
                    html = '<span class="rsl-date-picker-summary-range">' +
                        this._formatDateShort(instance.startDate, config.locale) + ' - ' +
                        this._formatDateShort(instance.endDate, config.locale) +
                        '</span><span class="rsl-date-picker-summary-days">(' + days + ' day' + (days !== 1 ? 's' : '') + ')</span>';
                } else if (instance.startDate) {
                    html = '<span class="rsl-date-picker-summary-range">' +
                        this._formatDateShort(instance.startDate, config.locale) +
                        '</span><span class="rsl-date-picker-summary-days">(select end date)</span>';
                } else {
                    html = '<span class="rsl-date-picker-summary-range">No dates selected</span>';
                }
            } else if (config.mode === 'multiple') {
                var count = instance.selectedDates.length;
                if (count > 0) {
                    html = '<span class="rsl-date-picker-summary-range">' + count + ' date' + (count !== 1 ? 's' : '') + ' selected</span>';
                } else {
                    html = '<span class="rsl-date-picker-summary-range">No dates selected</span>';
                }
            } else if (config.mode === 'single') {
                if (instance.selectedDates.length > 0) {
                    html = '<span class="rsl-date-picker-summary-range">' +
                        this._formatDateShort(instance.selectedDates[0], config.locale) + '</span>';
                } else {
                    html = '<span class="rsl-date-picker-summary-range">No date selected</span>';
                }
            }

            instance.summaryElement.innerHTML = html;
        },

        /**
         * Update preset button states
         */
        _updatePresetButtons: function(instance, activePreset) {
            var presets = instance.popover.querySelectorAll('.rsl-date-picker-preset');
            presets.forEach(function(btn) {
                var isActive = btn.getAttribute('data-preset') === activePreset;
                btn.setAttribute('aria-pressed', isActive ? 'true' : 'false');
                btn.classList.toggle('active', isActive);
            });
        },

        /**
         * Apply the current selection
         */
        _applySelection: function(instance) {
            this._updateInputValues(instance);
            this._triggerEvent(instance, 'apply', {
                dates: instance.selectedDates,
                startDate: instance.startDate,
                endDate: instance.endDate
            });

            // Publish to FilterBus if configured
            this.publishToFilterBus(instance);
        },

        /**
         * Publish date selection to FilterBus
         * @param {Object} instance - DatePicker instance
         */
        publishToFilterBus: function(instance) {
            var config = instance.config;

            // Check if FilterBus publishing is enabled
            if (!config.filterBusPublish) return;

            // Check if FilterBus is available
            if (!window.RSL || !window.RSL.FilterBus || !window.RSL.FilterBus.publish) {
                console.warn('RSL.FilterBus not available for DatePicker publishing');
                return;
            }

            var publishKey = config.filterBusPublish;
            var value = null;

            // Build the value based on mode
            if (config.mode === 'single') {
                if (instance.selectedDates.length > 0) {
                    value = {
                        mode: 'single',
                        date: this._formatDateISO(instance.selectedDates[0]),
                        formatted: this._formatDate(instance.selectedDates[0], config.format, config.locale)
                    };
                }
            } else if (config.mode === 'range') {
                if (instance.startDate) {
                    value = {
                        mode: 'range',
                        startDate: this._formatDateISO(instance.startDate),
                        endDate: instance.endDate ? this._formatDateISO(instance.endDate) : null,
                        formatted: this._formatDate(instance.startDate, config.format, config.locale) +
                            (instance.endDate ? ' - ' + this._formatDate(instance.endDate, config.format, config.locale) : '')
                    };

                    // Add convenience dateRange array for easy filtering
                    if (instance.endDate) {
                        value.dateRange = [
                            this._formatDateISO(instance.startDate),
                            this._formatDateISO(instance.endDate)
                        ];
                    }
                }
            } else if (config.mode === 'multiple') {
                if (instance.selectedDates.length > 0) {
                    var self = this;
                    value = {
                        mode: 'multiple',
                        dates: instance.selectedDates.map(function(d) {
                            return self._formatDateISO(d);
                        }),
                        formatted: instance.selectedDates.map(function(d) {
                            return self._formatDate(d, config.format, config.locale);
                        }).join(', ')
                    };
                }
            }

            // Publish to FilterBus
            window.RSL.FilterBus.publish(publishKey, value, {
                source: 'date-picker',
                element: instance.element,
                mode: config.mode
            });

            // Update visual indicator for FilterBus active state
            if (value) {
                instance.element.setAttribute('data-filterbus-active', 'true');
            } else {
                instance.element.removeAttribute('data-filterbus-active');
            }
        },

        /**
         * Open the calendar popover
         */
        open: function(instance) {
            if (typeof instance === 'string') {
                instance = this._getInstance(instance);
            }
            if (!instance || instance.isOpen || instance.config.inline) return;

            instance.isOpen = true;
            instance.popover.classList.add('open');

            // Update trigger aria
            if (instance.triggerElement) {
                instance.triggerElement.setAttribute('aria-expanded', 'true');
            }

            // Set view date to current selection or today
            if (instance.startDate) {
                instance.viewDate = new Date(instance.startDate);
            } else if (instance.selectedDates.length > 0) {
                instance.viewDate = new Date(instance.selectedDates[0]);
            } else {
                instance.viewDate = new Date();
            }
            instance.viewDate.setDate(1);

            // Render calendar
            this._renderCalendar(instance);

            // Position popover
            this._positionPopover(instance);

            // Focus first focusable or selected date
            var self = this;
            requestAnimationFrame(function() {
                var focusTarget = instance.popover.querySelector('.rsl-date-picker-day-btn[aria-selected="true"]') ||
                                  instance.popover.querySelector('.rsl-date-picker-day-btn[aria-current="date"]') ||
                                  instance.popover.querySelector('.rsl-date-picker-day-btn[tabindex="0"]');
                if (focusTarget) {
                    focusTarget.focus();
                    instance.focusedDate = new Date(focusTarget.getAttribute('data-date'));
                }
            });

            // Announce
            var monthNames = this.monthNames[instance.config.locale] || this.monthNames['en-US'];
            this._announce(instance, 'Calendar opened. ' + monthNames[instance.viewDate.getMonth()] + ' ' +
                instance.viewDate.getFullYear() + '. Use arrow keys to navigate days.');

            this._triggerEvent(instance, 'open');
        },

        /**
         * Close the calendar popover
         */
        close: function(instance) {
            if (typeof instance === 'string') {
                instance = this._getInstance(instance);
            }
            if (!instance || !instance.isOpen || instance.config.inline) return;

            instance.isOpen = false;
            instance._justClosed = true;

            // Reset the flag after a short delay to allow reopening
            setTimeout(function() {
                instance._justClosed = false;
            }, 100);

            instance.popover.classList.remove('open');

            // Update trigger aria
            if (instance.triggerElement) {
                instance.triggerElement.setAttribute('aria-expanded', 'false');
            }

            // Return focus to trigger
            requestAnimationFrame(function() {
                var focusTarget = instance.config.mode === 'range' ? instance.startInput : instance.input;
                if (focusTarget) {
                    focusTarget.focus();
                }
            });

            this._triggerEvent(instance, 'close');
        },

        /**
         * Toggle the popover open/close
         */
        _togglePopover: function(instance) {
            if (instance.isOpen) {
                this.close(instance);
            } else {
                this.open(instance);
            }
        },

        /**
         * Position the popover relative to the input
         */
        _positionPopover: function(instance) {
            // On mobile, use fixed positioning at bottom
            if (window.innerWidth < 768) return;

            var popover = instance.popover;
            var rect = instance.element.getBoundingClientRect();

            // Reset ALL position styles
            popover.style.top = '';
            popover.style.left = '';
            popover.style.bottom = '';

            // Check if it fits below
            var spaceBelow = window.innerHeight - rect.bottom;
            var spaceAbove = rect.top;
            var popoverHeight = popover.offsetHeight;

            if (spaceBelow < popoverHeight && spaceAbove > spaceBelow) {
                // Position above
                popover.style.top = 'auto';
                popover.style.bottom = 'calc(100% + 8px)';
            }
        },

        /**
         * Clear the selection
         */
        clear: function(instance) {
            if (typeof instance === 'string') {
                instance = this._getInstance(instance);
            }
            if (!instance) return;

            instance.selectedDates = [];
            instance.startDate = null;
            instance.endDate = null;

            // Clear inputs
            if (instance.input) instance.input.value = '';
            if (instance.startInput) instance.startInput.value = '';
            if (instance.endInput) instance.endInput.value = '';

            this._updateSummary(instance);
            this._updatePresetButtons(instance, null);
            this._updateClearButton(instance);
            this._renderCalendar(instance);
            this._clearError(instance);

            this._announce(instance, 'Date selection cleared.');

            this._triggerEvent(instance, 'clear');

            // Publish null to FilterBus to clear any filters
            this.publishToFilterBus(instance);
        },

        /**
         * Get the current value
         */
        getValue: function(instance) {
            if (typeof instance === 'string') {
                instance = this._getInstance(instance);
            }
            if (!instance) return null;

            var config = instance.config;

            if (config.mode === 'single') {
                return instance.selectedDates.length > 0 ?
                    new Date(instance.selectedDates[0]) : null;
            } else if (config.mode === 'range') {
                return {
                    start: instance.startDate ? new Date(instance.startDate) : null,
                    end: instance.endDate ? new Date(instance.endDate) : null
                };
            } else {
                return instance.selectedDates.map(function(d) {
                    return new Date(d);
                });
            }
        },

        /**
         * Set the value programmatically
         */
        setValue: function(instance, value) {
            if (typeof instance === 'string') {
                instance = this._getInstance(instance);
            }
            if (!instance) return;

            this._setInitialValue(instance, value);
            this._renderCalendar(instance);
        },

        /**
         * Set initial value
         */
        _setInitialValue: function(instance, value) {
            var config = instance.config;

            if (config.mode === 'single') {
                var date = this._parseDate(value);
                if (date) {
                    instance.selectedDates = [date];
                    instance.viewDate = new Date(date);
                }
            } else if (config.mode === 'range') {
                if (typeof value === 'object' && value.start) {
                    instance.startDate = this._parseDate(value.start);
                    instance.endDate = value.end ? this._parseDate(value.end) : null;
                    if (instance.startDate) {
                        instance.viewDate = new Date(instance.startDate);
                    }
                } else if (typeof value === 'string' && value.includes(' to ')) {
                    var parts = value.split(' to ');
                    instance.startDate = this._parseDate(parts[0]);
                    instance.endDate = this._parseDate(parts[1]);
                    if (instance.startDate) {
                        instance.viewDate = new Date(instance.startDate);
                    }
                }
            }

            instance.viewDate.setDate(1);
            this._updateInputValues(instance);
            this._updateSummary(instance);
        },

        /**
         * Destroy the instance
         */
        destroy: function(instance) {
            if (typeof instance === 'string') {
                instance = this._getInstance(instance);
            }
            if (!instance) return;

            // Remove from instances map
            this.instances.delete(instance.element);

            // Clean up DOM
            instance.element.innerHTML = '';
            instance.element.classList.remove('rsl-date-picker');
            instance.element.removeAttribute('data-show-dual-calendar');

            this._triggerEvent(instance, 'destroy');
        },

        /**
         * Get instance by element or ID
         */
        _getInstance: function(identifier) {
            if (typeof identifier === 'string') {
                // Handle ID without # prefix
                var selector = identifier;
                if (identifier.indexOf('#') !== 0 && identifier.indexOf('.') !== 0 && identifier.indexOf('[') !== 0) {
                    selector = '#' + identifier;
                }

                var element = document.querySelector(selector);
                if (!element) {
                    // Try without the added #
                    element = document.querySelector(identifier);
                }
                if (!element) return null;

                // First try direct lookup
                var instance = this.instances.get(element);
                if (instance) return instance;

                // If element is the original input, search for instance by originalInput
                var foundInstance = null;
                this.instances.forEach(function(inst) {
                    if (inst.originalInput === element || inst.element === element) {
                        foundInstance = inst;
                    }
                });
                return foundInstance;
            }
            return this.instances.get(identifier);
        },

        /**
         * Announce to screen readers
         */
        _announce: function(instance, message) {
            var self = this;

            // Debounce announcements
            if (instance._announceTimeout) {
                clearTimeout(instance._announceTimeout);
            }

            instance._announceTimeout = setTimeout(function() {
                instance.liveRegion.textContent = message;
            }, 150);
        },

        /**
         * Show error message
         */
        _showError: function(instance, message) {
            instance.errorContainer.textContent = message;
            instance.errorContainer.classList.add('visible');

            // Update input aria
            var input = instance.input || instance.startInput;
            if (input) {
                input.setAttribute('aria-invalid', 'true');
                input.setAttribute('aria-describedby', instance.hintId + ' ' + instance.errorContainer.id);
            }
        },

        /**
         * Clear error message
         */
        _clearError: function(instance) {
            instance.errorContainer.textContent = '';
            instance.errorContainer.classList.remove('visible');

            var input = instance.input || instance.startInput;
            if (input) {
                input.removeAttribute('aria-invalid');
                input.setAttribute('aria-describedby', instance.hintId);
            }
        },

        /**
         * Trigger custom event
         */
        _triggerEvent: function(instance, eventName, detail) {
            var self = this;
            var config = instance.config;

            // Build formatted date string for the detail
            var formatted = '';
            if (config.mode === 'single' && instance.selectedDates.length > 0) {
                formatted = this._formatDate(instance.selectedDates[0], config.format, config.locale);
            } else if (config.mode === 'range' && instance.startDate) {
                formatted = this._formatDate(instance.startDate, config.format, config.locale);
                if (instance.endDate) {
                    formatted += ' - ' + this._formatDate(instance.endDate, config.format, config.locale);
                }
            } else if (config.mode === 'multiple' && instance.selectedDates.length > 0) {
                formatted = instance.selectedDates.map(function(d) {
                    return self._formatDate(d, config.format, config.locale);
                }).join(', ');
            }

            var eventDetail = Object.assign({
                instance: instance,
                formatted: formatted
            }, detail || {});

            // Dispatch on container element with rsl-datepicker- prefix
            var event = new CustomEvent('rsl-datepicker-' + eventName, {
                bubbles: true,
                detail: eventDetail
            });
            instance.element.dispatchEvent(event);

            // Also dispatch with rsl-date- prefix for simpler usage
            var simpleEvent = new CustomEvent('rsl-date-' + eventName, {
                bubbles: true,
                detail: eventDetail
            });
            instance.element.dispatchEvent(simpleEvent);

            // If there's an original input, dispatch on that too
            if (instance.originalInput) {
                var inputEvent = new CustomEvent('rsl-date-' + eventName, {
                    bubbles: true,
                    detail: eventDetail
                });
                instance.originalInput.dispatchEvent(inputEvent);
            }
        },

        /**
         * Generate unique ID
         */
        _generateId: function(prefix) {
            return 'rsl-dp-' + prefix + '-' + Math.random().toString(36).substr(2, 9);
        },

        /**
         * Parse a date string
         */
        _parseDate: function(str) {
            if (!str) return null;
            if (str instanceof Date) return new Date(str);

            // Handle special keywords
            var strLower = str.toLowerCase();
            if (strLower === 'today') {
                var today = new Date();
                today.setHours(0, 0, 0, 0);
                return today;
            }
            if (strLower === 'tomorrow') {
                var tomorrow = new Date();
                tomorrow.setDate(tomorrow.getDate() + 1);
                tomorrow.setHours(0, 0, 0, 0);
                return tomorrow;
            }
            if (strLower === 'yesterday') {
                var yesterday = new Date();
                yesterday.setDate(yesterday.getDate() - 1);
                yesterday.setHours(0, 0, 0, 0);
                return yesterday;
            }

            // Try common formats FIRST to avoid timezone issues with ISO strings
            // (new Date("2025-12-04") parses as UTC, causing day-before bug in western timezones)
            var formats = [
                /^(\d{4})-(\d{2})-(\d{2})$/,        // YYYY-MM-DD
                /^(\d{2})\/(\d{2})\/(\d{4})$/,       // MM/DD/YYYY
                /^(\d{2})-(\d{2})-(\d{4})$/          // DD-MM-YYYY
            ];

            for (var i = 0; i < formats.length; i++) {
                var match = str.match(formats[i]);
                if (match) {
                    if (i === 0) {
                        return new Date(parseInt(match[1]), parseInt(match[2]) - 1, parseInt(match[3]));
                    } else if (i === 1) {
                        return new Date(parseInt(match[3]), parseInt(match[1]) - 1, parseInt(match[2]));
                    } else if (i === 2) {
                        return new Date(parseInt(match[3]), parseInt(match[2]) - 1, parseInt(match[1]));
                    }
                }
            }

            // Fallback to native Date parsing for other formats
            var date = new Date(str);
            if (!isNaN(date.getTime())) return date;

            return null;
        },

        /**
         * Format date to ISO string (YYYY-MM-DD)
         */
        _formatDateISO: function(date) {
            var year = date.getFullYear();
            var month = String(date.getMonth() + 1).padStart(2, '0');
            var day = String(date.getDate()).padStart(2, '0');
            return year + '-' + month + '-' + day;
        },

        /**
         * Parse ISO date string (YYYY-MM-DD) as LOCAL time, not UTC
         * This avoids timezone issues where "2025-12-18" becomes Dec 17 in some timezones
         */
        _parseISOLocal: function(dateStr) {
            if (!dateStr) return null;
            var parts = dateStr.split('-');
            if (parts.length !== 3) return null;
            // Month is 0-indexed in JavaScript Date
            return new Date(parseInt(parts[0], 10), parseInt(parts[1], 10) - 1, parseInt(parts[2], 10));
        },

        /**
         * Format date according to format string
         */
        _formatDate: function(date, format, locale) {
            var monthNames = this.monthNames[locale] || this.monthNames['en-US'];
            var monthNamesShort = this.monthNamesShort[locale] || this.monthNamesShort['en-US'];

            // Build the values
            var year = date.getFullYear();
            var month = date.getMonth();
            var day = date.getDate();

            // Simple sequential replacement using unique placeholders
            // Process longest tokens first, use numbered placeholders to avoid conflicts
            var result = format;

            // Step 1: Replace all tokens with numbered placeholders (longest first)
            result = result.replace(/YYYY/g, '{{0}}');
            result = result.replace(/MMMM/g, '{{1}}');
            result = result.replace(/MMM/g, '{{2}}');
            result = result.replace(/MM/g, '{{3}}');
            result = result.replace(/YY/g, '{{4}}');
            result = result.replace(/DD/g, '{{5}}');
            result = result.replace(/M/g, '{{6}}');
            result = result.replace(/D/g, '{{7}}');

            // Step 2: Replace placeholders with actual values
            result = result.replace(/\{\{0\}\}/g, String(year));
            result = result.replace(/\{\{1\}\}/g, monthNames[month]);
            result = result.replace(/\{\{2\}\}/g, monthNamesShort[month]);
            result = result.replace(/\{\{3\}\}/g, String(month + 1).padStart(2, '0'));
            result = result.replace(/\{\{4\}\}/g, String(year).slice(-2));
            result = result.replace(/\{\{5\}\}/g, String(day).padStart(2, '0'));
            result = result.replace(/\{\{6\}\}/g, String(month + 1));
            result = result.replace(/\{\{7\}\}/g, String(day));

            return result;
        },

        /**
         * Format date for display (short format)
         */
        _formatDateShort: function(date, locale) {
            var monthNamesShort = this.monthNamesShort[locale] || this.monthNamesShort['en-US'];
            return monthNamesShort[date.getMonth()] + ' ' + date.getDate() + ', ' + date.getFullYear();
        },

        /**
         * Format date for screen readers (long format)
         */
        _formatDateLong: function(date, locale) {
            var dayNames = this.dayNames[locale] || this.dayNames['en-US'];
            var monthNames = this.monthNames[locale] || this.monthNames['en-US'];
            return dayNames[date.getDay()] + ', ' + monthNames[date.getMonth()] + ' ' +
                   date.getDate() + ', ' + date.getFullYear();
        },

        /**
         * Get format hint for display
         */
        _getFormatHint: function(format) {
            return format.replace('YYYY', 'YYYY').replace('MMM', 'MMM').replace('MM', 'MM').replace('DD', 'DD').replace('D', 'D');
        }

    };

    // Auto-initialize on DOMContentLoaded
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', function() {
            window.RSL.DatePicker.init();
        });
    } else {
        window.RSL.DatePicker.init();
    }

})();
