text:
window.CONFETTI_HACK = true;

Math.TAU = Math.PI*2;

var particles = [];
var mouseRadius = 300;

window.onload = function(){

	// Canvas!
	var canvas = document.createElement("canvas");
	var w = document.body.clientWidth;
	var h = document.body.clientHeight;
	canvas.width = w*2;
	canvas.height = h*2;
	canvas.style.width = w+"px";
	canvas.style.height = h+"px";
	document.body.appendChild(canvas);

	// Create particles at a certain density
	var density = 1/Math.pow(80,2);
	var area = document.body.clientWidth*(document.body.clientHeight+100*2);
	var count = Math.floor(density*area);
	for(var i=0; i<count; i++){
		var x = _notRandomX();
		var y = i*((document.body.clientHeight*2+200)/count);
		particles.push(new Particle(x,y));
	}

	// Update
	var _tickTimer = 0;
	var update = function(){
		for(var i=0;i<particles.length;i++) particles[i].update();
	};
	setInterval(update,1000/60);
	update();

	// RAF
	var ctx = canvas.getContext("2d");
	var draw = function(){

		// RAF
		window.requestAnimationFrame(draw);

		// Clear
		ctx.clearRect(0,0,canvas.width,canvas.height);

		// Draw Particles
		ctx.globalAlpha = 0.5;
		for(var i=0;i<particles.length;i++) particles[i].draw(ctx);
		ctx.globalAlpha = 1.0;

		// DRAW CIRCLE
		_drawCircle(ctx, mouseRadius*0.7);

	};
	window.requestAnimationFrame(draw);

};

var flipGravity = flipGravity || false;
var yesSway = yesSway || false;
var image = new Image();
image.src = imageSource;
var _x = 0;
var _notRandomX = function(){
	_x += 100*4*(document.body.clientWidth/1280); //whatever
	if(_x>document.body.clientWidth*2) _x-=document.body.clientWidth*2;
	return _x;
};
function Particle(x,y){

	var self = this;
	var w = document.body.clientWidth*2;
	var h = document.body.clientHeight*2;
	self.x = x; //Math.random()*w;
	self.y = y; //Math.random()*h;
	var margin = 100;

	self.vel = {x:0, y:0};

	self.sway = Math.random()*Math.TAU;

	self.update = function(){

		self.x += self.vel.x;
		self.y += self.vel.y;
		self.vel.y += (flipGravity?-1:1) * 0.2;
		self.vel.x *= 0.95;
		self.vel.y *= 0.95;

		if(yesSway){
			self.sway += 0.07;
			var vx = Math.sin(self.sway);
			self.vel.x += vx*0.05;
		}

		// GET AWAY FROM THE MOUSE
		var multiplier = Mouse.pressed?2:1;
		var magnet = 0.25;
		var M = {x:Mouse.x*2, y:Mouse.y*2};
		if(_ifPointTooClose(M, self, mouseRadius*multiplier)){
			var center = [M.x, M.y];
			//debugger;
			_addToVector(center, [-self.x,-self.y]); // relative center
			var power = 1 - (_magnitude(center)/(mouseRadius*multiplier));
			_normalize(center, -magnet*power*multiplier);
			var myVel = [self.vel.x, self.vel.y];
			_addToVector(myVel, center);
			self.vel.x = myVel[0];
			self.vel.y = myVel[1];
		}

		// Bounds
		if(self.x<-margin) self.x=w+margin;
		if(self.y<-margin){
			self.y=h+margin;
			self.x = _notRandomX();
		}
		if(self.x>w+margin) self.x=-margin;
		if(self.y>h+margin){
			self.y=-margin;
			self.x = _notRandomX();
		}

	};

	self.draw = function(ctx){
		ctx.save();
		ctx.translate(self.x, self.y);

		// angle
		var vector = [self.vel.x, 4];
		var a = _vectorToAngle(vector)+imageAngle;
		ctx.rotate(a * (flipGravity?-1:1));

		ctx.drawImage(image, -imageWidth/2, -imageHeight/2, imageWidth, imageHeight);
		ctx.restore();
	};

}


text:
var w = document.body.clientWidth*2;
var h = document.body.clientHeight*2;

// module aliases
var Engine = Matter.Engine,
    Render = Matter.Render,
    Runner = Matter.Runner,
    Composite = Matter.Composite,
    Composites = Matter.Composites,
    Common = Matter.Common,
    MouseConstraint = Matter.MouseConstraint,
    Mouse = Matter.Mouse,
    World = Matter.World,
    Bodies = Matter.Bodies,
    Vertices = Matter.Vertices;

// create an engine
var engine = Engine.create();

// Canvas!
var canvas = document.createElement("canvas");
canvas.width = w;
canvas.height = h;
canvas.style.width = w/2+"px";
canvas.style.height = h/2+"px";
document.body.appendChild(canvas);
var context = canvas.getContext("2d");

var img = new Image();
if(window.SPLASH=="misc"){
    img.src="shrug.png";
}
if(window.SPLASH=="meta"){
    img.src="meta.png";
}

var images = {
    tv: new Image(),
    paper: new Image(),
    mike: new Image(),
    phone: new Image()
};
if(window.SPLASH=="journalism"){
    images.tv.src = "tv.png";
    images.paper.src = "paper.png";
    images.mike.src = "mike.png";
    images.phone.src = "phone.png";
}

(function render() {

    var bodies = Composite.allBodies(engine.world);
    //console.log(bodies.length);

    window.requestAnimationFrame(render);
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.beginPath();

    context.save();
    if(window.SPLASH=="journalism"){
        context.globalAlpha = 0.5;
    }

    // Draw all of 'em
    for (var i = 0; i < bodies.length; i += 1) {
    	if(i<7) continue;

        if(window.SPLASH){

            var body = bodies[i];
            context.save();
            context.translate(body.position.x, body.position.y);
            context.rotate(body.angle);
            var image = img;
            if(body._IMAGE_) image=images[body._IMAGE_];
            context.drawImage(image, -image.width/2, -image.height/2);
            context.restore();

        }else{

            var vertices = bodies[i].vertices;
            context.moveTo(vertices[0].x, vertices[0].y);
            for (var j = 1; j < vertices.length; j += 1) {
                context.lineTo(vertices[j].x, vertices[j].y);
            }
            context.lineTo(vertices[0].x, vertices[0].y);

        }

    }
    if(!window.SPLASH){
        context.lineWidth = 4;
        context.strokeStyle = "rgba(255,255,255,0.5)";
        context.stroke();
    }

    context.restore();

    // DRAW CIRCLE
    _drawCircle(context, 200);

})();

//////////////////////////////////
// CREATE BORDERS (with bump) ////
//////////////////////////////////

var thick = 50;
var lift = 0;

var weirdVertices = [
    { x: w/2-100, y: h-120-lift },
    { x: w/2, y: h-20-lift },
    { x: w/2-100, y: h-20-lift }
];
var weirdFloor = Matter.Body.create({
    position: Matter.Vertices.centre(weirdVertices),
    vertices: weirdVertices,
    isStatic: true
});
var weirdVertices = [
    { x: w/2+100, y: h-120-lift },
    { x: w/2+100, y: h-20-lift },
    { x: w/2, y: h-20-lift }
];
var weirdFloor2 = Matter.Body.create({
    position: Matter.Vertices.centre(weirdVertices),
    vertices: weirdVertices,
    isStatic: true
});

World.add(engine.world, [
    // walls
    Bodies.rectangle(       w/2,  -thick/2,     w, thick, { isStatic: true, restitution:1 }),
    Bodies.rectangle( w+thick/2,       h/2, thick,     h, { isStatic: true, restitution:1 }),
    Bodies.rectangle(  -thick/2,       h/2, thick,     h, { isStatic: true, restitution:1 }),

    Bodies.rectangle( (w/4)-50, h+thick/2-120-lift, (w/2)-100, thick, { isStatic: true, restitution:1 }),
    Bodies.rectangle( (w*3/4)+50, h+thick/2-120-lift, (w/2)-100, thick, { isStatic: true, restitution:1 }),
    weirdFloor,
    weirdFloor2
    //
]);

//////////////////////////////////
// LET THE BODIES HIT THE FLOOR //
//////////////////////////////////

var shapeW = 80;
if(window.SPLASH=="misc"){
    shapeW = 100;
}
if(window.SPLASH=="meta"){
    shapeW = 90;
}
var columns = Math.floor((w/2)/shapeW)-3;
var shapeH = 50;
if(window.SPLASH=="meta"){
    shapeH = 40;
}
var rows = Math.floor((h/2)/shapeH)-3;

var things = [
    {img:"tv", w:200, h:180},
    {img:"paper", w:150, h:160},
    {img:"mike", w:80, h:120},
    {img:"phone", w:80, h:120}
];

// add bodies
var stack = Composites.stack(shapeW, shapeH, columns, rows, shapeW, shapeH, function(x,y) {

    if(!window.SPLASH){

        var sides = Math.round(Common.random(1, 6));
        var shape = Bodies.polygon(x, y, sides, Common.random(25*2, 50*2), {restitution:0.75});
        //debugger;
        shape.position.x += (Math.random()-0.5)*50;
        shape.position.y += (Math.random()-0.5)*50;
        shape.angle += (Math.random()-0.5)*0.5;
        return shape;

    }else if(window.SPLASH=="misc"){

        var rect = Bodies.rectangle(x+(Math.random()-0.5)*200, y, 300, 75);
        Matter.Body.rotate(rect, (Math.random()-0.5)*0.5);
        return rect;

    }else if(window.SPLASH=="meta"){

        var rect = Bodies.rectangle(x+(Math.random()-0.5)*200, y, 200, 54);
        Matter.Body.rotate(rect, (Math.random()-0.5)*0.5);
        return rect;

    }else if(window.SPLASH=="journalism"){

        var thing = things[Math.floor(Math.random()*things.length)];
        var rect = Bodies.rectangle(x+(Math.random()-0.5)*100, y, thing.w, thing.h);
        Matter.Body.rotate(rect, (Math.random()-0.5)*0.5);
        rect._IMAGE_ = thing.img;
        return rect;

    }

});

World.add(engine.world, stack);

//////////////////////////////////
// ZE MOUSE //////////////////////
//////////////////////////////////

// add mouse control
var mouse = Mouse.create(canvas),
    mouseConstraint = MouseConstraint.create(engine, {
        mouse: mouse,
        constraint: {
            stiffness: 0.035,
            render: {
                visible: false
            }
        }
    });

mouse.element.removeEventListener("mousewheel", mouse.mousewheel);
mouse.element.removeEventListener("DOMMouseScroll", mouse.mousewheel);

World.add(engine.world, mouseConstraint);

// run the engine
Engine.run(engine);

repo_language: JavaScript

mime_type: text/html


text:
<!DOCTYPE html>

<link rel="stylesheet" type="text/css" href="../splash.css">


text:
<!DOCTYPE html>

<link rel="stylesheet" type="text/css" href="../splash.css">
<meta charset="utf-8">


text:
Math.TAU = Math.PI*2;

var flockRadius = 500;
var separationRadius = 200;
var runRadius = 300;

window.onload = function(){

	// Canvas!
	var canvas = document.createElement("canvas");
	var w = document.body.clientWidth;
	var h = document.body.clientHeight;
	canvas.width = w*2;
	canvas.height = h*2;
	canvas.style.width = w+"px";
	canvas.style.height = h+"px";
	document.body.appendChild(canvas);

	// Create boids at a certain density
	var density = 1/Math.pow(50,2);
	var area = document.body.clientWidth*document.body.clientHeight;
	var count = Math.floor(density*area);
	for(var i=0; i<count; i++) boids.push(new Boid());

	// Update
	var update = function(){
		for(var i=0;i<boids.length;i++) boids[i].update();
	};
	setInterval(update,1000/60);
	update();

	// RAF
	var ctx = canvas.getContext("2d");
	var draw = function(){

		// Clear
		ctx.clearRect(0,0,canvas.width,canvas.height);
		ctx.lineWidth = 2;

		// Draw Boids
		ctx.strokeStyle = "rgba(255,255,255,0.5)";
		for(var i=0;i<boids.length;i++) boids[i].draw(ctx);

		// DRAW CIRCLE
		_drawCircle(ctx, runRadius*0.7);

		// RAF
		window.requestAnimationFrame(draw);
	};
	window.requestAnimationFrame(draw);

};

