text: const TWO_PI = Math.PI * 2;
  const HALF_PI = Math.PI * 0.5;
  
  // canvas settings
  var viewWidth = 512,
      viewHeight = 512,
      drawingCanvas = document.getElementById("drawing_canvas"),
      ctx,
      timeStep = (1/60);
  
  Point = function(x, y) {
      this.x = x || 0;
      this.y = y || 0;
  };
  
  Particle = function(p0, p1, p2, p3) {
      this.p0 = p0;
      this.p1 = p1;
      this.p2 = p2;
      this.p3 = p3;
  
      this.time = 0;
      this.duration = 3 + Math.random() * 2;
      this.color =  '#' + Math.floor((Math.random() * 0xffffff)).toString(16);
  
      this.w = 8;
      this.h = 6;
  
      this.complete = false;
  };
  
  Particle.prototype = {
      update:function() {
          this.time = Math.min(this.duration, this.time + timeStep);
  
          var f = Ease.outCubic(this.time, 0, 1, this.duration);
          var p = cubeBezier(this.p0, this.p1, this.p2, this.p3, f);
  
          var dx = p.x - this.x;
          var dy = p.y - this.y;
  
          this.r =  Math.atan2(dy, dx) + HALF_PI;
          this.sy = Math.sin(Math.PI * f * 10);
          this.x = p.x;
          this.y = p.y;
  
          this.complete = this.time === this.duration;
      },
      draw:function() {
          ctx.save();
          ctx.translate(this.x, this.y);
          ctx.rotate(this.r);
          ctx.scale(1, this.sy);
  
          ctx.fillStyle = this.color;
          ctx.fillRect(-this.w * 0.5, -this.h * 0.5, this.w, this.h);
  
          ctx.restore();
      }
  };
  
  Loader = function(x, y) {
      this.x = x;
      this.y = y;
  
      this.r = 24;
      this._progress = 0;
  
      this.complete = false;
  };
  
  Loader.prototype = {
      reset:function() {
          this._progress = 0;
          this.complete = false;
      },
      set progress(p) {
          this._progress = p < 0 ? 0 : (p > 1 ? 1 : p);
  
          this.complete = this._progress === 1;
      },
      get progress() {
          return this._progress;
      },
      draw:function() {
          ctx.fillStyle = 'transparent';
          ctx.beginPath();
          ctx.arc(this.x, this.y, this.r, -HALF_PI, TWO_PI * this._progress - HALF_PI);
          ctx.lineTo(this.x, this.y);
          ctx.closePath();
          ctx.fill();
      }
  };
  
  // pun intended
  Exploader = function(x, y) {
      this.x = x;
      this.y = y;
  
      this.startRadius = 24;
  
      this.time = 0;
      this.duration = 0.4;
      this.progress = 0;
  
      this.complete = false;
  };
  
  Exploader.prototype = {
      reset:function() {
          this.time = 0;
          this.progress = 0;
          this.complete = false;
      },
      update:function() {
          this.time = Math.min(this.duration, this.time + timeStep);
          this.progress = Ease.inBack(this.time, 0, 1, this.duration);
  
          this.complete = this.time === this.duration;
      },
      draw:function() {
          ctx.fillStyle = 'transparent';
          ctx.beginPath();
          ctx.arc(this.x, this.y, this.startRadius * (1 - this.progress), 0, TWO_PI);
          ctx.fill();
      }
  };
  
  var particles = [],
      loader,
      exploader,
      phase = 0;
  
  function initDrawingCanvas() {
      drawingCanvas.width = viewWidth;
      drawingCanvas.height = viewHeight;
      ctx = drawingCanvas.getContext('2d');
  
      createLoader();
      createExploader();
      createParticles();
  }
  
  function createLoader() {
      loader = new Loader(viewWidth * 0.5, viewHeight * 0.5);
  }
  
  function createExploader() {
      exploader = new Exploader(viewWidth * 0.5, viewHeight * 0.5);
  }
  
  function createParticles() {
      for (var i = 0; i < 128; i++) {
          var p0 = new Point(viewWidth * 0.5, viewHeight * 0.5);
          var p1 = new Point(Math.random() * viewWidth, Math.random() * viewHeight);
          var p2 = new Point(Math.random() * viewWidth, Math.random() * viewHeight);
          var p3 = new Point(Math.random() * viewWidth, viewHeight + 64);
  
          particles.push(new Particle(p0, p1, p2, p3));
      }
  }
  
  function update() {
  
      switch (phase) {
          case 0:
              loader.progress += (1/45);
              break;
          case 1:
              exploader.update();
              break;
          case 2:
              particles.forEach(function(p) {
                  p.update();
              });
              break;
      }
  }
  
  function draw() {
      ctx.clearRect(0, 0, viewWidth, viewHeight);
  
      switch (phase) {
          case 0:
              loader.draw();
              break;
          case 1:
              exploader.draw();
              break;
          case 2:
              particles.forEach(function(p) {
                  p.draw();
              });
          break;
      }
  }
  
  window.onload = function() {
      initDrawingCanvas();
      requestAnimationFrame(loop);
  };
  
  function loop() {
      update();
      draw();
  
      if (phase === 0 && loader.complete) {
          phase = 1;
      }
      else if (phase === 1 && exploader.complete) {
          phase = 2;
      }
      else if (phase === 2 && checkParticlesComplete()) {
          // reset
          phase = 0;
          loader.reset();
          exploader.reset();
          particles.length = 0;
          createParticles();
      }
  
      requestAnimationFrame(loop);
  }
  
  function checkParticlesComplete() {
      for (var i = 0; i < particles.length; i++) {
          if (particles[i].complete === false) return false;
      }
      return true;
  }
  
  // math and stuff
  
  /**
   * easing equations from biruabuhitam
   * t = current time
   * b = start value
   * c = delta value
   * d = duration
   */
  var Ease = {
      inCubic:function (t, b, c, d) {
          t /= d;
          return c*t*t*t + b;
      },
      outCubic:function(t, b, c, d) {
          t /= d;
          t--;
          return c*(t*t*t + 1) + b;
      },
      inOutCubic:function(t, b, c, d) {
          t /= d/2;
          if (t < 1) return c/2*t*t*t + b;
          t -= 2;
          return c/2*(t*t*t + 2) + b;
      },
      inBack: function (t, b, c, d, s) {
          s = s || 1.70158;
          return c*(t/=d)*t*((s+1)*t - s) + b;
      }
  };
  
  function cubeBezier(p0, c0, c1, p1, t) {
      var p = new Point();
      var nt = (1 - t);
  
      p.x = nt * nt * nt * p0.x + 3 * nt * nt * t * c0.x + 3 * nt * t * t * c1.x + t * t * t * p1.x;
      p.y = nt * nt * nt * p0.y + 3 * nt * nt * t * c0.y + 3 * nt * t * t * c1.y + t * t * t * p1.y;
  
      return p;
  }
  /*--neon--*/
  
  var TxtRotate = function(el, toRotate, period) {
    this.toRotate = toRotate;
    this.el = el;
    this.loopNum = 0;
    this.period = parseInt(period, 10) || 2000;
    this.txt = '';
    this.tick();
    this.isDeleting = false;
  };
  
  TxtRotate.prototype.tick = function() {
    var i = this.loopNum % this.toRotate.length;
    var fullTxt = this.toRotate[i];
  
    if (this.isDeleting) {
      this.txt = fullTxt.substring(0, this.txt.length - 1);
    } else {
      this.txt = fullTxt.substring(0, this.txt.length + 1);
    }
  
    this.el.innerHTML = '<span class="wrap">'+this.txt+'</span>';
  
    var that = this;
    var delta = 300 - Math.random() * 100;
  
    if (this.isDeleting) { delta /= 2; }
  
    if (!this.isDeleting && this.txt === fullTxt) {
      delta = this.period;
      this.isDeleting = true;
    } else if (this.isDeleting && this.txt === '') {
      this.isDeleting = false;
      this.loopNum++;
      delta = 500;
    }
  
    setTimeout(function() {
      that.tick();
    }, delta);
  };
  
  window.onload = function() {
    var elements = document.getElementsByClassName('txt-rotate');
    for (var i=0; i<elements.length; i++) {
      var toRotate = elements[i].getAttribute('data-rotate');
      var period = elements[i].getAttribute('data-period');
      if (toRotate) {
        new TxtRotate(elements[i], JSON.parse(toRotate), period);
      }
    }
    // INJECT CSS
    var css = document.createElement("style");
    css.type = "text/css";
    css.innerHTML = ".txt-rotate > .wrap { border-right: 0.08em solid #666 }";
    document.body.appendChild(css);
  };
  const hours = document.querySelector(".card-clock__innerHours");
  const minutes = document.querySelector(".card-clock__innerMinutes");
  const seconds = document.querySelector(".card-clock__innerSeconds");
  
  const calculateDegrees = (value, maxValue) => value / maxValue * 360 - 90;
  
  const setClock = () => {
    const date = new Date();
  
    seconds.style.transform = `rotate(${calculateDegrees(date.getSeconds(), 60)}deg)`;
    minutes.style.transform = `rotate(${calculateDegrees(date.getMinutes(), 60)}deg)`;
    hours.style.transform = `rotate(${calculateDegrees(date.getHours(), 12)}deg)`;
  };
  setClock();
  
  setInterval(setClock, 1000);
  
  