diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..cfa85aa
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,4 @@
+{
+ "presets": ["es2015"],
+ "compact": false,
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..34fdc15
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+.sass-cache
+node_modules
+prod.js.map
+style.css.map
\ No newline at end of file
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 0000000..08482c2
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,76 @@
+/**
+ * A lot of directories are verbose without wildcards, largely a result of having a shared codebase with the backend code.
+ *
+ * TODO: Separate tasks for backend app!
+ */
+module.exports = function (grunt) {
+
+ // Project configuration.
+ grunt.initConfig({
+ pkg: grunt.file.readJSON('package.json'),
+
+ /**
+ * Converts our Sass files to CSS.
+ */
+ sass: {
+ compile: {
+ options: {
+ style: 'nested'
+ },
+ files: {
+ 'public/css/style.css': 'style.scss'
+ }
+ }
+ },
+
+
+ /**
+ * Watches for changes on all JS and CSS files.
+ *
+ * Live reload is working (servers running on localhost 35729 and 35728).
+ * You'll need a Live-reload plugin installed (https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei)
+ *
+ * Changes to grunt file will rerun the grunt script.
+ */
+ watch: {
+ css: {
+ files: ['style.scss'],
+ tasks: ['sass:compile']
+ },
+ configFiles: {
+ files: ['Gruntfile.js'],
+ options: {
+ reload: true
+ }
+ }
+ },
+
+ /**
+ * Converts all ES6 Javascript into ES5 Javascript.
+ *
+ * .babelrc full configures Babel.
+ */
+ babel: {
+ /**
+ * Transform ES6 JS files into ES5.
+ */
+ es6: {
+ options: {
+ sourceMap: true,
+ presets: ['es2015'],
+ },
+ files: {
+ // "client.js": "public/js/prod.js"
+ "public/js/prod.js": "client.js",
+ },
+ },
+ },
+ });
+
+ grunt.loadNpmTasks('grunt-contrib-sass');
+ grunt.loadNpmTasks('grunt-contrib-watch');
+ grunt.loadNpmTasks('grunt-babel');
+
+ grunt.registerTask('development', ['sass:compile', 'watch']);
+ grunt.registerTask('production', ['sass:compile', 'babel:es6']);
+};
diff --git a/README.md b/README.md
index f943f2c..6e14a81 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,16 @@
-# afx
\ No newline at end of file
+# afx
+
+## Setup
+
+Install the package dependencies: `npm install`.
+
+Copy the pre-commit Git hook, to ensure the assets are compiled before you commit.
+```
+cp pre-commit .git/hooks/.
+```
+
+## Development
+
+```
+grunt development
+```
diff --git a/client.js b/client.js
new file mode 100644
index 0000000..01ec7b0
--- /dev/null
+++ b/client.js
@@ -0,0 +1,254 @@
+
+class TextScramble {
+ /** Modified version of Justin Windle's Text Scrambler: https://codepen.io/soulwire/pen/mErPAK */
+
+ constructor(el, scrambleSpeed, chars) {
+ this.el = el;
+ this.scrambleSpeed = scrambleSpeed || 25;
+ this.chars = chars || 'aphextwin';
+ this.update = this.update.bind(this)
+ }
+
+ setText(newText) {
+ window.countdowner.updateField = false;
+ const oldText = this.el.innerText;
+ const length = Math.max(oldText.length, newText.length);
+ this.queue = [];
+
+ for (let i = 0; i < length; i++) {
+ const from = oldText[i] || '';
+ const to = newText[i] || '';
+
+ const start = Math.floor(Math.random() * (this.scrambleSpeed));
+ const end = start + Math.floor(Math.random() * (this.scrambleSpeed));
+
+ this.queue.push({ from, to, start, end })
+ }
+ cancelAnimationFrame(this.frameRequest);
+ this.frame = 0;
+ this.update();
+ }
+
+ update() {
+ let output = '';
+ let complete = 0;
+ for (let i = 0, n = this.queue.length; i < n; i++) {
+ let { from, to, start, end, char } = this.queue[i];
+ if (this.frame >= end) {
+ complete++;
+ output += to
+ } else if (this.frame >= start) {
+ if (!char || Math.random() < 0.28) {
+ char = this.randomChar();
+ this.queue[i].char = char
+ }
+ output += `${char}`
+ } else {
+ output += from
+ }
+ }
+ this.el.innerHTML = output;
+ if (complete === this.queue.length) {
+ window.countdowner.updateField = true;
+ return;
+ } else {
+ this.frameRequest = requestAnimationFrame(this.update);
+ this.frame++
+ }
+ }
+
+ randomChar() {
+ return this.chars[Math.floor(Math.random() * this.chars.length)]
+ }
+}
+
+function padWithDots(str) {
+ let maxPadding = 40;
+ let numToAdd = maxPadding - str.length;
+
+ let dots = '';
+ for (let i=0; i < numToAdd; i++) {
+ dots = dots + ".";
+ }
+
+ return str + dots;
+}
+
+class Countdown {
+ constructor() {
+ let that = this;
+ let a = new Date().valueOf();
+ let b = 1499119200000;
+ let d = 1496520000000;
+
+ this.$el = $('#countdown');
+ this.updateField = true;
+ this.c = b - a;
+
+ this._setText();
+ setInterval(function() {
+ that.c = Math.floor((that.c - (100 * ((b - a) / (d - a)) ) )) ;
+ that._setText();
+ }, 100);
+ }
+
+ _setText() {
+ if (this.updateField) {
+ this.$el.text( padWithDots(this.c + "") );
+ }
+ }
+}
+
+function initScramblers() {
+ window.countdowner = new Countdown();
+ const countdownScrambler = new TextScramble(document.getElementById('countdown'), 15, 'aphex');
+
+ $('#nts-label').text(padWithDots("NTS"));
+
+ let $paddingElements = $('.aphexDotPadding');
+ let paddingScramblers = [];
+ $paddingElements.each( function(i) {
+ let $el = $($paddingElements[i]);
+ $el.length && $el.text( padWithDots(""));
+
+ paddingScramblers.push( new TextScramble($paddingElements[i], 25, i % 2 === 0 ? 'twin' : 'aphex'));
+ });
+
+ let scrambleText = function() {
+ for(let i=0; i < paddingScramblers.length; i++) {
+ paddingScramblers[i].setText(padWithDots(""));
+ }
+
+ countdownScrambler.setText( padWithDots(window.countdowner.c + "") );
+
+ let rangeInSeconds = 4.5;
+ let randomTimeout = Math.floor( (Math.random() * 1000) * rangeInSeconds);
+
+ setTimeout(scrambleText, randomTimeout)
+ };
+
+ scrambleText();
+}
+
+let NTS_AFX = {};
+NTS_AFX.store = {
+ init: function() {
+ let config = {
+ apiKey: "AIzaSyCn2JexWTvW3fyvyvjWNcdwe-wDkgOw1c0",
+ authDomain: "nts-afx.firebaseapp.com",
+ databaseURL: "https://nts-afx.firebaseio.com",
+ projectId: "nts-afx",
+ storageBucket: "nts-afx.appspot.com",
+ messagingSenderId: "1740064170"
+ };
+ firebase.initializeApp(config);
+ },
+ post: function(message) {
+ let record = { message: message };
+ let newPostKey = firebase.database().ref().child('messages').push().key;
+ let updates = {};
+ updates['/messages/' + newPostKey] = record;
+ return firebase.database().ref().update(updates);
+ }
+};
+
+(function (i, s, o, g, r, a, m) {
+ i['GoogleAnalyticsObject'] = r;
+ i[r] = i[r] || function () {
+ (i[r].q = i[r].q || []).push(arguments)
+ }, i[r].l = 1 * new Date();
+ a = s.createElement(o),
+ m = s.getElementsByTagName(o)[0];
+ a.async = 1;
+ a.src = g;
+ m.parentNode.insertBefore(a, m)
+})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
+ga('create', 'UA-6061419-3', 'auto');
+
+class AudioPlayer {
+ constructor() {
+ this.el = document.getElementById('aphex-audio');
+
+ this.el.addEventListener('play', function(e) {
+ $('#player').addClass('playing');
+ });
+ this.el.addEventListener('pause', function(e) {
+ $('#player').removeClass('playing');
+ });
+
+ this.el.volume = 0.8;
+ }
+
+ play() {
+ this.el.play();
+ }
+
+ pause() {
+ this.el.pause();
+ }
+
+ isPlaying() {
+ return !this.el.paused;
+ }
+
+ toggleAudio() {
+ this.isPlaying()
+ ? this.pause()
+ : this.play();
+ }
+}
+
+$(document).ready( function () {
+ ga('send', 'pageview', window.location.pathname);
+
+ initScramblers();
+ NTS_AFX.store.init();
+
+ window.audioPlayer = new AudioPlayer();
+
+ let $consoleEntryForm = $('#console-entry-form');
+
+ $consoleEntryForm.focus();
+ $consoleEntryForm.submit( function(e) {
+ e.preventDefault();
+
+ ga('send', 'event', 'Aphex', 'PasswordAttempt');
+
+ let authenticated = NTS_AFX.store.post(
+ e.currentTarget.children['console-entry'].value
+ ).then(function(authenticated) {
+
+ if (authenticated) {
+ let $msg = $('#success-message');
+ $msg.addClass('display');
+
+ setTimeout(function() {
+ $msg.removeClass('display');
+ },2000);
+
+ authenticated.authenticate();
+ } else {
+ let $msg = $('#error-message');
+ $msg.addClass('display');
+
+ setTimeout(function() {
+ $msg.removeClass('display');
+ }, 1500);
+ }
+
+ e.currentTarget.children['console-entry'].value = "";
+ });
+ });
+
+ $('#nts-link').on('click', function() {
+ ga('send', 'event', 'Aphex', 'GoTo-NTS');
+ });
+
+ $('#warp-link').on('click', function() {
+ ga('send', 'event', 'Aphex', 'GoTo-Warp');
+ });
+
+ $('#player').on('click', function() {
+ window.audioPlayer.toggleAudio();
+ });
+});
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..188ab4a
--- /dev/null
+++ b/index.html
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Aphex Twin | NTS
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ERROR
+
+
+
+ ACCESS GRANTED
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..f237187
--- /dev/null
+++ b/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "afx",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.html",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/ntslive/afx.git"
+ },
+ "author": "",
+ "license": "ISC",
+ "bugs": {
+ "url": "https://github.com/ntslive/afx/issues"
+ },
+ "homepage": "https://github.com/ntslive/afx#readme",
+ "devDependencies": {
+ "babel-preset-es2015": "^6.24.1",
+ "grunt": "^1.0.1",
+ "grunt-babel": "^6.0.0",
+ "grunt-contrib-sass": "^1.0.0",
+ "grunt-contrib-watch": "^1.0.0"
+ }
+}
diff --git a/pre-commit b/pre-commit
new file mode 100755
index 0000000..9fd1f93
--- /dev/null
+++ b/pre-commit
@@ -0,0 +1,4 @@
+#!/bin/sh
+#
+grunt production
+git add public/.
diff --git a/public/audio/afx.mp3 b/public/audio/afx.mp3
new file mode 100644
index 0000000..e1790f5
Binary files /dev/null and b/public/audio/afx.mp3 differ
diff --git a/public/css/fontello.css b/public/css/fontello.css
new file mode 100755
index 0000000..70dad0f
--- /dev/null
+++ b/public/css/fontello.css
@@ -0,0 +1,59 @@
+@font-face {
+ font-family: 'fontello';
+ src: url('../font/fontello.eot?17501704');
+ src: url('../font/fontello.eot?17501704#iefix') format('embedded-opentype'),
+ url('../font/fontello.woff2?17501704') format('woff2'),
+ url('../font/fontello.woff?17501704') format('woff'),
+ url('../font/fontello.ttf?17501704') format('truetype'),
+ url('../font/fontello.svg?17501704#fontello') format('svg');
+ font-weight: normal;
+ font-style: normal;
+}
+/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
+/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
+/*
+@media screen and (-webkit-min-device-pixel-ratio:0) {
+ @font-face {
+ font-family: 'fontello';
+ src: url('../font/fontello.svg?17501704#fontello') format('svg');
+ }
+}
+*/
+
+ [class^="icon"]:before, [class*=" icon"]:before {
+ font-family: "fontello";
+ font-style: normal;
+ font-weight: normal;
+ speak: none;
+
+ display: inline-block;
+ text-decoration: inherit;
+ width: 1em;
+ margin-right: .2em;
+ text-align: center;
+ /* opacity: .8; */
+
+ /* For safety - reset parent styles, that can break glyph codes*/
+ font-variant: normal;
+ text-transform: none;
+
+ /* fix buttons height, for twitter bootstrap */
+ line-height: 1em;
+
+ /* Animation center compensation - margins should be symmetric */
+ /* remove if not needed */
+ margin-left: .2em;
+
+ /* you can be more comfortable with increased icons size */
+ /* font-size: 120%; */
+
+ /* Font smoothing. That was taken from TWBS */
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+
+ /* Uncomment for 3D effect */
+ /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
+}
+
+.icon-play:before { content: '\e800'; } /* '' */
+.icon-pause:before { content: '\e802'; } /* '' */
\ No newline at end of file
diff --git a/public/css/fonts/DecimaMonoPro.ttf b/public/css/fonts/DecimaMonoPro.ttf
new file mode 100644
index 0000000..c036626
Binary files /dev/null and b/public/css/fonts/DecimaMonoPro.ttf differ
diff --git a/public/css/fonts/decimamonopro-webfont.woff b/public/css/fonts/decimamonopro-webfont.woff
new file mode 100755
index 0000000..174a2b8
Binary files /dev/null and b/public/css/fonts/decimamonopro-webfont.woff differ
diff --git a/public/css/fonts/decimamonopro-webfont.woff2 b/public/css/fonts/decimamonopro-webfont.woff2
new file mode 100755
index 0000000..36c6efb
Binary files /dev/null and b/public/css/fonts/decimamonopro-webfont.woff2 differ
diff --git a/public/css/style.css b/public/css/style.css
new file mode 100644
index 0000000..adc4f5c
--- /dev/null
+++ b/public/css/style.css
@@ -0,0 +1,219 @@
+@import url(fontello.css);
+@font-face {
+ font-family: 'Decima';
+ src: url("fonts/decimamonopro-webfont.woff2") format("woff2"), url("fonts/decimamonopro-webfont.woff") format("woff"), url("fonts/DecimaMonoPro.ttf") format("ttf");
+ font-weight: normal;
+ font-style: normal; }
+html {
+ background-color: black;
+ color: white;
+ font-family: "Decima", courier;
+ min-width: 320px; }
+
+* {
+ box-sizing: border-box; }
+
+input[type="search"]::-webkit-search-decoration {
+ display: none; }
+
+input {
+ margin: 0;
+ outline: 0;
+ vertical-align: middle;
+ background: none;
+ border: none;
+ color: white;
+ font-family: "Decima", courier !important;
+ font-size: 1em; }
+
+input[type="reset"], input[type="submit"], input[type="button"] {
+ -webkit-appearance: none;
+ background: none;
+ border: 0;
+ cursor: pointer;
+ overflow: visible;
+ padding: 0;
+ width: auto;
+ font-family: "Decima", courier; }
+
+a {
+ text-decoration: none;
+ transition: opacity 0.2s linear; }
+ a:hover {
+ opacity: 0.7; }
+ a:visited {
+ color: white; }
+ a:-webkit-any-link {
+ color: white; }
+
+#aphex-page {
+ color: white;
+ width: 100%;
+ font-size: 19.5px; }
+
+#aphex-console-container {
+ position: absolute;
+ top: 50%;
+ left: 0;
+ width: 50%;
+ height: auto;
+ padding: 0 20px;
+ -webkit-transform: translateY(-50%);
+ -moz-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ -o-transform: translateY(-50%);
+ transform: translateY(-50%);
+ max-width: 50%;
+ overflow: hidden; }
+
+#links-bottom {
+ margin-top: 20px; }
+ #links-bottom #warp-link {
+ float: left; }
+ #links-bottom #warp-link img {
+ height: 35px; }
+ #links-bottom #nts-link {
+ float: left;
+ margin-right: 10px; }
+ #links-bottom #nts-link img {
+ width: 35px; }
+
+#links-top, #console, #console-entry-form, #links-bottom > div {
+ max-width: 500px;
+ margin-left: auto;
+ margin-right: auto; }
+
+#console .console-row {
+ display: inline-block; }
+#console .aphexDotPadding {
+ display: inline; }
+#console #console-entry-form {
+ width: 500px; }
+ #console #console-entry-form #console-entry {
+ width: 100%; }
+
+#aphex-gif-container {
+ position: absolute;
+ float: right;
+ top: 50%;
+ right: 0;
+ width: 50%;
+ -webkit-transform: translateY(-50%);
+ -moz-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ -o-transform: translateY(-50%);
+ transform: translateY(-50%);
+ text-align: center; }
+ #aphex-gif-container img {
+ max-width: 80%; }
+
+#error-message, #success-message {
+ position: absolute;
+ top: 50%;
+ left: 0;
+ right: 0;
+ -webkit-transform: translateY(-50%);
+ -moz-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ -o-transform: translateY(-50%);
+ transform: translateY(-50%);
+ text-align: center;
+ font-size: 6em;
+ font-weight: lighter;
+ z-index: 99999;
+ visibility: hidden;
+ opacity: 0;
+ -webkit-transition: all 0.2s linear;
+ -moz-transition: all 0.2s linear;
+ -ms-transition: all 0.2s linear;
+ -o-transition: all 0.2s linear;
+ transition: all 0.2s linear; }
+ #error-message.display, #success-message.display {
+ visibility: visible;
+ opacity: 1; }
+
+#error-message {
+ color: #be0000;
+ text-shadow: 0 0 40px #ab0505; }
+
+#success-message {
+ color: #00d200;
+ text-shadow: 0 0 30px green;
+ overflow: hidden; }
+
+audio {
+ display: none; }
+
+#player {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ font-size: 2em;
+ cursor: pointer;
+ color: white;
+ opacity: 1;
+ z-index: 9999999999;
+ -webkit-transition: opacity 0.2s linear;
+ -moz-transition: opacity 0.2s linear;
+ -ms-transition: opacity 0.2s linear;
+ -o-transition: opacity 0.2s linear;
+ transition: opacity 0.2s linear; }
+ #player:hover {
+ opacity: 0.7;
+ cursor: pointer; }
+ #player.playing #player-play {
+ display: none; }
+ #player.playing #player-pause {
+ display: block; }
+
+#player-pause {
+ display: none; }
+
+@media only screen and (max-width: 700px) {
+ #aphex-page {
+ position: absolute;
+ top: 50%;
+ left: 0;
+ right: 0;
+ font-size: 1.2em;
+ height: 450px;
+ -webkit-transform: translateY(-50%);
+ -moz-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ -o-transform: translateY(-50%);
+ transform: translateY(-50%); }
+
+ #aphex-console-container {
+ position: relative;
+ display: block;
+ width: 300px;
+ height: auto;
+ max-width: 100%;
+ margin: 0 auto;
+ padding: 0;
+ top: 0;
+ overflow: hidden;
+ -webkit-transform: none;
+ -moz-transform: none;
+ -ms-transform: none;
+ -o-transform: none;
+ transform: none; }
+ #aphex-console-container #nts-link img {
+ width: 30px; }
+
+ #aphex-gif-container {
+ position: relative;
+ width: 100%;
+ display: block;
+ overflow: auto;
+ top: 0;
+ padding-top: 0;
+ -webkit-transform: none;
+ -moz-transform: none;
+ -ms-transform: none;
+ -o-transform: none;
+ transform: none; }
+ #aphex-gif-container img {
+ width: 250px; } }
+
+/*# sourceMappingURL=style.css.map */
diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png
new file mode 100644
index 0000000..05548c5
Binary files /dev/null and b/public/favicon-16x16.png differ
diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png
new file mode 100644
index 0000000..9294fe0
Binary files /dev/null and b/public/favicon-32x32.png differ
diff --git a/public/favicon.gif b/public/favicon.gif
new file mode 100644
index 0000000..70545fa
Binary files /dev/null and b/public/favicon.gif differ
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..7857ac4
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/public/font/fontello.eot b/public/font/fontello.eot
new file mode 100755
index 0000000..4fedfca
Binary files /dev/null and b/public/font/fontello.eot differ
diff --git a/public/font/fontello.svg b/public/font/fontello.svg
new file mode 100755
index 0000000..c00ae64
--- /dev/null
+++ b/public/font/fontello.svg
@@ -0,0 +1,14 @@
+
+
+
\ No newline at end of file
diff --git a/public/font/fontello.ttf b/public/font/fontello.ttf
new file mode 100755
index 0000000..d6785c1
Binary files /dev/null and b/public/font/fontello.ttf differ
diff --git a/public/font/fontello.woff b/public/font/fontello.woff
new file mode 100755
index 0000000..cd77117
Binary files /dev/null and b/public/font/fontello.woff differ
diff --git a/public/font/fontello.woff2 b/public/font/fontello.woff2
new file mode 100755
index 0000000..571d038
Binary files /dev/null and b/public/font/fontello.woff2 differ
diff --git a/public/img/afx_basic.gif b/public/img/afx_basic.gif
new file mode 100644
index 0000000..6b0fe04
Binary files /dev/null and b/public/img/afx_basic.gif differ
diff --git a/public/img/nts_white.png b/public/img/nts_white.png
new file mode 100644
index 0000000..696990e
Binary files /dev/null and b/public/img/nts_white.png differ
diff --git a/public/img/socials.png b/public/img/socials.png
new file mode 100644
index 0000000..a116a95
Binary files /dev/null and b/public/img/socials.png differ
diff --git a/public/img/warp.png b/public/img/warp.png
new file mode 100644
index 0000000..f65ff0e
Binary files /dev/null and b/public/img/warp.png differ
diff --git a/public/js/prod.js b/public/js/prod.js
new file mode 100644
index 0000000..e616f0d
--- /dev/null
+++ b/public/js/prod.js
@@ -0,0 +1,287 @@
+'use strict';
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var TextScramble = function () {
+ /** Modified version of Justin Windle's Text Scrambler: https://codepen.io/soulwire/pen/mErPAK */
+
+ function TextScramble(el, scrambleSpeed, chars) {
+ _classCallCheck(this, TextScramble);
+
+ this.el = el;
+ this.scrambleSpeed = scrambleSpeed || 25;
+ this.chars = chars || 'aphextwin';
+ this.update = this.update.bind(this);
+ }
+
+ _createClass(TextScramble, [{
+ key: 'setText',
+ value: function setText(newText) {
+ window.countdowner.updateField = false;
+ var oldText = this.el.innerText;
+ var length = Math.max(oldText.length, newText.length);
+ this.queue = [];
+
+ for (var i = 0; i < length; i++) {
+ var from = oldText[i] || '';
+ var to = newText[i] || '';
+
+ var start = Math.floor(Math.random() * this.scrambleSpeed);
+ var end = start + Math.floor(Math.random() * this.scrambleSpeed);
+
+ this.queue.push({ from: from, to: to, start: start, end: end });
+ }
+ cancelAnimationFrame(this.frameRequest);
+ this.frame = 0;
+ this.update();
+ }
+ }, {
+ key: 'update',
+ value: function update() {
+ var output = '';
+ var complete = 0;
+ for (var i = 0, n = this.queue.length; i < n; i++) {
+ var _queue$i = this.queue[i],
+ from = _queue$i.from,
+ to = _queue$i.to,
+ start = _queue$i.start,
+ end = _queue$i.end,
+ char = _queue$i.char;
+
+ if (this.frame >= end) {
+ complete++;
+ output += to;
+ } else if (this.frame >= start) {
+ if (!char || Math.random() < 0.28) {
+ char = this.randomChar();
+ this.queue[i].char = char;
+ }
+ output += '' + char + '';
+ } else {
+ output += from;
+ }
+ }
+ this.el.innerHTML = output;
+ if (complete === this.queue.length) {
+ window.countdowner.updateField = true;
+ return;
+ } else {
+ this.frameRequest = requestAnimationFrame(this.update);
+ this.frame++;
+ }
+ }
+ }, {
+ key: 'randomChar',
+ value: function randomChar() {
+ return this.chars[Math.floor(Math.random() * this.chars.length)];
+ }
+ }]);
+
+ return TextScramble;
+}();
+
+function padWithDots(str) {
+ var maxPadding = 40;
+ var numToAdd = maxPadding - str.length;
+
+ var dots = '';
+ for (var i = 0; i < numToAdd; i++) {
+ dots = dots + ".";
+ }
+
+ return str + dots;
+}
+
+var Countdown = function () {
+ function Countdown() {
+ _classCallCheck(this, Countdown);
+
+ var that = this;
+ var a = new Date().valueOf();
+ var b = 1499119200000;
+ var d = 1496520000000;
+
+ this.$el = $('#countdown');
+ this.updateField = true;
+ this.c = b - a;
+
+ this._setText();
+ setInterval(function () {
+ that.c = Math.floor(that.c - 100 * ((b - a) / (d - a)));
+ that._setText();
+ }, 100);
+ }
+
+ _createClass(Countdown, [{
+ key: '_setText',
+ value: function _setText() {
+ if (this.updateField) {
+ this.$el.text(padWithDots(this.c + ""));
+ }
+ }
+ }]);
+
+ return Countdown;
+}();
+
+function initScramblers() {
+ window.countdowner = new Countdown();
+ var countdownScrambler = new TextScramble(document.getElementById('countdown'), 15, 'aphex');
+
+ $('#nts-label').text(padWithDots("NTS"));
+
+ var $paddingElements = $('.aphexDotPadding');
+ var paddingScramblers = [];
+ $paddingElements.each(function (i) {
+ var $el = $($paddingElements[i]);
+ $el.length && $el.text(padWithDots(""));
+
+ paddingScramblers.push(new TextScramble($paddingElements[i], 25, i % 2 === 0 ? 'twin' : 'aphex'));
+ });
+
+ var scrambleText = function scrambleText() {
+ for (var i = 0; i < paddingScramblers.length; i++) {
+ paddingScramblers[i].setText(padWithDots(""));
+ }
+
+ countdownScrambler.setText(padWithDots(window.countdowner.c + ""));
+
+ var rangeInSeconds = 4.5;
+ var randomTimeout = Math.floor(Math.random() * 1000 * rangeInSeconds);
+
+ setTimeout(scrambleText, randomTimeout);
+ };
+
+ scrambleText();
+}
+
+var NTS_AFX = {};
+NTS_AFX.store = {
+ init: function init() {
+ var config = {
+ apiKey: "AIzaSyCn2JexWTvW3fyvyvjWNcdwe-wDkgOw1c0",
+ authDomain: "nts-afx.firebaseapp.com",
+ databaseURL: "https://nts-afx.firebaseio.com",
+ projectId: "nts-afx",
+ storageBucket: "nts-afx.appspot.com",
+ messagingSenderId: "1740064170"
+ };
+ firebase.initializeApp(config);
+ },
+ post: function post(message) {
+ var record = { message: message };
+ var newPostKey = firebase.database().ref().child('messages').push().key;
+ var updates = {};
+ updates['/messages/' + newPostKey] = record;
+ return firebase.database().ref().update(updates);
+ }
+};
+
+(function (i, s, o, g, r, a, m) {
+ i['GoogleAnalyticsObject'] = r;
+ i[r] = i[r] || function () {
+ (i[r].q = i[r].q || []).push(arguments);
+ }, i[r].l = 1 * new Date();
+ a = s.createElement(o), m = s.getElementsByTagName(o)[0];
+ a.async = 1;
+ a.src = g;
+ m.parentNode.insertBefore(a, m);
+})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
+ga('create', 'UA-6061419-3', 'auto');
+
+var AudioPlayer = function () {
+ function AudioPlayer() {
+ _classCallCheck(this, AudioPlayer);
+
+ this.el = document.getElementById('aphex-audio');
+
+ this.el.addEventListener('play', function (e) {
+ $('#player').addClass('playing');
+ });
+ this.el.addEventListener('pause', function (e) {
+ $('#player').removeClass('playing');
+ });
+
+ this.el.volume = 0.8;
+ }
+
+ _createClass(AudioPlayer, [{
+ key: 'play',
+ value: function play() {
+ this.el.play();
+ }
+ }, {
+ key: 'pause',
+ value: function pause() {
+ this.el.pause();
+ }
+ }, {
+ key: 'isPlaying',
+ value: function isPlaying() {
+ return !this.el.paused;
+ }
+ }, {
+ key: 'toggleAudio',
+ value: function toggleAudio() {
+ this.isPlaying() ? this.pause() : this.play();
+ }
+ }]);
+
+ return AudioPlayer;
+}();
+
+$(document).ready(function () {
+ ga('send', 'pageview', window.location.pathname);
+
+ initScramblers();
+ NTS_AFX.store.init();
+
+ window.audioPlayer = new AudioPlayer();
+
+ var $consoleEntryForm = $('#console-entry-form');
+
+ $consoleEntryForm.focus();
+ $consoleEntryForm.submit(function (e) {
+ e.preventDefault();
+
+ ga('send', 'event', 'Aphex', 'PasswordAttempt');
+
+ var authenticated = NTS_AFX.store.post(e.currentTarget.children['console-entry'].value).then(function (authenticated) {
+
+ if (authenticated) {
+ var $msg = $('#success-message');
+ $msg.addClass('display');
+
+ setTimeout(function () {
+ $msg.removeClass('display');
+ }, 2000);
+
+ authenticated.authenticate();
+ } else {
+ var _$msg = $('#error-message');
+ _$msg.addClass('display');
+
+ setTimeout(function () {
+ _$msg.removeClass('display');
+ }, 1500);
+ }
+
+ e.currentTarget.children['console-entry'].value = "";
+ });
+ });
+
+ $('#nts-link').on('click', function () {
+ ga('send', 'event', 'Aphex', 'GoTo-NTS');
+ });
+
+ $('#warp-link').on('click', function () {
+ ga('send', 'event', 'Aphex', 'GoTo-Warp');
+ });
+
+ $('#player').on('click', function () {
+ window.audioPlayer.toggleAudio();
+ });
+});
+//# sourceMappingURL=prod.js.map
diff --git a/style.scss b/style.scss
new file mode 100644
index 0000000..457cc1e
--- /dev/null
+++ b/style.scss
@@ -0,0 +1,302 @@
+$font: 'Decima', courier;
+$row-width: 500px;
+
+@import "fontello.css";
+
+@font-face {
+ font-family: 'Decima';
+ src: url('fonts/decimamonopro-webfont.woff2') format('woff2'),
+ url('fonts/decimamonopro-webfont.woff') format('woff'),
+ url('fonts/DecimaMonoPro.ttf') format('ttf');
+ font-weight: normal;
+ font-style: normal;
+}
+
+html {
+ background-color: black;
+ color: white;
+
+ font-family: $font;
+
+ min-width: 320px;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+input[type="search"]::-webkit-search-decoration {
+ display: none;
+}
+input {
+ margin: 0;
+ outline: 0;
+ vertical-align: middle;
+ background: none;
+ border: none;
+ color: white;
+ font-family: $font !important;
+ font-size: 1em;
+}
+input[type="reset"], input[type="submit"], input[type="button"] {
+ -webkit-appearance: none;
+ background: none;
+ border: 0;
+ cursor: pointer;
+ overflow: visible;
+ padding: 0;
+ width: auto;
+
+ font-family: $font;
+}
+input::-webkit-input-placeholder { }
+
+a {
+ text-decoration: none;
+ transition: opacity 0.2s linear;
+ &:hover {
+ opacity: 0.7;
+ }
+ &:visited {
+ color: white;
+ }
+ &:-webkit-any-link {
+ color: white;
+ }
+}
+
+#aphex-page {
+ color: white;
+ width: 100%;
+ font-size: 19.5px;
+}
+
+#aphex-console-container {
+ position: absolute;
+
+ top: 50%;
+ left: 0;
+ width: 50%;
+ height: auto;
+
+ padding: 0 20px;
+
+ -webkit-transform: translateY(-50%);
+ -moz-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ -o-transform: translateY(-50%);
+ transform: translateY(-50%);
+
+ max-width: 50%;
+
+ overflow: hidden;
+}
+
+#links-bottom {
+ margin-top: 20px;
+
+ #warp-link {
+ float: left;
+ img {
+ height: 35px;
+ }
+ }
+ #nts-link {
+ float: left;
+ margin-right: 10px;
+ img {
+ width: 35px;
+ }
+ }
+}
+
+#links-top, #console, #console-entry-form, #links-bottom > div {
+ max-width: $row-width;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+#console {
+ .console-row {
+ display: inline-block;
+ }
+
+ .aphexDotPadding {
+ display: inline;
+ }
+
+ #console-entry-form {
+ width: $row-width;
+
+ #console-entry {
+ width: 100%;
+ }
+ }
+}
+
+#aphex-gif-container {
+ position: absolute;
+ float: right;
+ top: 50%;
+ right: 0;
+ width: 50%;
+ -webkit-transform: translateY(-50%);
+ -moz-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ -o-transform: translateY(-50%);
+ transform: translateY(-50%);
+
+ text-align: center;
+
+ img {
+ max-width: 80%;
+ }
+}
+
+#error-message, #success-message {
+ position: absolute;
+ top: 50%;
+ left: 0; right: 0;
+
+ -webkit-transform: translateY(-50%);
+ -moz-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ -o-transform: translateY(-50%);
+ transform: translateY(-50%);
+
+ text-align: center;
+
+ font-size: 6em;
+
+ font-weight: lighter;
+ z-index: 99999;
+
+ visibility: hidden;
+ opacity: 0;
+
+ &.display {
+ visibility: visible;
+ opacity: 1;
+ }
+
+ -webkit-transition: all 0.2s linear;
+ -moz-transition: all 0.2s linear ;
+ -ms-transition: all 0.2s linear ;
+ -o-transition: all 0.2s linear ;
+ transition: all 0.2s linear ;
+}
+#error-message {
+ color: #be0000;
+ text-shadow: 0 0 40px #ab0505;
+}
+#success-message {
+ color: #00d200;
+ text-shadow: 0 0 30px green;
+ overflow: hidden;
+}
+
+audio {
+ display: none;
+}
+#player {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ font-size: 2em;
+ cursor: pointer;
+
+ color: white;
+ opacity: 1;
+
+ //width: 45px;
+ //height: 36px;
+
+ z-index: 9999999999;
+
+ &:hover {
+ opacity: 0.7;
+ cursor: pointer;
+ }
+
+ -webkit-transition: opacity 0.2s linear;
+ -moz-transition: opacity 0.2s linear ;
+ -ms-transition: opacity 0.2s linear ;
+ -o-transition: opacity 0.2s linear ;
+ transition: opacity 0.2s linear ;
+
+ &.playing {
+ #player-play {
+ display: none;
+ }
+
+ #player-pause {
+ display: block;
+ }
+ }
+}
+
+#player-pause {
+ display: none;
+}
+
+@media only screen and (max-width: 700px) {
+ #aphex-page {
+ position: absolute;
+ top: 50%;
+ left: 0; right: 0;
+
+ font-size: 1.2em;
+ height: 450px;
+
+ -webkit-transform: translateY(-50%);
+ -moz-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ -o-transform: translateY(-50%);
+ transform: translateY(-50%);
+ }
+ #aphex-console-container {
+ position: relative;
+ display: block;
+ width: 300px;
+ height: auto;
+ max-width: 100%;
+
+ margin: 0 auto;
+ padding: 0;
+ top: 0;
+
+ overflow: hidden;
+
+ -webkit-transform: none;
+ -moz-transform: none;
+ -ms-transform: none;
+ -o-transform: none;
+ transform: none;
+
+ #nts-link img {
+ width: 30px;
+ }
+ }
+
+ #aphex-gif-container {
+ position: relative;
+ width: 100%;
+ display: block;
+ overflow: auto;
+
+ top: 0;
+
+ padding-top: 0;
+
+ -webkit-transform: none;
+ -moz-transform: none;
+ -ms-transform: none;
+ -o-transform: none;
+ transform: none;
+
+ img {
+ width: 250px;
+ }
+ }
+}
+