var boids = [];
function Boid(){

	var self = this;
	var w = document.body.clientWidth*2;
	var h = document.body.clientHeight*2;
	self.x = Math.random()*w;
	self.y = Math.random()*h;
	self.a = Math.random()*Math.TAU;
	self.speed = 3;
	var margin = 50;

	self.update = function(){

		// Velocity
		self.x += Math.cos(self.a)*self.speed;
		self.y += Math.sin(self.a)*self.speed;

		// Get Closest Boids
		var closestBoids = _tooClose(boids, self, flockRadius);

		if(closestBoids.length>0){

			// Alignment: Sum up angles, these ease into it, yo.
			var myVector = _angleToVector(self.a);
			var theirVector = [0,0];
			for(var i=0;i<closestBoids.length;i++){
				var cb = closestBoids[i];
				_addToVector(theirVector, _angleToVector(cb.a));
			}
			_normalize(theirVector, 0.05);
			_normalize(myVector, 0.95);
			_addToVector(myVector, theirVector);

			// Cohesion: Move towards center of crowd
			var center = _getCenterOfPoints(closestBoids);
			_addToVector(center, [-self.x,-self.y]); // relative center
			_normalize(center, 0.05);
			_normalize(myVector, 0.95);
			_addToVector(myVector, center);

			// Separation: But also away from CLOSEST BOID... if it's TOO close
			var theClosestBoid = _getClosestPoint(closestBoids, self, separationRadius);
			if(theClosestBoid){
				var center = [theClosestBoid.x, theClosestBoid.y];
				_addToVector(center, [-self.x,-self.y]); // relative center
				_normalize(center, -0.1);
				_addToVector(myVector, center);
			}

			// GET AWAY FROM THE MOUSE
			var M = {x:Mouse.x*2, y:Mouse.y*2};
			if(_ifPointTooClose(M, self, runRadius)){
				var center = [M.x, M.y];
				_addToVector(center, [-self.x,-self.y]); // relative center
				var power = 1 - (_magnitude(center)/runRadius);
				if(Mouse.pressed){
					_normalize(center, 0.5*power);
				}else{
					_normalize(center, -0.5*power);
				}
				_addToVector(myVector, center);
			}

			// Turn into an angle!
			self.a = _vectorToAngle(myVector);

		}

		// Bounds
		if(self.x<-margin) self.x=w+margin;
		if(self.y<-margin) self.y=h+margin;
		if(self.x>w+margin) self.x=-margin;
		if(self.y>h+margin) self.y=-margin;

	};

	self.draw = function(ctx){
		ctx.save();
		ctx.translate(self.x, self.y);
		ctx.rotate(self.a);
		ctx.beginPath();
		ctx.moveTo(20, 0);
		ctx.lineTo(-10, 10);
		ctx.lineTo(-10, -10);
		ctx.closePath();
		ctx.stroke();
		ctx.restore();
	};

}


text:
<!DOCTYPE html>
<html>
<head><link rel="stylesheet" type="text/css" href="../splash.css"></head>
<body>	</body>
</html>

<script src="../Circle.js"></script>
<script src="../Mouse.js"></script>
<script>
var NUMS = [0, 1];
var OPACITIES = [0.0, 0.3];
var mouseRadius = 200;
var mouseRadius2 = mouseRadius*mouseRadius;

var updateFn = function(grid, x, y){

	var cell = grid[y][x];

	// Get neighbors, count num of alive
	var neighbors = _getNeighbors(grid, x, y);
	var count = 0;
	for(var i=0; i<neighbors.length; i++){
		if(neighbors[i].state==1) count++;
	}

	// live: < 2 neighbors -> die
	// live: > 3 neighbors -> die
	// dead: = 3 neighbors -> live
	if(cell.state==1){
		if(count<2) cell.nextState=0; // die
		if(count>3) cell.nextState=0; // die
	}else{
		if(count==3) cell.nextState=1; // ALIVE
	}

};
</script>
<script src="ca.js"></script>


text:
<!DOCTYPE html>
<html>
<head><link rel="stylesheet" type="text/css" href="../splash.css"></head>
<body>	</body>
</html>

<script src="../Mouse.js"></script>
<script src="../Circle.js"></script>
<script>
var NUMS = [0, 1, 2];
var OPACITIES = [0.0, 0.05, 0.3];
var mouseRadius = 200;
var mouseRadius2 = mouseRadius*mouseRadius;

var randomChooser = function(){
	if(Math.random()<0.999){
		if(Math.random()<0.8){
			return 0; // empty
		}else{
			return 1; // mobile
		}
	}
	return 2; // seed
};
var updateFn = function(grid, x, y){

	var cell = grid[y][x];

	// If mobile, "walk around" until you hit a seed. Then, become a seed.
	// from: https://www.hermetic.ch/pca/da.htm

	var neighbors = _getNeighbors(grid, x, y);
	if(cell.state==1){

		// Any seed neighbors? Become seed!
		var count = 0;
		for(var i=0; i<neighbors.length; i++){
			if(neighbors[i].state==2) count++;
		}
		if(count>0){
			cell.nextState = 2; // I'm a seed now!
			return;
		}

		// Walk around
		var spots = neighbors.filter(function(n){
			return n.state==0; // empty spot
		});
		if(spots.length>0){
			var spot = spots[Math.floor(Math.random()*spots.length)];
			spot.nextState = cell.state; // "walk" to there
			cell.nextState = 0; // leave empty in THIS spot
		}

	}

	// Empty, and all neighbors empty? become mobile!
	if(cell.state==0){

		var count = 0;
		for(var i=0; i<neighbors.length; i++){
			if(neighbors[i].state==0) count++;
		}
		if(count==8){ // ALL NEIGHBORS EMPTY
			if(Math.random()<0.005){
				cell.nextState = 1; // ...with a certain probability.
			}
		}
	}

};
</script>
<script src="ca.js"></script>


text:
Math.TAU = Math.PI*2;

var _getNeighbors = function(grid, ox, oy){

	var gWidth = grid[0].length;
	var gHeight = grid.length;

	// Get positions...
	var positions = [];
	for(var y=-1; y<=1; y++){
		for(var x=-1; x<=1; x++){

			if(x==0 && y==0) continue;

			var px = (ox + x);
			if(px<0) px+=gWidth;
			if(px>=gWidth) px-=gWidth;

			var py = (oy + y);
			if(py<0) py+=gHeight;
			if(py>=gHeight) py-=gHeight;

			positions.push([px,py]);

		}
	}

	// Get neighbors
	var neighbors = [];
	for(var i=0; i<positions.length; i++){
		var x = positions[i][0];
		var y = positions[i][1];
		neighbors.push(grid[y][x]);
	}

	return neighbors;

};

window.onload = function(){

	// Canvas!
	var canvas = document.createElement("canvas");
	var w = document.body.clientWidth;
	var h = document.body.clientHeight;
	canvas.width = w*2;
	canvas.height = h*2;
	canvas.style.width = w+"px";
	canvas.style.height = h+"px";
	document.body.appendChild(canvas);

	// A grid
	var tileSize = 20;
	var gridWidth = Math.ceil(document.body.clientWidth*2/tileSize);
	var gridHeight = Math.ceil(document.body.clientHeight*2/tileSize);
	var grid = _createGrid(gridWidth, gridHeight, NUMS);

	// Update
	var _tickTimer = 0;
	var update = function(){

		// MOUSE MESSUP
		if(Mouse.pressed){

			// Anything within radius, make RANDOM
			for(var y=0; y<grid.length; y++){
				for(var x=0; x<grid[y].length; x++){
					var dx = (x*tileSize)-Mouse.x*2;
					var dy = (y*tileSize)-Mouse.y*2;
					var d2 = dx*dx+dy*dy;
					if(d2<mouseRadius2){
						var randomNum = randomChooser ? randomChooser() : NUMS[Math.floor(Math.random()*NUMS.length)];
						grid[y][x].state = randomNum;
						grid[y][x].nextState = randomNum;
					}
				}
			}
		}

		// UPDATE
		if(_tickTimer==0){

			// Next State...
			for(var y=0; y<grid.length; y++){
				for(var x=0; x<grid[y].length; x++){
					updateFn(grid, x, y);
				}
			}

			// Sync State!
			for(var y=0; y<grid.length; y++){
				for(var x=0; x<grid[y].length; x++){
					grid[y][x].state = grid[y][x].nextState;
				}
			}

		}
		_tickTimer++;
		if(_tickTimer>5) _tickTimer=0;

	};
	setInterval(update,1000/60);
	update();

	// RAF
	var ctx = canvas.getContext("2d");
	var draw = function(){

		// RAF
		window.requestAnimationFrame(draw);

		// Clear
		ctx.clearRect(0,0,canvas.width,canvas.height);
		ctx.fillStyle = "#fff";

		// Draw Grid
		for(var y=0; y<grid.length; y++){
			var row = grid[y];
			for(var x=0; x<row.length; x++){
				var cell = row[x];
				ctx.globalAlpha = OPACITIES[cell.state];
				ctx.fillRect(x*tileSize, y*tileSize, tileSize, tileSize);
			}
		}

		// DRAW CIRCLE
		ctx.globalAlpha = 1;
		_drawCircle(ctx, mouseRadius);

	};
	window.requestAnimationFrame(draw);

};

var randomChooser = randomChooser || null;
var _createGrid = function(width, height, nums){
	var grid = [];
	for(var y=0; y<height; y++){
		var row = [];
		for(var x=0; x<width; x++){
			var randomNum = randomChooser ? randomChooser() : nums[Math.floor(Math.random()*nums.length)];
			row.push({
				state: randomNum,
				nextState: randomNum
			});
		}
		grid.push(row);
	}
	return grid;
};


text:
Math.TAU = Math.PI*2;

var particles = [];
var mouseRadius = 300;

window.onload = function(){

	// Canvas!
	var canvas = document.createElement("canvas");
	var w = document.body.clientWidth;
	var h = document.body.clientHeight;
	canvas.width = w*2;
	canvas.height = h*2;
	canvas.style.width = w+"px";
	canvas.style.height = h+"px";
	document.body.appendChild(canvas);

	// PARTICLES & CONNECTIONS
	var particles = [];
	var connections = [];

	// Create particles at a certain density
	var density = 1/Math.pow(80,2);
	var area = document.body.clientWidth*(document.body.clientHeight+100*2);
	var count = Math.floor(density*area);

	// Placement: just pick random spots that aren't within a certain radius of others.
	// say, 70 pixels
	var withinRadius = 150;
	var margin = 300;
	for(var i=0; i<count; i++){

		// Get closest possible position...
		var possiblePosition;
		var closestPoint;
		do{
			possiblePosition = {
				x: (Math.random()*((w*2)+margin*2))-margin,
				y: (Math.random()*((h*2)+margin*2))-margin
			};
			closestPoint = _getClosestPoint(particles, possiblePosition, withinRadius);

		}while(closestPoint!=null);

		// And... MAKE IT!
		particles.push(new Particle(possiblePosition.x, possiblePosition.y));

	}

	// FIND THE CONNECTIONS
	var connectionDistance = 275;
	for(var i=0; i<particles.length; i++){
		for(var j=i+1; j<particles.length; j++){
			var from = particles[i];
			var to = particles[j];
			if(_ifPointTooClose(from, to, connectionDistance)){
				connections.push([from, to]);
			}
		}
	}

	// Update
	var _tickTimer = 0;
	var update = function(){
		for(var i=0;i<particles.length;i++) particles[i].update();
	};
	setInterval(update,1000/60);
	update();

	// RAF
	var ctx = canvas.getContext("2d");
	var draw = function(){

		// RAF
		window.requestAnimationFrame(draw);

		// Clear
		ctx.clearRect(0,0,canvas.width,canvas.height);

		// Draw connections
		ctx.strokeStyle = "rgba(255,255,255,0.3)";
		ctx.lineWidth = 2;
		ctx.beginPath();
		for(var i=0;i<connections.length;i++){
			var c = connections[i];
			ctx.moveTo(c[0].x, c[0].y);
			ctx.lineTo(c[1].x, c[1].y);
		}
		ctx.stroke();

		// Draw Particles
		for(var i=0;i<particles.length;i++) particles[i].draw(ctx);

		// DRAW CIRCLE
		_drawCircle(ctx, mouseRadius*0.7);

	};
	window.requestAnimationFrame(draw);

};

var image = new Image();
image.src = imageSource;
var imageWidth = 100;
var imageHeight = 100;

var _x = 0;
var _notRandomX = function(){
	_x += imageWidth*4;
	if(_x>document.body.clientWidth*2) _x-=document.body.clientWidth*2;
	return _x;
};

