/* ============================================
   RSL Color Picker Component
   Version: 1.0.0
   Description: Premium accessible color picker with
   WCAG contrast checking, multiple selection modes,
   and full ADA/WCAG 2.1 AA compliance.
   ============================================ */

(function() {
    'use strict';

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

    /**
     * Color Picker Component
     * A fully accessible color picker with contrast checking and multiple modes
     */
    window.RSL.ColorPicker = {

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

        /** Default configuration */
        defaults: {
            mode: 'palette',              // 'palette', 'custom', 'constrained'
            format: 'hex',                // 'hex', 'rgb', 'hsl'
            value: null,                  // Initial color value
            palette: 'default',           // Palette name or custom array
            contrastAgainst: '#FFFFFF',   // Surface to check contrast against
            minContrast: 4.5,             // Minimum contrast ratio (WCAG AA = 4.5)
            wcagLevel: 'AA',              // 'AA' or 'AAA'
            showContrast: true,           // Show contrast information
            showPreview: true,            // Show text preview
            showNames: true,              // Show color names for screen readers
            showRecent: true,             // Show recent colors
            showAlpha: false,             // Show opacity slider
            closeOnSelect: false,         // Close picker when color is selected
            inline: false,                // Display inline (always open)
            compact: false,               // Compact trigger mode
            disabled: false,
            required: false,
            placeholder: 'Select color',
            ariaLabel: 'Color picker',
            maxRecent: 8,                 // Maximum recent colors to store
            recentStorageKey: 'rsl-color-picker-recent'
        },

        /** Predefined color palettes */
        palettes: {
            // Default accessible palette - 24 colors
            default: [
                { hex: '#000000', name: 'Black' },
                { hex: '#374151', name: 'Gray 700' },
                { hex: '#6B7280', name: 'Gray 500' },
                { hex: '#9CA3AF', name: 'Gray 400' },
                { hex: '#D1D5DB', name: 'Gray 300' },
                { hex: '#FFFFFF', name: 'White' },
                { hex: '#DC2626', name: 'Red' },
                { hex: '#EA580C', name: 'Orange' },
                { hex: '#D97706', name: 'Amber' },
                { hex: '#CA8A04', name: 'Yellow' },
                { hex: '#65A30D', name: 'Lime' },
                { hex: '#16A34A', name: 'Green' },
                { hex: '#059669', name: 'Emerald' },
                { hex: '#0D9488', name: 'Teal' },
                { hex: '#0891B2', name: 'Cyan' },
                { hex: '#0284C7', name: 'Sky' },
                { hex: '#2563EB', name: 'Blue' },
                { hex: '#4F46E5', name: 'Indigo' },
                { hex: '#7C3AED', name: 'Violet' },
                { hex: '#9333EA', name: 'Purple' },
                { hex: '#C026D3', name: 'Fuchsia' },
                { hex: '#DB2777', name: 'Pink' },
                { hex: '#E11D48', name: 'Rose' },
                { hex: '#6E7BFF', name: 'RSL Primary' }
            ],

            // Semantic palette for UI elements
            semantic: [
                { hex: '#6E7BFF', name: 'Primary' },
                { hex: '#5A67D8', name: 'Primary Dark' },
                { hex: '#10B981', name: 'Success' },
                { hex: '#059669', name: 'Success Dark' },
                { hex: '#F59E0B', name: 'Warning' },
                { hex: '#D97706', name: 'Warning Dark' },
                { hex: '#EF4444', name: 'Danger' },
                { hex: '#DC2626', name: 'Danger Dark' },
                { hex: '#3B82F6', name: 'Info' },
                { hex: '#2563EB', name: 'Info Dark' },
                { hex: '#6B7280', name: 'Secondary' },
                { hex: '#4B5563', name: 'Secondary Dark' }
            ],

            // Grayscale palette
            grayscale: [
                { hex: '#000000', name: 'Black' },
                { hex: '#111827', name: 'Gray 900' },
                { hex: '#1F2937', name: 'Gray 800' },
                { hex: '#374151', name: 'Gray 700' },
                { hex: '#4B5563', name: 'Gray 600' },
                { hex: '#6B7280', name: 'Gray 500' },
                { hex: '#9CA3AF', name: 'Gray 400' },
                { hex: '#D1D5DB', name: 'Gray 300' },
                { hex: '#E5E7EB', name: 'Gray 200' },
                { hex: '#F3F4F6', name: 'Gray 100' },
                { hex: '#F9FAFB', name: 'Gray 50' },
                { hex: '#FFFFFF', name: 'White' }
            ],

            // Extended rainbow palette
            rainbow: [
                { hex: '#EF4444', name: 'Red' },
                { hex: '#F97316', name: 'Orange' },
                { hex: '#F59E0B', name: 'Amber' },
                { hex: '#EAB308', name: 'Yellow' },
                { hex: '#84CC16', name: 'Lime' },
                { hex: '#22C55E', name: 'Green' },
                { hex: '#10B981', name: 'Emerald' },
                { hex: '#14B8A6', name: 'Teal' },
                { hex: '#06B6D4', name: 'Cyan' },
                { hex: '#0EA5E9', name: 'Sky' },
                { hex: '#3B82F6', name: 'Blue' },
                { hex: '#6366F1', name: 'Indigo' },
                { hex: '#8B5CF6', name: 'Violet' },
                { hex: '#A855F7', name: 'Purple' },
                { hex: '#D946EF', name: 'Fuchsia' },
                { hex: '#EC4899', name: 'Pink' },
                { hex: '#F43F5E', name: 'Rose' }
            ],

            // Minimal palette for quick selection
            minimal: [
                { hex: '#000000', name: 'Black' },
                { hex: '#FFFFFF', name: 'White' },
                { hex: '#EF4444', name: 'Red' },
                { hex: '#22C55E', name: 'Green' },
                { hex: '#3B82F6', name: 'Blue' },
                { hex: '#F59E0B', name: 'Yellow' }
            ]
        },

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

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

            return this;
        },

        /**
         * Create a single color 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,
                currentColor: null,
                currentHSL: { h: 0, s: 100, l: 50 },
                currentAlpha: 1,
                selectedSwatch: null,
                focusedIndex: 0,
                recentColors: [],
                container: null,
                trigger: null,
                dialog: null,
                hexInput: null,
                liveRegion: null
            };

            // Load recent colors from storage
            this._loadRecentColors(instance);

            // Set initial color
            if (config.value) {
                instance.currentColor = this._normalizeColor(config.value);
                instance.currentHSL = this._hexToHSL(instance.currentColor);
            }

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

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

            // Store instance
            this.instances.set(element, instance);

            // If inline mode, show dialog
            if (config.inline) {
                instance.dialog.classList.add('open');
            }

            return instance;
        },

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

            if (dataset.mode) config.mode = dataset.mode;
            if (dataset.format) config.format = dataset.format;
            if (dataset.value) config.value = dataset.value;
            if (dataset.palette) config.palette = dataset.palette;
            if (dataset.customPalette) {
                try {
                    config.palette = JSON.parse(dataset.customPalette);
                } catch (e) {
                    console.warn('RSL ColorPicker: Invalid custom palette JSON');
                }
            }
            if (dataset.contrastAgainst) config.contrastAgainst = dataset.contrastAgainst;
            if (dataset.minContrast) config.minContrast = parseFloat(dataset.minContrast);
            if (dataset.wcagLevel) config.wcagLevel = dataset.wcagLevel;
            if (dataset.showContrast !== undefined) config.showContrast = dataset.showContrast === 'true';
            if (dataset.showPreview !== undefined) config.showPreview = dataset.showPreview === 'true';
            if (dataset.showNames !== undefined) config.showNames = dataset.showNames === 'true';
            if (dataset.showRecent !== undefined) config.showRecent = dataset.showRecent === 'true';
            if (dataset.showAlpha !== undefined) config.showAlpha = dataset.showAlpha === 'true';
            if (dataset.closeOnSelect !== undefined) config.closeOnSelect = dataset.closeOnSelect === 'true';
            if (dataset.inline !== undefined) config.inline = dataset.inline === 'true';
            if (dataset.compact !== undefined) config.compact = dataset.compact === 'true';
            if (dataset.disabled !== undefined) config.disabled = dataset.disabled === 'true';
            if (dataset.required !== undefined) config.required = dataset.required === 'true';
            if (dataset.placeholder) config.placeholder = dataset.placeholder;
            if (dataset.ariaLabel) config.ariaLabel = dataset.ariaLabel;

            return config;
        },

        /**
         * Build the DOM structure for the color picker
         */
        _buildDOM: function(instance) {
            var self = this;
            var config = instance.config;
            var element = instance.element;
            var isInput = element.tagName === 'INPUT';

            // Create container
            var container = document.createElement('div');
            container.className = 'rsl-color-picker';
            if (config.inline) container.setAttribute('data-inline', 'true');
            if (config.compact) container.setAttribute('data-compact', 'true');

            // If element is an input, wrap it
            if (isInput) {
                element.style.display = 'none';
                element.parentNode.insertBefore(container, element);
                container.appendChild(element);
                instance.originalInput = element;
            } else {
                // Create hidden input for form submission
                var hiddenInput = document.createElement('input');
                hiddenInput.type = 'hidden';
                hiddenInput.name = element.dataset.name || 'color';
                if (instance.currentColor) hiddenInput.value = instance.currentColor;
                container.appendChild(hiddenInput);
                instance.originalInput = hiddenInput;
                element.appendChild(container);
            }

            instance.container = container;

            // Create trigger button
            var triggerId = 'rsl-cp-trigger-' + Date.now();
            var dialogId = 'rsl-cp-dialog-' + Date.now();

            var trigger = document.createElement('button');
            trigger.type = 'button';
            trigger.className = 'rsl-color-picker-trigger';
            trigger.id = triggerId;
            trigger.setAttribute('aria-haspopup', 'dialog');
            trigger.setAttribute('aria-expanded', 'false');
            trigger.setAttribute('aria-controls', dialogId);
            trigger.setAttribute('aria-label', config.ariaLabel);
            if (config.disabled) trigger.disabled = true;

            // Swatch preview
            var swatchPreview = document.createElement('span');
            swatchPreview.className = 'rsl-color-picker-swatch-preview';
            if (instance.currentColor) {
                swatchPreview.style.setProperty('--swatch-color', instance.currentColor);
            }
            trigger.appendChild(swatchPreview);

            // Value display
            var valueDisplay = document.createElement('span');
            valueDisplay.className = 'rsl-color-picker-value-display';
            var initialDisplay = instance.currentColor ? self._formatOutput(instance, instance.currentColor) : config.placeholder;
            valueDisplay.textContent = initialDisplay;
            trigger.appendChild(valueDisplay);

            // Dropdown icon
            var dropdownIcon = document.createElement('i');
            dropdownIcon.className = 'fas fa-chevron-down dropdown-icon';
            dropdownIcon.setAttribute('aria-hidden', 'true');
            trigger.appendChild(dropdownIcon);

            container.appendChild(trigger);
            instance.trigger = trigger;
            instance.swatchPreview = swatchPreview;
            instance.valueDisplay = valueDisplay;

            // Create dialog
            var dialog = document.createElement('div');
            dialog.className = 'rsl-color-picker-dialog';
            dialog.id = dialogId;
            dialog.setAttribute('role', 'dialog');
            dialog.setAttribute('aria-modal', 'true');
            dialog.setAttribute('aria-labelledby', dialogId + '-title');

            // Dialog header
            var header = document.createElement('div');
            header.className = 'rsl-color-picker-header';

            var title = document.createElement('h3');
            title.className = 'rsl-color-picker-title';
            title.id = dialogId + '-title';
            title.textContent = 'Choose Color';
            header.appendChild(title);

            var closeBtn = document.createElement('button');
            closeBtn.type = 'button';
            closeBtn.className = 'rsl-color-picker-close';
            closeBtn.setAttribute('aria-label', 'Close color picker, press Enter to close');
            closeBtn.innerHTML = '<i class="fas fa-times" aria-hidden="true"></i>';
            header.appendChild(closeBtn);
            instance.closeBtn = closeBtn;

            dialog.appendChild(header);

            // Mode tabs (if not constrained)
            if (config.mode !== 'constrained') {
                var tabs = this._buildTabs(instance);
                dialog.appendChild(tabs);
                instance.tabs = tabs;
            }

            // Palette panel
            var palettePanel = document.createElement('div');
            palettePanel.className = 'rsl-color-picker-palette-panel';
            palettePanel.id = dialogId + '-palette';
            palettePanel.setAttribute('role', 'tabpanel');
            palettePanel.setAttribute('aria-labelledby', dialogId + '-tab-palette');

            // Recent colors (if enabled)
            if (config.showRecent && instance.recentColors.length > 0) {
                var recentSection = this._buildRecentColors(instance);
                palettePanel.appendChild(recentSection);
            }

            // Palette grid
            var palette = this._buildPalette(instance);
            palettePanel.appendChild(palette);

            dialog.appendChild(palettePanel);
            instance.palettePanel = palettePanel;

            // Custom color panel
            var customPanel = document.createElement('div');
            customPanel.className = 'rsl-color-picker-custom';
            customPanel.id = dialogId + '-custom';
            customPanel.setAttribute('role', 'tabpanel');
            customPanel.setAttribute('aria-labelledby', dialogId + '-tab-custom');

            // HSL Sliders
            var sliders = this._buildSliders(instance);
            customPanel.appendChild(sliders);

            // Hex input with eyedropper
            var inputGroup = this._buildHexInput(instance);
            customPanel.appendChild(inputGroup);

            dialog.appendChild(customPanel);
            instance.customPanel = customPanel;

            // Preview & Contrast section
            if (config.showContrast || config.showPreview) {
                var previewSection = this._buildPreviewSection(instance);
                dialog.appendChild(previewSection);
            }

            // Suggestion banner (for smart suggestions)
            var suggestion = document.createElement('div');
            suggestion.className = 'rsl-color-picker-suggestion';
            dialog.appendChild(suggestion);
            instance.suggestionBanner = suggestion;

            // Action buttons
            var actions = document.createElement('div');
            actions.className = 'rsl-color-picker-actions';

            var cancelBtn = document.createElement('button');
            cancelBtn.type = 'button';
            cancelBtn.className = 'rsl-color-picker-btn rsl-color-picker-btn-secondary';
            cancelBtn.textContent = 'Cancel';
            actions.appendChild(cancelBtn);
            instance.cancelBtn = cancelBtn;

            var applyBtn = document.createElement('button');
            applyBtn.type = 'button';
            applyBtn.className = 'rsl-color-picker-btn rsl-color-picker-btn-primary';
            applyBtn.textContent = 'Apply Color';
            actions.appendChild(applyBtn);
            instance.applyBtn = applyBtn;

            dialog.appendChild(actions);

            container.appendChild(dialog);
            instance.dialog = dialog;

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

            // Set initial mode
            if (config.mode === 'custom') {
                instance.customPanel.classList.add('active');
                instance.palettePanel.style.display = 'none';
            }
        },

        /**
         * Build mode tabs
         */
        _buildTabs: function(instance) {
            var dialogId = instance.dialog ? instance.dialog.id : 'rsl-cp-dialog-' + Date.now();

            var tabs = document.createElement('div');
            tabs.className = 'rsl-color-picker-tabs';
            tabs.setAttribute('role', 'tablist');

            var paletteTab = document.createElement('button');
            paletteTab.type = 'button';
            paletteTab.className = 'rsl-color-picker-tab';
            paletteTab.id = dialogId + '-tab-palette';
            paletteTab.setAttribute('role', 'tab');
            paletteTab.setAttribute('aria-selected', instance.config.mode === 'palette' ? 'true' : 'false');
            paletteTab.setAttribute('aria-controls', dialogId + '-palette');
            paletteTab.innerHTML = '<i class="fas fa-palette" aria-hidden="true"></i> Palette';
            tabs.appendChild(paletteTab);
            instance.paletteTab = paletteTab;

            var customTab = document.createElement('button');
            customTab.type = 'button';
            customTab.className = 'rsl-color-picker-tab';
            customTab.id = dialogId + '-tab-custom';
            customTab.setAttribute('role', 'tab');
            customTab.setAttribute('aria-selected', instance.config.mode === 'custom' ? 'true' : 'false');
            customTab.setAttribute('aria-controls', dialogId + '-custom');
            customTab.innerHTML = '<i class="fas fa-sliders-h" aria-hidden="true"></i> Custom';
            tabs.appendChild(customTab);
            instance.customTab = customTab;

            return tabs;
        },

        /**
         * Build palette grid
         */
        _buildPalette: function(instance) {
            var self = this;
            var config = instance.config;
            var colors = this._getPaletteColors(config.palette);

            var palette = document.createElement('div');
            palette.className = 'rsl-color-picker-palette';
            palette.setAttribute('role', 'listbox');
            palette.setAttribute('aria-label', 'Color palette');

            colors.forEach(function(color, index) {
                var hex = typeof color === 'string' ? color : color.hex;
                var name = typeof color === 'string' ? hex : (color.name || hex);
                var isSelected = instance.currentColor && instance.currentColor.toUpperCase() === hex.toUpperCase();

                // Check contrast in constrained mode
                var contrast = self.getContrastRatio(hex, config.contrastAgainst);
                var passesContrast = contrast >= config.minContrast;
                var isDisabled = config.mode === 'constrained' && !passesContrast;

                var swatch = document.createElement('button');
                swatch.type = 'button';
                swatch.className = 'rsl-color-picker-swatch';
                if (isDisabled) swatch.classList.add('disabled');
                swatch.style.setProperty('--swatch-color', hex);
                swatch.setAttribute('role', 'option');
                swatch.setAttribute('aria-selected', isSelected ? 'true' : 'false');
                swatch.setAttribute('aria-label', name + ', ' + hex + ', contrast ratio ' + contrast.toFixed(1) + ' to 1');
                swatch.setAttribute('data-color', hex);
                swatch.setAttribute('data-name', name);
                swatch.setAttribute('tabindex', index === 0 ? '0' : '-1');
                if (isDisabled) {
                    swatch.setAttribute('aria-disabled', 'true');
                    swatch.setAttribute('tabindex', '-1');
                }

                // Add checkmark for selected
                if (isSelected) {
                    var checkIcon = document.createElement('i');
                    checkIcon.className = 'fas fa-check check-icon';
                    checkIcon.setAttribute('aria-hidden', 'true');
                    swatch.appendChild(checkIcon);
                }

                // Add contrast badge if enabled
                if (config.showContrast && config.mode !== 'constrained') {
                    var badge = document.createElement('span');
                    badge.className = 'contrast-badge';
                    badge.classList.add(passesContrast ? 'pass' : 'fail');
                    badge.setAttribute('aria-hidden', 'true');
                    swatch.appendChild(badge);
                }

                palette.appendChild(swatch);
            });

            instance.palette = palette;
            instance.swatches = palette.querySelectorAll('.rsl-color-picker-swatch:not(.disabled)');
            return palette;
        },

        /**
         * Build recent colors section
         */
        _buildRecentColors: function(instance) {
            var self = this;
            var section = document.createElement('div');
            section.className = 'rsl-color-picker-recent';

            var label = document.createElement('div');
            label.className = 'rsl-color-picker-recent-label';
            label.textContent = 'Recent Colors';
            section.appendChild(label);

            var swatches = document.createElement('div');
            swatches.className = 'rsl-color-picker-recent-swatches';
            swatches.setAttribute('role', 'listbox');
            swatches.setAttribute('aria-label', 'Recent colors');

            instance.recentColors.forEach(function(hex, index) {
                var swatch = document.createElement('button');
                swatch.type = 'button';
                swatch.className = 'rsl-color-picker-recent-swatch';
                swatch.style.setProperty('--swatch-color', hex);
                swatch.setAttribute('role', 'option');
                swatch.setAttribute('aria-label', 'Recent color ' + hex);
                swatch.setAttribute('data-color', hex);
                swatch.setAttribute('tabindex', '-1');
                swatches.appendChild(swatch);
            });

            section.appendChild(swatches);
            instance.recentSwatches = swatches;
            return section;
        },

        /**
         * Build HSL sliders
         */
        _buildSliders: function(instance) {
            var self = this;
            var sliders = document.createElement('div');
            sliders.className = 'rsl-color-picker-sliders';

            // Hue slider
            var hueGroup = this._buildSlider(instance, 'hue', 'Hue', 0, 360, instance.currentHSL.h, '°');
            sliders.appendChild(hueGroup);

            // Saturation slider
            var satGroup = this._buildSlider(instance, 'saturation', 'Saturation', 0, 100, instance.currentHSL.s, '%');
            sliders.appendChild(satGroup);

            // Lightness slider
            var lightGroup = this._buildSlider(instance, 'lightness', 'Lightness', 0, 100, instance.currentHSL.l, '%');
            sliders.appendChild(lightGroup);

            // Alpha slider (if enabled)
            if (instance.config.showAlpha) {
                var alphaGroup = this._buildSlider(instance, 'alpha', 'Opacity', 0, 100, instance.currentAlpha * 100, '%');
                sliders.appendChild(alphaGroup);
            }

            return sliders;
        },

        /**
         * Build a single slider
         */
        _buildSlider: function(instance, type, label, min, max, value, suffix) {
            var group = document.createElement('div');
            group.className = 'rsl-color-picker-slider-group';

            var labelEl = document.createElement('div');
            labelEl.className = 'rsl-color-picker-slider-label';

            var labelText = document.createElement('span');
            labelText.textContent = label;
            labelEl.appendChild(labelText);

            var valueDisplay = document.createElement('span');
            valueDisplay.className = 'rsl-color-picker-slider-value';
            valueDisplay.textContent = Math.round(value) + suffix;
            labelEl.appendChild(valueDisplay);

            group.appendChild(labelEl);

            var slider = document.createElement('input');
            slider.type = 'range';
            slider.className = 'rsl-color-picker-slider';
            slider.setAttribute('data-type', type);
            slider.min = min;
            slider.max = max;
            slider.value = value;
            slider.setAttribute('aria-label', label);
            slider.setAttribute('aria-valuemin', min);
            slider.setAttribute('aria-valuemax', max);
            slider.setAttribute('aria-valuenow', value);
            slider.setAttribute('aria-valuetext', Math.round(value) + suffix);

            group.appendChild(slider);

            // Store references
            instance[type + 'Slider'] = slider;
            instance[type + 'Value'] = valueDisplay;

            return group;
        },

        /**
         * Build hex input with eyedropper
         */
        _buildHexInput: function(instance) {
            var self = this;
            var group = document.createElement('div');
            group.className = 'rsl-color-picker-input-group';

            var input = document.createElement('input');
            input.type = 'text';
            input.className = 'rsl-color-picker-hex-input';
            input.placeholder = '#000000';
            input.value = instance.currentColor || '';
            input.setAttribute('aria-label', 'Hex color value');
            input.setAttribute('autocomplete', 'off');
            input.setAttribute('spellcheck', 'false');
            group.appendChild(input);
            instance.hexInput = input;

            // Eyedropper button (if supported)
            if ('EyeDropper' in window) {
                var eyedropper = document.createElement('button');
                eyedropper.type = 'button';
                eyedropper.className = 'rsl-color-picker-eyedropper';
                eyedropper.setAttribute('aria-label', 'Pick color from screen');
                eyedropper.innerHTML = '<i class="fas fa-eye-dropper" aria-hidden="true"></i>';
                group.appendChild(eyedropper);
                instance.eyedropperBtn = eyedropper;
            }

            return group;
        },

        /**
         * Build preview and contrast section
         */
        _buildPreviewSection: function(instance) {
            var config = instance.config;
            var section = document.createElement('div');
            section.className = 'rsl-color-picker-preview-section';

            // Text preview
            if (config.showPreview) {
                var preview = document.createElement('div');
                preview.className = 'rsl-color-picker-preview';

                var fgPreview = document.createElement('div');
                fgPreview.className = 'rsl-color-picker-preview-box foreground';
                fgPreview.style.setProperty('--preview-bg', config.contrastAgainst);
                fgPreview.style.setProperty('--preview-color', instance.currentColor || '#000000');
                fgPreview.textContent = 'Text Preview';
                preview.appendChild(fgPreview);
                instance.fgPreview = fgPreview;

                var bgPreview = document.createElement('div');
                bgPreview.className = 'rsl-color-picker-preview-box background';
                bgPreview.style.setProperty('--preview-bg', config.contrastAgainst);
                bgPreview.style.setProperty('--preview-color', instance.currentColor || '#000000');
                bgPreview.textContent = 'Background Preview';
                preview.appendChild(bgPreview);
                instance.bgPreview = bgPreview;

                section.appendChild(preview);
            }

            // Contrast info
            if (config.showContrast) {
                var contrastInfo = document.createElement('div');
                contrastInfo.className = 'rsl-color-picker-contrast-info';

                var ratio = document.createElement('span');
                ratio.className = 'rsl-color-picker-contrast-ratio';
                ratio.textContent = '—:1';
                contrastInfo.appendChild(ratio);
                instance.contrastRatio = ratio;

                var badges = document.createElement('div');
                badges.className = 'rsl-color-picker-contrast-badges';
                contrastInfo.appendChild(badges);
                instance.contrastBadges = badges;

                section.appendChild(contrastInfo);
            }

            instance.previewSection = section;
            return section;
        },

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

            // Trigger click
            instance.trigger.addEventListener('click', function() {
                if (instance.isOpen) {
                    self.close(instance);
                } else {
                    self.open(instance);
                }
            });

            // Close button
            instance.closeBtn.addEventListener('click', function() {
                self.close(instance);
            });

            // Cancel button
            instance.cancelBtn.addEventListener('click', function() {
                self.close(instance);
            });

            // Apply button
            instance.applyBtn.addEventListener('click', function() {
                self._applyColor(instance);
                self.close(instance);
            });

            // Tab switching
            if (instance.paletteTab) {
                instance.paletteTab.addEventListener('click', function() {
                    self._switchTab(instance, 'palette');
                });
            }

            if (instance.customTab) {
                instance.customTab.addEventListener('click', function() {
                    self._switchTab(instance, 'custom');
                });
            }

            // Palette swatch clicks and keyboard
            instance.palette.addEventListener('click', function(e) {
                var swatch = e.target.closest('.rsl-color-picker-swatch');
                if (swatch && !swatch.classList.contains('disabled')) {
                    self._selectColor(instance, swatch.dataset.color, swatch.dataset.name);
                }
            });

            instance.palette.addEventListener('keydown', function(e) {
                self._handlePaletteKeydown(instance, e);
            });

            // Recent swatch clicks
            if (instance.recentSwatches) {
                instance.recentSwatches.addEventListener('click', function(e) {
                    var swatch = e.target.closest('.rsl-color-picker-recent-swatch');
                    if (swatch) {
                        self._selectColor(instance, swatch.dataset.color);
                    }
                });
            }

            // Slider changes
            ['hue', 'saturation', 'lightness', 'alpha'].forEach(function(type) {
                var slider = instance[type + 'Slider'];
                if (slider) {
                    slider.addEventListener('input', function() {
                        self._handleSliderChange(instance, type, this.value);
                    });
                }
            });

            // Hex input
            if (instance.hexInput) {
                instance.hexInput.addEventListener('input', function() {
                    self._handleHexInput(instance, this.value);
                });

                instance.hexInput.addEventListener('blur', function() {
                    self._validateHexInput(instance, this.value);
                });

                instance.hexInput.addEventListener('keydown', function(e) {
                    if (e.key === 'Enter') {
                        e.preventDefault();
                        self._validateHexInput(instance, this.value);
                        self._applyColor(instance);
                        self.close(instance);
                    }
                });
            }

            // Eyedropper
            if (instance.eyedropperBtn) {
                instance.eyedropperBtn.addEventListener('click', function() {
                    self._openEyedropper(instance);
                });
            }

            // Outside click - use mousedown like date picker
            document.addEventListener('mousedown', function(e) {
                if (instance.isOpen && !instance.container.contains(e.target)) {
                    // Apply the current color before closing
                    if (instance.currentColor) {
                        self._applyColor(instance);
                    }
                    self.close(instance);
                }
            });

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

        /**
         * Handle palette keyboard navigation
         */
        _handlePaletteKeydown: function(instance, e) {
            var swatches = Array.from(instance.swatches);
            var currentIndex = swatches.findIndex(function(s) {
                return s.getAttribute('tabindex') === '0';
            });
            var newIndex = currentIndex;
            var cols = 6; // Assume 6 columns

            switch (e.key) {
                case 'ArrowRight':
                    newIndex = Math.min(currentIndex + 1, swatches.length - 1);
                    break;
                case 'ArrowLeft':
                    newIndex = Math.max(currentIndex - 1, 0);
                    break;
                case 'ArrowDown':
                    newIndex = Math.min(currentIndex + cols, swatches.length - 1);
                    break;
                case 'ArrowUp':
                    newIndex = Math.max(currentIndex - cols, 0);
                    break;
                case 'Home':
                    newIndex = 0;
                    break;
                case 'End':
                    newIndex = swatches.length - 1;
                    break;
                case 'Enter':
                case ' ':
                    e.preventDefault();
                    var swatch = swatches[currentIndex];
                    if (swatch) {
                        this._selectColor(instance, swatch.dataset.color, swatch.dataset.name);
                    }
                    return;
                default:
                    return;
            }

            e.preventDefault();

            // Update tabindex
            if (swatches[currentIndex]) {
                swatches[currentIndex].setAttribute('tabindex', '-1');
            }
            if (swatches[newIndex]) {
                swatches[newIndex].setAttribute('tabindex', '0');
                swatches[newIndex].focus();
            }
        },

        /**
         * Switch between tabs
         */
        _switchTab: function(instance, tab) {
            if (tab === 'palette') {
                instance.paletteTab.setAttribute('aria-selected', 'true');
                instance.customTab.setAttribute('aria-selected', 'false');
                instance.palettePanel.style.display = 'block';
                instance.customPanel.classList.remove('active');
            } else {
                instance.paletteTab.setAttribute('aria-selected', 'false');
                instance.customTab.setAttribute('aria-selected', 'true');
                instance.palettePanel.style.display = 'none';
                instance.customPanel.classList.add('active');
            }
        },

        /**
         * Select a color from palette
         */
        _selectColor: function(instance, hex, name) {
            var self = this;
            instance.currentColor = hex;
            instance.currentHSL = this._hexToHSL(hex);

            // Update palette selection
            instance.palette.querySelectorAll('.rsl-color-picker-swatch').forEach(function(s) {
                var isSelected = s.dataset.color.toUpperCase() === hex.toUpperCase();
                s.setAttribute('aria-selected', isSelected ? 'true' : 'false');

                // Remove existing checkmark
                var existing = s.querySelector('.check-icon');
                if (existing) existing.remove();

                // Add checkmark if selected
                if (isSelected) {
                    var checkIcon = document.createElement('i');
                    checkIcon.className = 'fas fa-check check-icon';
                    checkIcon.setAttribute('aria-hidden', 'true');
                    s.appendChild(checkIcon);
                }
            });

            // Update sliders
            this._updateSliders(instance);

            // Update hex input
            if (instance.hexInput) {
                instance.hexInput.value = hex;
            }

            // Update preview
            this._updatePreview(instance);

            // Announce to screen reader
            var contrast = this.getContrastRatio(hex, instance.config.contrastAgainst);
            var wcag = this.getWCAGStatus(contrast);
            var announcement = (name || hex) + ' selected. Contrast ratio ' + contrast.toFixed(1) + ' to 1. ';
            announcement += wcag.normalAA ? 'Passes WCAG AA.' : 'Fails WCAG AA.';
            this._announce(instance, announcement);

            // Close on select if configured
            if (instance.config.closeOnSelect) {
                this._applyColor(instance);
                this.close(instance);
                instance.trigger.focus();
            }
        },

        /**
         * Handle slider change
         */
        _handleSliderChange: function(instance, type, value) {
            value = parseFloat(value);

            if (type === 'hue') {
                instance.currentHSL.h = value;
            } else if (type === 'saturation') {
                instance.currentHSL.s = value;
            } else if (type === 'lightness') {
                instance.currentHSL.l = value;
            } else if (type === 'alpha') {
                instance.currentAlpha = value / 100;
            }

            // Update value display
            var suffix = type === 'hue' ? '°' : '%';
            instance[type + 'Value'].textContent = Math.round(value) + suffix;

            // Update current color
            instance.currentColor = this._hslToHex(instance.currentHSL.h, instance.currentHSL.s, instance.currentHSL.l);

            // Update hex input
            if (instance.hexInput) {
                instance.hexInput.value = instance.currentColor;
            }

            // Update slider backgrounds
            this._updateSliderBackgrounds(instance);

            // Update preview
            this._updatePreview(instance);
        },

        /**
         * Handle hex input
         */
        _handleHexInput: function(instance, value) {
            // Normalize input
            value = value.trim();
            if (!value.startsWith('#') && value.length > 0) {
                value = '#' + value;
            }

            // Validate
            if (this._isValidHex(value)) {
                instance.hexInput.classList.remove('invalid');
                instance.currentColor = this._normalizeColor(value);
                instance.currentHSL = this._hexToHSL(instance.currentColor);
                this._updateSliders(instance);
                this._updatePreview(instance);
            } else if (value.length > 1) {
                instance.hexInput.classList.add('invalid');
            }
        },

        /**
         * Validate hex input on blur
         */
        _validateHexInput: function(instance, value) {
            if (!this._isValidHex(value)) {
                instance.hexInput.value = instance.currentColor || '';
                instance.hexInput.classList.remove('invalid');
            }
        },

        /**
         * Open eyedropper
         */
        _openEyedropper: function(instance) {
            var self = this;
            if ('EyeDropper' in window) {
                var eyeDropper = new EyeDropper();
                eyeDropper.open().then(function(result) {
                    self._selectColor(instance, result.sRGBHex);
                }).catch(function(e) {
                    // User cancelled or error
                });
            }
        },

        /**
         * Update sliders to match current color
         */
        _updateSliders: function(instance) {
            if (instance.hueSlider) {
                instance.hueSlider.value = instance.currentHSL.h;
                instance.hueValue.textContent = Math.round(instance.currentHSL.h) + '°';
            }
            if (instance.saturationSlider) {
                instance.saturationSlider.value = instance.currentHSL.s;
                instance.saturationValue.textContent = Math.round(instance.currentHSL.s) + '%';
            }
            if (instance.lightnessSlider) {
                instance.lightnessSlider.value = instance.currentHSL.l;
                instance.lightnessValue.textContent = Math.round(instance.currentHSL.l) + '%';
            }
            this._updateSliderBackgrounds(instance);
        },

        /**
         * Update slider background gradients
         */
        _updateSliderBackgrounds: function(instance) {
            var h = instance.currentHSL.h;
            var s = instance.currentHSL.s;
            var l = instance.currentHSL.l;

            if (instance.saturationSlider) {
                instance.saturationSlider.style.background = 'linear-gradient(to right, hsl(' + h + ', 0%, 50%), hsl(' + h + ', 100%, 50%))';
            }
            if (instance.lightnessSlider) {
                instance.lightnessSlider.style.background = 'linear-gradient(to right, hsl(' + h + ', ' + s + '%, 0%), hsl(' + h + ', ' + s + '%, 50%), hsl(' + h + ', ' + s + '%, 100%))';
            }
        },

        /**
         * Update preview section
         */
        _updatePreview: function(instance) {
            var config = instance.config;
            var color = instance.currentColor || '#000000';

            // Update preview boxes
            if (instance.fgPreview) {
                instance.fgPreview.style.setProperty('--preview-color', color);
            }
            if (instance.bgPreview) {
                instance.bgPreview.style.setProperty('--preview-color', color);
            }

            // Update contrast info
            if (config.showContrast) {
                var contrast = this.getContrastRatio(color, config.contrastAgainst);
                var wcag = this.getWCAGStatus(contrast);

                instance.contrastRatio.textContent = contrast.toFixed(2) + ':1';

                // Build badges
                var badges = '';
                badges += '<span class="rsl-color-picker-wcag-badge ' + (wcag.normalAA ? 'pass' : 'fail') + '">';
                badges += '<i class="fas fa-' + (wcag.normalAA ? 'check' : 'times') + ' icon" aria-hidden="true"></i> AA Normal';
                badges += '</span>';

                badges += '<span class="rsl-color-picker-wcag-badge ' + (wcag.largeAA ? 'pass' : 'fail') + '">';
                badges += '<i class="fas fa-' + (wcag.largeAA ? 'check' : 'times') + ' icon" aria-hidden="true"></i> AA Large';
                badges += '</span>';

                badges += '<span class="rsl-color-picker-wcag-badge ' + (wcag.normalAAA ? 'pass' : 'fail') + '">';
                badges += '<i class="fas fa-' + (wcag.normalAAA ? 'check' : 'times') + ' icon" aria-hidden="true"></i> AAA';
                badges += '</span>';

                instance.contrastBadges.innerHTML = badges;

                // Show suggestion if fails
                if (!wcag.normalAA && instance.suggestionBanner) {
                    var suggested = this.suggestAccessibleColor(color, config.contrastAgainst, 4.5);
                    if (suggested) {
                        instance.suggestionBanner.innerHTML = '<div class="rsl-color-picker-suggestion-text">This color fails WCAG AA. Try this accessible alternative:</div>' +
                            '<button type="button" class="rsl-color-picker-suggestion-color" data-color="' + suggested + '">' +
                            '<span class="rsl-color-picker-suggestion-swatch" style="--suggestion-color: ' + suggested + '"></span>' +
                            '<span>' + suggested + '</span>' +
                            '</button>';
                        instance.suggestionBanner.classList.add('visible');

                        // Attach click handler
                        var self = this;
                        instance.suggestionBanner.querySelector('.rsl-color-picker-suggestion-color').addEventListener('click', function() {
                            self._selectColor(instance, suggested);
                        });
                    }
                } else if (instance.suggestionBanner) {
                    instance.suggestionBanner.classList.remove('visible');
                }
            }

            // Update trigger preview
            instance.swatchPreview.style.setProperty('--swatch-color', color);
        },

        /**
         * Apply the selected color
         */
        _applyColor: function(instance) {
            var color = instance.currentColor;
            if (!color) return;

            // Format the output based on config
            var formattedColor = this._formatOutput(instance, color);

            // Update trigger display with formatted color
            instance.valueDisplay.textContent = formattedColor;
            instance.swatchPreview.style.setProperty('--swatch-color', color);

            // Update hidden input
            if (instance.originalInput) {
                instance.originalInput.value = formattedColor;
            }

            // Add to recent colors
            this._addToRecent(instance, color);

            // Dispatch change event on the original element
            var colorName = this._getColorName(instance, color);
            var event = new CustomEvent('rsl-color-change', {
                detail: {
                    value: this._formatOutput(instance, color),
                    hex: color,
                    name: colorName,
                    rgb: this._hexToRGB(color),
                    hsl: instance.currentHSL,
                    contrast: this.getContrastRatio(color, instance.config.contrastAgainst),
                    wcag: this.getWCAGStatus(this.getContrastRatio(color, instance.config.contrastAgainst))
                },
                bubbles: true
            });
            instance.element.dispatchEvent(event);
        },

        /**
         * Format output based on config
         */
        _formatOutput: function(instance, hex) {
            var format = instance.config.format;
            if (format === 'rgb') {
                var rgb = this._hexToRGB(hex);
                return 'rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')';
            } else if (format === 'hsl') {
                var hsl = instance.currentHSL;
                return 'hsl(' + Math.round(hsl.h) + ', ' + Math.round(hsl.s) + '%, ' + Math.round(hsl.l) + '%)';
            }
            return hex;
        },

        /**
         * Get color name from palette
         */
        _getColorName: function(instance, hex) {
            var self = this;
            var normalizedHex = hex.toUpperCase();

            // Check in current palette
            var paletteKey = instance.config.palette;
            var palette = this.palettes[paletteKey] || this.palettes.default;

            for (var i = 0; i < palette.length; i++) {
                if (palette[i].hex.toUpperCase() === normalizedHex) {
                    return palette[i].name;
                }
            }

            // Check in all palettes as fallback
            var allPalettes = Object.keys(this.palettes);
            for (var j = 0; j < allPalettes.length; j++) {
                var p = this.palettes[allPalettes[j]];
                for (var k = 0; k < p.length; k++) {
                    if (p[k].hex.toUpperCase() === normalizedHex) {
                        return p[k].name;
                    }
                }
            }

            return null; // Custom color without a name
        },

        /**
         * Open the color picker dialog
         * @param {string|Element|Object} selector - Selector, element, or instance
         */
        open: function(selector) {
            var instance = this._resolveInstance(selector);
            if (!instance || instance.config.disabled) return;

            instance.isOpen = true;
            instance.trigger.setAttribute('aria-expanded', 'true');
            instance.dialog.classList.add('open');

            // Focus first swatch or hex input
            var firstFocusable = instance.palette.querySelector('[tabindex="0"]') || instance.hexInput;
            if (firstFocusable) {
                setTimeout(function() {
                    firstFocusable.focus();
                }, 100);
            }

            this._announce(instance, 'Color picker opened');
        },

        /**
         * Close the color picker dialog
         * @param {string|Element|Object} selector - Selector, element, or instance
         */
        close: function(selector) {
            var instance = this._resolveInstance(selector);
            if (!instance) return;
            instance.isOpen = false;
            instance.trigger.setAttribute('aria-expanded', 'false');
            instance.dialog.classList.remove('open');
            this._announce(instance, 'Color picker closed');
        },

        /**
         * Get the current value
         * @param {string|Element|Object} selector - Selector, element, or instance
         */
        getValue: function(selector) {
            var instance = this._resolveInstance(selector);
            if (!instance) return null;
            return instance.currentColor ? this._formatOutput(instance, instance.currentColor) : null;
        },

        /**
         * Set the color value
         * @param {string|Element|Object} selector - Selector, element, or instance
         * @param {string} color - Color value
         */
        setValue: function(selector, color) {
            var instance = this._resolveInstance(selector);
            if (!instance || !color) return;
            this._selectColor(instance, this._normalizeColor(color));
            this._applyColor(instance);
        },

        /**
         * Clear the current value
         * @param {string|Element|Object} selector - Selector, element, or instance
         */
        clear: function(selector) {
            var instance = this._resolveInstance(selector);
            if (!instance) return;
            instance.currentColor = null;
            instance.currentHSL = null;
            instance.valueDisplay.textContent = instance.config.placeholder;
            instance.swatchPreview.style.removeProperty('--swatch-color');
            if (instance.originalInput) {
                instance.originalInput.value = '';
            }
            // Dispatch clear event
            var event = new CustomEvent('rsl-color-clear', { bubbles: true });
            instance.element.dispatchEvent(event);
        },

        /**
         * Get instance by element
         */
        getInstance: function(element) {
            if (typeof element === 'string') {
                element = document.querySelector(element);
            }
            return this.instances.get(element);
        },

        /**
         * Resolve selector/element/instance to an instance
         */
        _resolveInstance: function(selector) {
            if (!selector) return null;
            // Already an instance object
            if (selector.element && selector.config) return selector;
            // Selector string or element
            return this.getInstance(selector);
        },

        // ============================================
        // Color Utility Functions
        // ============================================

        /**
         * Calculate contrast ratio between two colors
         * @param {string} fg - Foreground color (hex)
         * @param {string} bg - Background color (hex)
         * @returns {number} Contrast ratio
         */
        getContrastRatio: function(fg, bg) {
            var fgLum = this._getLuminance(fg);
            var bgLum = this._getLuminance(bg);
            var lighter = Math.max(fgLum, bgLum);
            var darker = Math.min(fgLum, bgLum);
            return (lighter + 0.05) / (darker + 0.05);
        },

        /**
         * Get WCAG compliance status
         * @param {number} ratio - Contrast ratio
         * @returns {Object} Status object
         */
        getWCAGStatus: function(ratio) {
            return {
                normalAA: ratio >= 4.5,   // Normal text AA
                largeAA: ratio >= 3,      // Large text AA
                normalAAA: ratio >= 7,    // Normal text AAA
                largeAAA: ratio >= 4.5,   // Large text AAA
                uiAA: ratio >= 3          // UI components AA
            };
        },

        /**
         * Suggest an accessible alternative color
         * @param {string} color - Original color (hex)
         * @param {string} against - Background color (hex)
         * @param {number} targetRatio - Target contrast ratio
         * @returns {string|null} Suggested color hex or null
         */
        suggestAccessibleColor: function(color, against, targetRatio) {
            var hsl = this._hexToHSL(color);
            var bgLum = this._getLuminance(against);

            // Determine if we need to go darker or lighter
            var colorLum = this._getLuminance(color);
            var goLighter = bgLum < 0.5;

            // Adjust lightness until we hit target
            for (var i = 0; i <= 100; i++) {
                var testL = goLighter ? Math.min(100, hsl.l + i) : Math.max(0, hsl.l - i);
                var testHex = this._hslToHex(hsl.h, hsl.s, testL);
                var testRatio = this.getContrastRatio(testHex, against);

                if (testRatio >= targetRatio) {
                    return testHex;
                }
            }

            // Fallback: return black or white
            return goLighter ? '#FFFFFF' : '#000000';
        },

        /**
         * Get relative luminance
         */
        _getLuminance: function(hex) {
            var rgb = this._hexToRGB(hex);
            var r = rgb.r / 255;
            var g = rgb.g / 255;
            var b = rgb.b / 255;

            r = r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4);
            g = g <= 0.03928 ? g / 12.92 : Math.pow((g + 0.055) / 1.055, 2.4);
            b = b <= 0.03928 ? b / 12.92 : Math.pow((b + 0.055) / 1.055, 2.4);

            return 0.2126 * r + 0.7152 * g + 0.0722 * b;
        },

        /**
         * Convert hex to RGB
         */
        _hexToRGB: function(hex) {
            hex = hex.replace('#', '');
            if (hex.length === 3) {
                hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
            }
            return {
                r: parseInt(hex.substr(0, 2), 16),
                g: parseInt(hex.substr(2, 2), 16),
                b: parseInt(hex.substr(4, 2), 16)
            };
        },

        /**
         * Convert RGB to hex
         */
        _rgbToHex: function(r, g, b) {
            var toHex = function(c) {
                var hex = Math.round(c).toString(16);
                return hex.length === 1 ? '0' + hex : hex;
            };
            return '#' + toHex(r) + toHex(g) + toHex(b);
        },

        /**
         * Convert hex to HSL
         */
        _hexToHSL: function(hex) {
            var rgb = this._hexToRGB(hex);
            var r = rgb.r / 255;
            var g = rgb.g / 255;
            var b = rgb.b / 255;

            var max = Math.max(r, g, b);
            var min = Math.min(r, g, b);
            var h, s, l = (max + min) / 2;

            if (max === min) {
                h = s = 0;
            } else {
                var d = max - min;
                s = l > 0.5 ? d / (2 - max - min) : d / (max + min);

                switch (max) {
                    case r:
                        h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
                        break;
                    case g:
                        h = ((b - r) / d + 2) / 6;
                        break;
                    case b:
                        h = ((r - g) / d + 4) / 6;
                        break;
                }
            }

            return {
                h: h * 360,
                s: s * 100,
                l: l * 100
            };
        },

        /**
         * Convert HSL to hex
         */
        _hslToHex: function(h, s, l) {
            h = h / 360;
            s = s / 100;
            l = l / 100;

            var r, g, b;

            if (s === 0) {
                r = g = b = l;
            } else {
                var hue2rgb = function(p, q, t) {
                    if (t < 0) t += 1;
                    if (t > 1) t -= 1;
                    if (t < 1/6) return p + (q - p) * 6 * t;
                    if (t < 1/2) return q;
                    if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
                    return p;
                };

                var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
                var p = 2 * l - q;
                r = hue2rgb(p, q, h + 1/3);
                g = hue2rgb(p, q, h);
                b = hue2rgb(p, q, h - 1/3);
            }

            return this._rgbToHex(r * 255, g * 255, b * 255);
        },

        /**
         * Normalize color to uppercase hex
         */
        _normalizeColor: function(color) {
            if (!color) return null;
            color = color.trim();

            // Handle hex
            if (color.startsWith('#')) {
                color = color.toUpperCase();
                if (color.length === 4) {
                    // Expand 3-digit hex
                    color = '#' + color[1] + color[1] + color[2] + color[2] + color[3] + color[3];
                }
                return color;
            }

            // Handle rgb()
            if (color.startsWith('rgb')) {
                var match = color.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
                if (match) {
                    return this._rgbToHex(parseInt(match[1]), parseInt(match[2]), parseInt(match[3]));
                }
            }

            // Handle color names (basic)
            var colorNames = {
                'black': '#000000',
                'white': '#FFFFFF',
                'red': '#FF0000',
                'green': '#00FF00',
                'blue': '#0000FF'
            };
            if (colorNames[color.toLowerCase()]) {
                return colorNames[color.toLowerCase()];
            }

            return color.toUpperCase();
        },

        /**
         * Check if valid hex color
         */
        _isValidHex: function(hex) {
            return /^#([0-9A-Fa-f]{3}){1,2}$/.test(hex);
        },

        /**
         * Get palette colors
         */
        _getPaletteColors: function(palette) {
            if (Array.isArray(palette)) {
                return palette;
            }
            return this.palettes[palette] || this.palettes.default;
        },

        /**
         * Load recent colors from storage
         */
        _loadRecentColors: function(instance) {
            try {
                var stored = localStorage.getItem(instance.config.recentStorageKey);
                if (stored) {
                    instance.recentColors = JSON.parse(stored);
                }
            } catch (e) {
                instance.recentColors = [];
            }
        },

        /**
         * Add color to recent
         */
        _addToRecent: function(instance, color) {
            // Remove if exists
            var index = instance.recentColors.indexOf(color);
            if (index > -1) {
                instance.recentColors.splice(index, 1);
            }

            // Add to front
            instance.recentColors.unshift(color);

            // Limit length
            if (instance.recentColors.length > instance.config.maxRecent) {
                instance.recentColors = instance.recentColors.slice(0, instance.config.maxRecent);
            }

            // Save to storage
            try {
                localStorage.setItem(instance.config.recentStorageKey, JSON.stringify(instance.recentColors));
            } catch (e) {
                // Storage not available
            }
        },

        /**
         * Announce to screen readers
         */
        _announce: function(instance, message) {
            if (instance.liveRegion) {
                instance.liveRegion.textContent = message;
            }
        }
    };

    // Auto-initialize on DOMContentLoaded
    document.addEventListener('DOMContentLoaded', function() {
        window.RSL.ColorPicker.init();
    });

})();
