<div class="nueclock-wrap">
  <div class="outer-ring"></div>
  <div class="inner-outer-ring"></div>
  <div class="mid-ring"></div>
  <div class="hour"><div class="shimmer"><div></div><div></div><div></div></div></div>
  <div class="outer-inner-ring"></div>
  <div class="inner-inner-ring"></div>
</div>

<div class="minihud ">
  <div class="metal-ring"></div>
  <div class="scene">
    <div class="sky"></div>
    <div id="timeContainer" ></div>
    <div class="clouds"></div>
    <div class="clouds sec"></div>
  </div>
</div>

<svg>
  <filter id="cloud1" x="-50%" y="-50%" width="200%" height="200%">
    <feTurbulence baseFrequency="0.9" numOctaves="4" seed="2"><animate attributeName="baseFrequency" dur="20s" values="0.05;0.02" keyTimes="0; 1" repeatCount="indefinite"/></feTurbulence>
    <feOffset dx="200" dy="100" /><feDisplacementMap in="SourceGraphic" scale="20" />
  </filter>
  <filter id="cloud2" x="-50%" y="-50%" width="200%" height="200%">
    <feTurbulence baseFrequency="0.9" numOctaves="3" seed="4"><animate attributeName="baseFrequency" dur="33s" values="0.05;0.02" keyTimes="0; 1" repeatCount="indefinite"/></feTurbulence>
    <feOffset dx="200" dy="100" /><feDisplacementMap in="SourceGraphic" scale="20" />
  </filter>
</svg>
@import url('https://fonts.cdnfonts.com/css/digital-7-mono');
*{ box-sizing: border-box; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; scroll-behavior: smooth;}
html, body { height: 100%; overflow: hidden;}

html {
    filter: grayscale(1) brightness(0.5) contrast(4) brightness(1.6);
}
body {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    margin: 0;

    --clr-d: #c2d1e3;  /* midday */
    --clr-n: #35373a; /* midnight */
    --clr: var(--clr-d);
    --clr-dark: lch(from var(--clr) calc(l - 16) c h);

    background: var(--clr);
    background: linear-gradient(225deg, var(--clr), var(--clr-dark));

    font-size: calc(var(--_size) * 0.02);
    --_factor: min(600px, 100vh);
    --_size: min(var(--_factor), 100vw);

    --rotate-hour: 0;
    --pecentage-of-day: 0;
}
svg {
    height: 0; width: 0;
    overflow: hidden;
    max-width: 0px;
    max-height: 0;
}
.nueclock-wrap {
    width: 50em; height: 50em;
    border-radius: 50%;
    position: relative;
    --fox: calc( sin( ( var(--rotate-hour) + 135 ) * 1deg ) );
    --foy: calc( sin( ( var(--rotate-hour) + 45 )* 1deg ) );
    --sox: 1; --soy: 1;
    rotate: 90deg;
}
#timeContainer {
    font-family: 'Digital-7 Mono', sans-serif;
    font-size: 4.2em;
    font-weight: 1000;
    filter: blur(3px);
    opacity: 0.3;
    transition: opacity 0s; 
    text-align: center;
    position: absolute;
    
    color: #fff;
    top: 32%;
    transition: all 0.2s ease-in-out;
}
body:has( .hour.dragging ) #timeContainer {
    opacity: 0;
}
.scene * { pointer-events: none; }
.scene:hover #timeContainer {
    opacity: 0.6;
    filter: blur(1px);
}

.nueclock-wrap * { transition: transform 0.2s ease-out; }
.nueclock-wrap > * { position: absolute; left: 0; right: 0; top: 0; bottom: 0; margin: auto; }
.hour {
    width: 90%;
    height: 3%;
    transform-origin: 50% 50%;
    clip-path: polygon(-10% -400%, 50% -400%, 50% 400%, -10% 400%);
    transform: rotate(calc( 1deg * var(--rotate-hour)));    
    filter: grayscale(0.2) contrast(1.6);
    --sox: 0.5; --soy: 0.5;
    transition: width 0.2s ease-out;
}
.hour.hovered {
    width: 88%;
}