function Particle(x,y){

	var self = this;
	var w = document.body.clientWidth*2;
	var h = document.body.clientHeight*2;

	self.flip = Math.random()<0.5;

	self.initX = x;
	self.initY = y;
	self.initRotation = window.IS_NEURON ? Math.random()*Math.TAU : (Math.random()-0.5)*0.3;

	self.x = self.initX;
	self.y = self.initY;
	self.rotation = self.initRotation;

	self.spin = Math.random()*Math.TAU;
	self.spinSpeed = 0.003 + Math.random()*0.01;
	self.spinXRadius = 10 + Math.random()*40;
	self.spinYRadius = 10 + Math.random()*40;

	self.sway = Math.random()*Math.TAU;
	self.swaySpeed = 0.003 + Math.random()*0.01;
	self.swayRadius = 0.1 + Math.random()*0.5;

	self.bulgeX = 0;
	self.bulgeY = 0;

	self.update = function(){

		// SPIN & SWAY
		self.spin += self.spinSpeed;
		self.sway += self.swaySpeed;

		// BULGE
		var bulgeX = 0;
		var bulgeY = 0;
		var mx = Mouse.x*2 - self.initX;
		var my = Mouse.y*2 - self.initY;
		var vector = [mx,my];
		var dist = _magnitude(vector);
		if(dist<mouseRadius){
			_normalize(vector);
			var t = dist/mouseRadius;
			var force = (Math.cos(t*Math.TAU/2)+1)/2;
			force *= Mouse.pressed ? 200 : -200;
			if(force>dist) force=dist;
			bulgeX = vector[0]*force;
			bulgeY = vector[1]*force;
		}
		self.bulgeX = self.bulgeX*0.8 + bulgeX*0.2;
		self.bulgeY = self.bulgeY*0.8 + bulgeY*0.2;

		// NEW SHTUFF
		self.x = self.initX + self.bulgeX + Math.sin(self.spin)*self.spinXRadius;
		self.y = self.initY + self.bulgeY + Math.cos(self.spin)*self.spinYRadius;
		self.rotation = self.initRotation + Math.sin(self.spin)*self.swayRadius;

	};

	self.draw = function(ctx){

		ctx.save();

		ctx.translate(self.x, self.y);
		ctx.rotate(self.rotation);
		if(self.flip) ctx.scale(-1,1);

		ctx.drawImage(image, -imageWidth/2, -imageHeight/2, imageWidth, imageHeight);
		ctx.restore();

	};

}


text:
Math.TAU = Math.PI*2;

window.noOuterCircle = true;

var w = document.body.clientWidth;
var h = document.body.clientHeight;

var _makeCanvas = function(DO_NOT_APPEND){
	var canvas = document.createElement("canvas");
	canvas.width = w*2;
	canvas.height = h*2;
	canvas.style.width = w+"px";
	canvas.style.height = h+"px";
	canvas.style.position = "absolute";
	canvas.style.top = 0;
	canvas.style.left = 0;
	if(!DO_NOT_APPEND) document.body.appendChild(canvas);
	return canvas;
};

window.onload = function(){

	// Canvas #1!
	var canvas1 = _makeCanvas();
	var canvas2 = _makeCanvas();
	var tempCanvas = _makeCanvas(true);

	// THE GEAR
	var gear = new Gear(w, h, 200);

	// Update
	var lastMousePressed = false;
	var update = function(){

		// Stop or start?
		if(Mouse.pressed && !lastMousePressed){
			gear.stop();
		}
		if(!Mouse.pressed && lastMousePressed){
			gear.start();
		}
		lastMousePressed = Mouse.pressed;

		// SIMULATED ANNEALING
		if(Mouse.pressed){

			// Each frame, do 100 iterations...
			var temperature = 1;
			var old_cost = _costFunction(gear);
			while(temperature > 0.001 && old_cost>1){

				for(var i=0; i<1; i++){
					gear.newSolution();
		            var new_cost = _costFunction(gear);
		            var ap = _acceptance_probability(old_cost, new_cost, temperature);
		            if(Math.random() < ap){
		                old_cost = new_cost; // stick with it!
		            }else{
		            	gear.oldSolution(); // nope, go back!
		            }
				}

				temperature *= 0.9;

			}

		}

		// Update...
		gear.update();

	};
	setInterval(update,1000/60);
	update();

	var lastX;
	var lastY;

	// RAF
	var ctx1 = canvas1.getContext("2d");
	var ctx2 = canvas2.getContext("2d");
	var tmp = tempCanvas.getContext("2d");
	var draw = function(){

		// Clear
		ctx1.clearRect(0,0,canvas1.width,canvas1.height);

		// Draw Gear
		ctx1.strokeStyle = "rgba(255,255,255,0.2)";
		ctx1.lineWidth = 2;
		ctx1.beginPath();
		gear.draw(ctx1);
		ctx1.closePath();
		ctx1.stroke();

		// DRAW CURSOR CIRCLE
		_drawCircle(ctx1, 200);

		//////////////////////////////
		// CANVAS 2: THE SHINY PATH //
		//////////////////////////////

		var finalPoint = _findFinalPoint(gear);
		var x = finalPoint.x;
		var y = finalPoint.y;

		/*if(Mouse.pressed){

			ctx2.clearRect(0,0,canvas2.width,canvas2.height);

			ctx2.fillStyle = "#fff";
			ctx2.beginPath();
			ctx2.arc(x, y, 10, 0, Math.TAU, false);
			ctx2.closePath();
			ctx2.fill();

		}else{*/

			tmp.clearRect(0,0,tempCanvas.width,tempCanvas.height);
			tmp.drawImage(canvas2, 0, 0);
			ctx2.clearRect(0,0,canvas2.width,canvas2.height);
			//ctx2.globalAlpha = 0.99;
			ctx2.globalAlpha = Mouse.pressed ? 0.5 : 0.99;
			ctx2.drawImage(tempCanvas, 0, 0);
			ctx2.globalAlpha = 1.00;

			if(!lastX && !lastY){
				lastX = x;
				lastY = y;
			}

			ctx2.strokeStyle = "#fff";
			ctx2.lineCap = "round";
			ctx2.lineJoin = "round";
			ctx2.lineWidth = 20;
			ctx2.beginPath();
			ctx2.moveTo(lastX, lastY);
			ctx2.lineTo(x,y);
			ctx2.closePath();
			ctx2.stroke();

		//}

		lastX = x;
		lastY = y;

		///////////////////////////

		// RAF
		window.requestAnimationFrame(draw);
	};
	window.requestAnimationFrame(draw);

};

var _acceptance_probability = function(old_cost, new_cost, temperature){
	return Math.exp( (old_cost-new_cost)/temperature );
};

var _costFunction = function(startGear){

	var finalPoint = _findFinalPoint(startGear);
	var x = finalPoint.x;
	var y = finalPoint.y;

	var dx = x - Mouse.x*2;
	var dy = y - Mouse.y*2;

	return Math.sqrt(dx*dx + dy*dy);

}

var _findFinalPoint = function(startGear){

	var x = startGear.x;
	var y = startGear.y;
	var a = 0;
	var g = startGear;
	while(g){

		// The position...
		a += g.rotation;
		x += Math.cos(a)*g.radius;
		y += Math.sin(a)*g.radius;

		// Next gear...
		g = g.gear;

	}

	return { x:x, y:y };

};

function Gear(x,y,radius){

	var self = this;

	self.x = x;
	self.y = y;
	self.radius = radius;
	self.rotation = 0;
	var _randomSpeed = function(){
		self.speed = (Math.random()*2-1)*0.05;
	};
	_randomSpeed();

	if(self.radius>100){
		self.gear = new Gear(self.radius, 0, self.radius*0.8);
	}

	// WHEN MOUSE UP/DOWN

	self.stop = function(){
		self.speed = 0;
		if(self.gear) self.gear.stop();
	};
	self.start = function(){
		_randomSpeed();
		if(self.gear) self.gear.start();
	};

	// SIM ANNEAL

	self.oldRotation = self.rotation;
	self.newSolution = function(){
		self.oldRotation = self.rotation;
		self.rotation += (Math.random()*2-1)*0.01;
		if(self.gear) self.gear.newSolution();
	};
	self.oldSolution = function(){
		self.rotation = self.oldRotation;
		if(self.gear) self.gear.oldSolution();
	};

	self.update = function(){

		// Me
		self.rotation += self.speed;

		// Subgear
		if(self.gear) self.gear.update();

	};

	self.draw = function(ctx){
		ctx.save();
		ctx.translate(self.x, self.y);
		ctx.rotate(self.rotation);
		ctx.moveTo(0,0);
		ctx.arc(0, 0, self.radius, 0, Math.TAU, false);
		if(self.gear) self.gear.draw(ctx);
		ctx.restore();
	};

}


text:
<!DOCTYPE html>

	<base href='/'>
	<title>Chemistry | Explorable Explanations</title>

	<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
	<meta content="utf-8" http-equiv="encoding">
	<meta charset="utf-8">
	<meta name="viewport" content="width=640">
	<link rel="icon" type="image/png" href="favicon.png">

	<meta itemprop="name" content="Chemistry | Explorable Explanations">
	<meta itemprop="description" content="a hub for learning through play">
	<meta itemprop="image" content="http://explorabl.es/-sharing/index.png">

	<meta name="twitter:card" content="summary_large_image">
	<meta name="twitter:title" content="Chemistry | Explorable Explanations">
	<meta name="twitter:description" content="a hub for learning through play">
	<meta name="twitter:image" content="http://explorabl.es/-sharing/index.png">

	<meta property="og:title" content="Chemistry | Explorable Explanations">
	<meta property="og:type" content="website">
	<meta property="og:url" content="http://explorabl.es/">
	<meta property="og:image" content="http://explorabl.es/-sharing/index.png">
	<meta property="og:description" content="a hub for learning through play">

	<link rel="stylesheet" type="text/css" href="-css/page.css">

		Sorry! Explorable Explanations needs JavaScript.
		Don't worry, there's no tracking code or anything creepy like that,
		the JS is just so I can dynamically load shtuff.
		Thanks!

CHEMISTRY

Look around you. The world is made of stuff. How does stuff become stuff? How do you make one stuff into another stuff? Why does stuff stuff stuff stuff stuff?

Here’s some explorable explanations about chemistry, because matter matters:

[loading...]

				Play Explorable Explanations in specific subjects:

				Make your own Explorable Explanations:

				See everything on one page:

				ALL OF IT

				Explorable Explanations is, above all, an experiment.
				None of us know anything, and that's exciting.
				We'd love for you to join us, in playing & making these interactive things!

				There's a lot to explore with Explorable Explanations. ♥

				@explorables
				r/explorables

			this website is open sauce

			get code & see credits!

			<sharing title="Explorable Explanations"
				 text="Explorable Explanations, a hub for learning through play:"
				 link="http://explorabl.es/"></sharing>


text:
<!DOCTYPE html>

	<base href='/'>
	<title>Earth Science | Explorable Explanations</title>

	<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
	<meta content="utf-8" http-equiv="encoding">
	<meta charset="utf-8">
	<meta name="viewport" content="width=640">
	<link rel="icon" type="image/png" href="favicon.png">

	<meta itemprop="name" content="Earth Science | Explorable Explanations">
	<meta itemprop="description" content="a hub for learning through play">
	<meta itemprop="image" content="http://explorabl.es/-sharing/index.png">

	<meta name="twitter:card" content="summary_large_image">
	<meta name="twitter:title" content="Earth Science | Explorable Explanations">
	<meta name="twitter:description" content="a hub for learning through play">
	<meta name="twitter:image" content="http://explorabl.es/-sharing/index.png">

	<meta property="og:title" content="Earth Science | Explorable Explanations">
	<meta property="og:type" content="website">
	<meta property="og:url" content="http://explorabl.es/">
	<meta property="og:image" content="http://explorabl.es/-sharing/index.png">
	<meta property="og:description" content="a hub for learning through play">

	<link rel="stylesheet" type="text/css" href="-css/page.css">

		Sorry! Explorable Explanations needs JavaScript.
		Don't worry, there's no tracking code or anything creepy like that,
		the JS is just so I can dynamically load shtuff.
		Thanks!

EARTH SCIENCE

A big, blue-green rock hurtling through the cold, empty void. Or in other words: home.

Here’s some explorables about our one and only Earth:

[loading...]

				Play Explorable Explanations in specific subjects:

				Make your own Explorable Explanations:

				See everything on one page:

				ALL OF IT

				Explorable Explanations is, above all, an experiment.
				None of us know anything, and that's exciting.
				We'd love for you to join us, in playing & making these interactive things!

				There's a lot to explore with Explorable Explanations. ♥

				@explorables
				r/explorables

			this website is open sauce

			get code & see credits!

			<sharing title="Explorable Explanations"
				 text="Explorable Explanations, a hub for learning through play:"
				 link="http://explorabl.es/"></sharing>


