<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Dual Scroll-Wheel Time Picker</title>

    <style>

        * {

            margin: 0;

            padding: 0;

            box-sizing: border-box;

        }

        body {

            background: #000000;

            font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;

            color: white;

            overflow: hidden;

            height: 100vh;

            display: flex;

            align-items: center;

            justify-content: center;

            user-select: none;

            -webkit-user-select: none;

        }

        .time-picker {

            position: relative;

            width: 320px;

            height: 400px;

            display: flex;

            flex-direction: column;

        }

        .wheels-container {

            flex: 1;

            display: flex;

            align-items: center;

            justify-content: center;

            position: relative;

            padding: 40px 0;

        }

        .wheel-wrapper {

            width: 120px;

            height: 240px;

            position: relative;

            overflow: hidden;

        }

        .wheel-wrapper::before,

        .wheel-wrapper::after {

            content: '';

            position: absolute;

            left: 0;

            right: 0;

            height: 80px;

            pointer-events: none;

            z-index: 10;

        }

        .wheel-wrapper::before {

            top: 0;

            background: linear-gradient(to bottom, #000000 0%, transparent 100%);

        }

        .wheel-wrapper::after {

            bottom: 0;

            background: linear-gradient(to top, #000000 0%, transparent 100%);

        }

        .wheel {

            position: absolute;

            width: 100%;

            touch-action: pan-y;

            cursor: grab;

            will-change: transform;

        }

        .wheel:active {

            cursor: grabbing;

        }

        .wheel-item {

            height: 80px;

            display: flex;

            align-items: center;

            justify-content: center;

            position: relative;

            transition: all 0.3s ease-out;

        }

        .wheel-item span {

            font-weight: 400;

            font-size: 32px;

            opacity: 0.3;

            text-shadow: 0 0 2px rgba(255, 255, 255, 0.3);

            -webkit-text-stroke: 0.5px rgba(255, 255, 255, 0.2);

            transition: all 0.3s ease-out;

        }

        .wheel-item.selected span {

            font-weight: 700;

            font-size: 48px;

            opacity: 1;

            animation: glow-pulse 3s ease-in-out infinite;

        }

        @keyframes glow-pulse {

            0%, 100% {

                text-shadow: 

                    0 0 10px rgba(255, 255, 255, 0.6),

                    0 0 20px rgba(255, 255, 255, 0.4),

                    0 0 30px rgba(255, 255, 255, 0.2);

            }

            50% {

                text-shadow: 

                    0 0 15px rgba(255, 255, 255, 0.8),

                    0 0 25px rgba(255, 255, 255, 0.6),

                    0 0 35px rgba(255, 255, 255, 0.4);

            }

        }

        .colon {

            font-size: 48px;

            font-weight: 700;

            margin: 0 20px;

            opacity: 0.8;

        }

        .lock-button {

            position: absolute;

            bottom: 0;

            left: 0;

            right: 0;

            height: 60px;

            background: #FF6B35;

            border: none;

            border-radius: 8px 8px 0 0;

            color: white;

            font-size: 18px;

            font-weight: 700;

            cursor: pointer;

            transition: all 0.2s ease;

        }

        .lock-button:hover {

            background: #FF7F50;

        }

        .lock-button:active {

            transform: scale(0.98);

        }

        .confirmation-panel {

            position: fixed;

            bottom: -40vh;

            left: 0;

            right: 0;

            height: 40vh;

            background: #1a1a1a;

            border-radius: 24px 24px 0 0;

            padding: 24px;

            transition: bottom 0.3s ease-out;

            z-index: 100;

        }

        .confirmation-panel.active {

            bottom: 0;

        }

        .time-options {

            display: flex;

            gap: 12px;

            justify-content: center;

            margin-top: 24px;

            flex-wrap: wrap;

        }

        .time-option {

            padding: 12px 20px;

            border: 1px solid rgba(255, 255, 255, 0.2);

            border-radius: 8px;

            background: rgba(255, 255, 255, 0.05);

            cursor: pointer;

            transition: all 0.2s ease;

        }

        .time-option:hover {

            background: rgba(255, 255, 255, 0.1);

            border-color: rgba(255, 255, 255, 0.4);

        }

        .close-panel {

            position: absolute;

            top: 12px;

            right: 12px;

            background: none;

            border: none;

            color: white;

            font-size: 24px;

            cursor: pointer;

            opacity: 0.6;

            transition: opacity 0.2s ease;

        }

        .close-panel:hover {

            opacity: 1;

        }

        .sr-only {

            position: absolute;

            width: 1px;

            height: 1px;

            padding: 0;

            margin: -1px;

            overflow: hidden;

            clip: rect(0, 0, 0, 0);

            white-space: nowrap;

            border-width: 0;

        }

    </style>

</head>

<body>

    <div class="time-picker" role="group" aria-label="Time picker">

        <div class="wheels-container">

            <div class="wheel-wrapper">

                <div class="wheel hours-wheel" role="listbox" aria-label="Hours" tabindex="0"></div>

            </div>

            <div class="colon">:</div>

            <div class="wheel-wrapper">

                <div class="wheel minutes-wheel" role="listbox" aria-label="Minutes" tabindex="0"></div>

            </div>

        </div>

        <button class="lock-button" aria-label="Lock selected time">Lock</button>

        <div class="sr-only" aria-live="polite" aria-atomic="true" id="time-announcement"></div>

    </div>

    <div class="confirmation-panel" role="dialog" aria-label="Time selection confirmation">

        <button class="close-panel" aria-label="Close panel">&times;</button>

        <h3 style="text-align: center; margin-bottom: 16px;">Quick Time Selection</h3>

        <div class="time-options">

            <div class="time-option" data-time="00:00">00:00</div>

            <div class="time-option" data-time="06:00">06:00</div>

            <div class="time-option" data-time="12:00">12:00</div>

            <div class="time-option" data-time="18:00">18:00</div>

            <div class="time-option" data-time="22:00">22:00</div>

        </div>

    </div>

    <script>

        class TimePickerWheel {

            constructor(element, max, onChange) {

                this.element = element;

                this.max = max;

                this.onChange = onChange;

                this.value = 0;

                this.position = 0;

                this.velocity = 0;

                this.isDragging = false;

                this.startY = 0;

                this.startPosition = 0;

                this.itemHeight = 80;

                this.friction = 0.95;

                this.snapThreshold = 0.5;

                

                this.init();

            }

            init() {

                this.renderItems();

                this.attachEvents();

                this.updatePosition(0);

            }

            renderItems() {

                const itemsToRender = this.max + 6; // Extra items for smooth looping

                let html = '';

                

                for (let i = -3; i < itemsToRender; i++) {

                    const value = this.mod(i, this.max + 1);

                    html += `<div class="wheel-item" data-value="${value}" role="option">

                        <span>${value.toString().padStart(2, '0')}</span>

                    </div>`;

                }

                

                this.element.innerHTML = html;

                this.items = this.element.querySelectorAll('.wheel-item');

            }

            mod(n, m) {

                return ((n % m) + m) % m;

            }

            attachEvents() {

                // Touch events

                this.element.addEventListener('touchstart', this.handleStart.bind(this), { passive: false });

                this.element.addEventListener('touchmove', this.handleMove.bind(this), { passive: false });

                this.element.addEventListener('touchend', this.handleEnd.bind(this));

                

                // Mouse events

                this.element.addEventListener('mousedown', this.handleStart.bind(this));

                this.element.addEventListener('mousemove', this.handleMove.bind(this));

                this.element.addEventListener('mouseup', this.handleEnd.bind(this));

                this.element.addEventListener('mouseleave', this.handleEnd.bind(this));

                

                // Keyboard events

                this.element.addEventListener('keydown', this.handleKeydown.bind(this));

            }

            handleStart(e) {

                e.preventDefault();

                this.isDragging = true;

                this.velocity = 0;

                this.startY = e.touches ? e.touches[0].clientY : e.clientY;

                this.startPosition = this.position;

                

                if (this.animationFrame) {

                    cancelAnimationFrame(this.animationFrame);

                }

            }

            handleMove(e) {

                if (!this.isDragging) return;

                e.preventDefault();

                

                const currentY = e.touches ? e.touches[0].clientY : e.clientY;

                const deltaY = currentY - this.startY;

                this.position = this.startPosition + deltaY;

                

                this.velocity = deltaY - (this.lastDeltaY || 0);

                this.lastDeltaY = deltaY;

                

                this.updatePosition(this.position);

            }

            handleEnd() {

                if (!this.isDragging) return;

                this.isDragging = false;

                this.lastDeltaY = 0;

                

                this.animateInertia();

            }

            handleKeydown(e) {

                if (e.key === 'ArrowUp') {

                    e.preventDefault();

                    this.setValue(this.mod(this.value - 1, this.max + 1));

                } else if (e.key === 'ArrowDown') {

                    e.preventDefault();

                    this.setValue(this.mod(this.value + 1, this.max + 1));

                }

            }

            animateInertia() {

                if (Math.abs(this.velocity) > this.snapThreshold) {

                    this.position += this.velocity;

                    this.velocity *= this.friction;

                    this.updatePosition(this.position);

                    this.animationFrame = requestAnimationFrame(() => this.animateInertia());

                } else {

                    this.snapToNearest();

                }

            }

            snapToNearest() {

                const targetIndex = Math.round(-this.position / this.itemHeight);

                const targetPosition = -targetIndex * this.itemHeight;

                

                this.animateToPosition(targetPosition, () => {

                    const newValue = this.mod(targetIndex, this.max + 1);

                    if (newValue !== this.value) {

                        this.value = newValue;

                        this.onChange(this.value);

                    }

                });

            }

            animateToPosition(target, callback) {

                const start = this.position;

                const distance = target - start;

                const duration = 300;

                const startTime = performance.now();

                

                const animate = (currentTime) => {

                    const elapsed = currentTime - startTime;

                    const progress = Math.min(elapsed / duration, 1);

                    const easeOut = 1 - Math.pow(1 - progress, 3);

                    

                    this.position = start + distance * easeOut;

                    this.updatePosition(this.position);

                    

                    if (progress < 1) {

                        requestAnimationFrame(animate);

                    } else if (callback) {

                        callback();

                    }

                };

                

                requestAnimationFrame(animate);

            }

            updatePosition(position) {

                const offset = position % (this.itemHeight * (this.max + 1));

                this.element.style.transform = translateY(${offset + this.itemHeight}px);

                

                // Calculate which item should be centered (selected)

                const centerIndex = Math.round(-position / this.itemHeight);

                

                // Update selection state

                this.items.forEach((item, index) => {

                    // Calculate the actual index this item represents

                    const itemIndex = index - 3; // Offset for the 3 padding items at start

                    const isSelected = itemIndex === centerIndex;

                    item.classList.toggle('selected', isSelected);

                });

            }

            setValue(value) {

                this.value = value;

                const targetPosition = -value * this.itemHeight;

                this.animateToPosition(targetPosition, () => {

                    this.onChange(this.value);

                });

            }

            getValue() {

                return this.value;

            }

        }

        // Initialize time picker

        const hoursWheel = new TimePickerWheel(

            document.querySelector('.hours-wheel'),

            23,

            (value) => updateTime('hours', value)

        );

        const minutesWheel = new TimePickerWheel(

            document.querySelector('.minutes-wheel'),

            59,

            (value) => updateTime('minutes', value)

        );

        let currentTime = { hours: 0, minutes: 0 };

        function updateTime(type, value) {

            currentTime[type] = value;

            announceTime();

            

            // Emit custom event

            window.dispatchEvent(new CustomEvent('timechange', {

                detail: { hours: currentTime.hours, minutes: currentTime.minutes }

            }));

        }

        function announceTime() {

            const announcement = document.getElementById('time-announcement');

            const hours = currentTime.hours.toString().padStart(2, '0');

            const minutes = currentTime.minutes.toString().padStart(2, '0');

            announcement.textContent = Selected time: ${hours}:${minutes};

        }

        // Lock button and confirmation panel

        const lockButton = document.querySelector('.lock-button');

        const confirmationPanel = document.querySelector('.confirmation-panel');

        const closePanel = document.querySelector('.close-panel');

        const timeOptions = document.querySelectorAll('.time-option');

        lockButton.addEventListener('click', () => {

            confirmationPanel.classList.add('active');

        });

        closePanel.addEventListener('click', () => {

            confirmationPanel.classList.remove('active');

        });

        timeOptions.forEach(option => {

            option.addEventListener('click', () => {

                const [hours, minutes] = option.dataset.time.split(':').map(Number);

                hoursWheel.setValue(hours);

                minutesWheel.setValue(minutes);

                confirmationPanel.classList.remove('active');

            });

        });

        // Initial announcement

        announceTime();

        // Prevent body scroll on mobile

        document.addEventListener('touchmove', (e) => {

            if (e.target.closest('.wheel')) {

                e.preventDefault();

            }

        }, { passive: false });

    </script>

</body>

</html>

-------

can u find out why the centered number wont glow??!?!