.hour, .hour::before {
    background: var(--clr-dark);
    box-shadow: 
    calc(0.4em * var(--soy) * var(--foy)) calc(0.4em * var(--sox) * var(--fox)) 0.2em -0.2em #000,
    calc(1em * var(--soy) * var(--foy)) calc(1em * var(--sox) * var(--fox)) 0.8em -0.2em #0005,
    inset calc(-0.4em * var(--soy) * var(--foy)) calc(-1em * var(--sox) * var(--fox)) 1em -0.6em #232323,
    inset calc(0.4em * var(--soy) * var(--foy)) calc(0.6em * var(--sox) * var(--fox)) 0.6em -0.5em #000a,
    inset calc(0.8em * var(--soy) * var(--foy)) calc(2em * var(--sox) * var(--fox)) 1em -0.6em #eee,
    inset calc(0.8em * var(--soy) * var(--foy)) calc(2em * var(--sox) * var(--fox)) 1em -0.1em #eee,
    inset calc(-0.8em * var(--soy) * var(--foy)) calc(-2em * var(--sox) * var(--fox)) 2em -0.1em #232323;
}

.hour::before {
    content: ''; display: block;
    width: 11%; 
    height: 400%;
    position: absolute;
    bottom: -150%;
    left: -2%;
    border-radius: 1.2em;
    --sox: 1;
    --soy: 1;
    cursor: grab;
}
.hour.dragging::before {
    cursor: grabbing;
}
.hour::after {
    content: ''; display: block;
    width: 1.2%; height: 200%;
    position: absolute;
    left: 8.8%; top: -50%;
    background: var(--clr-dark);
    font-size: 0.6em;
    box-shadow: 
    inset calc((2em * var(--foy)) + 1em) 0 1em -2em #000c,
    inset calc(-0.4em * var(--soy) * var(--foy)) calc(-1em * var(--sox) * var(--fox)) 1em -0.6em #232323,
    inset calc(0.4em * var(--soy) * var(--foy)) calc(0.6em * var(--sox) * var(--fox)) 0.6em -0.5em #000a,
    inset calc(0.8em * var(--soy) * var(--foy)) calc(2em * var(--sox) * var(--fox)) 1em -0.6em #eee,
    inset calc(0.8em * var(--soy) * var(--foy)) calc(2em * var(--sox) * var(--fox)) 1em -0.1em #eee,
    inset calc(-0.8em * var(--soy) * var(--foy)) calc(-2em * var(--sox) * var(--fox)) 2em -0.1em #232323;
}
.shimmer {
    position: absolute; left: 0; top: 0; z-index: 3;
    transform: translate(0, 0); transition: transform 2s ease, opacity 2s ease, scale 2s ease;
    animation: positionShimmer 1s linear infinite; animation-delay: calc((var(--rotate-hour) / 360) * -1s); animation-play-state: paused;
    opacity: 0.8;
    pointer-events: none;
}
@keyframes positionShimmer {
    0%    { opacity: 1;   transform: translate(-4.2em, -1.6em);  /* top right corner */ }
    12.5% { opacity: 1;   transform: translate(-4.8em, 0.5em);   /* top middle */ }
    25%   { opacity: 1;   transform: translate(-4.2em, 3.6em);   /* top left corner */ }
    37.5% { opacity: 1;   transform: translate(-2.2em, 3.7em);   /* left middle */ }
    50%   { opacity: 0.6; transform: translate(-0.4em, 3.3em);   /* bottom left corner */ }
    62.5% { opacity: 0.2; transform: translate(-0.2em, 0.8em);   /* bottom middle */ }
    75%   { opacity: 0.6; transform: translate(-0.4em, -1.6em);  /* bottom right corner */ }
    87.5% { opacity: 1;   transform: translate(-2.2em, -2em);    /* right middle */ }
    100%  { opacity: 1;   transform: translate(-4.2em, -1.6em);  /* back to top right corner */ }
}
.shimmer > div, .shimmer > div::before {
    --shimmer-size: 4em;
    position:absolute; left:0; right: 0; top: 0; bottom: 0; margin: auto; z-index: 100; 
    width: var(--shimmer-size); height: var(--shimmer-size);
}
.shimmer > div {
    --ani-speed: 12s; aspect-ratio: 1;
    width: calc( 2 * var(--shimmer-size));
    animation: flicker-spin var(--ani-speed) linear infinite;
}
.shimmer > div + div { animation-delay: calc( -1 * var(--ani-speed) / 3); }
.shimmer > div + div + div { animation-delay: calc( -2 * var(--ani-speed) / 3); }
.shimmer > div::before {
    content:''; display: block; width: 1em; height: 1em;
    background: #fff; filter: blur(4px);
    animation: flicker-spin calc(var(--ani-speed)/2) linear reverse infinite;
}
@keyframes flicker-spin {
    0% { border-image: radial-gradient(#fff 69%,#0000 70%) 2%/45%; rotate:0deg; }
    50% { border-image: radial-gradient(#fff 69%,#0000 70%) 0%/42%; }
    100% { border-image: radial-gradient(#fff 69%,#0000 70%) 2%/45%; rotate:360deg; }
}

.outer-ring {
    width: 63%; height: 63%; 
    border-radius: 100%;
    box-shadow: 
    -0.4em -0.4em 0.8em -0.8em #fff,
    1.4em 1.4em 1.4em 0.2em #0005,
    0.2em 0.2em 0.3em -0.1em #0005,
    inset 1.2em 1.2em 0.8em -1.2em #fff,
    inset -0.6em -0.6em 0.8em -0.2em #0005,
    inset 0em 0em 1em -0.2em #000a;
    background: #fff1;
}
.inner-outer-ring {
    width: 51%; height: 51%; 
    border-radius: 100%;
    box-shadow: 
    -0.1em -0.1em 0.2em -0.1em #000,
    inset -0.1em -0.1em 0.4em -0.1em #fff,
    inset 1em 1em 4em -1em #000;
}
.mid-ring {
    width: 46%; height: 46%; 
    border-radius: 100%;
    background: var(--clr);
    box-shadow: 
    1em 1em 1.2em -0.6em #fff5,
    -0.3em -0.3em 0.4em -0.6em #0005,
    -0.2em -0.2em 1em 0em #0004,
    inset -0.3em -0.3em 0.6em -0.2em #fff3,
    inset -1.2em -1.2em 1.2em -1.4em #fff3,
    inset 0.1em 0.1em 0.2em -0.1em #0003,
    inset 1em 1em 2em 0em #0007;
}
.mid-ring::before {
    content: ''; display: block;
    position: absolute;
    width: 100%; height: 100%;
    border-radius: 100%; 
    background: repeating-conic-gradient(
        var(--clr) 0%,
        var(--clr) calc((100%)*( 1 / 12)),
        #0001 calc((100%)*( 1 / 12)),
        #0001 calc((100%)*( 2 / 12))
    );
    mix-blend-mode: multiply;
    opacity: 0.5;
}

.outer-inner-ring {
    background: var(--clr);
    width: 36%; height: 36%;
    border-radius: 100%;
    box-shadow: 
    -1em -1em 3em -1em #fff3,
    1em 1em 3em -1em #000a,
    0.2em 0.2em 0.3em -0.1em #0001,
    0.2em 0.2em 2em -1em #000,
    inset 0.4em 0.4em 1em -0.2em #fffa,
    inset 1em 1em 1.6em -0.5em #fff2,
    inset 0em 0em 1em 0.6em #0005
    ;
}
.inner-inner-ring {
    background: var(--clr);
    width: 24%; height: 24%;
    border-radius: 100%;
    box-shadow: 
    inset 0em 0em 0.6em -0.1em #fff4,
    inset -2em -2em 2em -2em #fff2,
    inset 2em 2em 2em -2em #0002,
    -0.1em -0.1em 1em 0em #fffa,
    -1em -1em 3em 1em #fff4,
    0.1em 0.1em 1em 0em #000a,
    1em 1em 3em 1em #0004;
}

.minihud, .minhud * {
    position: absolute; left: 0; right: 0; top: 0; bottom: 0; margin: auto;
}
.minihud {
    width: 12em; height: 12em;
    border-radius: 100%;
}
.minihud{
    background: linear-gradient(-45deg, #111 0%, #444 100%);
    filter: blur(0.1px);
    box-shadow: inset 1em 1em 3em 0em #0a0a0a;
}
.minihud *:not(.metal-ring) {
    transition: opacity 3s ease-in-out;
}
.metal-ring {
    width: 100%; height: 100%;
    border-radius: 100%;
    box-shadow: 
    -0.2em -0.2em 0.3em 0em #fff7,
    0.1em 0.1em 0.3em 0em #000a,
    0em 0em 0em 0.04em #2c2c2c,
    inset 0em 0em 0.1em 0.02em #0007,
    inset 0.1em 0.1em 0.1em 0em #fffc,
    inset -0.1em -0.1em 0.1em 0em #0005,
    inset 0 0 0.1em 0.3em #777,
    inset 0.2em 0.2em 0.4em 0.2em #0005,
    inset -0.2em -0.2em 0.1em 0.1em #fffa,
    inset 0 0 0 0.4em #777;
    rotate: 90deg;
    filter: contrast(1.4) blur(0.1px);
}
.minihud .scene {
    width: 94%; height: 94%;
    border-radius: 10em;
    overflow: hidden;
}
.minihud .scene,
.minihud .scene *{
    position: absolute; margin: auto;
    top: 0; bottom: 0; left: 0; right: 0;
}

.minihud .scene .sky {
    width: 100%;
    height: 100%;
    bottom: unset;
    
    transition: --clr1 1s, --clr2 1s, --clr3 1s, --clr4 1s;
    background: linear-gradient(170deg, var(--clr1), var(--clr2), var(--clr3), var(--clr4));
    animation: daynight 1s linear infinite alternate;
    animation-play-state: paused;
    animation-delay: calc(( var(--percentage-of-day) ) * -1s);
}
@property --clr1 { syntax: '<color>'; inherits: false; initial-value: #fff; }
@property --clr2 { syntax: '<color>'; inherits: false; initial-value: #fff; }
@property --clr3 { syntax: '<color>'; inherits: false; initial-value: #fff; }
@property --clr4 { syntax: '<color>'; inherits: false; initial-value: #fff; }
@keyframes daynight {
    0%  { --clr1:#061420; --clr2:#18354e; --clr3:#41698b; --clr4:#73add0; }
    15%  { --clr1:#061420; --clr2:#18354e; --clr3:#41698b; --clr4:#73add0; }
    30%  { --clr1:#8f5a6c; --clr2:#d58078; --clr3:#fbe280; --clr4:#fdfdc6; }
    50%   { --clr1:#0180b9; --clr2:#3399c9; --clr3:#8ce2de; --clr4:#e2f9f8; }
    65%   { --clr1:#0180b9; --clr2:#3399c9; --clr3:#8ce2de; --clr4:#e2f9f8; }
    80%  { --clr1:#8f5a6c; --clr2:#d58078; --clr3:#fbe280; --clr4:#fdfdc6; }
    90%  { --clr1:#061420; --clr2:#18354e; --clr3:#41698b; --clr4:#73add0; }
    100%  { --clr1:#061420; --clr2:#18354e; --clr3:#41698b; --clr4:#73add0; }
}

.minihud .scene .clouds {
    background: #aaa;
    width: 100%;
    min-width: 150px;
    min-height: 24px;
    height: 28%;
    top: unset;
    z-index: 3;
    border: 1px solid #fff;
    padding: 2%;
    rotate: 0deg;
    scale: 2.4;
    translate: 0 40%;
    filter: url(#cloud1) blur(1.2px);
    -webkit-filter: url(#cloud1) blur(1.2px);

    animation: clouds 20s linear infinite;
}
.minihud .scene .clouds::before {
    content: ""; display: block;
    position: absolute;
    width: 100%; height: 64%;
    margin: 0; 
    top: 0px;
    left: 0px;
    right: 0px;
    bottom: 0px;
    border: 0.1em solid #fff;
    box-shadow: 0 0 3em #fff;
    filter: url(#cloud1) blur(2px);
    -webkit-filter: url(#cloud1) blur(2px);
  
    z-index: -2;
}
@keyframes clouds {
    0% { opacity: 0;}
    5% { opacity: 1;}
    95% { opacity: 1;}
    100% { opacity: 0;}
}
.minihud .scene .clouds.sec {
    height: 24%;
    filter: url(#cloud2) blur(1.2px);
    -webkit-filter: url(#cloud2) blur(1.2px);
    animation: clouds 33s linear infinite;
}
.minihud .scene .clouds.sec::before {
    filter: url(#cloud2) blur(2px);
    -webkit-filter: url(#cloud2) blur(2px);
}
document.addEventListener('DOMContentLoaded', function() {
    document.documentElement.style.transition = 'filter 3s ease-out';
    document.documentElement.style.filter = 'grayscale(0) brightness(1) contrast(1) brightness(1)';
});

function getTime() {
    const now = new Date();
    const hours = now.getHours();
    const minutes = now.getMinutes();
    const seconds = now.getSeconds();
    const hours12 = hours % 12;
    return { hours, hours12, minutes, seconds };
}

function getClockRotation() {
    const { hours, minutes } = getTime();
    const thr = hours + ( minutes / 60 ); 
    const totalRotation = 720 * thr /24;
    return totalRotation;
}

function getPercentageOfDay() {
    const pod = getClockRotation() / 720;
    return pod.toFixed(2);
}

document.body.style.setProperty('--rotate-hour', getClockRotation()+90 );
document.body.style.setProperty('--pecentage-of-day', getPercentageOfDay());
document.body.querySelector('.minihud .scene .sky').style.animationDelay = `calc(${ getPercentageOfDay()} * -1s)`;

function showCurrentTime() {
    const { hours12, minutes } = getTime();
    let disHour = hours12
    const timeContainer = document.getElementById('timeContainer');
    if (disHour == 0 ){ disHour = 12; }
    timeContainer.textContent = `${String(disHour)}:${String(minutes).padStart(2, '0')}`;
    
    updateBgColor(getPercentageOfDay());
    document.body.style.setProperty('--rotate-hour', getClockRotation() );
}
showCurrentTime();
setTimeout(function() {
    showCurrentTime();
    setInterval(showCurrentTime, 1000 * 60);
}, (60 - getTime().seconds) * 1000);

function smoothCurve(val) {
    return (1 - Math.cos(2 * Math.PI * val + Math.PI)) / 2;
}
function updateBgColor(percentage) {
    percentage = smoothCurve(percentage);
    const dayColor = getComputedStyle(document.querySelector('body')).getPropertyValue('--clr-d').trim().slice(1).match(/.{2}/g).map(hex => parseInt(hex, 16));
    const nightColor = getComputedStyle(document.querySelector('body')).getPropertyValue('--clr-n').trim().slice(1).match(/.{2}/g).map(hex => parseInt(hex, 16));
    const currentColor = dayColor.map((start, index) => {
        const end = nightColor[index];
        return Math.round(start + percentage * (end - start));
    });
    const currentColorHex = `#${currentColor.map(c => c.toString(16).padStart(2, '0')).join('')}`;
    
    document.querySelector('body').style.setProperty('--clr', currentColorHex);
}
updateBgColor(getPercentageOfDay());

document.querySelectorAll('.hour').forEach(hour => {
    let isDragging = false;
    let lastAngle = null;
    let cumulativeRotation = 0;
    let initialRotation = 0;

    hour.addEventListener('mouseenter', () => {
        hour.classList.add('hovered');
    });

    hour.addEventListener('mouseleave', () => {
        hour.classList.remove('hovered');
    });

    hour.addEventListener('mousedown', (e) => {
        isDragging = true;
        hour.classList.add('dragging');
        e.preventDefault();

        const centerX = window.innerWidth / 2;
        const centerY = window.innerHeight / 2;
        const deltaX = e.clientX - centerX;
        const deltaY = e.clientY - centerY;
        const angleInRadians = Math.atan2(deltaY, deltaX);
        let angleInDegrees = (angleInRadians * (180 / Math.PI)) + 180;

        initialRotation = parseFloat(getComputedStyle(document.body).getPropertyValue('--rotate-hour').replace('deg', ''));
        lastAngle = angleInDegrees;
        cumulativeRotation = initialRotation;
    });

    window.addEventListener('mousemove', (e) => {
        if (isDragging) {
            const centerX = window.innerWidth / 2;
            const centerY = window.innerHeight / 2;
            const deltaX = e.clientX - centerX;
            const deltaY = e.clientY - centerY;
            const angleInRadians = Math.atan2(deltaY, deltaX);
            let angleInDegrees = (angleInRadians * (180 / Math.PI)) + 180;
            if (lastAngle === null) {
                lastAngle = angleInDegrees;
            }
            let angleDifference = angleInDegrees - lastAngle;
            if (angleDifference > 180) {
                angleDifference -= 360;
            } else if (angleDifference < -180) {
                angleDifference += 360;
            }
            cumulativeRotation += angleDifference;
            if (cumulativeRotation < 0) {
                cumulativeRotation += 720;
            } else if (cumulativeRotation >= 720) {
                cumulativeRotation -= 720;
            }
            lastAngle = angleInDegrees;
            let percentage = (cumulativeRotation / 720).toFixed(3);

            document.body.style.setProperty('--rotate-hour', cumulativeRotation.toFixed(2));
            document.body.style.setProperty('--percentage-of-day', percentage);
            updateBgColor(percentage);
            document.body.querySelector('.minihud .scene .sky').style.animationDelay = `calc(${(cumulativeRotation / 720).toFixed(2)} * -1s)`;
        }
    });

    window.addEventListener('mouseup', () => {
        if (isDragging) {
            setTimeout(function (){
                isDragging = false;
            }, 100); 
            hour.classList.remove('dragging');
            const currentRotation = parseFloat(getComputedStyle(document.body).getPropertyValue('--rotate-hour').replace('deg', ''));
            const degreeIncrement = (getClockRotation()) - currentRotation;

            smoothRotateClock(degreeIncrement, 1000);
        }
    });
});

function smoothRotateClock(degreeIncrement, duration) {
    const startRotation = parseFloat(getComputedStyle(document.body).getPropertyValue('--rotate-hour').replace('deg', ''));
    const frameRate = 60;
    const totalFrames = (duration / 1000) * frameRate;
    let currentFrame = 0;
    function rotate() {
        currentFrame++;
        const progress = currentFrame / totalFrames;
        const currentRotation = startRotation + degreeIncrement * easeInOutCubic(progress);
        document.body.style.setProperty('--rotate-hour', `${currentRotation}`);
        updateBgColor(currentRotation/720);
        document.body.querySelector('.minihud .scene .sky').style.animationDelay = `calc(${currentRotation/720} * -1s)`;
        if (currentFrame < totalFrames) {
            requestAnimationFrame(rotate);
        }
    }
    rotate();
}
function easeInOutCubic(t) {
    return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.