text:
<!DOCTYPE html>

	<base href='/'>
	<title>ALL OF IT | Explorable Explanations</title>

	<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
	<meta content="utf-8" http-equiv="encoding">
	<meta charset="utf-8">
	<meta name="viewport" content="width=640">
	<link rel="icon" type="image/png" href="favicon.png">

	<meta itemprop="name" content="ALL OF IT | Explorable Explanations">
	<meta itemprop="description" content="a hub for learning through play">
	<meta itemprop="image" content="http://explorabl.es/-sharing/index.png">

	<meta name="twitter:card" content="summary_large_image">
	<meta name="twitter:title" content="ALL OF IT | Explorable Explanations">
	<meta name="twitter:description" content="a hub for learning through play">
	<meta name="twitter:image" content="http://explorabl.es/-sharing/index.png">

	<meta property="og:title" content="ALL OF IT | Explorable Explanations">
	<meta property="og:type" content="website">
	<meta property="og:url" content="http://explorabl.es/">
	<meta property="og:image" content="http://explorabl.es/-sharing/index.png">
	<meta property="og:description" content="a hub for learning through play">

	<link rel="stylesheet" type="text/css" href="-css/page.css">

		Sorry! Explorable Explanations needs JavaScript.
		Don't worry, there's no tracking code or anything creepy like that,
		the JS is just so I can dynamically load shtuff.
		Thanks!

ALL OF IT

Here's ALL ... ENTRIES we have so far: both interactive explorable explanations, and articles/talks about explorable explanations. Enjoy!

[loading...]

				Play Explorable Explanations in specific subjects:

				Make your own Explorable Explanations:

				See everything on one page:

				ALL OF IT

				Explorable Explanations is, above all, an experiment.
				None of us know anything, and that's exciting.
				We'd love for you to join us, in playing & making these interactive things!

				There's a lot to explore with Explorable Explanations. ♥

				@explorables
				r/explorables

			this website is open sauce

			get code & see credits!

			<sharing title="Explorable Explanations"
				 text="Explorable Explanations, a hub for learning through play:"
				 link="http://explorabl.es/"></sharing>


text:
<!DOCTYPE html>

	<base href='/'>
	<title>Psychology | Explorable Explanations</title>

	<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
	<meta content="utf-8" http-equiv="encoding">
	<meta charset="utf-8">
	<meta name="viewport" content="width=640">
	<link rel="icon" type="image/png" href="favicon.png">

	<meta itemprop="name" content="Psychology | Explorable Explanations">
	<meta itemprop="description" content="a hub for learning through play">
	<meta itemprop="image" content="http://explorabl.es/-sharing/index.png">

	<meta name="twitter:card" content="summary_large_image">
	<meta name="twitter:title" content="Psychology | Explorable Explanations">
	<meta name="twitter:description" content="a hub for learning through play">
	<meta name="twitter:image" content="http://explorabl.es/-sharing/index.png">

	<meta property="og:title" content="Psychology | Explorable Explanations">
	<meta property="og:type" content="website">
	<meta property="og:url" content="http://explorabl.es/">
	<meta property="og:image" content="http://explorabl.es/-sharing/index.png">
	<meta property="og:description" content="a hub for learning through play">

	<link rel="stylesheet" type="text/css" href="-css/page.css">

		Sorry! Explorable Explanations needs JavaScript.
		Don't worry, there's no tracking code or anything creepy like that,
		the JS is just so I can dynamically load shtuff.
		Thanks!

PSYCHOLOGY

You are a three-pound ball of wrinkly meat, sitting in a boney sphere, reading these words through two holes in the front. And it’s not just you — all your friends, your loved ones, every person that lives, has lived, will live — is also a thinking, dreaming, wet sponge-y ball of meat.

Here’s some explorable explanations about the miracle that is the human mind:

[loading...]

				Play Explorable Explanations in specific subjects:

				Make your own Explorable Explanations:

				See everything on one page:

				ALL OF IT

				Explorable Explanations is, above all, an experiment.
				None of us know anything, and that's exciting.
				We'd love for you to join us, in playing & making these interactive things!

				There's a lot to explore with Explorable Explanations. ♥

				@explorables
				r/explorables

			this website is open sauce

			get code & see credits!

			<sharing title="Explorable Explanations"
				 text="Explorable Explanations, a hub for learning through play:"
				 link="http://explorabl.es/"></sharing>


text:
<!DOCTYPE html>

	<base href='/'>
	<title>FAQ | Explorable Explanations</title>

	<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
	<meta content="utf-8" http-equiv="encoding">
	<meta charset="utf-8">
	<meta name="viewport" content="width=640">
	<link rel="icon" type="image/png" href="favicon.png">

	<meta itemprop="name" content="FAQ | Explorable Explanations">
	<meta itemprop="description" content="a hub for learning through play">
	<meta itemprop="image" content="http://explorabl.es/-sharing/index.png">

	<meta name="twitter:card" content="summary_large_image">
	<meta name="twitter:title" content="FAQ | Explorable Explanations">
	<meta name="twitter:description" content="a hub for learning through play">
	<meta name="twitter:image" content="http://explorabl.es/-sharing/index.png">

	<meta property="og:title" content="FAQ | Explorable Explanations">
	<meta property="og:type" content="website">
	<meta property="og:url" content="http://explorabl.es/">
	<meta property="og:image" content="http://explorabl.es/-sharing/index.png">
	<meta property="og:description" content="a hub for learning through play">

	<link rel="stylesheet" type="text/css" href="-css/page.css">

		Sorry! Explorable Explanations needs JavaScript.
		Don't worry, there's no tracking code or anything creepy like that,
		the JS is just so I can dynamically load shtuff.
		Thanks!

FREQUENTLY ASKED
QUESTIONS

Are these questions actually asked, or are these just questions you want to answer?

...next question.

So what is an Explorable Explanation?

Haha, I have no idea.

But seriously: since it's early days, we're keeping the definition pretty open! This website contains everything from videogames, to sandbox toys, to interactive graphics/articles/textbooks.

In short, by "explorable explanation" we mean something that 1) teaches something, and 2) is more interactive than a boring ol' quiz with only one right answer.

Ooh, this is like "gamification", right?

[sharp inhale]

hnnnnnnnnnngh okay I don't want to police other peoples' use of words, but my problem with "gamification" is that people usually use it to refer to the worst kind of game design: the "do some task and get some reward" skinner box.

Those are called "extrinsic rewards", and while they're good for motivating people to do boring, routine tasks, they're incredibly damaging for creativity & learning. Better instead to tap into "intrinsic rewards": peoples' inner sense of curiosity, mastery, autonomy, expression, purpose.

That's what Explorable Explanations aims to do. Not wrapping stale school material in gold stars and high scores.

Are the Featured (★) explorables the best ones?

Not necessarily! The ones we're featuring are just the ones we think would serve as the best introduction to what play can do for learning. So if there's a thing that's otherwise amazing & educational, but only uses minimal interaction (or isn't free, or requires a download), we maaaaay not pick it as a Featured (★) explorable. Maybe.

Long story short: it's pretty freakin' arbitrary.

How do I get started making my own explorable?

You've already started! Browse this site for examples of explorables to inspire you. Check out the tools and tutorials pages, to learn how to make explorables. And if you want to get a deeper sense for why play matters so much to learning, check out the further reading!

[loading...]

				Play Explorable Explanations in specific subjects:

				Make your own Explorable Explanations:

				See everything on one page:

				ALL OF IT

				Explorable Explanations is, above all, an experiment.
				None of us know anything, and that's exciting.
				We'd love for you to join us, in playing & making these interactive things!

				There's a lot to explore with Explorable Explanations. ♥

				@explorables
				r/explorables

			this website is open sauce

			get code & see credits!

			<sharing title="Explorable Explanations"
				 text="Explorable Explanations, a hub for learning through play:"
				 link="http://explorabl.es/"></sharing>


text:
<!DOCTYPE html>

	<base href='/'>
	<title>Civics | Explorable Explanations</title>

	<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
	<meta content="utf-8" http-equiv="encoding">
	<meta charset="utf-8">
	<meta name="viewport" content="width=640">
	<link rel="icon" type="image/png" href="favicon.png">

	<meta itemprop="name" content="Civics | Explorable Explanations">
	<meta itemprop="description" content="a hub for learning through play">
	<meta itemprop="image" content="http://explorabl.es/-sharing/index.png">

	<meta name="twitter:card" content="summary_large_image">
	<meta name="twitter:title" content="Civics | Explorable Explanations">
	<meta name="twitter:description" content="a hub for learning through play">
	<meta name="twitter:image" content="http://explorabl.es/-sharing/index.png">

	<meta property="og:title" content="Civics | Explorable Explanations">
	<meta property="og:type" content="website">
	<meta property="og:url" content="http://explorabl.es/">
	<meta property="og:image" content="http://explorabl.es/-sharing/index.png">
	<meta property="og:description" content="a hub for learning through play">

	<link rel="stylesheet" type="text/css" href="-css/page.css">

		Sorry! Explorable Explanations needs JavaScript.
		Don't worry, there's no tracking code or anything creepy like that,
		the JS is just so I can dynamically load shtuff.
		Thanks!

CIVICS

How can our democracy be well-informed, if we’re not well-informed about our democracy? Here are some explorable explanations of how our complex governmental machinery works... or doesn’t work:

[loading...]

				Play Explorable Explanations in specific subjects:

				Make your own Explorable Explanations:

				See everything on one page:

				ALL OF IT

				Explorable Explanations is, above all, an experiment.
				None of us know anything, and that's exciting.
				We'd love for you to join us, in playing & making these interactive things!

				There's a lot to explore with Explorable Explanations. ♥

				@explorables
				r/explorables

			this website is open sauce

			get code & see credits!

			<sharing title="Explorable Explanations"
				 text="Explorable Explanations, a hub for learning through play:"
				 link="http://explorabl.es/"></sharing>


text:
**Are these questions actually asked, or are these just questions you want to answer?**

...next question.

**So what *is* an Explorable Explanation?**

Haha, I have no idea.

But seriously: since it's early days, we're keeping the definition pretty open! By "explorable explanation" we mean something that 1) teaches something, and 2) is more interactive than a boring ol' quiz with only one right answer.

**Ooh, this is like "gamification", right?**

[sharp inhale]

hnnnnnnnnnngh okay I don't want to police other peoples' use of words, but my problem with "gamification" is that people usually use it to refer to the _worst kind_ of game design: the "do some task and get some reward" skinner box.

Those are called "extrinsic rewards", and while they're good for motivating people to do boring, routine tasks, they're _incredibly damaging_ for creativity & learning. Better instead to tap into "intrinsic rewards": peoples' inner sense of curiosity, mastery, autonomy, expression, purpose.

_That's_ what Explorable Explanations aims to do. Not wrapping stale school material in gold stars and high scores.

**Are the Featured (★) explorables the best explorables?**

Not necessarily! The ones we're featuring are just the ones we think would serve as _the best introduction_ to what play can do for learning. So if there's a thing that's otherwise amazing & educational, but only uses minimal interaction (or isn't free, or requires a download), we maaaaay not pick it as a Featured (★) explorable. Maybe.

Long story short: it's pretty freakin' arbitrary.

**How do I get started making my own explorable?**

You've already started! Browse this site for examples of explorables to inspire you. Check out the [tools](/tools) and [tutorials](/tutorials) pages, to learn how to make explorables. And if you want to get a deeper sense for *why* play matters so much to learning, check out the [further reading](/reading)!


text:
{

	/////////////////////////////
	// THE INDEX ////////////////
	/////////////////////////////

	"index": {
		"title": "",

		"splashTitle": "
			EX
			PLO
			RABLE

			EXPLANATIONS",

		"intro": "

			Lion cubs play-fight to learn social skills.
			Rats play to learn emotional skills.
			Monkeys play to learn cognitive skills.
			And yet, in the last century, we humans have convinced ourselves that
			play is useless, and learning is supposed to be boring.

			Gosh, no wonder we’re all so miserable.

			Welcome to Explorable Explanations,
			a hub for learning through play!
			We’re a disorganized “movement” of artists, coders & educators
			who want to reunite play and learning.

			Let's get started! Check out these 3 random Explorables:

		",

		"splash": "boids/boids.html",
		"gallery": {
			"index": true,
			"sort": "random",
			"count": 3
		}
	},

	"all": {
		"title": "ALL OF IT",

		"splashTitle": "ALL OF IT",

		"intro": "

			Here's ALL ... ENTRIES we have so far:
			both interactive explorable explanations, and articles/talks about explorable explanations.
			Enjoy!

		",

		"splash": "boids/boids.html",
		"gallery": {
			"sort": "featured-first"
		}
	},

	/////////////////////////////
	// THE EXPLORABLE TAGS //////
	/////////////////////////////

	"math": {
		"title": "Math",

		"splashTitle": "MATH",

		"intro": "

			Galileo Galilei once said: “Mathematics is the language with which God has written the universe.”
			Too bad most schools are awful at helping us become fluent in Universe.

			So, instead, here’s a bunch of mathematical games which
			can help you learn the Universe’s language, through play:

		",

		"splash": "math/math.html",
		"gallery": {
			"sort": "featured-first"
		}
	},

	"social": {
		"title": "Social Science",

		"splashTitle": "SOCIAL SCIENCE",
		"customCSS": "@media (max-width: 960px){ #splash_title{ width: 500px; margin: 70px auto; } }",

		"intro": "

			Now, more than ever, we need to understand people, and create more understanding people.
			So, here’s some stuff that let you explore what it means to be human(s):

		",

		"splash": "network/social.html",
		"gallery": {
			"sort": "featured-first"
		}
	},

	"art": {
		"title": "Arts",

		"splashTitle": "THE ARTS",

		"intro": "

			We play music, we put on a play, we type up screenplays.
			That’s what art is: play, playing with ideas and materials and human emotions.
			So, here’s some games & interactives to help you better understand different forms of art:

		",

		"splash": "confetti/art.html",
		"gallery": {
			"sort": "featured-first"
		}
	},

	"civics": {
		"title": "Civics",

		"splashTitle": "CIVICS",
		"intro": "

			How can our democracy be well-informed, if we’re not well-informed about our democracy?
			Here are some explorable explanations of how our complex governmental machinery works...
			or doesn’t work:

		",

		"splash": "confetti/civics.html",
		"gallery": {
			"sort": "featured-first"
		}
	},

	"biology": {
		"title": "Biology",

		"splashTitle": "BIOLOGY",
		"intro": "

			Of all the things in our vast universe,
			only an eeny, teeny, weeny fraction of those things can grow, can evolve,
			can have goals, can take action towards those goals.
			It’s that mysterious property we call: being alive.

			Here’s some explorables about the magic of life:

		",

		"splash": "ca/growth.html",
		"gallery": {
			"sort": "featured-first"
		}
	},

	"journalism": {
		"title": "Journalism",

		"splashTitle": "JOURNALISM",
		"customCSS": "@media (max-width: 800px){ #splash_title{ margin-top:130px; font-size:85px; } }",

		"intro": "

			Journalism, at its best, empowers us to be active citizens.
			And what better way to do that, than to make the journalistic articles themselves active?

			Here’s some interactive pieces of journalism, that let readers understand current events in a deeper way:

		",

		"splash": "physics/journalism.html",
		"gallery": {
			"sort": "featured-first"
		}
	},

	"philosophy": {
		"title": "Philosophy",

		"splashTitle": "PHILOSOPHY",
		"customCSS": "@media (max-width: 800px){ #splash_title{ margin-top:130px; font-size:90px; } }",

		"intro": "

			Why? How? What if? Philosophy is the act of playing with ideas —
			so, here’s a list of philosophical games, that let you ask deep questions, through play:

		",

		"splash": "confetti/philosophy.html",
		"gallery": {
			"sort": "featured-first"
		}
	},

	"physics": {
		"title": "Physics",

		"splashTitle": "PHYSICS",

		"intro": "

			Gedankenexperiment.
			That’s the German word Albert Einstein used to explain what he did.
			Gedanken = thoughts, experiment = experiment.
			By playing with thought experiments in his head, good ol’ Al
			could unlock the secrets of the universe.

			Here’s some explorable explanations of physics,
			so you can learn by playing with ideas, theories, simulations...
			gedankenexperiments.

		",

		"splash": "physics/physics.html",
		"gallery": {
			"sort": "featured-first"
		}
	},

	"chemistry": {
		"title": "Chemistry",

		"splashTitle": "CHEMISTRY",
		"customCSS": "@media (max-width: 800px){ #splash_title{ margin-top:125px; font-size:100px; } }",

		"intro": "

			Look around you. The world is made of stuff. How does stuff become stuff?
			How do you make one stuff into another stuff? Why does stuff stuff stuff stuff stuff?

			Here’s some explorable explanations about chemistry, because matter matters:

		",

		"splash": "ca/bz.html",
		"gallery": {
			"sort": "featured-first"
		}
	},

	"psychology": {
		"title": "Psychology",

		"splashTitle": "PSYCHOLOGY",
		"customCSS": "@media (max-width: 860px){ #splash_title{ margin-top:135px; font-size:90px; } }",

		"intro": "

			You are a three-pound ball of wrinkly meat, sitting in a boney sphere,
			reading these words through two holes in the front.
			And it’s not just you — all your friends, your loved ones, every person that lives,
			has lived, will live — is also a thinking, dreaming, wet sponge-y ball of meat.

			Here’s some explorable explanations about the miracle that is the human mind:

		",

		"splash": "network/psych.html",
		"gallery": {
			"sort": "featured-first"
		}
	},

	"economics": {
		"title": "Economics",

		"splashTitle": "ECONOMICS",
		"customCSS": "@media (max-width: 800px){ #splash_title{ margin-top:125px; font-size:100px; } }",

		"intro": "

			It makes the world go round. It’s the root of all evil. It can’t buy happiness.
			It doesn’t grow on trees. It talks.

			We're all part of a complex economic system, so we'd best understand it.
			And one way we can understand economics, is through play!
			Maybe that'd make “the dismal science” a lil’ less dismal:

		",

		"splash": "confetti/econ.html",
		"gallery": {
			"sort": "featured-first"
		}
	},

	"programming": {
		"title": "Programming",

		"splashTitle": "PROGRAMMING",
		"customCSS": "@media (max-width: 960px){ #splash_title{ margin-top:140px; font-size:75px; } }",

		"intro": "

			Imagine you had a genie who, with the right sequence of words,
			you could command to create magic. Now imagine it’s a genie who grants wishes really literally,
			and if you mispronounce a single word the genie explodes.

			That’s what programming is like. Here’s some explorable explanations to give you a less scary,
			more playful guide to creating code:

		",

		"splash": "ca/conway.html",
		"gallery": {
			"sort": "featured-first"
		}
	},

	"earth": {
		"title": "Earth Science",

		"splashTitle": "EARTH SCIENCE",
		"customCSS": "@media (max-width: 900px){ #splash_title{ width: 500px; margin: 70px auto; } }",

		"intro": "

			A big, blue-green rock hurtling through the cold, empty void. Or in other words: home.

			Here’s some explorables about our one and only Earth:

		",

		"splash": "earth/earth.html",
		"gallery": {
			"sort": "featured-first"
		}
	},

	"meta": {
		"title": "Meta",

		"splashTitle": "META",

		"intro": "

			Sometimes, it’s hard to explain what an explorable explanation is.
			So, here are some explorable explanations about explorable explanations:

		",

		"splash": "physics/meta.html",
		"gallery": {
			"sort": "featured-first"
		}
	},

	"misc": {
		"title": "Misc",

		"splashTitle": "MISCELLANEOUS",
		"customCSS": "@media (max-width: 1000px){ #splash_title{ margin-top:135px; font-size:75px; } }",

		"intro": "

...and here’s all the shtuff I couldn’t figure out how to categorize:

		",

		"splash": "physics/misc.html",
		"gallery": {
			"sort": "featured-first"
		}
	},

	/////////////////////////////
	// THE NON-EXPLORABLE TAGS //
	/////////////////////////////

	"tools": {
		"title": "Tools",

		"splashTitle": "TOOLS",

		"intro": "

			Want to make your own explorable explanations?
			Well, you’re in... partial luck!
			Here’s a list of tools to make explorables, that require little or NO programming:

		",

		"splash": "boids/boids.html",
		"gallery": {
			"sort": "featured-first"
		}
	},
	"tutorials": {
		"title": "Tutorials",

		"splashTitle": "TUTORIALS",
		"customCSS": "@media (max-width: 700px){ #splash_title{ margin-top:120px; font-size:110px; } }",

		"intro": "

			Tools are just what you make things with —
			but you also need to know how to make things!

			Here’s a list of tutorials (or at least thoughts) on how to design your own explorable explanation:

		",

		"splash": "boids/boids.html",
		"gallery": {
			"sort": "featured-first"
		}
	},
	"reading": {
		"title": "Further Reading",

		"splashTitle": "FURTHER READING",
		"customCSS": "@media (max-width: 1100px){ #splash_title{ width: 640px; margin: 65px auto; } }",

		"intro": "

			We shouldn't make chocolate-covered broccoli.
			That is: we shouldn’t just take old, soul-sucking educational materials and simply slap superficial
			“fun” “game” “play” on top. We need to understand why play matters, on a deeper level.

			Tools are the “what”. Tutorials are the “how”. These books, talks, and essays show us the why:

		",

		"splash": "boids/boids.html",
		"gallery": {
			"sort": "featured-first"
		}
	},
	"faq": {
		"title": "FAQ",

		"splashTitle": "FREQUENTLY ASKED
QUESTIONS",
		"customCSS": "
			#splash_title{ font-size: 110px; line-height: 1em; margin-top: 60px; }
			@media (max-width: 1050px){ #splash_title{ width:640px; margin: 50px auto; font-size: 80px; } }
		",

		"intro": "

Are these questions actually asked, or are these just questions you want to answer?

...next question.

So what is an Explorable Explanation?

Haha, I have no idea.

		But seriously: since it's early days, we're keeping the definition pretty open!
		This website contains everything from videogames, to sandbox toys,
		to interactive graphics/articles/textbooks.

		In short, by "explorable explanation" we mean something that 1) teaches something, and 2) is more interactive than a boring ol' quiz with only one right answer.

Ooh, this is like "gamification", right?

[sharp inhale]

hnnnnnnnnnngh okay I don't want to police other peoples' use of words, but my problem with "gamification" is that people usually use it to refer to the worst kind of game design: the "do some task and get some reward" skinner box.

Those are called "extrinsic rewards", and while they're good for motivating people to do boring, routine tasks, they're incredibly damaging for creativity & learning. Better instead to tap into "intrinsic rewards": peoples' inner sense of curiosity, mastery, autonomy, expression, purpose.

That's what Explorable Explanations aims to do. Not wrapping stale school material in gold stars and high scores.

Are the Featured (★) explorables the best ones?

Not necessarily! The ones we're featuring are just the ones we think would serve as the best introduction to what play can do for learning. So if there's a thing that's otherwise amazing & educational, but only uses minimal interaction (or isn't free, or requires a download), we maaaaay not pick it as a Featured (★) explorable. Maybe.

Long story short: it's pretty freakin' arbitrary.

How do I get started making my own explorable?

You've already started! Browse this site for examples of explorables to inspire you. Check out the tools and tutorials pages, to learn how to make explorables. And if you want to get a deeper sense for why play matters so much to learning, check out the further reading!

		",

		"splash": "boids/boids.html",
		"gallery": {
			"sort": "featured-first"
		}
	}

	//
Great! Ping us at

}


text:
[

	/////////////////////////////
	// THE EXPLORABLE TAGS //////
	/////////////////////////////

	{
		"id": "philosophy",
		"name": "philosophy",
		"color": "#A0522D",
		"explorable": true
	},
	{
		"id": "math",
		"name": "math",
		"color": "hsl(220, 70%, 56%)",
		"explorable": true
	},
	{
		"id": "physics",
		"name": "physics",
		"color": "hsl(210, 53%, 70%)",
		"explorable": true
	},
	{
		"id": "chemistry",
		"name": "chemistry",
		"color": "#4B0082",
		"explorable": true
	},
	{
		"id": "biology",
		"name": "biology",
		"color": "hsl(90, 100%, 36%)",
		"explorable": true
	},
	{
		"id": "psychology",
		"name": "psychology",
		"color": "#FF69B4",
		"explorable": true
	},
	{
		"id": "social",
		"name": "social science",
		"color": "#FFA500",
		"explorable": true
	},
	{
		"id": "art",
		"name": "art",
		"color": "#ff4040",
		"explorable": true
	},
	{
		"id": "civics",
		"name": "civics",
		"color": "#ffcc00",
		"explorable": true
	},
	{
		"id": "journalism",
		"name": "journalism",
		"color": "hsl(270, 100%, 47%)",
		"explorable": true
	},
	{
		"id": "economics",
		"name": "economics",
		"color": "hsl(90, 100%, 20%)",
		"explorable": true
	},
	{
		"id": "programming",
		"name": "programming",
		"color": "#E91E63",
		"explorable": true
	},
	{
		"id": "earth",
		"name": "earth science",
		"color": "#0dd4ba",
		"explorable": true
	},
	{
		"id": "meta",
		"name": "meta",
		"color": "#222",
		"explorable": true
	},
	{
		"id": "misc",
		"name": "misc",
		"color": "#aaa",
		"explorable": true
	},

	/////////////////////////////
	// THE NON-EXPLORABLE TAGS //
	/////////////////////////////

	{
		"id": "tools",
		"name": "tools",
		"color": "#ff4040",
		"explorable": false
	},
	{
		"id": "tutorials",
		"name": "tutorials",
		"color": "hsl(90, 100%, 40%)",
		"explorable": false
	},
	{
		"id": "reading",
		"name": "further reading",
		"color": "hsl(220, 70%, 56%)",
		"explorable": false
	},
	{
		"id": "faq",
		"name": "frequently asked questions",
		"color": "#222",
		"explorable": false
	}

]


text:
<!DOCTYPE html>

	<base href='/'>
	<title>Biology | Explorable Explanations</title>

	<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
	<meta content="utf-8" http-equiv="encoding">
	<meta charset="utf-8">
	<meta name="viewport" content="width=640">
	<link rel="icon" type="image/png" href="favicon.png">

	<meta itemprop="name" content="Biology | Explorable Explanations">
	<meta itemprop="description" content="a hub for learning through play">
	<meta itemprop="image" content="http://explorabl.es/-sharing/index.png">

	<meta name="twitter:card" content="summary_large_image">
	<meta name="twitter:title" content="Biology | Explorable Explanations">
	<meta name="twitter:description" content="a hub for learning through play">
	<meta name="twitter:image" content="http://explorabl.es/-sharing/index.png">

	<meta property="og:title" content="Biology | Explorable Explanations">
	<meta property="og:type" content="website">
	<meta property="og:url" content="http://explorabl.es/">
	<meta property="og:image" content="http://explorabl.es/-sharing/index.png">
	<meta property="og:description" content="a hub for learning through play">

	<link rel="stylesheet" type="text/css" href="-css/page.css">

		Sorry! Explorable Explanations needs JavaScript.
		Don't worry, there's no tracking code or anything creepy like that,
		the JS is just so I can dynamically load shtuff.
		Thanks!

BIOLOGY

Of all the things in our vast universe, only an eeny, teeny, weeny fraction of those things can grow, can evolve, can have goals, can take action towards those goals. It’s that mysterious property we call: being alive.

Here’s some explorables about the magic of life:

[loading...]

				Play Explorable Explanations in specific subjects:

				Make your own Explorable Explanations:

				See everything on one page:

				ALL OF IT

				Explorable Explanations is, above all, an experiment.
				None of us know anything, and that's exciting.
				We'd love for you to join us, in playing & making these interactive things!

				There's a lot to explore with Explorable Explanations. ♥

				@explorables
				r/explorables

			this website is open sauce

			get code & see credits!

			<sharing title="Explorable Explanations"
				 text="Explorable Explanations, a hub for learning through play:"
				 link="http://explorabl.es/"></sharing>


text:
<!DOCTYPE html>

	<base href='/'>
	<title>Further Reading | Explorable Explanations</title>

	<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
	<meta content="utf-8" http-equiv="encoding">
	<meta charset="utf-8">
	<meta name="viewport" content="width=640">
	<link rel="icon" type="image/png" href="favicon.png">

	<meta itemprop="name" content="Further Reading | Explorable Explanations">
	<meta itemprop="description" content="a hub for learning through play">
	<meta itemprop="image" content="http://explorabl.es/-sharing/index.png">

	<meta name="twitter:card" content="summary_large_image">
	<meta name="twitter:title" content="Further Reading | Explorable Explanations">
	<meta name="twitter:description" content="a hub for learning through play">
	<meta name="twitter:image" content="http://explorabl.es/-sharing/index.png">

	<meta property="og:title" content="Further Reading | Explorable Explanations">
	<meta property="og:type" content="website">
	<meta property="og:url" content="http://explorabl.es/">
	<meta property="og:image" content="http://explorabl.es/-sharing/index.png">
	<meta property="og:description" content="a hub for learning through play">

	<link rel="stylesheet" type="text/css" href="-css/page.css">

		Sorry! Explorable Explanations needs JavaScript.
		Don't worry, there's no tracking code or anything creepy like that,
		the JS is just so I can dynamically load shtuff.
		Thanks!

FURTHER READING

We shouldn't make chocolate-covered broccoli. That is: we shouldn’t just take old, soul-sucking educational materials and simply slap superficial “fun” “game” “play” on top. We need to understand why play matters, on a deeper level.

Tools are the “what”. Tutorials are the “how”. These books, talks, and essays show us the why:

[loading...]

				Play Explorable Explanations in specific subjects:

				Make your own Explorable Explanations:

				See everything on one page:

				ALL OF IT

				Explorable Explanations is, above all, an experiment.
				None of us know anything, and that's exciting.
				We'd love for you to join us, in playing & making these interactive things!

				There's a lot to explore with Explorable Explanations. ♥

				@explorables
				r/explorables

			this website is open sauce

			get code & see credits!

			<sharing title="Explorable Explanations"
				 text="Explorable Explanations, a hub for learning through play:"
				 link="http://explorabl.es/"></sharing>


text:
<!DOCTYPE html>

	<base href='/'>
	<title>Arts | Explorable Explanations</title>

	<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
	<meta content="utf-8" http-equiv="encoding">
	<meta charset="utf-8">
	<meta name="viewport" content="width=640">
	<link rel="icon" type="image/png" href="favicon.png">

	<meta itemprop="name" content="Arts | Explorable Explanations">
	<meta itemprop="description" content="a hub for learning through play">
	<meta itemprop="image" content="http://explorabl.es/-sharing/index.png">

	<meta name="twitter:card" content="summary_large_image">
	<meta name="twitter:title" content="Arts | Explorable Explanations">
	<meta name="twitter:description" content="a hub for learning through play">
	<meta name="twitter:image" content="http://explorabl.es/-sharing/index.png">

	<meta property="og:title" content="Arts | Explorable Explanations">
	<meta property="og:type" content="website">
	<meta property="og:url" content="http://explorabl.es/">
	<meta property="og:image" content="http://explorabl.es/-sharing/index.png">
	<meta property="og:description" content="a hub for learning through play">

	<link rel="stylesheet" type="text/css" href="-css/page.css">

		Sorry! Explorable Explanations needs JavaScript.
		Don't worry, there's no tracking code or anything creepy like that,
		the JS is just so I can dynamically load shtuff.
		Thanks!

THE ARTS

We play music, we put on a play, we type up screenplays. That’s what art is: play, playing with ideas and materials and human emotions. So, here’s some games & interactives to help you better understand different forms of art:

[loading...]

				Play Explorable Explanations in specific subjects:

				Make your own Explorable Explanations:

				See everything on one page:

				ALL OF IT

				Explorable Explanations is, above all, an experiment.
				None of us know anything, and that's exciting.
				We'd love for you to join us, in playing & making these interactive things!

				There's a lot to explore with Explorable Explanations. ♥

				@explorables
				r/explorables

			this website is open sauce

			get code & see credits!

			<sharing title="Explorable Explanations"
				 text="Explorable Explanations, a hub for learning through play:"
				 link="http://explorabl.es/"></sharing>


text:
<!DOCTYPE html>

	<base href='/'>
	<title>Math | Explorable Explanations</title>

	<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
	<meta content="utf-8" http-equiv="encoding">
	<meta charset="utf-8">
	<meta name="viewport" content="width=640">
	<link rel="icon" type="image/png" href="favicon.png">

	<meta itemprop="name" content="Math | Explorable Explanations">
	<meta itemprop="description" content="a hub for learning through play">
	<meta itemprop="image" content="http://explorabl.es/-sharing/index.png">

	<meta name="twitter:card" content="summary_large_image">
	<meta name="twitter:title" content="Math | Explorable Explanations">
	<meta name="twitter:description" content="a hub for learning through play">
	<meta name="twitter:image" content="http://explorabl.es/-sharing/index.png">

	<meta property="og:title" content="Math | Explorable Explanations">
	<meta property="og:type" content="website">
	<meta property="og:url" content="http://explorabl.es/">
	<meta property="og:image" content="http://explorabl.es/-sharing/index.png">
	<meta property="og:description" content="a hub for learning through play">

	<link rel="stylesheet" type="text/css" href="-css/page.css">

		Sorry! Explorable Explanations needs JavaScript.
		Don't worry, there's no tracking code or anything creepy like that,
		the JS is just so I can dynamically load shtuff.
		Thanks!

MATH

Galileo Galilei once said: “Mathematics is the language with which God has written the universe.” Too bad most schools are awful at helping us become fluent in Universe.

So, instead, here’s a bunch of mathematical games which can help you learn the Universe’s language, through play:

[loading...]

				Play Explorable Explanations in specific subjects:

				Make your own Explorable Explanations:

				See everything on one page:

				ALL OF IT

				Explorable Explanations is, above all, an experiment.
				None of us know anything, and that's exciting.
				We'd love for you to join us, in playing & making these interactive things!

				There's a lot to explore with Explorable Explanations. ♥

				@explorables
				r/explorables

			this website is open sauce

			get code & see credits!

			<sharing title="Explorable Explanations"
				 text="Explorable Explanations, a hub for learning through play:"
				 link="http://explorabl.es/"></sharing>


text:
/*******************
****** BODY ******
********************/

/** Font Faces**/
@font-face {
	font-family: 'Open Sans';
	font-style: normal;
	font-weight: 100;
	src: url(font/OpenSans-Light.ttf) format('truetype');
}
@font-face {
	font-family: 'Open Sans';
	font-style: normal;
	font-weight: 700;
	src: url(font/OpenSans-Bold.ttf) format('truetype');
}

/** Body **/
html{
}
body{
	min-width: 600px;
	background: #fff;
	color:#222222;
	margin: 0;
	font-family: "Open Sans", Helvetica, Arial, sans-serif;
	font-size: 22px;
	line-height: 1.5em;
	font-weight: 100;
}
b, strong{
	font-weight: 700;
}

@media (max-width: 641px){
	body{
		font-size: 30px;
	}
	#intro, #footer_nav_container{
		text-align: left !important;
	}
}

/*******************
****** SPLASH ******
********************/

#splash{
	position: relative;
	overflow: hidden;
	width: 100%;
	height: 390px;
	background: #222222;
}
#splash_iframe{
	border: none;
    width: 100%;
    height: 400px;
    position: absolute;
}
#splash_title{
	color: #fff;
	text-align: center;
	font-size: 120px;
	line-height: 0.85em;
	margin-top: 115px;
	pointer-events: none;
	cursor: default;

	position: relative;
	z-index: 99;
}
#splash_arrow{
	position: absolute;
	bottom:0;
	width:100%;
	height: 50px;
	pointer-events: none;
}
#splash_arrow > div{
    position: absolute;
}
#splash_arrow > div:nth-child(-n+2){
    width: 50%;
    height: 100%;
    background: #fff;
}
#splash_arrow > div:nth-child(1){
    left: -50px;
}
#splash_arrow > div:nth-child(2){
    right: -50px;
}
#splash_arrow > div:nth-child(n+3){
    width: 0;
	height: 0;
	border-style: solid;
}
#splash_arrow > div:nth-child(3){
	border-width: 50px 0 0 50px;
	border-color: transparent transparent transparent #ffffff;
    left: calc(50% - 50px);
}
#splash_arrow > div:nth-child(4){
	border-width: 0 0 50px 50px;
	border-color: transparent transparent #ffffff transparent;
    right: calc(50% - 50px);
}
#splash_home{
	display: block;
    width:70px; height:70px;
    background: url(home.png);
    background-size: 100% 100%;
    position: absolute;
    top: 10px;
    left: 10px;
    text-decoration: none;
}
#splash_home:after{
	content: 'back to home page';
	display: none;
    width: 110px;
    color: #fff;
    font-size: 20px;
    position: absolute;
    top: 19px;
    left: 80px;
    line-height: 1em;
}
#splash_home:hover:after{
    display: block;
}

/*******************
****** WORDS ******
********************/

#words{
	width: 100%;
	padding-top: 10px;
	padding-bottom: 30px;
}
#intro{
	max-width: calc(100% - 50px);
	width:640px;
	margin: auto;
	text-align: justify;
	overflow: hidden;
}
#gallery{
	max-width: calc(100% - 40px);
	width:800px;
	margin: auto;
	margin-top: 20px;
	overflow: hidden;
}
#gallery #entry{
	float:left;
	margin-bottom: 35px;
	position: relative;
	transition: opacity 0.6s ease-in-out, top 0.6s ease-in-out;
}
#gallery #entry #thumb{
	border: 1px solid #eee;
	background: #bbb;

	transition: opacity 0.1s ease-in-out;
	opacity: 1;
}
#gallery #entry:hover #thumb{
	opacity: 0.7;
}
#gallery #entry #name{
	color: #000;
	font-weight: 700;
	line-height: 1.3em;
    margin-top: 6px;
}
#gallery #entry #description{
	color: #909090;
	font-size: 0.92em;
	line-height: 1.3em;
}
#gallery[size=big]{
	width: 600px;
}
#gallery[size=big] #entry{
	width: 600px;
}
#gallery[size=big] #entry #thumb{
	width: 598px;
	height: 148px;
}
#gallery[size=big] #entry:hover #thumb{}
#gallery[size=big] #entry #name{}
#gallery[size=big] #entry #description{}
#gallery[size=small]{
	width: 820px;
}
#gallery[size=small] #entry{
	width: 400px;
	margin: 0 5px 25px 5px;
}
#gallery[size=small] #entry #thumb{
	width: 398px;
	height: 98px;
}
#gallery[size=small] #entry:hover #thumb{}
#gallery[size=small] #entry #name{
	font-size: 0.92em;
	margin-top: 3px;
	margin-bottom: 5px;
}
#gallery[size=small] #entry #description{
	font-size: 0.83em;
}
#gallery[size=small] .divider{
	display: block;
	clear:both;
}
#load_more{

	clear: both;
	margin: 0 auto;

	border: 2px solid black;
	border-radius: 10px;

	font-size: 30px;
	text-align: center;
	font-weight: 100;
	line-height: 40px;

	width: 300px;
	height: 40px;
	padding: 10px 0;
	cursor: pointer;

	transition: all 0.1s ease-in-out;
	position: relative;
	top:0;
	opacity: 1.0;

}
#load_more:hover{
	opacity: 0.5;
	top:-3px;
}

/*******************
**** FOOTER NAV ****
********************/

#footer_nav_container{
	width: 100%;
	padding: 30px 0 50px 0;
	background: #f0f0f0;
	text-align: justify;
}
#footer_nav{
	margin: 0 auto;
	max-width: calc(100% - 50px);
	width:640px;
}
.footer_buttons{
	text-align:center;
	padding-bottom: 1em;

	margin-top: -0.5em;
    margin-bottom: -0.5em;
}
.tag{
	position: relative;
	top:0;
	transition: top 0.1s ease-in-out;
	display: inline-block;
	color: #fff;
	border-radius: 10px;
	padding: 0 15px;
	margin: 5px;
	font-size: 1em;
	/*font-weight: 700;*/
	text-decoration: none;
	line-height: 1.7em;
	border-bottom: 4px solid rgba(0,0,0,0.35);
}
.tag:hover{
	top:-2px;
}
.tag[small=yes]{
	font-size: 0.75em;
	line-height: 1.4em;
	padding: 0 10px;
	font-weight: 100;
	margin: 1px;
	border-radius: 100px;
	border: none;
}
.tag.rainbow{
	font-size:1.5em;
	color: #000;
    background: #dd4040; /* For browsers that do not support gradients */
    background: -webkit-linear-gradient(left, hsl(0, 100%, 63%), hsl(30, 100%, 63%), hsl(60, 100%, 63%), hsl(90, 100%, 63%), hsl(120, 100%, 63%), hsl(180, 100%, 63%), hsl(240, 100%, 63%)); /* For Safari 5.1 to 6.0 */
    background: -o-linear-gradient(right, hsl(0, 100%, 63%), hsl(30, 100%, 63%), hsl(60, 100%, 63%), hsl(90, 100%, 63%), hsl(120, 100%, 63%), hsl(180, 100%, 63%), hsl(240, 100%, 63%)); /* For Opera 11.1 to 12.0 */
    background: -moz-linear-gradient(right, hsl(0, 100%, 63%), hsl(30, 100%, 63%), hsl(60, 100%, 63%), hsl(90, 100%, 63%), hsl(120, 100%, 63%), hsl(180, 100%, 63%), hsl(240, 100%, 63%)); /* For Firefox 3.6 to 15 */
    background: linear-gradient(to right, hsl(0, 100%, 63%), hsl(30, 100%, 63%), hsl(60, 100%, 63%), hsl(90, 100%, 63%), hsl(120, 100%, 63%), hsl(180, 100%, 63%), hsl(240, 100%, 63%)); /* Standard syntax (must be last) */
}

/*******************
** FOOTER CREDITS **
********************/

#footer_credits_container{
	width: 100%;
	padding: 50px 0 75px 0;
	background: #222222;
}
#footer_credits{
	margin: 0 auto;
	max-width: calc(100% - 50px);
	width:600px;
	color: #fff;
	font-size: 0.71em;
	text-align: center;
	line-height: 1.5em;
}
#footer_credits a{
	color:#dd4040;
}
#footer_credits a:hover{
	color:#ee5151;
}
.sharing{
	margin-top: 20px;
}
.sharing a{
	display: inline-block;
    height: 20px;
    width: 20px;
    margin: 5px;
    border:1px solid #fff;
    border-radius: 100px;
    padding:5px;
}
.sharing a:hover{
	background: rgba(255,255,255,0.3);
}
.sharing svg{
	width:20px;
	height:20px;
	fill:#fff;
}


text:
<!DOCTYPE html>

	<base href='/'>
	<title>Tutorials | Explorable Explanations</title>

	<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
	<meta content="utf-8" http-equiv="encoding">
	<meta charset="utf-8">
	<meta name="viewport" content="width=640">
	<link rel="icon" type="image/png" href="favicon.png">

	<meta itemprop="name" content="Tutorials | Explorable Explanations">
	<meta itemprop="description" content="a hub for learning through play">
	<meta itemprop="image" content="http://explorabl.es/-sharing/index.png">

	<meta name="twitter:card" content="summary_large_image">
	<meta name="twitter:title" content="Tutorials | Explorable Explanations">
	<meta name="twitter:description" content="a hub for learning through play">
	<meta name="twitter:image" content="http://explorabl.es/-sharing/index.png">

	<meta property="og:title" content="Tutorials | Explorable Explanations">
	<meta property="og:type" content="website">
	<meta property="og:url" content="http://explorabl.es/">
	<meta property="og:image" content="http://explorabl.es/-sharing/index.png">
	<meta property="og:description" content="a hub for learning through play">

	<link rel="stylesheet" type="text/css" href="-css/page.css">

		Sorry! Explorable Explanations needs JavaScript.
		Don't worry, there's no tracking code or anything creepy like that,
		the JS is just so I can dynamically load shtuff.
		Thanks!

TUTORIALS

Tools are just what you make things with — but you also need to know how to make things!

Here’s a list of tutorials (or at least thoughts) on how to design your own explorable explanation:

[loading...]

				Play Explorable Explanations in specific subjects:

				Make your own Explorable Explanations:

				See everything on one page:

				ALL OF IT

				Explorable Explanations is, above all, an experiment.
				None of us know anything, and that's exciting.
				We'd love for you to join us, in playing & making these interactive things!

				There's a lot to explore with Explorable Explanations. ♥

				@explorables
				r/explorables

			this website is open sauce

			get code & see credits!

			<sharing title="Explorable Explanations"
				 text="Explorable Explanations, a hub for learning through play:"
				 link="http://explorabl.es/"></sharing>


text:
<!DOCTYPE html>

	<base href='/'>
	<title>Social Science | Explorable Explanations</title>

	<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
	<meta content="utf-8" http-equiv="encoding">
	<meta charset="utf-8">
	<meta name="viewport" content="width=640">
	<link rel="icon" type="image/png" href="favicon.png">

	<meta itemprop="name" content="Social Science | Explorable Explanations">
	<meta itemprop="description" content="a hub for learning through play">
	<meta itemprop="image" content="http://explorabl.es/-sharing/index.png">

	<meta name="twitter:card" content="summary_large_image">
	<meta name="twitter:title" content="Social Science | Explorable Explanations">
	<meta name="twitter:description" content="a hub for learning through play">
	<meta name="twitter:image" content="http://explorabl.es/-sharing/index.png">

	<meta property="og:title" content="Social Science | Explorable Explanations">
	<meta property="og:type" content="website">
	<meta property="og:url" content="http://explorabl.es/">
	<meta property="og:image" content="http://explorabl.es/-sharing/index.png">
	<meta property="og:description" content="a hub for learning through play">

	<link rel="stylesheet" type="text/css" href="-css/page.css">

		Sorry! Explorable Explanations needs JavaScript.
		Don't worry, there's no tracking code or anything creepy like that,
		the JS is just so I can dynamically load shtuff.
		Thanks!

SOCIAL SCIENCE

Now, more than ever, we need to understand people, and create more understanding people. So, here’s some stuff that let you explore what it means to be human(s):

[loading...]

				Play Explorable Explanations in specific subjects:

				Make your own Explorable Explanations:

				See everything on one page:

				ALL OF IT

				Explorable Explanations is, above all, an experiment.
				None of us know anything, and that's exciting.
				We'd love for you to join us, in playing & making these interactive things!

				There's a lot to explore with Explorable Explanations. ♥

				@explorables
				r/explorables

			this website is open sauce

			get code & see credits!

			<sharing title="Explorable Explanations"
				 text="Explorable Explanations, a hub for learning through play:"
				 link="http://explorabl.es/"></sharing>


text:
<!DOCTYPE html>

	<base href='/'>
	<title>Philosophy | Explorable Explanations</title>

	<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
	<meta content="utf-8" http-equiv="encoding">
	<meta charset="utf-8">
	<meta name="viewport" content="width=640">
	<link rel="icon" type="image/png" href="favicon.png">

	<meta itemprop="name" content="Philosophy | Explorable Explanations">
	<meta itemprop="description" content="a hub for learning through play">
	<meta itemprop="image" content="http://explorabl.es/-sharing/index.png">

	<meta name="twitter:card" content="summary_large_image">
	<meta name="twitter:title" content="Philosophy | Explorable Explanations">
	<meta name="twitter:description" content="a hub for learning through play">
	<meta name="twitter:image" content="http://explorabl.es/-sharing/index.png">

	<meta property="og:title" content="Philosophy | Explorable Explanations">
	<meta property="og:type" content="website">
	<meta property="og:url" content="http://explorabl.es/">
	<meta property="og:image" content="http://explorabl.es/-sharing/index.png">
	<meta property="og:description" content="a hub for learning through play">

	<link rel="stylesheet" type="text/css" href="-css/page.css">

		Sorry! Explorable Explanations needs JavaScript.
		Don't worry, there's no tracking code or anything creepy like that,
		the JS is just so I can dynamically load shtuff.
		Thanks!

PHILOSOPHY

Why? How? What if? Philosophy is the act of playing with ideas — so, here’s a list of philosophical games, that let you ask deep questions, through play:

[loading...]

				Play Explorable Explanations in specific subjects:

				Make your own Explorable Explanations:

				See everything on one page:

				ALL OF IT

				Explorable Explanations is, above all, an experiment.
				None of us know anything, and that's exciting.
				We'd love for you to join us, in playing & making these interactive things!

				There's a lot to explore with Explorable Explanations. ♥

				@explorables
				r/explorables

			this website is open sauce

			get code & see credits!

			<sharing title="Explorable Explanations"
				 text="Explorable Explanations, a hub for learning through play:"
				 link="http://explorabl.es/"></sharing>


text:
window.addEventListener("load",function(){

	// Find the "sharing" dom
	var sharingDOM = document.body.querySelector("sharing");

	// URL encodeable
	var title = sharingDOM.getAttribute("title");
	var text = sharingDOM.getAttribute("text");
	var link = sharingDOM.getAttribute("link");
	text = encodeURIComponent(text);
	link = encodeURIComponent(link);

	// SVGs
	var svgFacebook = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18.77 7.46H14.5v-1.9c0-.9.6-1.1 1-1.1h3V.5h-4.33C10.24.5 9.5 3.44 9.5 5.32v2.15h-3v4h3v12h5v-12h3.85l.42-4z"/></svg>';
	var svgTwitter = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23.44 4.83c-.8.37-1.5.38-2.22.02.93-.56.98-.96 1.32-2.02-.88.52-1.86.9-2.9 1.1-.82-.88-2-1.43-3.3-1.43-2.5 0-4.55 2.04-4.55 4.54 0 .36.03.7.1 1.04-3.77-.2-7.12-2-9.36-4.75-.4.67-.6 1.45-.6 2.3 0 1.56.8 2.95 2 3.77-.74-.03-1.44-.23-2.05-.57v.06c0 2.2 1.56 4.03 3.64 4.44-.67.2-1.37.2-2.06.08.58 1.8 2.26 3.12 4.25 3.16C5.78 18.1 3.37 18.74 1 18.46c2 1.3 4.4 2.04 6.97 2.04 8.35 0 12.92-6.92 12.92-12.93 0-.2 0-.4-.02-.6.9-.63 1.96-1.22 2.56-2.14z"/></svg>';
	var svgEmail = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M22 4H2C.9 4 0 4.9 0 6v12c0 1.1.9 2 2 2h20c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zM7.25 14.43l-3.5 2c-.08.05-.17.07-.25.07-.17 0-.34-.1-.43-.25-.14-.24-.06-.55.18-.68l3.5-2c.24-.14.55-.06.68.18.14.24.06.55-.18.68zm4.75.07c-.1 0-.2-.03-.27-.08l-8.5-5.5c-.23-.15-.3-.46-.15-.7.15-.22.46-.3.7-.14L12 13.4l8.23-5.32c.23-.15.54-.08.7.15.14.23.07.54-.16.7l-8.5 5.5c-.08.04-.17.07-.27.07zm8.93 1.75c-.1.16-.26.25-.43.25-.08 0-.17-.02-.25-.07l-3.5-2c-.24-.13-.32-.44-.18-.68s.44-.32.68-.18l3.5 2c.24.13.32.44.18.68z"/></svg>';

	// Create full html
	var sharing = document.createElement("div");
	sharing.className = "sharing";
	sharing.innerHTML = ''+svgFacebook+''+
						''+svgTwitter+''+
						''+svgEmail+'';

	// Replace it in the dom
	sharingDOM.parentNode.replaceChild(sharing, sharingDOM);

});


text:
// LOAD THE JSONS
var pages;
var explorables;
var tags;
window.addEventListener("load", function(){
	Q.all([
		pegasus("-data/pages.json"),
		pegasus("-data/tags.json"),
		pegasus("-data/explorables.csv")
	]).then(function(data){

		// Store Data
		pages = JSON.parse(_clean(data[0]));
		tags = JSON.parse(_clean(data[1]));
		explorables = _csvToJSON(data[2]);

		// Show page!
		_showPage(window.location.pathname);

	});
},false);

// SHOW PAGE
var pageIsIndex = false;
var _showPage = function(pageID){

	// Get page config
	pageID = pageID.replace(/\//g, ''); // strip slashes
	pageID = pageID || "index";
	var page = pages[pageID];

	// IS INDEX?
	pageIsIndex = (pageID=="index");

	// Show gallery
	var tag = pageIsIndex ? "featured" : pageID; // tag is "featured" or pageID!
	if(pageID=="all"){
		var totalDOMs = document.querySelectorAll("#how_many_total");
		totalDOMs.forEach(function(dom){
			dom.innerHTML = explorables.length;
		});
		tag=null;
	}
	_showGallery(page.gallery, tag);

	// Show tags
	_makeTagStyle(tags);
	setTimeout(function(){

		// Explorables Tags
		var explorableTags = tags.filter(function(tag){ return tag.explorable; });
		explorableTags.sort(function(a,b){
			return a.id.localeCompare(b.id); // sort alphabetically
		});
		for(var i=0; i<explorableTags.length; i++){
			$("#tags_explorables").appendChild( _makeTagButton(explorableTags[i].id) );
		}

		// Meta Tags
		var miscTags = tags.filter(function(tag){ return !tag.explorable; });
		for(var i=0; i<miscTags.length; i++){
			$("#tags_not_explorables").appendChild( _makeTagButton(miscTags[i].id) );
		}

	},1);

	// Resize everything
	setTimeout(_resize, 1);

};

// SHOW GALLERY
var _showGallery = function(query, tag){

	var gallery = $("#gallery");
	gallery.innerHTML = "";

	// Load all by tag
	var results = tag ? explorables.filter(function(e){
		//return true;
		return e.tags.indexOf(tag)>=0; // yes, has the tag!
	}) : explorables.slice(0);

	// Sort the results
	switch(query.sort){
		case "random":
			_shuffle(results);
			break;
		case "featured-first": // separate, shuffle each, concat.
			var featured = [];
			var not_featured = [];
			for(var i=0;i<results.length;i++){
				var entry = results[i];
				if(entry.tags.indexOf("featured")>=0){
					featured.push(entry);
				}else{
					not_featured.push(entry);
				}
			}
			_shuffle(featured);
			_shuffle(not_featured);
			results = featured.concat(not_featured);
			break;
	}

	// Is this the index page? Then...
	if(query.index){

		// Get rid of all NON EXPLORABLE results
		results = results.filter(function(e){
			if(e.tags.indexOf("tools")>=0) return false;
			if(e.tags.indexOf("tutorials")>=0) return false;
			if(e.tags.indexOf("reading")>=0) return false;
			if(e.tags.indexOf("faq")>=0) return false;
			return true;
		});

		gallery.setAttribute("size", "big"); // Make it big
		//results = results.splice(0,3); // Only show first THREE results

	}else{

		gallery.setAttribute("size", "small"); // Make it small

	}

	var showStart = 0;
	var showEnd = query.count || results.length;

	// Insert each result into the gallery
	var _show = function(fadeIn){
		for(var i=showStart; i<showEnd && i<results.length; i++){

			var entry = _makeGalleryEntry(results[i]);

			// Fade in?
			if(fadeIn){
				(function(entry){
					var dom = entry.querySelector("#entry");
					dom.style.opacity = 0;
					dom.style.top = "30px";
					setTimeout(function(){
						dom.style.opacity = 1;
						dom.style.top = "0px";
					}, (i-showStart)*150);
				})(entry);
			}

			gallery.appendChild(entry);

			// Divider...
			if(!query.index && i%2==1){
				var span = document.createElement("span");
				span.className = "divider";
				gallery.appendChild(span);
			}

		}
		showStart = showEnd;
	};
	_show();

	// INDEX PAGE ONLY: "LOAD MORE"
	var loadMoreButton;
	var countToWords;
	if(query.count==3) countToWords="three";
	if(query.count==10) countToWords="ten";
	var say = ["load "+countToWords+" more!", "even more!", "more please!"];
	var sayIndex = 0;
	if(query.count){
		loadMoreButton = document.createElement("div");
		loadMoreButton.id = "load_more";
		loadMoreButton.innerHTML = say[sayIndex];
		gallery.appendChild(loadMoreButton);

		loadMoreButton.onclick = function(){

			gallery.removeChild(loadMoreButton);

			if(sayIndex<say.length-1) sayIndex++;
			loadMoreButton.innerHTML = say[sayIndex];

			showEnd += query.count;
			_show(true);
			if(showEnd<results.length){
				gallery.appendChild(loadMoreButton);
			}

		};

	}

};

// CREATE GALLERY ENTRY
var _makeGalleryEntry = function(entry){

	// Whole dom is a link!
	var link = document.createElement("a");
	link.href = entry.link;
	var dom = _createDom("entry", link, "div");

	// Thumbnail
	var thumb = _createDom("thumb", dom, "img");
	thumb.src = "-thumbs/"+entry.thumb;
	//thumb.src = "-thumbs/placeholder.jpg";

	// Name
	var name = _createDom("name", dom, "div");
	var isFeatured = entry.tags.indexOf("featured")>=0;
	name.innerHTML = (isFeatured?"★ ":"") + entry.name + " ";

	// Colored tags
	for(var i=0; i<entry.tags.length; i++){
		var tag = _makeTagButton(entry.tags[i], {small:true});
		if(tag) name.appendChild(tag);
	}

	// Description
	var description = _createDom("description", dom, "div");
	description.innerHTML = entry.description;

	// Return the DOM
	return link;

};

// CREATE TAG STYLE
var _makeTagStyle = function(tags){
	var style = document.createElement("style");
	for(var i=0; i<tags.length; i++){
		var tag = tags[i];
		style.innerHTML += ".tag_"+tag.id+"{ background:"+tag.color+" }";
	}
	document.head.appendChild(style);
};

// CREATE TAG
var _makeTagButton = function(tagID, options){
	options = options || {};
	var conf = tags.filter(function(tag){
		return tag.id==tagID;
	})[0];
	if(!conf) return null; // NO SUCH TAG, WHATEVER
	var button = document.createElement("a");
	button.href = "/"+tagID;
	button.classList.add("tag");
	button.classList.add("tag_"+tagID);
	if(options.small) button.setAttribute("small", "yes");
	button.innerHTML = conf.name;
	return button;
};

// Helper: remove newlines
var _clean = function(str){
	str = str.replace(/[^\:]\/\/.*\n/g,""); // strip comments
	str = str.replace(/\n|\t/g,""); // strip newlines & tabs
	return str;
};

// CSV to JSON
var _csvToJSON = function(csv){

	var results = [];

	// Get lines
	var lines = csv.split("\n");
	for(var i=1; i<lines.length; i++){ // skip first line, it's the header
		var line = lines[i];

		// NO
		if(line=="") continue;

		// Get props
		var props = line.split('\",\"');
		props[0] = props[0].slice(1); // remove quotes
		props[6] = props[6].slice(0, props[6].length-1); // remove quotes

		// Convert tags into array
		var tags = props[4].split(/,\s*/).sort();

		// Convert props
		if(props[5]=="yes") tags.push("featured");

		// Oh. Forget it.
		if(props[0]=="") continue;

		// Add result
		results.push({
			name: props[0],
			description: props[1],
			link: props[2],
			thumb: props[3],
			tags: tags
		});

	}

	return results;

};

// RESIZE
var _resize = function(){

	// Splash title position...
	// TODO: IN CSS
	/*setTimeout(function(){
		var bounds = splash_title.getBoundingClientRect();
		var w = bounds.width;
		var h = bounds.height;
		splash_title.style.marginTop = ((330-h)/2)+"px";
	},1);*/

	if(!pageIsIndex){
		var gallery = $("#gallery");
		gallery.setAttribute("size", (document.body.clientWidth<890) ? "big" : "small");
	}

};
window.addEventListener("resize", _resize, false);

// SCROLL
var splash_iframe = $("#splash_iframe");
window.onscroll = function(){
	var scrollY = window.pageYOffset;
	splash_iframe.style.top = (scrollY*0.65)+"px";
};


text:
// a   url (naming it a, because it will be reused to store callbacks)
// e   timeout error placeholder to avoid using var, not to be used
// xhr placeholder to avoid using var, not to be used
function pegasus(a, e, xhr) {
  xhr = new XMLHttpRequest();

  // Set URL
  xhr.open('GET', a);

  // Don't need a to store URL anymore
  // Reuse it to store callbacks
  a = [];

  pegasus.timeout && (xhr.timeout = pegasus.timeout);

  xhr.ontimeout = function (event) {
    e = event
  }

  xhr.onreadystatechange = xhr.then = function(onSuccess, onError, cb, data) {
    // Test if onSuccess is a function
    // Means that the user called xhr.then
    if (onSuccess && onSuccess.call) {
      a = [,onSuccess, onError];
    }

    // Test if there's a timeout error
    e && a[2] && a[2](e, xhr)

    // Test if request is complete
    if (xhr.readyState == 4) {
      // index will be:
      // 0 if undefined
      // 1 if status is between 200 and 399
      // 2 if status is over
      cb = a[0|xhr.status / 200];
      if (cb) {
        /*try {
          data = JSON.parse(xhr.responseText) // NICKY FIX -- don't try to be helpful
        } catch (e) {*/
          data = null;
        //}
        //cb(data, xhr); // NICKY FIX
        cb(xhr.response);
      }
    }
  };

  // Send the GET request
  xhr.send();

  // Return request
  return xhr;
}


text:
// The poor man's jQuery
var $ = function(query){
	return document.querySelector(query);
};

// DOMs made quick & cheap
var _createDom = function(id, appendTo, tag){
	appendTo = appendTo || document.body;
	tag = tag || "div";
	var div = document.createElement(tag);
	div.id = id;
	appendTo.appendChild(div);
	return div;
};

// Everyday I'm shuffling
// From StackOverflow: https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array
function _shuffle(a) {
    var j, x, i;
    for (i = a.length; i; i--) {
        j = Math.floor(Math.random() * i);
        x = a[i - 1];
        a[i - 1] = a[j];
        a[j] = x;
    }
}