diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -12,60 +12,43 @@
 
 
 main :: IO ()
-main = defaultMainWithHooks simpleUserHooks { postBuild = myPostBuild }
+main =
+  defaultMainWithHooks simpleUserHooks { postBuild = myPostBuild }
 
+
 myPostBuild :: Args -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()
 myPostBuild args flags pd lbi =
-    do putStrLn "Custom build step: compiling debuggerInterface.elm"
-       buildInterface lbi
-       concatJS lbi
-       postBuild simpleUserHooks args flags pd lbi
+  do  putStrLn "Custom build step: compiling debuggerInterface.elm"
+      buildInterface
+      concatJS lbi
+      postBuild simpleUserHooks args flags pd lbi
 
+
 concatJS :: LocalBuildInfo -> IO ()
 concatJS lbi =
-  do let files = map (("assets" </> "_reactor") </>)
-          [ "debuggerInterface.js"
-          , "toString.js"
-          , "core.js"
-          , "reactor.js"
-          ]
-     megaJS <- concat `fmap` mapM readFile files
-     _ <- putStrLn "Writing composite debugger.js"
-     writeFile ("assets" </> "debugger.js") megaJS
+  do  megaJS <- concat `fmap` mapM readFile jsFiles
+      _ <- putStrLn "Writing composite debugger.js"
+      writeFile ("assets" </> "debugger.js") megaJS
 
-buildInterface :: LocalBuildInfo -> IO ()
-buildInterface lbi =
-    do exitCode <- compile $ args "debuggerInterface.elm"
-       case exitCode of
-            ExitFailure _ ->
-                putStrLn "Build failed: debuggerInterface"
-            ExitSuccess ->
-                renameFile
-                    ("slider" </> "build" </> "debuggerInterface.js")
-                    ("assets" </> "_reactor" </> "debuggerInterface.js")
 
-       removeEverything "slider" "Slider.elm"
-       removeEverything "slider" "debuggerInterface.elm"
-    where
-        args file =
-            [ "--make"
-            , "--only-js"
-            , file
-            ]
+jsFiles :: [FilePath]
+jsFiles =
+  map (\name -> "assets" </> "_reactor" </> name)
+    [ "debuggerInterface.js"
+    , "toString.js"
+    , "core.js"
+    , "reactor.js"
+    ]
 
-        compile args =
-            do let workingDir = Just "slider"
-               handle <- runProcess "elm" args workingDir Nothing Nothing Nothing Nothing
-               exitCode <- waitForProcess handle
-               return exitCode
 
-        removeEverything dir file =
-            do remove "cache" "elmi"
-               remove "cache" "elmo"
-               remove "build" "js"
-            where
-                remove :: String -> String -> IO ()
-                remove subdir ext =
-                    do let path = dir </> subdir </> file`replaceExtension` ext
-                       exists <- doesFileExist path
-                       when exists (removeFile path)
+buildInterface :: IO ()
+buildInterface =
+  do  (exitCode, out, err) <-
+        readProcessWithExitCode "elm-make" [ "--yes", "frontend" </> "debuggerInterface.elm" ] ""
+      case exitCode of
+        ExitSuccess ->
+          renameFile "elm.js" ("assets" </> "_reactor" </> "debuggerInterface.js")
+
+        ExitFailure _ ->
+          do  hPutStrLn stderr ("Failed to build debuggerInterface.elm\n\n" ++ out ++ err)
+              exitFailure
diff --git a/assets/debugger.js b/assets/debugger.js
--- a/assets/debugger.js
+++ b/assets/debugger.js
@@ -1,1050 +1,12063 @@
-Elm.Native.Slider = {};
-Elm.Native.Slider.make = function(elm) {
-
-    elm.Native = elm.Native || {};
-    elm.Native.Slider = elm.Native.Slider || {};
-    if (elm.Native.Slider.values) return elm.Native.Slider.values;
-
-    var newNode = ElmRuntime.use(ElmRuntime.Render.Utils).newElement;
-    var newElement = Elm.Graphics.Element.make(elm).newElement;
-
-    function renderSlider(model) {
-        var node = newNode('input');
-        node.type = 'range';
-
-        node.min = model.styling.min;
-        node.max = model.styling.max;
-        node.step = model.styling.step;
-        node.value = model.styling.value;
-
-        if (!model.styling.horizontal) {
-            node.orient = "vertical"; // FF
-            node.style.webkitAppearance = "slider-vertical"; // webkit
-            node.style.writingMode = "bt-lr"; // ie
-        }
-
-        if (model.styling.disabled) {
-            node.disabled = true;
-        }
-
-        node.style.display = 'block';
-        node.style.pointerEvents = 'auto';
-        node.elm_signal = model.signal;
-        node.elm_handler = model.handler;
-        node.addEventListener('input', notifySlider);
-        node.addEventListener('change', notifySlider);
-        function notifySlider() {
-            elm.notify(node.elm_signal.id, node.elm_handler(node.value));
-        }
-        return node;
-    }
-
-    function updateSlider(node, oldModel, newModel) {
-        if (newModel.styling.disabled) {
-            node.disabled = true;
-        } else {
-            node.disabled = false;
-        }
-        node.elm_signal = newModel.signal;
-        node.elm_handler = newModel.handler;
-        node.min = newModel.styling.min;
-        node.max = newModel.styling.max;
-        node.step = newModel.styling.step;
-        node.value = newModel.styling.value;
-    }
-
-    function slider(signal, handler, styling) {
-        var width = styling.length;
-        var height = 24;
-        if (!styling.horizontal) {
-            var temp = width;
-            width = height;
-            height = temp;
-        }
-        return A3(newElement, width, height, {
-            ctor: 'Custom',
-            type: 'Slider',
-            render: renderSlider,
-            update: updateSlider,
-            model: { signal:signal, handler:handler, styling:styling }
-        });
-    }
-
-    return elm.Native.Slider.values = {
-        slider:F3(slider)
-    };
-}
-Elm.DebuggerInterface = Elm.DebuggerInterface || {};
-Elm.DebuggerInterface.make = function (_elm) {
-   "use strict";
-   _elm.DebuggerInterface = _elm.DebuggerInterface || {};
-   if (_elm.DebuggerInterface.values)
-   return _elm.DebuggerInterface.values;
-   var _op = {},
-   _N = Elm.Native,
-   _U = _N.Utils.make(_elm),
-   _L = _N.List.make(_elm),
-   _A = _N.Array.make(_elm),
-   _E = _N.Error.make(_elm),
-   $moduleName = "DebuggerInterface",
-   $Basics = Elm.Basics.make(_elm),
-   $Color = Elm.Color.make(_elm),
-   $Graphics$Collage = Elm.Graphics.Collage.make(_elm),
-   $Graphics$Element = Elm.Graphics.Element.make(_elm),
-   $Graphics$Input = Elm.Graphics.Input.make(_elm),
-   $List = Elm.List.make(_elm),
-   $Maybe = Elm.Maybe.make(_elm),
-   $Native$Json = Elm.Native.Json.make(_elm),
-   $Native$Ports = Elm.Native.Ports.make(_elm),
-   $Signal = Elm.Signal.make(_elm),
-   $Slider = Elm.Slider.make(_elm),
-   $String = Elm.String.make(_elm),
-   $Text = Elm.Text.make(_elm),
-   $Window = Elm.Window.make(_elm);
-   var noWatches = $Text.markdown("<div style=\"height:0;width:0;\">&nbsp;</div><h3><span style=\"font-family: Gotham, Futura, \'Lucida Grande\', sans-serif; font-size: 12pt; color: rgb(170,170,170)\"> You don&#39;t have any watches! </span></h3>\n<p><span style=\"color: rgb(170,170,170)\">\n<span style=\"font-family: Gotham, Futura, \'Lucida Grande\', sans-serif; font-size: 10pt; color: rgb(170,170,170)\">\nUse <a href=\"http://library.elm-lang.org/catalog/elm-lang-Elm/latest/Debug#watch\"><span style=\"text-decoration:underline; color: rgb(170,170,170)\">Debug.watch</span></a>\nto show any value. <br>\n<code>watch : String -&gt; a -&gt; a</code></span></p>\n<p><span style=\"font-family: Gotham, Futura, \'Lucida Grande\', sans-serif; font-size: 10pt; color: rgb(170,170,170)\">\nUse <a href=\"http://library.elm-lang.org/catalog/elm-lang-Elm/latest/Debug#watchSummary\"><span style=\"text-decoration:underline; color: rgb(170,170,170)\">Debug.watchSummary</span></a> to show a <br>\nsummary or subvalue of any value. </span><br></p>\n<div style=\"height:0;width:0;\">&nbsp;</div>",
-   "320:13");
-   var roundedSquare = F3(function (side,
-   radius,
-   toForm) {
-      return function () {
-         var formedCircle = toForm($Graphics$Collage.circle(radius));
-         var shortSide = side - 2 * radius;
-         var xRect = toForm(A2($Graphics$Collage.rect,
-         side,
-         shortSide));
-         var yRect = toForm(A2($Graphics$Collage.rect,
-         shortSide,
-         side));
-         var circleOffset = shortSide / 2;
-         var tl = $Graphics$Collage.move({ctor: "_Tuple2"
-                                         ,_0: 0 - circleOffset
-                                         ,_1: circleOffset})(formedCircle);
-         var tr = $Graphics$Collage.move({ctor: "_Tuple2"
-                                         ,_0: circleOffset
-                                         ,_1: circleOffset})(formedCircle);
-         var bl = $Graphics$Collage.move({ctor: "_Tuple2"
-                                         ,_0: 0 - circleOffset
-                                         ,_1: 0 - circleOffset})(formedCircle);
-         var br = $Graphics$Collage.move({ctor: "_Tuple2"
-                                         ,_0: circleOffset
-                                         ,_1: 0 - circleOffset})(formedCircle);
-         return $Graphics$Collage.group(_L.fromArray([xRect
-                                                     ,yRect
-                                                     ,tl
-                                                     ,tr
-                                                     ,bl
-                                                     ,br]));
-      }();
-   });
-   var startState = {_: {}
-                    ,paused: false
-                    ,scrubPosition: 0
-                    ,totalEvents: 0};
-   var step = F2(function (update,
-   state) {
-      return function () {
-         switch (update.ctor)
-         {case "Pause":
-            return _U.replace([["paused"
-                               ,update._0]
-                              ,["totalEvents"
-                               ,update._0 ? state.totalEvents : state.scrubPosition]],
-              state);
-            case "Restart":
-            return startState;
-            case "ScrubPosition":
-            return _U.replace([["scrubPosition"
-                               ,update._0]
-                              ,["paused",true]],
-              state);
-            case "TotalEvents":
-            return _U.replace([["totalEvents"
-                               ,update._0]
-                              ,["scrubPosition",update._0]],
-              state);}
-         _E.Case($moduleName,
-         "between lines 265 and 286");
-      }();
-   });
-   var showSwap = $Native$Ports.portIn("showSwap",
-   function (v) {
-      return typeof v === "boolean" ? v : _E.raise("invalid input, expecting JSBoolean but got " + v);
-   });
-   var watches = $Native$Ports.portIn("watches",
-   $Native$Ports.incomingSignal(function (v) {
-      return _U.isJSArray(v) ? _L.fromArray(v.map(function (v) {
-         return _U.isJSArray(v) ? {ctor: "_Tuple2"
-                                  ,_0: typeof v[0] === "string" || typeof v[0] === "object" && v[0] instanceof String ? v[0] : _E.raise("invalid input, expecting JSString but got " + v[0])
-                                  ,_1: typeof v[1] === "string" || typeof v[1] === "object" && v[1] instanceof String ? v[1] : _E.raise("invalid input, expecting JSString but got " + v[1])} : _E.raise("invalid input, expecting JSArray but got " + v);
-      })) : _E.raise("invalid input, expecting JSArray but got " + v);
-   }));
-   var eventCounter = $Native$Ports.portIn("eventCounter",
-   $Native$Ports.incomingSignal(function (v) {
-      return typeof v === "number" ? v : _E.raise("invalid input, expecting JSNumber but got " + v);
-   }));
-   var scrubInput = $Graphics$Input.input(0);
-   var restartInput = $Graphics$Input.input({ctor: "_Tuple0"});
-   var permitSwapInput = $Graphics$Input.input(true);
-   var pausedInput = $Graphics$Input.input(false);
-   var permitSwap = $Native$Ports.portOut("permitSwap",
-   $Native$Ports.outgoingSignal(function (v) {
-      return v;
-   }),
-   permitSwapInput.signal);
-   var restart = $Native$Ports.portOut("restart",
-   $Native$Ports.outgoingSignal(function (v) {
-      return v;
-   }),
-   A2($Signal.lift,
-   function (x) {
-      return 0;
-   },
-   restartInput.signal));
-   var scrubSlider = F2(function (_v4,
-   state) {
-      return function () {
-         switch (_v4.ctor)
-         {case "_Tuple2":
-            return function () {
-                 var sliderLength = _v4._0;
-                 var sliderStyle = _U.replace([["length"
-                                               ,sliderLength]
-                                              ,["max"
-                                               ,$Basics.toFloat(state.totalEvents)]
-                                              ,["value"
-                                               ,$Basics.toFloat(state.scrubPosition)]],
-                 $Slider.defaultSlider);
-                 return A3($Graphics$Element.container,
-                 sliderLength,
-                 20,
-                 $Graphics$Element.middle)(A3($Slider.slider,
-                 scrubInput.handle,
-                 $Basics.round,
-                 sliderStyle));
-              }();}
-         _E.Case($moduleName,
-         "between lines 115 and 123");
-      }();
-   });
-   var myButton = F3(function (handle,
-   value,
-   name) {
-      return function () {
-         var img = function (state) {
-            return A3($Graphics$Element.image,
-            40,
-            40,
-            _L.append("/_reactor/debugger/",
-            _L.append(name,
-            _L.append("-button-",
-            _L.append(state,".png")))));
-         };
-         return A5($Graphics$Input.customButton,
-         handle,
-         value,
-         img("up"),
-         img("hover"),
-         img("down"));
-      }();
-   });
-   var playButton = A3(myButton,
-   pausedInput.handle,
-   false,
-   "play");
-   var pauseButton = A3(myButton,
-   pausedInput.handle,
-   true,
-   "pause");
-   var restartButton = A3(myButton,
-   restartInput.handle,
-   {ctor: "_Tuple0"},
-   "restart");
-   var darkGrey = A3($Color.rgb,
-   74,
-   74,
-   74);
-   var lightGrey = A3($Color.rgb,
-   228,
-   228,
-   228);
-   var dataStyle = F3(function (typefaces,
-   height,
-   string) {
-      return function () {
-         var myStyle = _U.replace([["typeface"
-                                   ,typefaces]
-                                  ,["color",lightGrey]
-                                  ,["height"
-                                   ,$Maybe.Just(height)]],
-         $Text.defaultStyle);
-         return A2($Text.style,
-         myStyle,
-         $Text.toText(string));
-      }();
-   });
-   var textStyle = A2(dataStyle,
-   _L.fromArray(["Gotham"
-                ,"Futura"
-                ,"Lucida Grande"
-                ,"sans-serif"]),
-   12);
-   var watchStyle = A2(dataStyle,
-   _L.fromArray(["Gotham"
-                ,"Futura"
-                ,"Lucida Grande"
-                ,"sans-serif"]),
-   14);
-   var codeStyle = A2(dataStyle,
-   _L.fromArray(["Menlo for Powerline"
-                ,"monospace"]),
-   12);
-   var blue = A3($Color.rgb,
-   28,
-   129,
-   218);
-   var swapButton = function (permitSwap) {
-      return function () {
-         var info = $Text.leftAligned(textStyle("swap"));
-         var radius = 4;
-         var hsWidth = 25;
-         var bgButton = A3(roundedSquare,
-         hsWidth,
-         radius,
-         $Graphics$Collage.filled(lightGrey));
-         var trueButton = _L.fromArray([bgButton
-                                       ,A3(roundedSquare,
-                                       22,
-                                       radius,
-                                       $Graphics$Collage.filled(blue))]);
-         var falseButtonClick = trueButton;
-         var trueButtonHover = _L.fromArray([bgButton
-                                            ,A3(roundedSquare,
-                                            22,
-                                            radius,
-                                            $Graphics$Collage.filled(blue))
-                                            ,$Graphics$Collage.alpha(0.1)(A3(roundedSquare,
-                                            22,
-                                            radius,
-                                            $Graphics$Collage.filled(darkGrey)))]);
-         var falseButton = _L.fromArray([bgButton
-                                        ,A3(roundedSquare,
-                                        22,
-                                        radius,
-                                        $Graphics$Collage.filled(darkGrey))]);
-         var trueButtonClick = falseButton;
-         var falseButtonHover = _L.fromArray([bgButton
-                                             ,A3(roundedSquare,
-                                             22,
-                                             radius,
-                                             $Graphics$Collage.filled(darkGrey))
-                                             ,$Graphics$Collage.alpha(0.1)(A3(roundedSquare,
-                                             22,
-                                             radius,
-                                             $Graphics$Collage.filled(blue)))]);
-         var button = permitSwap ? A5($Graphics$Input.customButton,
-         permitSwapInput.handle,
-         false,
-         A3($Graphics$Collage.collage,
-         hsWidth,
-         hsWidth,
-         trueButton),
-         A3($Graphics$Collage.collage,
-         hsWidth,
-         hsWidth,
-         trueButtonHover),
-         A3($Graphics$Collage.collage,
-         hsWidth,
-         hsWidth,
-         trueButtonClick)) : A5($Graphics$Input.customButton,
-         permitSwapInput.handle,
-         true,
-         A3($Graphics$Collage.collage,
-         hsWidth,
-         hsWidth,
-         falseButton),
-         A3($Graphics$Collage.collage,
-         hsWidth,
-         hsWidth,
-         falseButtonHover),
-         A3($Graphics$Collage.collage,
-         hsWidth,
-         hsWidth,
-         falseButtonClick));
-         return A2($Graphics$Element.flow,
-         $Graphics$Element.right,
-         _L.fromArray([info
-                      ,A2($Graphics$Element.spacer,
-                      10,
-                      1)
-                      ,button]));
-      }();
-   };
-   var panelWidth = 275;
-   var textHeight = 20;
-   var sliderMinMaxText = F2(function (w,
-   state) {
-      return function () {
-         var sliderTotalEvents = A3($Graphics$Element.container,
-         w,
-         textHeight,
-         $Graphics$Element.topRight)($Text.rightAligned(textStyle($String.show(state.totalEvents))));
-         var sliderStartText = A3($Graphics$Element.container,
-         w,
-         textHeight,
-         $Graphics$Element.topLeft)($Text.leftAligned(textStyle("0")));
-         return A2($Graphics$Element.flow,
-         $Graphics$Element.outward,
-         _L.fromArray([sliderStartText
-                      ,sliderTotalEvents]));
-      }();
-   });
-   var sideMargin = 2 * 20;
-   var sliderEventText = F2(function (w,
-   state) {
-      return function () {
-         var text$ = $Text.centered(textStyle($String.show(state.scrubPosition)));
-         var yPos = $Graphics$Element.absolute($Basics.round(textHeight / 2));
-         var totalEvents = $Basics.toFloat(state.totalEvents);
-         var scrubPosition = $Basics.toFloat(state.scrubPosition);
-         var textWidthOffset = 14;
-         var midWidth = $Basics.toFloat(w) - sideMargin - textWidthOffset;
-         var leftDistance = _U.eq(totalEvents,
-         0) ? sideMargin / 2 + textWidthOffset / 2 : scrubPosition / totalEvents * midWidth + sideMargin / 2 + textWidthOffset / 2;
-         var xPos = $Graphics$Element.absolute($Basics.round(leftDistance));
-         var textPosition = A2($Graphics$Element.middleAt,
-         xPos,
-         yPos);
-         return A4($Graphics$Element.container,
-         w,
-         textHeight,
-         textPosition,
-         text$);
-      }();
-   });
-   var buttonWidth = 40;
-   var buttonHeight = 40;
-   var view = F4(function (_v8,
-   watches,
-   permitSwap,
-   state) {
-      return function () {
-         switch (_v8.ctor)
-         {case "_Tuple2":
-            return function () {
-                 var showWatch = function (_v12) {
-                    return function () {
-                       switch (_v12.ctor)
-                       {case "_Tuple2":
-                          return A2($Graphics$Element.flow,
-                            $Graphics$Element.down,
-                            _L.fromArray([$Graphics$Element.width(_v8._0)($Text.leftAligned($Text.bold(watchStyle(_v12._0))))
-                                         ,$Graphics$Element.width(_v8._0)($Text.leftAligned(codeStyle(_v12._1)))
-                                         ,A2($Graphics$Element.spacer,
-                                         1,
-                                         12)]));}
-                       _E.Case($moduleName,
-                       "between lines 195 and 199");
-                    }();
-                 };
-                 var watchView = A2($Graphics$Element.flow,
-                 $Graphics$Element.right,
-                 _L.fromArray([A2($Graphics$Element.spacer,
-                              20,
-                              1)
-                              ,function () {
-                                 switch (watches.ctor)
-                                 {case "[]": return noWatches;}
-                                 return $Graphics$Element.flow($Graphics$Element.down)(A2($List.map,
-                                 showWatch,
-                                 watches));
-                              }()]));
-                 var bar = A2($Graphics$Element.flow,
-                 $Graphics$Element.down,
-                 _L.fromArray([$Graphics$Element.opacity(0.3)($Graphics$Element.color(lightGrey)(A2($Graphics$Element.spacer,
-                              _v8._0,
-                              1)))
-                              ,A2($Graphics$Element.spacer,
-                              _v8._0,
-                              12)]));
-                 var fittedSwapButton = showSwap ? A3($Graphics$Element.container,
-                 _v8._0 - 2 * buttonWidth - sideMargin,
-                 buttonHeight,
-                 $Graphics$Element.middle)(swapButton(permitSwap)) : A2($Graphics$Element.spacer,
-                 2 * buttonWidth,
-                 1);
-                 var buttons = A2($Graphics$Element.flow,
-                 $Graphics$Element.right,
-                 _L.fromArray([restartButton
-                              ,fittedSwapButton
-                              ,state.paused ? playButton : pauseButton]));
-                 var buttonContainer = A4($Graphics$Element.container,
-                 _v8._0,
-                 buttonHeight,
-                 $Graphics$Element.midTop,
-                 buttons);
-                 var buttonSliderSpaceHeight = 10;
-                 var topSpacerHeight = 15;
-                 var midWidth = _v8._0 - sideMargin;
-                 var centeredSliderContainer = A3($Graphics$Element.container,
-                 _v8._0,
-                 24 + textHeight,
-                 $Graphics$Element.midTop)(A2($Graphics$Element.flow,
-                 $Graphics$Element.down,
-                 _L.fromArray([A2(scrubSlider,
-                              {ctor: "_Tuple2"
-                              ,_0: midWidth
-                              ,_1: _v8._1},
-                              state)
-                              ,A2(sliderMinMaxText,
-                              midWidth,
-                              state)])));
-                 var slider = A3($Graphics$Element.container,
-                 _v8._0,
-                 24 + 2 * textHeight,
-                 $Graphics$Element.midTop)(A2($Graphics$Element.flow,
-                 $Graphics$Element.down,
-                 _L.fromArray([A2(sliderEventText,
-                              _v8._0,
-                              state)
-                              ,centeredSliderContainer])));
-                 var controls = A2($Graphics$Element.flow,
-                 $Graphics$Element.down,
-                 _L.fromArray([A2($Graphics$Element.spacer,
-                              midWidth,
-                              topSpacerHeight)
-                              ,buttonContainer
-                              ,A2($Graphics$Element.spacer,
-                              midWidth,
-                              buttonSliderSpaceHeight)
-                              ,slider
-                              ,A2($Graphics$Element.spacer,
-                              midWidth,
-                              10)]));
-                 return A2($Graphics$Element.flow,
-                 $Graphics$Element.down,
-                 _L.fromArray([controls
-                              ,bar
-                              ,watchView]));
-              }();}
-         _E.Case($moduleName,
-         "between lines 160 and 210");
-      }();
-   });
-   var State = F3(function (a,
-   b,
-   c) {
-      return {_: {}
-             ,paused: a
-             ,scrubPosition: c
-             ,totalEvents: b};
-   });
-   var ScrubPosition = function (a) {
-      return {ctor: "ScrubPosition"
-             ,_0: a};
-   };
-   var TotalEvents = function (a) {
-      return {ctor: "TotalEvents"
-             ,_0: a};
-   };
-   var Pause = function (a) {
-      return {ctor: "Pause",_0: a};
-   };
-   var Restart = {ctor: "Restart"};
-   var aggregateUpdates = $Signal.merges(_L.fromArray([A2($Signal._op["<~"],
-                                                      $Basics.always(Restart),
-                                                      restartInput.signal)
-                                                      ,A2($Signal._op["<~"],
-                                                      Pause,
-                                                      pausedInput.signal)
-                                                      ,A2($Signal._op["<~"],
-                                                      TotalEvents,
-                                                      eventCounter)
-                                                      ,A2($Signal._op["<~"],
-                                                      ScrubPosition,
-                                                      scrubInput.signal)]));
-   var scene = A3($Signal.foldp,
-   step,
-   startState,
-   aggregateUpdates);
-   var main = A2($Signal._op["~"],
-   A2($Signal._op["~"],
-   A2($Signal._op["~"],
-   A2($Signal._op["<~"],
-   view,
-   A2($Signal._op["<~"],
-   function (_v17) {
-      return function () {
-         switch (_v17.ctor)
-         {case "_Tuple2":
-            return {ctor: "_Tuple2"
-                   ,_0: panelWidth
-                   ,_1: _v17._1};}
-         _E.Case($moduleName,
-         "on line 218, column 30 to 43");
-      }();
-   },
-   $Window.dimensions)),
-   watches),
-   permitSwapInput.signal),
-   scene);
-   var scrubTo = $Native$Ports.portOut("scrubTo",
-   $Native$Ports.outgoingSignal(function (v) {
-      return v;
-   }),
-   A2($Signal._op["<~"],
-   function (_) {
-      return _.scrubPosition;
-   },
-   scene));
-   var pause = $Native$Ports.portOut("pause",
-   $Native$Ports.outgoingSignal(function (v) {
-      return v;
-   }),
-   A2($Signal._op["<~"],
-   function (_) {
-      return _.paused;
-   },
-   scene));
-   _elm.DebuggerInterface.values = {_op: _op
-                                   ,Restart: Restart
-                                   ,Pause: Pause
-                                   ,TotalEvents: TotalEvents
-                                   ,ScrubPosition: ScrubPosition
-                                   ,State: State
-                                   ,buttonHeight: buttonHeight
-                                   ,buttonWidth: buttonWidth
-                                   ,sideMargin: sideMargin
-                                   ,textHeight: textHeight
-                                   ,panelWidth: panelWidth
-                                   ,blue: blue
-                                   ,lightGrey: lightGrey
-                                   ,darkGrey: darkGrey
-                                   ,dataStyle: dataStyle
-                                   ,textStyle: textStyle
-                                   ,watchStyle: watchStyle
-                                   ,codeStyle: codeStyle
-                                   ,myButton: myButton
-                                   ,playButton: playButton
-                                   ,pauseButton: pauseButton
-                                   ,restartButton: restartButton
-                                   ,swapButton: swapButton
-                                   ,scrubSlider: scrubSlider
-                                   ,sliderEventText: sliderEventText
-                                   ,sliderMinMaxText: sliderMinMaxText
-                                   ,view: view
-                                   ,main: main
-                                   ,pausedInput: pausedInput
-                                   ,permitSwapInput: permitSwapInput
-                                   ,restartInput: restartInput
-                                   ,scrubInput: scrubInput
-                                   ,scene: scene
-                                   ,startState: startState
-                                   ,step: step
-                                   ,aggregateUpdates: aggregateUpdates
-                                   ,roundedSquare: roundedSquare
-                                   ,noWatches: noWatches};
-   return _elm.DebuggerInterface.values;
-};Elm.Slider = Elm.Slider || {};
-Elm.Slider.make = function (_elm) {
-   "use strict";
-   _elm.Slider = _elm.Slider || {};
-   if (_elm.Slider.values)
-   return _elm.Slider.values;
-   var _op = {},
-   _N = Elm.Native,
-   _U = _N.Utils.make(_elm),
-   _L = _N.List.make(_elm),
-   _A = _N.Array.make(_elm),
-   _E = _N.Error.make(_elm),
-   $moduleName = "Slider",
-   $Graphics$Element = Elm.Graphics.Element.make(_elm),
-   $Graphics$Input = Elm.Graphics.Input.make(_elm),
-   $Native$Slider = Elm.Native.Slider.make(_elm);
-   var slider = $Native$Slider.slider;
-   var defaultSlider = {_: {}
-                       ,disabled: false
-                       ,horizontal: true
-                       ,length: 100
-                       ,max: 100
-                       ,min: 0
-                       ,step: 1
-                       ,value: 0};
-   var SliderStyle = F7(function (a,
-   b,
-   c,
-   d,
-   e,
-   f,
-   g) {
-      return {_: {}
-             ,disabled: b
-             ,horizontal: a
-             ,length: c
-             ,max: e
-             ,min: d
-             ,step: f
-             ,value: g};
-   });
-   _elm.Slider.values = {_op: _op
-                        ,SliderStyle: SliderStyle
-                        ,defaultSlider: defaultSlider
-                        ,slider: slider};
-   return _elm.Slider.values;
-};
-// A note to the reader:
-// This file is concatenated with debuggerInterface.elm's compiled
-// javascript and debug-core.js. This is done at build time in Setup.hs
-
-var prettyPrint = function(){
-
-    var independentElm = {};
-    var NList = Elm.Native.List.make(independentElm);
-    var List = Elm.List.make(independentElm);
-    var ElmArray = Elm.Array.make(independentElm);
-    var Dict = Elm.Dict.make(independentElm);
-    var Tuple2 = Elm.Native.Utils.make(independentElm).Tuple2;
-
-    var toString = function(v, separator) {
-        var type = typeof v;
-        if (type === "function") {
-            var name = v.func ? v.func.name : v.name;
-            return '<function' + (name === '' ? '' : ': ') + name + '>';
-        } else if (type === "boolean") {
-            return v ? "True" : "False";
-        } else if (type === "number") {
-            return v.toFixed(2).replace(/\.0+$/g, '');
-        } else if ((v instanceof String) && v.isChar) {
-            return "'" + addSlashes(v) + "'";
-        } else if (type === "string") {
-            return '"' + addSlashes(v) + '"';
-        } else if (type === "object" && '_' in v && probablyPublic(v)) {
-            var output = [];
-            for (var k in v._) {
-                for (var i = v._[k].length; i--; ) {
-                    output.push(k + " = " + toString(v._[k][i], separator));
-                }
-            }
-            for (var k in v) {
-                if (k === '_') continue;
-                output.push(k + " = " + toString(v[k], separator));
-            }
-            if (output.length === 0) return "{}";
-            var body = "\n" + output.join(",\n");
-            return "{" + body.replace(/\n/g,"\n" + separator) + "\n}";
-        } else if (type === "object" && 'ctor' in v) {
-            if (v.ctor.substring(0,6) === "_Tuple") {
-                var output = [];
-                for (var k in v) {
-                    if (k === 'ctor') continue;
-                    output.push(toString(v[k], separator));
-                }
-                return "(" + output.join(", ") + ")";
-            } else if (v.ctor === "_Array") {
-                var list = ElmArray.toList(v);
-                return "Array.fromList " + toString(list, separator);
-            } else if (v.ctor === "::") {
-                var output = '[\n' + toString(v._0, separator);
-                v = v._1;
-                while (v && v.ctor === "::") {
-                    output += ",\n" + toString(v._0, separator);
-                    v = v._1;
-                }
-                return output.replace(/\n/g,"\n" + separator) + "\n]";
-            } else if (v.ctor === "[]") {
-                return "[]";
-            } else if (v.ctor === "RBNode" || v.ctor === "RBEmpty") {
-                var cons = F3(function(k,v,acc){return NList.Cons(Tuple2(k,v),acc)});
-                var list = A3(Dict.foldr, cons, NList.Nil, v);
-                var name = "Dict";
-                if (list.ctor === "::" && list._0._1.ctor === "_Tuple0") {
-                    name = "Set";
-                    list = A2(List.map, function(x){return x._0}, list);
-                }
-                return name + ".fromList " + toString(list, separator);
-            } else {
-                var output = "";
-                for (var i in v) {
-                    if (i === 'ctor') continue;
-                    var str = toString(v[i], separator);
-                    var parenless = str[0] === '{' ||
-                                    str[0] === '<' ||
-                                    str[0] === "[" ||
-                                    str.indexOf(' ') < 0;
-                    output += ' ' + (parenless ? str : "(" + str + ')');
-                }
-                return v.ctor + output;
-            }
-        }
-        if (type === 'object' && 'recv' in v) return '<signal>';
-        return "<internal structure>";
-    };
-
-    function addSlashes(str) {
-        return str.replace(/\\/g, '\\\\')
-                  .replace(/\n/g, '\\n')
-                  .replace(/\t/g, '\\t')
-                  .replace(/\r/g, '\\r')
-                  .replace(/\v/g, '\\v')
-                  .replace(/\0/g, '\\0')
-                  .replace(/\'/g, "\\'")
-                  .replace(/\"/g, '\\"');
-    }
-
-    function probablyPublic(v) {
-        var keys = Object.keys(v);
-        var len = keys.length;
-        if (len === 3
-            && 'props' in v
-            && 'element' in v) return false;
-        if (len === 5
-            && 'horizontal' in v
-            && 'vertical' in v
-            && 'x' in v
-            && 'y' in v) return false;
-        if (len === 7
-            && 'theta' in v
-            && 'scale' in v
-            && 'x' in v
-            && 'y' in v
-            && 'alpha' in v
-            && 'form' in v) return false;
-        return true;
-    }
-
-    return toString;
-}();
-// A note to the reader:
-// This file is concatenated with debuggerInterface.elm's compiled
-// javascript, toString.js, and reactor.js.
-// This is done at build time in Setup.hs.
-
-// Options:
-
-// Expose internal swap function, disable swap button, no socket
-// options.externalSwap = boolean
-
-ElmRuntime.debugFullscreenWithOptions = function(options) {
-
-    return function(module, moduleFile, swapState /* =undefined */) {
-        var createdSocket = false;
-        var elmPermitSwaps = true;
-
-        var ELM_DEBUGGER_ID = "elmToolPanel";
-        var ELM_DARK_GREY = "#4A4A4A";
-        var ELM_LIGHT_GREY = "#E4E4E4";
-
-        var mainHandle = Elm.fullscreenDebugHooks(module, swapState);
-        var debuggerHandle = initDebugger();
-        if (!options.externalSwap) {
-            initSocket();
-        }
-
-        parent.window.addEventListener("message", function(e) {
-            if (e.data === "elmNotify") {
-                var currentPosition = mainHandle.debugger.getMaxSteps();
-                if (debuggerHandle.ports) {
-                    debuggerHandle.ports.eventCounter.send(currentPosition);
-                    sendWatches(currentPosition);
-                }
-            }
-        }, false);
-
-        function createDebuggingElement() {
-            var debuggingPanelExpanded = true;
-            var debuggerWidth = 275;
-
-            var debugTools = document.createElement("div");
-            debugTools.id = ELM_DEBUGGER_ID;
-
-            var debuggerDiv = document.createElement("div");
-            debuggerDiv.id = "elmDebugger";
-            debuggerDiv.style.overflow = "hidden";
-
-            // Create and style the panel
-            debugTools.style.background = ELM_DARK_GREY;
-            debugTools.style.width = debuggerWidth + "px";
-            debugTools.style.height = "100%";
-            debugTools.style.position = "absolute";
-            debugTools.style.top = "0px";
-            debugTools.style.right = "0px";
-            debugTools.style.transitionDuration = "0.3s";
-            debugTools.style.opacity = 0.97;
-            debugTools.style.zIndex = 1;
-
-            // Prevent clicks from reaching the main elm instance under the panel
-            function stopEvents(e) {
-                if (!e) {
-                    var e = window.event;
-                }
-                e.cancelBubble = true;
-                if (e.stopPropagation) {
-                    e.stopPropagation();
-                }
-            }
-            debugTools.addEventListener("click", stopEvents);
-
-            // Create and style the button
-            var tabWidth = 25;
-            var debugTab = document.createElement("div");
-            debugTab.id = "debugToggle";
-            debugTab.style.position = "absolute";
-            debugTab.style.width = tabWidth + "px";
-            debugTab.style.height = "60px";
-            debugTab.style.top = window.innerHeight / 2 + "px";
-            debugTab.style.left = "-" + tabWidth + "px";
-            debugTab.style.borderTopLeftRadius = "3px";
-            debugTab.style.borderBottomLeftRadius = "3px";
-            debugTab.style.background = ELM_DARK_GREY;
-
-
-            // Wire the button
-            debugTab.onclick = function() {
-                var toolPanel = document.getElementById("elmToolPanel");
-                if (debuggingPanelExpanded){
-                    toolPanel.style.width = "0px";
-                    debuggingPanelExpanded = false;
-                } else {
-                    toolPanel.style.right = "0px";
-                    toolPanel.style.width = debuggerWidth + "px";
-                    debuggingPanelExpanded = true;
-                }
-            };
-
-            debugTools.appendChild(debugTab);
-            debugTools.appendChild(debuggerDiv);
-            return debugTools;
-        }
-
-        function initDebugger() {
-            function scrubber(position) {
-                if (mainHandle.debugger.getPaused()) {
-                    mainHandle.debugger.stepTo(position);
-                    sendWatches(position);
-                }
-            }
-
-            function elmPauser(doPause) {
-                if (doPause) {
-                  mainHandle.debugger.pause();
-                } else {
-                    mainHandle.debugger.kontinue();
-                }
-            }
-
-            function elmRestart() {
-                mainHandle.debugger.restart();
-                sendWatches(0);
-            }
-
-            function elmSwap(permitSwaps) {
-                elmPermitSwaps = permitSwaps;
-            }
-
-            var debugTools = createDebuggingElement();
-            document.body.appendChild(debugTools);
-            var debuggerDiv = document.getElementById("elmDebugger");
-
-            var handle = Elm.embed(Elm.DebuggerInterface, debuggerDiv,
-                { eventCounter: 0,
-                  watches: [],
-                  showSwap: !options.externalSwap
-                });
-            handle.ports.scrubTo.subscribe(scrubber);
-            handle.ports.pause.subscribe(elmPauser);
-            handle.ports.restart.subscribe(elmRestart);
-            handle.ports.permitSwap.subscribe(elmSwap);
-            return handle;
-        }
-
-        function sendWatches(position) {
-            var separator = "  ";
-            var output = [];
-
-            var watchAtPoint = mainHandle.debugger.watchTracker.frames[position];
-
-            for(key in watchAtPoint) {
-                var value = watchAtPoint[key];
-                // The toString object is defined in toString.js
-                // and is prepended to this file at build time.
-                var stringified = prettyPrint(value, separator);
-                output.push([key, stringified]);
-            }
-            debuggerHandle.ports.watches.send(output);
-        }
-
-        function initSocket() {
-            createdSocket = true;
-            // "/todo.html" => "todo.elm"
-            moduleFile = moduleFile || window.location.pathname.substr(1).split(".")[0] + ".elm";
-            var socketLocation = "ws://" + window.location.host + "/socket?file=" + moduleFile;
-            var serverConnection = new WebSocket(socketLocation);
-            serverConnection.onmessage = function(event) {
-                if (elmPermitSwaps && debuggerHandle.ports) {
-                    swap(event.data);
-                }
-            };
-            window.addEventListener("unload", function() {
-                serverConnection.close();
-            });
-        }
-
-        function swap(raw) {
-            var debuggerDiv = document.getElementById(ELM_DEBUGGER_ID);
-            var result = JSON.parse(raw);
-            var js = result.success;
-            var errorMessage = result.error;
-            var error = document.getElementById('ErrorMessage');
-            if (error) {
-                error.parentNode.removeChild(error);
-            }
-            if (js) {
-                window.eval(js);
-                var moduleStr = js.match(/(Elm\..+)\ =\ \1/)[1];
-                var module = window.eval(moduleStr);
-                if (mainHandle.debugger) {
-                    var debuggerState = mainHandle.debugger.getSwapState();
-                    mainHandle.debugger.dispose();
-                    mainHandle.dispose();
-
-                    mainHandle = Elm.fullscreenDebugHooks(module, debuggerState);
-
-                    // The div that rejects events must be after Elm
-                    var ignoringDiv = document.getElementById("elmEventIgnorer");
-                    if (ignoringDiv) {
-                        ignoringDiv.parentNode.appendChild(ignoringDiv);
-                    }
-                }
-                else {
-                    mainHandle = mainHandle.swap(module);
-                }
-            } else if (errorMessage) {
-                var errorNode = document.createElement("pre");
-                errorNode.id = "ErrorMessage";
-                errorNode.innerHTML = errorMessage;
-                errorNode.style.zindex = 1;
-                errorNode.style.position = "absolute";
-                errorNode.style.top = "0";
-                errorNode.style.left = "0";
-                errorNode.style.color = ELM_DARK_GREY;
-                errorNode.style.backgroundColor = ELM_LIGHT_GREY;
-                errorNode.style.padding = "1em";
-                errorNode.style.margin = "1em";
-                errorNode.style.borderRadius = "10px";
-
-                document.body.appendChild(errorNode);
-            }
-        }
-
-        if (!options.externalSwap) {
-            mainHandle.debugger.swap = swap;
-        }
-        return mainHandle;
-    };
-};
-// A note to the reader:
-// This file is concatenated with debuggerInterface.elm's compiled
-// javascript, toString.js, and debug-core.js. This is done at build time in Setup.hs
-
-Elm.debugFullscreen = ElmRuntime.debugFullscreenWithOptions({
+var Elm = Elm || { Native: {} };
+Elm.Array = Elm.Array || {};
+Elm.Array.make = function (_elm) {
+   "use strict";
+   _elm.Array = _elm.Array || {};
+   if (_elm.Array.values)
+   return _elm.Array.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Array",
+   $Basics = Elm.Basics.make(_elm),
+   $List = Elm.List.make(_elm),
+   $Maybe = Elm.Maybe.make(_elm),
+   $Native$Array = Elm.Native.Array.make(_elm);
+   var append = $Native$Array.append;
+   var length = $Native$Array.length;
+   var slice = $Native$Array.slice;
+   var set = $Native$Array.set;
+   var get = F2(function (i,
+   array) {
+      return _U.cmp(0,
+      i) < 1 && _U.cmp(i,
+      $Native$Array.length(array)) < 0 ? $Maybe.Just(A2($Native$Array.get,
+      i,
+      array)) : $Maybe.Nothing;
+   });
+   var push = $Native$Array.push;
+   var empty = $Native$Array.empty;
+   var filter = F2(function (isOkay,
+   arr) {
+      return function () {
+         var update = F2(function (x,
+         xs) {
+            return isOkay(x) ? A2($Native$Array.push,
+            x,
+            xs) : xs;
+         });
+         return A3($Native$Array.foldl,
+         update,
+         $Native$Array.empty,
+         arr);
+      }();
+   });
+   var foldr = $Native$Array.foldr;
+   var foldl = $Native$Array.foldl;
+   var indexedMap = $Native$Array.indexedMap;
+   var map = $Native$Array.map;
+   var toIndexedList = function (array) {
+      return A3($List.map2,
+      F2(function (v0,v1) {
+         return {ctor: "_Tuple2"
+                ,_0: v0
+                ,_1: v1};
+      }),
+      _L.range(0,
+      $Native$Array.length(array) - 1),
+      $Native$Array.toList(array));
+   };
+   var toList = $Native$Array.toList;
+   var fromList = $Native$Array.fromList;
+   var initialize = $Native$Array.initialize;
+   var repeat = F2(function (n,e) {
+      return A2(initialize,
+      n,
+      $Basics.always(e));
+   });
+   var Array = {ctor: "Array"};
+   _elm.Array.values = {_op: _op
+                       ,Array: Array
+                       ,initialize: initialize
+                       ,repeat: repeat
+                       ,fromList: fromList
+                       ,toList: toList
+                       ,toIndexedList: toIndexedList
+                       ,map: map
+                       ,indexedMap: indexedMap
+                       ,foldl: foldl
+                       ,foldr: foldr
+                       ,filter: filter
+                       ,empty: empty
+                       ,push: push
+                       ,get: get
+                       ,set: set
+                       ,slice: slice
+                       ,length: length
+                       ,append: append};
+   return _elm.Array.values;
+};
+Elm.Basics = Elm.Basics || {};
+Elm.Basics.make = function (_elm) {
+   "use strict";
+   _elm.Basics = _elm.Basics || {};
+   if (_elm.Basics.values)
+   return _elm.Basics.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Basics",
+   $Native$Basics = Elm.Native.Basics.make(_elm),
+   $Native$Show = Elm.Native.Show.make(_elm),
+   $Native$Utils = Elm.Native.Utils.make(_elm);
+   var uncurry = F2(function (f,
+   _v0) {
+      return function () {
+         switch (_v0.ctor)
+         {case "_Tuple2": return A2(f,
+              _v0._0,
+              _v0._1);}
+         _U.badCase($moduleName,
+         "on line 461, column 19 to 24");
+      }();
+   });
+   var curry = F3(function (f,
+   a,
+   b) {
+      return f({ctor: "_Tuple2"
+               ,_0: a
+               ,_1: b});
+   });
+   var flip = F3(function (f,b,a) {
+      return A2(f,a,b);
+   });
+   var snd = function (_v4) {
+      return function () {
+         switch (_v4.ctor)
+         {case "_Tuple2": return _v4._1;}
+         _U.badCase($moduleName,
+         "on line 445, column 13 to 14");
+      }();
+   };
+   var fst = function (_v8) {
+      return function () {
+         switch (_v8.ctor)
+         {case "_Tuple2": return _v8._0;}
+         _U.badCase($moduleName,
+         "on line 441, column 13 to 14");
+      }();
+   };
+   var always = F2(function (a,
+   _v12) {
+      return function () {
+         return a;
+      }();
+   });
+   var identity = function (x) {
+      return x;
+   };
+   _op["<|"] = F2(function (f,x) {
+      return f(x);
+   });
+   _op["|>"] = F2(function (x,f) {
+      return f(x);
+   });
+   _op[">>"] = F3(function (f,
+   g,
+   x) {
+      return g(f(x));
+   });
+   _op["<<"] = F3(function (g,
+   f,
+   x) {
+      return g(f(x));
+   });
+   _op["++"] = $Native$Utils.append;
+   var toString = $Native$Show.toString;
+   var isInfinite = $Native$Basics.isInfinite;
+   var isNaN = $Native$Basics.isNaN;
+   var toFloat = $Native$Basics.toFloat;
+   var ceiling = $Native$Basics.ceiling;
+   var floor = $Native$Basics.floor;
+   var truncate = $Native$Basics.truncate;
+   var round = $Native$Basics.round;
+   var otherwise = true;
+   var not = $Native$Basics.not;
+   var xor = $Native$Basics.xor;
+   _op["||"] = $Native$Basics.or;
+   _op["&&"] = $Native$Basics.and;
+   var max = $Native$Basics.max;
+   var min = $Native$Basics.min;
+   var GT = {ctor: "GT"};
+   var EQ = {ctor: "EQ"};
+   var LT = {ctor: "LT"};
+   var compare = $Native$Basics.compare;
+   _op[">="] = $Native$Basics.ge;
+   _op["<="] = $Native$Basics.le;
+   _op[">"] = $Native$Basics.gt;
+   _op["<"] = $Native$Basics.lt;
+   _op["/="] = $Native$Basics.neq;
+   _op["=="] = $Native$Basics.eq;
+   var e = $Native$Basics.e;
+   var pi = $Native$Basics.pi;
+   var clamp = $Native$Basics.clamp;
+   var logBase = $Native$Basics.logBase;
+   var abs = $Native$Basics.abs;
+   var negate = $Native$Basics.negate;
+   var sqrt = $Native$Basics.sqrt;
+   var atan2 = $Native$Basics.atan2;
+   var atan = $Native$Basics.atan;
+   var asin = $Native$Basics.asin;
+   var acos = $Native$Basics.acos;
+   var tan = $Native$Basics.tan;
+   var sin = $Native$Basics.sin;
+   var cos = $Native$Basics.cos;
+   _op["^"] = $Native$Basics.exp;
+   _op["%"] = $Native$Basics.mod;
+   var rem = $Native$Basics.rem;
+   _op["//"] = $Native$Basics.div;
+   _op["/"] = $Native$Basics.floatDiv;
+   _op["*"] = $Native$Basics.mul;
+   _op["-"] = $Native$Basics.sub;
+   _op["+"] = $Native$Basics.add;
+   var toPolar = $Native$Basics.toPolar;
+   var fromPolar = $Native$Basics.fromPolar;
+   var turns = $Native$Basics.turns;
+   var degrees = $Native$Basics.degrees;
+   var radians = function (t) {
+      return t;
+   };
+   _elm.Basics.values = {_op: _op
+                        ,radians: radians
+                        ,degrees: degrees
+                        ,turns: turns
+                        ,fromPolar: fromPolar
+                        ,toPolar: toPolar
+                        ,rem: rem
+                        ,cos: cos
+                        ,sin: sin
+                        ,tan: tan
+                        ,acos: acos
+                        ,asin: asin
+                        ,atan: atan
+                        ,atan2: atan2
+                        ,sqrt: sqrt
+                        ,negate: negate
+                        ,abs: abs
+                        ,logBase: logBase
+                        ,clamp: clamp
+                        ,pi: pi
+                        ,e: e
+                        ,compare: compare
+                        ,LT: LT
+                        ,EQ: EQ
+                        ,GT: GT
+                        ,min: min
+                        ,max: max
+                        ,xor: xor
+                        ,not: not
+                        ,otherwise: otherwise
+                        ,round: round
+                        ,truncate: truncate
+                        ,floor: floor
+                        ,ceiling: ceiling
+                        ,toFloat: toFloat
+                        ,isNaN: isNaN
+                        ,isInfinite: isInfinite
+                        ,toString: toString
+                        ,identity: identity
+                        ,always: always
+                        ,fst: fst
+                        ,snd: snd
+                        ,flip: flip
+                        ,curry: curry
+                        ,uncurry: uncurry};
+   return _elm.Basics.values;
+};
+Elm.Char = Elm.Char || {};
+Elm.Char.make = function (_elm) {
+   "use strict";
+   _elm.Char = _elm.Char || {};
+   if (_elm.Char.values)
+   return _elm.Char.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Char",
+   $Native$Char = Elm.Native.Char.make(_elm);
+   var fromCode = $Native$Char.fromCode;
+   var toCode = $Native$Char.toCode;
+   var toLocaleLower = $Native$Char.toLocaleLower;
+   var toLocaleUpper = $Native$Char.toLocaleUpper;
+   var toLower = $Native$Char.toLower;
+   var toUpper = $Native$Char.toUpper;
+   var isHexDigit = $Native$Char.isHexDigit;
+   var isOctDigit = $Native$Char.isOctDigit;
+   var isDigit = $Native$Char.isDigit;
+   var isLower = $Native$Char.isLower;
+   var isUpper = $Native$Char.isUpper;
+   _elm.Char.values = {_op: _op
+                      ,isUpper: isUpper
+                      ,isLower: isLower
+                      ,isDigit: isDigit
+                      ,isOctDigit: isOctDigit
+                      ,isHexDigit: isHexDigit
+                      ,toUpper: toUpper
+                      ,toLower: toLower
+                      ,toLocaleUpper: toLocaleUpper
+                      ,toLocaleLower: toLocaleLower
+                      ,toCode: toCode
+                      ,fromCode: fromCode};
+   return _elm.Char.values;
+};
+Elm.Color = Elm.Color || {};
+Elm.Color.make = function (_elm) {
+   "use strict";
+   _elm.Color = _elm.Color || {};
+   if (_elm.Color.values)
+   return _elm.Color.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Color",
+   $Basics = Elm.Basics.make(_elm);
+   var Radial = F5(function (a,
+   b,
+   c,
+   d,
+   e) {
+      return {ctor: "Radial"
+             ,_0: a
+             ,_1: b
+             ,_2: c
+             ,_3: d
+             ,_4: e};
+   });
+   var radial = Radial;
+   var Linear = F3(function (a,
+   b,
+   c) {
+      return {ctor: "Linear"
+             ,_0: a
+             ,_1: b
+             ,_2: c};
+   });
+   var linear = Linear;
+   var fmod = F2(function (f,n) {
+      return function () {
+         var integer = $Basics.floor(f);
+         return $Basics.toFloat(A2($Basics._op["%"],
+         integer,
+         n)) + f - $Basics.toFloat(integer);
+      }();
+   });
+   var rgbToHsl = F3(function (red,
+   green,
+   blue) {
+      return function () {
+         var b = $Basics.toFloat(blue) / 255;
+         var g = $Basics.toFloat(green) / 255;
+         var r = $Basics.toFloat(red) / 255;
+         var cMax = A2($Basics.max,
+         A2($Basics.max,r,g),
+         b);
+         var cMin = A2($Basics.min,
+         A2($Basics.min,r,g),
+         b);
+         var c = cMax - cMin;
+         var lightness = (cMax + cMin) / 2;
+         var saturation = _U.eq(lightness,
+         0) ? 0 : c / (1 - $Basics.abs(2 * lightness - 1));
+         var hue = $Basics.degrees(60) * (_U.eq(cMax,
+         r) ? A2(fmod,
+         (g - b) / c,
+         6) : _U.eq(cMax,
+         g) ? (b - r) / c + 2 : _U.eq(cMax,
+         b) ? (r - g) / c + 4 : _U.badIf($moduleName,
+         "between lines 141 and 143"));
+         return {ctor: "_Tuple3"
+                ,_0: hue
+                ,_1: saturation
+                ,_2: lightness};
+      }();
+   });
+   var hslToRgb = F3(function (hue,
+   saturation,
+   lightness) {
+      return function () {
+         var hue$ = hue / $Basics.degrees(60);
+         var chroma = (1 - $Basics.abs(2 * lightness - 1)) * saturation;
+         var x = chroma * (1 - $Basics.abs(A2(fmod,
+         hue$,
+         2) - 1));
+         var $ = _U.cmp(hue$,
+         0) < 0 ? {ctor: "_Tuple3"
+                  ,_0: 0
+                  ,_1: 0
+                  ,_2: 0} : _U.cmp(hue$,
+         1) < 0 ? {ctor: "_Tuple3"
+                  ,_0: chroma
+                  ,_1: x
+                  ,_2: 0} : _U.cmp(hue$,
+         2) < 0 ? {ctor: "_Tuple3"
+                  ,_0: x
+                  ,_1: chroma
+                  ,_2: 0} : _U.cmp(hue$,
+         3) < 0 ? {ctor: "_Tuple3"
+                  ,_0: 0
+                  ,_1: chroma
+                  ,_2: x} : _U.cmp(hue$,
+         4) < 0 ? {ctor: "_Tuple3"
+                  ,_0: 0
+                  ,_1: x
+                  ,_2: chroma} : _U.cmp(hue$,
+         5) < 0 ? {ctor: "_Tuple3"
+                  ,_0: x
+                  ,_1: 0
+                  ,_2: chroma} : _U.cmp(hue$,
+         6) < 0 ? {ctor: "_Tuple3"
+                  ,_0: chroma
+                  ,_1: 0
+                  ,_2: x} : {ctor: "_Tuple3"
+                            ,_0: 0
+                            ,_1: 0
+                            ,_2: 0},
+         r = $._0,
+         g = $._1,
+         b = $._2;
+         var m = lightness - chroma / 2;
+         return {ctor: "_Tuple3"
+                ,_0: r + m
+                ,_1: g + m
+                ,_2: b + m};
+      }();
+   });
+   var toRgb = function (color) {
+      return function () {
+         switch (color.ctor)
+         {case "HSLA":
+            return function () {
+                 var $ = A3(hslToRgb,
+                 color._0,
+                 color._1,
+                 color._2),
+                 r = $._0,
+                 g = $._1,
+                 b = $._2;
+                 return {_: {}
+                        ,alpha: color._3
+                        ,blue: $Basics.round(255 * b)
+                        ,green: $Basics.round(255 * g)
+                        ,red: $Basics.round(255 * r)};
+              }();
+            case "RGBA": return {_: {}
+                                ,alpha: color._3
+                                ,blue: color._2
+                                ,green: color._1
+                                ,red: color._0};}
+         _U.badCase($moduleName,
+         "between lines 115 and 123");
+      }();
+   };
+   var toHsl = function (color) {
+      return function () {
+         switch (color.ctor)
+         {case "HSLA": return {_: {}
+                              ,alpha: color._3
+                              ,hue: color._0
+                              ,lightness: color._2
+                              ,saturation: color._1};
+            case "RGBA":
+            return function () {
+                 var $ = A3(rgbToHsl,
+                 color._0,
+                 color._1,
+                 color._2),
+                 h = $._0,
+                 s = $._1,
+                 l = $._2;
+                 return {_: {}
+                        ,alpha: color._3
+                        ,hue: h
+                        ,lightness: l
+                        ,saturation: s};
+              }();}
+         _U.badCase($moduleName,
+         "between lines 105 and 112");
+      }();
+   };
+   var HSLA = F4(function (a,
+   b,
+   c,
+   d) {
+      return {ctor: "HSLA"
+             ,_0: a
+             ,_1: b
+             ,_2: c
+             ,_3: d};
+   });
+   var hsla = F4(function (hue,
+   saturation,
+   lightness,
+   alpha) {
+      return A4(HSLA,
+      hue - $Basics.turns($Basics.toFloat($Basics.floor(hue / (2 * $Basics.pi)))),
+      saturation,
+      lightness,
+      alpha);
+   });
+   var hsl = F3(function (hue,
+   saturation,
+   lightness) {
+      return A4(hsla,
+      hue,
+      saturation,
+      lightness,
+      1);
+   });
+   var complement = function (color) {
+      return function () {
+         switch (color.ctor)
+         {case "HSLA": return A4(hsla,
+              color._0 + $Basics.degrees(180),
+              color._1,
+              color._2,
+              color._3);
+            case "RGBA":
+            return function () {
+                 var $ = A3(rgbToHsl,
+                 color._0,
+                 color._1,
+                 color._2),
+                 h = $._0,
+                 s = $._1,
+                 l = $._2;
+                 return A4(hsla,
+                 h + $Basics.degrees(180),
+                 s,
+                 l,
+                 color._3);
+              }();}
+         _U.badCase($moduleName,
+         "between lines 96 and 102");
+      }();
+   };
+   var grayscale = function (p) {
+      return A4(HSLA,0,0,1 - p,1);
+   };
+   var greyscale = function (p) {
+      return A4(HSLA,0,0,1 - p,1);
+   };
+   var RGBA = F4(function (a,
+   b,
+   c,
+   d) {
+      return {ctor: "RGBA"
+             ,_0: a
+             ,_1: b
+             ,_2: c
+             ,_3: d};
+   });
+   var rgba = RGBA;
+   var rgb = F3(function (r,g,b) {
+      return A4(RGBA,r,g,b,1);
+   });
+   var lightRed = A4(RGBA,
+   239,
+   41,
+   41,
+   1);
+   var red = A4(RGBA,204,0,0,1);
+   var darkRed = A4(RGBA,
+   164,
+   0,
+   0,
+   1);
+   var lightOrange = A4(RGBA,
+   252,
+   175,
+   62,
+   1);
+   var orange = A4(RGBA,
+   245,
+   121,
+   0,
+   1);
+   var darkOrange = A4(RGBA,
+   206,
+   92,
+   0,
+   1);
+   var lightYellow = A4(RGBA,
+   255,
+   233,
+   79,
+   1);
+   var yellow = A4(RGBA,
+   237,
+   212,
+   0,
+   1);
+   var darkYellow = A4(RGBA,
+   196,
+   160,
+   0,
+   1);
+   var lightGreen = A4(RGBA,
+   138,
+   226,
+   52,
+   1);
+   var green = A4(RGBA,
+   115,
+   210,
+   22,
+   1);
+   var darkGreen = A4(RGBA,
+   78,
+   154,
+   6,
+   1);
+   var lightBlue = A4(RGBA,
+   114,
+   159,
+   207,
+   1);
+   var blue = A4(RGBA,
+   52,
+   101,
+   164,
+   1);
+   var darkBlue = A4(RGBA,
+   32,
+   74,
+   135,
+   1);
+   var lightPurple = A4(RGBA,
+   173,
+   127,
+   168,
+   1);
+   var purple = A4(RGBA,
+   117,
+   80,
+   123,
+   1);
+   var darkPurple = A4(RGBA,
+   92,
+   53,
+   102,
+   1);
+   var lightBrown = A4(RGBA,
+   233,
+   185,
+   110,
+   1);
+   var brown = A4(RGBA,
+   193,
+   125,
+   17,
+   1);
+   var darkBrown = A4(RGBA,
+   143,
+   89,
+   2,
+   1);
+   var black = A4(RGBA,0,0,0,1);
+   var white = A4(RGBA,
+   255,
+   255,
+   255,
+   1);
+   var lightGrey = A4(RGBA,
+   238,
+   238,
+   236,
+   1);
+   var grey = A4(RGBA,
+   211,
+   215,
+   207,
+   1);
+   var darkGrey = A4(RGBA,
+   186,
+   189,
+   182,
+   1);
+   var lightGray = A4(RGBA,
+   238,
+   238,
+   236,
+   1);
+   var gray = A4(RGBA,
+   211,
+   215,
+   207,
+   1);
+   var darkGray = A4(RGBA,
+   186,
+   189,
+   182,
+   1);
+   var lightCharcoal = A4(RGBA,
+   136,
+   138,
+   133,
+   1);
+   var charcoal = A4(RGBA,
+   85,
+   87,
+   83,
+   1);
+   var darkCharcoal = A4(RGBA,
+   46,
+   52,
+   54,
+   1);
+   _elm.Color.values = {_op: _op
+                       ,RGBA: RGBA
+                       ,HSLA: HSLA
+                       ,rgba: rgba
+                       ,rgb: rgb
+                       ,hsla: hsla
+                       ,hsl: hsl
+                       ,grayscale: grayscale
+                       ,greyscale: greyscale
+                       ,complement: complement
+                       ,toHsl: toHsl
+                       ,toRgb: toRgb
+                       ,fmod: fmod
+                       ,rgbToHsl: rgbToHsl
+                       ,hslToRgb: hslToRgb
+                       ,Linear: Linear
+                       ,Radial: Radial
+                       ,linear: linear
+                       ,radial: radial
+                       ,lightRed: lightRed
+                       ,red: red
+                       ,darkRed: darkRed
+                       ,lightOrange: lightOrange
+                       ,orange: orange
+                       ,darkOrange: darkOrange
+                       ,lightYellow: lightYellow
+                       ,yellow: yellow
+                       ,darkYellow: darkYellow
+                       ,lightGreen: lightGreen
+                       ,green: green
+                       ,darkGreen: darkGreen
+                       ,lightBlue: lightBlue
+                       ,blue: blue
+                       ,darkBlue: darkBlue
+                       ,lightPurple: lightPurple
+                       ,purple: purple
+                       ,darkPurple: darkPurple
+                       ,lightBrown: lightBrown
+                       ,brown: brown
+                       ,darkBrown: darkBrown
+                       ,black: black
+                       ,white: white
+                       ,lightGrey: lightGrey
+                       ,grey: grey
+                       ,darkGrey: darkGrey
+                       ,lightGray: lightGray
+                       ,gray: gray
+                       ,darkGray: darkGray
+                       ,lightCharcoal: lightCharcoal
+                       ,charcoal: charcoal
+                       ,darkCharcoal: darkCharcoal};
+   return _elm.Color.values;
+};
+Elm.Debug = Elm.Debug || {};
+Elm.Debug.make = function (_elm) {
+   "use strict";
+   _elm.Debug = _elm.Debug || {};
+   if (_elm.Debug.values)
+   return _elm.Debug.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Debug",
+   $Graphics$Collage = Elm.Graphics.Collage.make(_elm),
+   $Native$Debug = Elm.Native.Debug.make(_elm);
+   var trace = $Native$Debug.tracePath;
+   var watchSummary = $Native$Debug.watchSummary;
+   var watch = $Native$Debug.watch;
+   var crash = $Native$Debug.crash;
+   var log = $Native$Debug.log;
+   _elm.Debug.values = {_op: _op
+                       ,log: log
+                       ,crash: crash
+                       ,watch: watch
+                       ,watchSummary: watchSummary
+                       ,trace: trace};
+   return _elm.Debug.values;
+};
+Elm.DebuggerInterface = Elm.DebuggerInterface || {};
+Elm.DebuggerInterface.make = function (_elm) {
+   "use strict";
+   _elm.DebuggerInterface = _elm.DebuggerInterface || {};
+   if (_elm.DebuggerInterface.values)
+   return _elm.DebuggerInterface.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "DebuggerInterface",
+   $Basics = Elm.Basics.make(_elm),
+   $Color = Elm.Color.make(_elm),
+   $Graphics$Collage = Elm.Graphics.Collage.make(_elm),
+   $Graphics$Element = Elm.Graphics.Element.make(_elm),
+   $Graphics$Input = Elm.Graphics.Input.make(_elm),
+   $List = Elm.List.make(_elm),
+   $Markdown = Elm.Markdown.make(_elm),
+   $Maybe = Elm.Maybe.make(_elm),
+   $Signal = Elm.Signal.make(_elm),
+   $Slider = Elm.Slider.make(_elm),
+   $Text = Elm.Text.make(_elm),
+   $Window = Elm.Window.make(_elm);
+   var noWatches = $Markdown.toElement("\n\n### <span style=\"font-family: Gotham, Futura, \'Lucida Grande\', sans-serif; font-size: 12pt; color: rgb(170,170,170)\"> You don\'t have any watches! </span>\n\n<span style=\"color: rgb(170,170,170)\">\n<span style=\"font-family: Gotham, Futura, \'Lucida Grande\', sans-serif; font-size: 10pt; color: rgb(170,170,170)\">\nUse [<span style=\"text-decoration:underline; color: rgb(170,170,170)\">Debug.watch</span>](http://package.elm-lang.org/packages/elm-lang/core/latest/Debug#watch)\nto show any value. <br>\n`watch : String -> a -> a`</span>\n\n<span style=\"font-family: Gotham, Futura, \'Lucida Grande\', sans-serif; font-size: 10pt; color: rgb(170,170,170)\">\nUse [<span style=\"text-decoration:underline; color: rgb(170,170,170)\">Debug.watchSummary</span>](http://package.elm-lang.org/packages/elm-lang/core/latest/Debug#watchSummary) to show a <br>\nsummary or subvalue of any value. </span><br>\n\n");
+   var roundedSquare = F3(function (side,
+   radius,
+   toForm) {
+      return function () {
+         var formedCircle = toForm($Graphics$Collage.circle(radius));
+         var shortSide = side - 2 * radius;
+         var xRect = toForm(A2($Graphics$Collage.rect,
+         side,
+         shortSide));
+         var yRect = toForm(A2($Graphics$Collage.rect,
+         shortSide,
+         side));
+         var circleOffset = shortSide / 2;
+         var tl = $Graphics$Collage.move({ctor: "_Tuple2"
+                                         ,_0: 0 - circleOffset
+                                         ,_1: circleOffset})(formedCircle);
+         var tr = $Graphics$Collage.move({ctor: "_Tuple2"
+                                         ,_0: circleOffset
+                                         ,_1: circleOffset})(formedCircle);
+         var bl = $Graphics$Collage.move({ctor: "_Tuple2"
+                                         ,_0: 0 - circleOffset
+                                         ,_1: 0 - circleOffset})(formedCircle);
+         var br = $Graphics$Collage.move({ctor: "_Tuple2"
+                                         ,_0: circleOffset
+                                         ,_1: 0 - circleOffset})(formedCircle);
+         return $Graphics$Collage.group(_L.fromArray([xRect
+                                                     ,yRect
+                                                     ,tl
+                                                     ,tr
+                                                     ,bl
+                                                     ,br]));
+      }();
+   });
+   var startState = {_: {}
+                    ,paused: false
+                    ,scrubPosition: 0
+                    ,totalEvents: 0};
+   var step = F2(function (update,
+   state) {
+      return function () {
+         switch (update.ctor)
+         {case "Pause":
+            return _U.replace([["paused"
+                               ,update._0]
+                              ,["totalEvents"
+                               ,update._0 ? state.totalEvents : state.scrubPosition]],
+              state);
+            case "Restart":
+            return startState;
+            case "ScrubPosition":
+            return _U.replace([["scrubPosition"
+                               ,update._0]
+                              ,["paused",true]],
+              state);
+            case "TotalEvents":
+            return _U.replace([["totalEvents"
+                               ,update._0]
+                              ,["scrubPosition",update._0]],
+              state);}
+         _U.badCase($moduleName,
+         "between lines 289 and 310");
+      }();
+   });
+   var showSwap = _P.portIn("showSwap",
+   function (v) {
+      return typeof v === "boolean" ? v : _U.badPort("a boolean (true or false)",
+      v);
+   });
+   var watches = _P.portIn("watches",
+   _P.incomingSignal(function (v) {
+      return typeof v === "object" && v instanceof Array ? Elm.Native.List.make(_elm).fromArray(v.map(function (v) {
+         return typeof v === "object" && v instanceof Array ? {ctor: "_Tuple2"
+                                                              ,_0: typeof v[0] === "string" || typeof v[0] === "object" && v[0] instanceof String ? v[0] : _U.badPort("a string",
+                                                              v[0])
+                                                              ,_1: typeof v[1] === "string" || typeof v[1] === "object" && v[1] instanceof String ? v[1] : _U.badPort("a string",
+                                                              v[1])} : _U.badPort("an array",
+         v);
+      })) : _U.badPort("an array",v);
+   }));
+   var eventCounter = _P.portIn("eventCounter",
+   _P.incomingSignal(function (v) {
+      return typeof v === "number" ? v : _U.badPort("a number",
+      v);
+   }));
+   var scrupChannel = $Signal.channel(0);
+   var restartChannel = $Signal.channel({ctor: "_Tuple0"});
+   var permitSwapChannel = $Signal.channel(true);
+   var pausedInput = $Signal.channel(false);
+   var permitSwap = _P.portOut("permitSwap",
+   _P.outgoingSignal(function (v) {
+      return v;
+   }),
+   $Signal.subscribe(permitSwapChannel));
+   var restart = _P.portOut("restart",
+   _P.outgoingSignal(function (v) {
+      return v;
+   }),
+   A2($Signal.map,
+   $Basics.always(0),
+   $Signal.subscribe(restartChannel)));
+   var scrubSlider = F2(function (_v4,
+   state) {
+      return function () {
+         switch (_v4.ctor)
+         {case "_Tuple2":
+            return function () {
+                 var sliderLength = _v4._0;
+                 var sliderStyle = _U.replace([["length"
+                                               ,sliderLength]
+                                              ,["max"
+                                               ,$Basics.toFloat(state.totalEvents)]
+                                              ,["value"
+                                               ,$Basics.toFloat(state.scrubPosition)]],
+                 $Slider.defaultSlider);
+                 return A3($Graphics$Element.container,
+                 sliderLength,
+                 20,
+                 $Graphics$Element.middle)(A2($Slider.slider,
+                 function (n) {
+                    return A2($Signal.send,
+                    scrupChannel,
+                    $Basics.round(n));
+                 },
+                 sliderStyle));
+              }();}
+         _U.badCase($moduleName,
+         "between lines 127 and 136");
+      }();
+   });
+   var myButton = F2(function (message,
+   name) {
+      return function () {
+         var img = function (state) {
+            return A3($Graphics$Element.image,
+            40,
+            40,
+            A2($Basics._op["++"],
+            "/_reactor/debugger/",
+            A2($Basics._op["++"],
+            name,
+            A2($Basics._op["++"],
+            "-button-",
+            A2($Basics._op["++"],
+            state,
+            ".png")))));
+         };
+         return A4($Graphics$Input.customButton,
+         message,
+         img("up"),
+         img("hover"),
+         img("down"));
+      }();
+   });
+   var playButton = A2(myButton,
+   A2($Signal.send,
+   pausedInput,
+   false),
+   "play");
+   var pauseButton = A2(myButton,
+   A2($Signal.send,
+   pausedInput,
+   true),
+   "pause");
+   var restartButton = A2(myButton,
+   A2($Signal.send,
+   restartChannel,
+   {ctor: "_Tuple0"}),
+   "restart");
+   var darkGrey = A3($Color.rgb,
+   74,
+   74,
+   74);
+   var lightGrey = A3($Color.rgb,
+   228,
+   228,
+   228);
+   var dataStyle = F3(function (typefaces,
+   height,
+   string) {
+      return function () {
+         var myStyle = _U.replace([["typeface"
+                                   ,typefaces]
+                                  ,["color",lightGrey]
+                                  ,["height"
+                                   ,$Maybe.Just(height)]],
+         $Text.defaultStyle);
+         return A2($Text.style,
+         myStyle,
+         $Text.fromString(string));
+      }();
+   });
+   var textStyle = A2(dataStyle,
+   _L.fromArray(["Gotham"
+                ,"Futura"
+                ,"Lucida Grande"
+                ,"sans-serif"]),
+   12);
+   var watchStyle = A2(dataStyle,
+   _L.fromArray(["Gotham"
+                ,"Futura"
+                ,"Lucida Grande"
+                ,"sans-serif"]),
+   14);
+   var codeStyle = A2(dataStyle,
+   _L.fromArray(["Menlo for Powerline"
+                ,"monospace"]),
+   12);
+   var blue = A3($Color.rgb,
+   28,
+   129,
+   218);
+   var swapButton = function (permitSwap) {
+      return function () {
+         var info = $Text.leftAligned(textStyle("swap"));
+         var radius = 4;
+         var hsWidth = 25;
+         var bgButton = A3(roundedSquare,
+         hsWidth,
+         radius,
+         $Graphics$Collage.filled(lightGrey));
+         var trueButton = _L.fromArray([bgButton
+                                       ,A3(roundedSquare,
+                                       22,
+                                       radius,
+                                       $Graphics$Collage.filled(blue))]);
+         var falseButtonClick = trueButton;
+         var trueButtonHover = _L.fromArray([bgButton
+                                            ,A3(roundedSquare,
+                                            22,
+                                            radius,
+                                            $Graphics$Collage.filled(blue))
+                                            ,$Graphics$Collage.alpha(0.1)(A3(roundedSquare,
+                                            22,
+                                            radius,
+                                            $Graphics$Collage.filled(darkGrey)))]);
+         var falseButton = _L.fromArray([bgButton
+                                        ,A3(roundedSquare,
+                                        22,
+                                        radius,
+                                        $Graphics$Collage.filled(darkGrey))]);
+         var trueButtonClick = falseButton;
+         var falseButtonHover = _L.fromArray([bgButton
+                                             ,A3(roundedSquare,
+                                             22,
+                                             radius,
+                                             $Graphics$Collage.filled(darkGrey))
+                                             ,$Graphics$Collage.alpha(0.1)(A3(roundedSquare,
+                                             22,
+                                             radius,
+                                             $Graphics$Collage.filled(blue)))]);
+         var button = permitSwap ? A4($Graphics$Input.customButton,
+         A2($Signal.send,
+         permitSwapChannel,
+         false),
+         A3($Graphics$Collage.collage,
+         hsWidth,
+         hsWidth,
+         trueButton),
+         A3($Graphics$Collage.collage,
+         hsWidth,
+         hsWidth,
+         trueButtonHover),
+         A3($Graphics$Collage.collage,
+         hsWidth,
+         hsWidth,
+         trueButtonClick)) : A4($Graphics$Input.customButton,
+         A2($Signal.send,
+         permitSwapChannel,
+         true),
+         A3($Graphics$Collage.collage,
+         hsWidth,
+         hsWidth,
+         falseButton),
+         A3($Graphics$Collage.collage,
+         hsWidth,
+         hsWidth,
+         falseButtonHover),
+         A3($Graphics$Collage.collage,
+         hsWidth,
+         hsWidth,
+         falseButtonClick));
+         return A2($Graphics$Element.flow,
+         $Graphics$Element.right,
+         _L.fromArray([info
+                      ,A2($Graphics$Element.spacer,
+                      10,
+                      1)
+                      ,button]));
+      }();
+   };
+   var panelWidth = 275;
+   var textHeight = 20;
+   var sliderMinMaxText = F2(function (w,
+   state) {
+      return function () {
+         var sliderTotalEvents = A3($Graphics$Element.container,
+         w,
+         textHeight,
+         $Graphics$Element.topRight)($Text.rightAligned(textStyle($Basics.toString(state.totalEvents))));
+         var sliderStartText = A3($Graphics$Element.container,
+         w,
+         textHeight,
+         $Graphics$Element.topLeft)($Text.leftAligned(textStyle("0")));
+         return A2($Graphics$Element.flow,
+         $Graphics$Element.outward,
+         _L.fromArray([sliderStartText
+                      ,sliderTotalEvents]));
+      }();
+   });
+   var sideMargin = 2 * 20;
+   var sliderEventText = F2(function (w,
+   state) {
+      return function () {
+         var text$ = $Text.centered(textStyle($Basics.toString(state.scrubPosition)));
+         var yPos = $Graphics$Element.absolute($Basics.round(textHeight / 2));
+         var totalEvents = $Basics.toFloat(state.totalEvents);
+         var scrubPosition = $Basics.toFloat(state.scrubPosition);
+         var textWidthOffset = 14;
+         var midWidth = $Basics.toFloat(w) - sideMargin - textWidthOffset;
+         var leftDistance = _U.eq(totalEvents,
+         0) ? sideMargin / 2 + textWidthOffset / 2 : scrubPosition / totalEvents * midWidth + sideMargin / 2 + textWidthOffset / 2;
+         var xPos = $Graphics$Element.absolute($Basics.round(leftDistance));
+         var textPosition = A2($Graphics$Element.middleAt,
+         xPos,
+         yPos);
+         return A4($Graphics$Element.container,
+         w,
+         textHeight,
+         textPosition,
+         text$);
+      }();
+   });
+   var buttonWidth = 40;
+   var buttonHeight = 40;
+   var view = F4(function (_v8,
+   watches,
+   permitSwap,
+   state) {
+      return function () {
+         switch (_v8.ctor)
+         {case "_Tuple2":
+            return function () {
+                 var showWatch = function (_v12) {
+                    return function () {
+                       switch (_v12.ctor)
+                       {case "_Tuple2":
+                          return A2($Graphics$Element.flow,
+                            $Graphics$Element.down,
+                            _L.fromArray([$Graphics$Element.width(_v8._0)($Text.leftAligned($Text.bold(watchStyle(_v12._0))))
+                                         ,$Graphics$Element.width(_v8._0)($Text.leftAligned(codeStyle(_v12._1)))
+                                         ,A2($Graphics$Element.spacer,
+                                         1,
+                                         12)]));}
+                       _U.badCase($moduleName,
+                       "between lines 212 and 216");
+                    }();
+                 };
+                 var watchView = A2($Graphics$Element.flow,
+                 $Graphics$Element.right,
+                 _L.fromArray([A2($Graphics$Element.spacer,
+                              20,
+                              1)
+                              ,function () {
+                                 switch (watches.ctor)
+                                 {case "[]": return noWatches;}
+                                 return $Graphics$Element.flow($Graphics$Element.down)(A2($List.map,
+                                 showWatch,
+                                 watches));
+                              }()]));
+                 var bar = A2($Graphics$Element.flow,
+                 $Graphics$Element.down,
+                 _L.fromArray([$Graphics$Element.opacity(0.3)($Graphics$Element.color(lightGrey)(A2($Graphics$Element.spacer,
+                              _v8._0,
+                              1)))
+                              ,A2($Graphics$Element.spacer,
+                              _v8._0,
+                              12)]));
+                 var fittedSwapButton = showSwap ? A3($Graphics$Element.container,
+                 _v8._0 - 2 * buttonWidth - sideMargin,
+                 buttonHeight,
+                 $Graphics$Element.middle)(swapButton(permitSwap)) : A2($Graphics$Element.spacer,
+                 2 * buttonWidth,
+                 1);
+                 var buttons = A2($Graphics$Element.flow,
+                 $Graphics$Element.right,
+                 _L.fromArray([restartButton
+                              ,fittedSwapButton
+                              ,state.paused ? playButton : pauseButton]));
+                 var buttonContainer = A4($Graphics$Element.container,
+                 _v8._0,
+                 buttonHeight,
+                 $Graphics$Element.midTop,
+                 buttons);
+                 var buttonSliderSpaceHeight = 10;
+                 var topSpacerHeight = 15;
+                 var midWidth = _v8._0 - sideMargin;
+                 var centeredSliderContainer = A3($Graphics$Element.container,
+                 _v8._0,
+                 24 + textHeight,
+                 $Graphics$Element.midTop)(A2($Graphics$Element.flow,
+                 $Graphics$Element.down,
+                 _L.fromArray([A2(scrubSlider,
+                              {ctor: "_Tuple2"
+                              ,_0: midWidth
+                              ,_1: _v8._1},
+                              state)
+                              ,A2(sliderMinMaxText,
+                              midWidth,
+                              state)])));
+                 var slider = A3($Graphics$Element.container,
+                 _v8._0,
+                 24 + 2 * textHeight,
+                 $Graphics$Element.midTop)(A2($Graphics$Element.flow,
+                 $Graphics$Element.down,
+                 _L.fromArray([A2(sliderEventText,
+                              _v8._0,
+                              state)
+                              ,centeredSliderContainer])));
+                 var controls = A2($Graphics$Element.flow,
+                 $Graphics$Element.down,
+                 _L.fromArray([A2($Graphics$Element.spacer,
+                              midWidth,
+                              topSpacerHeight)
+                              ,buttonContainer
+                              ,A2($Graphics$Element.spacer,
+                              midWidth,
+                              buttonSliderSpaceHeight)
+                              ,slider
+                              ,A2($Graphics$Element.spacer,
+                              midWidth,
+                              10)]));
+                 return A2($Graphics$Element.flow,
+                 $Graphics$Element.down,
+                 _L.fromArray([controls
+                              ,bar
+                              ,watchView]));
+              }();}
+         _U.badCase($moduleName,
+         "between lines 177 and 227");
+      }();
+   });
+   var State = F3(function (a,
+   b,
+   c) {
+      return {_: {}
+             ,paused: a
+             ,scrubPosition: c
+             ,totalEvents: b};
+   });
+   var ScrubPosition = function (a) {
+      return {ctor: "ScrubPosition"
+             ,_0: a};
+   };
+   var TotalEvents = function (a) {
+      return {ctor: "TotalEvents"
+             ,_0: a};
+   };
+   var Pause = function (a) {
+      return {ctor: "Pause",_0: a};
+   };
+   var Restart = {ctor: "Restart"};
+   var aggregateUpdates = $Signal.mergeMany(_L.fromArray([A2($Signal._op["<~"],
+                                                         $Basics.always(Restart),
+                                                         $Signal.subscribe(restartChannel))
+                                                         ,A2($Signal._op["<~"],
+                                                         Pause,
+                                                         $Signal.subscribe(pausedInput))
+                                                         ,A2($Signal._op["<~"],
+                                                         TotalEvents,
+                                                         eventCounter)
+                                                         ,A2($Signal._op["<~"],
+                                                         ScrubPosition,
+                                                         $Signal.subscribe(scrupChannel))]));
+   var scene = A3($Signal.foldp,
+   step,
+   startState,
+   aggregateUpdates);
+   var main = A2($Signal._op["~"],
+   A2($Signal._op["~"],
+   A2($Signal._op["~"],
+   A2($Signal._op["<~"],
+   view,
+   A2($Signal._op["<~"],
+   function (_v17) {
+      return function () {
+         switch (_v17.ctor)
+         {case "_Tuple2":
+            return {ctor: "_Tuple2"
+                   ,_0: panelWidth
+                   ,_1: _v17._1};}
+         _U.badCase($moduleName,
+         "on line 235, column 30 to 43");
+      }();
+   },
+   $Window.dimensions)),
+   watches),
+   $Signal.subscribe(permitSwapChannel)),
+   scene);
+   var scrubTo = _P.portOut("scrubTo",
+   _P.outgoingSignal(function (v) {
+      return v;
+   }),
+   A2($Signal._op["<~"],
+   function (_) {
+      return _.scrubPosition;
+   },
+   scene));
+   var pause = _P.portOut("pause",
+   _P.outgoingSignal(function (v) {
+      return v;
+   }),
+   A2($Signal._op["<~"],
+   function (_) {
+      return _.paused;
+   },
+   scene));
+   _elm.DebuggerInterface.values = {_op: _op
+                                   ,Restart: Restart
+                                   ,Pause: Pause
+                                   ,TotalEvents: TotalEvents
+                                   ,ScrubPosition: ScrubPosition
+                                   ,State: State
+                                   ,buttonHeight: buttonHeight
+                                   ,buttonWidth: buttonWidth
+                                   ,sideMargin: sideMargin
+                                   ,textHeight: textHeight
+                                   ,panelWidth: panelWidth
+                                   ,blue: blue
+                                   ,lightGrey: lightGrey
+                                   ,darkGrey: darkGrey
+                                   ,dataStyle: dataStyle
+                                   ,textStyle: textStyle
+                                   ,watchStyle: watchStyle
+                                   ,codeStyle: codeStyle
+                                   ,myButton: myButton
+                                   ,playButton: playButton
+                                   ,pauseButton: pauseButton
+                                   ,restartButton: restartButton
+                                   ,swapButton: swapButton
+                                   ,scrubSlider: scrubSlider
+                                   ,sliderEventText: sliderEventText
+                                   ,sliderMinMaxText: sliderMinMaxText
+                                   ,view: view
+                                   ,main: main
+                                   ,pausedInput: pausedInput
+                                   ,permitSwapChannel: permitSwapChannel
+                                   ,restartChannel: restartChannel
+                                   ,scrupChannel: scrupChannel
+                                   ,scene: scene
+                                   ,startState: startState
+                                   ,step: step
+                                   ,aggregateUpdates: aggregateUpdates
+                                   ,roundedSquare: roundedSquare
+                                   ,noWatches: noWatches};
+   return _elm.DebuggerInterface.values;
+};
+Elm.Dict = Elm.Dict || {};
+Elm.Dict.make = function (_elm) {
+   "use strict";
+   _elm.Dict = _elm.Dict || {};
+   if (_elm.Dict.values)
+   return _elm.Dict.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Dict",
+   $Basics = Elm.Basics.make(_elm),
+   $List = Elm.List.make(_elm),
+   $Maybe = Elm.Maybe.make(_elm),
+   $Native$Debug = Elm.Native.Debug.make(_elm),
+   $String = Elm.String.make(_elm);
+   var foldr = F3(function (f,
+   acc,
+   t) {
+      return function () {
+         switch (t.ctor)
+         {case "RBEmpty":
+            switch (t._0.ctor)
+              {case "LBlack": return acc;}
+              break;
+            case "RBNode": return A3(foldr,
+              f,
+              A3(f,
+              t._1,
+              t._2,
+              A3(foldr,f,acc,t._4)),
+              t._3);}
+         _U.badCase($moduleName,
+         "between lines 410 and 418");
+      }();
+   });
+   var keys = function (dict) {
+      return A3(foldr,
+      F3(function (key,
+      value,
+      keyList) {
+         return A2($List._op["::"],
+         key,
+         keyList);
+      }),
+      _L.fromArray([]),
+      dict);
+   };
+   var values = function (dict) {
+      return A3(foldr,
+      F3(function (key,
+      value,
+      valueList) {
+         return A2($List._op["::"],
+         value,
+         valueList);
+      }),
+      _L.fromArray([]),
+      dict);
+   };
+   var toList = function (dict) {
+      return A3(foldr,
+      F3(function (key,value,list) {
+         return A2($List._op["::"],
+         {ctor: "_Tuple2"
+         ,_0: key
+         ,_1: value},
+         list);
+      }),
+      _L.fromArray([]),
+      dict);
+   };
+   var foldl = F3(function (f,
+   acc,
+   dict) {
+      return function () {
+         switch (dict.ctor)
+         {case "RBEmpty":
+            switch (dict._0.ctor)
+              {case "LBlack": return acc;}
+              break;
+            case "RBNode": return A3(foldl,
+              f,
+              A3(f,
+              dict._1,
+              dict._2,
+              A3(foldl,f,acc,dict._3)),
+              dict._4);}
+         _U.badCase($moduleName,
+         "between lines 399 and 407");
+      }();
+   });
+   var isBBlack = function (dict) {
+      return function () {
+         switch (dict.ctor)
+         {case "RBEmpty":
+            switch (dict._0.ctor)
+              {case "LBBlack": return true;}
+              break;
+            case "RBNode":
+            switch (dict._0.ctor)
+              {case "BBlack": return true;}
+              break;}
+         return false;
+      }();
+   };
+   var showFlag = function (f) {
+      return function () {
+         switch (f.ctor)
+         {case "Insert": return "Insert";
+            case "Remove": return "Remove";
+            case "Same": return "Same";}
+         _U.badCase($moduleName,
+         "between lines 175 and 181");
+      }();
+   };
+   var Same = {ctor: "Same"};
+   var Remove = {ctor: "Remove"};
+   var Insert = {ctor: "Insert"};
+   var get = F2(function (targetKey,
+   dict) {
+      return function () {
+         switch (dict.ctor)
+         {case "RBEmpty":
+            switch (dict._0.ctor)
+              {case "LBlack":
+                 return $Maybe.Nothing;}
+              break;
+            case "RBNode":
+            return function () {
+                 var _v29 = A2($Basics.compare,
+                 targetKey,
+                 dict._1);
+                 switch (_v29.ctor)
+                 {case "EQ":
+                    return $Maybe.Just(dict._2);
+                    case "GT": return A2(get,
+                      targetKey,
+                      dict._4);
+                    case "LT": return A2(get,
+                      targetKey,
+                      dict._3);}
+                 _U.badCase($moduleName,
+                 "between lines 131 and 137");
+              }();}
+         _U.badCase($moduleName,
+         "between lines 126 and 137");
+      }();
+   });
+   var member = F2(function (key,
+   dict) {
+      return function () {
+         var _v30 = A2(get,key,dict);
+         switch (_v30.ctor)
+         {case "Just": return true;
+            case "Nothing": return false;}
+         _U.badCase($moduleName,
+         "between lines 140 and 142");
+      }();
+   });
+   var max = function (dict) {
+      return function () {
+         switch (dict.ctor)
+         {case "RBEmpty":
+            return $Native$Debug.crash("(max Empty) is not defined");
+            case "RBNode":
+            switch (dict._4.ctor)
+              {case "RBEmpty":
+                 return {ctor: "_Tuple2"
+                        ,_0: dict._1
+                        ,_1: dict._2};}
+              return max(dict._4);}
+         _U.badCase($moduleName,
+         "between lines 100 and 123");
+      }();
+   };
+   var min = function (dict) {
+      return function () {
+         switch (dict.ctor)
+         {case "RBEmpty":
+            switch (dict._0.ctor)
+              {case "LBlack":
+                 return $Native$Debug.crash("(min Empty) is not defined");}
+              break;
+            case "RBNode":
+            switch (dict._3.ctor)
+              {case "RBEmpty":
+                 switch (dict._3._0.ctor)
+                   {case "LBlack":
+                      return {ctor: "_Tuple2"
+                             ,_0: dict._1
+                             ,_1: dict._2};}
+                   break;}
+              return min(dict._3);}
+         _U.badCase($moduleName,
+         "between lines 87 and 95");
+      }();
+   };
+   var RBEmpty = function (a) {
+      return {ctor: "RBEmpty"
+             ,_0: a};
+   };
+   var RBNode = F5(function (a,
+   b,
+   c,
+   d,
+   e) {
+      return {ctor: "RBNode"
+             ,_0: a
+             ,_1: b
+             ,_2: c
+             ,_3: d
+             ,_4: e};
+   });
+   var showLColor = function (color) {
+      return function () {
+         switch (color.ctor)
+         {case "LBBlack":
+            return "LBBlack";
+            case "LBlack": return "LBlack";}
+         _U.badCase($moduleName,
+         "between lines 70 and 72");
+      }();
+   };
+   var LBBlack = {ctor: "LBBlack"};
+   var LBlack = {ctor: "LBlack"};
+   var empty = RBEmpty(LBlack);
+   var map = F2(function (f,dict) {
+      return function () {
+         switch (dict.ctor)
+         {case "RBEmpty":
+            switch (dict._0.ctor)
+              {case "LBlack":
+                 return RBEmpty(LBlack);}
+              break;
+            case "RBNode": return A5(RBNode,
+              dict._0,
+              dict._1,
+              A2(f,dict._1,dict._2),
+              A2(map,f,dict._3),
+              A2(map,f,dict._4));}
+         _U.badCase($moduleName,
+         "between lines 387 and 396");
+      }();
+   });
+   var showNColor = function (c) {
+      return function () {
+         switch (c.ctor)
+         {case "BBlack": return "BBlack";
+            case "Black": return "Black";
+            case "NBlack": return "NBlack";
+            case "Red": return "Red";}
+         _U.badCase($moduleName,
+         "between lines 56 and 60");
+      }();
+   };
+   var reportRemBug = F4(function (msg,
+   c,
+   lgot,
+   rgot) {
+      return $Native$Debug.crash($String.concat(_L.fromArray(["Internal red-black tree invariant violated, expected "
+                                                             ,msg
+                                                             ," and got "
+                                                             ,showNColor(c)
+                                                             ,"/"
+                                                             ,lgot
+                                                             ,"/"
+                                                             ,rgot
+                                                             ,"\nPlease report this bug to <https://github.com/elm-lang/Elm/issues>"])));
+   });
+   var NBlack = {ctor: "NBlack"};
+   var BBlack = {ctor: "BBlack"};
+   var Black = {ctor: "Black"};
+   var ensureBlackRoot = function (dict) {
+      return function () {
+         switch (dict.ctor)
+         {case "RBEmpty":
+            switch (dict._0.ctor)
+              {case "LBlack": return dict;}
+              break;
+            case "RBNode":
+            switch (dict._0.ctor)
+              {case "Black": return dict;
+                 case "Red": return A5(RBNode,
+                   Black,
+                   dict._1,
+                   dict._2,
+                   dict._3,
+                   dict._4);}
+              break;}
+         _U.badCase($moduleName,
+         "between lines 147 and 159");
+      }();
+   };
+   var blackish = function (t) {
+      return function () {
+         switch (t.ctor)
+         {case "RBEmpty": return true;
+            case "RBNode":
+            return _U.eq(t._0,
+              Black) || _U.eq(t._0,BBlack);}
+         _U.badCase($moduleName,
+         "between lines 332 and 334");
+      }();
+   };
+   var blacken = function (t) {
+      return function () {
+         switch (t.ctor)
+         {case "RBEmpty":
+            return RBEmpty(LBlack);
+            case "RBNode": return A5(RBNode,
+              Black,
+              t._1,
+              t._2,
+              t._3,
+              t._4);}
+         _U.badCase($moduleName,
+         "between lines 371 and 373");
+      }();
+   };
+   var Red = {ctor: "Red"};
+   var moreBlack = function (color) {
+      return function () {
+         switch (color.ctor)
+         {case "BBlack":
+            return $Native$Debug.crash("Can\'t make a double black node more black!");
+            case "Black": return BBlack;
+            case "NBlack": return Red;
+            case "Red": return Black;}
+         _U.badCase($moduleName,
+         "between lines 237 and 241");
+      }();
+   };
+   var lessBlack = function (color) {
+      return function () {
+         switch (color.ctor)
+         {case "BBlack": return Black;
+            case "Black": return Red;
+            case "NBlack":
+            return $Native$Debug.crash("Can\'t make a negative black node less black!");
+            case "Red": return NBlack;}
+         _U.badCase($moduleName,
+         "between lines 246 and 250");
+      }();
+   };
+   var lessBlackTree = function (dict) {
+      return function () {
+         switch (dict.ctor)
+         {case "RBEmpty":
+            switch (dict._0.ctor)
+              {case "LBBlack":
+                 return RBEmpty(LBlack);}
+              break;
+            case "RBNode": return A5(RBNode,
+              lessBlack(dict._0),
+              dict._1,
+              dict._2,
+              dict._3,
+              dict._4);}
+         _U.badCase($moduleName,
+         "between lines 255 and 257");
+      }();
+   };
+   var redden = function (t) {
+      return function () {
+         switch (t.ctor)
+         {case "RBEmpty":
+            return $Native$Debug.crash("can\'t make a Leaf red");
+            case "RBNode": return A5(RBNode,
+              Red,
+              t._1,
+              t._2,
+              t._3,
+              t._4);}
+         _U.badCase($moduleName,
+         "between lines 379 and 384");
+      }();
+   };
+   var balance_node = function (t) {
+      return function () {
+         var assemble = function (col) {
+            return function (xk) {
+               return function (xv) {
+                  return function (yk) {
+                     return function (yv) {
+                        return function (zk) {
+                           return function (zv) {
+                              return function (a) {
+                                 return function (b) {
+                                    return function (c) {
+                                       return function (d) {
+                                          return A5(RBNode,
+                                          lessBlack(col),
+                                          yk,
+                                          yv,
+                                          A5(RBNode,Black,xk,xv,a,b),
+                                          A5(RBNode,Black,zk,zv,c,d));
+                                       };
+                                    };
+                                 };
+                              };
+                           };
+                        };
+                     };
+                  };
+               };
+            };
+         };
+         return blackish(t) ? function () {
+            switch (t.ctor)
+            {case "RBNode":
+               switch (t._3.ctor)
+                 {case "RBNode":
+                    switch (t._3._0.ctor)
+                      {case "Red":
+                         switch (t._3._3.ctor)
+                           {case "RBNode":
+                              switch (t._3._3._0.ctor)
+                                {case "Red":
+                                   return assemble(t._0)(t._3._3._1)(t._3._3._2)(t._3._1)(t._3._2)(t._1)(t._2)(t._3._3._3)(t._3._3._4)(t._3._4)(t._4);}
+                                break;}
+                           switch (t._3._4.ctor)
+                           {case "RBNode":
+                              switch (t._3._4._0.ctor)
+                                {case "Red":
+                                   return assemble(t._0)(t._3._1)(t._3._2)(t._3._4._1)(t._3._4._2)(t._1)(t._2)(t._3._3)(t._3._4._3)(t._3._4._4)(t._4);}
+                                break;}
+                           break;}
+                      break;}
+                 switch (t._4.ctor)
+                 {case "RBNode":
+                    switch (t._4._0.ctor)
+                      {case "Red":
+                         switch (t._4._3.ctor)
+                           {case "RBNode":
+                              switch (t._4._3._0.ctor)
+                                {case "Red":
+                                   return assemble(t._0)(t._1)(t._2)(t._4._3._1)(t._4._3._2)(t._4._1)(t._4._2)(t._3)(t._4._3._3)(t._4._3._4)(t._4._4);}
+                                break;}
+                           switch (t._4._4.ctor)
+                           {case "RBNode":
+                              switch (t._4._4._0.ctor)
+                                {case "Red":
+                                   return assemble(t._0)(t._1)(t._2)(t._4._1)(t._4._2)(t._4._4._1)(t._4._4._2)(t._3)(t._4._3)(t._4._4._3)(t._4._4._4);}
+                                break;}
+                           break;}
+                      break;}
+                 switch (t._0.ctor)
+                 {case "BBlack":
+                    switch (t._4.ctor)
+                      {case "RBNode":
+                         switch (t._4._0.ctor)
+                           {case "NBlack":
+                              switch (t._4._3.ctor)
+                                {case "RBNode":
+                                   switch (t._4._3._0.ctor)
+                                     {case "Black":
+                                        return function () {
+                                             switch (t._4._4.ctor)
+                                             {case "RBNode":
+                                                switch (t._4._4._0.ctor)
+                                                  {case "Black":
+                                                     return A5(RBNode,
+                                                       Black,
+                                                       t._4._3._1,
+                                                       t._4._3._2,
+                                                       A5(RBNode,
+                                                       Black,
+                                                       t._1,
+                                                       t._2,
+                                                       t._3,
+                                                       t._4._3._3),
+                                                       A5(balance,
+                                                       Black,
+                                                       t._4._1,
+                                                       t._4._2,
+                                                       t._4._3._4,
+                                                       redden(t._4._4)));}
+                                                  break;}
+                                             return t;
+                                          }();}
+                                     break;}
+                                break;}
+                           break;}
+                      switch (t._3.ctor)
+                      {case "RBNode":
+                         switch (t._3._0.ctor)
+                           {case "NBlack":
+                              switch (t._3._4.ctor)
+                                {case "RBNode":
+                                   switch (t._3._4._0.ctor)
+                                     {case "Black":
+                                        return function () {
+                                             switch (t._3._3.ctor)
+                                             {case "RBNode":
+                                                switch (t._3._3._0.ctor)
+                                                  {case "Black":
+                                                     return A5(RBNode,
+                                                       Black,
+                                                       t._3._4._1,
+                                                       t._3._4._2,
+                                                       A5(balance,
+                                                       Black,
+                                                       t._3._1,
+                                                       t._3._2,
+                                                       redden(t._3._3),
+                                                       t._3._4._3),
+                                                       A5(RBNode,
+                                                       Black,
+                                                       t._1,
+                                                       t._2,
+                                                       t._3._4._4,
+                                                       t._4));}
+                                                  break;}
+                                             return t;
+                                          }();}
+                                     break;}
+                                break;}
+                           break;}
+                      break;}
+                 break;}
+            return t;
+         }() : t;
+      }();
+   };
+   var balance = F5(function (c,
+   k,
+   v,
+   l,
+   r) {
+      return balance_node(A5(RBNode,
+      c,
+      k,
+      v,
+      l,
+      r));
+   });
+   var bubble = F5(function (c,
+   k,
+   v,
+   l,
+   r) {
+      return isBBlack(l) || isBBlack(r) ? A5(balance,
+      moreBlack(c),
+      k,
+      v,
+      lessBlackTree(l),
+      lessBlackTree(r)) : A5(RBNode,
+      c,
+      k,
+      v,
+      l,
+      r);
+   });
+   var remove_max = F5(function (c,
+   k,
+   v,
+   l,
+   r) {
+      return function () {
+         switch (r.ctor)
+         {case "RBEmpty": return A3(rem,
+              c,
+              l,
+              r);
+            case "RBNode": return A5(bubble,
+              c,
+              k,
+              v,
+              l,
+              A5(remove_max,
+              r._0,
+              r._1,
+              r._2,
+              r._3,
+              r._4));}
+         _U.badCase($moduleName,
+         "between lines 316 and 321");
+      }();
+   });
+   var rem = F3(function (c,l,r) {
+      return function () {
+         var _v169 = {ctor: "_Tuple2"
+                     ,_0: l
+                     ,_1: r};
+         switch (_v169.ctor)
+         {case "_Tuple2":
+            switch (_v169._0.ctor)
+              {case "RBEmpty":
+                 switch (_v169._1.ctor)
+                   {case "RBEmpty":
+                      return function () {
+                           switch (c.ctor)
+                           {case "Black":
+                              return RBEmpty(LBBlack);
+                              case "Red":
+                              return RBEmpty(LBlack);}
+                           _U.badCase($moduleName,
+                           "between lines 275 and 279");
+                        }();
+                      case "RBNode":
+                      return function () {
+                           var _v191 = {ctor: "_Tuple3"
+                                       ,_0: c
+                                       ,_1: _v169._0._0
+                                       ,_2: _v169._1._0};
+                           switch (_v191.ctor)
+                           {case "_Tuple3":
+                              switch (_v191._0.ctor)
+                                {case "Black":
+                                   switch (_v191._1.ctor)
+                                     {case "LBlack":
+                                        switch (_v191._2.ctor)
+                                          {case "Red": return A5(RBNode,
+                                               Black,
+                                               _v169._1._1,
+                                               _v169._1._2,
+                                               _v169._1._3,
+                                               _v169._1._4);}
+                                          break;}
+                                     break;}
+                                break;}
+                           return A4(reportRemBug,
+                           "Black/LBlack/Red",
+                           c,
+                           showLColor(_v169._0._0),
+                           showNColor(_v169._1._0));
+                        }();}
+                   break;
+                 case "RBNode":
+                 switch (_v169._1.ctor)
+                   {case "RBEmpty":
+                      return function () {
+                           var _v195 = {ctor: "_Tuple3"
+                                       ,_0: c
+                                       ,_1: _v169._0._0
+                                       ,_2: _v169._1._0};
+                           switch (_v195.ctor)
+                           {case "_Tuple3":
+                              switch (_v195._0.ctor)
+                                {case "Black":
+                                   switch (_v195._1.ctor)
+                                     {case "Red":
+                                        switch (_v195._2.ctor)
+                                          {case "LBlack":
+                                             return A5(RBNode,
+                                               Black,
+                                               _v169._0._1,
+                                               _v169._0._2,
+                                               _v169._0._3,
+                                               _v169._0._4);}
+                                          break;}
+                                     break;}
+                                break;}
+                           return A4(reportRemBug,
+                           "Black/Red/LBlack",
+                           c,
+                           showNColor(_v169._0._0),
+                           showLColor(_v169._1._0));
+                        }();
+                      case "RBNode":
+                      return function () {
+                           var l$ = A5(remove_max,
+                           _v169._0._0,
+                           _v169._0._1,
+                           _v169._0._2,
+                           _v169._0._3,
+                           _v169._0._4);
+                           var r = A5(RBNode,
+                           _v169._1._0,
+                           _v169._1._1,
+                           _v169._1._2,
+                           _v169._1._3,
+                           _v169._1._4);
+                           var l = A5(RBNode,
+                           _v169._0._0,
+                           _v169._0._1,
+                           _v169._0._2,
+                           _v169._0._3,
+                           _v169._0._4);
+                           var $ = max(l),
+                           k = $._0,
+                           v = $._1;
+                           return A5(bubble,c,k,v,l$,r);
+                        }();}
+                   break;}
+              break;}
+         _U.badCase($moduleName,
+         "between lines 273 and 302");
+      }();
+   });
+   var update = F3(function (k,
+   alter,
+   dict) {
+      return function () {
+         var up = function (dict) {
+            return function () {
+               switch (dict.ctor)
+               {case "RBEmpty":
+                  switch (dict._0.ctor)
+                    {case "LBlack":
+                       return function () {
+                            var _v206 = alter($Maybe.Nothing);
+                            switch (_v206.ctor)
+                            {case "Just":
+                               return {ctor: "_Tuple2"
+                                      ,_0: Insert
+                                      ,_1: A5(RBNode,
+                                      Red,
+                                      k,
+                                      _v206._0,
+                                      empty,
+                                      empty)};
+                               case "Nothing":
+                               return {ctor: "_Tuple2"
+                                      ,_0: Same
+                                      ,_1: empty};}
+                            _U.badCase($moduleName,
+                            "between lines 187 and 191");
+                         }();}
+                    break;
+                  case "RBNode":
+                  return function () {
+                       var _v208 = A2($Basics.compare,
+                       k,
+                       dict._1);
+                       switch (_v208.ctor)
+                       {case "EQ": return function () {
+                               var _v209 = alter($Maybe.Just(dict._2));
+                               switch (_v209.ctor)
+                               {case "Just":
+                                  return {ctor: "_Tuple2"
+                                         ,_0: Same
+                                         ,_1: A5(RBNode,
+                                         dict._0,
+                                         dict._1,
+                                         _v209._0,
+                                         dict._3,
+                                         dict._4)};
+                                  case "Nothing":
+                                  return {ctor: "_Tuple2"
+                                         ,_0: Remove
+                                         ,_1: A3(rem,
+                                         dict._0,
+                                         dict._3,
+                                         dict._4)};}
+                               _U.badCase($moduleName,
+                               "between lines 194 and 199");
+                            }();
+                          case "GT": return function () {
+                               var $ = up(dict._4),
+                               flag = $._0,
+                               newRight = $._1;
+                               return function () {
+                                  switch (flag.ctor)
+                                  {case "Insert":
+                                     return {ctor: "_Tuple2"
+                                            ,_0: Insert
+                                            ,_1: A5(balance,
+                                            dict._0,
+                                            dict._1,
+                                            dict._2,
+                                            dict._3,
+                                            newRight)};
+                                     case "Remove":
+                                     return {ctor: "_Tuple2"
+                                            ,_0: Remove
+                                            ,_1: A5(bubble,
+                                            dict._0,
+                                            dict._1,
+                                            dict._2,
+                                            dict._3,
+                                            newRight)};
+                                     case "Same":
+                                     return {ctor: "_Tuple2"
+                                            ,_0: Same
+                                            ,_1: A5(RBNode,
+                                            dict._0,
+                                            dict._1,
+                                            dict._2,
+                                            dict._3,
+                                            newRight)};}
+                                  _U.badCase($moduleName,
+                                  "between lines 208 and 213");
+                               }();
+                            }();
+                          case "LT": return function () {
+                               var $ = up(dict._3),
+                               flag = $._0,
+                               newLeft = $._1;
+                               return function () {
+                                  switch (flag.ctor)
+                                  {case "Insert":
+                                     return {ctor: "_Tuple2"
+                                            ,_0: Insert
+                                            ,_1: A5(balance,
+                                            dict._0,
+                                            dict._1,
+                                            dict._2,
+                                            newLeft,
+                                            dict._4)};
+                                     case "Remove":
+                                     return {ctor: "_Tuple2"
+                                            ,_0: Remove
+                                            ,_1: A5(bubble,
+                                            dict._0,
+                                            dict._1,
+                                            dict._2,
+                                            newLeft,
+                                            dict._4)};
+                                     case "Same":
+                                     return {ctor: "_Tuple2"
+                                            ,_0: Same
+                                            ,_1: A5(RBNode,
+                                            dict._0,
+                                            dict._1,
+                                            dict._2,
+                                            newLeft,
+                                            dict._4)};}
+                                  _U.badCase($moduleName,
+                                  "between lines 201 and 206");
+                               }();
+                            }();}
+                       _U.badCase($moduleName,
+                       "between lines 192 and 213");
+                    }();}
+               _U.badCase($moduleName,
+               "between lines 185 and 213");
+            }();
+         };
+         var $ = up(dict),
+         flag = $._0,
+         updatedDict = $._1;
+         return function () {
+            switch (flag.ctor)
+            {case "Insert":
+               return ensureBlackRoot(updatedDict);
+               case "Remove":
+               return blacken(updatedDict);
+               case "Same":
+               return updatedDict;}
+            _U.badCase($moduleName,
+            "between lines 215 and 221");
+         }();
+      }();
+   });
+   var insert = F3(function (key,
+   value,
+   dict) {
+      return A3(update,
+      key,
+      $Basics.always($Maybe.Just(value)),
+      dict);
+   });
+   var singleton = F2(function (key,
+   value) {
+      return A3(insert,
+      key,
+      value,
+      RBEmpty(LBlack));
+   });
+   var union = F2(function (t1,
+   t2) {
+      return A3(foldl,
+      insert,
+      t2,
+      t1);
+   });
+   var fromList = function (assocs) {
+      return A3($List.foldl,
+      F2(function (_v214,dict) {
+         return function () {
+            switch (_v214.ctor)
+            {case "_Tuple2":
+               return A3(insert,
+                 _v214._0,
+                 _v214._1,
+                 dict);}
+            _U.badCase($moduleName,
+            "on line 459, column 38 to 59");
+         }();
+      }),
+      empty,
+      assocs);
+   };
+   var filter = F2(function (predicate,
+   dictionary) {
+      return function () {
+         var add = F3(function (key,
+         value,
+         dict) {
+            return A2(predicate,
+            key,
+            value) ? A3(insert,
+            key,
+            value,
+            dict) : dict;
+         });
+         return A3(foldl,
+         add,
+         empty,
+         dictionary);
+      }();
+   });
+   var intersect = F2(function (t1,
+   t2) {
+      return A2(filter,
+      F2(function (k,_v218) {
+         return function () {
+            return A2(member,k,t2);
+         }();
+      }),
+      t1);
+   });
+   var partition = F2(function (predicate,
+   dict) {
+      return function () {
+         var add = F3(function (key,
+         value,
+         _v220) {
+            return function () {
+               switch (_v220.ctor)
+               {case "_Tuple2":
+                  return A2(predicate,
+                    key,
+                    value) ? {ctor: "_Tuple2"
+                             ,_0: A3(insert,
+                             key,
+                             value,
+                             _v220._0)
+                             ,_1: _v220._1} : {ctor: "_Tuple2"
+                                              ,_0: _v220._0
+                                              ,_1: A3(insert,
+                                              key,
+                                              value,
+                                              _v220._1)};}
+               _U.badCase($moduleName,
+               "between lines 480 and 482");
+            }();
+         });
+         return A3(foldl,
+         add,
+         {ctor: "_Tuple2"
+         ,_0: empty
+         ,_1: empty},
+         dict);
+      }();
+   });
+   var remove = F2(function (key,
+   dict) {
+      return A3(update,
+      key,
+      $Basics.always($Maybe.Nothing),
+      dict);
+   });
+   var diff = F2(function (t1,t2) {
+      return A3(foldl,
+      F3(function (k,v,t) {
+         return A2(remove,k,t);
+      }),
+      t1,
+      t2);
+   });
+   _elm.Dict.values = {_op: _op
+                      ,empty: empty
+                      ,singleton: singleton
+                      ,insert: insert
+                      ,update: update
+                      ,get: get
+                      ,remove: remove
+                      ,member: member
+                      ,filter: filter
+                      ,partition: partition
+                      ,foldl: foldl
+                      ,foldr: foldr
+                      ,map: map
+                      ,union: union
+                      ,intersect: intersect
+                      ,diff: diff
+                      ,keys: keys
+                      ,values: values
+                      ,toList: toList
+                      ,fromList: fromList};
+   return _elm.Dict.values;
+};
+Elm.Graphics = Elm.Graphics || {};
+Elm.Graphics.Collage = Elm.Graphics.Collage || {};
+Elm.Graphics.Collage.make = function (_elm) {
+   "use strict";
+   _elm.Graphics = _elm.Graphics || {};
+   _elm.Graphics.Collage = _elm.Graphics.Collage || {};
+   if (_elm.Graphics.Collage.values)
+   return _elm.Graphics.Collage.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Graphics.Collage",
+   $Basics = Elm.Basics.make(_elm),
+   $Color = Elm.Color.make(_elm),
+   $Graphics$Element = Elm.Graphics.Element.make(_elm),
+   $List = Elm.List.make(_elm),
+   $Native$Graphics$Collage = Elm.Native.Graphics.Collage.make(_elm),
+   $Transform2D = Elm.Transform2D.make(_elm);
+   var ngon = F2(function (n,r) {
+      return function () {
+         var m = $Basics.toFloat(n);
+         var t = 2 * $Basics.pi / m;
+         var f = function (i) {
+            return {ctor: "_Tuple2"
+                   ,_0: r * $Basics.cos(t * i)
+                   ,_1: r * $Basics.sin(t * i)};
+         };
+         return A2($List.map,
+         f,
+         _L.range(0,m - 1));
+      }();
+   });
+   var oval = F2(function (w,h) {
+      return function () {
+         var hh = h / 2;
+         var hw = w / 2;
+         var n = 50;
+         var t = 2 * $Basics.pi / n;
+         var f = function (i) {
+            return {ctor: "_Tuple2"
+                   ,_0: hw * $Basics.cos(t * i)
+                   ,_1: hh * $Basics.sin(t * i)};
+         };
+         return A2($List.map,
+         f,
+         _L.range(0,n - 1));
+      }();
+   });
+   var circle = function (r) {
+      return A2(oval,2 * r,2 * r);
+   };
+   var rect = F2(function (w,h) {
+      return function () {
+         var hh = h / 2;
+         var hw = w / 2;
+         return _L.fromArray([{ctor: "_Tuple2"
+                              ,_0: 0 - hw
+                              ,_1: 0 - hh}
+                             ,{ctor: "_Tuple2"
+                              ,_0: 0 - hw
+                              ,_1: hh}
+                             ,{ctor: "_Tuple2",_0: hw,_1: hh}
+                             ,{ctor: "_Tuple2"
+                              ,_0: hw
+                              ,_1: 0 - hh}]);
+      }();
+   });
+   var square = function (n) {
+      return A2(rect,n,n);
+   };
+   var polygon = function (points) {
+      return points;
+   };
+   var segment = F2(function (p1,
+   p2) {
+      return _L.fromArray([p1,p2]);
+   });
+   var path = function (ps) {
+      return ps;
+   };
+   var collage = $Native$Graphics$Collage.collage;
+   var alpha = F2(function (a,f) {
+      return _U.replace([["alpha"
+                         ,a]],
+      f);
+   });
+   var rotate = F2(function (t,f) {
+      return _U.replace([["theta"
+                         ,f.theta + t]],
+      f);
+   });
+   var scale = F2(function (s,f) {
+      return _U.replace([["scale"
+                         ,f.scale * s]],
+      f);
+   });
+   var moveY = F2(function (y,f) {
+      return _U.replace([["y"
+                         ,f.y + y]],
+      f);
+   });
+   var moveX = F2(function (x,f) {
+      return _U.replace([["x"
+                         ,f.x + x]],
+      f);
+   });
+   var move = F2(function (_v0,f) {
+      return function () {
+         switch (_v0.ctor)
+         {case "_Tuple2":
+            return _U.replace([["x"
+                               ,f.x + _v0._0]
+                              ,["y",f.y + _v0._1]],
+              f);}
+         _U.badCase($moduleName,
+         "on line 174, column 20 to 48");
+      }();
+   });
+   var form = function (f) {
+      return {_: {}
+             ,alpha: 1
+             ,form: f
+             ,scale: 1
+             ,theta: 0
+             ,x: 0
+             ,y: 0};
+   };
+   var Fill = function (a) {
+      return {ctor: "Fill",_0: a};
+   };
+   var Line = function (a) {
+      return {ctor: "Line",_0: a};
+   };
+   var FGroup = F2(function (a,b) {
+      return {ctor: "FGroup"
+             ,_0: a
+             ,_1: b};
+   });
+   var group = function (fs) {
+      return form(A2(FGroup,
+      $Transform2D.identity,
+      fs));
+   };
+   var groupTransform = F2(function (matrix,
+   fs) {
+      return form(A2(FGroup,
+      matrix,
+      fs));
+   });
+   var FElement = function (a) {
+      return {ctor: "FElement"
+             ,_0: a};
+   };
+   var toForm = function (e) {
+      return form(FElement(e));
+   };
+   var FImage = F4(function (a,
+   b,
+   c,
+   d) {
+      return {ctor: "FImage"
+             ,_0: a
+             ,_1: b
+             ,_2: c
+             ,_3: d};
+   });
+   var sprite = F4(function (w,
+   h,
+   pos,
+   src) {
+      return form(A4(FImage,
+      w,
+      h,
+      pos,
+      src));
+   });
+   var FShape = F2(function (a,b) {
+      return {ctor: "FShape"
+             ,_0: a
+             ,_1: b};
+   });
+   var fill = F2(function (style,
+   shape) {
+      return form(A2(FShape,
+      Fill(style),
+      shape));
+   });
+   var outlined = F2(function (style,
+   shape) {
+      return form(A2(FShape,
+      Line(style),
+      shape));
+   });
+   var FPath = F2(function (a,b) {
+      return {ctor: "FPath"
+             ,_0: a
+             ,_1: b};
+   });
+   var traced = F2(function (style,
+   path) {
+      return form(A2(FPath,
+      style,
+      path));
+   });
+   var LineStyle = F6(function (a,
+   b,
+   c,
+   d,
+   e,
+   f) {
+      return {_: {}
+             ,cap: c
+             ,color: a
+             ,dashOffset: f
+             ,dashing: e
+             ,join: d
+             ,width: b};
+   });
+   var Clipped = {ctor: "Clipped"};
+   var Sharp = function (a) {
+      return {ctor: "Sharp",_0: a};
+   };
+   var Smooth = {ctor: "Smooth"};
+   var Padded = {ctor: "Padded"};
+   var Round = {ctor: "Round"};
+   var Flat = {ctor: "Flat"};
+   var defaultLine = {_: {}
+                     ,cap: Flat
+                     ,color: $Color.black
+                     ,dashOffset: 0
+                     ,dashing: _L.fromArray([])
+                     ,join: Sharp(10)
+                     ,width: 1};
+   var solid = function (clr) {
+      return _U.replace([["color"
+                         ,clr]],
+      defaultLine);
+   };
+   var dashed = function (clr) {
+      return _U.replace([["color"
+                         ,clr]
+                        ,["dashing"
+                         ,_L.fromArray([8,4])]],
+      defaultLine);
+   };
+   var dotted = function (clr) {
+      return _U.replace([["color"
+                         ,clr]
+                        ,["dashing"
+                         ,_L.fromArray([3,3])]],
+      defaultLine);
+   };
+   var Grad = function (a) {
+      return {ctor: "Grad",_0: a};
+   };
+   var gradient = F2(function (grad,
+   shape) {
+      return A2(fill,
+      Grad(grad),
+      shape);
+   });
+   var Texture = function (a) {
+      return {ctor: "Texture"
+             ,_0: a};
+   };
+   var textured = F2(function (src,
+   shape) {
+      return A2(fill,
+      Texture(src),
+      shape);
+   });
+   var Solid = function (a) {
+      return {ctor: "Solid",_0: a};
+   };
+   var filled = F2(function (color,
+   shape) {
+      return A2(fill,
+      Solid(color),
+      shape);
+   });
+   var Form = F6(function (a,
+   b,
+   c,
+   d,
+   e,
+   f) {
+      return {_: {}
+             ,alpha: e
+             ,form: f
+             ,scale: b
+             ,theta: a
+             ,x: c
+             ,y: d};
+   });
+   _elm.Graphics.Collage.values = {_op: _op
+                                  ,Form: Form
+                                  ,Solid: Solid
+                                  ,Texture: Texture
+                                  ,Grad: Grad
+                                  ,Flat: Flat
+                                  ,Round: Round
+                                  ,Padded: Padded
+                                  ,Smooth: Smooth
+                                  ,Sharp: Sharp
+                                  ,Clipped: Clipped
+                                  ,LineStyle: LineStyle
+                                  ,defaultLine: defaultLine
+                                  ,solid: solid
+                                  ,dashed: dashed
+                                  ,dotted: dotted
+                                  ,FPath: FPath
+                                  ,FShape: FShape
+                                  ,FImage: FImage
+                                  ,FElement: FElement
+                                  ,FGroup: FGroup
+                                  ,Line: Line
+                                  ,Fill: Fill
+                                  ,form: form
+                                  ,fill: fill
+                                  ,filled: filled
+                                  ,textured: textured
+                                  ,gradient: gradient
+                                  ,outlined: outlined
+                                  ,traced: traced
+                                  ,sprite: sprite
+                                  ,toForm: toForm
+                                  ,group: group
+                                  ,groupTransform: groupTransform
+                                  ,move: move
+                                  ,moveX: moveX
+                                  ,moveY: moveY
+                                  ,scale: scale
+                                  ,rotate: rotate
+                                  ,alpha: alpha
+                                  ,collage: collage
+                                  ,path: path
+                                  ,segment: segment
+                                  ,polygon: polygon
+                                  ,rect: rect
+                                  ,square: square
+                                  ,oval: oval
+                                  ,circle: circle
+                                  ,ngon: ngon};
+   return _elm.Graphics.Collage.values;
+};
+Elm.Graphics = Elm.Graphics || {};
+Elm.Graphics.Element = Elm.Graphics.Element || {};
+Elm.Graphics.Element.make = function (_elm) {
+   "use strict";
+   _elm.Graphics = _elm.Graphics || {};
+   _elm.Graphics.Element = _elm.Graphics.Element || {};
+   if (_elm.Graphics.Element.values)
+   return _elm.Graphics.Element.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Graphics.Element",
+   $Basics = Elm.Basics.make(_elm),
+   $Color = Elm.Color.make(_elm),
+   $List = Elm.List.make(_elm),
+   $Maybe = Elm.Maybe.make(_elm),
+   $Native$Graphics$Element = Elm.Native.Graphics.Element.make(_elm);
+   var DOut = {ctor: "DOut"};
+   var outward = DOut;
+   var DIn = {ctor: "DIn"};
+   var inward = DIn;
+   var DRight = {ctor: "DRight"};
+   var right = DRight;
+   var DLeft = {ctor: "DLeft"};
+   var left = DLeft;
+   var DDown = {ctor: "DDown"};
+   var down = DDown;
+   var DUp = {ctor: "DUp"};
+   var up = DUp;
+   var Position = F4(function (a,
+   b,
+   c,
+   d) {
+      return {_: {}
+             ,horizontal: a
+             ,vertical: b
+             ,x: c
+             ,y: d};
+   });
+   var Relative = function (a) {
+      return {ctor: "Relative"
+             ,_0: a};
+   };
+   var relative = Relative;
+   var Absolute = function (a) {
+      return {ctor: "Absolute"
+             ,_0: a};
+   };
+   var absolute = Absolute;
+   var N = {ctor: "N"};
+   var bottomLeftAt = F2(function (x,
+   y) {
+      return {_: {}
+             ,horizontal: N
+             ,vertical: N
+             ,x: x
+             ,y: y};
+   });
+   var Z = {ctor: "Z"};
+   var middle = {_: {}
+                ,horizontal: Z
+                ,vertical: Z
+                ,x: Relative(0.5)
+                ,y: Relative(0.5)};
+   var midLeft = _U.replace([["horizontal"
+                             ,N]
+                            ,["x",Absolute(0)]],
+   middle);
+   var middleAt = F2(function (x,
+   y) {
+      return {_: {}
+             ,horizontal: Z
+             ,vertical: Z
+             ,x: x
+             ,y: y};
+   });
+   var midLeftAt = F2(function (x,
+   y) {
+      return {_: {}
+             ,horizontal: N
+             ,vertical: Z
+             ,x: x
+             ,y: y};
+   });
+   var midBottomAt = F2(function (x,
+   y) {
+      return {_: {}
+             ,horizontal: Z
+             ,vertical: N
+             ,x: x
+             ,y: y};
+   });
+   var P = {ctor: "P"};
+   var topLeft = {_: {}
+                 ,horizontal: N
+                 ,vertical: P
+                 ,x: Absolute(0)
+                 ,y: Absolute(0)};
+   var bottomLeft = _U.replace([["vertical"
+                                ,N]],
+   topLeft);
+   var topRight = _U.replace([["horizontal"
+                              ,P]],
+   topLeft);
+   var bottomRight = _U.replace([["horizontal"
+                                 ,P]],
+   bottomLeft);
+   var midRight = _U.replace([["horizontal"
+                              ,P]],
+   midLeft);
+   var midTop = _U.replace([["vertical"
+                            ,P]
+                           ,["y",Absolute(0)]],
+   middle);
+   var midBottom = _U.replace([["vertical"
+                               ,N]],
+   midTop);
+   var topLeftAt = F2(function (x,
+   y) {
+      return {_: {}
+             ,horizontal: N
+             ,vertical: P
+             ,x: x
+             ,y: y};
+   });
+   var topRightAt = F2(function (x,
+   y) {
+      return {_: {}
+             ,horizontal: P
+             ,vertical: P
+             ,x: x
+             ,y: y};
+   });
+   var bottomRightAt = F2(function (x,
+   y) {
+      return {_: {}
+             ,horizontal: P
+             ,vertical: N
+             ,x: x
+             ,y: y};
+   });
+   var midRightAt = F2(function (x,
+   y) {
+      return {_: {}
+             ,horizontal: P
+             ,vertical: Z
+             ,x: x
+             ,y: y};
+   });
+   var midTopAt = F2(function (x,
+   y) {
+      return {_: {}
+             ,horizontal: Z
+             ,vertical: P
+             ,x: x
+             ,y: y};
+   });
+   var Tiled = {ctor: "Tiled"};
+   var Cropped = function (a) {
+      return {ctor: "Cropped"
+             ,_0: a};
+   };
+   var Fitted = {ctor: "Fitted"};
+   var Plain = {ctor: "Plain"};
+   var Custom = {ctor: "Custom"};
+   var RawHtml = {ctor: "RawHtml"};
+   var Spacer = {ctor: "Spacer"};
+   var Flow = F2(function (a,b) {
+      return {ctor: "Flow"
+             ,_0: a
+             ,_1: b};
+   });
+   var Container = F2(function (a,
+   b) {
+      return {ctor: "Container"
+             ,_0: a
+             ,_1: b};
+   });
+   var Image = F4(function (a,
+   b,
+   c,
+   d) {
+      return {ctor: "Image"
+             ,_0: a
+             ,_1: b
+             ,_2: c
+             ,_3: d};
+   });
+   var link = F2(function (href,
+   e) {
+      return function () {
+         var p = e.props;
+         return {_: {}
+                ,element: e.element
+                ,props: _U.replace([["href"
+                                    ,href]],
+                p)};
+      }();
+   });
+   var tag = F2(function (name,e) {
+      return function () {
+         var p = e.props;
+         return {_: {}
+                ,element: e.element
+                ,props: _U.replace([["tag"
+                                    ,name]],
+                p)};
+      }();
+   });
+   var color = F2(function (c,e) {
+      return function () {
+         var p = e.props;
+         return {_: {}
+                ,element: e.element
+                ,props: _U.replace([["color"
+                                    ,$Maybe.Just(c)]],
+                p)};
+      }();
+   });
+   var opacity = F2(function (o,
+   e) {
+      return function () {
+         var p = e.props;
+         return {_: {}
+                ,element: e.element
+                ,props: _U.replace([["opacity"
+                                    ,o]],
+                p)};
+      }();
+   });
+   var height = F2(function (nh,
+   e) {
+      return function () {
+         var p = e.props;
+         var props = function () {
+            var _v0 = e.element;
+            switch (_v0.ctor)
+            {case "Image":
+               return _U.replace([["width"
+                                  ,$Basics.round($Basics.toFloat(_v0._1) / $Basics.toFloat(_v0._2) * $Basics.toFloat(nh))]],
+                 p);}
+            return p;
+         }();
+         return {_: {}
+                ,element: e.element
+                ,props: _U.replace([["height"
+                                    ,nh]],
+                p)};
+      }();
+   });
+   var width = F2(function (nw,e) {
+      return function () {
+         var p = e.props;
+         var props = function () {
+            var _v5 = e.element;
+            switch (_v5.ctor)
+            {case "Image":
+               return _U.replace([["height"
+                                  ,$Basics.round($Basics.toFloat(_v5._2) / $Basics.toFloat(_v5._1) * $Basics.toFloat(nw))]],
+                 p);
+               case "RawHtml":
+               return _U.replace([["height"
+                                  ,$Basics.snd(A2($Native$Graphics$Element.htmlHeight,
+                                  nw,
+                                  e.element))]],
+                 p);}
+            return p;
+         }();
+         return {_: {}
+                ,element: e.element
+                ,props: _U.replace([["width"
+                                    ,nw]],
+                props)};
+      }();
+   });
+   var size = F3(function (w,h,e) {
+      return A2(height,
+      h,
+      A2(width,w,e));
+   });
+   var sizeOf = function (e) {
+      return {ctor: "_Tuple2"
+             ,_0: e.props.width
+             ,_1: e.props.height};
+   };
+   var heightOf = function (e) {
+      return e.props.height;
+   };
+   var widthOf = function (e) {
+      return e.props.width;
+   };
+   var Element = F2(function (a,
+   b) {
+      return {_: {}
+             ,element: b
+             ,props: a};
+   });
+   var Properties = F9(function (a,
+   b,
+   c,
+   d,
+   e,
+   f,
+   g,
+   h,
+   i) {
+      return {_: {}
+             ,click: i
+             ,color: e
+             ,height: c
+             ,hover: h
+             ,href: f
+             ,id: a
+             ,opacity: d
+             ,tag: g
+             ,width: b};
+   });
+   var newElement = F3(function (w,
+   h,
+   e) {
+      return {_: {}
+             ,element: e
+             ,props: A9(Properties,
+             $Native$Graphics$Element.guid({ctor: "_Tuple0"}),
+             w,
+             h,
+             1,
+             $Maybe.Nothing,
+             "",
+             "",
+             {ctor: "_Tuple0"},
+             {ctor: "_Tuple0"})};
+   });
+   var image = F3(function (w,
+   h,
+   src) {
+      return A3(newElement,
+      w,
+      h,
+      A4(Image,Plain,w,h,src));
+   });
+   var fittedImage = F3(function (w,
+   h,
+   src) {
+      return A3(newElement,
+      w,
+      h,
+      A4(Image,Fitted,w,h,src));
+   });
+   var croppedImage = F4(function (pos,
+   w,
+   h,
+   src) {
+      return A3(newElement,
+      w,
+      h,
+      A4(Image,Cropped(pos),w,h,src));
+   });
+   var tiledImage = F3(function (w,
+   h,
+   src) {
+      return A3(newElement,
+      w,
+      h,
+      A4(Image,Tiled,w,h,src));
+   });
+   var container = F4(function (w,
+   h,
+   pos,
+   e) {
+      return A3(newElement,
+      w,
+      h,
+      A2(Container,pos,e));
+   });
+   var spacer = F2(function (w,h) {
+      return A3(newElement,
+      w,
+      h,
+      Spacer);
+   });
+   var empty = A2(spacer,0,0);
+   var flow = F2(function (dir,
+   es) {
+      return function () {
+         var newFlow = F2(function (w,
+         h) {
+            return A3(newElement,
+            w,
+            h,
+            A2(Flow,dir,es));
+         });
+         var hs = A2($List.map,
+         heightOf,
+         es);
+         var ws = A2($List.map,
+         widthOf,
+         es);
+         return _U.eq(es,
+         _L.fromArray([])) ? empty : function () {
+            switch (dir.ctor)
+            {case "DDown":
+               return A2(newFlow,
+                 $List.maximum(ws),
+                 $List.sum(hs));
+               case "DIn": return A2(newFlow,
+                 $List.maximum(ws),
+                 $List.maximum(hs));
+               case "DLeft": return A2(newFlow,
+                 $List.sum(ws),
+                 $List.maximum(hs));
+               case "DOut": return A2(newFlow,
+                 $List.maximum(ws),
+                 $List.maximum(hs));
+               case "DRight":
+               return A2(newFlow,
+                 $List.sum(ws),
+                 $List.maximum(hs));
+               case "DUp": return A2(newFlow,
+                 $List.maximum(ws),
+                 $List.sum(hs));}
+            _U.badCase($moduleName,
+            "between lines 280 and 291");
+         }();
+      }();
+   });
+   var above = F2(function (hi,
+   lo) {
+      return A3(newElement,
+      A2($Basics.max,
+      widthOf(hi),
+      widthOf(lo)),
+      heightOf(hi) + heightOf(lo),
+      A2(Flow,
+      DDown,
+      _L.fromArray([hi,lo])));
+   });
+   var below = F2(function (lo,
+   hi) {
+      return A3(newElement,
+      A2($Basics.max,
+      widthOf(hi),
+      widthOf(lo)),
+      heightOf(hi) + heightOf(lo),
+      A2(Flow,
+      DDown,
+      _L.fromArray([hi,lo])));
+   });
+   var beside = F2(function (lft,
+   rht) {
+      return A3(newElement,
+      widthOf(lft) + widthOf(rht),
+      A2($Basics.max,
+      heightOf(lft),
+      heightOf(rht)),
+      A2(Flow,
+      right,
+      _L.fromArray([lft,rht])));
+   });
+   var layers = function (es) {
+      return function () {
+         var hs = A2($List.map,
+         heightOf,
+         es);
+         var ws = A2($List.map,
+         widthOf,
+         es);
+         return A3(newElement,
+         $List.maximum(ws),
+         $List.maximum(hs),
+         A2(Flow,DOut,es));
+      }();
+   };
+   _elm.Graphics.Element.values = {_op: _op
+                                  ,Properties: Properties
+                                  ,Element: Element
+                                  ,empty: empty
+                                  ,widthOf: widthOf
+                                  ,heightOf: heightOf
+                                  ,sizeOf: sizeOf
+                                  ,width: width
+                                  ,height: height
+                                  ,size: size
+                                  ,opacity: opacity
+                                  ,color: color
+                                  ,tag: tag
+                                  ,link: link
+                                  ,newElement: newElement
+                                  ,Image: Image
+                                  ,Container: Container
+                                  ,Flow: Flow
+                                  ,Spacer: Spacer
+                                  ,RawHtml: RawHtml
+                                  ,Custom: Custom
+                                  ,Plain: Plain
+                                  ,Fitted: Fitted
+                                  ,Cropped: Cropped
+                                  ,Tiled: Tiled
+                                  ,image: image
+                                  ,fittedImage: fittedImage
+                                  ,croppedImage: croppedImage
+                                  ,tiledImage: tiledImage
+                                  ,P: P
+                                  ,Z: Z
+                                  ,N: N
+                                  ,Absolute: Absolute
+                                  ,Relative: Relative
+                                  ,Position: Position
+                                  ,container: container
+                                  ,spacer: spacer
+                                  ,DUp: DUp
+                                  ,DDown: DDown
+                                  ,DLeft: DLeft
+                                  ,DRight: DRight
+                                  ,DIn: DIn
+                                  ,DOut: DOut
+                                  ,flow: flow
+                                  ,above: above
+                                  ,below: below
+                                  ,beside: beside
+                                  ,layers: layers
+                                  ,absolute: absolute
+                                  ,relative: relative
+                                  ,middle: middle
+                                  ,topLeft: topLeft
+                                  ,topRight: topRight
+                                  ,bottomLeft: bottomLeft
+                                  ,bottomRight: bottomRight
+                                  ,midLeft: midLeft
+                                  ,midRight: midRight
+                                  ,midTop: midTop
+                                  ,midBottom: midBottom
+                                  ,middleAt: middleAt
+                                  ,topLeftAt: topLeftAt
+                                  ,topRightAt: topRightAt
+                                  ,bottomLeftAt: bottomLeftAt
+                                  ,bottomRightAt: bottomRightAt
+                                  ,midLeftAt: midLeftAt
+                                  ,midRightAt: midRightAt
+                                  ,midTopAt: midTopAt
+                                  ,midBottomAt: midBottomAt
+                                  ,up: up
+                                  ,down: down
+                                  ,left: left
+                                  ,right: right
+                                  ,inward: inward
+                                  ,outward: outward};
+   return _elm.Graphics.Element.values;
+};
+Elm.Graphics = Elm.Graphics || {};
+Elm.Graphics.Input = Elm.Graphics.Input || {};
+Elm.Graphics.Input.make = function (_elm) {
+   "use strict";
+   _elm.Graphics = _elm.Graphics || {};
+   _elm.Graphics.Input = _elm.Graphics.Input || {};
+   if (_elm.Graphics.Input.values)
+   return _elm.Graphics.Input.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Graphics.Input",
+   $Graphics$Element = Elm.Graphics.Element.make(_elm),
+   $Native$Graphics$Input = Elm.Native.Graphics.Input.make(_elm),
+   $Signal = Elm.Signal.make(_elm);
+   var clickable = $Native$Graphics$Input.clickable;
+   var hoverable = $Native$Graphics$Input.hoverable;
+   var dropDown = $Native$Graphics$Input.dropDown;
+   var checkbox = $Native$Graphics$Input.checkbox;
+   var customButton = $Native$Graphics$Input.customButton;
+   var button = $Native$Graphics$Input.button;
+   _elm.Graphics.Input.values = {_op: _op
+                                ,button: button
+                                ,customButton: customButton
+                                ,checkbox: checkbox
+                                ,dropDown: dropDown
+                                ,hoverable: hoverable
+                                ,clickable: clickable};
+   return _elm.Graphics.Input.values;
+};
+Elm.Html = Elm.Html || {};
+Elm.Html.make = function (_elm) {
+   "use strict";
+   _elm.Html = _elm.Html || {};
+   if (_elm.Html.values)
+   return _elm.Html.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Html",
+   $Graphics$Element = Elm.Graphics.Element.make(_elm),
+   $VirtualDom = Elm.VirtualDom.make(_elm);
+   var fromElement = $VirtualDom.fromElement;
+   var toElement = $VirtualDom.toElement;
+   var text = $VirtualDom.text;
+   var node = $VirtualDom.node;
+   var body = node("body");
+   var section = node("section");
+   var nav = node("nav");
+   var article = node("article");
+   var aside = node("aside");
+   var h1 = node("h1");
+   var h2 = node("h2");
+   var h3 = node("h3");
+   var h4 = node("h4");
+   var h5 = node("h5");
+   var h6 = node("h6");
+   var header = node("header");
+   var footer = node("footer");
+   var address = node("address");
+   var main$ = node("main");
+   var p = node("p");
+   var hr = node("hr");
+   var pre = node("pre");
+   var blockquote = node("blockquote");
+   var ol = node("ol");
+   var ul = node("ul");
+   var li = node("li");
+   var dl = node("dl");
+   var dt = node("dt");
+   var dd = node("dd");
+   var figure = node("figure");
+   var figcaption = node("figcaption");
+   var div = node("div");
+   var a = node("a");
+   var em = node("em");
+   var strong = node("strong");
+   var small = node("small");
+   var s = node("s");
+   var cite = node("cite");
+   var q = node("q");
+   var dfn = node("dfn");
+   var abbr = node("abbr");
+   var time = node("time");
+   var code = node("code");
+   var $var = node("var");
+   var samp = node("samp");
+   var kbd = node("kbd");
+   var sub = node("sub");
+   var sup = node("sup");
+   var i = node("i");
+   var b = node("b");
+   var u = node("u");
+   var mark = node("mark");
+   var ruby = node("ruby");
+   var rt = node("rt");
+   var rp = node("rp");
+   var bdi = node("bdi");
+   var bdo = node("bdo");
+   var span = node("span");
+   var br = node("br");
+   var wbr = node("wbr");
+   var ins = node("ins");
+   var del = node("del");
+   var img = node("img");
+   var iframe = node("iframe");
+   var embed = node("embed");
+   var object = node("object");
+   var param = node("param");
+   var video = node("video");
+   var audio = node("audio");
+   var source = node("source");
+   var track = node("track");
+   var canvas = node("canvas");
+   var svg = node("svg");
+   var math = node("math");
+   var table = node("table");
+   var caption = node("caption");
+   var colgroup = node("colgroup");
+   var col = node("col");
+   var tbody = node("tbody");
+   var thead = node("thead");
+   var tfoot = node("tfoot");
+   var tr = node("tr");
+   var td = node("td");
+   var th = node("th");
+   var form = node("form");
+   var fieldset = node("fieldset");
+   var legend = node("legend");
+   var label = node("label");
+   var input = node("input");
+   var button = node("button");
+   var select = node("select");
+   var datalist = node("datalist");
+   var optgroup = node("optgroup");
+   var option = node("option");
+   var textarea = node("textarea");
+   var keygen = node("keygen");
+   var output = node("output");
+   var progress = node("progress");
+   var meter = node("meter");
+   var details = node("details");
+   var summary = node("summary");
+   var menuitem = node("menuitem");
+   var menu = node("menu");
+   _elm.Html.values = {_op: _op
+                      ,node: node
+                      ,text: text
+                      ,toElement: toElement
+                      ,fromElement: fromElement
+                      ,body: body
+                      ,section: section
+                      ,nav: nav
+                      ,article: article
+                      ,aside: aside
+                      ,h1: h1
+                      ,h2: h2
+                      ,h3: h3
+                      ,h4: h4
+                      ,h5: h5
+                      ,h6: h6
+                      ,header: header
+                      ,footer: footer
+                      ,address: address
+                      ,main$: main$
+                      ,p: p
+                      ,hr: hr
+                      ,pre: pre
+                      ,blockquote: blockquote
+                      ,ol: ol
+                      ,ul: ul
+                      ,li: li
+                      ,dl: dl
+                      ,dt: dt
+                      ,dd: dd
+                      ,figure: figure
+                      ,figcaption: figcaption
+                      ,div: div
+                      ,a: a
+                      ,em: em
+                      ,strong: strong
+                      ,small: small
+                      ,s: s
+                      ,cite: cite
+                      ,q: q
+                      ,dfn: dfn
+                      ,abbr: abbr
+                      ,time: time
+                      ,code: code
+                      ,$var: $var
+                      ,samp: samp
+                      ,kbd: kbd
+                      ,sub: sub
+                      ,sup: sup
+                      ,i: i
+                      ,b: b
+                      ,u: u
+                      ,mark: mark
+                      ,ruby: ruby
+                      ,rt: rt
+                      ,rp: rp
+                      ,bdi: bdi
+                      ,bdo: bdo
+                      ,span: span
+                      ,br: br
+                      ,wbr: wbr
+                      ,ins: ins
+                      ,del: del
+                      ,img: img
+                      ,iframe: iframe
+                      ,embed: embed
+                      ,object: object
+                      ,param: param
+                      ,video: video
+                      ,audio: audio
+                      ,source: source
+                      ,track: track
+                      ,canvas: canvas
+                      ,svg: svg
+                      ,math: math
+                      ,table: table
+                      ,caption: caption
+                      ,colgroup: colgroup
+                      ,col: col
+                      ,tbody: tbody
+                      ,thead: thead
+                      ,tfoot: tfoot
+                      ,tr: tr
+                      ,td: td
+                      ,th: th
+                      ,form: form
+                      ,fieldset: fieldset
+                      ,legend: legend
+                      ,label: label
+                      ,input: input
+                      ,button: button
+                      ,select: select
+                      ,datalist: datalist
+                      ,optgroup: optgroup
+                      ,option: option
+                      ,textarea: textarea
+                      ,keygen: keygen
+                      ,output: output
+                      ,progress: progress
+                      ,meter: meter
+                      ,details: details
+                      ,summary: summary
+                      ,menuitem: menuitem
+                      ,menu: menu};
+   return _elm.Html.values;
+};
+Elm.Json = Elm.Json || {};
+Elm.Json.Decode = Elm.Json.Decode || {};
+Elm.Json.Decode.make = function (_elm) {
+   "use strict";
+   _elm.Json = _elm.Json || {};
+   _elm.Json.Decode = _elm.Json.Decode || {};
+   if (_elm.Json.Decode.values)
+   return _elm.Json.Decode.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Json.Decode",
+   $Array = Elm.Array.make(_elm),
+   $Dict = Elm.Dict.make(_elm),
+   $Json$Encode = Elm.Json.Encode.make(_elm),
+   $List = Elm.List.make(_elm),
+   $Maybe = Elm.Maybe.make(_elm),
+   $Native$Json = Elm.Native.Json.make(_elm),
+   $Result = Elm.Result.make(_elm);
+   var tuple8 = $Native$Json.decodeTuple8;
+   var tuple7 = $Native$Json.decodeTuple7;
+   var tuple6 = $Native$Json.decodeTuple6;
+   var tuple5 = $Native$Json.decodeTuple5;
+   var tuple4 = $Native$Json.decodeTuple4;
+   var tuple3 = $Native$Json.decodeTuple3;
+   var tuple2 = $Native$Json.decodeTuple2;
+   var tuple1 = $Native$Json.decodeTuple1;
+   var succeed = $Native$Json.succeed;
+   var fail = $Native$Json.fail;
+   var andThen = $Native$Json.andThen;
+   var customDecoder = $Native$Json.customDecoder;
+   var decodeValue = $Native$Json.runDecoderValue;
+   var value = $Native$Json.decodeValue;
+   var maybe = $Native$Json.decodeMaybe;
+   var $null = $Native$Json.decodeNull;
+   var array = $Native$Json.decodeArray;
+   var list = $Native$Json.decodeList;
+   var bool = $Native$Json.decodeBool;
+   var $int = $Native$Json.decodeInt;
+   var $float = $Native$Json.decodeFloat;
+   var string = $Native$Json.decodeString;
+   var oneOf = $Native$Json.oneOf;
+   var keyValuePairs = $Native$Json.decodeKeyValuePairs;
+   var object8 = $Native$Json.decodeObject8;
+   var object7 = $Native$Json.decodeObject7;
+   var object6 = $Native$Json.decodeObject6;
+   var object5 = $Native$Json.decodeObject5;
+   var object4 = $Native$Json.decodeObject4;
+   var object3 = $Native$Json.decodeObject3;
+   var object2 = $Native$Json.decodeObject2;
+   var object1 = $Native$Json.decodeObject1;
+   _op[":="] = $Native$Json.decodeField;
+   var at = F2(function (fields,
+   decoder) {
+      return A3($List.foldr,
+      F2(function (x,y) {
+         return A2(_op[":="],x,y);
+      }),
+      decoder,
+      fields);
+   });
+   var decodeString = $Native$Json.runDecoderString;
+   var map = $Native$Json.decodeObject1;
+   var dict = function (decoder) {
+      return A2(map,
+      $Dict.fromList,
+      keyValuePairs(decoder));
+   };
+   var Decoder = {ctor: "Decoder"};
+   _elm.Json.Decode.values = {_op: _op
+                             ,Decoder: Decoder
+                             ,map: map
+                             ,decodeString: decodeString
+                             ,at: at
+                             ,object1: object1
+                             ,object2: object2
+                             ,object3: object3
+                             ,object4: object4
+                             ,object5: object5
+                             ,object6: object6
+                             ,object7: object7
+                             ,object8: object8
+                             ,keyValuePairs: keyValuePairs
+                             ,dict: dict
+                             ,oneOf: oneOf
+                             ,string: string
+                             ,$float: $float
+                             ,$int: $int
+                             ,bool: bool
+                             ,list: list
+                             ,array: array
+                             ,$null: $null
+                             ,maybe: maybe
+                             ,value: value
+                             ,decodeValue: decodeValue
+                             ,customDecoder: customDecoder
+                             ,andThen: andThen
+                             ,fail: fail
+                             ,succeed: succeed
+                             ,tuple1: tuple1
+                             ,tuple2: tuple2
+                             ,tuple3: tuple3
+                             ,tuple4: tuple4
+                             ,tuple5: tuple5
+                             ,tuple6: tuple6
+                             ,tuple7: tuple7
+                             ,tuple8: tuple8};
+   return _elm.Json.Decode.values;
+};
+Elm.Json = Elm.Json || {};
+Elm.Json.Encode = Elm.Json.Encode || {};
+Elm.Json.Encode.make = function (_elm) {
+   "use strict";
+   _elm.Json = _elm.Json || {};
+   _elm.Json.Encode = _elm.Json.Encode || {};
+   if (_elm.Json.Encode.values)
+   return _elm.Json.Encode.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Json.Encode",
+   $Array = Elm.Array.make(_elm),
+   $Native$Json = Elm.Native.Json.make(_elm);
+   var list = $Native$Json.encodeList;
+   var array = $Native$Json.encodeArray;
+   var object = $Native$Json.encodeObject;
+   var $null = $Native$Json.encodeNull;
+   var bool = $Native$Json.identity;
+   var $float = $Native$Json.identity;
+   var $int = $Native$Json.identity;
+   var string = $Native$Json.identity;
+   var encode = $Native$Json.encode;
+   var Value = {ctor: "Value"};
+   _elm.Json.Encode.values = {_op: _op
+                             ,Value: Value
+                             ,encode: encode
+                             ,string: string
+                             ,$int: $int
+                             ,$float: $float
+                             ,bool: bool
+                             ,$null: $null
+                             ,object: object
+                             ,array: array
+                             ,list: list};
+   return _elm.Json.Encode.values;
+};
+Elm.List = Elm.List || {};
+Elm.List.make = function (_elm) {
+   "use strict";
+   _elm.List = _elm.List || {};
+   if (_elm.List.values)
+   return _elm.List.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "List",
+   $Basics = Elm.Basics.make(_elm),
+   $Maybe = Elm.Maybe.make(_elm),
+   $Native$List = Elm.Native.List.make(_elm);
+   var sortWith = $Native$List.sortWith;
+   var sortBy = $Native$List.sortBy;
+   var sort = $Native$List.sort;
+   var repeat = $Native$List.repeat;
+   var drop = $Native$List.drop;
+   var take = $Native$List.take;
+   var map5 = $Native$List.map5;
+   var map4 = $Native$List.map4;
+   var map3 = $Native$List.map3;
+   var map2 = $Native$List.map2;
+   var append = $Native$List.append;
+   var any = $Native$List.any;
+   var all = $Native$List.all;
+   var reverse = $Native$List.reverse;
+   var length = $Native$List.length;
+   var filter = $Native$List.filter;
+   var scanl1 = $Native$List.scanl1;
+   var scanl = $Native$List.scanl;
+   var foldr1 = $Native$List.foldr1;
+   var foldl1 = $Native$List.foldl1;
+   var maximum = foldl1($Basics.max);
+   var minimum = foldl1($Basics.min);
+   var foldr = $Native$List.foldr;
+   var concat = function (lists) {
+      return A3(foldr,
+      append,
+      _L.fromArray([]),
+      lists);
+   };
+   var foldl = $Native$List.foldl;
+   var sum = function (numbers) {
+      return A3(foldl,
+      F2(function (x,y) {
+         return x + y;
+      }),
+      0,
+      numbers);
+   };
+   var product = function (numbers) {
+      return A3(foldl,
+      F2(function (x,y) {
+         return x * y;
+      }),
+      1,
+      numbers);
+   };
+   var indexedMap = F2(function (f,
+   xs) {
+      return A3(map2,
+      f,
+      _L.range(0,length(xs) - 1),
+      xs);
+   });
+   var map = $Native$List.map;
+   var concatMap = F2(function (f,
+   list) {
+      return concat(A2(map,
+      f,
+      list));
+   });
+   var member = $Native$List.member;
+   var isEmpty = function (xs) {
+      return function () {
+         switch (xs.ctor)
+         {case "[]": return true;}
+         return false;
+      }();
+   };
+   var tail = $Native$List.tail;
+   var head = $Native$List.head;
+   _op["::"] = $Native$List.cons;
+   var maybeCons = F3(function (f,
+   mx,
+   xs) {
+      return function () {
+         var _v1 = f(mx);
+         switch (_v1.ctor)
+         {case "Just":
+            return A2(_op["::"],_v1._0,xs);
+            case "Nothing": return xs;}
+         _U.badCase($moduleName,
+         "between lines 162 and 169");
+      }();
+   });
+   var filterMap = F2(function (f,
+   xs) {
+      return A3(foldr,
+      maybeCons(f),
+      _L.fromArray([]),
+      xs);
+   });
+   var partition = F2(function (pred,
+   list) {
+      return function () {
+         var step = F2(function (x,
+         _v3) {
+            return function () {
+               switch (_v3.ctor)
+               {case "_Tuple2":
+                  return pred(x) ? {ctor: "_Tuple2"
+                                   ,_0: A2(_op["::"],x,_v3._0)
+                                   ,_1: _v3._1} : {ctor: "_Tuple2"
+                                                  ,_0: _v3._0
+                                                  ,_1: A2(_op["::"],x,_v3._1)};}
+               _U.badCase($moduleName,
+               "between lines 270 and 272");
+            }();
+         });
+         return A3(foldr,
+         step,
+         {ctor: "_Tuple2"
+         ,_0: _L.fromArray([])
+         ,_1: _L.fromArray([])},
+         list);
+      }();
+   });
+   var unzip = function (pairs) {
+      return function () {
+         var step = F2(function (_v7,
+         _v8) {
+            return function () {
+               switch (_v8.ctor)
+               {case "_Tuple2":
+                  return function () {
+                       switch (_v7.ctor)
+                       {case "_Tuple2":
+                          return {ctor: "_Tuple2"
+                                 ,_0: A2(_op["::"],_v7._0,_v8._0)
+                                 ,_1: A2(_op["::"],
+                                 _v7._1,
+                                 _v8._1)};}
+                       _U.badCase($moduleName,
+                       "on line 308, column 12 to 28");
+                    }();}
+               _U.badCase($moduleName,
+               "on line 308, column 12 to 28");
+            }();
+         });
+         return A3(foldr,
+         step,
+         {ctor: "_Tuple2"
+         ,_0: _L.fromArray([])
+         ,_1: _L.fromArray([])},
+         pairs);
+      }();
+   };
+   var intersperse = F2(function (sep,
+   xs) {
+      return function () {
+         switch (xs.ctor)
+         {case "::": return function () {
+                 var step = F2(function (x,
+                 rest) {
+                    return A2(_op["::"],
+                    sep,
+                    A2(_op["::"],x,rest));
+                 });
+                 var spersed = A3(foldr,
+                 step,
+                 _L.fromArray([]),
+                 xs._1);
+                 return A2(_op["::"],
+                 xs._0,
+                 spersed);
+              }();
+            case "[]":
+            return _L.fromArray([]);}
+         _U.badCase($moduleName,
+         "between lines 319 and 330");
+      }();
+   });
+   _elm.List.values = {_op: _op
+                      ,head: head
+                      ,tail: tail
+                      ,isEmpty: isEmpty
+                      ,member: member
+                      ,map: map
+                      ,indexedMap: indexedMap
+                      ,foldl: foldl
+                      ,foldr: foldr
+                      ,foldl1: foldl1
+                      ,foldr1: foldr1
+                      ,scanl: scanl
+                      ,scanl1: scanl1
+                      ,filter: filter
+                      ,filterMap: filterMap
+                      ,maybeCons: maybeCons
+                      ,length: length
+                      ,reverse: reverse
+                      ,all: all
+                      ,any: any
+                      ,append: append
+                      ,concat: concat
+                      ,concatMap: concatMap
+                      ,sum: sum
+                      ,product: product
+                      ,maximum: maximum
+                      ,minimum: minimum
+                      ,partition: partition
+                      ,map2: map2
+                      ,map3: map3
+                      ,map4: map4
+                      ,map5: map5
+                      ,unzip: unzip
+                      ,intersperse: intersperse
+                      ,take: take
+                      ,drop: drop
+                      ,repeat: repeat
+                      ,sort: sort
+                      ,sortBy: sortBy
+                      ,sortWith: sortWith};
+   return _elm.List.values;
+};
+Elm.Markdown = Elm.Markdown || {};
+Elm.Markdown.make = function (_elm) {
+   "use strict";
+   _elm.Markdown = _elm.Markdown || {};
+   if (_elm.Markdown.values)
+   return _elm.Markdown.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Markdown",
+   $Graphics$Element = Elm.Graphics.Element.make(_elm),
+   $Html = Elm.Html.make(_elm),
+   $Maybe = Elm.Maybe.make(_elm),
+   $Native$Markdown = Elm.Native.Markdown.make(_elm);
+   var toElementWith = $Native$Markdown.toElementWith;
+   var toHtmlWith = $Native$Markdown.toHtmlWith;
+   var defaultOptions = {_: {}
+                        ,githubFlavored: $Maybe.Just({_: {}
+                                                     ,breaks: false
+                                                     ,tables: false})
+                        ,sanitize: false
+                        ,smartypants: false};
+   var Options = F3(function (a,
+   b,
+   c) {
+      return {_: {}
+             ,githubFlavored: a
+             ,sanitize: b
+             ,smartypants: c};
+   });
+   var toElement = function (string) {
+      return A2($Native$Markdown.toElementWith,
+      defaultOptions,
+      string);
+   };
+   var toHtml = function (string) {
+      return A2($Native$Markdown.toHtmlWith,
+      defaultOptions,
+      string);
+   };
+   _elm.Markdown.values = {_op: _op
+                          ,toHtml: toHtml
+                          ,toElement: toElement
+                          ,Options: Options
+                          ,defaultOptions: defaultOptions
+                          ,toHtmlWith: toHtmlWith
+                          ,toElementWith: toElementWith};
+   return _elm.Markdown.values;
+};
+Elm.Maybe = Elm.Maybe || {};
+Elm.Maybe.make = function (_elm) {
+   "use strict";
+   _elm.Maybe = _elm.Maybe || {};
+   if (_elm.Maybe.values)
+   return _elm.Maybe.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Maybe";
+   _op["?"] = F2(function (maybe,
+   $default) {
+      return function () {
+         switch (maybe.ctor)
+         {case "Just": return maybe._0;
+            case "Nothing":
+            return $default;}
+         _U.badCase($moduleName,
+         "between lines 53 and 55");
+      }();
+   });
+   var Nothing = {ctor: "Nothing"};
+   var oneOf = function (maybes) {
+      return function () {
+         switch (maybes.ctor)
+         {case "::": return function () {
+                 switch (maybes._0.ctor)
+                 {case "Just": return maybes._0;
+                    case "Nothing":
+                    return oneOf(maybes._1);}
+                 _U.badCase($moduleName,
+                 "between lines 74 and 83");
+              }();
+            case "[]": return Nothing;}
+         _U.badCase($moduleName,
+         "between lines 69 and 83");
+      }();
+   };
+   var andThen = F2(function (maybeValue,
+   callback) {
+      return function () {
+         switch (maybeValue.ctor)
+         {case "Just":
+            return callback(maybeValue._0);
+            case "Nothing": return Nothing;}
+         _U.badCase($moduleName,
+         "between lines 120 and 122");
+      }();
+   });
+   var Just = function (a) {
+      return {ctor: "Just",_0: a};
+   };
+   var map = F2(function (f,
+   maybe) {
+      return function () {
+         switch (maybe.ctor)
+         {case "Just":
+            return Just(f(maybe._0));
+            case "Nothing": return Nothing;}
+         _U.badCase($moduleName,
+         "between lines 86 and 117");
+      }();
+   });
+   _elm.Maybe.values = {_op: _op
+                       ,andThen: andThen
+                       ,map: map
+                       ,oneOf: oneOf
+                       ,Just: Just
+                       ,Nothing: Nothing};
+   return _elm.Maybe.values;
+};
+Elm.Native.Array = {};
+Elm.Native.Array.make = function(elm) {
+    elm.Native = elm.Native || {};
+    elm.Native.Array = elm.Native.Array || {};
+    if (elm.Native.Array.values) return elm.Native.Array.values;
+    if ('values' in Elm.Native.Array)
+      return elm.Native.Array.values = Elm.Native.Array.values;
+
+    var List = Elm.Native.List.make(elm);
+
+    // A RRB-Tree has two distinct data types.
+    // Leaf -> "height"  is always 0
+    //         "table"   is an array of elements
+    // Node -> "height"  is always greater than 0
+    //         "table"   is an array of child nodes
+    //         "lengths" is an array of accumulated lengths of the child nodes
+
+    // M is the maximal table size. 32 seems fast. E is the allowed increase
+    // of search steps when concatting to find an index. Lower values will 
+    // decrease balancing, but will increase search steps.
+    var M = 32;
+    var E = 2;
+
+    // An empty array.
+    var empty = { ctor:"_Array", height:0, table:new Array() };
+
+    function get(i, array) {
+        if (i < 0 || i >= length(array)) {
+            throw new Error("Index " + i + " is out of range. Check the length of " +
+                            "your array first or use getMaybe or getWithDefault.");
+        }
+        return unsafeGet(i, array);
+    }
+
+    function unsafeGet(i, array) {
+      for (var x = array.height; x > 0; x--) {
+        var slot = i >> (x * 5);
+        while (array.lengths[slot] <= i) {
+          slot++;
+        }
+        if (slot > 0) {
+          i -= array.lengths[slot - 1];
+        }
+        array = array.table[slot];
+      }
+      return array.table[i];
+    }
+
+    // Sets the value at the index i. Only the nodes leading to i will get
+    // copied and updated.
+    function set(i, item, array) {
+      if (i < 0 || length(array) <= i) {
+        return array;
+      }
+      return unsafeSet(i, item, array);
+    }
+
+    function unsafeSet(i, item, array) {
+      array = nodeCopy(array);
+
+      if (array.height == 0) {
+        array.table[i] = item;
+      } else {
+        var slot = getSlot(i, array);
+        if (slot > 0) {
+          i -= array.lengths[slot - 1];
+        }
+        array.table[slot] = unsafeSet(i, item, array.table[slot]);
+      }
+      return array;
+    }
+
+    function initialize(len, f) {
+      if (len == 0) { return empty; }
+      var h = Math.floor(Math.log(len)/Math.log(M));
+      return initialize_(f, h, 0, len);
+    }
+
+    function initialize_(f, h, from, to) {
+      if (h == 0) {
+        var table = new Array((to - from) % (M + 1));
+        for (var i = 0; i < table.length; i++) {
+          table[i] = f(from + i);
+        }
+        return { ctor:"_Array", height:0, table:table };
+      }
+
+      var step = Math.pow(M, h);
+      var table = new Array(Math.ceil((to - from) / step));
+      var lengths = new Array(table.length);
+      for (var i = 0; i < table.length; i++) {
+        table[i] = initialize_( f, h - 1, from + (i * step)
+                              , Math.min(from + ((i + 1) * step), to));
+        lengths[i] = length(table[i]) + (i > 0 ? lengths[i-1] : 0);
+      }
+      return { ctor:"_Array", height:h, table:table, lengths:lengths };
+    }
+
+    function fromList(list) {
+      if (list == List.Nil) { return empty; }
+
+      // Allocate M sized blocks (table) and write list elements to it.
+      var table = new Array(M);
+      var nodes = new Array();
+      var i = 0;
+
+      while (list.ctor !== '[]') {
+        table[i] = list._0;
+        list = list._1;
+        i++;
+
+        // table is full, so we can push a leaf containing it into the
+        // next node.
+        if (i == M) {
+          fromListPush({ ctor:"_Array", height:0, table:table }
+                      , nodes);
+          table = new Array(M);
+          i = 0;
+        }
+      }
+
+      // Maybe there is something left on the table.
+      if (i > 0) {
+        fromListPush({ ctor:"_Array", height:0, table:table.splice(0,i) }
+                    , nodes);
+      }
+
+      // Go through all of the nodes and eventually push them into higher nodes.
+      for (var h = 0; h < nodes.length - 1; h++) {
+        if (nodes[h].table.length > 0) {
+          fromListPush(nodes[h], nodes);
+        }
+      }
+
+      var head = nodes[nodes.length - 1];
+      if (head.height > 0 && head.table.length == 1) {
+        return head.table[0];
+      } else {
+        return head;
+      }
+    }
+
+    // Push a node into a higher node as a child.
+    function fromListPush(toPush, nodes) {
+      var h = toPush.height;
+
+      // Maybe the node on this height does not exist.
+      if (nodes.length == h) {
+        nodes.push({ ctor:"_Array", height:h + 1
+                                  , table:new Array()
+                                  , lengths:new Array() });
+      }
+
+      nodes[h].table.push(toPush);
+      var len = length(toPush);
+      if (nodes[h].lengths.length > 0) {
+        len += nodes[h].lengths[nodes[h].lengths.length - 1];
+      }
+      nodes[h].lengths.push(len);
+
+      if (nodes[h].table.length == M) {
+        fromListPush(nodes[h], nodes);
+        nodes[h] = { ctor:"_Array", height:h + 1
+                                  , table:new Array()
+                                  , lengths:new Array() };
+      }
+    }
+
+    // Pushes an item via push_ to the bottom right of a tree.
+    function push(item, a) {
+      var pushed = push_(item, a);
+      if (pushed !== null) {
+        return pushed;
+      }
+
+      var newTree = create(item, a.height);
+      return siblise(a, newTree);
+    }
+
+    // Recursively tries to push an item to the bottom-right most
+    // tree possible. If there is no space left for the item,
+    // null will be returned.
+    function push_(item, a) {
+      // Handle resursion stop at leaf level.
+      if (a.height == 0) {
+        if (a.table.length < M) {
+          var newA = { ctor:"_Array", height:0, table:a.table.slice() };
+          newA.table.push(item);
+          return newA;
+        } else {
+          return null;
+        }
+      }
+
+      // Recursively push
+      var pushed = push_(item, botRight(a));
+
+      // There was space in the bottom right tree, so the slot will
+      // be updated.
+      if (pushed != null) {
+        var newA = nodeCopy(a);
+        newA.table[newA.table.length - 1] = pushed;
+        newA.lengths[newA.lengths.length - 1]++;
+        return newA
+      }
+
+      // When there was no space left, check if there is space left
+      // for a new slot with a tree which contains only the item
+      // at the bottom.
+      if (a.table.length < M) {
+        var newSlot = create(item, a.height - 1);
+        var newA = nodeCopy(a);
+        newA.table.push(newSlot);
+        newA.lengths.push(newA.lengths[newA.lengths.length - 1] + length(newSlot));
+        return newA
+      } else {
+        return null;
+      }
+    }
+
+    // Converts an array into a list of elements.
+    function toList(a) {
+      return toList_(List.Nil, a);
+    }
+
+    function toList_(list, a) {
+      for (var i = a.table.length - 1; i >= 0; i--) {
+        list = a.height == 0 ? List.Cons(a.table[i], list) : toList_(list, a.table[i]);
+      }
+      return list;
+    }
+
+    // Maps a function over the elements of an array.
+    function map(f, a) {
+      var newA = { ctor:"_Array", height:a.height, table:new Array(a.table) };
+      if (a.height > 0) { newA.lengths = a.lengths; }
+      for (var i = 0; i < a.table.length; i++) {
+        newA.table[i] = a.height == 0 ? f(a.table[i]) : map(f, a.table[i]);
+      }
+      return newA;
+    }
+
+    // Maps a function over the elements with their index as first argument.
+    function indexedMap(f, a) {
+      return indexedMap_(f, a, 0);
+    }
+
+    function indexedMap_(f, a, from) {
+      var newA = { ctor:"_Array", height:a.height, table:new Array(a.table) };
+      if (a.height > 0) { newA.lengths = a.lengths; }
+      for (var i = 0; i < a.table.length; i++) {
+        newA.table[i] = a.height == 0 ? A2(f, from + i, a.table[i])
+                                      : indexedMap_( f, a.table[i]
+                                                   , i == 0 ? 0 : a.lengths[i - 1]);
+      }
+      return newA;
+    }
+
+    function foldl(f, b, a) {
+      if (a.height == 0) {
+        for (var i = 0; i < a.table.length; i++) {
+          b = A2(f, a.table[i], b);
+        }
+      } else {
+        for (var i = 0; i < a.table.length; i++) {
+          b = foldl(f, b, a.table[i]);
+        }
+      }
+      return b;
+    }
+
+    function foldr(f, b, a) {
+      if (a.height == 0) {
+        for (var i = a.table.length; i--; ) {
+          b = A2(f, a.table[i], b);
+        }
+      } else {
+        for (var i = a.table.length; i--; ) {
+          b = foldl(f, b, a.table[i]);
+        }
+      }
+      return b;
+    }
+
+    // TODO: currently, it slices the right, then the left. This can be
+    // optimized.
+    function slice(from, to, a) {
+      if (from < 0) { from += length(a); }
+      if (to < 0)   { to += length(a); }
+      return sliceLeft(from, sliceRight(to, a));
+    }
+
+    function sliceRight(to, a) {
+      if (to == length(a)) {
+        return a;
+      }
+
+      // Handle leaf level.
+      if (a.height == 0) {
+        var newA = { ctor:"_Array", height:0 };
+        newA.table = a.table.slice(0, to);
+        return newA;
+      }
+
+      // Slice the right recursively.
+      var right = getSlot(to, a);
+      var sliced = sliceRight(to - (right > 0 ? a.lengths[right - 1] : 0), a.table[right]);
+
+      // Maybe the a node is not even needed, as sliced contains the whole slice.
+      if (right == 0) {
+        return sliced;
+      }
+
+      // Create new node.
+      var newA = { ctor:"_Array", height:a.height
+                                , table:a.table.slice(0, right)
+                                , lengths:a.lengths.slice(0, right) };
+      if (sliced.table.length > 0) {
+        newA.table[right] = sliced;
+        newA.lengths[right] = length(sliced) + (right > 0 ? newA.lengths[right - 1] : 0);
+      }
+      return newA;
+    }
+
+    function sliceLeft(from, a) {
+      if (from == 0) {
+        return a;
+      }
+
+      // Handle leaf level.
+      if (a.height == 0) {
+        var newA = { ctor:"_Array", height:0 };
+        newA.table = a.table.slice(from, a.table.length + 1);
+        return newA;
+      }
+
+      // Slice the left recursively.
+      var left = getSlot(from, a);
+      var sliced = sliceLeft(from - (left > 0 ? a.lengths[left - 1] : 0), a.table[left]);
+
+      // Maybe the a node is not even needed, as sliced contains the whole slice.
+      if (left == a.table.length - 1) {
+        return sliced;
+      }
+
+      // Create new node.
+      var newA = { ctor:"_Array", height:a.height
+                                , table:a.table.slice(left, a.table.length + 1)
+                                , lengths:new Array(a.table.length - left) };
+      newA.table[0] = sliced;
+      var len = 0;
+      for (var i = 0; i < newA.table.length; i++) {
+        len += length(newA.table[i]);
+        newA.lengths[i] = len;
+      }
+
+      return newA;
+    }
+
+    // Appends two trees.
+    function append(a,b) {
+      if (a.table.length === 0) {
+        return b;
+      }
+      if (b.table.length === 0) {
+        return a;
+      }
+
+      var c = append_(a, b);
+
+      // Check if both nodes can be crunshed together.
+      if (c[0].table.length + c[1].table.length <= M) {
+        if (c[0].table.length === 0) {
+          return c[1];
+        }
+        if (c[1].table.length === 0) {
+          return c[0];
+        }
+
+        // Adjust .table and .lengths
+        c[0].table = c[0].table.concat(c[1].table);
+        if (c[0].height > 0) {
+          var len = length(c[0]);
+          for (var i = 0; i < c[1].lengths.length; i++) {
+            c[1].lengths[i] += len;
+          }
+          c[0].lengths = c[0].lengths.concat(c[1].lengths);
+        }
+
+        return c[0];
+      }
+
+      if (c[0].height > 0) {
+        var toRemove = calcToRemove(a, b);
+        if (toRemove > E) {
+          c = shuffle(c[0], c[1], toRemove);
+        }
+      }
+
+      return siblise(c[0], c[1]);
+    }
+
+    // Returns an array of two nodes; right and left. One node _may_ be empty.
+    function append_(a, b) {
+      if (a.height === 0 && b.height === 0) {
+        return [a, b];
+      }
+
+      if (a.height !== 1 || b.height !== 1) {
+        if (a.height === b.height) {
+          a = nodeCopy(a);
+          b = nodeCopy(b);
+          var appended = append_(botRight(a), botLeft(b));
+
+          insertRight(a, appended[1]);
+          insertLeft(b, appended[0]);
+        } else if (a.height > b.height) {
+          a = nodeCopy(a);
+          var appended = append_(botRight(a), b);
+
+          insertRight(a, appended[0]);
+          b = parentise(appended[1], appended[1].height + 1);
+        } else {
+          b = nodeCopy(b);
+          var appended = append_(a, botLeft(b));
+
+          var left = appended[0].table.length === 0 ? 0 : 1;
+          var right = left === 0 ? 1 : 0;
+          insertLeft(b, appended[left]);
+          a = parentise(appended[right], appended[right].height + 1);
+        }
+      }
+
+      // Check if balancing is needed and return based on that.
+      if (a.table.length === 0 || b.table.length === 0) {
+        return [a,b];
+      }
+
+      var toRemove = calcToRemove(a, b);
+      if (toRemove <= E) {
+        return [a,b];
+      }
+      return shuffle(a, b, toRemove);
+    }
+
+    // Helperfunctions for append_. Replaces a child node at the side of the parent.
+    function insertRight(parent, node) {
+      var index = parent.table.length - 1;
+      parent.table[index] = node;
+      parent.lengths[index] = length(node)
+      parent.lengths[index] += index > 0 ? parent.lengths[index - 1] : 0;
+    }
+
+    function insertLeft(parent, node) {
+      if (node.table.length > 0) {
+        parent.table[0] = node;
+        parent.lengths[0] = length(node);
+
+        var len = length(parent.table[0]);
+        for (var i = 1; i < parent.lengths.length; i++) {
+          len += length(parent.table[i]);
+          parent.lengths[i] = len;
+        }
+      } else {
+        parent.table.shift();
+        for (var i = 1; i < parent.lengths.length; i++) {
+          parent.lengths[i] = parent.lengths[i] - parent.lengths[0];
+        }
+        parent.lengths.shift();
+      }
+    }
+
+    // Returns the extra search steps for E. Refer to the paper.
+    function calcToRemove(a, b) {
+      var subLengths = 0;
+      for (var i = 0; i < a.table.length; i++) {
+        subLengths += a.table[i].table.length;
+      }
+      for (var i = 0; i < b.table.length; i++) {
+        subLengths += b.table[i].table.length;
+      }
+
+      var toRemove = a.table.length + b.table.length
+      return toRemove - (Math.floor((subLengths - 1) / M) + 1);
+    }
+
+    // get2, set2 and saveSlot are helpers for accessing elements over two arrays.
+    function get2(a, b, index) {
+      return index < a.length ? a[index] : b[index - a.length];
+    }
+
+    function set2(a, b, index, value) {
+      if (index < a.length) {
+        a[index] = value;
+      } else {
+        b[index - a.length] = value;
+      }
+    }
+
+    function saveSlot(a, b, index, slot) {
+      set2(a.table, b.table, index, slot);
+
+      var l = (index == 0 || index == a.lengths.length) ?
+                0 : get2(a.lengths, a.lengths, index - 1);
+      set2(a.lengths, b.lengths, index, l + length(slot));
+    }
+
+    // Creates a node or leaf with a given length at their arrays for perfomance.
+    // Is only used by shuffle.
+    function createNode(h, length) {
+      if (length < 0) { length = 0; }
+      var a = { ctor:"_Array", height:h, table:new Array(length) };
+      if (h > 0) {
+        a.lengths = new Array(length);
+      }
+      return a;
+    }
+
+    // Returns an array of two balanced nodes.
+    function shuffle(a, b, toRemove) {
+      var newA = createNode(a.height, Math.min(M, a.table.length + b.table.length - toRemove));
+      var newB = createNode(a.height, newA.table.length - (a.table.length + b.table.length - toRemove));
+
+      // Skip the slots with size M. More precise: copy the slot references
+      // to the new node
+      var read = 0;
+      while (get2(a.table, b.table, read).table.length % M == 0) {
+        set2(newA.table, newB.table, read, get2(a.table, b.table, read));
+        set2(newA.lengths, newB.lengths, read, get2(a.lengths, b.lengths, read));
+        read++;
+      }
+
+      // Pulling items from left to right, caching in a slot before writing
+      // it into the new nodes.
+      var write = read;
+      var slot = new createNode(a.height - 1, 0);
+      var from = 0;
+
+      // If the current slot is still containing data, then there will be at
+      // least one more write, so we do not break this loop yet.
+      while (read - write - (slot.table.length > 0 ? 1 : 0) < toRemove) {
+        // Find out the max possible items for copying.
+        var source = get2(a.table, b.table, read);
+        var to = Math.min(M - slot.table.length, source.table.length)
+
+        // Copy and adjust size table.
+        slot.table = slot.table.concat(source.table.slice(from, to));
+        if (slot.height > 0) {
+          var len = slot.lengths.length;
+          for (var i = len; i < len + to - from; i++) {
+            slot.lengths[i] = length(slot.table[i]);
+            slot.lengths[i] += (i > 0 ? slot.lengths[i - 1] : 0);
+          }
+        }
+
+        from += to;
+
+        // Only proceed to next slots[i] if the current one was
+        // fully copied.
+        if (source.table.length <= to) {
+          read++; from = 0;
+        }
+
+        // Only create a new slot if the current one is filled up.
+        if (slot.table.length == M) {
+          saveSlot(newA, newB, write, slot);
+          slot = createNode(a.height - 1,0);
+          write++;
+        }
+      }
+
+      // Cleanup after the loop. Copy the last slot into the new nodes.
+      if (slot.table.length > 0) {
+        saveSlot(newA, newB, write, slot);
+        write++;
+      }
+
+      // Shift the untouched slots to the left
+      while (read < a.table.length + b.table.length ) {
+        saveSlot(newA, newB, write, get2(a.table, b.table, read));
+        read++; write++;
+      }
+
+      return [newA, newB];
+    }
+
+    // Navigation functions
+    function botRight(a) { return a.table[a.table.length - 1]; }
+    function botLeft(a)  { return a.table[0]; }
+
+    // Copies a node for updating. Note that you should not use this if
+    // only updating only one of "table" or "lengths" for performance reasons.
+    function nodeCopy(a) {
+      var newA = { ctor:"_Array", height:a.height
+                                , table:a.table.slice() };
+      if (a.height > 0) { newA.lengths = a.lengths.slice(); }
+      return newA;
+    }
+
+    // Returns how many items are in the tree.
+    function length(array) {
+      if (array.height == 0) {
+        return array.table.length;
+      } else {
+        return array.lengths[array.lengths.length - 1];
+      }
+    }
+
+    // Calculates in which slot of "table" the item probably is, then
+    // find the exact slot via forward searching in  "lengths". Returns the index.
+    function getSlot(i, a) {
+      var slot = i >> (5 * a.height);
+      while (a.lengths[slot] <= i) {
+        slot++;
+      }
+      return slot;
+    }
+
+    // Recursively creates a tree with a given height containing
+    // only the given item.
+    function create(item, h) {
+      if (h == 0) {
+        return { ctor:"_Array", height:0
+                              , table:[item] };
+      } else {
+        return { ctor:"_Array", height:h
+                              , table:[create(item, h - 1)]
+                              , lengths:[1] };
+      }
+    }
+
+    // Recursively creates a tree that contains the given tree.
+    function parentise(tree, h) {
+      if (h == tree.height) {
+        return tree;
+      } else {
+        return { ctor:"_Array", height:h
+                              , table:[parentise(tree, h - 1)]
+                              , lengths:[length(tree)] };
+      }
+    }
+
+    // Emphasizes blood brotherhood beneath two trees.
+    function siblise(a, b) {
+      return { ctor:"_Array", height:a.height + 1
+                            , table:[a, b]
+                            , lengths:[length(a), length(a) + length(b)] };
+    }
+
+    function toJSArray(a) {
+      var jsArray = new Array(length(a));
+      toJSArray_(jsArray, 0, a);
+      return jsArray;
+    }
+
+    function toJSArray_(jsArray, i, a) {
+      for (var t = 0; t < a.table.length; t++) {
+        if (a.height == 0) {
+          jsArray[i + t] = a.table[t];
+        } else {
+          var inc = t == 0 ? 0 : a.lengths[t - 1];
+          toJSArray_(jsArray, i + inc, a.table[t]);
+        }
+      }
+    }
+
+    function fromJSArray(jsArray) {
+      if (jsArray.length == 0) { return empty; }
+      var h = Math.floor(Math.log(jsArray.length) / Math.log(M));
+      return fromJSArray_(jsArray, h, 0, jsArray.length);
+    }
+
+    function fromJSArray_(jsArray, h, from, to) {
+      if (h == 0) {
+        return { ctor:"_Array", height:0
+                              , table:jsArray.slice(from, to) };
+      }
+
+      var step = Math.pow(M, h);
+      var table = new Array(Math.ceil((to - from) / step));
+      var lengths = new Array(table.length);
+      for (var i = 0; i < table.length; i++) {
+        table[i] = fromJSArray_( jsArray, h - 1, from + (i * step)
+                               , Math.min(from + ((i + 1) * step), to));
+        lengths[i] = length(table[i]) + (i > 0 ? lengths[i-1] : 0);
+      }
+      return { ctor:"_Array", height:h, table:table, lengths:lengths };
+    }
+
+    Elm.Native.Array.values = {
+      empty:empty,
+      fromList:fromList,
+      toList:toList,
+      initialize:F2(initialize),
+      append:F2(append),
+      push:F2(push),
+      slice:F3(slice),
+      get:F2(get),
+      set:F3(set),
+      map:F2(map),
+      indexedMap:F2(indexedMap),
+      foldl:F3(foldl),
+      foldr:F3(foldr),
+      length:length,
+
+      toJSArray:toJSArray,
+      fromJSArray:fromJSArray
+    };
+
+    return elm.Native.Array.values = Elm.Native.Array.values;
+}
+
+
+Elm.Native.Basics = {};
+Elm.Native.Basics.make = function(elm) {
+  elm.Native = elm.Native || {};
+  elm.Native.Basics = elm.Native.Basics || {};
+  if (elm.Native.Basics.values) return elm.Native.Basics.values;
+
+  var Utils = Elm.Native.Utils.make(elm);
+
+  function div(a, b) {
+      return (a/b)|0;
+  }
+  function rem(a, b) {
+      return a % b;
+  }
+  function mod(a, b) {
+        if (b === 0) {
+            throw new Error("Cannot perform mod 0. Division by zero error.");
+        }
+        var r = a % b;
+        var m = a === 0 ? 0 : (b > 0 ? (a >= 0 ? r : r+b) : -mod(-a,-b));
+
+        return m === b ? 0 : m;
+  }
+  function logBase(base, n) {
+      return Math.log(n) / Math.log(base);
+  }
+  function negate(n) {
+      return -n;
+  }
+  function abs(n) {
+      return n < 0 ? -n : n;
+  }
+
+  function min(a, b) {
+      return Utils.cmp(a,b) < 0 ? a : b;
+  }
+  function max(a, b) {
+      return Utils.cmp(a,b) > 0 ? a : b;
+  }
+  function clamp(lo, hi, n) {
+      return Utils.cmp(n,lo) < 0 ? lo : Utils.cmp(n,hi) > 0 ? hi : n;
+  }
+
+  function xor(a, b) {
+      return a !== b;
+  }
+  function not(b) {
+      return !b;
+  }
+  function isInfinite(n) {
+      return n === Infinity || n === -Infinity
+  }
+
+  function truncate(n) {
+      return n|0;
+  }
+
+  function degrees(d) {
+      return d * Math.PI / 180;
+  }
+  function turns(t) {
+      return 2 * Math.PI * t;
+  }
+  function fromPolar(point) {
+      var r = point._0;
+      var t = point._1;
+      return Utils.Tuple2(r * Math.cos(t), r * Math.sin(t));
+  }
+  function toPolar(point) {
+      var x = point._0;
+      var y = point._1;
+      return Utils.Tuple2(Math.sqrt(x * x + y * y), Math.atan2(y,x));
+  }
+
+  var basics = {
+      div: F2(div),
+      rem: F2(rem),
+      mod: F2(mod),
+
+      pi: Math.PI,
+      e: Math.E,
+      cos: Math.cos,
+      sin: Math.sin,
+      tan: Math.tan,
+      acos: Math.acos,
+      asin: Math.asin,
+      atan: Math.atan,
+      atan2: F2(Math.atan2),
+
+      degrees:  degrees,
+      turns:  turns,
+      fromPolar:  fromPolar,
+      toPolar:  toPolar,
+
+      sqrt: Math.sqrt,
+      logBase: F2(logBase),
+      negate: negate,
+      abs: abs,
+      min: F2(min),
+      max: F2(max),
+      clamp: F3(clamp),
+      compare: Utils.compare,
+
+      xor: F2(xor),
+      not: not,
+
+      truncate: truncate,
+      ceiling: Math.ceil,
+      floor: Math.floor,
+      round: Math.round,
+      toFloat: function(x) { return x; },
+      isNaN: isNaN,
+      isInfinite: isInfinite
+  };
+
+  return elm.Native.Basics.values = basics;
+};
+
+Elm.Native.Char = {};
+Elm.Native.Char.make = function(elm) {
+    elm.Native = elm.Native || {};
+    elm.Native.Char = elm.Native.Char || {};
+    if (elm.Native.Char.values) return elm.Native.Char.values;
+
+    var Utils = Elm.Native.Utils.make(elm);
+
+    function isBetween(lo,hi) { return function(chr) {
+	var c = chr.charCodeAt(0);
+	return lo <= c && c <= hi;
+    };
+                              }
+    var isDigit = isBetween('0'.charCodeAt(0),'9'.charCodeAt(0));
+    var chk1 = isBetween('a'.charCodeAt(0),'f'.charCodeAt(0));
+    var chk2 = isBetween('A'.charCodeAt(0),'F'.charCodeAt(0));
+
+    return elm.Native.Char.values = {
+        fromCode : function(c) { return String.fromCharCode(c); },
+        toCode   : function(c) { return c.toUpperCase().charCodeAt(0); },
+        toUpper  : function(c) { return Utils.chr(c.toUpperCase()); },
+        toLower  : function(c) { return Utils.chr(c.toLowerCase()); },
+        toLocaleUpper : function(c) { return Utils.chr(c.toLocaleUpperCase()); },
+        toLocaleLower : function(c) { return Utils.chr(c.toLocaleLowerCase()); },
+        isLower    : isBetween('a'.charCodeAt(0),'z'.charCodeAt(0)),
+        isUpper    : isBetween('A'.charCodeAt(0),'Z'.charCodeAt(0)),
+        isDigit    : isDigit,
+        isOctDigit : isBetween('0'.charCodeAt(0),'7'.charCodeAt(0)),
+        isHexDigit : function(c) { return isDigit(c) || chk1(c) || chk2(c); }
+    };
+};
+
+Elm.Native.Color = {};
+Elm.Native.Color.make = function(elm) {
+    elm.Native = elm.Native || {};
+    elm.Native.Color = elm.Native.Color || {};
+    if (elm.Native.Color.values) return elm.Native.Color.values;
+
+    function toCss(c) {
+        var format = '';
+        var colors = '';
+        if (c.ctor === 'RGBA') {
+            format = 'rgb';
+            colors = c._0 + ', ' + c._1 + ', ' + c._2;
+        } else {
+            format = 'hsl';
+            colors = (c._0 * 180 / Math.PI) + ', ' +
+                     (c._1 * 100) + '%, ' +
+                     (c._2 * 100) + '%';
+        }
+        if (c._3 === 1) {
+            return format + '(' + colors + ')';
+        } else {
+            return format + 'a(' + colors + ', ' + c._3 + ')';
+        }
+    }
+
+    return elm.Native.Color.values = {
+        toCss:toCss
+    };
+
+};
+
+Elm.Native.Debug = {};
+Elm.Native.Debug.make = function(elm) {
+    elm.Native = elm.Native || {};
+    elm.Native.Debug = elm.Native.Debug || {};
+    if (elm.Native.Debug.values) return elm.Native.Debug.values;
+    if ('values' in Elm.Native.Debug)
+        return elm.Native.Debug.values = Elm.Native.Debug.values;
+
+    var toString = Elm.Native.Show.make(elm).toString;
+    var replace = Elm.Native.Utils.make(elm).replace;
+
+    function log(tag, value) {
+        var msg = tag + ': ' + toString(value);
+        var process = process || {};
+        if (process.stdout) {
+            process.stdout.write(msg);
+        } else {
+            console.log(msg);
+        }
+        return value;
+    }
+
+    function crash(message) {
+        throw new Error(message);
+    }
+
+    function tracePath(debugId, form) {
+        return replace([["debugTracePathId",debugId]], form);
+    }
+
+    function WatchTracker() {
+        this.frames = [{}];
+        this.clear = function() {
+            this.watches = {};
+        };
+        this.pushFrame = function() {
+            var lastFrame = this.frames[this.frames.length - 1];
+            this.frames.push(lastFrame);
+        }
+        this.notify = function(tag, value) {
+            this.frames[this.frames.length - 1][tag] = value;
+        };
+    }
+    var watchTracker = new WatchTracker();
+
+    function watch(tag, value) {
+        watchTracker.notify(tag, value);
+        return value;
+    }
+
+    function watchSummary(tag, f, value) {
+        watchTracker.notify(tag, f(value));
+        return value;
+    }
+
+    Elm.Native.Debug.values = {
+        crash: crash,
+        tracePath: F2(tracePath),
+        log: F2(log),
+        watch: F2(watch),
+        watchSummary:F3(watchSummary),
+        watchTracker: watchTracker
+    };
+    return elm.Native.Debug.values = Elm.Native.Debug.values;
+};
+
+
+// setup
+Elm.Native = Elm.Native || {};
+Elm.Native.Graphics = Elm.Native.Graphics || {};
+Elm.Native.Graphics.Collage = Elm.Native.Graphics.Collage || {};
+
+// definition
+Elm.Native.Graphics.Collage.make = function(localRuntime) {
+    'use strict';
+
+    // attempt to short-circuit
+    if ('values' in Elm.Native.Graphics.Collage) {
+        return Elm.Native.Graphics.Collage.values;
+    }
+
+    // okay, we cannot short-ciruit, so now we define everything
+    var Color = Elm.Native.Color.make(localRuntime);
+    var List = Elm.Native.List.make(localRuntime);
+    var Transform = Elm.Transform2D.make(localRuntime);
+
+    var Element = Elm.Graphics.Element.make(localRuntime);
+    var NativeElement = Elm.Native.Graphics.Element.make(localRuntime);
+
+
+    function trace(ctx, path) {
+        var points = List.toArray(path);
+        var i = points.length - 1;
+        if (i <= 0) {
+            return;
+        }
+        ctx.moveTo(points[i]._0, points[i]._1);
+        while (i--) {
+            ctx.lineTo(points[i]._0, points[i]._1);
+        }
+        if (path.closed) {
+            i = points.length - 1;
+            ctx.lineTo(points[i]._0, points[i]._1);
+        }
+    }
+
+    function line(ctx,style,path) {
+        (style.dashing.ctor === '[]')
+            ? trace(ctx, path)
+            : customLineHelp(ctx, style, path);
+        ctx.scale(1,-1);
+        ctx.stroke();
+    }
+
+    function customLineHelp(ctx, style, path) {
+        var points = List.toArray(path);
+        if (path.closed) {
+            points.push(points[0]);
+        }
+        var pattern = List.toArray(style.dashing);
+        var i = points.length - 1;
+        if (i <= 0) {
+            return;
+        }
+        var x0 = points[i]._0, y0 = points[i]._1;
+        var x1=0, y1=0, dx=0, dy=0, remaining=0, nx=0, ny=0;
+        var pindex = 0, plen = pattern.length;
+        var draw = true, segmentLength = pattern[0];
+        ctx.moveTo(x0,y0);
+        while (i--) {
+            x1 = points[i]._0; y1 = points[i]._1;
+            dx = x1 - x0; dy = y1 - y0;
+            remaining = Math.sqrt(dx * dx + dy * dy);
+            while (segmentLength <= remaining) {
+                x0 += dx * segmentLength / remaining;
+                y0 += dy * segmentLength / remaining;
+                ctx[draw ? 'lineTo' : 'moveTo'](x0, y0);
+                // update starting position
+                dx = x1 - x0; dy = y1 - y0;
+                remaining = Math.sqrt(dx * dx + dy * dy);
+                // update pattern
+                draw = !draw;
+                pindex = (pindex + 1) % plen;
+                segmentLength = pattern[pindex];
+            }
+            if (remaining > 0) {
+                ctx[draw ? 'lineTo' : 'moveTo'](x1, y1);
+                segmentLength -= remaining;
+            }
+            x0 = x1; y0 = y1;
+        }
+    }
+
+    function drawLine(ctx, style, path) {
+        ctx.lineWidth = style.width;
+
+        var cap = style.cap.ctor;
+        ctx.lineCap = cap === 'Flat'
+            ? 'butt'
+            : cap === 'Round'
+                ? 'round'
+                : 'square';
+
+        var join = style.join.ctor;
+        ctx.lineJoin = join === 'Smooth'
+            ? 'round'
+            : join === 'Sharp'
+                ? 'miter'
+                : 'bevel';
+
+        ctx.miterLimit = style.join._0 || 10;
+        ctx.strokeStyle = Color.toCss(style.color);
+
+        return line(ctx, style, path);
+    }
+
+    function texture(redo, ctx, src) {
+        var img = new Image();
+        img.src = src;
+        img.onload = redo;
+        return ctx.createPattern(img, 'repeat');
+    }
+
+    function gradient(ctx, grad) {
+        var g;
+        var stops = [];
+        if (grad.ctor === 'Linear') {
+            var p0 = grad._0, p1 = grad._1;
+            g = ctx.createLinearGradient(p0._0, -p0._1, p1._0, -p1._1);
+            stops = List.toArray(grad._2);
+        } else {
+            var p0 = grad._0, p2 = grad._2;
+            g = ctx.createRadialGradient(p0._0, -p0._1, grad._1, p2._0, -p2._1, grad._3);
+            stops = List.toArray(grad._4);
+        }
+        var len = stops.length;
+        for (var i = 0; i < len; ++i) {
+            var stop = stops[i];
+            g.addColorStop(stop._0, Color.toCss(stop._1));
+        }
+        return g;
+    }
+
+    function drawShape(redo, ctx, style, path) {
+        trace(ctx, path);
+        var sty = style.ctor;
+        ctx.fillStyle = sty === 'Solid'
+            ? Color.toCss(style._0)
+            : sty === 'Texture'
+                ? texture(redo, ctx, style._0)
+                : gradient(ctx, style._0);
+
+        ctx.scale(1,-1);
+        ctx.fill();
+    }
+
+    function drawImage(redo, ctx, form) {
+        var img = new Image();
+        img.onload = redo;
+        img.src = form._3;
+        var w = form._0,
+            h = form._1,
+            pos = form._2,
+            srcX = pos._0,
+            srcY = pos._1,
+            srcW = w,
+            srcH = h,
+            destX = -w/2,
+            destY = -h/2,
+            destW = w,
+            destH = h;
+
+        ctx.scale(1,-1);
+        ctx.drawImage(img, srcX, srcY, srcW, srcH, destX, destY, destW, destH);
+    }
+
+    function renderForm(redo, ctx, form) {
+        ctx.save();
+        var x = form.x, y = form.y, theta = form.theta, scale = form.scale;
+        if (x !== 0 || y !== 0) ctx.translate(x, y);
+        if (theta !== 0) ctx.rotate(theta);
+        if (scale !== 1) ctx.scale(scale,scale);
+        if (form.alpha !== 1) ctx.globalAlpha = ctx.globalAlpha * form.alpha;
+        ctx.beginPath();
+        var f = form.form;
+        switch(f.ctor) {
+        case 'FPath' : drawLine(ctx, f._0, f._1); break;
+        case 'FImage': drawImage(redo, ctx, f); break;
+        case 'FShape':
+          if (f._0.ctor === 'Line') {
+            f._1.closed = true;
+            drawLine(ctx, f._0._0, f._1);
+          } else {
+            drawShape(redo, ctx, f._0._0, f._1);
+          }
+        break;
+        }
+        ctx.restore();
+    }
+
+    function formToMatrix(form) {
+       var scale = form.scale;
+       var matrix = A6( Transform.matrix, scale, 0, 0, scale, form.x, form.y );
+
+       var theta = form.theta
+       if (theta !== 0) {
+           matrix = A2( Transform.multiply, matrix, Transform.rotation(theta) );
+       }
+
+       return matrix;
+    }
+
+    function str(n) {
+        if (n < 0.00001 && n > -0.00001) return 0;
+        return n;
+    }
+
+    function makeTransform(w, h, form, matrices) {
+        var props = form.form._0.props;
+        var m = A6( Transform.matrix, 1, 0, 0, -1,
+                    (w - props.width ) / 2,
+                    (h - props.height) / 2 );
+        var len = matrices.length;
+        for (var i = 0; i < len; ++i) {
+            m = A2( Transform.multiply, m, matrices[i] );
+        }
+        m = A2( Transform.multiply, m, formToMatrix(form) );
+
+        return 'matrix(' + str( m[0]) + ', ' + str( m[3]) + ', ' +
+                           str(-m[1]) + ', ' + str(-m[4]) + ', ' +
+                           str( m[2]) + ', ' + str( m[5]) + ')';
+    }
+
+    function stepperHelp(list) {
+        var arr = List.toArray(list);
+        var i = 0;
+        function peekNext() {
+            return i < arr.length ? arr[i].form.ctor : '';
+        }
+        // assumes that there is a next element
+        function next() {
+            var out = arr[i];
+            ++i;
+            return out;
+        }
+        return {
+            peekNext:peekNext,
+            next:next
+        };
+    }
+
+    function formStepper(forms) {
+        var ps = [stepperHelp(forms)];
+        var matrices = [];
+        var alphas = [];
+        function peekNext() {
+            var len = ps.length;
+            var formType = '';
+            for (var i = 0; i < len; ++i ) {
+                if (formType = ps[i].peekNext()) return formType;
+            }
+            return '';
+        }
+        // assumes that there is a next element
+        function next(ctx) {
+            while (!ps[0].peekNext()) {
+                ps.shift();
+                matrices.pop();
+                alphas.shift();
+                if (ctx) { ctx.restore(); }
+            }
+            var out = ps[0].next();
+            var f = out.form;
+            if (f.ctor === 'FGroup') {
+                ps.unshift(stepperHelp(f._1));
+                var m = A2(Transform.multiply, f._0, formToMatrix(out));
+                ctx.save();
+                ctx.transform(m[0], m[3], m[1], m[4], m[2], m[5]);
+                matrices.push(m);
+
+                var alpha = (alphas[0] || 1) * out.alpha;
+                alphas.unshift(alpha);
+                ctx.globalAlpha = alpha;
+            }
+            return out;
+        }
+        function transforms() { return matrices; }
+        function alpha() { return alphas[0] || 1; }
+        return {
+            peekNext:peekNext,
+            next:next,
+            transforms:transforms,
+            alpha:alpha
+        };
+    }
+
+    function makeCanvas(w,h) {
+        var canvas = NativeElement.createNode('canvas');
+        canvas.style.width  = w + 'px';
+        canvas.style.height = h + 'px';
+        canvas.style.display = "block";
+        canvas.style.position = "absolute";
+        canvas.width  = w;
+        canvas.height = h;
+        return canvas;
+    }
+
+    function render(model) {
+        var div = NativeElement.createNode('div');
+        div.style.overflow = 'hidden';
+        div.style.position = 'relative';
+        update(div, model, model);
+        return div;
+    }
+
+    function nodeStepper(w,h,div) {
+        var kids = div.childNodes;
+        var i = 0;
+        function transform(transforms, ctx) {
+            ctx.translate(w/2, h/2);
+            ctx.scale(1,-1);
+            var len = transforms.length;
+            for (var i = 0; i < len; ++i) {
+                var m = transforms[i];
+                ctx.save();
+                ctx.transform(m[0], m[3], m[1], m[4], m[2], m[5]);
+            }
+            return ctx;
+        }
+        function nextContext(transforms) {
+            while (i < kids.length) {
+                var node = kids[i];
+                if (node.getContext) {
+                    node.width = w;
+                    node.height = h;
+                    node.style.width = w + 'px';
+                    node.style.height = h + 'px';
+                    ++i;
+                    return transform(transforms, node.getContext('2d'));
+                }
+                div.removeChild(node);
+            }
+            var canvas = makeCanvas(w,h);
+            div.appendChild(canvas);
+            // we have added a new node, so we must step our position
+            ++i;
+            return transform(transforms, canvas.getContext('2d'));
+        }
+        function addElement(matrices, alpha, form) {
+            var kid = kids[i];
+            var elem = form.form._0;
+
+            var node = (!kid || kid.getContext)
+                ? NativeElement.render(elem)
+                : NativeElement.update(kid, kid.oldElement, elem);
+
+            node.style.position = 'absolute';
+            node.style.opacity = alpha * form.alpha * elem.props.opacity;
+            NativeElement.addTransform(node.style, makeTransform(w, h, form, matrices));
+            node.oldElement = elem;
+            ++i;
+            if (!kid) {
+                div.appendChild(node);
+            } else if (kid.getContext) {
+                div.insertBefore(node, kid);
+            }
+        }
+        function clearRest() {
+            while (i < kids.length) {
+                div.removeChild(kids[i]);
+            }
+        }
+        return { nextContext:nextContext, addElement:addElement, clearRest:clearRest };
+    }
+
+
+    function update(div, _, model) {
+        var w = model.w;
+        var h = model.h;
+
+        var forms = formStepper(model.forms);
+        var nodes = nodeStepper(w,h,div);
+        var ctx = null;
+        var formType = '';
+
+        while (formType = forms.peekNext()) {
+            // make sure we have context if we need it
+            if (ctx === null && formType !== 'FElement') {
+                ctx = nodes.nextContext(forms.transforms());
+                ctx.globalAlpha = forms.alpha();
+            }
+
+            var form = forms.next(ctx);
+            // if it is FGroup, all updates are made within formStepper when next is called.
+            if (formType === 'FElement') {
+                // update or insert an element, get a new context
+                nodes.addElement(forms.transforms(), forms.alpha(), form);
+                ctx = null;
+            } else if (formType !== 'FGroup') {
+                renderForm(function() { update(div, model, model); }, ctx, form);
+            }
+        }
+        nodes.clearRest();
+        return div;
+    }
+
+
+    function collage(w,h,forms) {
+        return A3(Element.newElement, w, h, {
+            ctor: 'Custom',
+            type: 'Collage',
+            render: render,
+            update: update,
+            model: {w:w, h:h, forms:forms}
+      	});
+    }
+
+    return Elm.Native.Graphics.Collage.values = {
+        collage:F3(collage)
+    };
+};
+
+// setup
+Elm.Native = Elm.Native || {};
+Elm.Native.Graphics = Elm.Native.Graphics || {};
+Elm.Native.Graphics.Element = Elm.Native.Graphics.Element || {};
+
+// definition
+Elm.Native.Graphics.Element.make = function(localRuntime) {
+    'use strict';
+
+    // attempt to short-circuit
+    if ('values' in Elm.Native.Graphics.Element) {
+        return Elm.Native.Graphics.Element.values;
+    }
+
+    var Color = Elm.Native.Color.make(localRuntime);
+    var List = Elm.Native.List.make(localRuntime);
+    var Utils = Elm.Native.Utils.make(localRuntime);
+
+
+    function createNode(elementType) {
+        var node = document.createElement(elementType);
+        node.style.padding = "0";
+        node.style.margin = "0";
+        return node;
+    }
+
+    function setProps(elem, node) {
+        var props = elem.props;
+
+        var element = elem.element;
+        var width = props.width - (element.adjustWidth || 0);
+        var height = props.height - (element.adjustHeight || 0);
+        node.style.width  = (width |0) + 'px';
+        node.style.height = (height|0) + 'px';
+
+        if (props.opacity !== 1) {
+            node.style.opacity = props.opacity;
+        }
+
+        if (props.color.ctor === 'Just') {
+            node.style.backgroundColor = Color.toCss(props.color._0);
+        }
+
+        if (props.tag !== '') {
+            node.id = props.tag;
+        }
+
+        if (props.hover.ctor !== '_Tuple0') {
+            addHover(node, props.hover);
+        }
+
+        if (props.click.ctor !== '_Tuple0') {
+            addClick(node, props.click);
+        }
+
+        if (props.href !== '') {
+            var anchor = createNode('a');
+            anchor.href = props.href;
+            anchor.style.display = 'block';
+            anchor.style.pointerEvents = 'auto';
+            anchor.appendChild(node);
+            node = anchor;
+        }
+
+        return node;
+    }
+
+    function addClick(e, handler) {
+        e.style.pointerEvents = 'auto';
+        e.elm_click_handler = handler;
+        function trigger(ev) {
+            e.elm_click_handler(Utils.Tuple0);
+            ev.stopPropagation();
+        }
+        e.elm_click_trigger = trigger;
+        e.addEventListener('click', trigger);
+    }
+
+    function removeClick(e, handler) {
+        if (e.elm_click_trigger) {
+            e.removeEventListener('click', e.elm_click_trigger);
+            e.elm_click_trigger = null;
+            e.elm_click_handler = null;
+        }
+    }
+
+    function addHover(e, handler) {
+        e.style.pointerEvents = 'auto';
+        e.elm_hover_handler = handler;
+        e.elm_hover_count = 0;
+
+        function over(evt) {
+            if (e.elm_hover_count++ > 0) return;
+            e.elm_hover_handler(true);
+            evt.stopPropagation();
+        }
+        function out(evt) {
+            if (e.contains(evt.toElement || evt.relatedTarget)) return;
+            e.elm_hover_count = 0;
+            e.elm_hover_handler(false);
+            evt.stopPropagation();
+        }
+        e.elm_hover_over = over;
+        e.elm_hover_out = out;
+        e.addEventListener('mouseover', over);
+        e.addEventListener('mouseout', out);
+    }
+
+    function removeHover(e) {
+        e.elm_hover_handler = null;
+        if (e.elm_hover_over) {
+            e.removeEventListener('mouseover', e.elm_hover_over);
+            e.elm_hover_over = null;
+        }
+        if (e.elm_hover_out) {
+            e.removeEventListener('mouseout', e.elm_hover_out);
+            e.elm_hover_out = null;
+        }
+    }
+
+    function image(props, img) {
+        switch (img._0.ctor) {
+        case 'Plain':   return plainImage(img._3);
+        case 'Fitted':  return fittedImage(props.width, props.height, img._3);
+        case 'Cropped': return croppedImage(img,props.width,props.height,img._3);
+        case 'Tiled':   return tiledImage(img._3);
+        }
+    }
+
+    function plainImage(src) {
+        var img = createNode('img');
+        img.src = src;
+        img.name = src;
+        img.style.display = "block";
+        return img;
+    }
+
+    function tiledImage(src) {
+        var div = createNode('div');
+        div.style.backgroundImage = 'url(' + src + ')';
+        return div;
+    }
+
+    function fittedImage(w, h, src) {
+        var div = createNode('div');
+        div.style.background = 'url(' + src + ') no-repeat center';
+        div.style.webkitBackgroundSize = 'cover';
+        div.style.MozBackgroundSize = 'cover';
+        div.style.OBackgroundSize = 'cover';
+        div.style.backgroundSize = 'cover';
+        return div;
+    }
+
+    function croppedImage(elem, w, h, src) {
+        var pos = elem._0._0;
+        var e = createNode('div');
+        e.style.overflow = "hidden";
+
+        var img = createNode('img');
+        img.onload = function() {
+            var sw = w / elem._1, sh = h / elem._2;
+            img.style.width = ((this.width * sw)|0) + 'px';
+            img.style.height = ((this.height * sh)|0) + 'px';
+            img.style.marginLeft = ((- pos._0 * sw)|0) + 'px';
+            img.style.marginTop = ((- pos._1 * sh)|0) + 'px';
+        };
+        img.src = src;
+        img.name = src;
+        e.appendChild(img);
+        return e;
+    }
+
+    function goOut(node) {
+        node.style.position = 'absolute';
+        return node;
+    }
+    function goDown(node) {
+        return node;
+    }
+    function goRight(node) {
+        node.style.styleFloat = 'left';
+        node.style.cssFloat = 'left';
+        return node;
+    }
+
+    var directionTable = {
+        DUp    : goDown,
+        DDown  : goDown,
+        DLeft  : goRight,
+        DRight : goRight,
+        DIn    : goOut,
+        DOut   : goOut
+    };
+    function needsReversal(dir) {
+        return dir == 'DUp' || dir == 'DLeft' || dir == 'DIn';
+    }
+
+    function flow(dir,elist) {
+        var array = List.toArray(elist);
+        var container = createNode('div');
+        var goDir = directionTable[dir];
+        if (goDir == goOut) {
+            container.style.pointerEvents = 'none';
+        }
+        if (needsReversal(dir)) {
+            array.reverse();
+        }
+        var len = array.length;
+        for (var i = 0; i < len; ++i) {
+            container.appendChild(goDir(render(array[i])));
+        }
+        return container;
+    }
+
+    function toPos(pos) {
+        switch(pos.ctor) {
+        case "Absolute": return  pos._0 + "px";
+        case "Relative": return (pos._0 * 100) + "%";
+        }
+    }
+
+    // must clear right, left, top, bottom, and transform
+    // before calling this function
+    function setPos(pos,elem,e) {
+        var element = elem.element;
+        var props = elem.props;
+        var w = props.width + (element.adjustWidth ? element.adjustWidth : 0);
+        var h = props.height + (element.adjustHeight ? element.adjustHeight : 0);
+
+        e.style.position = 'absolute';
+        e.style.margin = 'auto';
+        var transform = '';
+        switch(pos.horizontal.ctor) {
+        case 'P': e.style.right = toPos(pos.x); e.style.removeProperty('left'); break;
+        case 'Z': transform = 'translateX(' + ((-w/2)|0) + 'px) ';
+        case 'N': e.style.left = toPos(pos.x); e.style.removeProperty('right'); break;
+        }
+        switch(pos.vertical.ctor) {
+        case 'N': e.style.bottom = toPos(pos.y); e.style.removeProperty('top'); break;
+        case 'Z': transform += 'translateY(' + ((-h/2)|0) + 'px)';
+        case 'P': e.style.top = toPos(pos.y); e.style.removeProperty('bottom'); break;
+        }
+        if (transform !== '') {
+            addTransform(e.style, transform);
+        }
+        return e;
+    }
+
+    function addTransform(style, transform) {
+        style.transform       = transform;
+        style.msTransform     = transform;
+        style.MozTransform    = transform;
+        style.webkitTransform = transform;
+        style.OTransform      = transform;
+    }
+
+    function container(pos,elem) {
+        var e = render(elem);
+        setPos(pos, elem, e);
+        var div = createNode('div');
+        div.style.position = 'relative';
+        div.style.overflow = 'hidden';
+        div.appendChild(e);
+        return div;
+    }
+
+    function rawHtml(elem) {
+        var html = elem.html;
+        var guid = elem.guid;
+        var align = elem.align;
+
+        var div = createNode('div');
+        div.innerHTML = html;
+        div.style.visibility = "hidden";
+        if (align) {
+            div.style.textAlign = align;
+        }
+        div.style.visibility = 'visible';
+        div.style.pointerEvents = 'auto';
+        return div;
+    }
+
+    function render(elem) {
+        return setProps(elem, makeElement(elem));
+    }
+    function makeElement(e) {
+        var elem = e.element;
+        switch(elem.ctor) {
+        case 'Image':     return image(e.props, elem);
+        case 'Flow':      return flow(elem._0.ctor, elem._1);
+        case 'Container': return container(elem._0, elem._1);
+        case 'Spacer':    return createNode('div');
+        case 'RawHtml':   return rawHtml(elem);
+        case 'Custom':    return elem.render(elem.model);
+        }
+    }
+
+    function updateAndReplace(node, curr, next) {
+        var newNode = update(node, curr, next);
+        if (newNode !== node) {
+            node.parentNode.replaceChild(newNode, node);
+        }
+        return newNode;
+    }
+
+    function update(node, curr, next) {
+        var rootNode = node;
+        if (node.tagName === 'A') {
+            node = node.firstChild;
+        }
+        if (curr.props.id === next.props.id) {
+            updateProps(node, curr, next);
+            return rootNode;
+        }
+        if (curr.element.ctor !== next.element.ctor) {
+            return render(next);
+        }
+        var nextE = next.element;
+        var currE = curr.element;
+        switch(nextE.ctor) {
+        case "Spacer":
+            updateProps(node, curr, next);
+            return rootNode;
+
+        case "RawHtml":
+            // only markdown blocks have guids, so this must be a text block
+            if (nextE.guid === null) {
+                if(currE.html.valueOf() !== nextE.html.valueOf()) {
+                    node.innerHTML = nextE.html;
+                }
+                updateProps(node, curr, next);
+                return rootNode;
+            }
+            if (nextE.guid !== currE.guid) {
+                return render(next);
+            }
+            updateProps(node, curr, next);
+            return rootNode;
+
+        case "Image":
+            if (nextE._0.ctor === 'Plain') {
+                if (nextE._3 !== currE._3) {
+                    node.src = nextE._3;
+                }
+            } else if (!Utils.eq(nextE,currE) ||
+                       next.props.width !== curr.props.width ||
+                       next.props.height !== curr.props.height) {
+                return render(next);
+            }
+            updateProps(node, curr, next);
+            return rootNode;
+
+        case "Flow":
+            var arr = List.toArray(nextE._1);
+            for (var i = arr.length; i--; ) {
+                arr[i] = arr[i].element.ctor;
+            }
+            if (nextE._0.ctor !== currE._0.ctor) {
+                return render(next);
+            }
+            var nexts = List.toArray(nextE._1);
+            var kids = node.childNodes;
+            if (nexts.length !== kids.length) {
+                return render(next);
+            }
+            var currs = List.toArray(currE._1);
+            var dir = nextE._0.ctor;
+            var goDir = directionTable[dir];
+            var toReverse = needsReversal(dir);
+            var len = kids.length;
+            for (var i = len; i-- ;) {
+                var subNode = kids[toReverse ? len - i - 1 : i];
+                goDir(updateAndReplace(subNode, currs[i], nexts[i]));
+            }
+            updateProps(node, curr, next);
+            return rootNode;
+
+        case "Container":
+            var subNode = node.firstChild;
+            var newSubNode = updateAndReplace(subNode, currE._1, nextE._1);
+            setPos(nextE._0, nextE._1, newSubNode);
+            updateProps(node, curr, next);
+            return rootNode;
+
+        case "Custom":
+            if (currE.type === nextE.type) {
+                var updatedNode = nextE.update(node, currE.model, nextE.model);
+                updateProps(updatedNode, curr, next);
+                return updatedNode;
+            } else {
+                return render(next);
+            }
+        }
+    }
+
+    function updateProps(node, curr, next) {
+        var nextProps = next.props;
+        var currProps = curr.props;
+
+        var element = next.element;
+        var width = nextProps.width - (element.adjustWidth || 0);
+        var height = nextProps.height - (element.adjustHeight || 0);
+        if (width !== currProps.width) {
+            node.style.width = (width|0) + 'px';
+        }
+        if (height !== currProps.height) {
+            node.style.height = (height|0) + 'px';
+        }
+
+        if (nextProps.opacity !== currProps.opacity) {
+            node.style.opacity = nextProps.opacity;
+        }
+
+        var nextColor = nextProps.color.ctor === 'Just'
+            ? Color.toCss(nextProps.color._0)
+            : '';
+        if (node.style.backgroundColor !== nextColor) {
+            node.style.backgroundColor = nextColor;
+        }
+
+        if (nextProps.tag !== currProps.tag) {
+            node.id = nextProps.tag;
+        }
+
+        if (nextProps.href !== currProps.href) {
+            if (currProps.href === '') {
+                // add a surrounding href
+                var anchor = createNode('a');
+                anchor.href = nextProps.href;
+                anchor.style.display = 'block';
+                anchor.style.pointerEvents = 'auto';
+
+                node.parentNode.replaceChild(anchor, node);
+                anchor.appendChild(node);
+            } else if (nextProps.href === '') {
+                // remove the surrounding href
+                var anchor = node.parentNode;
+                anchor.parentNode.replaceChild(node, anchor);
+            } else {
+                // just update the link
+                node.parentNode.href = nextProps.href;
+            }
+        }
+
+        // update click and hover handlers
+        var removed = false;
+
+        // update hover handlers
+        if (currProps.hover.ctor === '_Tuple0') {
+            if (nextProps.hover.ctor !== '_Tuple0') {
+                addHover(node, nextProps.hover);
+            }
+        }
+        else {
+            if (nextProps.hover.ctor === '_Tuple0') {
+                removed = true;
+                removeHover(node);
+            }
+            else {
+                node.elm_hover_handler = nextProps.hover;
+            }
+        }
+
+        // update click handlers
+        if (currProps.click.ctor === '_Tuple0') {
+            if (nextProps.click.ctor !== '_Tuple0') {
+                addClick(node, nextProps.click);
+            }
+        }
+        else {
+            if (nextProps.click.ctor === '_Tuple0') {
+                removed = true;
+                removeClick(node);
+            } else {
+                node.elm_click_handler = nextProps.click;
+            }
+        }
+
+        // stop capturing clicks if 
+        if (removed
+            && nextProps.hover.ctor === '_Tuple0'
+            && nextProps.click.ctor === '_Tuple0')
+        {
+            node.style.pointerEvents = 'none';
+        }
+    }
+
+
+    function htmlHeight(width, rawHtml) {
+        // create dummy node
+        var temp = document.createElement('div');
+        temp.innerHTML = rawHtml.html;
+        if (width > 0) {
+            temp.style.width = width + "px";
+        }
+        temp.style.visibility = "hidden";
+        temp.style.styleFloat = "left";
+        temp.style.cssFloat   = "left";
+
+        document.body.appendChild(temp);
+
+        // get dimensions
+        var style = window.getComputedStyle(temp, null);
+        var w = Math.ceil(style.getPropertyValue("width").slice(0,-2) - 0);
+        var h = Math.ceil(style.getPropertyValue("height").slice(0,-2) - 0);
+        document.body.removeChild(temp);
+        return Utils.Tuple2(w,h);
+    }
+
+
+    return Elm.Native.Graphics.Element.values = {
+        render: render,
+        update: update,
+        updateAndReplace: updateAndReplace,
+
+        createNode: createNode,
+        addTransform: addTransform,
+        htmlHeight: F2(htmlHeight),
+        guid: Utils.guid
+    };
+
+};
+
+// setup
+Elm.Native = Elm.Native || {};
+Elm.Native.Graphics = Elm.Native.Graphics || {};
+Elm.Native.Graphics.Input = Elm.Native.Graphics.Input || {};
+
+// definition
+Elm.Native.Graphics.Input.make = function(localRuntime) {
+    'use strict';
+
+    // attempt to short-circuit
+    if ('values' in Elm.Native.Graphics.Input) {
+        return Elm.Native.Graphics.Input.values;
+    }
+
+    var Color = Elm.Native.Color.make(localRuntime);
+    var List = Elm.Native.List.make(localRuntime);
+    var Text = Elm.Native.Text.make(localRuntime);
+    var Utils = Elm.Native.Utils.make(localRuntime);
+
+    var Element = Elm.Graphics.Element.make(localRuntime);
+    var NativeElement = Elm.Native.Graphics.Element.make(localRuntime);
+
+
+    function renderDropDown(model) {
+        var drop = NativeElement.createNode('select');
+        drop.style.border = '0 solid';
+        drop.style.pointerEvents = 'auto';
+        drop.style.display = 'block';
+
+        drop.elm_values = List.toArray(model.values);
+        var values = drop.elm_values;
+
+        for (var i = 0; i < values.length; ++i) {
+            var option = NativeElement.createNode('option');
+            var name = values[i]._0;
+            option.value = name;
+            option.innerHTML = name;
+            drop.appendChild(option);
+        }
+        drop.addEventListener('change', function() {
+            drop.elm_values[drop.selectedIndex]._1();
+        });
+
+        return drop;
+    }
+
+    function updateDropDown(node, oldModel, newModel) {
+        node.elm_values = List.toArray(newModel.values);
+
+        var values = node.elm_values;
+        var kids = node.childNodes;
+        var kidsLength = kids.length;
+
+        var i = 0;
+        for (; i < kidsLength && i < values.length; ++i) {
+            var option = kids[i];
+            var name = values[i]._0;
+            option.value = name;
+            option.innerHTML = name;
+        }
+        for (; i < kidsLength; ++i) {
+            node.removeChild(node.lastChild);
+        }
+        for (; i < values.length; ++i) {
+            var option = NativeElement.createNode('option');
+            var name = values[i]._0;
+            option.value = name;
+            option.innerHTML = name;
+            node.appendChild(option);
+        }
+        return node;
+    }
+
+    function dropDown(values) {
+        return A3(Element.newElement, 100, 24, {
+            ctor: 'Custom',
+            type: 'DropDown',
+            render: renderDropDown,
+            update: updateDropDown,
+            model: {
+                values: values
+            }
+        });
+    }
+
+    function renderButton(model) {
+        var node = NativeElement.createNode('button');
+        node.style.display = 'block';
+        node.style.pointerEvents = 'auto';
+        node.elm_message = model.message;
+        function click() {
+            node.elm_message();
+        }
+        node.addEventListener('click', click);
+        node.innerHTML = model.text;
+        return node;
+    }
+
+    function updateButton(node, oldModel, newModel) {
+        node.elm_message = newModel.message;
+        var txt = newModel.text;
+        if (oldModel.text !== txt) {
+            node.innerHTML = txt;
+        }
+        return node;
+    }
+
+    function button(message, text) {
+        return A3(Element.newElement, 100, 40, {
+            ctor: 'Custom',
+            type: 'Button',
+            render: renderButton,
+            update: updateButton,
+            model: {
+                message: message,
+                text:text
+            }
+        });
+    }
+
+    function renderCustomButton(model) {
+        var btn = NativeElement.createNode('div');
+        btn.style.pointerEvents = 'auto';
+        btn.elm_message = model.message;
+
+        btn.elm_up    = NativeElement.render(model.up);
+        btn.elm_hover = NativeElement.render(model.hover);
+        btn.elm_down  = NativeElement.render(model.down);
+
+        btn.elm_up.style.display = 'block';
+        btn.elm_hover.style.display = 'none';
+        btn.elm_down.style.display = 'none';
+  
+        btn.appendChild(btn.elm_up);
+        btn.appendChild(btn.elm_hover);
+        btn.appendChild(btn.elm_down);
+
+        function swap(visibleNode, hiddenNode1, hiddenNode2) {
+            visibleNode.style.display = 'block';
+            hiddenNode1.style.display = 'none';
+            hiddenNode2.style.display = 'none';
+        }
+
+        var overCount = 0;
+        function over(e) {
+            if (overCount++ > 0) return;
+            swap(btn.elm_hover, btn.elm_down, btn.elm_up);
+        }
+        function out(e) {
+            if (btn.contains(e.toElement || e.relatedTarget)) return;
+            overCount = 0;
+            swap(btn.elm_up, btn.elm_down, btn.elm_hover);
+        }
+        function up() {
+            swap(btn.elm_hover, btn.elm_down, btn.elm_up);
+            btn.elm_message();
+        }
+        function down() {
+            swap(btn.elm_down, btn.elm_hover, btn.elm_up);
+        }
+
+        btn.addEventListener('mouseover', over);
+        btn.addEventListener('mouseout' , out);
+        btn.addEventListener('mousedown', down);
+        btn.addEventListener('mouseup'  , up);
+
+        return btn;
+    }
+
+    function updateCustomButton(node, oldModel, newModel) {
+        node.elm_message = newModel.message;
+
+        var kids = node.childNodes;
+        var styleUp    = kids[0].style.display;
+        var styleHover = kids[1].style.display;
+        var styleDown  = kids[2].style.display;
+
+        NativeElement.updateAndReplace(kids[0], oldModel.up, newModel.up);
+        NativeElement.updateAndReplace(kids[1], oldModel.hover, newModel.hover);
+        NativeElement.updateAndReplace(kids[2], oldModel.down, newModel.down);
+
+        var kids = node.childNodes;
+        kids[0].style.display = styleUp;
+        kids[1].style.display = styleHover;
+        kids[2].style.display = styleDown;
+
+        return node;
+    }
+
+    function max3(a,b,c) {
+        var ab = a > b ? a : b;
+        return ab > c ? ab : c;
+    }
+
+    function customButton(message, up, hover, down) {
+        return A3(Element.newElement,
+                  max3(up.props.width, hover.props.width, down.props.width),
+                  max3(up.props.height, hover.props.height, down.props.height),
+                  { ctor: 'Custom',
+                    type: 'CustomButton',
+                    render: renderCustomButton,
+                    update: updateCustomButton,
+                    model: {
+                        message: message,
+                        up: up,
+                        hover: hover,
+                        down: down
+                    }
+                  });
+    }
+
+    function renderCheckbox(model) {
+        var node = NativeElement.createNode('input');
+        node.type = 'checkbox';
+        node.checked = model.checked;
+        node.style.display = 'block';
+        node.style.pointerEvents = 'auto';
+        node.elm_handler = model.handler;
+        function change() {
+            node.elm_handler(node.checked)();
+        }
+        node.addEventListener('change', change);
+        return node;
+    }
+
+    function updateCheckbox(node, oldModel, newModel) {
+        node.elm_handler = newModel.handler;
+        node.checked = newModel.checked;
+        return node;
+    }
+
+    function checkbox(handler, checked) {
+        return A3(Element.newElement, 13, 13, {
+            ctor: 'Custom',
+            type: 'CheckBox',
+            render: renderCheckbox,
+            update: updateCheckbox,
+            model: { handler:handler, checked:checked }
+        });
+    }
+
+    function setRange(node, start, end, dir) {
+        if (node.parentNode) {
+            node.setSelectionRange(start, end, dir);
+        } else {
+            setTimeout(function(){node.setSelectionRange(start, end, dir);}, 0);
+        }
+    }
+
+    function updateIfNeeded(css, attribute, latestAttribute) {
+        if (css[attribute] !== latestAttribute) {
+            css[attribute] = latestAttribute;
+        }
+    }
+    function cssDimensions(dimensions) {
+        return dimensions.top    + 'px ' +
+               dimensions.right  + 'px ' +
+               dimensions.bottom + 'px ' +
+               dimensions.left   + 'px';
+    }
+    function updateFieldStyle(css, style) {
+        updateIfNeeded(css, 'padding', cssDimensions(style.padding));
+
+        var outline = style.outline;
+        updateIfNeeded(css, 'border-width', cssDimensions(outline.width));
+        updateIfNeeded(css, 'border-color', Color.toCss(outline.color));
+        updateIfNeeded(css, 'border-radius', outline.radius + 'px');
+
+        var highlight = style.highlight;
+        if (highlight.width === 0) {
+            css.outline = 'none';
+        } else {
+            updateIfNeeded(css, 'outline-width', highlight.width + 'px');
+            updateIfNeeded(css, 'outline-color', Color.toCss(highlight.color));
+        }
+
+        var textStyle = style.style;
+        updateIfNeeded(css, 'color', Color.toCss(textStyle.color));
+        if (textStyle.typeface.ctor !== '[]') {
+            updateIfNeeded(css, 'font-family', Text.toTypefaces(textStyle.typeface));
+        }
+        if (textStyle.height.ctor !== "Nothing") {
+            updateIfNeeded(css, 'font-size', textStyle.height._0 + 'px');
+        }
+        updateIfNeeded(css, 'font-weight', textStyle.bold ? 'bold' : 'normal');
+        updateIfNeeded(css, 'font-style', textStyle.italic ? 'italic' : 'normal');
+        if (textStyle.line.ctor !== 'Nothing') {
+            updateIfNeeded(css, 'text-decoration', Text.toLine(textStyle.line._0));
+        }
+    }
+
+    function renderField(model) {
+        var field = NativeElement.createNode('input');
+        updateFieldStyle(field.style, model.style);
+        field.style.borderStyle = 'solid';
+        field.style.pointerEvents = 'auto';
+
+        field.type = model.type;
+        field.placeholder = model.placeHolder;
+        field.value = model.content.string;
+
+        field.elm_handler = model.handler;
+        field.elm_old_value = field.value;
+
+        function inputUpdate(event) {
+            var curr = field.elm_old_value;
+            var next = field.value;
+            if (curr === next) {
+                return;
+            }
+
+            var direction = field.selectionDirection === 'forward' ? 'Forward' : 'Backward';
+            var start = field.selectionStart;
+            var end = field.selectionEnd;
+            field.value = field.elm_old_value;
+
+            field.elm_handler({
+                _:{},
+                string: next,
+                selection: {
+                    _:{},
+                    start: start,
+                    end: end,
+                    direction: { ctor: direction }
+                }
+            })();
+        }
+
+        field.addEventListener('input', inputUpdate);
+        field.addEventListener('focus', function() {
+            field.elm_hasFocus = true;
+        });
+        field.addEventListener('blur', function() {
+            field.elm_hasFocus = false;
+        });
+
+        return field;
+    }
+
+    function updateField(field, oldModel, newModel) {
+        if (oldModel.style !== newModel.style) {
+            updateFieldStyle(field.style, newModel.style);
+        }
+        field.elm_handler = newModel.handler;
+
+        field.type = newModel.type;
+        field.placeholder = newModel.placeHolder;
+        var value = newModel.content.string;
+        field.value = value;
+        field.elm_old_value = value;
+        if (field.elm_hasFocus) {
+            var selection = newModel.content.selection;
+            var direction = selection.direction.ctor === 'Forward' ? 'forward' : 'backward';
+            setRange(field, selection.start, selection.end, direction);
+        }
+        return field;
+    }
+
+    function mkField(type) {
+        function field(style, handler, placeHolder, content) {
+            var padding = style.padding;
+            var outline = style.outline.width;
+            var adjustWidth = padding.left + padding.right + outline.left + outline.right;
+            var adjustHeight = padding.top + padding.bottom + outline.top + outline.bottom;
+            return A3(Element.newElement, 200, 30, {
+                ctor: 'Custom',
+                type: type + 'Field',
+                adjustWidth: adjustWidth,
+                adjustHeight: adjustHeight,
+                render: renderField,
+                update: updateField,
+                model: {
+                    handler:handler,
+                    placeHolder:placeHolder,
+                    content:content,
+                    style:style,
+                    type:type
+                }
+            });
+        }
+        return F4(field);
+    }
+
+    function hoverable(handler, elem) {
+        function onHover(bool) {
+            handler(bool)();
+        }
+        var props = Utils.replace([['hover',onHover]], elem.props);
+        return { props:props, element:elem.element };
+    }
+
+    function clickable(message, elem) {
+        function onClick() {
+            message();
+        }
+        var props = Utils.replace([['click',onClick]], elem.props);
+        return { props:props, element:elem.element };
+    }
+
+    return Elm.Native.Graphics.Input.values = {
+        button: F2(button),
+        customButton: F4(customButton),
+        checkbox: F2(checkbox),
+        dropDown: dropDown,
+        field: mkField('text'),
+        email: mkField('email'),
+        password: mkField('password'),
+        hoverable: F2(hoverable),
+        clickable: F2(clickable)
+    };
+
+};
+
+Elm.Native.Json = {};
+Elm.Native.Json.make = function(localRuntime) {
+    localRuntime.Native = localRuntime.Native || {};
+    localRuntime.Native.Json = localRuntime.Native.Json || {};
+    if (localRuntime.Native.Json.values) {
+        return localRuntime.Native.Json.values;
+    }
+
+    var ElmArray = Elm.Native.Array.make(localRuntime);
+    var List = Elm.Native.List.make(localRuntime);
+    var Maybe = Elm.Maybe.make(localRuntime);
+    var Result = Elm.Result.make(localRuntime);
+    var Utils = Elm.Native.Utils.make(localRuntime);
+
+
+    function crash(expected, actual) {
+        throw new Error(
+            'expecting ' + expected + ' but got ' + JSON.stringify(actual)
+        );
+    }
+
+
+    // PRIMITIVE VALUES
+
+    function decodeNull(successValue) {
+        return function(value) {
+            if (value === null) {
+                return successValue;
+            }
+            crash('null', value);
+        };
+    }
+
+
+    function decodeString(value) {
+        if (typeof value === 'string' || value instanceof String) {
+            return value;
+        }
+        crash('a String', value);
+    }
+
+
+    function decodeFloat(value) {
+        if (typeof value === 'number') {
+            return value;
+        }
+        crash('a Float', value);
+    }
+
+
+    function decodeInt(value) {
+        if (typeof value === 'number' && (value|0) === value) {
+            return value;
+        }
+        crash('an Int', value);
+    }
+
+
+    function decodeBool(value) {
+        if (typeof value === 'boolean') {
+            return value;
+        }
+        crash('a Bool', value);
+    }
+
+
+    // ARRAY
+
+    function decodeArray(decoder) {
+        return function(value) {
+            if (value instanceof Array) {
+                var len = value.length;
+                var array = new Array(len);
+                for (var i = len; i-- ; ) {
+                    array[i] = decoder(value[i]);
+                }
+                return ElmArray.fromJSArray(array);
+            }
+            crash('an Array', value);
+        };
+    }
+
+
+    // LIST
+
+    function decodeList(decoder) {
+        return function(value) {
+            if (value instanceof Array) {
+                var len = value.length;
+                var list = List.Nil;
+                for (var i = len; i-- ; ) {
+                    list = List.Cons( decoder(value[i]), list );
+                }
+                return list;
+            }
+            crash('a List', value);
+        };
+    }
+
+
+    // MAYBE
+
+    function decodeMaybe(decoder) {
+        return function(value) {
+            try {
+                return Maybe.Just(decoder(value));
+            } catch(e) {
+                return Maybe.Nothing;
+            }
+        };
+    }
+
+
+    // FIELDS
+
+    function decodeField(field, decoder) {
+        return function(value) {
+            var subValue = value[field];
+            if (subValue !== undefined) {
+                return decoder(subValue);
+            }
+            crash("an object with field '" + field + "'", value);
+        };
+    }
+
+
+    // OBJECTS
+
+    function decodeKeyValuePairs(decoder) {
+        return function(value) {
+            var isObject =
+                typeof value === 'object'
+                    && value !== null
+                    && !(value instanceof Array);
+
+            if (isObject) {
+                var keyValuePairs = List.Nil;
+                for (var key in value) {
+                    var elmValue = decoder(value[key]);
+                    var pair = Utils.Tuple2(key, elmValue);
+                    keyValuePairs = List.Cons(pair, keyValuePairs);
+                }
+                return keyValuePairs;
+            }
+
+            crash("an object", value);
+        };
+    }
+
+    function decodeObject1(f, d1) {
+        return function(value) {
+            return f(d1(value));
+        };
+    }
+
+    function decodeObject2(f, d1, d2) {
+        return function(value) {
+            return A2( f, d1(value), d2(value) );
+        };
+    }
+
+    function decodeObject3(f, d1, d2, d3) {
+        return function(value) {
+            return A3( f, d1(value), d2(value), d3(value) );
+        };
+    }
+
+    function decodeObject4(f, d1, d2, d3, d4) {
+        return function(value) {
+            return A4( f, d1(value), d2(value), d3(value), d4(value) );
+        };
+    }
+
+    function decodeObject5(f, d1, d2, d3, d4, d5) {
+        return function(value) {
+            return A5( f, d1(value), d2(value), d3(value), d4(value), d5(value) );
+        };
+    }
+
+    function decodeObject6(f, d1, d2, d3, d4, d5, d6) {
+        return function(value) {
+            return A6( f,
+                d1(value),
+                d2(value),
+                d3(value),
+                d4(value),
+                d5(value),
+                d6(value)
+            );
+        };
+    }
+
+    function decodeObject7(f, d1, d2, d3, d4, d5, d6, d7) {
+        return function(value) {
+            return A7( f,
+                d1(value),
+                d2(value),
+                d3(value),
+                d4(value),
+                d5(value),
+                d6(value),
+                d7(value)
+            );
+        };
+    }
+
+    function decodeObject8(f, d1, d2, d3, d4, d5, d6, d7, d8) {
+        return function(value) {
+            return A8( f,
+                d1(value),
+                d2(value),
+                d3(value),
+                d4(value),
+                d5(value),
+                d6(value),
+                d7(value),
+                d8(value)
+            );
+        };
+    }
+
+
+    // TUPLES
+
+    function decodeTuple1(f, d1) {
+        return function(value) {
+            if ( !(value instanceof Array) || value.length !== 1 ) {
+                crash('a Tuple of length 1', value);
+            }
+            return f( d1(value[0]) );
+        };
+    }
+
+    function decodeTuple2(f, d1, d2) {
+        return function(value) {
+            if ( !(value instanceof Array) || value.length !== 2 ) {
+                crash('a Tuple of length 2', value);
+            }
+            return A2( f, d1(value[0]), d2(value[1]) );
+        };
+    }
+
+    function decodeTuple3(f, d1, d2, d3) {
+        return function(value) {
+            if ( !(value instanceof Array) || value.length !== 3 ) {
+                crash('a Tuple of length 3', value);
+            }
+            return A3( f, d1(value[0]), d2(value[1]), d3(value[2]) );
+        };
+    }
+
+
+    function decodeTuple4(f, d1, d2, d3, d4) {
+        return function(value) {
+            if ( !(value instanceof Array) || value.length !== 4 ) {
+                crash('a Tuple of length 4', value);
+            }
+            return A4( f, d1(value[0]), d2(value[1]), d3(value[2]), d4(value[3]) );
+        };
+    }
+
+
+    function decodeTuple5(f, d1, d2, d3, d4, d5) {
+        return function(value) {
+            if ( !(value instanceof Array) || value.length !== 5 ) {
+                crash('a Tuple of length 5', value);
+            }
+            return A5( f,
+                d1(value[0]),
+                d2(value[1]),
+                d3(value[2]),
+                d4(value[3]),
+                d5(value[4])
+            );
+        };
+    }
+
+
+    function decodeTuple6(f, d1, d2, d3, d4, d5, d6) {
+        return function(value) {
+            if ( !(value instanceof Array) || value.length !== 6 ) {
+                crash('a Tuple of length 6', value);
+            }
+            return A6( f,
+                d1(value[0]),
+                d2(value[1]),
+                d3(value[2]),
+                d4(value[3]),
+                d5(value[4]),
+                d6(value[5])
+            );
+        };
+    }
+
+    function decodeTuple7(f, d1, d2, d3, d4, d5, d6, d7) {
+        return function(value) {
+            if ( !(value instanceof Array) || value.length !== 7 ) {
+                crash('a Tuple of length 7', value);
+            }
+            return A7( f,
+                d1(value[0]),
+                d2(value[1]),
+                d3(value[2]),
+                d4(value[3]),
+                d5(value[4]),
+                d6(value[5]),
+                d7(value[6])
+            );
+        };
+    }
+
+
+    function decodeTuple8(f, d1, d2, d3, d4, d5, d6, d7, d8) {
+        return function(value) {
+            if ( !(value instanceof Array) || value.length !== 8 ) {
+                crash('a Tuple of length 8', value);
+            }
+            return A8( f,
+                d1(value[0]),
+                d2(value[1]),
+                d3(value[2]),
+                d4(value[3]),
+                d5(value[4]),
+                d6(value[5]),
+                d7(value[6]),
+                d8(value[7])
+            );
+        };
+    }
+
+
+    // CUSTOM DECODERS
+
+    function decodeValue(value) {
+        return value;
+    }
+
+    function runDecoderValue(decoder, value) {
+        try {
+            return Result.Ok(decoder(value));
+        } catch(e) {
+            return Result.Err(e.message);
+        }
+    }
+
+    function customDecoder(decoder, callback) {
+        return function(value) {
+            var result = callback(decoder(value));
+            if (result.ctor === 'Err') {
+                throw new Error('custom decoder failed: ' + result._0);
+            }
+            return result._0;
+        }
+    }
+
+    function andThen(decode, callback) {
+        return function(value) {
+            var result = decode(value);
+            return callback(result)(value);
+        }
+    }
+
+    function fail(msg) {
+        return function(value) {
+            throw new Error(msg);
+        }
+    }
+
+    function succeed(successValue) {
+        return function(value) {
+            return successValue;
+        }
+    }
+
+
+    // ONE OF MANY
+
+    function oneOf(decoders) {
+        return function(value) {
+            var errors = [];
+            while (decoders.ctor !== '[]') {
+                try {
+                    return decoders._0(value);
+                } catch(e) {
+                    errors.push(e.message);
+                }
+                decoders = decoders._1;
+            }
+            throw new Error('expecting one of the following:\n    ' + errors.join('\n    '));
+        }
+    }
+
+    function get(decoder, value) {
+        try {
+            return Result.Ok(decoder(value));
+        } catch(e) {
+            return Result.Err(e.message);
+        }
+    }
+
+
+    // ENCODE / DECODE
+
+    function runDecoderString(decoder, string) {
+        try {
+            return Result.Ok(decoder(JSON.parse(string)));
+        } catch(e) {
+            return Result.Err(e.message);
+        }
+    }
+
+    function encode(indentLevel, value) {
+        return JSON.stringify(value, null, indentLevel);
+    }
+
+    function identity(value) {
+        return value;
+    }
+
+    function encodeObject(keyValuePairs) {
+        var obj = {};
+        while (keyValuePairs.ctor !== '[]') {
+            var pair = keyValuePairs._0;
+            obj[pair._0] = pair._1;
+            keyValuePairs = keyValuePairs._1;
+        }
+        return obj;
+    }
+
+    return localRuntime.Native.Json.values = {
+        encode: F2(encode),
+        runDecoderString: F2(runDecoderString),
+        runDecoderValue: F2(runDecoderValue),
+
+        get: F2(get),
+        oneOf: oneOf,
+
+        decodeNull: decodeNull,
+        decodeInt: decodeInt,
+        decodeFloat: decodeFloat,
+        decodeString: decodeString,
+        decodeBool: decodeBool,
+
+        decodeMaybe: decodeMaybe,
+
+        decodeList: decodeList,
+        decodeArray: decodeArray,
+
+        decodeField: F2(decodeField),
+
+        decodeObject1: F2(decodeObject1),
+        decodeObject2: F3(decodeObject2),
+        decodeObject3: F4(decodeObject3),
+        decodeObject4: F5(decodeObject4),
+        decodeObject5: F6(decodeObject5),
+        decodeObject6: F7(decodeObject6),
+        decodeObject7: F8(decodeObject7),
+        decodeObject8: F9(decodeObject8),
+        decodeKeyValuePairs: decodeKeyValuePairs,
+
+        decodeTuple1: F2(decodeTuple1),
+        decodeTuple2: F3(decodeTuple2),
+        decodeTuple3: F4(decodeTuple3),
+        decodeTuple4: F5(decodeTuple4),
+        decodeTuple5: F6(decodeTuple5),
+        decodeTuple6: F7(decodeTuple6),
+        decodeTuple7: F8(decodeTuple7),
+        decodeTuple8: F9(decodeTuple8),
+
+        andThen: F2(andThen),
+        decodeValue: decodeValue,
+        customDecoder: F2(customDecoder),
+        fail: fail,
+        succeed: succeed,
+
+        identity: identity,
+        encodeNull: null,
+        encodeArray: ElmArray.toJSArray,
+        encodeList: List.toArray,
+        encodeObject: encodeObject
+
+    };
+
+};
+
+Elm.Native.List = {};
+Elm.Native.List.make = function(elm) {
+    elm.Native = elm.Native || {};
+    elm.Native.List = elm.Native.List || {};
+    if (elm.Native.List.values) return elm.Native.List.values;
+    if ('values' in Elm.Native.List)
+        return elm.Native.List.values = Elm.Native.List.values;
+
+    var Utils = Elm.Native.Utils.make(elm);
+
+    var Nil = Utils.Nil;
+    var Cons = Utils.Cons;
+
+    function throwError(f) {
+        throw new Error("Function '" + f + "' expects a non-empty list!");
+    }
+
+    function toArray(xs) {
+        var out = [];
+        while (xs.ctor !== '[]') {
+            out.push(xs._0);
+            xs = xs._1;
+        }
+        return out;
+    }
+
+    function fromArray(arr) {
+        var out = Nil;
+        for (var i = arr.length; i--; ) {
+            out = Cons(arr[i], out);
+        }
+        return out;
+    }
+
+    function range(lo,hi) {
+        var lst = Nil;
+        if (lo <= hi) {
+            do { lst = Cons(hi,lst) } while (hi-->lo);
+        }
+        return lst
+    }
+
+    function head(v) {
+        return v.ctor === '[]' ? throwError('head') : v._0;
+    }
+    function tail(v) {
+        return v.ctor === '[]' ? throwError('tail') : v._1;
+    }
+
+    function last(xs) {
+        if (xs.ctor === '[]') { throwError('last'); }
+        var out = xs._0;
+        while (xs.ctor !== '[]') {
+            out = xs._0;
+            xs = xs._1;
+        }
+        return out;
+    }
+
+    function map(f, xs) {
+        var arr = [];
+        while (xs.ctor !== '[]') {
+            arr.push(f(xs._0));
+            xs = xs._1;
+        }
+        return fromArray(arr);
+    }
+
+    // f defined similarly for both foldl and foldr (NB: different from Haskell)
+    // ie, foldl : (a -> b -> b) -> b -> [a] -> b
+    function foldl(f, b, xs) {
+        var acc = b;
+        while (xs.ctor !== '[]') {
+            acc = A2(f, xs._0, acc);
+            xs = xs._1;
+        }
+        return acc;
+    }
+
+    function foldr(f, b, xs) {
+        var arr = toArray(xs);
+        var acc = b;
+        for (var i = arr.length; i--; ) {
+            acc = A2(f, arr[i], acc);
+        }
+        return acc;
+    }
+
+    function foldl1(f, xs) {
+        return xs.ctor === '[]' ? throwError('foldl1') : foldl(f, xs._0, xs._1);
+    }
+
+    function foldr1(f, xs) {
+        if (xs.ctor === '[]') { throwError('foldr1'); }
+        var arr = toArray(xs);
+        var acc = arr.pop();
+        for (var i = arr.length; i--; ) {
+            acc = A2(f, arr[i], acc);
+        }
+        return acc;
+    }
+
+    function scanl(f, b, xs) {
+        var arr = toArray(xs);
+        arr.unshift(b);
+        var len = arr.length;
+        for (var i = 1; i < len; ++i) {
+            arr[i] = A2(f, arr[i], arr[i-1]);
+        }
+        return fromArray(arr);
+    }
+
+    function scanl1(f, xs) {
+        return xs.ctor === '[]' ? throwError('scanl1') : scanl(f, xs._0, xs._1);
+    }
+
+    function filter(pred, xs) {
+        var arr = [];
+        while (xs.ctor !== '[]') {
+            if (pred(xs._0)) { arr.push(xs._0); }
+            xs = xs._1;
+        }
+        return fromArray(arr);
+    }
+
+    function length(xs) {
+        var out = 0;
+        while (xs.ctor !== '[]') {
+            out += 1;
+            xs = xs._1;
+        }
+        return out;
+    }
+
+    function member(x, xs) {
+        while (xs.ctor !== '[]') {
+            if (Utils.eq(x,xs._0)) return true;
+            xs = xs._1;
+        }
+        return false;
+    }
+
+    function reverse(xs) {
+        return fromArray(toArray(xs).reverse());
+    }
+
+    function append(xs, ys) {
+        if (xs.ctor === '[]') {
+            return ys;
+        }
+        var root = Cons(xs._0, Nil);
+        var curr = root;
+        xs = xs._1;
+        while (xs.ctor !== '[]') {
+            curr._1 = Cons(xs._0, Nil);
+            xs = xs._1;
+            curr = curr._1;
+        }
+        curr._1 = ys;
+        return root;
+    }
+
+    function all(pred, xs) {
+        while (xs.ctor !== '[]') {
+            if (!pred(xs._0)) return false;
+            xs = xs._1;
+        }
+        return true;
+    }
+
+    function any(pred, xs) {
+        while (xs.ctor !== '[]') {
+            if (pred(xs._0)) return true;
+            xs = xs._1;
+        }
+        return false;
+    }
+
+    function map2(f, xs, ys) {
+        var arr = [];
+        while (xs.ctor !== '[]' && ys.ctor !== '[]') {
+            arr.push(A2(f, xs._0, ys._0));
+            xs = xs._1;
+            ys = ys._1;
+        }
+        return fromArray(arr);
+    }
+
+    function map3(f, xs, ys, zs) {
+        var arr = [];
+        while (xs.ctor !== '[]' && ys.ctor !== '[]' && zs.ctor !== '[]') {
+            arr.push(A3(f, xs._0, ys._0, zs._0));
+            xs = xs._1;
+            ys = ys._1;
+            zs = zs._1;
+        }
+        return fromArray(arr);
+    }
+
+    function map4(f, ws, xs, ys, zs) {
+        var arr = [];
+        while (   ws.ctor !== '[]'
+               && xs.ctor !== '[]'
+               && ys.ctor !== '[]'
+               && zs.ctor !== '[]')
+        {
+            arr.push(A4(f, ws._0, xs._0, ys._0, zs._0));
+            ws = ws._1;
+            xs = xs._1;
+            ys = ys._1;
+            zs = zs._1;
+        }
+        return fromArray(arr);
+    }
+
+    function map5(f, vs, ws, xs, ys, zs) {
+        var arr = [];
+        while (   vs.ctor !== '[]'
+               && ws.ctor !== '[]'
+               && xs.ctor !== '[]'
+               && ys.ctor !== '[]'
+               && zs.ctor !== '[]')
+        {
+            arr.push(A5(f, vs._0, ws._0, xs._0, ys._0, zs._0));
+            vs = vs._1;
+            ws = ws._1;
+            xs = xs._1;
+            ys = ys._1;
+            zs = zs._1;
+        }
+        return fromArray(arr);
+    }
+
+    function sort(xs) {
+        return fromArray(toArray(xs).sort(Utils.cmp));
+    }
+
+    function sortBy(f, xs) {
+        return fromArray(toArray(xs).sort(function(a,b){
+            return Utils.cmp(f(a), f(b));
+        }));
+    }
+
+    function sortWith(f, xs) {
+        return fromArray(toArray(xs).sort(function(a,b){
+            var ord = f(a)(b).ctor;
+            return ord === 'EQ' ? 0 : ord === 'LT' ? -1 : 1;
+        }));
+    }
+
+    function nth(xs, n) {
+        return toArray(xs)[n];
+    }
+
+    function take(n, xs) {
+        var arr = [];
+        while (xs.ctor !== '[]' && n > 0) {
+            arr.push(xs._0);
+            xs = xs._1;
+            --n;
+        }
+        return fromArray(arr);
+    }
+
+    function drop(n, xs) {
+        while (xs.ctor !== '[]' && n > 0) {
+            xs = xs._1;
+            --n;
+        }
+        return xs;
+    }
+
+    function repeat(n, x) {
+        var arr = [];
+        var pattern = [x];
+        while (n > 0) {
+            if (n & 1) arr = arr.concat(pattern);
+            n >>= 1, pattern = pattern.concat(pattern);
+        }
+        return fromArray(arr);
+    }
+
+
+    Elm.Native.List.values = {
+        Nil:Nil,
+        Cons:Cons,
+        cons:F2(Cons),
+        toArray:toArray,
+        fromArray:fromArray,
+        range:range,
+        append: F2(append),
+
+        head:head,
+        tail:tail,
+        last:last,
+
+        map:F2(map),
+        foldl:F3(foldl),
+        foldr:F3(foldr),
+
+        foldl1:F2(foldl1),
+        foldr1:F2(foldr1),
+        scanl:F3(scanl),
+        scanl1:F2(scanl1),
+        filter:F2(filter),
+        length:length,
+        member:F2(member),
+        reverse:reverse,
+
+        all:F2(all),
+        any:F2(any),
+        map2:F3(map2),
+        map3:F4(map3),
+        map4:F5(map4),
+        map5:F6(map5),
+        sort:sort,
+        sortBy:F2(sortBy),
+        sortWith:F2(sortWith),
+        nth:F2(nth),
+        take:F2(take),
+        drop:F2(drop),
+        repeat:F2(repeat)
+    };
+    return elm.Native.List.values = Elm.Native.List.values;
+
+};
+
+
+// setup
+Elm.Native = Elm.Native || {};
+Elm.Native.Markdown = Elm.Native.Markdown || {};
+
+// definition
+Elm.Native.Markdown.make = function(localRuntime) {
+    'use strict';
+
+    // attempt to short-circuit
+    if ('values' in Elm.Native.Markdown) {
+        return Elm.Native.Markdown.values;
+    }
+
+    var Text = Elm.Text.make(localRuntime);
+
+    /**
+     * marked - a markdown parser
+     * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
+     * https://github.com/chjj/marked
+     */
+    (function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";block.html=replace(block.html)("comment",/<!--[\s\S]*?-->/)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,paragraph:/^/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1","\\2")+"|"+block.list.source.replace("\\1","\\3")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables}else{this.rules=block.gfm}}}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g,"    ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top,bq){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:"space"})}}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].split(/ *\| */)}this.tokens.push(item);continue}if(cap=this.rules.lheading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[2]==="="?1:2,text:cap[1]});continue}if(cap=this.rules.hr.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"hr"});continue}if(cap=this.rules.blockquote.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"blockquote_start"});cap=cap[0].replace(/^ *> ?/gm,"");this.token(cap,top,true);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i<l;i++){item=cap[i];space=item.length;item=item.replace(/^ *([*+-]|\d+\.) +/,"");if(~item.indexOf("\n ")){space-=item.length;item=!this.options.pedantic?item.replace(new RegExp("^ {1,"+space+"}","gm"),""):item.replace(/^ {1,4}/gm,"")}if(this.options.smartLists&&i!==l-1){b=block.bullet.exec(cap[i+1])[0];if(bull!==b&&!(bull.length>1&&b.length>1)){src=cap.slice(i+1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item.charAt(item.length-1)==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false,bq);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:cap[1]==="pre"||cap[1]==="script"||cap[1]==="style",text:cap[0]});continue}if(!bq&&top&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].replace(/^ *\| *| *\| *$/g,"").split(/ *\| */)}this.tokens.push(item);continue}if(top&&(cap=this.rules.paragraph.exec(src))){src=src.substring(cap[0].length);this.tokens.push({type:"paragraph",text:cap[1].charAt(cap[1].length-1)==="\n"?cap[1].slice(0,-1):cap[1]});continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"text",text:cap[0]});continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return this.tokens};var inline={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/};inline._inside=/(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;inline._href=/\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;this.renderer=this.options.renderer||new Renderer;this.renderer.options=this.options;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=inline.breaks}else{this.rules=inline.gfm}}else if(this.options.pedantic){this.rules=inline.pedantic}}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1].charAt(6)===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=this.renderer.link(href,null,text);continue}if(!this.inLink&&(cap=this.rules.url.exec(src))){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=this.renderer.link(href,null,text);continue}if(cap=this.rules.tag.exec(src)){if(!this.inLink&&/^<a /i.test(cap[0])){this.inLink=true}else if(this.inLink&&/^<\/a>/i.test(cap[0])){this.inLink=false}src=src.substring(cap[0].length);out+=this.options.sanitize?escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);this.inLink=true;out+=this.outputLink(cap,{href:cap[2],title:cap[3]});this.inLink=false;continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0].charAt(0);src=cap[0].substring(1)+src;continue}this.inLink=true;out+=this.outputLink(cap,link);this.inLink=false;continue}if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.strong(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.em(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.codespan(escape(cap[2],true));continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.br();continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.del(this.output(cap[1]));continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=escape(this.smartypants(cap[0]));continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return out};InlineLexer.prototype.outputLink=function(cap,link){var href=escape(link.href),title=link.title?escape(link.title):null;return cap[0].charAt(0)!=="!"?this.renderer.link(href,title,this.output(cap[1])):this.renderer.image(href,title,escape(cap[1]))};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/--/g,"—").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…")};InlineLexer.prototype.mangle=function(text){var out="",l=text.length,i=0,ch;for(;i<l;i++){ch=text.charCodeAt(i);if(Math.random()>.5){ch="x"+ch.toString(16)}out+="&#"+ch+";"}return out};function Renderer(options){this.options=options||{}}Renderer.prototype.code=function(code,lang,escaped){if(this.options.highlight){var out=this.options.highlight(code,lang);if(out!=null&&out!==code){escaped=true;code=out}}if(!lang){return"<pre><code>"+(escaped?code:escape(code,true))+"\n</code></pre>"}return'<pre><code class="'+this.options.langPrefix+escape(lang,true)+'">'+(escaped?code:escape(code,true))+"\n</code></pre>\n"};Renderer.prototype.blockquote=function(quote){return"<blockquote>\n"+quote+"</blockquote>\n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"<h"+level+' id="'+this.options.headerPrefix+raw.toLowerCase().replace(/[^\w]+/g,"-")+'">'+text+"</h"+level+">\n"};Renderer.prototype.hr=function(){return this.options.xhtml?"<hr/>\n":"<hr>\n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+"</"+type+">\n"};Renderer.prototype.listitem=function(text){return"<li>"+text+"</li>\n"};Renderer.prototype.paragraph=function(text){return"<p>"+text+"</p>\n"};Renderer.prototype.table=function(header,body){return"<table>\n"+"<thead>\n"+header+"</thead>\n"+"<tbody>\n"+body+"</tbody>\n"+"</table>\n"};Renderer.prototype.tablerow=function(content){return"<tr>\n"+content+"</tr>\n"};Renderer.prototype.tablecell=function(content,flags){var type=flags.header?"th":"td";var tag=flags.align?"<"+type+' style="text-align:'+flags.align+'">':"<"+type+">";return tag+content+"</"+type+">\n"};Renderer.prototype.strong=function(text){return"<strong>"+text+"</strong>"};Renderer.prototype.em=function(text){return"<em>"+text+"</em>"};Renderer.prototype.codespan=function(text){return"<code>"+text+"</code>"};Renderer.prototype.br=function(){return this.options.xhtml?"<br/>":"<br>"};Renderer.prototype.del=function(text){return"<del>"+text+"</del>"};Renderer.prototype.link=function(href,title,text){if(this.options.sanitize){try{var prot=decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(prot.indexOf("javascript:")===0){return""}}var out='<a href="'+href+'"';if(title){out+=' title="'+title+'"'}out+=">"+text+"</a>";return out};Renderer.prototype.image=function(href,title,text){var out='<img src="'+href+'" alt="'+text+'"';if(title){out+=' title="'+title+'"'}out+=this.options.xhtml?"/>":">";return out};function Parser(options){this.tokens=[];this.token=null;this.options=options||marked.defaults;this.options.renderer=this.options.renderer||new Renderer;this.renderer=this.options.renderer;this.renderer.options=this.options}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options,this.renderer);this.tokens=src.reverse();var out="";while(this.next()){out+=this.tok()}return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case"space":{return""}case"hr":{return this.renderer.hr()}case"heading":{return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text)}case"code":{return this.renderer.code(this.token.text,this.token.lang,this.token.escaped)}case"table":{var header="",body="",i,row,cell,flags,j;cell="";for(i=0;i<this.token.header.length;i++){flags={header:true,align:this.token.align[i]};cell+=this.renderer.tablecell(this.inline.output(this.token.header[i]),{header:true,align:this.token.align[i]})}header+=this.renderer.tablerow(cell);for(i=0;i<this.token.cells.length;i++){row=this.token.cells[i];cell="";for(j=0;j<row.length;j++){cell+=this.renderer.tablecell(this.inline.output(row[j]),{header:false,align:this.token.align[j]})}body+=this.renderer.tablerow(cell)}return this.renderer.table(header,body)}case"blockquote_start":{var body="";while(this.next().type!=="blockquote_end"){body+=this.tok()}return this.renderer.blockquote(body)}case"list_start":{var body="",ordered=this.token.ordered;while(this.next().type!=="list_end"){body+=this.tok()}return this.renderer.list(body,ordered)}case"list_item_start":{var body="";while(this.next().type!=="list_item_end"){body+=this.token.type==="text"?this.parseText():this.tok()}return this.renderer.listitem(body)}case"loose_item_start":{var body="";while(this.next().type!=="list_item_end"){body+=this.tok()}return this.renderer.listitem(body)}case"html":{var html=!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;return this.renderer.html(html)}case"paragraph":{return this.renderer.paragraph(this.inline.output(this.token.text))}case"text":{return this.renderer.paragraph(this.parseText())}}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function unescape(html){return html.replace(/&([#\w]+);/g,function(_,n){n=n.toLowerCase();if(n==="colon")return":";if(n.charAt(0)==="#"){return n.charAt(1)==="x"?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1))}return""})}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i=1,target,key;for(;i<arguments.length;i++){target=arguments[i];for(key in target){if(Object.prototype.hasOwnProperty.call(target,key)){obj[key]=target[key]}}}return obj}function marked(src,opt,callback){if(callback||typeof opt==="function"){if(!callback){callback=opt;opt=null}opt=merge({},marked.defaults,opt||{});var highlight=opt.highlight,tokens,pending,i=0;try{tokens=Lexer.lex(src,opt)}catch(e){return callback(e)}pending=tokens.length;var done=function(err){if(err){opt.highlight=highlight;return callback(err)}var out;try{out=Parser.parse(tokens,opt)}catch(e){err=e}opt.highlight=highlight;return err?callback(err):callback(null,out)};if(!highlight||highlight.length<3){return done()}delete opt.highlight;if(!pending)return done();for(;i<tokens.length;i++){(function(token){if(token.type!=="code"){return--pending||done()}return highlight(token.text,token.lang,function(err,code){if(err)return done(err);if(code==null||code===token.text){return--pending||done()}token.text=code;token.escaped=true;--pending||done()})})(tokens[i])}return}try{if(opt)opt=merge({},marked.defaults,opt);return Parser.parse(Lexer.lex(src,opt),opt)}catch(e){e.message+="\nPlease report this to https://github.com/chjj/marked.";if((opt||marked.defaults).silent){return"<p>An error occured:</p><pre>"+escape(e.message+"",true)+"</pre>"}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=marked}else if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}).call(function(){return this||(typeof window!=="undefined"?window:global)}());
+
+    marked.setOptions({
+        highlight: function (code, lang) {
+            if (typeof hljs === 'undefined') {
+                return code;
+            }
+            else if (lang) {
+                return hljs.highlight(lang, code, true).value;
+            }
+            else {
+                return hljs.highlightAuto(code).value;
+            }
+        }
+    });
+
+    function formatOptions(options) {
+        var gfm = options.githubFlavored;
+        if (gfm.ctor === 'Just') {
+            return {
+                gfm: true,
+                tables: gfm.tables,
+                breaks: gfm.breaks,
+                sanitize: options.sanitize,
+                smartypants: options.smartypants
+            }
+        }
+        else {
+            return {
+                gfm: false,
+                tables: false,
+                breaks: false,
+                sanitize: options.sanitize,
+                smartypants: options.smartypants
+            }
+        }
+    }
+
+    function toHtmlWith(options, rawMarkdown) {
+        var widget = {
+            type: "Widget",
+
+            init: function () {
+                var html = marked(rawMarkdown, formatOptions(options));
+                var div = document.createElement('div');
+                div.innerHTML = html;
+                return div;
+            },
+
+            update: function (previous, node) {
+                var html = marked(rawMarkdown, formatOptions(options));
+                node.innerHTML = html;
+                return node;
+            }
+        };
+        return widget;
+    }
+
+    function toElementWith(options, rawMarkdown) {
+        return Text.markdown(marked(rawMarkdown, formatOptions(options)));
+    }
+
+    return Elm.Native.Markdown.values = {
+        toHtmlWith: F2(toHtmlWith),
+        toElementWith: F2(toElementWith)
+    };
+};
+Elm.Native.Ports = {};
+Elm.Native.Ports.make = function(localRuntime) {
+    localRuntime.Native = localRuntime.Native || {};
+    localRuntime.Native.Ports = localRuntime.Native.Ports || {};
+    if (localRuntime.Native.Ports.values) {
+        return localRuntime.Native.Ports.values;
+    }
+
+    var Signal;
+
+    function incomingSignal(converter) {
+        converter.isSignal = true;
+        return converter;
+    }
+
+    function outgoingSignal(converter) {
+        if (!Signal) {
+            Signal = Elm.Signal.make(localRuntime);
+        }
+        return function(signal) {
+            var subscribers = []
+            function subscribe(handler) {
+                subscribers.push(handler);
+            }
+            function unsubscribe(handler) {
+                subscribers.pop(subscribers.indexOf(handler));
+            }
+            A2( Signal.map, function(value) {
+                var val = converter(value);
+                var len = subscribers.length;
+                for (var i = 0; i < len; ++i) {
+                    subscribers[i](val);
+                }
+            }, signal);
+            return { subscribe:subscribe, unsubscribe:unsubscribe };
+        }
+    }
+
+    function portIn(name, converter) {
+        var jsValue = localRuntime.ports.incoming[name];
+        if (jsValue === undefined) {
+            throw new Error("Initialization Error: port '" + name +
+                            "' was not given an input!");
+        }
+        localRuntime.ports.uses[name] += 1;
+        try {
+            var elmValue = converter(jsValue);
+        } catch(e) {
+            throw new Error("Initialization Error on port '" + name + "': \n" + e.message);
+        }
+
+        // just return a static value if it is not a signal
+        if (!converter.isSignal) {
+            return elmValue;
+        }
+
+        // create a signal if necessary
+        if (!Signal) {
+            Signal = Elm.Signal.make(localRuntime);
+        }
+        var signal = Signal.constant(elmValue);
+        function send(jsValue) {
+            try {
+                var elmValue = converter(jsValue);
+            } catch(e) {
+                throw new Error("Error sending to port '" + name + "': \n" + e.message);
+            }
+            setTimeout(function() {
+                localRuntime.notify(signal.id, elmValue);
+            }, 0);
+        }
+        localRuntime.ports.outgoing[name] = { send:send };
+        return signal;
+    }
+
+    function portOut(name, converter, value) {
+        try {
+            localRuntime.ports.outgoing[name] = converter(value);
+        } catch(e) {
+            throw new Error("Initialization Error on port '" + name + "': \n" + e.message);
+        }
+        return value;
+    }
+
+    return localRuntime.Native.Ports.values = {
+        incomingSignal: incomingSignal,
+        outgoingSignal: outgoingSignal,
+        portOut: portOut,
+        portIn: portIn
+    };
+};
+
+
+
+if (!Elm.fullscreen) {
+
+    (function() {
+        'use strict';
+
+        var Display = { FULLSCREEN: 0, COMPONENT: 1, NONE: 2 };
+
+        Elm.fullscreen = function(module, ports) {
+            var container = document.createElement('div');
+            document.body.appendChild(container);
+            return init(Display.FULLSCREEN, container, module, ports || {});
+        };
+
+        Elm.embed = function(module, container, ports) {
+            var tag = container.tagName;
+            if (tag !== 'DIV') {
+                throw new Error('Elm.node must be given a DIV, not a ' + tag + '.');
+            } else if (container.hasChildNodes()) {
+                throw new Error('Elm.node must be given an empty DIV. No children allowed!');
+            }
+            return init(Display.COMPONENT, container, module, ports || {});
+        };
+
+        Elm.worker = function(module, ports) {
+            return init(Display.NONE, {}, module, ports || {});
+        };
+
+        function init(display, container, module, ports, moduleToReplace) {
+          // defining state needed for an instance of the Elm RTS
+          var inputs = [];
+
+          /* OFFSET
+           * Elm's time traveling debugger lets you interrupt the smooth flow of time
+           * by pausing and continuing program execution. To ensure the user sees a
+           * program that moves smoothly through the pause/continue time gap,
+           * we need to adjsut the value of Date.now().
+           */
+          var timer = function() {
+            var inducedDelay = 0;
+
+            var now = function() {
+              return Date.now() - inducedDelay;
+            };
+
+            var addDelay = function(d) {
+              inducedDelay += d;
+              return inducedDelay;
+            };
+
+            return { now : now
+                   , addDelay : addDelay
+                   }
+          }();
+
+          var updateInProgress = false;
+          function notify(id, v) {
+              if (updateInProgress) {
+                  throw new Error(
+                      'The notify function has been called synchronously!\n' +
+                      'This can lead to frames being dropped.\n' +
+                      'Definitely report this to <https://github.com/elm-lang/Elm/issues>\n');
+              }
+              updateInProgress = true;
+              var timestep = timer.now();
+              for (var i = inputs.length; i--; ) {
+                  inputs[i].recv(timestep, id, v);
+              }
+              updateInProgress = false;
+          }
+          function setTimeout(func, delay) {
+            window.setTimeout(func, delay);
+          }
+
+          var listeners = [];
+          function addListener(relevantInputs, domNode, eventName, func) {
+              domNode.addEventListener(eventName, func);
+              var listener = {
+                  relevantInputs: relevantInputs,
+                  domNode: domNode,
+                  eventName: eventName,
+                  func: func
+              };
+              listeners.push(listener);
+          }
+
+          var portUses = {}
+          for (var key in ports) {
+              portUses[key] = 0;
+          }
+          // create the actual RTS. Any impure modules will attach themselves to this
+          // object. This permits many Elm programs to be embedded per document.
+          var elm = {
+              notify: notify,
+              setTimeout: setTimeout,
+              node: container,
+              addListener: addListener,
+              inputs: inputs,
+              timer: timer,
+              ports: { incoming:ports, outgoing:{}, uses:portUses },
+
+              isFullscreen: function() { return display === Display.FULLSCREEN; },
+              isEmbed: function() { return display === Display.COMPONENT; },
+              isWorker: function() { return display === Display.NONE; }
+          };
+
+          function swap(newModule) {
+              removeListeners(listeners);
+              var div = document.createElement('div');
+              var newElm = init(display, div, newModule, ports, elm);
+              inputs = [];
+              // elm.swap = newElm.swap;
+              return newElm;
+          }
+
+          function dispose() {
+            removeListeners(listeners);
+            inputs = [];
+          }
+
+          var Module = {};
+          try {
+              Module = module.make(elm);
+              checkPorts(elm);
+          } catch(e) {
+              var code = document.createElement('code');
+
+              var lines = e.message.split('\n');
+              code.appendChild(document.createTextNode(lines[0]));
+              code.appendChild(document.createElement('br'));
+              code.appendChild(document.createElement('br'));
+              for (var i = 1; i < lines.length; ++i) {
+                  code.appendChild(document.createTextNode('\u00A0 \u00A0 ' + lines[i]));
+                  code.appendChild(document.createElement('br'));
+              }
+              code.appendChild(document.createElement('br'));
+              code.appendChild(document.createTextNode("Open the developer console for more details."));
+
+              container.appendChild(code);
+              throw e;
+          }
+          inputs = filterDeadInputs(inputs);
+          filterListeners(inputs, listeners);
+          addReceivers(elm.ports.outgoing);
+          if (display !== Display.NONE) {
+              var graphicsNode = initGraphics(elm, Module);
+          }
+          if (typeof moduleToReplace !== 'undefined') {
+              hotSwap(moduleToReplace, elm);
+
+              // rerender scene if graphics are enabled.
+              if (typeof graphicsNode !== 'undefined') {
+                  graphicsNode.recv(0, true, 0);
+              }
+          }
+
+          return {
+            swap:swap,
+            ports:elm.ports.outgoing,
+            dispose:dispose
+          };
+        };
+
+        function checkPorts(elm) {
+            var portUses = elm.ports.uses;
+            for (var key in portUses) {
+                var uses = portUses[key]
+                if (uses === 0) {
+                    throw new Error(
+                        "Initialization Error: provided port '" + key +
+                        "' to a module that does not take it as in input.\n" +
+                        "Remove '" + key + "' from the module initialization code.");
+                } else if (uses > 1) {
+                    throw new Error(
+                        "Initialization Error: port '" + key +
+                        "' has been declared multiple times in the Elm code.\n" +
+                        "Remove declarations until there is exactly one.");
+                }
+            }
+        }
+
+
+        //// FILTER SIGNALS ////
+
+        // TODO: move this code into the signal module and create a function
+        // Signal.initializeGraph that actually instantiates everything.
+
+        function filterListeners(inputs, listeners) {
+            loop:
+            for (var i = listeners.length; i--; ) {
+                var listener = listeners[i];
+                for (var j = inputs.length; j--; ) {
+                    if (listener.relevantInputs.indexOf(inputs[j].id) >= 0) {
+                        continue loop;
+                    }
+                }
+                listener.domNode.removeEventListener(listener.eventName, listener.func);
+            }
+        }
+
+        function removeListeners(listeners) {
+            for (var i = listeners.length; i--; ) {
+                var listener = listeners[i];
+                listener.domNode.removeEventListener(listener.eventName, listener.func);
+            }
+        }
+
+        // add receivers for built-in ports if they are defined
+        function addReceivers(ports) {
+            if ('log' in ports) {
+                ports.log.subscribe(function(v) { console.log(v) });
+            }
+            if ('stdout' in ports) {
+                var process = process || {};
+                var handler = process.stdout
+                    ? function(v) { process.stdout.write(v); }
+                    : function(v) { console.log(v); };
+                ports.stdout.subscribe(handler);
+            }
+            if ('stderr' in ports) {
+                var process = process || {};
+                var handler = process.stderr
+                    ? function(v) { process.stderr.write(v); }
+                    : function(v) { console.log('Error:' + v); };
+                ports.stderr.subscribe(handler);
+            }
+            if ('title' in ports) {
+                if (typeof ports.title === 'string') {
+                    document.title = ports.title;
+                } else {
+                    ports.title.subscribe(function(v) { document.title = v; });
+                }
+            }
+            if ('redirect' in ports) {
+                ports.redirect.subscribe(function(v) {
+                    if (v.length > 0) window.location = v;
+                });
+            }
+            if ('favicon' in ports) {
+                if (typeof ports.favicon === 'string') {
+                    changeFavicon(ports.favicon);
+                } else {
+                    ports.favicon.subscribe(changeFavicon);
+                }
+            }
+            function changeFavicon(src) {
+                var link = document.createElement('link');
+                var oldLink = document.getElementById('elm-favicon');
+                link.id = 'elm-favicon';
+                link.rel = 'shortcut icon';
+                link.href = src;
+                if (oldLink) {
+                    document.head.removeChild(oldLink);
+                }
+                document.head.appendChild(link);
+            }
+        }
+
+
+        function filterDeadInputs(inputs) {
+            var temp = [];
+            for (var i = inputs.length; i--; ) {
+                if (isAlive(inputs[i])) temp.push(inputs[i]);
+            }
+            return temp;
+        }
+
+
+        function isAlive(input) {
+            if (!('defaultNumberOfKids' in input)) return true;
+            var len = input.kids.length;
+            if (len === 0) return false;
+            if (len > input.defaultNumberOfKids) return true;
+            var alive = false;
+            for (var i = len; i--; ) {
+                alive = alive || isAlive(input.kids[i]);
+            }
+            return alive;
+        }
+
+
+        ////  RENDERING  ////
+
+        function initGraphics(elm, Module) {
+          if (!('main' in Module)) {
+              throw new Error("'main' is missing! What do I display?!");
+          }
+
+          var signalGraph = Module.main;
+
+          // make sure the signal graph is actually a signal & extract the visual model
+          var Signal = Elm.Signal.make(elm);
+          if (!('recv' in signalGraph)) {
+              signalGraph = Signal.constant(signalGraph);
+          }
+          var currentScene = signalGraph.value;
+
+         // Add the currentScene to the DOM
+          var Element = Elm.Native.Graphics.Element.make(elm);
+          elm.node.appendChild(Element.render(currentScene));
+
+          // set up updates so that the DOM is adjusted as necessary.
+          var savedScene = currentScene;
+          var previousDrawId = 0;
+          function domUpdate(newScene) {
+              previousDrawId = draw(previousDrawId, function(_) {
+                  Element.updateAndReplace(elm.node.firstChild, savedScene, newScene);
+                  if (elm.Native.Window) {
+                      elm.Native.Window.values.resizeIfNeeded();
+                  }
+                  savedScene = newScene;
+              });
+          }
+          var renderer = A2(Signal.map, domUpdate, signalGraph);
+
+          // must check for resize after 'renderer' is created so
+          // that changes show up.
+          if (elm.Native.Window) {
+              elm.Native.Window.values.resizeIfNeeded();
+          }
+
+          return renderer;
+        }
+
+
+        // define function for drawing efficiently
+        //
+        //   draw : RequestID -> (() -> ()) -> RequestID
+        //
+        // Takes a "RequestID" allowing you to cancel old requests if possible.
+        // Returns a "RequestID" so you can refer to past requests.
+        //
+        function draw(previousRequestID, callback) {
+            callback();
+            return previousRequestID;
+        }
+
+        var vendors = ['ms', 'moz', 'webkit', 'o'];
+        var win = typeof window !== 'undefined' ? window : {};
+        for (var i = 0; i < vendors.length && !win.requestAnimationFrame; ++i) {
+            win.requestAnimationFrame = win[vendors[i]+'RequestAnimationFrame'];
+            win.cancelAnimationFrame  = win[vendors[i]+'CancelAnimationFrame'] ||
+                                        win[vendors[i]+'CancelRequestAnimationFrame'];
+        }
+        if (win.requestAnimationFrame && win.cancelAnimationFrame) {
+            draw = function(previousRequestID, callback) {
+                win.cancelAnimationFrame(previousRequestID);
+                return win.requestAnimationFrame(callback);
+            };
+        }
+
+
+        //// HOT SWAPPING ////
+
+        // Returns boolean indicating if the swap was successful.
+        // Requires that the two signal graphs have exactly the same
+        // structure.
+        function hotSwap(from, to) {
+            function similar(nodeOld,nodeNew) {
+                var idOkay = nodeOld.id === nodeNew.id;
+                var lengthOkay = nodeOld.kids.length === nodeNew.kids.length;
+                return idOkay && lengthOkay;
+            }
+            function swap(nodeOld,nodeNew) {
+                nodeNew.value = nodeOld.value;
+                return true;
+            }
+            var canSwap = depthFirstTraversals(similar, from.inputs, to.inputs);
+            if (canSwap) {
+                depthFirstTraversals(swap, from.inputs, to.inputs);
+            }
+            from.node.parentNode.replaceChild(to.node, from.node);
+
+            return canSwap;
+        }
+
+        // Returns false if the node operation f ever fails.
+        function depthFirstTraversals(f, queueOld, queueNew) {
+            if (queueOld.length !== queueNew.length) return false;
+            queueOld = queueOld.slice(0);
+            queueNew = queueNew.slice(0);
+
+            var seen = [];
+            while (queueOld.length > 0 && queueNew.length > 0) {
+                var nodeOld = queueOld.pop();
+                var nodeNew = queueNew.pop();
+                if (seen.indexOf(nodeOld.id) < 0) {
+                    if (!f(nodeOld, nodeNew)) return false;
+                    queueOld = queueOld.concat(nodeOld.kids);
+                    queueNew = queueNew.concat(nodeNew.kids);
+                    seen.push(nodeOld.id);
+                }
+            }
+            return true;
+        }
+    }());
+
+    function F2(fun) {
+      function wrapper(a) { return function(b) { return fun(a,b) } }
+      wrapper.arity = 2;
+      wrapper.func = fun;
+      return wrapper;
+    }
+
+    function F3(fun) {
+      function wrapper(a) {
+        return function(b) { return function(c) { return fun(a,b,c) }}
+      }
+      wrapper.arity = 3;
+      wrapper.func = fun;
+      return wrapper;
+    }
+
+    function F4(fun) {
+      function wrapper(a) { return function(b) { return function(c) {
+        return function(d) { return fun(a,b,c,d) }}}
+      }
+      wrapper.arity = 4;
+      wrapper.func = fun;
+      return wrapper;
+    }
+
+    function F5(fun) {
+      function wrapper(a) { return function(b) { return function(c) {
+        return function(d) { return function(e) { return fun(a,b,c,d,e) }}}}
+      }
+      wrapper.arity = 5;
+      wrapper.func = fun;
+      return wrapper;
+    }
+
+    function F6(fun) {
+      function wrapper(a) { return function(b) { return function(c) {
+        return function(d) { return function(e) { return function(f) {
+          return fun(a,b,c,d,e,f) }}}}}
+      }
+      wrapper.arity = 6;
+      wrapper.func = fun;
+      return wrapper;
+    }
+
+    function F7(fun) {
+      function wrapper(a) { return function(b) { return function(c) {
+        return function(d) { return function(e) { return function(f) {
+          return function(g) { return fun(a,b,c,d,e,f,g) }}}}}}
+      }
+      wrapper.arity = 7;
+      wrapper.func = fun;
+      return wrapper;
+    }
+
+    function F8(fun) {
+      function wrapper(a) { return function(b) { return function(c) {
+        return function(d) { return function(e) { return function(f) {
+      return function(g) { return function(h) {return fun(a,b,c,d,e,f,g,h)}}}}}}}
+      }
+      wrapper.arity = 8;
+      wrapper.func = fun;
+      return wrapper;
+    }
+
+    function F9(fun) {
+      function wrapper(a) { return function(b) { return function(c) {
+        return function(d) { return function(e) { return function(f) {
+      return function(g) { return function(h) { return function(i) {
+            return fun(a,b,c,d,e,f,g,h,i) }}}}}}}}
+      }
+      wrapper.arity = 9;
+      wrapper.func = fun;
+      return wrapper;
+    }
+
+    function A2(fun,a,b) {
+        return fun.arity === 2
+            ? fun.func(a,b)
+            : fun(a)(b);
+    }
+    function A3(fun,a,b,c) {
+        return fun.arity === 3
+            ? fun.func(a,b,c)
+            : fun(a)(b)(c);
+    }
+    function A4(fun,a,b,c,d) {
+        return fun.arity === 4
+            ? fun.func(a,b,c,d)
+            : fun(a)(b)(c)(d);
+    }
+    function A5(fun,a,b,c,d,e) {
+        return fun.arity === 5
+            ? fun.func(a,b,c,d,e)
+            : fun(a)(b)(c)(d)(e);
+    }
+    function A6(fun,a,b,c,d,e,f) {
+        return fun.arity === 6
+            ? fun.func(a,b,c,d,e,f)
+            : fun(a)(b)(c)(d)(e)(f);
+    }
+    function A7(fun,a,b,c,d,e,f,g) {
+        return fun.arity === 7
+            ? fun.func(a,b,c,d,e,f,g)
+            : fun(a)(b)(c)(d)(e)(f)(g);
+    }
+    function A8(fun,a,b,c,d,e,f,g,h) {
+        return fun.arity === 8
+            ? fun.func(a,b,c,d,e,f,g,h)
+            : fun(a)(b)(c)(d)(e)(f)(g)(h);
+    }
+    function A9(fun,a,b,c,d,e,f,g,h,i) {
+        return fun.arity === 9
+            ? fun.func(a,b,c,d,e,f,g,h,i)
+            : fun(a)(b)(c)(d)(e)(f)(g)(h)(i);
+    }
+}
+Elm.Native.Show = {};
+Elm.Native.Show.make = function(elm) {
+    elm.Native = elm.Native || {};
+    elm.Native.Show = elm.Native.Show || {};
+    if (elm.Native.Show.values) return elm.Native.Show.values;
+
+    var _Array;
+    var Dict;
+    var List;
+    var Utils = Elm.Native.Utils.make(elm);
+
+    var toString = function(v) {
+        var type = typeof v;
+        if (type === "function") {
+            var name = v.func ? v.func.name : v.name;
+            return '<function' + (name === '' ? '' : ': ') + name + '>';
+        }
+        else if (type === "boolean") {
+            return v ? "True" : "False";
+        }
+        else if (type === "number") {
+            return v + "";
+        }
+        else if ((v instanceof String) && v.isChar) {
+            return "'" + addSlashes(v) + "'";
+        }
+        else if (type === "string") {
+            return '"' + addSlashes(v) + '"';
+        }
+        else if (type === "object" && '_' in v && probablyPublic(v)) {
+            var output = [];
+            for (var k in v._) {
+                for (var i = v._[k].length; i--; ) {
+                    output.push(k + " = " + toString(v._[k][i]));
+                }
+            }
+            for (var k in v) {
+                if (k === '_') continue;
+                output.push(k + " = " + toString(v[k]));
+            }
+            if (output.length === 0) {
+                return "{}";
+            }
+            return "{ " + output.join(", ") + " }";
+        }
+        else if (type === "object" && 'ctor' in v) {
+            if (v.ctor.substring(0,6) === "_Tuple") {
+                var output = [];
+                for (var k in v) {
+                    if (k === 'ctor') continue;
+                    output.push(toString(v[k]));
+                }
+                return "(" + output.join(",") + ")";
+            }
+            else if (v.ctor === "_Array") {
+                if (!_Array) {
+                    _Array = Elm.Dict.make(elm);
+                }
+                var list = _Array.toList(v);
+                return "Array.fromList " + toString(list);
+            }
+            else if (v.ctor === "::") {
+                var output = '[' + toString(v._0);
+                v = v._1;
+                while (v.ctor === "::") {
+                    output += "," + toString(v._0);
+                    v = v._1;
+                }
+                return output + ']';
+            }
+            else if (v.ctor === "[]") {
+                return "[]";
+            }
+            else if (v.ctor === "RBNode" || v.ctor === "RBEmpty") {
+                if (!Dict) {
+                    Dict = Elm.Dict.make(elm);
+                }
+                if (!List) {
+                    List = Elm.List.make(elm);
+                }
+                var list = Dict.toList(v);
+                var name = "Dict";
+                if (list.ctor === "::" && list._0._1.ctor === "_Tuple0") {
+                    name = "Set";
+                    list = A2(List.map, function(x){return x._0}, list);
+                }
+                return name + ".fromList " + toString(list);
+            }
+            else {
+                var output = "";
+                for (var i in v) {
+                    if (i === 'ctor') continue;
+                    var str = toString(v[i]);
+                    var parenless = str[0] === '{' || str[0] === '<' || str.indexOf(' ') < 0;
+                    output += ' ' + (parenless ? str : '(' + str + ')');
+                }
+                return v.ctor + output;
+            }
+        }
+        if (type === 'object' && 'recv' in v) {
+            return '<signal>';
+        }
+        return "<internal structure>";
+    };
+
+    function addSlashes(str) {
+        return str.replace(/\\/g, '\\\\')
+                  .replace(/\n/g, '\\n')
+                  .replace(/\t/g, '\\t')
+                  .replace(/\r/g, '\\r')
+                  .replace(/\v/g, '\\v')
+                  .replace(/\0/g, '\\0')
+                  .replace(/\'/g, "\\'")
+                  .replace(/\"/g, '\\"');
+    }
+
+    function probablyPublic(v) {
+        var keys = Object.keys(v);
+        var len = keys.length;
+        if (len === 3
+            && 'props' in v
+            && 'element' in v)
+        {
+            return false;
+        }
+        else if (len === 5
+            && 'horizontal' in v
+            && 'vertical' in v
+            && 'x' in v
+            && 'y' in v)
+        {
+            return false;
+        }
+        else if (len === 7
+            && 'theta' in v
+            && 'scale' in v
+            && 'x' in v
+            && 'y' in v
+            && 'alpha' in v
+            && 'form' in v)
+        {
+            return false;
+        }
+        return true;
+    }
+
+    return elm.Native.Show.values = {
+        toString: toString
+    };
+};
+
+
+Elm.Native.Signal = {};
+Elm.Native.Signal.make = function(localRuntime) {
+
+  localRuntime.Native = localRuntime.Native || {};
+  localRuntime.Native.Signal = localRuntime.Native.Signal || {};
+  if (localRuntime.Native.Signal.values) {
+      return localRuntime.Native.Signal.values;
+  }
+
+  var Utils = Elm.Native.Utils.make(localRuntime);
+
+  function broadcastToKids(node, timestep, changed) {
+    var kids = node.kids;
+    for (var i = kids.length; i--; ) {
+      kids[i].recv(timestep, changed, node.id);
+    }
+  }
+
+  function Input(base) {
+    this.id = Utils.guid();
+    this.value = base;
+    this.kids = [];
+    this.defaultNumberOfKids = 0;
+    this.recv = function(timestep, eid, v) {
+      var changed = eid === this.id;
+      if (changed) {
+        this.value = v;
+      }
+      broadcastToKids(this, timestep, changed);
+      return changed;
+    };
+    localRuntime.inputs.push(this);
+  }
+
+  function LiftN(update, args) {
+    this.id = Utils.guid();
+    this.value = update();
+    this.kids = [];
+
+    var n = args.length;
+    var count = 0;
+    var isChanged = false;
+
+    this.recv = function(timestep, changed, parentID) {
+      ++count;
+      if (changed) { isChanged = true; }
+      if (count == n) {
+        if (isChanged) { this.value = update(); }
+        broadcastToKids(this, timestep, isChanged);
+        isChanged = false;
+        count = 0;
+      }
+    };
+    for (var i = n; i--; ) { args[i].kids.push(this); }
+  }
+
+  function map(func, a) {
+    function update() { return func(a.value); }
+    return new LiftN(update, [a]);
+  }
+  function map2(func, a, b) {
+    function update() { return A2( func, a.value, b.value ); }
+    return new LiftN(update, [a,b]);
+  }
+  function map3(func, a, b, c) {
+    function update() { return A3( func, a.value, b.value, c.value ); }
+    return new LiftN(update, [a,b,c]);
+  }
+  function map4(func, a, b, c, d) {
+    function update() { return A4( func, a.value, b.value, c.value, d.value ); }
+    return new LiftN(update, [a,b,c,d]);
+  }
+  function map5(func, a, b, c, d, e) {
+    function update() { return A5( func, a.value, b.value, c.value, d.value, e.value ); }
+    return new LiftN(update, [a,b,c,d,e]);
+  }
+
+  function Foldp(step, state, input) {
+    this.id = Utils.guid();
+    this.value = state;
+    this.kids = [];
+
+    this.recv = function(timestep, changed, parentID) {
+      if (changed) {
+          this.value = A2( step, input.value, this.value );
+      }
+      broadcastToKids(this, timestep, changed);
+    };
+    input.kids.push(this);
+  }
+
+  function foldp(step, state, input) {
+      return new Foldp(step, state, input);
+  }
+
+  function DropIf(pred,base,input) {
+    this.id = Utils.guid();
+    this.value = pred(input.value) ? base : input.value;
+    this.kids = [];
+    this.recv = function(timestep, changed, parentID) {
+      var chng = changed && !pred(input.value);
+      if (chng) { this.value = input.value; }
+      broadcastToKids(this, timestep, chng);
+    };
+    input.kids.push(this);
+  }
+
+  function DropRepeats(input) {
+    this.id = Utils.guid();
+    this.value = input.value;
+    this.kids = [];
+    this.recv = function(timestep, changed, parentID) {
+      var chng = changed && !Utils.eq(this.value,input.value);
+      if (chng) { this.value = input.value; }
+      broadcastToKids(this, timestep, chng);
+    };
+    input.kids.push(this);
+  }
+
+  function timestamp(a) {
+    function update() { return Utils.Tuple2(localRuntime.timer.now(), a.value); }
+    return new LiftN(update, [a]);
+  }
+
+  function SampleOn(s1,s2) {
+    this.id = Utils.guid();
+    this.value = s2.value;
+    this.kids = [];
+
+    var count = 0;
+    var isChanged = false;
+
+    this.recv = function(timestep, changed, parentID) {
+      if (parentID === s1.id) isChanged = changed;
+      ++count;
+      if (count == 2) {
+        if (isChanged) { this.value = s2.value; }
+        broadcastToKids(this, timestep, isChanged);
+        count = 0;
+        isChanged = false;
+      }
+    };
+    s1.kids.push(this);
+    s2.kids.push(this);
+  }
+
+  function sampleOn(s1,s2) { return new SampleOn(s1,s2); }
+
+  function delay(t,s) {
+      var delayed = new Input(s.value);
+      var firstEvent = true;
+      function update(v) {
+        if (firstEvent) {
+            firstEvent = false; return;
+        }
+        setTimeout(function() {
+            localRuntime.notify(delayed.id, v);
+        }, t);
+      }
+      function first(a,b) { return a; }
+      return new SampleOn(delayed, map2(F2(first), delayed, map(update,s)));
+  }
+
+  function Merge(s1,s2) {
+      this.id = Utils.guid();
+      this.value = s1.value;
+      this.kids = [];
+
+      var next = null;
+      var count = 0;
+      var isChanged = false;
+
+      this.recv = function(timestep, changed, parentID) {
+        ++count;
+        if (changed) {
+            isChanged = true;
+            if (parentID == s2.id && next === null) { next = s2.value; }
+            if (parentID == s1.id) { next = s1.value; }
+        }
+
+        if (count == 2) {
+            if (isChanged) { this.value = next; next = null; }
+            broadcastToKids(this, timestep, isChanged);
+            isChanged = false;
+            count = 0;
+        }
+      };
+      s1.kids.push(this);
+      s2.kids.push(this);
+  }
+
+  function merge(s1,s2) {
+      return new Merge(s1,s2);
+  }
+
+
+    // SIGNAL INPUTS
+
+    function input(initialValue) {
+        return new Input(initialValue);
+    }
+
+    function send(input, value) {
+        return function() {
+            localRuntime.notify(input.id, value);
+        };
+    }
+
+    function subscribe(input) {
+        return input;
+    }
+
+
+  return localRuntime.Native.Signal.values = {
+    constant : function(v) { return new Input(v); },
+    map  : F2(map ),
+    map2 : F3(map2),
+    map3 : F4(map3),
+    map4 : F5(map4),
+    map5 : F6(map5),
+    foldp : F3(foldp),
+    delay : F2(delay),
+    merge : F2(merge),
+    keepIf : F3(function(pred,base,sig) {
+      return new DropIf(function(x) {return !pred(x);},base,sig); }),
+    dropIf : F3(function(pred,base,sig) { return new DropIf(pred,base,sig); }),
+    dropRepeats : function(s) { return new DropRepeats(s);},
+    sampleOn : F2(sampleOn),
+    timestamp : timestamp,
+    input: input,
+    send: F2(send),
+    subscribe: subscribe
+  };
+};
+
+Elm.Native.Slider = {};
+Elm.Native.Slider.make = function(localRuntime) {
+
+    localRuntime.Native = localRuntime.Native || {};
+    localRuntime.Native.Slider = localRuntime.Native.Slider || {};
+    if (localRuntime.Native.Slider.values) {
+        return localRuntime.Native.Slider.values;
+    }
+
+    var Element = Elm.Graphics.Element.make(localRuntime);
+    var NativeElement = Elm.Native.Graphics.Element.make(localRuntime);
+
+    function renderSlider(model) {
+        var node = NativeElement.createNode('input');
+        node.type = 'range';
+
+        node.min = model.styling.min;
+        node.max = model.styling.max;
+        node.step = model.styling.step;
+        node.value = model.styling.value;
+
+        if (!model.styling.horizontal) {
+            node.orient = "vertical"; // FF
+            node.style.webkitAppearance = "slider-vertical"; // webkit
+            node.style.writingMode = "bt-lr"; // ie
+        }
+
+        if (model.styling.disabled) {
+            node.disabled = true;
+        }
+
+        node.style.display = 'block';
+        node.style.pointerEvents = 'auto';
+        node.elm_handler = model.handler;
+        node.addEventListener('input', notifySlider);
+        node.addEventListener('change', notifySlider);
+        function notifySlider() {
+            node.elm_handler(node.value)();
+        }
+        return node;
+    }
+
+    function updateSlider(node, oldModel, newModel) {
+        if (newModel.styling.disabled) {
+            node.disabled = true;
+        } else {
+            node.disabled = false;
+        }
+        node.elm_handler = newModel.handler;
+        node.min = newModel.styling.min;
+        node.max = newModel.styling.max;
+        node.step = newModel.styling.step;
+        node.value = newModel.styling.value;
+
+        return node;
+    }
+
+    function slider(handler, styling) {
+        var width = styling.length;
+        var height = 24;
+        if (!styling.horizontal) {
+            var temp = width;
+            width = height;
+            height = temp;
+        }
+        return A3(Element.newElement, width, height, {
+            ctor: 'Custom',
+            type: 'Slider',
+            render: renderSlider,
+            update: updateSlider,
+            model: { handler:handler, styling:styling }
+        });
+    }
+
+    return localRuntime.Native.Slider.values = {
+        slider: F2(slider)
+    };
+}
+
+Elm.Native.String = {};
+Elm.Native.String.make = function(elm) {
+    elm.Native = elm.Native || {};
+    elm.Native.String = elm.Native.String || {};
+    if (elm.Native.String.values) return elm.Native.String.values;
+    if ('values' in Elm.Native.String) {
+        return elm.Native.String.values = Elm.Native.String.values;
+    }
+
+    var Char = Elm.Char.make(elm);
+    var List = Elm.Native.List.make(elm);
+    var Maybe = Elm.Maybe.make(elm);
+    var Result = Elm.Result.make(elm);
+    var Utils = Elm.Native.Utils.make(elm);
+
+    function isEmpty(str) {
+        return str.length === 0;
+    }
+    function cons(chr,str) {
+        return chr + str;
+    }
+    function uncons(str) {
+        var hd;
+        return (hd = str[0])
+            ? Maybe.Just(Utils.Tuple2(Utils.chr(hd), str.slice(1)))
+            : Maybe.Nothing;
+    }
+    function append(a,b) {
+        return a + b;
+    }
+    function concat(strs) {
+        return List.toArray(strs).join('');
+    }
+    function length(str) {
+        return str.length;
+    }
+    function map(f,str) {
+        var out = str.split('');
+        for (var i = out.length; i--; ) {
+            out[i] = f(Utils.chr(out[i]));
+        }
+        return out.join('');
+    }
+    function filter(pred,str) {
+        return str.split('').map(Utils.chr).filter(pred).join('');
+    }
+    function reverse(str) {
+        return str.split('').reverse().join('');
+    }
+    function foldl(f,b,str) {
+        var len = str.length;
+        for (var i = 0; i < len; ++i) {
+            b = A2(f, Utils.chr(str[i]), b);
+        }
+        return b;
+    }
+    function foldr(f,b,str) {
+        for (var i = str.length; i--; ) {
+            b = A2(f, Utils.chr(str[i]), b);
+        }
+        return b;
+    }
+
+    function split(sep, str) {
+        return List.fromArray(str.split(sep));
+    }
+    function join(sep, strs) {
+        return List.toArray(strs).join(sep);
+    }
+    function repeat(n, str) {
+        var result = '';
+        while (n > 0) {
+            if (n & 1) result += str;
+            n >>= 1, str += str;
+        }
+        return result;
+    }
+
+    function slice(start, end, str) {
+        return str.slice(start,end);
+    }
+    function left(n, str) {
+        return n < 1 ? "" : str.slice(0,n);
+    }
+    function right(n, str) {
+        return n < 1 ? "" : str.slice(-n);
+    }
+    function dropLeft(n, str) {
+        return n < 1 ? str : str.slice(n);
+    }
+    function dropRight(n, str) {
+        return n < 1 ? str : str.slice(0,-n);
+    }
+
+    function pad(n,chr,str) {
+        var half = (n - str.length) / 2;
+        return repeat(Math.ceil(half),chr) + str + repeat(half|0,chr);
+    }
+    function padRight(n,chr,str) {
+        return str + repeat(n - str.length, chr);
+    }
+    function padLeft(n,chr,str) {
+        return repeat(n - str.length, chr) + str;
+    }
+
+    function trim(str) {
+        return str.trim();
+    }
+    function trimLeft(str) {
+        return str.trimLeft();
+    }
+    function trimRight(str) {
+        return str.trimRight();
+    }
+
+    function words(str) {
+        return List.fromArray(str.trim().split(/\s+/g));
+    }
+    function lines(str) {
+        return List.fromArray(str.split(/\r\n|\r|\n/g));
+    }
+
+    function toUpper(str) {
+        return str.toUpperCase();
+    }
+    function toLower(str) {
+        return str.toLowerCase();
+    }
+
+    function any(pred, str) {
+        for (var i = str.length; i--; ) {
+            if (pred(Utils.chr(str[i]))) return true;
+        }
+        return false;
+    }
+    function all(pred, str) {
+        for (var i = str.length; i--; ) {
+            if (!pred(Utils.chr(str[i]))) return false;
+        }
+        return true;
+    }
+
+    function contains(sub, str) {
+        return str.indexOf(sub) > -1;
+    }
+    function startsWith(sub, str) {
+        return str.indexOf(sub) === 0;
+    }
+    function endsWith(sub, str) {
+        return str.length >= sub.length &&
+               str.lastIndexOf(sub) === str.length - sub.length;
+    }
+    function indexes(sub, str) {
+        var subLen = sub.length;
+        var i = 0;
+        var is = [];
+        while ((i = str.indexOf(sub, i)) > -1) {
+            is.push(i);
+            i = i + subLen;
+        }
+        return List.fromArray(is);
+    }
+
+    function toInt(s) {
+        var len = s.length;
+        if (len === 0) {
+            return Result.Err("could not convert string '" + s + "' to an Int" );
+        }
+        var start = 0;
+        if (s[0] == '-') {
+            if (len === 1) {
+                return Result.Err("could not convert string '" + s + "' to an Int" );
+            }
+            start = 1;
+        }
+        for (var i = start; i < len; ++i) {
+            if (!Char.isDigit(s[i])) {
+                return Result.Err("could not convert string '" + s + "' to an Int" );
+            }
+        }
+        return Result.Ok(parseInt(s, 10));
+    }
+
+    function toFloat(s) {
+        var len = s.length;
+        if (len === 0) {
+            return Result.Err("could not convert string '" + s + "' to a Float" );
+        }
+        var start = 0;
+        if (s[0] == '-') {
+            if (len === 1) {
+                return Result.Err("could not convert string '" + s + "' to a Float" );
+            }
+            start = 1;
+        }
+        var dotCount = 0;
+        for (var i = start; i < len; ++i) {
+            if (Char.isDigit(s[i])) {
+                continue;
+            }
+            if (s[i] === '.') {
+                dotCount += 1;
+                if (dotCount <= 1) {
+                    continue;
+                }
+            }
+            return Result.Err("could not convert string '" + s + "' to a Float" );
+        }
+        return Result.Ok(parseFloat(s));
+    }
+
+    function toList(str) {
+        return List.fromArray(str.split('').map(Utils.chr));
+    }
+    function fromList(chars) {
+        return List.toArray(chars).join('');
+    }
+
+    return Elm.Native.String.values = {
+        isEmpty: isEmpty,
+        cons: F2(cons),
+        uncons: uncons,
+        append: F2(append),
+        concat: concat,
+        length: length,
+        map: F2(map),
+        filter: F2(filter),
+        reverse: reverse,
+        foldl: F3(foldl),
+        foldr: F3(foldr),
+
+        split: F2(split),
+        join: F2(join),
+        repeat: F2(repeat),
+
+        slice: F3(slice),
+        left: F2(left),
+        right: F2(right),
+        dropLeft: F2(dropLeft),
+        dropRight: F2(dropRight),
+
+        pad: F3(pad),
+        padLeft: F3(padLeft),
+        padRight: F3(padRight),
+
+        trim: trim,
+        trimLeft: trimLeft,
+        trimRight: trimRight,
+
+        words: words,
+        lines: lines,
+
+        toUpper: toUpper,
+        toLower: toLower,
+
+        any: F2(any),
+        all: F2(all),
+
+        contains: F2(contains),
+        startsWith: F2(startsWith),
+        endsWith: F2(endsWith),
+        indexes: F2(indexes),
+
+        toInt: toInt,
+        toFloat: toFloat,
+        toList: toList,
+        fromList: fromList
+    };
+};
+
+Elm.Native.Text = {};
+Elm.Native.Text.make = function(elm) {
+    elm.Native = elm.Native || {};
+    elm.Native.Text = elm.Native.Text || {};
+    if (elm.Native.Text.values) return elm.Native.Text.values;
+
+    var toCss = Elm.Native.Color.make(elm).toCss;
+    var Element = Elm.Graphics.Element.make(elm);
+    var NativeElement = Elm.Native.Graphics.Element.make(elm);
+    var List = Elm.Native.List.make(elm);
+    var Utils = Elm.Native.Utils.make(elm);
+
+    function makeSpaces(s) {
+        if (s.length == 0) { return s; }
+        var arr = s.split('');
+        if (arr[0] == ' ') { arr[0] = "&nbsp;" }      
+        for (var i = arr.length; --i; ) {
+            if (arr[i][0] == ' ' && arr[i-1] == ' ') {
+                arr[i-1] = arr[i-1] + arr[i];
+                arr[i] = '';
+            }
+        }
+        for (var i = arr.length; i--; ) {
+            if (arr[i].length > 1 && arr[i][0] == ' ') {
+                var spaces = arr[i].split('');
+                for (var j = spaces.length - 2; j >= 0; j -= 2) {
+                    spaces[j] = '&nbsp;';
+                }
+                arr[i] = spaces.join('');
+            }
+        }
+        arr = arr.join('');
+        if (arr[arr.length-1] === " ") {
+            return arr.slice(0,-1) + '&nbsp;';
+        }
+        return arr;
+    }
+
+    function properEscape(str) {
+        if (str.length == 0) return str;
+        str = str //.replace(/&/g,  "&#38;")
+            .replace(/"/g,  '&#34;')
+            .replace(/'/g,  "&#39;")
+            .replace(/</g,  "&#60;")
+            .replace(/>/g,  "&#62;")
+            .replace(/\n/g, "<br/>");
+        var arr = str.split('<br/>');
+        for (var i = arr.length; i--; ) {
+            arr[i] = makeSpaces(arr[i]);
+        }
+        return arr.join('<br/>');
+    }
+
+    function fromString(str) {
+        return Utils.txt(properEscape(str));
+    }
+
+    function append(xs, ys) {
+        return Utils.txt(Utils.makeText(xs) + Utils.makeText(ys));
+    }
+
+    // conversions from Elm values to CSS
+    function toTypefaces(list) {
+        var typefaces = List.toArray(list);
+        for (var i = typefaces.length; i--; ) {
+            var typeface = typefaces[i];
+            if (typeface.indexOf(' ') > -1) {
+                typefaces[i] = "'" + typeface + "'";
+            }
+        }
+        return typefaces.join(',');
+    }
+    function toLine(line) {
+        var ctor = line.ctor;
+        return ctor === 'Under' ? 'underline' :
+               ctor === 'Over'  ? 'overline'  : 'line-through';
+    }
+
+    // setting styles of Text
+    function style(style, text) {
+        var newText = '<span style="color:' + toCss(style.color) + ';'
+        if (style.typeface.ctor !== '[]') {
+            newText += 'font-family:' + toTypefaces(style.typeface) + ';'
+        }
+        if (style.height.ctor !== "Nothing") {
+            newText += 'font-size:' + style.height._0 + 'px;';
+        }
+        if (style.bold) {
+            newText += 'font-weight:bold;';
+        }
+        if (style.italic) {
+            newText += 'font-style:italic;';
+        }
+        if (style.line.ctor !== 'Nothing') {
+            newText += 'text-decoration:' + toLine(style.line._0) + ';';
+        }
+        newText += '">' + Utils.makeText(text) + '</span>'
+        return Utils.txt(newText);
+    }
+    function height(px, text) {
+        return { style: 'font-size:' + px + 'px;', text:text }
+    }
+    function typeface(names, text) {
+        return { style: 'font-family:' + toTypefaces(names) + ';', text:text }
+    }
+    function monospace(text) {
+        return { style: 'font-family:monospace;', text:text }
+    }
+    function italic(text) {
+        return { style: 'font-style:italic;', text:text }
+    }
+    function bold(text) {
+        return { style: 'font-weight:bold;', text:text }
+    }
+    function link(href, text) {
+        return { href: fromString(href), text:text };
+    }
+    function line(line, text) {
+        return { style: 'text-decoration:' + toLine(line) + ';', text:text };
+    }
+
+    function color(color, text) {
+        return { style: 'color:' + toCss(color) + ';', text:text };
+    }
+
+    function block(align) {
+        return function(text) {
+            var raw = {
+                ctor :'RawHtml',
+                html : Utils.makeText(text),
+                align: align,
+                guid : null
+            };
+            var pos = A2(NativeElement.htmlHeight, 0, raw);
+            return A3(Element.newElement, pos._0, pos._1, raw);
+        }
+    }
+
+    function markdown(text, guid) {
+        var raw = {
+            ctor:'RawHtml',
+            html: text,
+            align: null,
+            guid: guid
+        };
+        var pos = A2(NativeElement.htmlHeight, 0, raw);
+        return A3(Element.newElement, pos._0, pos._1, raw);
+    }
+
+    return elm.Native.Text.values = {
+        fromString: fromString,
+        append: F2(append),
+
+        height : F2(height),
+        italic : italic,
+        bold : bold,
+        line : F2(line),
+        monospace : monospace,
+        typeface : F2(typeface),
+        color : F2(color),
+        link : F2(link),
+        style : F2(style),
+
+        leftAligned  : block('left'),
+        rightAligned : block('right'),
+        centered     : block('center'),
+        justified    : block('justify'),
+        markdown     : markdown,
+
+        toTypefaces:toTypefaces,
+        toLine:toLine
+    };
+};
+
+Elm.Native.Transform2D = {};
+Elm.Native.Transform2D.make = function(elm) {
+
+ elm.Native = elm.Native || {};
+ elm.Native.Transform2D = elm.Native.Transform2D || {};
+ if (elm.Native.Transform2D.values) return elm.Native.Transform2D.values;
+
+ var A;
+ if (typeof Float32Array === 'undefined') {
+     A = function(arr) {
+         this.length = arr.length;
+         this[0] = arr[0];
+         this[1] = arr[1];
+         this[2] = arr[2];
+         this[3] = arr[3];
+         this[4] = arr[4];
+         this[5] = arr[5];
+     };
+ } else {
+     A = Float32Array;
+ }
+
+ // layout of matrix in an array is
+ //
+ //   | m11 m12 dx |
+ //   | m21 m22 dy |
+ //   |  0   0   1 |
+ //
+ //  new A([ m11, m12, dx, m21, m22, dy ])
+
+ var identity = new A([1,0,0,0,1,0]);
+ function matrix(m11, m12, m21, m22, dx, dy) {
+     return new A([m11, m12, dx, m21, m22, dy]);
+ }
+ function rotation(t) {
+     var c = Math.cos(t);
+     var s = Math.sin(t);
+     return new A([c, -s, 0, s, c, 0]);
+ }
+ function rotate(t,m) {
+     var c = Math.cos(t);
+     var s = Math.sin(t);
+     var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4];
+     return new A([m11*c + m12*s, -m11*s + m12*c, m[2],
+                   m21*c + m22*s, -m21*s + m22*c, m[5]]);
+ }
+ /*
+ function move(xy,m) {
+     var x = xy._0;
+     var y = xy._1;
+     var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4];
+     return new A([m11, m12, m11*x + m12*y + m[2],
+                   m21, m22, m21*x + m22*y + m[5]]);
+ }
+ function scale(s,m) { return new A([m[0]*s, m[1]*s, m[2], m[3]*s, m[4]*s, m[5]]); }
+ function scaleX(x,m) { return new A([m[0]*x, m[1], m[2], m[3]*x, m[4], m[5]]); }
+ function scaleY(y,m) { return new A([m[0], m[1]*y, m[2], m[3], m[4]*y, m[5]]); }
+ function reflectX(m) { return new A([-m[0], m[1], m[2], -m[3], m[4], m[5]]); }
+ function reflectY(m) { return new A([m[0], -m[1], m[2], m[3], -m[4], m[5]]); }
+
+ function transform(m11, m21, m12, m22, mdx, mdy, n) {
+     var n11 = n[0], n12 = n[1], n21 = n[3], n22 = n[4], ndx = n[2], ndy = n[5];
+     return new A([m11*n11 + m12*n21,
+                   m11*n12 + m12*n22,
+                   m11*ndx + m12*ndy + mdx,
+                   m21*n11 + m22*n21,
+                   m21*n12 + m22*n22,
+                   m21*ndx + m22*ndy + mdy]);
+ }
+ */
+ function multiply(m, n) {
+     var m11 = m[0], m12 = m[1], m21 = m[3], m22 = m[4], mdx = m[2], mdy = m[5];
+     var n11 = n[0], n12 = n[1], n21 = n[3], n22 = n[4], ndx = n[2], ndy = n[5];
+     return new A([m11*n11 + m12*n21,
+                   m11*n12 + m12*n22,
+                   m11*ndx + m12*ndy + mdx,
+                   m21*n11 + m22*n21,
+                   m21*n12 + m22*n22,
+                   m21*ndx + m22*ndy + mdy]);
+ }
+
+ return elm.Native.Transform2D.values = {
+     identity:identity,
+     matrix:F6(matrix),
+     rotation:rotation,
+     multiply:F2(multiply)
+     /*
+     transform:F7(transform),
+     rotate:F2(rotate),
+     move:F2(move),
+     scale:F2(scale),
+     scaleX:F2(scaleX),
+     scaleY:F2(scaleY),
+     reflectX:reflectX,
+     reflectY:reflectY
+     */
+ };
+
+};
+
+Elm.Native = Elm.Native || {};
+Elm.Native.Utils = {};
+Elm.Native.Utils.make = function(localRuntime) {
+
+    localRuntime.Native = localRuntime.Native || {};
+    localRuntime.Native.Utils = localRuntime.Native.Utils || {};
+    if (localRuntime.Native.Utils.values) {
+        return localRuntime.Native.Utils.values;
+    }
+
+    function eq(l,r) {
+        var stack = [{'x': l, 'y': r}]
+        while (stack.length > 0) {
+            var front = stack.pop();
+            var x = front.x;
+            var y = front.y;
+            if (x === y) continue;
+            if (typeof x === "object") {
+                var c = 0;
+                for (var i in x) {
+                    ++c;
+                    if (i in y) {
+                        if (i !== 'ctor') {
+                            stack.push({ 'x': x[i], 'y': y[i] });
+                        }
+                    } else {
+                        return false;
+                    }
+                }
+                if ('ctor' in x) {
+                    stack.push({'x': x.ctor, 'y': y.ctor});
+                }
+                if (c !== Object.keys(y).length) {
+                    return false;
+                };
+            } else if (typeof x === 'function') {
+                throw new Error('Equality error: general function equality is ' +
+                                'undecidable, and therefore, unsupported');
+            } else {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    // code in Generate/JavaScript.hs depends on the particular
+    // integer values assigned to LT, EQ, and GT
+    var LT = -1, EQ = 0, GT = 1, ord = ['LT','EQ','GT'];
+    function compare(x,y) { return { ctor: ord[cmp(x,y)+1] } }
+    function cmp(x,y) {
+        var ord;
+        if (typeof x !== 'object'){
+            return x === y ? EQ : x < y ? LT : GT;
+        }
+        else if (x.isChar){
+            var a = x.toString();
+            var b = y.toString();
+            return a === b ? EQ : a < b ? LT : GT;
+        }
+        else if (x.ctor === "::" || x.ctor === "[]") {
+            while (true) {
+                if (x.ctor === "[]" && y.ctor === "[]") return EQ;
+                if (x.ctor !== y.ctor) return x.ctor === '[]' ? LT : GT;
+                ord = cmp(x._0, y._0);
+                if (ord !== EQ) return ord;
+                x = x._1;
+                y = y._1;
+            }
+        }
+        else if (x.ctor.slice(0,6) === '_Tuple') {
+            var n = x.ctor.slice(6) - 0;
+            var err = 'cannot compare tuples with more than 6 elements.';
+            if (n === 0) return EQ;
+            if (n >= 1) { ord = cmp(x._0, y._0); if (ord !== EQ) return ord;
+            if (n >= 2) { ord = cmp(x._1, y._1); if (ord !== EQ) return ord;
+            if (n >= 3) { ord = cmp(x._2, y._2); if (ord !== EQ) return ord;
+            if (n >= 4) { ord = cmp(x._3, y._3); if (ord !== EQ) return ord;
+            if (n >= 5) { ord = cmp(x._4, y._4); if (ord !== EQ) return ord;
+            if (n >= 6) { ord = cmp(x._5, y._5); if (ord !== EQ) return ord;
+            if (n >= 7) throw new Error('Comparison error: ' + err); } } } } } }
+            return EQ;
+        }
+        else {
+            throw new Error('Comparison error: comparison is only defined on ints, ' +
+                            'floats, times, chars, strings, lists of comparable values, ' +
+                            'and tuples of comparable values.');
+        }
+    }
+
+
+    var Tuple0 = { ctor: "_Tuple0" };
+    function Tuple2(x,y) {
+        return {
+            ctor: "_Tuple2",
+            _0: x,
+            _1: y
+        };
+    }
+
+    function chr(c) {
+        var x = new String(c);
+        x.isChar = true;
+        return x;
+    }
+
+    function txt(str) {
+        var t = new String(str);
+        t.text = true;
+        return t;
+    }
+
+    function makeText(text) {
+        var style = '';
+        var href = '';
+        while (true) {
+            if (text.style) {
+                style += text.style;
+                text = text.text;
+                continue;
+            }
+            if (text.href) {
+                href = text.href;
+                text = text.text;
+                continue;
+            }
+            if (href) {
+                text = '<a href="' + href + '">' + text + '</a>';
+            }
+            if (style) {
+                text = '<span style="' + style + '">' + text + '</span>';
+            }
+            return text;
+        }
+    }
+
+    var count = 0;
+    function guid(_) {
+        return count++
+    }
+
+    function copy(oldRecord) {
+        var newRecord = {};
+        for (var key in oldRecord) {
+            var value = key === '_'
+                ? copy(oldRecord._)
+                : oldRecord[key]
+                ;
+            newRecord[key] = value;
+        }
+        return newRecord;
+    }
+
+    function remove(key, oldRecord) {
+        var record = copy(oldRecord);
+        if (key in record._) {
+            record[key] = record._[key][0];
+            record._[key] = record._[key].slice(1);
+            if (record._[key].length === 0) {
+                delete record._[key];
+            }
+        } else {
+            delete record[key];
+        }
+        return record;
+    }
+
+    function replace(keyValuePairs, oldRecord) {
+        var record = copy(oldRecord);
+        for (var i = keyValuePairs.length; i--; ) {
+            var pair = keyValuePairs[i];
+            record[pair[0]] = pair[1];
+        }
+        return record;
+    }
+
+    function insert(key, value, oldRecord) {
+        var newRecord = copy(oldRecord);
+        if (key in newRecord) {
+            var values = newRecord._[key];
+            var copiedValues = values ? values.slice(0) : [];
+            newRecord._[key] = [newRecord[key]].concat(copiedValues);
+        }
+        newRecord[key] = value;
+        return newRecord;
+    }
+
+    function getXY(e) {
+        var posx = 0;
+        var posy = 0;
+        if (e.pageX || e.pageY) {
+            posx = e.pageX;
+            posy = e.pageY;
+        } else if (e.clientX || e.clientY) {
+            posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
+            posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
+        }
+
+        if (localRuntime.isEmbed()) {
+            var rect = localRuntime.node.getBoundingClientRect();
+            var relx = rect.left + document.body.scrollLeft + document.documentElement.scrollLeft;
+            var rely = rect.top + document.body.scrollTop + document.documentElement.scrollTop;
+            // TODO: figure out if there is a way to avoid rounding here
+            posx = posx - Math.round(relx) - localRuntime.node.clientLeft;
+            posy = posy - Math.round(rely) - localRuntime.node.clientTop;
+        }
+        return Tuple2(posx, posy);
+    }
+
+
+    //// LIST STUFF ////
+
+    var Nil = { ctor:'[]' };
+
+    function Cons(hd,tl) {
+        return {
+            ctor: "::",
+            _0: hd,
+            _1: tl
+        };
+    }
+
+    function append(xs,ys) {
+        // append Text
+        if (xs.text || ys.text) {
+            return txt(makeText(xs) + makeText(ys));
+        }
+
+        // append Strings
+        if (typeof xs === "string") {
+            return xs + ys;
+        }
+
+        // append Lists
+        if (xs.ctor === '[]') {
+            return ys;
+        }
+        var root = Cons(xs._0, Nil);
+        var curr = root;
+        xs = xs._1;
+        while (xs.ctor !== '[]') {
+            curr._1 = Cons(xs._0, Nil);
+            xs = xs._1;
+            curr = curr._1;
+        }
+        curr._1 = ys;
+        return root;
+    }
+
+    //// RUNTIME ERRORS ////
+
+    function indent(lines) {
+        return '\n' + lines.join('\n');
+    }
+
+    function badCase(moduleName, span) { 
+        var msg = indent([
+            'Non-exhaustive pattern match in case-expression.',
+            'Make sure your patterns cover every case!'
+        ]);
+        throw new Error('Runtime error in module ' + moduleName + ' (' + span + ')' + msg);
+    }
+
+    function badIf(moduleName, span) { 
+        var msg = indent([
+            'Non-exhaustive pattern match in multi-way-if expression.',
+            'It is best to use \'otherwise\' as the last branch of multi-way-if.'
+        ]);
+        throw new Error('Runtime error in module ' + moduleName + ' (' + span + ')' + msg);
+    }
+
+
+    function badPort(expected, received) { 
+        var msg = indent([
+            'Expecting ' + expected + ' but was given ',
+            JSON.stringify(received)
+        ]);
+        throw new Error('Runtime error when sending values through a port.' + msg);
+    }
+
+
+    return localRuntime.Native.Utils.values = {
+        eq:eq,
+        cmp:cmp,
+        compare:F2(compare),
+        Tuple0:Tuple0,
+        Tuple2:Tuple2,
+        chr:chr,
+        txt:txt,
+        makeText:makeText,
+        copy: copy,
+        remove: remove,
+        replace: replace,
+        insert: insert,
+        guid: guid,
+        getXY: getXY,
+
+        Nil: Nil,
+        Cons: Cons,
+        append: F2(append),
+
+        badCase: badCase,
+        badIf: badIf,
+        badPort: badPort
+    };
+};
+
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+module.exports = createHash
+
+function createHash(elem) {
+    var attributes = elem.attributes
+    var hash = {}
+
+    if (attributes === null || attributes === undefined) {
+        return hash
+    }
+
+    for (var i = 0; i < attributes.length; i++) {
+        var attr = attributes[i]
+
+        if (attr.name.substr(0,5) !== "data-") {
+            continue
+        }
+
+        hash[attr.name.substr(5)] = attr.value
+    }
+
+    return hash
+}
+
+},{}],2:[function(require,module,exports){
+var createStore = require("weakmap-shim/create-store")
+var Individual = require("individual")
+
+var createHash = require("./create-hash.js")
+
+var hashStore = Individual("__DATA_SET_WEAKMAP@3", createStore())
+
+module.exports = DataSet
+
+function DataSet(elem) {
+    var store = hashStore(elem)
+
+    if (!store.hash) {
+        store.hash = createHash(elem)
+    }
+
+    return store.hash
+}
+
+},{"./create-hash.js":1,"individual":3,"weakmap-shim/create-store":4}],3:[function(require,module,exports){
+(function (global){
+var root = typeof window !== 'undefined' ?
+    window : typeof global !== 'undefined' ?
+    global : {};
+
+module.exports = Individual
+
+function Individual(key, value) {
+    if (root[key]) {
+        return root[key]
+    }
+
+    Object.defineProperty(root, key, {
+        value: value
+        , configurable: true
+    })
+
+    return value
+}
+
+}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{}],4:[function(require,module,exports){
+var hiddenStore = require('./hidden-store.js');
+
+module.exports = createStore;
+
+function createStore() {
+    var key = {};
+
+    return function (obj) {
+        if (typeof obj !== 'object' || obj === null) {
+            throw new Error('Weakmap-shim: Key must be object')
+        }
+
+        var store = obj.valueOf(key);
+        return store && store.identity === key ?
+            store : hiddenStore(obj, key);
+    };
+}
+
+},{"./hidden-store.js":5}],5:[function(require,module,exports){
+module.exports = hiddenStore;
+
+function hiddenStore(obj, key) {
+    var store = { identity: key };
+    var valueOf = obj.valueOf;
+
+    Object.defineProperty(obj, "valueOf", {
+        value: function (value) {
+            return value !== key ?
+                valueOf.apply(this, arguments) : store;
+        },
+        writable: true
+    });
+
+    return store;
+}
+
+},{}],6:[function(require,module,exports){
+var DataSet = require("data-set")
+
+module.exports = addEvent
+
+function addEvent(target, type, handler) {
+    var ds = DataSet(target)
+    var events = ds[type]
+
+    if (!events) {
+        ds[type] = handler
+    } else if (Array.isArray(events)) {
+        if (events.indexOf(handler) === -1) {
+            events.push(handler)
+        }
+    } else if (events !== handler) {
+        ds[type] = [events, handler]
+    }
+}
+
+},{"data-set":2}],7:[function(require,module,exports){
+var globalDocument = require("global/document")
+var DataSet = require("data-set")
+var createStore = require("weakmap-shim/create-store")
+
+var addEvent = require("./add-event.js")
+var removeEvent = require("./remove-event.js")
+var ProxyEvent = require("./proxy-event.js")
+
+var HANDLER_STORE = createStore()
+
+module.exports = DOMDelegator
+
+function DOMDelegator(document) {
+    document = document || globalDocument
+
+    this.target = document.documentElement
+    this.events = {}
+    this.rawEventListeners = {}
+    this.globalListeners = {}
+}
+
+DOMDelegator.prototype.addEventListener = addEvent
+DOMDelegator.prototype.removeEventListener = removeEvent
+
+DOMDelegator.prototype.allocateHandle =
+    function allocateHandle(func) {
+        var handle = new Handle()
+
+        HANDLER_STORE(handle).func = func;
+
+        return handle
+    }
+
+DOMDelegator.prototype.transformHandle =
+    function transformHandle(handle, lambda) {
+        var func = HANDLER_STORE(handle).func
+
+        return this.allocateHandle(function (ev) {
+            var result = lambda(ev)
+            if (result) {
+                func(result)
+            }
+        })
+    }
+
+DOMDelegator.prototype.addGlobalEventListener =
+    function addGlobalEventListener(eventName, fn) {
+        var listeners = this.globalListeners[eventName] || [];
+        if (listeners.indexOf(fn) === -1) {
+            listeners.push(fn)
+        }
+
+        this.globalListeners[eventName] = listeners;
+    }
+
+DOMDelegator.prototype.removeGlobalEventListener =
+    function removeGlobalEventListener(eventName, fn) {
+        var listeners = this.globalListeners[eventName] || [];
+
+        var index = listeners.indexOf(fn)
+        if (index !== -1) {
+            listeners.splice(index, 1)
+        }
+    }
+
+DOMDelegator.prototype.listenTo = function listenTo(eventName) {
+    if (this.events[eventName]) {
+        return
+    }
+
+    this.events[eventName] = true
+
+    var listener = this.rawEventListeners[eventName]
+    if (!listener) {
+        listener = this.rawEventListeners[eventName] =
+            createHandler(eventName, this)
+    }
+
+    this.target.addEventListener(eventName, listener, true)
+}
+
+DOMDelegator.prototype.unlistenTo = function unlistenTo(eventName) {
+    if (!this.events[eventName]) {
+        return
+    }
+
+    this.events[eventName] = false
+    var listener = this.rawEventListeners[eventName]
+
+    if (!listener) {
+        throw new Error("dom-delegator#unlistenTo: cannot " +
+            "unlisten to " + eventName)
+    }
+
+    this.target.removeEventListener(eventName, listener, true)
+}
+
+function createHandler(eventName, delegator) {
+    var globalListeners = delegator.globalListeners;
+    var delegatorTarget = delegator.target;
+
+    return handler
+
+    function handler(ev) {
+        var globalHandlers = globalListeners[eventName] || []
+
+        if (globalHandlers.length > 0) {
+            var globalEvent = new ProxyEvent(ev);
+            globalEvent.currentTarget = delegatorTarget;
+            callListeners(globalHandlers, globalEvent)
+        }
+
+        findAndInvokeListeners(ev.target, ev, eventName)
+    }
+}
+
+function findAndInvokeListeners(elem, ev, eventName) {
+    var listener = getListener(elem, eventName)
+
+    if (listener && listener.handlers.length > 0) {
+        var listenerEvent = new ProxyEvent(ev);
+        listenerEvent.currentTarget = listener.currentTarget
+        callListeners(listener.handlers, listenerEvent)
+
+        if (listenerEvent._bubbles) {
+            var nextTarget = listener.currentTarget.parentNode
+            findAndInvokeListeners(nextTarget, ev, eventName)
+        }
+    }
+}
+
+function getListener(target, type) {
+    // terminate recursion if parent is `null`
+    if (target === null) {
+        return null
+    }
+
+    var ds = DataSet(target)
+    // fetch list of handler fns for this event
+    var handler = ds[type]
+    var allHandler = ds.event
+
+    if (!handler && !allHandler) {
+        return getListener(target.parentNode, type)
+    }
+
+    var handlers = [].concat(handler || [], allHandler || [])
+    return new Listener(target, handlers)
+}
+
+function callListeners(handlers, ev) {
+    handlers.forEach(function (handler) {
+        if (typeof handler === "function") {
+            handler(ev)
+        } else if (typeof handler.handleEvent === "function") {
+            handler.handleEvent(ev)
+        } else if (handler.type === "dom-delegator-handle") {
+            HANDLER_STORE(handler).func(ev)
+        } else {
+            throw new Error("dom-delegator: unknown handler " +
+                "found: " + JSON.stringify(handlers));
+        }
+    })
+}
+
+function Listener(target, handlers) {
+    this.currentTarget = target
+    this.handlers = handlers
+}
+
+function Handle() {
+    this.type = "dom-delegator-handle"
+}
+
+},{"./add-event.js":6,"./proxy-event.js":15,"./remove-event.js":16,"data-set":2,"global/document":10,"weakmap-shim/create-store":13}],8:[function(require,module,exports){
+var Individual = require("individual")
+var cuid = require("cuid")
+var globalDocument = require("global/document")
+
+var DOMDelegator = require("./dom-delegator.js")
+
+var delegatorCache = Individual("__DOM_DELEGATOR_CACHE@9", {
+    delegators: {}
+})
+var commonEvents = [
+    "blur", "change", "click",  "contextmenu", "dblclick",
+    "error","focus", "focusin", "focusout", "input", "keydown",
+    "keypress", "keyup", "load", "mousedown", "mouseup",
+    "resize", "scroll", "select", "submit", "touchcancel",
+    "touchend", "touchstart", "unload"
+]
+
+/*  Delegator is a thin wrapper around a singleton `DOMDelegator`
+        instance.
+
+    Only one DOMDelegator should exist because we do not want
+        duplicate event listeners bound to the DOM.
+
+    `Delegator` will also `listenTo()` all events unless 
+        every caller opts out of it
+*/
+module.exports = Delegator
+
+function Delegator(opts) {
+    opts = opts || {}
+    var document = opts.document || globalDocument
+
+    var cacheKey = document["__DOM_DELEGATOR_CACHE_TOKEN@9"]
+
+    if (!cacheKey) {
+        cacheKey =
+            document["__DOM_DELEGATOR_CACHE_TOKEN@9"] = cuid()
+    }
+
+    var delegator = delegatorCache.delegators[cacheKey]
+
+    if (!delegator) {
+        delegator = delegatorCache.delegators[cacheKey] =
+            new DOMDelegator(document)
+    }
+
+    if (opts.defaultEvents !== false) {
+        for (var i = 0; i < commonEvents.length; i++) {
+            delegator.listenTo(commonEvents[i])
+        }
+    }
+
+    return delegator
+}
+
+
+
+},{"./dom-delegator.js":7,"cuid":9,"global/document":10,"individual":11}],9:[function(require,module,exports){
+/**
+ * cuid.js
+ * Collision-resistant UID generator for browsers and node.
+ * Sequential for fast db lookups and recency sorting.
+ * Safe for element IDs and server-side lookups.
+ *
+ * Extracted from CLCTR
+ * 
+ * Copyright (c) Eric Elliott 2012
+ * MIT License
+ */
+
+/*global window, navigator, document, require, process, module */
+(function (app) {
+  'use strict';
+  var namespace = 'cuid',
+    c = 0,
+    blockSize = 4,
+    base = 36,
+    discreteValues = Math.pow(base, blockSize),
+
+    pad = function pad(num, size) {
+      var s = "000000000" + num;
+      return s.substr(s.length-size);
+    },
+
+    randomBlock = function randomBlock() {
+      return pad((Math.random() *
+            discreteValues << 0)
+            .toString(base), blockSize);
+    },
+
+    safeCounter = function () {
+      c = (c < discreteValues) ? c : 0;
+      c++; // this is not subliminal
+      return c - 1;
+    },
+
+    api = function cuid() {
+      // Starting with a lowercase letter makes
+      // it HTML element ID friendly.
+      var letter = 'c', // hard-coded allows for sequential access
+
+        // timestamp
+        // warning: this exposes the exact date and time
+        // that the uid was created.
+        timestamp = (new Date().getTime()).toString(base),
+
+        // Prevent same-machine collisions.
+        counter,
+
+        // A few chars to generate distinct ids for different
+        // clients (so different computers are far less
+        // likely to generate the same id)
+        fingerprint = api.fingerprint(),
+
+        // Grab some more chars from Math.random()
+        random = randomBlock() + randomBlock();
+
+        counter = pad(safeCounter().toString(base), blockSize);
+
+      return  (letter + timestamp + counter + fingerprint + random);
+    };
+
+  api.slug = function slug() {
+    var date = new Date().getTime().toString(36),
+      counter,
+      print = api.fingerprint().slice(0,1) +
+        api.fingerprint().slice(-1),
+      random = randomBlock().slice(-2);
+
+      counter = safeCounter().toString(36).slice(-4);
+
+    return date.slice(-2) + 
+      counter + print + random;
+  };
+
+  api.globalCount = function globalCount() {
+    // We want to cache the results of this
+    var cache = (function calc() {
+        var i,
+          count = 0;
+
+        for (i in window) {
+          count++;
+        }
+
+        return count;
+      }());
+
+    api.globalCount = function () { return cache; };
+    return cache;
+  };
+
+  api.fingerprint = function browserPrint() {
+    return pad((navigator.mimeTypes.length +
+      navigator.userAgent.length).toString(36) +
+      api.globalCount().toString(36), 4);
+  };
+
+  // don't change anything from here down.
+  if (app.register) {
+    app.register(namespace, api);
+  } else if (typeof module !== 'undefined') {
+    module.exports = api;
+  } else {
+    app[namespace] = api;
+  }
+
+}(this.applitude || this));
+
+},{}],10:[function(require,module,exports){
+(function (global){
+var topLevel = typeof global !== 'undefined' ? global :
+    typeof window !== 'undefined' ? window : {}
+var minDoc = require('min-document');
+
+if (typeof document !== 'undefined') {
+    module.exports = document;
+} else {
+    var doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];
+
+    if (!doccy) {
+        doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;
+    }
+
+    module.exports = doccy;
+}
+
+}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"min-document":40}],11:[function(require,module,exports){
+module.exports=require(3)
+},{}],12:[function(require,module,exports){
+if (typeof Object.create === 'function') {
+  // implementation from standard node.js 'util' module
+  module.exports = function inherits(ctor, superCtor) {
+    ctor.super_ = superCtor
+    ctor.prototype = Object.create(superCtor.prototype, {
+      constructor: {
+        value: ctor,
+        enumerable: false,
+        writable: true,
+        configurable: true
+      }
+    });
+  };
+} else {
+  // old school shim for old browsers
+  module.exports = function inherits(ctor, superCtor) {
+    ctor.super_ = superCtor
+    var TempCtor = function () {}
+    TempCtor.prototype = superCtor.prototype
+    ctor.prototype = new TempCtor()
+    ctor.prototype.constructor = ctor
+  }
+}
+
+},{}],13:[function(require,module,exports){
+module.exports=require(4)
+},{"./hidden-store.js":14}],14:[function(require,module,exports){
+module.exports=require(5)
+},{}],15:[function(require,module,exports){
+var inherits = require("inherits")
+
+var ALL_PROPS = [
+    "altKey", "bubbles", "cancelable", "ctrlKey",
+    "eventPhase", "metaKey", "relatedTarget", "shiftKey",
+    "target", "timeStamp", "type", "view", "which"
+]
+var KEY_PROPS = ["char", "charCode", "key", "keyCode"]
+var MOUSE_PROPS = [
+    "button", "buttons", "clientX", "clientY", "layerX",
+    "layerY", "offsetX", "offsetY", "pageX", "pageY",
+    "screenX", "screenY", "toElement"
+]
+
+var rkeyEvent = /^key|input/
+var rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/
+
+module.exports = ProxyEvent
+
+function ProxyEvent(ev) {
+    if (!(this instanceof ProxyEvent)) {
+        return new ProxyEvent(ev)
+    }
+
+    if (rkeyEvent.test(ev.type)) {
+        return new KeyEvent(ev)
+    } else if (rmouseEvent.test(ev.type)) {
+        return new MouseEvent(ev)
+    }
+
+    for (var i = 0; i < ALL_PROPS.length; i++) {
+        var propKey = ALL_PROPS[i]
+        this[propKey] = ev[propKey]
+    }
+
+    this._rawEvent = ev
+    this._bubbles = false;
+}
+
+ProxyEvent.prototype.preventDefault = function () {
+    this._rawEvent.preventDefault()
+}
+
+ProxyEvent.prototype.startPropagation = function () {
+    this._bubbles = true;
+}
+
+function MouseEvent(ev) {
+    for (var i = 0; i < ALL_PROPS.length; i++) {
+        var propKey = ALL_PROPS[i]
+        this[propKey] = ev[propKey]
+    }
+
+    for (var j = 0; j < MOUSE_PROPS.length; j++) {
+        var mousePropKey = MOUSE_PROPS[j]
+        this[mousePropKey] = ev[mousePropKey]
+    }
+
+    this._rawEvent = ev
+}
+
+inherits(MouseEvent, ProxyEvent)
+
+function KeyEvent(ev) {
+    for (var i = 0; i < ALL_PROPS.length; i++) {
+        var propKey = ALL_PROPS[i]
+        this[propKey] = ev[propKey]
+    }
+
+    for (var j = 0; j < KEY_PROPS.length; j++) {
+        var keyPropKey = KEY_PROPS[j]
+        this[keyPropKey] = ev[keyPropKey]
+    }
+
+    this._rawEvent = ev
+}
+
+inherits(KeyEvent, ProxyEvent)
+
+},{"inherits":12}],16:[function(require,module,exports){
+var DataSet = require("data-set")
+
+module.exports = removeEvent
+
+function removeEvent(target, type, handler) {
+    var ds = DataSet(target)
+    var events = ds[type]
+
+    if (!events) {
+        return
+    } else if (Array.isArray(events)) {
+        var index = events.indexOf(handler)
+        if (index !== -1) {
+            events.splice(index, 1)
+        }
+    } else if (events === handler) {
+        ds[type] = null
+    }
+}
+
+},{"data-set":2}],17:[function(require,module,exports){
+var isObject = require("is-object")
+var isHook = require("vtree/is-vhook")
+
+module.exports = applyProperties
+
+function applyProperties(node, props, previous) {
+    for (var propName in props) {
+        var propValue = props[propName]
+
+        if (propValue === undefined) {
+            removeProperty(node, props, previous, propName);
+        } else if (isHook(propValue)) {
+            propValue.hook(node,
+                propName,
+                previous ? previous[propName] : undefined)
+        } else {
+            if (isObject(propValue)) {
+                patchObject(node, props, previous, propName, propValue);
+            } else if (propValue !== undefined) {
+                node[propName] = propValue
+            }
+        }
+    }
+}
+
+function removeProperty(node, props, previous, propName) {
+    if (previous) {
+        var previousValue = previous[propName]
+
+        if (!isHook(previousValue)) {
+            if (propName === "attributes") {
+                for (var attrName in previousValue) {
+                    node.removeAttribute(attrName)
+                }
+            } else if (propName === "style") {
+                for (var i in previousValue) {
+                    node.style[i] = ""
+                }
+            } else if (typeof previousValue === "string") {
+                node[propName] = ""
+            } else {
+                node[propName] = null
+            }
+        }
+    }
+}
+
+function patchObject(node, props, previous, propName, propValue) {
+    var previousValue = previous ? previous[propName] : undefined
+
+    // Set attributes
+    if (propName === "attributes") {
+        for (var attrName in propValue) {
+            var attrValue = propValue[attrName]
+
+            if (attrValue === undefined) {
+                node.removeAttribute(attrName)
+            } else {
+                node.setAttribute(attrName, attrValue)
+            }
+        }
+
+        return
+    }
+
+    if(previousValue && isObject(previousValue) &&
+        getPrototype(previousValue) !== getPrototype(propValue)) {
+        node[propName] = propValue
+        return
+    }
+
+    if (!isObject(node[propName])) {
+        node[propName] = {}
+    }
+
+    var replacer = propName === "style" ? "" : undefined
+
+    for (var k in propValue) {
+        var value = propValue[k]
+        node[propName][k] = (value === undefined) ? replacer : value
+    }
+}
+
+function getPrototype(value) {
+    if (Object.getPrototypeOf) {
+        return Object.getPrototypeOf(value)
+    } else if (value.__proto__) {
+        return value.__proto__
+    } else if (value.constructor) {
+        return value.constructor.prototype
+    }
+}
+
+},{"is-object":21,"vtree/is-vhook":29}],18:[function(require,module,exports){
+var document = require("global/document")
+
+var applyProperties = require("./apply-properties")
+
+var isVNode = require("vtree/is-vnode")
+var isVText = require("vtree/is-vtext")
+var isWidget = require("vtree/is-widget")
+var handleThunk = require("vtree/handle-thunk")
+
+module.exports = createElement
+
+function createElement(vnode, opts) {
+    var doc = opts ? opts.document || document : document
+    var warn = opts ? opts.warn : null
+
+    vnode = handleThunk(vnode).a
+
+    if (isWidget(vnode)) {
+        return vnode.init()
+    } else if (isVText(vnode)) {
+        return doc.createTextNode(vnode.text)
+    } else if (!isVNode(vnode)) {
+        if (warn) {
+            warn("Item is not a valid virtual dom node", vnode)
+        }
+        return null
+    }
+
+    var node = (vnode.namespace === null) ?
+        doc.createElement(vnode.tagName) :
+        doc.createElementNS(vnode.namespace, vnode.tagName)
+
+    var props = vnode.properties
+    applyProperties(node, props)
+
+    var children = vnode.children
+
+    for (var i = 0; i < children.length; i++) {
+        var childNode = createElement(children[i], opts)
+        if (childNode) {
+            node.appendChild(childNode)
+        }
+    }
+
+    return node
+}
+
+},{"./apply-properties":17,"global/document":20,"vtree/handle-thunk":27,"vtree/is-vnode":30,"vtree/is-vtext":31,"vtree/is-widget":32}],19:[function(require,module,exports){
+// Maps a virtual DOM tree onto a real DOM tree in an efficient manner.
+// We don't want to read all of the DOM nodes in the tree so we use
+// the in-order tree indexing to eliminate recursion down certain branches.
+// We only recurse into a DOM node if we know that it contains a child of
+// interest.
+
+var noChild = {}
+
+module.exports = domIndex
+
+function domIndex(rootNode, tree, indices, nodes) {
+    if (!indices || indices.length === 0) {
+        return {}
+    } else {
+        indices.sort(ascending)
+        return recurse(rootNode, tree, indices, nodes, 0)
+    }
+}
+
+function recurse(rootNode, tree, indices, nodes, rootIndex) {
+    nodes = nodes || {}
+
+
+    if (rootNode) {
+        if (indexInRange(indices, rootIndex, rootIndex)) {
+            nodes[rootIndex] = rootNode
+        }
+
+        var vChildren = tree.children
+
+        if (vChildren) {
+
+            var childNodes = rootNode.childNodes
+
+            for (var i = 0; i < tree.children.length; i++) {
+                rootIndex += 1
+
+                var vChild = vChildren[i] || noChild
+                var nextIndex = rootIndex + (vChild.count || 0)
+
+                // skip recursion down the tree if there are no nodes down here
+                if (indexInRange(indices, rootIndex, nextIndex)) {
+                    recurse(childNodes[i], vChild, indices, nodes, rootIndex)
+                }
+
+                rootIndex = nextIndex
+            }
+        }
+    }
+
+    return nodes
+}
+
+// Binary search for an index in the interval [left, right]
+function indexInRange(indices, left, right) {
+    if (indices.length === 0) {
+        return false
+    }
+
+    var minIndex = 0
+    var maxIndex = indices.length - 1
+    var currentIndex
+    var currentItem
+
+    while (minIndex <= maxIndex) {
+        currentIndex = ((maxIndex + minIndex) / 2) >> 0
+        currentItem = indices[currentIndex]
+
+        if (minIndex === maxIndex) {
+            return currentItem >= left && currentItem <= right
+        } else if (currentItem < left) {
+            minIndex = currentIndex + 1
+        } else  if (currentItem > right) {
+            maxIndex = currentIndex - 1
+        } else {
+            return true
+        }
+    }
+
+    return false;
+}
+
+function ascending(a, b) {
+    return a > b ? 1 : -1
+}
+
+},{}],20:[function(require,module,exports){
+module.exports=require(10)
+},{"min-document":40}],21:[function(require,module,exports){
+module.exports = isObject
+
+function isObject(x) {
+    return typeof x === "object" && x !== null
+}
+
+},{}],22:[function(require,module,exports){
+var nativeIsArray = Array.isArray
+var toString = Object.prototype.toString
+
+module.exports = nativeIsArray || isArray
+
+function isArray(obj) {
+    return toString.call(obj) === "[object Array]"
+}
+
+},{}],23:[function(require,module,exports){
+var applyProperties = require("./apply-properties")
+
+var isWidget = require("vtree/is-widget")
+var VPatch = require("vtree/vpatch")
+
+var render = require("./create-element")
+var updateWidget = require("./update-widget")
+
+module.exports = applyPatch
+
+function applyPatch(vpatch, domNode, renderOptions) {
+    var type = vpatch.type
+    var vNode = vpatch.vNode
+    var patch = vpatch.patch
+
+    switch (type) {
+        case VPatch.REMOVE:
+            return removeNode(domNode, vNode)
+        case VPatch.INSERT:
+            return insertNode(domNode, patch, renderOptions)
+        case VPatch.VTEXT:
+            return stringPatch(domNode, vNode, patch, renderOptions)
+        case VPatch.WIDGET:
+            return widgetPatch(domNode, vNode, patch, renderOptions)
+        case VPatch.VNODE:
+            return vNodePatch(domNode, vNode, patch, renderOptions)
+        case VPatch.ORDER:
+            reorderChildren(domNode, patch)
+            return domNode
+        case VPatch.PROPS:
+            applyProperties(domNode, patch, vNode.properties)
+            return domNode
+        case VPatch.THUNK:
+            return replaceRoot(domNode,
+                renderOptions.patch(domNode, patch, renderOptions))
+        default:
+            return domNode
+    }
+}
+
+function removeNode(domNode, vNode) {
+    var parentNode = domNode.parentNode
+
+    if (parentNode) {
+        parentNode.removeChild(domNode)
+    }
+
+    destroyWidget(domNode, vNode);
+
+    return null
+}
+
+function insertNode(parentNode, vNode, renderOptions) {
+    var newNode = render(vNode, renderOptions)
+
+    if (parentNode) {
+        parentNode.appendChild(newNode)
+    }
+
+    return parentNode
+}
+
+function stringPatch(domNode, leftVNode, vText, renderOptions) {
+    var newNode
+
+    if (domNode.nodeType === 3) {
+        domNode.replaceData(0, domNode.length, vText.text)
+        newNode = domNode
+    } else {
+        var parentNode = domNode.parentNode
+        newNode = render(vText, renderOptions)
+
+        if (parentNode) {
+            parentNode.replaceChild(newNode, domNode)
+        }
+    }
+
+    destroyWidget(domNode, leftVNode)
+
+    return newNode
+}
+
+function widgetPatch(domNode, leftVNode, widget, renderOptions) {
+    if (updateWidget(leftVNode, widget)) {
+        return widget.update(leftVNode, domNode) || domNode
+    }
+
+    var parentNode = domNode.parentNode
+    var newWidget = render(widget, renderOptions)
+
+    if (parentNode) {
+        parentNode.replaceChild(newWidget, domNode)
+    }
+
+    destroyWidget(domNode, leftVNode)
+
+    return newWidget
+}
+
+function vNodePatch(domNode, leftVNode, vNode, renderOptions) {
+    var parentNode = domNode.parentNode
+    var newNode = render(vNode, renderOptions)
+
+    if (parentNode) {
+        parentNode.replaceChild(newNode, domNode)
+    }
+
+    destroyWidget(domNode, leftVNode)
+
+    return newNode
+}
+
+function destroyWidget(domNode, w) {
+    if (typeof w.destroy === "function" && isWidget(w)) {
+        w.destroy(domNode)
+    }
+}
+
+function reorderChildren(domNode, bIndex) {
+    var children = []
+    var childNodes = domNode.childNodes
+    var len = childNodes.length
+    var i
+    var reverseIndex = bIndex.reverse
+
+    for (i = 0; i < len; i++) {
+        children.push(domNode.childNodes[i])
+    }
+
+    var insertOffset = 0
+    var move
+    var node
+    var insertNode
+    for (i = 0; i < len; i++) {
+        move = bIndex[i]
+        if (move !== undefined && move !== i) {
+            // the element currently at this index will be moved later so increase the insert offset
+            if (reverseIndex[i] > i) {
+                insertOffset++
+            }
+
+            node = children[move]
+            insertNode = childNodes[i + insertOffset] || null
+            if (node !== insertNode) {
+                domNode.insertBefore(node, insertNode)
+            }
+
+            // the moved element came from the front of the array so reduce the insert offset
+            if (move < i) {
+                insertOffset--
+            }
+        }
+
+        // element at this index is scheduled to be removed so increase insert offset
+        if (i in bIndex.removes) {
+            insertOffset++
+        }
+    }
+}
+
+function replaceRoot(oldRoot, newRoot) {
+    if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) {
+        console.log(oldRoot)
+        oldRoot.parentNode.replaceChild(newRoot, oldRoot)
+    }
+
+    return newRoot;
+}
+
+},{"./apply-properties":17,"./create-element":18,"./update-widget":25,"vtree/is-widget":32,"vtree/vpatch":37}],24:[function(require,module,exports){
+var document = require("global/document")
+var isArray = require("x-is-array")
+
+var domIndex = require("./dom-index")
+var patchOp = require("./patch-op")
+module.exports = patch
+
+function patch(rootNode, patches) {
+    return patchRecursive(rootNode, patches)
+}
+
+function patchRecursive(rootNode, patches, renderOptions) {
+    var indices = patchIndices(patches)
+
+    if (indices.length === 0) {
+        return rootNode
+    }
+
+    var index = domIndex(rootNode, patches.a, indices)
+    var ownerDocument = rootNode.ownerDocument
+
+    if (!renderOptions) {
+        renderOptions = { patch: patchRecursive }
+        if (ownerDocument !== document) {
+            renderOptions.document = ownerDocument
+        }
+    }
+
+    for (var i = 0; i < indices.length; i++) {
+        var nodeIndex = indices[i]
+        rootNode = applyPatch(rootNode,
+            index[nodeIndex],
+            patches[nodeIndex],
+            renderOptions)
+    }
+
+    return rootNode
+}
+
+function applyPatch(rootNode, domNode, patchList, renderOptions) {
+    if (!domNode) {
+        return rootNode
+    }
+
+    var newNode
+
+    if (isArray(patchList)) {
+        for (var i = 0; i < patchList.length; i++) {
+            newNode = patchOp(patchList[i], domNode, renderOptions)
+
+            if (domNode === rootNode) {
+                rootNode = newNode
+            }
+        }
+    } else {
+        newNode = patchOp(patchList, domNode, renderOptions)
+
+        if (domNode === rootNode) {
+            rootNode = newNode
+        }
+    }
+
+    return rootNode
+}
+
+function patchIndices(patches) {
+    var indices = []
+
+    for (var key in patches) {
+        if (key !== "a") {
+            indices.push(Number(key))
+        }
+    }
+
+    return indices
+}
+
+},{"./dom-index":19,"./patch-op":23,"global/document":20,"x-is-array":22}],25:[function(require,module,exports){
+var isWidget = require("vtree/is-widget")
+
+module.exports = updateWidget
+
+function updateWidget(a, b) {
+    if (isWidget(a) && isWidget(b)) {
+        if ("name" in a && "name" in b) {
+            return a.id === b.id
+        } else {
+            return a.init === b.init
+        }
+    }
+
+    return false
+}
+
+},{"vtree/is-widget":32}],26:[function(require,module,exports){
+var isArray = require("x-is-array")
+var isObject = require("is-object")
+
+var VPatch = require("./vpatch")
+var isVNode = require("./is-vnode")
+var isVText = require("./is-vtext")
+var isWidget = require("./is-widget")
+var isThunk = require("./is-thunk")
+var handleThunk = require("./handle-thunk")
+
+module.exports = diff
+
+function diff(a, b) {
+    var patch = { a: a }
+    walk(a, b, patch, 0)
+    return patch
+}
+
+function walk(a, b, patch, index) {
+    if (a === b) {
+        if (isThunk(a) || isThunk(b)) {
+            thunks(a, b, patch, index)
+        } else {
+            hooks(b, patch, index)
+        }
+        return
+    }
+
+    var apply = patch[index]
+
+    if (b == null) {
+        apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b))
+        destroyWidgets(a, patch, index)
+    } else if (isThunk(a) || isThunk(b)) {
+        thunks(a, b, patch, index)
+    } else if (isVNode(b)) {
+        if (isVNode(a)) {
+            if (a.tagName === b.tagName &&
+                a.namespace === b.namespace &&
+                a.key === b.key) {
+                var propsPatch = diffProps(a.properties, b.properties, b.hooks)
+                if (propsPatch) {
+                    apply = appendPatch(apply,
+                        new VPatch(VPatch.PROPS, a, propsPatch))
+                }
+                apply = diffChildren(a, b, patch, apply, index)
+            } else {
+                apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b))
+                destroyWidgets(a, patch, index)
+            }
+        } else {
+            apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b))
+            destroyWidgets(a, patch, index)
+        }
+    } else if (isVText(b)) {
+        if (!isVText(a)) {
+            apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b))
+            destroyWidgets(a, patch, index)
+        } else if (a.text !== b.text) {
+            apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b))
+        }
+    } else if (isWidget(b)) {
+        apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b))
+
+        if (!isWidget(a)) {
+            destroyWidgets(a, patch, index)
+        }
+    }
+
+    if (apply) {
+        patch[index] = apply
+    }
+}
+
+function diffProps(a, b, hooks) {
+    var diff
+
+    for (var aKey in a) {
+        if (!(aKey in b)) {
+            diff = diff || {}
+            diff[aKey] = undefined
+        }
+
+        var aValue = a[aKey]
+        var bValue = b[aKey]
+
+        if (hooks && aKey in hooks) {
+            diff = diff || {}
+            diff[aKey] = bValue
+        } else {
+            if (isObject(aValue) && isObject(bValue)) {
+                if (getPrototype(bValue) !== getPrototype(aValue)) {
+                    diff = diff || {}
+                    diff[aKey] = bValue
+                } else {
+                    var objectDiff = diffProps(aValue, bValue)
+                    if (objectDiff) {
+                        diff = diff || {}
+                        diff[aKey] = objectDiff
+                    }
+                }
+            } else if (aValue !== bValue) {
+                diff = diff || {}
+                diff[aKey] = bValue
+            }
+        }
+    }
+
+    for (var bKey in b) {
+        if (!(bKey in a)) {
+            diff = diff || {}
+            diff[bKey] = b[bKey]
+        }
+    }
+
+    return diff
+}
+
+function getPrototype(value) {
+    if (Object.getPrototypeOf) {
+        return Object.getPrototypeOf(value)
+    } else if (value.__proto__) {
+        return value.__proto__
+    } else if (value.constructor) {
+        return value.constructor.prototype
+    }
+}
+
+function diffChildren(a, b, patch, apply, index) {
+    var aChildren = a.children
+    var bChildren = reorder(aChildren, b.children)
+
+    var aLen = aChildren.length
+    var bLen = bChildren.length
+    var len = aLen > bLen ? aLen : bLen
+
+    for (var i = 0; i < len; i++) {
+        var leftNode = aChildren[i]
+        var rightNode = bChildren[i]
+        index += 1
+
+        if (!leftNode) {
+            if (rightNode) {
+                // Excess nodes in b need to be added
+                apply = appendPatch(apply,
+                    new VPatch(VPatch.INSERT, null, rightNode))
+            }
+        } else if (!rightNode) {
+            if (leftNode) {
+                // Excess nodes in a need to be removed
+                patch[index] = new VPatch(VPatch.REMOVE, leftNode, null)
+                destroyWidgets(leftNode, patch, index)
+            }
+        } else {
+            walk(leftNode, rightNode, patch, index)
+        }
+
+        if (isVNode(leftNode) && leftNode.count) {
+            index += leftNode.count
+        }
+    }
+
+    if (bChildren.moves) {
+        // Reorder nodes last
+        apply = appendPatch(apply, new VPatch(VPatch.ORDER, a, bChildren.moves))
+    }
+
+    return apply
+}
+
+// Patch records for all destroyed widgets must be added because we need
+// a DOM node reference for the destroy function
+function destroyWidgets(vNode, patch, index) {
+    if (isWidget(vNode)) {
+        if (typeof vNode.destroy === "function") {
+            patch[index] = new VPatch(VPatch.REMOVE, vNode, null)
+        }
+    } else if (isVNode(vNode) && vNode.hasWidgets) {
+        var children = vNode.children
+        var len = children.length
+        for (var i = 0; i < len; i++) {
+            var child = children[i]
+            index += 1
+
+            destroyWidgets(child, patch, index)
+
+            if (isVNode(child) && child.count) {
+                index += child.count
+            }
+        }
+    }
+}
+
+// Create a sub-patch for thunks
+function thunks(a, b, patch, index) {
+    var nodes = handleThunk(a, b);
+    var thunkPatch = diff(nodes.a, nodes.b)
+    if (hasPatches(thunkPatch)) {
+        patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch)
+    }
+}
+
+function hasPatches(patch) {
+    for (var index in patch) {
+        if (index !== "a") {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+// Execute hooks when two nodes are identical
+function hooks(vNode, patch, index) {
+    if (isVNode(vNode)) {
+        if (vNode.hooks) {
+            patch[index] = new VPatch(VPatch.PROPS, vNode.hooks, vNode.hooks)
+        }
+
+        if (vNode.descendantHooks) {
+            var children = vNode.children
+            var len = children.length
+            for (var i = 0; i < len; i++) {
+                var child = children[i]
+                index += 1
+
+                hooks(child, patch, index)
+
+                if (isVNode(child) && child.count) {
+                    index += child.count
+                }
+            }
+        }
+    }
+}
+
+// List diff, naive left to right reordering
+function reorder(aChildren, bChildren) {
+
+    var bKeys = keyIndex(bChildren)
+
+    if (!bKeys) {
+        return bChildren
+    }
+
+    var aKeys = keyIndex(aChildren)
+
+    if (!aKeys) {
+        return bChildren
+    }
+
+    var bMatch = {}, aMatch = {}
+
+    for (var key in bKeys) {
+        bMatch[bKeys[key]] = aKeys[key]
+    }
+
+    for (var key in aKeys) {
+        aMatch[aKeys[key]] = bKeys[key]
+    }
+
+    var aLen = aChildren.length
+    var bLen = bChildren.length
+    var len = aLen > bLen ? aLen : bLen
+    var shuffle = []
+    var freeIndex = 0
+    var i = 0
+    var moveIndex = 0
+    var moves = {}
+    var removes = moves.removes = {}
+    var reverse = moves.reverse = {}
+    var hasMoves = false
+
+    while (freeIndex < len) {
+        var move = aMatch[i]
+        if (move !== undefined) {
+            shuffle[i] = bChildren[move]
+            if (move !== moveIndex) {
+                moves[move] = moveIndex
+                reverse[moveIndex] = move
+                hasMoves = true
+            }
+            moveIndex++
+        } else if (i in aMatch) {
+            shuffle[i] = undefined
+            removes[i] = moveIndex++
+            hasMoves = true
+        } else {
+            while (bMatch[freeIndex] !== undefined) {
+                freeIndex++
+            }
+
+            if (freeIndex < len) {
+                var freeChild = bChildren[freeIndex]
+                if (freeChild) {
+                    shuffle[i] = freeChild
+                    if (freeIndex !== moveIndex) {
+                        hasMoves = true
+                        moves[freeIndex] = moveIndex
+                        reverse[moveIndex] = freeIndex
+                    }
+                    moveIndex++
+                }
+                freeIndex++
+            }
+        }
+        i++
+    }
+
+    if (hasMoves) {
+        shuffle.moves = moves
+    }
+
+    return shuffle
+}
+
+function keyIndex(children) {
+    var i, keys
+
+    for (i = 0; i < children.length; i++) {
+        var child = children[i]
+
+        if (child.key !== undefined) {
+            keys = keys || {}
+            keys[child.key] = i
+        }
+    }
+
+    return keys
+}
+
+function appendPatch(apply, patch) {
+    if (apply) {
+        if (isArray(apply)) {
+            apply.push(patch)
+        } else {
+            apply = [apply, patch]
+        }
+
+        return apply
+    } else {
+        return patch
+    }
+}
+
+},{"./handle-thunk":27,"./is-thunk":28,"./is-vnode":30,"./is-vtext":31,"./is-widget":32,"./vpatch":37,"is-object":33,"x-is-array":34}],27:[function(require,module,exports){
+var isVNode = require("./is-vnode")
+var isVText = require("./is-vtext")
+var isWidget = require("./is-widget")
+var isThunk = require("./is-thunk")
+
+module.exports = handleThunk
+
+function handleThunk(a, b) {
+    var renderedA = a
+    var renderedB = b
+
+    if (isThunk(b)) {
+        renderedB = renderThunk(b, a)
+    }
+
+    if (isThunk(a)) {
+        renderedA = renderThunk(a, null)
+    }
+
+    return {
+        a: renderedA,
+        b: renderedB
+    }
+}
+
+function renderThunk(thunk, previous) {
+    var renderedThunk = thunk.vnode
+
+    if (!renderedThunk) {
+        renderedThunk = thunk.vnode = thunk.render(previous)
+    }
+
+    if (!(isVNode(renderedThunk) ||
+            isVText(renderedThunk) ||
+            isWidget(renderedThunk))) {
+        throw new Error("thunk did not return a valid node");
+    }
+
+    return renderedThunk
+}
+
+},{"./is-thunk":28,"./is-vnode":30,"./is-vtext":31,"./is-widget":32}],28:[function(require,module,exports){
+module.exports = isThunk
+
+function isThunk(t) {
+    return t && t.type === "Thunk"
+}
+
+},{}],29:[function(require,module,exports){
+module.exports = isHook
+
+function isHook(hook) {
+    return hook && typeof hook.hook === "function" &&
+        !hook.hasOwnProperty("hook")
+}
+
+},{}],30:[function(require,module,exports){
+var version = require("./version")
+
+module.exports = isVirtualNode
+
+function isVirtualNode(x) {
+    return x && x.type === "VirtualNode" && x.version === version
+}
+
+},{"./version":35}],31:[function(require,module,exports){
+var version = require("./version")
+
+module.exports = isVirtualText
+
+function isVirtualText(x) {
+    return x && x.type === "VirtualText" && x.version === version
+}
+
+},{"./version":35}],32:[function(require,module,exports){
+module.exports = isWidget
+
+function isWidget(w) {
+    return w && w.type === "Widget"
+}
+
+},{}],33:[function(require,module,exports){
+module.exports=require(21)
+},{}],34:[function(require,module,exports){
+module.exports=require(22)
+},{}],35:[function(require,module,exports){
+module.exports = "1"
+
+},{}],36:[function(require,module,exports){
+var version = require("./version")
+var isVNode = require("./is-vnode")
+var isWidget = require("./is-widget")
+var isVHook = require("./is-vhook")
+
+module.exports = VirtualNode
+
+var noProperties = {}
+var noChildren = []
+
+function VirtualNode(tagName, properties, children, key, namespace) {
+    this.tagName = tagName
+    this.properties = properties || noProperties
+    this.children = children || noChildren
+    this.key = key != null ? String(key) : undefined
+    this.namespace = (typeof namespace === "string") ? namespace : null
+
+    var count = (children && children.length) || 0
+    var descendants = 0
+    var hasWidgets = false
+    var descendantHooks = false
+    var hooks
+
+    for (var propName in properties) {
+        if (properties.hasOwnProperty(propName)) {
+            var property = properties[propName]
+            if (isVHook(property)) {
+                if (!hooks) {
+                    hooks = {}
+                }
+
+                hooks[propName] = property
+            }
+        }
+    }
+
+    for (var i = 0; i < count; i++) {
+        var child = children[i]
+        if (isVNode(child)) {
+            descendants += child.count || 0
+
+            if (!hasWidgets && child.hasWidgets) {
+                hasWidgets = true
+            }
+
+            if (!descendantHooks && (child.hooks || child.descendantHooks)) {
+                descendantHooks = true
+            }
+        } else if (!hasWidgets && isWidget(child)) {
+            if (typeof child.destroy === "function") {
+                hasWidgets = true
+            }
+        }
+    }
+
+    this.count = count + descendants
+    this.hasWidgets = hasWidgets
+    this.hooks = hooks
+    this.descendantHooks = descendantHooks
+}
+
+VirtualNode.prototype.version = version
+VirtualNode.prototype.type = "VirtualNode"
+
+},{"./is-vhook":29,"./is-vnode":30,"./is-widget":32,"./version":35}],37:[function(require,module,exports){
+var version = require("./version")
+
+VirtualPatch.NONE = 0
+VirtualPatch.VTEXT = 1
+VirtualPatch.VNODE = 2
+VirtualPatch.WIDGET = 3
+VirtualPatch.PROPS = 4
+VirtualPatch.ORDER = 5
+VirtualPatch.INSERT = 6
+VirtualPatch.REMOVE = 7
+VirtualPatch.THUNK = 8
+
+module.exports = VirtualPatch
+
+function VirtualPatch(type, vNode, patch) {
+    this.type = Number(type)
+    this.vNode = vNode
+    this.patch = patch
+}
+
+VirtualPatch.prototype.version = version
+VirtualPatch.prototype.type = "VirtualPatch"
+
+},{"./version":35}],38:[function(require,module,exports){
+var version = require("./version")
+
+module.exports = VirtualText
+
+function VirtualText(text) {
+    this.text = String(text)
+}
+
+VirtualText.prototype.version = version
+VirtualText.prototype.type = "VirtualText"
+
+},{"./version":35}],39:[function(require,module,exports){
+
+var VNode = require('vtree/vnode');
+var VText = require('vtree/vtext');
+var diff = require('vtree/diff');
+var patch = require('vdom/patch');
+var createElement = require('vdom/create-element');
+var DataSet = require("data-set");
+var Delegator = require("dom-delegator");
+var isHook = require("vtree/is-vhook");
+
+Elm.Native.VirtualDom = {};
+Elm.Native.VirtualDom.make = function(elm) {
+    elm.Native = elm.Native || {};
+    elm.Native.VirtualDom = elm.Native.VirtualDom || {};
+    if (elm.Native.VirtualDom.values) {
+        return elm.Native.VirtualDom.values;
+    }
+
+    // This manages event listeners. Somehow...
+    var delegator = Delegator();
+
+    var NativeElement = Elm.Native.Graphics.Element.make(elm);
+    var Element = Elm.Graphics.Element.make(elm);
+    var Json = Elm.Native.Json.make(elm);
+    var List = Elm.Native.List.make(elm);
+    var Utils = Elm.Native.Utils.make(elm);
+
+    function listToObject(list) {
+        var object = {};
+        while (list.ctor !== '[]') {
+            var entry = list._0;
+            object[entry.key] = entry.value;
+            list = list._1;
+        }
+        return object;
+    }
+
+    function node(name, propertyList, contents) {
+        var props = listToObject(propertyList);
+
+        var key, namespace;
+        // support keys
+        if (props.key !== undefined) {
+            key = props.key;
+            props.key = undefined;
+        }
+
+        // support namespace
+        if (props.namespace !== undefined) {
+            namespace = props.namespace;
+            props.namespace = undefined;
+        }
+
+        // ensure that setting text of an input does not move the cursor
+        var useSoftSet =
+            name === 'input'
+            && props.value !== undefined
+            && !isHook(props.value);
+
+        if (useSoftSet) {
+            props.value = SoftSetHook(props.value);
+        }
+
+        return new VNode(name, props, List.toArray(contents), key, namespace);
+    }
+
+    function property(key, value) {
+        return {
+            key: key,
+            value: value
+        };
+    }
+
+    function on(name, decoder, createMessage) {
+        function eventHandler(event) {
+            var value = A2(Json.runDecoderValue, decoder, event);
+            if (value.ctor === 'Ok') {
+                createMessage(value._0)();
+            }
+        }
+        return property(name, DataSetHook(eventHandler));
+    }
+
+    function DataSetHook(value) {
+        if (!(this instanceof DataSetHook)) {
+            return new DataSetHook(value);
+        }
+
+        this.value = value;
+    }
+
+    DataSetHook.prototype.hook = function (node, propertyName) {
+        var ds = DataSet(node);
+        ds[propertyName] = this.value;
+    };
+
+
+    function SoftSetHook(value) {
+      if (!(this instanceof SoftSetHook)) {
+        return new SoftSetHook(value);
+      }
+
+      this.value = value;
+    }
+
+    SoftSetHook.prototype.hook = function (node, propertyName) {
+      if (node[propertyName] !== this.value) {
+        node[propertyName] = this.value;
+      }
+    };
+
+    function text(string) {
+        return new VText(string);
+    }
+
+    function fromElement(element) {
+        return {
+            type: "Widget",
+
+            element: element,
+
+            init: function () {
+                return NativeElement.render(element);
+            },
+
+            update: function (previous, node) {
+                return NativeElement.update(node, previous.element, element);
+            }
+        };
+    }
+
+    function toElement(width, height, html) {
+        return A3(Element.newElement, width, height,
+                  { ctor: 'Custom'
+                  , type: 'evancz/elm-html'
+                  , render: render
+                  , update: update
+                  , model: html
+                  });
+    }
+
+    function render(model) {
+        var element = NativeElement.createNode('div');
+        element.appendChild(createElement(model));
+        return element;
+    }
+
+    function update(node, oldModel, newModel) {
+        var patches = diff(oldModel, newModel);
+        var newNode = patch(node.firstChild, patches)
+        if (newNode !== node.firstChild) {
+            node.replaceChild(newNode, node.firstChild)
+        }
+        return node;
+    }
+
+    function lazyRef(fn, a) {
+        function thunk() {
+            return fn(a);
+        }
+        return new Thunk(fn, [a], thunk);
+    }
+
+    function lazyRef2(fn, a, b) {
+        function thunk() {
+            return A2(fn, a, b);
+        }
+        return new Thunk(fn, [a,b], thunk);
+    }
+
+    function lazyRef3(fn, a, b, c) {
+        function thunk() {
+            return A3(fn, a, b, c);
+        }
+        return new Thunk(fn, [a,b,c], thunk);
+    }
+
+    function Thunk(fn, args, thunk) {
+        this.fn = fn;
+        this.args = args;
+        this.vnode = null;
+        this.key = undefined;
+        this.thunk = thunk;
+    }
+
+    Thunk.prototype.type = "Thunk";
+    Thunk.prototype.update = updateThunk;
+    Thunk.prototype.render = renderThunk;
+
+    function shouldUpdate(current, previous) {
+        if (current.fn !== previous.fn) {
+            return true;
+        }
+
+        // if it's the same function, we know the number of args must match
+        var cargs = current.args;
+        var pargs = previous.args;
+
+        for (var i = cargs.length; i--; ) {
+            if (cargs[i] !== pargs[i]) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    function updateThunk(previous, domNode) {
+        if (!shouldUpdate(this, previous)) {
+            this.vnode = previous.vnode;
+            return;
+        }
+
+        if (!this.vnode) {
+            this.vnode = this.thunk();
+        }
+
+        var patches = diff(previous.vnode, this.vnode);
+        patch(domNode, patches);
+    }
+
+    function renderThunk() {
+        return this.thunk();
+    }
+
+    return Elm.Native.VirtualDom.values = {
+        node: F3(node),
+        text: text,
+        on: F3(on),
+
+        property: F2(property),
+
+        lazy: F2(lazyRef),
+        lazy2: F3(lazyRef2),
+        lazy3: F4(lazyRef3),
+
+        toElement: F3(toElement),
+        fromElement: fromElement
+    };
+};
+
+},{"data-set":2,"dom-delegator":8,"vdom/create-element":18,"vdom/patch":24,"vtree/diff":26,"vtree/is-vhook":29,"vtree/vnode":36,"vtree/vtext":38}],40:[function(require,module,exports){
+
+},{}]},{},[39]);
+
+Elm.Native = Elm.Native || {};
+Elm.Native.Window = {};
+Elm.Native.Window.make = function(localRuntime) {
+
+    localRuntime.Native = localRuntime.Native || {};
+    localRuntime.Native.Window = localRuntime.Native.Window || {};
+    if (localRuntime.Native.Window.values) {
+        return localRuntime.Native.Window.values;
+    }
+
+    var Signal = Elm.Signal.make(localRuntime);
+    var NS = Elm.Native.Signal.make(localRuntime);
+    var Tuple2 = Elm.Native.Utils.make(localRuntime).Tuple2;
+
+    function getWidth() {
+        return localRuntime.node.clientWidth;
+    }
+    function getHeight() {
+        if (localRuntime.isFullscreen()) {
+            return window.innerHeight;
+        }
+        return localRuntime.node.clientHeight;
+    }
+
+    var dimensions = NS.input(Tuple2(getWidth(), getHeight()));
+    dimensions.defaultNumberOfKids = 2;
+
+    // Do not move width and height into Elm. By setting the default number of kids,
+    // the resize listener can be detached.
+    var width  = A2(Signal.map, function(p){return p._0;}, dimensions);
+    width.defaultNumberOfKids = 0;
+
+    var height = A2(Signal.map, function(p){return p._1;}, dimensions);
+    height.defaultNumberOfKids = 0;
+
+    function resizeIfNeeded() {
+        // Do not trigger event if the dimensions have not changed.
+        // This should be most of the time.
+        var w = getWidth();
+        var h = getHeight();
+        if (dimensions.value._0 === w && dimensions.value._1 === h) return;
+
+        setTimeout(function () {
+            // Check again to see if the dimensions have changed.
+            // It is conceivable that the dimensions have changed
+            // again while some other event was being processed.
+            var w = getWidth();
+            var h = getHeight();
+            if (dimensions.value._0 === w && dimensions.value._1 === h) return;
+            localRuntime.notify(dimensions.id, Tuple2(w,h));
+        }, 0);
+    }
+    localRuntime.addListener([dimensions.id], window, 'resize', resizeIfNeeded);
+
+    return localRuntime.Native.Window.values = {
+        dimensions: dimensions,
+        width: width,
+        height: height,
+        resizeIfNeeded: resizeIfNeeded
+    };
+
+};
+
+Elm.Result = Elm.Result || {};
+Elm.Result.make = function (_elm) {
+   "use strict";
+   _elm.Result = _elm.Result || {};
+   if (_elm.Result.values)
+   return _elm.Result.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Result",
+   $Maybe = Elm.Maybe.make(_elm);
+   var toMaybe = function (result) {
+      return function () {
+         switch (result.ctor)
+         {case "Err":
+            return $Maybe.Nothing;
+            case "Ok":
+            return $Maybe.Just(result._0);}
+         _U.badCase($moduleName,
+         "between lines 110 and 123");
+      }();
+   };
+   var Err = function (a) {
+      return {ctor: "Err",_0: a};
+   };
+   var andThen = F2(function (result,
+   callback) {
+      return function () {
+         switch (result.ctor)
+         {case "Err":
+            return Err(result._0);
+            case "Ok":
+            return callback(result._0);}
+         _U.badCase($moduleName,
+         "between lines 72 and 91");
+      }();
+   });
+   var Ok = function (a) {
+      return {ctor: "Ok",_0: a};
+   };
+   var map = F2(function (f,
+   result) {
+      return function () {
+         switch (result.ctor)
+         {case "Err":
+            return Err(result._0);
+            case "Ok":
+            return Ok(f(result._0));}
+         _U.badCase($moduleName,
+         "between lines 32 and 69");
+      }();
+   });
+   var formatError = F2(function (f,
+   result) {
+      return function () {
+         switch (result.ctor)
+         {case "Err":
+            return Err(f(result._0));
+            case "Ok":
+            return Ok(result._0);}
+         _U.badCase($moduleName,
+         "between lines 94 and 107");
+      }();
+   });
+   var fromMaybe = F2(function (err,
+   maybe) {
+      return function () {
+         switch (maybe.ctor)
+         {case "Just":
+            return Ok(maybe._0);
+            case "Nothing":
+            return Err(err);}
+         _U.badCase($moduleName,
+         "between lines 126 and 128");
+      }();
+   });
+   _elm.Result.values = {_op: _op
+                        ,Ok: Ok
+                        ,Err: Err
+                        ,map: map
+                        ,andThen: andThen
+                        ,formatError: formatError
+                        ,toMaybe: toMaybe
+                        ,fromMaybe: fromMaybe};
+   return _elm.Result.values;
+};
+Elm.Signal = Elm.Signal || {};
+Elm.Signal.make = function (_elm) {
+   "use strict";
+   _elm.Signal = _elm.Signal || {};
+   if (_elm.Signal.values)
+   return _elm.Signal.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Signal",
+   $Basics = Elm.Basics.make(_elm),
+   $List = Elm.List.make(_elm),
+   $Native$Signal = Elm.Native.Signal.make(_elm);
+   var subscribe = $Native$Signal.subscribe;
+   var send = $Native$Signal.send;
+   var channel = $Native$Signal.input;
+   var Message = {ctor: "Message"};
+   var Channel = {ctor: "Channel"};
+   _op["~"] = F2(function (sf,s) {
+      return A3($Native$Signal.map2,
+      F2(function (f,x) {
+         return f(x);
+      }),
+      sf,
+      s);
+   });
+   _op["<~"] = F2(function (f,s) {
+      return A2($Native$Signal.map,
+      f,
+      s);
+   });
+   var sampleOn = $Native$Signal.sampleOn;
+   var dropRepeats = $Native$Signal.dropRepeats;
+   var dropIf = $Native$Signal.dropIf;
+   var keepIf = $Native$Signal.keepIf;
+   var keepWhen = F3(function (bs,
+   def,
+   sig) {
+      return A2(_op["<~"],
+      $Basics.snd,
+      A3(keepIf,
+      $Basics.fst,
+      {ctor: "_Tuple2"
+      ,_0: false
+      ,_1: def},
+      A2(_op["~"],
+      A2(_op["<~"],
+      F2(function (v0,v1) {
+         return {ctor: "_Tuple2"
+                ,_0: v0
+                ,_1: v1};
+      }),
+      A2(sampleOn,sig,bs)),
+      sig)));
+   });
+   var dropWhen = function (bs) {
+      return keepWhen(A2(_op["<~"],
+      $Basics.not,
+      bs));
+   };
+   var merge = $Native$Signal.merge;
+   var mergeMany = function (signals) {
+      return A2($List.foldr1,
+      merge,
+      signals);
+   };
+   var foldp = $Native$Signal.foldp;
+   var map5 = $Native$Signal.map5;
+   var map4 = $Native$Signal.map4;
+   var map3 = $Native$Signal.map3;
+   var map2 = $Native$Signal.map2;
+   var map = $Native$Signal.map;
+   var constant = $Native$Signal.constant;
+   var Signal = {ctor: "Signal"};
+   _elm.Signal.values = {_op: _op
+                        ,Signal: Signal
+                        ,constant: constant
+                        ,map: map
+                        ,map2: map2
+                        ,map3: map3
+                        ,map4: map4
+                        ,map5: map5
+                        ,foldp: foldp
+                        ,merge: merge
+                        ,mergeMany: mergeMany
+                        ,keepIf: keepIf
+                        ,dropIf: dropIf
+                        ,keepWhen: keepWhen
+                        ,dropWhen: dropWhen
+                        ,dropRepeats: dropRepeats
+                        ,sampleOn: sampleOn
+                        ,Channel: Channel
+                        ,Message: Message
+                        ,channel: channel
+                        ,send: send
+                        ,subscribe: subscribe};
+   return _elm.Signal.values;
+};
+Elm.Slider = Elm.Slider || {};
+Elm.Slider.make = function (_elm) {
+   "use strict";
+   _elm.Slider = _elm.Slider || {};
+   if (_elm.Slider.values)
+   return _elm.Slider.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Slider",
+   $Graphics$Element = Elm.Graphics.Element.make(_elm),
+   $Native$Slider = Elm.Native.Slider.make(_elm),
+   $Signal = Elm.Signal.make(_elm);
+   var slider = $Native$Slider.slider;
+   var defaultSlider = {_: {}
+                       ,disabled: false
+                       ,horizontal: true
+                       ,length: 100
+                       ,max: 100
+                       ,min: 0
+                       ,step: 1
+                       ,value: 0};
+   var SliderStyle = F7(function (a,
+   b,
+   c,
+   d,
+   e,
+   f,
+   g) {
+      return {_: {}
+             ,disabled: b
+             ,horizontal: a
+             ,length: c
+             ,max: e
+             ,min: d
+             ,step: f
+             ,value: g};
+   });
+   _elm.Slider.values = {_op: _op
+                        ,SliderStyle: SliderStyle
+                        ,defaultSlider: defaultSlider
+                        ,slider: slider};
+   return _elm.Slider.values;
+};
+Elm.String = Elm.String || {};
+Elm.String.make = function (_elm) {
+   "use strict";
+   _elm.String = _elm.String || {};
+   if (_elm.String.values)
+   return _elm.String.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "String",
+   $Maybe = Elm.Maybe.make(_elm),
+   $Native$String = Elm.Native.String.make(_elm),
+   $Result = Elm.Result.make(_elm);
+   var fromList = $Native$String.fromList;
+   var toList = $Native$String.toList;
+   var toFloat = $Native$String.toFloat;
+   var toInt = $Native$String.toInt;
+   var indices = $Native$String.indexes;
+   var indexes = $Native$String.indexes;
+   var endsWith = $Native$String.endsWith;
+   var startsWith = $Native$String.startsWith;
+   var contains = $Native$String.contains;
+   var all = $Native$String.all;
+   var any = $Native$String.any;
+   var toLower = $Native$String.toLower;
+   var toUpper = $Native$String.toUpper;
+   var lines = $Native$String.lines;
+   var words = $Native$String.words;
+   var trimRight = $Native$String.trimRight;
+   var trimLeft = $Native$String.trimLeft;
+   var trim = $Native$String.trim;
+   var padRight = $Native$String.padRight;
+   var padLeft = $Native$String.padLeft;
+   var pad = $Native$String.pad;
+   var dropRight = $Native$String.dropRight;
+   var dropLeft = $Native$String.dropLeft;
+   var right = $Native$String.right;
+   var left = $Native$String.left;
+   var slice = $Native$String.slice;
+   var repeat = $Native$String.repeat;
+   var join = $Native$String.join;
+   var split = $Native$String.split;
+   var foldr = $Native$String.foldr;
+   var foldl = $Native$String.foldl;
+   var reverse = $Native$String.reverse;
+   var filter = $Native$String.filter;
+   var map = $Native$String.map;
+   var length = $Native$String.length;
+   var concat = $Native$String.concat;
+   var append = $Native$String.append;
+   var uncons = $Native$String.uncons;
+   var cons = $Native$String.cons;
+   var fromChar = function ($char) {
+      return A2(cons,$char,"");
+   };
+   var isEmpty = $Native$String.isEmpty;
+   _elm.String.values = {_op: _op
+                        ,isEmpty: isEmpty
+                        ,cons: cons
+                        ,fromChar: fromChar
+                        ,uncons: uncons
+                        ,append: append
+                        ,concat: concat
+                        ,length: length
+                        ,map: map
+                        ,filter: filter
+                        ,reverse: reverse
+                        ,foldl: foldl
+                        ,foldr: foldr
+                        ,split: split
+                        ,join: join
+                        ,repeat: repeat
+                        ,slice: slice
+                        ,left: left
+                        ,right: right
+                        ,dropLeft: dropLeft
+                        ,dropRight: dropRight
+                        ,pad: pad
+                        ,padLeft: padLeft
+                        ,padRight: padRight
+                        ,trim: trim
+                        ,trimLeft: trimLeft
+                        ,trimRight: trimRight
+                        ,words: words
+                        ,lines: lines
+                        ,toUpper: toUpper
+                        ,toLower: toLower
+                        ,any: any
+                        ,all: all
+                        ,contains: contains
+                        ,startsWith: startsWith
+                        ,endsWith: endsWith
+                        ,indexes: indexes
+                        ,indices: indices
+                        ,toInt: toInt
+                        ,toFloat: toFloat
+                        ,toList: toList
+                        ,fromList: fromList};
+   return _elm.String.values;
+};
+Elm.Text = Elm.Text || {};
+Elm.Text.make = function (_elm) {
+   "use strict";
+   _elm.Text = _elm.Text || {};
+   if (_elm.Text.values)
+   return _elm.Text.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Text",
+   $Basics = Elm.Basics.make(_elm),
+   $Color = Elm.Color.make(_elm),
+   $Graphics$Element = Elm.Graphics.Element.make(_elm),
+   $List = Elm.List.make(_elm),
+   $Maybe = Elm.Maybe.make(_elm),
+   $Native$Text = Elm.Native.Text.make(_elm);
+   var markdown = $Native$Text.markdown;
+   var justified = $Native$Text.justified;
+   var centered = $Native$Text.centered;
+   var rightAligned = $Native$Text.rightAligned;
+   var leftAligned = $Native$Text.leftAligned;
+   var line = $Native$Text.line;
+   var italic = $Native$Text.italic;
+   var bold = $Native$Text.bold;
+   var color = $Native$Text.color;
+   var height = $Native$Text.height;
+   var link = $Native$Text.link;
+   var monospace = $Native$Text.monospace;
+   var typeface = $Native$Text.typeface;
+   var style = $Native$Text.style;
+   var append = $Native$Text.append;
+   var fromString = $Native$Text.fromString;
+   var empty = fromString("");
+   var concat = function (texts) {
+      return A3($List.foldr,
+      append,
+      empty,
+      texts);
+   };
+   var join = F2(function (seperator,
+   texts) {
+      return concat(A2($List.intersperse,
+      seperator,
+      texts));
+   });
+   var plainText = function (str) {
+      return leftAligned(fromString(str));
+   };
+   var asText = function (value) {
+      return leftAligned(monospace(fromString($Basics.toString(value))));
+   };
+   var defaultStyle = {_: {}
+                      ,bold: false
+                      ,color: $Color.black
+                      ,height: $Maybe.Nothing
+                      ,italic: false
+                      ,line: $Maybe.Nothing
+                      ,typeface: _L.fromArray([])};
+   var Style = F6(function (a,
+   b,
+   c,
+   d,
+   e,
+   f) {
+      return {_: {}
+             ,bold: d
+             ,color: c
+             ,height: b
+             ,italic: e
+             ,line: f
+             ,typeface: a};
+   });
+   var Through = {ctor: "Through"};
+   var Over = {ctor: "Over"};
+   var Under = {ctor: "Under"};
+   var Text = {ctor: "Text"};
+   _elm.Text.values = {_op: _op
+                      ,Text: Text
+                      ,Under: Under
+                      ,Over: Over
+                      ,Through: Through
+                      ,Style: Style
+                      ,defaultStyle: defaultStyle
+                      ,fromString: fromString
+                      ,empty: empty
+                      ,append: append
+                      ,concat: concat
+                      ,join: join
+                      ,style: style
+                      ,typeface: typeface
+                      ,monospace: monospace
+                      ,link: link
+                      ,height: height
+                      ,color: color
+                      ,bold: bold
+                      ,italic: italic
+                      ,line: line
+                      ,leftAligned: leftAligned
+                      ,rightAligned: rightAligned
+                      ,centered: centered
+                      ,justified: justified
+                      ,plainText: plainText
+                      ,markdown: markdown
+                      ,asText: asText};
+   return _elm.Text.values;
+};
+Elm.Transform2D = Elm.Transform2D || {};
+Elm.Transform2D.make = function (_elm) {
+   "use strict";
+   _elm.Transform2D = _elm.Transform2D || {};
+   if (_elm.Transform2D.values)
+   return _elm.Transform2D.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Transform2D",
+   $Native$Transform2D = Elm.Native.Transform2D.make(_elm);
+   var multiply = $Native$Transform2D.multiply;
+   var rotation = $Native$Transform2D.rotation;
+   var matrix = $Native$Transform2D.matrix;
+   var translation = F2(function (x,
+   y) {
+      return A6(matrix,
+      1,
+      0,
+      0,
+      1,
+      x,
+      y);
+   });
+   var scale = function (s) {
+      return A6(matrix,
+      s,
+      0,
+      0,
+      s,
+      0,
+      0);
+   };
+   var scaleX = function (x) {
+      return A6(matrix,
+      x,
+      0,
+      0,
+      1,
+      0,
+      0);
+   };
+   var scaleY = function (y) {
+      return A6(matrix,
+      1,
+      0,
+      0,
+      y,
+      0,
+      0);
+   };
+   var identity = $Native$Transform2D.identity;
+   var Transform2D = {ctor: "Transform2D"};
+   _elm.Transform2D.values = {_op: _op
+                             ,identity: identity
+                             ,matrix: matrix
+                             ,multiply: multiply
+                             ,rotation: rotation
+                             ,translation: translation
+                             ,scale: scale
+                             ,scaleX: scaleX
+                             ,scaleY: scaleY};
+   return _elm.Transform2D.values;
+};
+Elm.VirtualDom = Elm.VirtualDom || {};
+Elm.VirtualDom.make = function (_elm) {
+   "use strict";
+   _elm.VirtualDom = _elm.VirtualDom || {};
+   if (_elm.VirtualDom.values)
+   return _elm.VirtualDom.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "VirtualDom",
+   $Graphics$Element = Elm.Graphics.Element.make(_elm),
+   $Json$Decode = Elm.Json.Decode.make(_elm),
+   $Native$VirtualDom = Elm.Native.VirtualDom.make(_elm),
+   $Signal = Elm.Signal.make(_elm);
+   var lazy3 = $Native$VirtualDom.lazy3;
+   var lazy2 = $Native$VirtualDom.lazy2;
+   var lazy = $Native$VirtualDom.lazy;
+   var on = $Native$VirtualDom.on;
+   var property = $Native$VirtualDom.property;
+   var Property = {ctor: "Property"};
+   var fromElement = $Native$VirtualDom.fromElement;
+   var toElement = $Native$VirtualDom.toElement;
+   var text = $Native$VirtualDom.text;
+   var node = $Native$VirtualDom.node;
+   var Node = {ctor: "Node"};
+   _elm.VirtualDom.values = {_op: _op
+                            ,Node: Node
+                            ,node: node
+                            ,text: text
+                            ,toElement: toElement
+                            ,fromElement: fromElement
+                            ,Property: Property
+                            ,property: property
+                            ,on: on
+                            ,lazy: lazy
+                            ,lazy2: lazy2
+                            ,lazy3: lazy3};
+   return _elm.VirtualDom.values;
+};
+Elm.Window = Elm.Window || {};
+Elm.Window.make = function (_elm) {
+   "use strict";
+   _elm.Window = _elm.Window || {};
+   if (_elm.Window.values)
+   return _elm.Window.values;
+   var _op = {},
+   _N = Elm.Native,
+   _U = _N.Utils.make(_elm),
+   _L = _N.List.make(_elm),
+   _P = _N.Ports.make(_elm),
+   $moduleName = "Window",
+   $Native$Window = Elm.Native.Window.make(_elm),
+   $Signal = Elm.Signal.make(_elm);
+   var height = $Native$Window.height;
+   var width = $Native$Window.width;
+   var dimensions = $Native$Window.dimensions;
+   _elm.Window.values = {_op: _op
+                        ,dimensions: dimensions
+                        ,width: width
+                        ,height: height};
+   return _elm.Window.values;
+};
+
+// A note to the reader:
+// This file is concatenated with debuggerInterface.elm's compiled
+// javascript and debug-core.js. This is done at build time in Setup.hs
+
+var prettyPrint = function(){
+
+    var independentRuntime = {};
+    var List;
+    var ElmArray;
+    var Dict;
+
+    var toString = function(v, separator) {
+        var type = typeof v;
+        if (type === "function") {
+            var name = v.func ? v.func.name : v.name;
+            return '<function' + (name === '' ? '' : ': ') + name + '>';
+        } else if (type === "boolean") {
+            return v ? "True" : "False";
+        } else if (type === "number") {
+            return v.toFixed(2).replace(/\.0+$/g, '');
+        } else if ((v instanceof String) && v.isChar) {
+            return "'" + addSlashes(v) + "'";
+        } else if (type === "string") {
+            return '"' + addSlashes(v) + '"';
+        } else if (type === "object" && '_' in v && probablyPublic(v)) {
+            var output = [];
+            for (var k in v._) {
+                for (var i = v._[k].length; i--; ) {
+                    output.push(k + " = " + toString(v._[k][i], separator));
+                }
+            }
+            for (var k in v) {
+                if (k === '_') continue;
+                output.push(k + " = " + toString(v[k], separator));
+            }
+            if (output.length === 0) return "{}";
+            var body = "\n" + output.join(",\n");
+            return "{" + body.replace(/\n/g,"\n" + separator) + "\n}";
+        } else if (type === "object" && 'ctor' in v) {
+            if (v.ctor.substring(0,6) === "_Tuple") {
+                var output = [];
+                for (var k in v) {
+                    if (k === 'ctor') continue;
+                    output.push(toString(v[k], separator));
+                }
+                return "(" + output.join(", ") + ")";
+            } else if (v.ctor === "_Array") {
+                if (!ElmArray) {
+                    ElmArray = Elm.Array.make(independentRuntime);
+                }
+                var list = ElmArray.toList(v);
+                return "Array.fromList " + toString(list, separator);
+            } else if (v.ctor === "::") {
+                var output = '[\n' + toString(v._0, separator);
+                v = v._1;
+                while (v && v.ctor === "::") {
+                    output += ",\n" + toString(v._0, separator);
+                    v = v._1;
+                }
+                return output.replace(/\n/g,"\n" + separator) + "\n]";
+            } else if (v.ctor === "[]") {
+                return "[]";
+            } else if (v.ctor === "RBNode" || v.ctor === "RBEmpty") {
+                if (!Dict || !List) {
+                    Dict = Elm.Dict.make(independentRuntime);
+                    List = Elm.List.make(independentRuntime);
+                }
+                var list = Dict.toList(v);
+                var name = "Dict";
+                if (list.ctor === "::" && list._0._1.ctor === "_Tuple0") {
+                    name = "Set";
+                    list = A2(List.map, function(x){return x._0}, list);
+                }
+                return name + ".fromList " + toString(list, separator);
+            } else {
+                var output = "";
+                for (var i in v) {
+                    if (i === 'ctor') continue;
+                    var str = toString(v[i], separator);
+                    var parenless = str[0] === '{' ||
+                                    str[0] === '<' ||
+                                    str[0] === "[" ||
+                                    str.indexOf(' ') < 0;
+                    output += ' ' + (parenless ? str : "(" + str + ')');
+                }
+                return v.ctor + output;
+            }
+        }
+        if (type === 'object' && 'recv' in v) return '<signal>';
+        return "<internal structure>";
+    };
+
+    function addSlashes(str) {
+        return str.replace(/\\/g, '\\\\')
+                  .replace(/\n/g, '\\n')
+                  .replace(/\t/g, '\\t')
+                  .replace(/\r/g, '\\r')
+                  .replace(/\v/g, '\\v')
+                  .replace(/\0/g, '\\0')
+                  .replace(/\'/g, "\\'")
+                  .replace(/\"/g, '\\"');
+    }
+
+    function probablyPublic(v) {
+        var keys = Object.keys(v);
+        var len = keys.length;
+        if (len === 3
+            && 'props' in v
+            && 'element' in v) return false;
+        if (len === 5
+            && 'horizontal' in v
+            && 'vertical' in v
+            && 'x' in v
+            && 'y' in v) return false;
+        if (len === 7
+            && 'theta' in v
+            && 'scale' in v
+            && 'x' in v
+            && 'y' in v
+            && 'alpha' in v
+            && 'form' in v) return false;
+        return true;
+    }
+
+    return toString;
+}();
+// A note to the reader:
+// This file is concatenated with debuggerInterface.elm's compiled
+// javascript, toString.js, and reactor.js.
+// This is done at build time in Setup.hs.
+
+// Options:
+
+// Expose internal swap function, disable swap button, no socket
+// options.externalSwap = boolean
+
+function debugFullscreenWithOptions(options) {
+
+    return function(module, moduleFile, swapState /* =undefined */) {
+        var createdSocket = false;
+        var elmPermitSwaps = true;
+
+        var ELM_DEBUGGER_ID = "elmToolPanel";
+        var ELM_DARK_GREY = "#4A4A4A";
+        var ELM_LIGHT_GREY = "#E4E4E4";
+
+        var mainHandle = Elm.fullscreenDebugHooks(module, swapState);
+        var debuggerHandle = initDebugger();
+        if (!options.externalSwap) {
+            initSocket();
+        }
+
+        parent.window.addEventListener("message", function(e) {
+            if (e.data === "elmNotify") {
+                var currentPosition = mainHandle.debugger.getMaxSteps();
+                if (debuggerHandle.ports) {
+                    debuggerHandle.ports.eventCounter.send(currentPosition);
+                    sendWatches(currentPosition);
+                }
+            }
+        }, false);
+
+        function createDebuggingElement() {
+            var debuggingPanelExpanded = true;
+            var debuggerWidth = 275;
+
+            var debugTools = document.createElement("div");
+            debugTools.id = ELM_DEBUGGER_ID;
+
+            var debuggerDiv = document.createElement("div");
+            debuggerDiv.id = "elmDebugger";
+            debuggerDiv.style.overflow = "hidden";
+
+            // Create and style the panel
+            debugTools.style.background = ELM_DARK_GREY;
+            debugTools.style.width = debuggerWidth + "px";
+            debugTools.style.height = "100%";
+            debugTools.style.position = "absolute";
+            debugTools.style.top = "0px";
+            debugTools.style.right = "0px";
+            debugTools.style.transitionDuration = "0.3s";
+            debugTools.style.opacity = 0.97;
+            debugTools.style.zIndex = 1;
+
+            // Prevent clicks from reaching the main elm instance under the panel
+            function stopEvents(e) {
+                if (!e) {
+                    var e = window.event;
+                }
+                e.cancelBubble = true;
+                if (e.stopPropagation) {
+                    e.stopPropagation();
+                }
+            }
+            debugTools.addEventListener("click", stopEvents);
+
+            // Create and style the button
+            var tabWidth = 25;
+            var debugTab = document.createElement("div");
+            debugTab.id = "debugToggle";
+            debugTab.style.position = "absolute";
+            debugTab.style.width = tabWidth + "px";
+            debugTab.style.height = "60px";
+            debugTab.style.top = window.innerHeight / 2 + "px";
+            debugTab.style.left = "-" + tabWidth + "px";
+            debugTab.style.borderTopLeftRadius = "3px";
+            debugTab.style.borderBottomLeftRadius = "3px";
+            debugTab.style.background = ELM_DARK_GREY;
+
+
+            // Wire the button
+            debugTab.onclick = function() {
+                var toolPanel = document.getElementById("elmToolPanel");
+                if (debuggingPanelExpanded){
+                    toolPanel.style.width = "0px";
+                    debuggingPanelExpanded = false;
+                } else {
+                    toolPanel.style.right = "0px";
+                    toolPanel.style.width = debuggerWidth + "px";
+                    debuggingPanelExpanded = true;
+                }
+            };
+
+            debugTools.appendChild(debugTab);
+            debugTools.appendChild(debuggerDiv);
+            return debugTools;
+        }
+
+        function initDebugger() {
+            function scrubber(position) {
+                if (mainHandle.debugger.getPaused()) {
+                    mainHandle.debugger.stepTo(position);
+                    sendWatches(position);
+                }
+            }
+
+            function elmPauser(doPause) {
+                if (doPause) {
+                  mainHandle.debugger.pause();
+                } else {
+                    mainHandle.debugger.kontinue();
+                }
+            }
+
+            function elmRestart() {
+                mainHandle.debugger.restart();
+                sendWatches(0);
+            }
+
+            function elmSwap(permitSwaps) {
+                elmPermitSwaps = permitSwaps;
+            }
+
+            var debugTools = createDebuggingElement();
+            document.body.appendChild(debugTools);
+            var debuggerDiv = document.getElementById("elmDebugger");
+
+            var handle = Elm.embed(Elm.DebuggerInterface, debuggerDiv,
+                { eventCounter: 0,
+                  watches: [],
+                  showSwap: !options.externalSwap
+                });
+            handle.ports.scrubTo.subscribe(scrubber);
+            handle.ports.pause.subscribe(elmPauser);
+            handle.ports.restart.subscribe(elmRestart);
+            handle.ports.permitSwap.subscribe(elmSwap);
+            return handle;
+        }
+
+        function sendWatches(position) {
+            var separator = "  ";
+            var output = [];
+
+            var watchAtPoint = mainHandle.debugger.watchTracker.frames[position];
+
+            for(key in watchAtPoint) {
+                var value = watchAtPoint[key];
+                // The toString object is defined in toString.js
+                // and is prepended to this file at build time.
+                var stringified = prettyPrint(value, separator);
+                output.push([key, stringified]);
+            }
+            debuggerHandle.ports.watches.send(output);
+        }
+
+        function initSocket() {
+            createdSocket = true;
+            // "/todo.html" => "todo.elm"
+            moduleFile = moduleFile || window.location.pathname.substr(1).split(".")[0] + ".elm";
+            var socketLocation = "ws://" + window.location.host + "/socket?file=" + moduleFile;
+            var serverConnection = new WebSocket(socketLocation);
+            serverConnection.onmessage = function(event) {
+                if (elmPermitSwaps && debuggerHandle.ports) {
+                    swap(event.data);
+                }
+            };
+            window.addEventListener("unload", function() {
+                serverConnection.close();
+            });
+        }
+
+        function swap(raw) {
+            var debuggerDiv = document.getElementById(ELM_DEBUGGER_ID);
+            var result = JSON.parse(raw);
+            var js = result.success;
+            var errorMessage = result.error;
+            var error = document.getElementById('ErrorMessage');
+            if (error) {
+                error.parentNode.removeChild(error);
+            }
+            if (js) {
+                window.eval(js);
+                var moduleStr = js.match(/(Elm\..+)\ =\ \1/)[1];
+                var module = window.eval(moduleStr);
+                if (mainHandle.debugger) {
+                    var debuggerState = mainHandle.debugger.getSwapState();
+                    mainHandle.debugger.dispose();
+                    mainHandle.dispose();
+
+                    mainHandle = Elm.fullscreenDebugHooks(module, debuggerState);
+
+                    // The div that rejects events must be after Elm
+                    var ignoringDiv = document.getElementById("elmEventIgnorer");
+                    if (ignoringDiv) {
+                        ignoringDiv.parentNode.appendChild(ignoringDiv);
+                    }
+                }
+                else {
+                    mainHandle = mainHandle.swap(module);
+                }
+            } else if (errorMessage) {
+                var errorNode = document.createElement("pre");
+                errorNode.id = "ErrorMessage";
+                errorNode.innerHTML = errorMessage;
+                errorNode.style.zindex = 1;
+                errorNode.style.position = "absolute";
+                errorNode.style.top = "0";
+                errorNode.style.left = "0";
+                errorNode.style.color = ELM_DARK_GREY;
+                errorNode.style.backgroundColor = ELM_LIGHT_GREY;
+                errorNode.style.padding = "1em";
+                errorNode.style.margin = "1em";
+                errorNode.style.borderRadius = "10px";
+
+                document.body.appendChild(errorNode);
+            }
+        }
+
+        if (options.externalSwap) {
+            mainHandle.debugger.swap = swap;
+        }
+        return mainHandle;
+    };
+};
+// A note to the reader:
+// This file is concatenated with debuggerInterface.elm's compiled
+// javascript, toString.js, and debug-core.js. This is done at build time in Setup.hs
+
+Elm.debugFullscreen = debugFullscreenWithOptions({
     externalSwap: false
 });
diff --git a/backend/Compile.hs b/backend/Compile.hs
new file mode 100644
--- /dev/null
+++ b/backend/Compile.hs
@@ -0,0 +1,126 @@
+{-# OPTIONS_GHC -Wall #-}
+{-# LANGUAGE OverloadedStrings #-}
+module Compile (toHtml, toJson) where
+
+import Control.Applicative ((<$>),(<*>))
+import Control.Monad (when)
+import qualified Data.Text as Text
+import qualified Text.Blaze as Blaze
+import Text.Blaze.Html5 ((!))
+import qualified Text.Blaze.Html5 as H
+import qualified Text.Blaze.Html5.Attributes as A
+
+import qualified Elm.Compiler as Compiler
+import qualified Elm.Compiler.Module as Module
+import qualified Elm.Utils as Utils
+
+
+-- ACTUALLY COMPILE STUFF
+
+compile :: FilePath -> IO (Either String String)
+compile filePath =
+  do  result <- Utils.unwrappedRun "elm-make" [ "--yes", filePath ]
+      case result of
+        Left (Utils.MissingExe msg) ->
+          return (Left msg)
+
+        Left (Utils.CommandFailed out err) ->
+          return (Left (out ++ err))
+
+        Right _ ->
+          do  code <- readFile "elm.js"
+              return (Right code)
+
+
+-- TO JSON
+
+toJson :: FilePath -> IO String
+toJson filePath =
+  do  result <- compile filePath
+      case result of
+        Right code ->
+          return (jsonReply "success" code)
+
+        Left err ->
+          return (jsonReply "error" err)
+
+
+jsonReply :: String -> String -> String
+jsonReply field value =
+    concat [ "{ ", show field, " : ", show value, " }" ]
+
+
+-- TO HTML
+
+toHtml :: Bool -> FilePath -> IO H.Html
+toHtml debug filePath =
+  do  sourceCode <- readFile filePath
+      result <- compile filePath
+      case (,) <$> Compiler.parseDependencies sourceCode <*> result of
+        Right ((name, _deps), code) ->
+            return $ htmlDocument (Module.nameToString name) $
+                do  H.script $ Blaze.preEscapedToMarkup code
+
+                    when debug $ do
+                        script "/debugger.js"
+                        script "/debugging-runtime.js"
+
+                    H.script $ Blaze.preEscapedToMarkup (initialize debug name filePath)
+
+        Left errMsg ->
+            return $ htmlDocument "Oops!" $
+                H.span ! A.style "font-family: monospace;" $
+                    Blaze.preEscapedToMarkup (addSpaces errMsg)
+
+
+htmlDocument :: String -> H.Html -> H.Html
+htmlDocument title content =
+  H.docTypeHtml $ do 
+    H.head $ do
+      H.meta ! A.charset "UTF-8"
+      H.title (H.toHtml title)
+      H.style $ Blaze.preEscapedToMarkup myStyle
+    H.body $ do
+      content
+
+
+script :: FilePath -> H.Html
+script path =
+    H.script ! A.src (H.toValue path) $ ""
+
+
+myStyle :: Text.Text
+myStyle =
+    "html, head, body { padding:0; margin:0; }\n\
+    \body { font-family: calibri, helvetica, arial, sans-serif; }\n\
+    \a:link { text-decoration: none; color: rgb(15,102,230); }\n\
+    \a:visited { text-decoration: none; }\n\
+    \a:active { text-decoration: none; }\n\
+    \a:hover { text-decoration: underline; color: rgb(234,21,122); }\n\
+    \html,body { height: 100%; margin: 0px; }\n"
+
+
+
+addSpaces :: String -> String
+addSpaces str =
+  case str of
+    ' ' : ' ' : rest ->
+        " &nbsp;" ++ addSpaces rest
+
+    '\n' : rest ->
+        "<br>" ++ addSpaces rest
+
+    c : rest ->
+        c : addSpaces rest
+
+    [] -> []
+
+
+initialize :: Bool -> Module.Name -> FilePath -> String
+initialize debug name filePath =
+  let moduleName = "Elm." ++ Module.nameToString name
+  in
+      "var runningElmModule =\n    " ++
+      case debug of
+        True -> "Elm.debugFullscreen(" ++ moduleName ++ ", \"" ++ filePath ++ "\");"
+        False -> "Elm.fullscreen(" ++ moduleName ++ ");"
diff --git a/backend/Index.hs b/backend/Index.hs
new file mode 100644
--- /dev/null
+++ b/backend/Index.hs
@@ -0,0 +1,201 @@
+{-# OPTIONS_GHC -Wall #-}
+{-# LANGUAGE OverloadedStrings #-}
+module Index (elmIndexGenerator) where
+
+import Control.Monad
+import Control.Monad.IO.Class
+import qualified Data.ByteString.Char8 as S
+import Data.List (sort, partition, intercalate)
+import Data.Time.Clock (diffUTCTime, getCurrentTime)
+import System.Directory (doesDirectoryExist, doesFileExist, getDirectoryContents, getModificationTime)
+import System.FilePath ((</>), takeExtension, splitDirectories)
+import Snap.Core (MonadSnap, modifyResponse, setContentType, writeBS)
+
+indexStyle :: S.ByteString
+indexStyle =
+    S.intercalate "\n"
+    [ "body {"
+    , "    margin: 0;"
+    , "    background: rgb(253,253,253);"
+    , "    font-family: 'Lucida Grande','Trebuchet MS','Bitstream Vera Sans',Verdana,Helvetica,sans-serif;"
+    , "}"
+    , "div.topbar {"
+    , "    height: 6px;"
+    , "    background-color: rgb(96,181,204);"
+    , "}"
+    , "div.header {"
+    , "    padding: 20px 50px;"
+    , "    font-size: 30px;"
+    , "}"
+    , "div.content { padding: 0 40px }"
+    , "table {"
+    , "    width:100%;"
+    , "    border-collapse: collapse;"
+    , "    margin-bottom: 40px;"
+    , "    float: left"
+    , "}"
+    , "a { text-decoration: none; color:rgb(96,181,204) }"
+    , "td { padding: 8px 10px; color:rgb(136,136,136) }"
+    , "tr { border-bottom: solid rgb(245,245,245) 1px }"
+    , "th {"
+    , "    text-align: left;"
+    , "    padding: 6px 10px;"
+    , "    font-weight: normal;"
+    , "    font-size: 24px;"
+    , "}"
+    ]
+
+writeS :: MonadSnap m => FilePath -> m ()
+writeS = writeBS . S.pack
+
+
+replaceChar :: Char -> Char -> String -> String
+replaceChar old new string =
+    map (\c -> if c == old then new else c) string
+
+
+makeSafe :: String -> String
+makeSafe filePath =
+    replaceChar ' ' '+' filePath
+
+
+writeLink :: MonadSnap m => String -> String -> m ()
+writeLink href name =
+ do writeBS "<a href=\""
+    writeS (makeSafe href)
+    writeBS "\">"
+    writeS name
+    writeBS "</a>"
+
+
+timeSince :: MonadSnap m => FilePath -> m String
+timeSince filePath =
+ do modificationTime <- liftIO $ getModificationTime filePath
+    currentTime <- liftIO getCurrentTime
+    return (showDiff currentTime modificationTime)
+ where
+    showDiff currentTime modificationTime =
+        case diffUTCTime currentTime modificationTime of
+          diff
+            | diff < minute -> format diff second "second"
+            | diff < hour   -> format diff minute "minute"
+            | diff < day    -> format diff hour "hour"
+            | diff < year   -> format diff day "day"
+            | otherwise     -> format diff year "year"
+
+    format diff scale name =
+        let t :: Integer
+            t = round (diff / scale)
+        in
+            show t ++ " " ++ name ++ (if t == 1 then "" else "s") ++ " ago"
+
+    second = 1
+    minute = 60 * second
+    hour = 60 * minute
+    day = 24 * hour
+    year = 365 * day
+
+
+elmIndexGenerator :: MonadSnap m => FilePath -> m ()
+elmIndexGenerator directory =
+ do modifyResponse $ setContentType "text/html; charset=utf-8"
+
+    let title =
+          intercalate "/" $
+          case splitDirectories directory of
+            "." : rest -> "~" : rest
+            path -> path
+
+    writeBS "<!DOCTYPE html>\n<html>\n<head>"
+    writeBS "<title>"
+    writeS title
+    writeBS "</title>"
+    writeBS "<style type='text/css'>"
+    writeBS indexStyle
+    writeBS "</style></head><body>"
+
+    writeBS "<div class=\"topbar\"></div>"
+
+    writeBS "<div class=\"header\">"
+    writeLink "/" "~"
+    writeBS " / "
+    case splitDirectories directory of
+      _ : pathParts@(_:_) -> do
+        let fullPaths = scanl1 (\a b -> a ++ "/" ++ b) pathParts
+        forM_ (zip pathParts fullPaths) $ \(part, fullPath) -> do
+            writeLink ("/" ++ fullPath) part
+            writeBS " / "
+      _ -> return ()
+
+    writeBS "</div>"
+
+    writeBS "<div class=\"content\">"
+
+    entries <- liftIO $ getDirectoryContents directory
+    allDirs <- liftIO $ filterM (doesDirectoryExist . (directory </>)) entries
+    files   <- liftIO $ filterM (doesFileExist . (directory </>)) entries
+
+    let (elmFiles, otherFiles) =
+            partition (\file -> takeExtension file == ".elm") files
+
+    let dotFile filePath =
+            null filePath || head filePath == '.'
+
+    let keepDir dir =
+            dir /= "cache" &&
+            dir /= "build" &&
+            not (dotFile dir)
+
+    let dirs = sort (filter keepDir allDirs)
+
+    let nonElmFiles = sort $ filter (not . dotFile) otherFiles
+
+    unless (null dirs) $ do
+        writeBS "<table><tr><th>Directories</th></tr>"
+        forM_ dirs $ \dir -> do
+            writeBS "<tr><td>"
+            writeLink (dir ++ "/") dir
+            writeBS "</td></tr>"
+        writeBS "</table>"
+
+    unless (null elmFiles) $ do
+        writeBS "<table><tr><th>Elm Files</th><th></th></tr>"
+        forM_ (sort elmFiles) $ \filePath -> do
+            writeBS "<tr>"
+
+            writeBS "<td>"
+            writeLink
+                ("/" ++ intercalate "/" (splitDirectories directory) ++ "/" ++ filePath ++ "?debug")
+                "<img title=\"Debug mode\" src=/_reactor/wrench.png width=\"12\" height=\"12\">"
+            writeBS "&#8195;"
+            writeLink filePath filePath
+            writeBS "</td>"
+
+            writeBS "<td style=\"text-align:right;\">"
+            writeS =<< timeSince (directory </> filePath)
+            writeBS "</td>"
+
+            writeBS "</tr>"
+        writeBS "</table>"
+
+    unless (null nonElmFiles) $ do
+        writeBS "<table>"
+        writeBS "<tr><th>Other Files</th><th></th></tr>"
+        forM_ nonElmFiles $ \filePath -> do
+            writeBS "<tr>"
+
+            writeBS "<td>"
+            writeLink filePath filePath 
+            writeBS "</td>"
+
+            writeBS "<td style=\"text-align:right;\">"
+            writeS =<< timeSince (directory </> filePath)
+            writeBS "</td>"
+
+            writeBS "</tr>"
+        writeBS "</table>"
+
+    writeBS "</div>"
+    writeBS "</body>"
+    writeBS "</html>"
+
diff --git a/backend/Main.hs b/backend/Main.hs
new file mode 100644
--- /dev/null
+++ b/backend/Main.hs
@@ -0,0 +1,152 @@
+{-# OPTIONS_GHC -Wall #-}
+{-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-}
+module Main where
+
+import Control.Applicative ((<$>),(<|>))
+import Control.Monad (guard)
+import Control.Monad.Trans (MonadIO(liftIO))
+import qualified Data.ByteString.Char8 as BSC
+import qualified Data.Version as Version
+import qualified Network.WebSockets.Snap as WSS
+import qualified Text.Blaze.Html5 as H
+import qualified Text.Blaze.Html.Renderer.Utf8 as Blaze
+import System.Console.CmdArgs
+import System.Directory
+import System.FilePath
+import Snap.Core
+import Snap.Http.Server
+import Snap.Util.FileServe
+
+import Index
+import qualified Compile
+import qualified Socket
+import qualified Utils
+import Paths_elm_reactor (version)
+import qualified Elm.Compiler as Compiler
+import Elm.Utils ((|>))
+
+
+data Flags = Flags
+    { port :: Int
+    , runtime :: Maybe FilePath
+    }
+    deriving (Data,Typeable,Show,Eq)
+
+
+flags :: Flags
+flags = Flags
+  { port = 8000 &= help "set the port of the reactor"
+  , runtime = Nothing &= typFile
+              &= help "Specify a custom location for Elm's runtime system."
+  } &= help "Interactive development tool that makes it easy to develop and debug Elm programs.\n\
+            \    Read more about it at <https://github.com/elm-lang/elm-reactor>."
+    &= helpArg [explicit, name "help", name "h"]
+    &= versionArg [ explicit, name "version", name "v"
+                  , summary (Version.showVersion version)
+                  ]
+    &= summary ("Elm Reactor " ++ Version.showVersion version ++
+                ", (c) Evan Czaplicki 2011-2014")
+
+
+config :: Int -> Config Snap a
+config portNumber =
+    defaultConfig
+      |> setPort portNumber
+      |> setAccessLog ConfigNoLog
+      |> setErrorLog ConfigNoLog
+
+
+-- | Set up the reactor.
+main :: IO ()
+main =
+  do  cargs <- cmdArgs flags
+      putStrLn startupMessage
+      httpServe (config (port cargs)) $
+          serveElm
+          <|> route [ ("socket", socket) ]
+          <|> serveDirectoryWith directoryConfig "."
+          <|> serveAssets
+          <|> error404
+
+
+startupMessage :: String
+startupMessage =
+  "Elm Reactor " ++ Version.showVersion version
+
+
+directoryConfig :: MonadSnap m => DirectoryConfig m
+directoryConfig =
+    fancyDirectoryConfig
+    { indexFiles = []
+    , indexGenerator = elmIndexGenerator
+    }
+
+
+socket :: Snap ()
+socket = maybe error400 socketSnap =<< getParam "file"
+  where
+    socketSnap fileParam =
+         WSS.runWebSocketsSnap $ Socket.fileChangeApp $ BSC.unpack fileParam
+
+
+error400 :: Snap ()
+error400 =
+    modifyResponse $ setResponseStatus 400 "Bad Request"
+
+
+error404 :: Snap ()
+error404 =
+    modifyResponse $ setResponseStatus 404 "Not Found"
+
+
+-- SERVE ELM CODE
+
+serveElm :: Snap ()
+serveElm =
+  let despace = map (\c -> if c == '+' then ' ' else c) in
+  do  file <- despace . BSC.unpack . rqPathInfo <$> getRequest
+      debugParam <- getParam "debug"
+      let debug = maybe False (const True) debugParam
+      exists <- liftIO $ doesFileExist file
+      guard (exists && takeExtension file == ".elm")
+      result <- liftIO $ Compile.toHtml debug file
+      serveHtml result
+
+
+serveHtml :: MonadSnap m => H.Html -> m ()
+serveHtml html =
+  do  _ <- setContentType "text/html" <$> getResponse
+      writeBuilder (Blaze.renderHtmlBuilder html)
+
+
+-- SERVE STATIC ASSETS
+
+serveAssets :: Snap ()
+serveAssets =
+  do  file <- BSC.unpack . rqPathInfo <$> getRequest
+      case () of
+        _ | file == "debugging-runtime.js" ->
+              serveFile =<< liftIO Compiler.runtimeDebugPath
+
+          | file `elem` staticAssets ->
+              serveFile =<< liftIO (Utils.getDataFile file)
+
+          | otherwise -> pass
+
+
+staticAssets :: [FilePath]
+staticAssets =
+    [ "favicon.ico"
+    , "debugger.js"
+    , "_reactor/wrench.png"
+    , "_reactor/debugger/pause-button-up.png"
+    , "_reactor/debugger/pause-button-down.png"
+    , "_reactor/debugger/pause-button-hover.png"
+    , "_reactor/debugger/play-button-up.png"
+    , "_reactor/debugger/play-button-down.png"
+    , "_reactor/debugger/play-button-hover.png"
+    , "_reactor/debugger/restart-button-up.png"
+    , "_reactor/debugger/restart-button-down.png"
+    , "_reactor/debugger/restart-button-hover.png"
+    ]
+
diff --git a/backend/Socket.hs b/backend/Socket.hs
new file mode 100644
--- /dev/null
+++ b/backend/Socket.hs
@@ -0,0 +1,58 @@
+{-# OPTIONS_GHC -Wall #-}
+{-# LANGUAGE OverloadedStrings #-}
+module Socket where
+
+import Control.Monad.Trans (MonadIO(liftIO))
+import Control.Concurrent (threadDelay, forkIO, killThread, ThreadId)
+import qualified Control.Exception as E
+import qualified Data.ByteString.Char8 as BSC
+import qualified Filesystem.Path.CurrentOS as FP
+import qualified Network.WebSockets as WS
+import qualified System.FSNotify.Devel as NDevel
+import qualified System.FSNotify as Notify
+
+import qualified Compile
+
+
+fileChangeApp :: FilePath -> WS.ServerApp
+fileChangeApp watchedFile pendingConnection =
+ do connection <- WS.acceptRequest pendingConnection
+    Notify.withManager $ \notifyManager -> do
+        _ <- NDevel.treeExtExists notifyManager "." "elm" (sendHotSwap watchedFile connection)
+        keepAlive connection
+
+
+sendHotSwap :: FilePath -> WS.Connection -> FP.FilePath -> IO ()
+sendHotSwap watchedFile connection _ =
+ do result <- liftIO (Compile.toJson watchedFile)
+    WS.sendTextData connection (BSC.pack result)
+
+
+keepAlive :: WS.Connection -> IO ()
+keepAlive connection =
+    loop
+  where
+    loop :: IO ()
+    loop = do
+      pingThread <- forkIO ping
+      listen pingThread
+
+    ping :: IO ()
+    ping = do
+      threadDelay (10 * 1000000) -- 10 seconds
+      WS.sendPing connection ("ping" :: BSC.ByteString) `E.catch` connectionClosed
+
+    connectionClosed :: E.SomeException -> IO ()
+    connectionClosed _ = return ()
+
+    listen :: ThreadId -> IO ()
+    listen pingThread = do
+      pong <- WS.receive connection
+      case pong of
+        WS.DataMessage _ -> listen pingThread
+        WS.ControlMessage controlMessage ->
+            case controlMessage of
+              WS.Ping _ -> listen pingThread
+              WS.Pong _ -> loop
+              WS.Close _ _ ->
+                  killThread pingThread >> return ()
diff --git a/backend/Utils.hs b/backend/Utils.hs
new file mode 100644
--- /dev/null
+++ b/backend/Utils.hs
@@ -0,0 +1,11 @@
+{-# OPTIONS_GHC -Wall #-}
+module Utils where
+
+import qualified Elm.Utils as Utils
+import qualified Paths_elm_reactor as Reactor
+
+
+{-| The absolute path to a data file -}
+getDataFile :: FilePath -> IO FilePath
+getDataFile name =
+    Utils.getAsset "reactor" Reactor.getDataFileName name
diff --git a/elm-reactor.cabal b/elm-reactor.cabal
--- a/elm-reactor.cabal
+++ b/elm-reactor.cabal
@@ -1,38 +1,49 @@
-Name:                elm-reactor
-Version:             0.1
-Synopsis:            Interactive development tool for Elm programs
-Description:         Provides an interactive development tool that makes it easy
-                     to develop and debug Elm programs. It will automatically
-                     compile any Elm program—independent of editor. It permits
-                     hot-swapping and time-traveling debugging.
+Name: elm-reactor
+Version: 0.2
 
-Homepage:            http://elm-lang.org
+Synopsis:
+  Interactive development tool for Elm programs
 
-License:             BSD3
-License-file:        LICENSE
+Description:
+  Provides an interactive development tool that makes it easy
+  to develop and debug Elm programs. It will automatically
+  compile any Elm program—independent of editor. It permits
+  hot-swapping and time-traveling debugging.
 
-Author:              Evan Czaplicki
-Maintainer:          info@elm-lang.org
-Copyright:           Copyright: (c) 2011-2014 Evan Czaplicki
 
-Category:            Compiler, Language
+Homepage:
+  http://elm-lang.org
 
-Build-type:          Simple
+License: BSD3
+License-file: LICENSE
 
-Data-dir:            assets
-Data-files:          favicon.ico
-                     debugger.js
-                     _reactor/wrench.png
-                     _reactor/debugger/pause-button-up.png
-                     _reactor/debugger/pause-button-down.png
-                     _reactor/debugger/pause-button-hover.png
-                     _reactor/debugger/play-button-up.png
-                     _reactor/debugger/play-button-down.png
-                     _reactor/debugger/play-button-hover.png
-                     _reactor/debugger/restart-button-up.png
-                     _reactor/debugger/restart-button-down.png
-                     _reactor/debugger/restart-button-hover.png
+Author:     Evan Czaplicki
+Maintainer: info@elm-lang.org
+Copyright:  Copyright: (c) 2011-2014 Evan Czaplicki
 
+Category:
+  Compiler, Language
+
+Build-type:
+  Custom
+
+Data-dir:
+  assets
+
+Data-files:
+  favicon.ico
+  debugger.js
+  _reactor/wrench.png
+  _reactor/debugger/pause-button-up.png
+  _reactor/debugger/pause-button-down.png
+  _reactor/debugger/pause-button-hover.png
+  _reactor/debugger/play-button-up.png
+  _reactor/debugger/play-button-down.png
+  _reactor/debugger/play-button-hover.png
+  _reactor/debugger/restart-button-up.png
+  _reactor/debugger/restart-button-down.png
+  _reactor/debugger/restart-button-hover.png
+
 Extra-source-files:  README.md
 Cabal-version:       >=1.8
 
@@ -41,32 +52,42 @@
   location: git://github.com/elm-lang/elm-reactor.git
 
 Executable elm-reactor
-  Main-is:             Server.hs
-  ghc-options:         -threaded -O2
-  other-modules:       Generate,
-                       Index,
-                       Socket,
-                       Utils
-  Build-depends:       base >=4.2 && <5,
-                       blaze-html,
-                       blaze-markup,
-                       bytestring,
-                       cmdargs,
-                       containers >= 0.3,
-                       directory >= 1.2,
-                       Elm >= 0.13,
-                       filepath,
-                       fsnotify >= 0.1.0.2,
-                       HTTP,
-                       mtl,
-                       process,
-                       snap-core,
-                       snap-server,
-                       system-filepath,
-                       time,
-                       transformers,
-                       unordered-containers,
-                       websockets >= 0.9 && < 0.10,
-                       websockets-snap >= 0.8.2.1
+  ghc-options:
+    -threaded -O2
+
+  hs-source-dirs:
+    backend
+
+  Main-is:
+    Main.hs
+
+  other-modules:
+    Compile,
+    Index,
+    Socket,
+    Utils
+
+  Build-depends:
+    base >=4.2 && <5,
+    blaze-html,
+    blaze-markup,
+    bytestring,
+    cmdargs,
+    containers >= 0.3,
+    directory >= 1.2,
+    elm-compiler >= 0.14 && < 0.15,
+    filepath,
+    fsnotify >= 0.1.0.2,
+    HTTP,
+    mtl,
+    process,
+    snap-core,
+    snap-server,
+    system-filepath,
+    text,
+    time,
+    transformers,
+    unordered-containers,
+    websockets >= 0.9 && < 0.10,
+    websockets-snap >= 0.8.2.1
   
-  hs-source-dirs:      server
diff --git a/server/Generate.hs b/server/Generate.hs
deleted file mode 100644
--- a/server/Generate.hs
+++ /dev/null
@@ -1,107 +0,0 @@
-{-# OPTIONS_GHC -Wall #-}
-{-# LANGUAGE OverloadedStrings #-}
-module Generate (html, js) where
-
-import Control.Monad (forM_)
-import Data.Maybe (fromMaybe)
-import System.Exit
-import System.FilePath
-import System.Process
-import System.IO (hGetContents)
-import Text.Blaze (preEscapedToMarkup)
-import Text.Blaze.Html5 ((!))
-import qualified Text.Blaze.Html5 as H
-import qualified Text.Blaze.Html5.Attributes as A
-
-import qualified Elm.Internal.Utils as Elm
-
--- | Using a page title and the full source of an Elm program, compile down to
---   a valid HTML document.
-html :: FilePath -> Bool -> IO H.Html
-html filePath doDebug =
-  do src <- readFile filePath
-     compilerResult <- compile filePath
-     return . buildPage $ formatResult src compilerResult
-  where
-    script = H.script ! A.type_ "text/javascript"
-
-    formatResult src compilerResult =
-        case compilerResult of
-          Right jsSrc ->
-              do script $ preEscapedToMarkup jsSrc
-                 script $ preEscapedToMarkup $ runFullscreen src
-          Left err ->
-              H.span ! A.style "font-family: monospace;" $
-               forM_ (lines err) $ \line ->
-                   do preEscapedToMarkup (addSpaces line)
-                      H.br
-
-    attachDebugger moduleName =
-      case doDebug of
-        True -> "Elm.debugFullscreen(" ++ moduleName ++ ", \"" ++ filePath ++ "\");"
-        False -> "Elm.fullscreen(" ++ moduleName ++ ");"
-
-    runFullscreen src =
-        let moduleName = "Elm." ++ fromMaybe "Main" (Elm.moduleName src)
-        in  "var runningElmModule = " ++ (attachDebugger moduleName)
-
-    insertDebuggerScript =
-      case doDebug of
-        True -> script ! A.src (H.toValue ("/debugger.js" :: String)) $ ""
-        False -> return ()
-
-    buildPage content = H.docTypeHtml $ do
-        H.head $ do
-          H.meta ! A.charset "UTF-8"
-          H.title . H.toHtml $ takeFileName filePath
-          H.style ! A.type_ "text/css" $ preEscapedToMarkup
-              ("a:link {text-decoration: none; color: rgb(15,102,230);}\n\
-               \a:visited {text-decoration: none}\n\
-               \a:active {text-decoration: none}\n\
-               \a:hover {text-decoration: underline; color: rgb(234,21,122);}\n\
-               \html,body {height: 100%; margin: 0px;}" :: String)
-        H.body $ do
-          script ! A.src (H.toValue ("/elm-runtime.js" :: String)) $ ""
-          insertDebuggerScript
-          content
-
--- | Creates the javascript for the elm program and returns it as a 
---   JSONified string with either success:<code> or error:<message>
-js :: FilePath -> IO String
-js filePath =
-  do output <- compile filePath
-     return (either (wrap "error") (wrap "success") output)
-  where
-    wrap :: String -> String -> String
-    wrap typ msg = "{ " ++ show typ ++ " : " ++ show msg ++ " }"
-
-addSpaces :: String -> String
-addSpaces str =
-  case str of
-    ' ' : ' ' : rest -> " &nbsp;" ++ addSpaces rest
-    c : rest -> c : addSpaces rest
-    [] -> []
-
-compile :: FilePath -> IO (Either String String)
-compile filePath =
-  do (_, Just hout, Just herr, p) <- createProcess (proc "elm" $ args fileName)
-                                     { cwd = Just directory
-                                     , std_out = CreatePipe
-                                     , std_err = CreatePipe
-                                     }
-     exitCode <- waitForProcess p
-     stdout <- exitCode `seq` hGetContents hout
-     stderr <- exitCode `seq` hGetContents herr
-     case exitCode of
-       ExitFailure _ ->
-         do return (Left (stdout ++ stderr))
-       ExitSuccess ->
-         do result <- readFile (directory </> "build" </> fileName `replaceExtension` "js")
-            return (Right result)
-  where
-    (directory, fileName) = splitFileName filePath
-    args file =
-        [ "--make"
-        , "--only-js"
-        , file
-        ]
diff --git a/server/Index.hs b/server/Index.hs
deleted file mode 100644
--- a/server/Index.hs
+++ /dev/null
@@ -1,201 +0,0 @@
-{-# OPTIONS_GHC -Wall #-}
-{-# LANGUAGE OverloadedStrings #-}
-module Index (elmIndexGenerator) where
-
-import Control.Monad
-import Control.Monad.IO.Class
-import qualified Data.ByteString.Char8 as S
-import Data.List (sort, partition, intercalate)
-import Data.Time.Clock (diffUTCTime, getCurrentTime)
-import System.Directory (doesDirectoryExist, doesFileExist, getDirectoryContents, getModificationTime)
-import System.FilePath ((</>), takeExtension, splitDirectories)
-import Snap.Core (MonadSnap, modifyResponse, setContentType, writeBS)
-
-indexStyle :: S.ByteString
-indexStyle =
-    S.intercalate "\n"
-    [ "body {"
-    , "    margin: 0;"
-    , "    background: rgb(253,253,253);"
-    , "    font-family: 'Lucida Grande','Trebuchet MS','Bitstream Vera Sans',Verdana,Helvetica,sans-serif;"
-    , "}"
-    , "div.topbar {"
-    , "    height: 6px;"
-    , "    background-color: rgb(96,181,204);"
-    , "}"
-    , "div.header {"
-    , "    padding: 20px 50px;"
-    , "    font-size: 30px;"
-    , "}"
-    , "div.content { padding: 0 40px }"
-    , "table {"
-    , "    width:100%;"
-    , "    border-collapse: collapse;"
-    , "    margin-bottom: 40px;"
-    , "    float: left"
-    , "}"
-    , "a { text-decoration: none; color:rgb(96,181,204) }"
-    , "td { padding: 8px 10px; color:rgb(136,136,136) }"
-    , "tr { border-bottom: solid rgb(245,245,245) 1px }"
-    , "th {"
-    , "    text-align: left;"
-    , "    padding: 6px 10px;"
-    , "    font-weight: normal;"
-    , "    font-size: 24px;"
-    , "}"
-    ]
-
-writeS :: MonadSnap m => FilePath -> m ()
-writeS = writeBS . S.pack
-
-
-replaceChar :: Char -> Char -> String -> String
-replaceChar old new string =
-    map (\c -> if c == old then new else c) string
-
-
-makeSafe :: String -> String
-makeSafe filePath =
-    replaceChar ' ' '+' filePath
-
-
-writeLink :: MonadSnap m => String -> String -> m ()
-writeLink href name =
- do writeBS "<a href=\""
-    writeS (makeSafe href)
-    writeBS "\">"
-    writeS name
-    writeBS "</a>"
-
-
-timeSince :: MonadSnap m => FilePath -> m String
-timeSince filePath =
- do modificationTime <- liftIO $ getModificationTime filePath
-    currentTime <- liftIO getCurrentTime
-    return (showDiff currentTime modificationTime)
- where
-    showDiff currentTime modificationTime =
-        case diffUTCTime currentTime modificationTime of
-          diff
-            | diff < minute -> format diff second "second"
-            | diff < hour   -> format diff minute "minute"
-            | diff < day    -> format diff hour "hour"
-            | diff < year   -> format diff day "day"
-            | otherwise     -> format diff year "year"
-
-    format diff scale name =
-        let t :: Integer
-            t = round (diff / scale)
-        in
-            show t ++ " " ++ name ++ (if t == 1 then "" else "s") ++ " ago"
-
-    second = 1
-    minute = 60 * second
-    hour = 60 * minute
-    day = 24 * hour
-    year = 365 * day
-
-
-elmIndexGenerator :: MonadSnap m => FilePath -> m ()
-elmIndexGenerator directory =
- do modifyResponse $ setContentType "text/html; charset=utf-8"
-
-    let title =
-          intercalate "/" $
-          case splitDirectories directory of
-            "." : rest -> "~" : rest
-            path -> path
-
-    writeBS "<!DOCTYPE html>\n<html>\n<head>"
-    writeBS "<title>"
-    writeS title
-    writeBS "</title>"
-    writeBS "<style type='text/css'>"
-    writeBS indexStyle
-    writeBS "</style></head><body>"
-
-    writeBS "<div class=\"topbar\"></div>"
-
-    writeBS "<div class=\"header\">"
-    writeLink "/" "~"
-    writeBS " / "
-    case splitDirectories directory of
-      _ : pathParts@(_:_) -> do
-        let fullPaths = scanl1 (\a b -> a ++ "/" ++ b) pathParts
-        forM_ (zip pathParts fullPaths) $ \(part, fullPath) -> do
-            writeLink ("/" ++ fullPath) part
-            writeBS " / "
-      _ -> return ()
-
-    writeBS "</div>"
-
-    writeBS "<div class=\"content\">"
-
-    entries <- liftIO $ getDirectoryContents directory
-    allDirs <- liftIO $ filterM (doesDirectoryExist . (directory </>)) entries
-    files   <- liftIO $ filterM (doesFileExist . (directory </>)) entries
-
-    let (elmFiles, otherFiles) =
-            partition (\file -> takeExtension file == ".elm") files
-
-    let dotFile filePath =
-            null filePath || head filePath == '.'
-
-    let keepDir dir =
-            dir /= "cache" &&
-            dir /= "build" &&
-            not (dotFile dir)
-
-    let dirs = sort (filter keepDir allDirs)
-
-    let nonElmFiles = sort $ filter (not . dotFile) otherFiles
-
-    unless (null dirs) $ do
-        writeBS "<table><tr><th>Directories</th></tr>"
-        forM_ dirs $ \dir -> do
-            writeBS "<tr><td>"
-            writeLink (dir ++ "/") dir
-            writeBS "</td></tr>"
-        writeBS "</table>"
-
-    unless (null elmFiles) $ do
-        writeBS "<table><tr><th>Elm Files</th><th></th></tr>"
-        forM_ (sort elmFiles) $ \filePath -> do
-            writeBS "<tr>"
-
-            writeBS "<td>"
-            writeLink
-                ("/" ++ intercalate "/" (splitDirectories directory) ++ "/" ++ filePath ++ "?debug")
-                "<img title=\"Debug mode\" src=/_reactor/wrench.png width=\"12\" height=\"12\">"
-            writeBS "&#8195;"
-            writeLink filePath filePath
-            writeBS "</td>"
-
-            writeBS "<td style=\"text-align:right;\">"
-            writeS =<< timeSince (directory </> filePath)
-            writeBS "</td>"
-
-            writeBS "</tr>"
-        writeBS "</table>"
-
-    unless (null nonElmFiles) $ do
-        writeBS "<table>"
-        writeBS "<tr><th>Other Files</th><th></th></tr>"
-        forM_ nonElmFiles $ \filePath -> do
-            writeBS "<tr>"
-
-            writeBS "<td>"
-            writeLink filePath filePath 
-            writeBS "</td>"
-
-            writeBS "<td style=\"text-align:right;\">"
-            writeS =<< timeSince (directory </> filePath)
-            writeBS "</td>"
-
-            writeBS "</tr>"
-        writeBS "</table>"
-
-    writeBS "</div>"
-    writeBS "</body>"
-    writeBS "</html>"
-
diff --git a/server/Server.hs b/server/Server.hs
deleted file mode 100644
--- a/server/Server.hs
+++ /dev/null
@@ -1,152 +0,0 @@
-{-# OPTIONS_GHC -Wall #-}
-{-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-}
-module Main where
-
-import Control.Applicative ((<$>),(<|>))
-import Control.Monad (guard)
-import Control.Monad.Trans (MonadIO(liftIO))
-import qualified Data.ByteString.Char8 as BSC
-import qualified Data.Version as Version
-import qualified Network.WebSockets.Snap as WSS
-import qualified Text.Blaze.Html5 as H
-import qualified Text.Blaze.Html.Renderer.Utf8 as BlazeBS
-import System.Console.CmdArgs
-import System.Directory
-import System.FilePath
-import System.Process
-import System.IO (hGetContents)
-import Paths_elm_reactor (version)
-import qualified Elm.Internal.Paths as Elm
-import Snap.Core
-import Snap.Http.Server
-import Snap.Util.FileServe
-
-import Index
-import qualified Generate
-import qualified Socket
-import qualified Utils
-
-data Flags = Flags
-  { port :: Int
-  , runtime :: Maybe FilePath
-  } deriving (Data,Typeable,Show,Eq)
-
-flags :: Flags
-flags = Flags
-  { port = 8000 &= help "set the port of the reactor"
-  , runtime = Nothing &= typFile
-              &= help "Specify a custom location for Elm's runtime system."
-  } &= help "Interactive development tool that makes it easy to develop and debug Elm programs.\n\
-            \    Read more about it at <https://github.com/elm-lang/elm-reactor>."
-    &= helpArg [explicit, name "help", name "h"]
-    &= versionArg [ explicit, name "version", name "v"
-                  , summary (Version.showVersion version)
-                  ]
-    &= summary ("Elm Reactor " ++ Version.showVersion version ++
-                ", (c) Evan Czaplicki 2011-2014")
-
-
-config :: Int -> Config Snap a
-config portNumber =
-  setBind "localhost" $
-  setPort portNumber $
-  setAccessLog ConfigNoLog $
-  setErrorLog ConfigNoLog $
-  defaultConfig
-
--- | Set up the reactor.
-main :: IO ()
-main = do
-  cargs <- cmdArgs flags
-  (_,Just h,_,_) <- createProcess $ (shell "elm --version") { std_out = CreatePipe }
-  elmVer <- hGetContents h
-  putStrLn (startupMessage elmVer)
-  httpServe (config (port cargs)) $
-      serveRuntime (maybe Elm.runtime id (runtime cargs))
-      <|> serveElm
-      <|> route [ ("socket", socket) ]
-      <|> serveDirectoryWith directoryConfig "."
-      <|> serveAssets
-      <|> error404
-
-startupMessage :: String -> String
-startupMessage elmVer =
-  "Elm Reactor " ++ Version.showVersion version ++ ", backed by version " ++
-  filter (/= '\n') elmVer ++ " of the compiler."
-
-directoryConfig :: MonadSnap m => DirectoryConfig m
-directoryConfig =
-    fancyDirectoryConfig
-    { indexFiles = []
-    , indexGenerator = elmIndexGenerator
-    }
-
-runtimeName :: String
-runtimeName = "elm-runtime.js"
-
-serveRuntime :: FilePath -> Snap ()
-serveRuntime runtimePath =
-  do file <- BSC.unpack . rqPathInfo <$> getRequest
-     guard (file == runtimeName)
-     serveFileAs "application/javascript" runtimePath
-
-socket :: Snap ()
-socket = maybe error400 socketSnap =<< getParam "file"
-  where
-    socketSnap fileParam =
-         WSS.runWebSocketsSnap $ Socket.fileChangeApp $ BSC.unpack fileParam
-
-withFile :: (FilePath -> H.Html) -> Snap ()
-withFile handler =
-  do filePath <- BSC.unpack . rqPathInfo <$> getRequest
-     exists <- liftIO (doesFileExist filePath)
-     if not exists then error404 else
-         serveHtml $ handler filePath
-
-error400 :: Snap ()
-error400 = modifyResponse $ setResponseStatus 400 "Bad Request"
-
-error404 :: Snap ()
-error404 = modifyResponse $ setResponseStatus 404 "Not Found"
-
-serveHtml :: MonadSnap m => H.Html -> m ()
-serveHtml html =
-  do _ <- setContentType "text/html" <$> getResponse
-     writeLBS (BlazeBS.renderHtml html)
-
-serveElm :: Snap ()
-serveElm =
-  let despace = map (\c -> if c == '+' then ' ' else c) in
-  do file <- despace . BSC.unpack . rqPathInfo <$> getRequest
-     debugParam <- getParam "debug"
-     let doDebug = maybe False (const True) debugParam
-     exists <- liftIO $ doesFileExist file
-     guard (exists && takeExtension file == ".elm")
-     result <- liftIO $ Generate.html file doDebug
-     serveHtml result
-
-serveAsset :: FilePath -> Snap ()
-serveAsset assetPath =
-  do dataPath <- liftIO $ Utils.getDataFile assetPath
-     serveFile dataPath
-
-staticAssets :: [FilePath]
-staticAssets = [ "favicon.ico"
-               , "debugger.js"
-               , "_reactor/wrench.png"
-               , "_reactor/debugger/pause-button-up.png"
-               , "_reactor/debugger/pause-button-down.png"
-               , "_reactor/debugger/pause-button-hover.png"
-               , "_reactor/debugger/play-button-up.png"
-               , "_reactor/debugger/play-button-down.png"
-               , "_reactor/debugger/play-button-hover.png"
-               , "_reactor/debugger/restart-button-up.png"
-               , "_reactor/debugger/restart-button-down.png"
-               , "_reactor/debugger/restart-button-hover.png"
-               ]
-
-serveAssets :: Snap ()
-serveAssets =
-  do file <- BSC.unpack . rqPathInfo <$> getRequest
-     guard (file `elem` staticAssets)
-     serveAsset file
diff --git a/server/Socket.hs b/server/Socket.hs
deleted file mode 100644
--- a/server/Socket.hs
+++ /dev/null
@@ -1,57 +0,0 @@
-{-# OPTIONS_GHC -Wall #-}
-{-# LANGUAGE OverloadedStrings #-}
-module Socket where
-
-import Control.Monad.Trans (MonadIO(liftIO))
-import Control.Concurrent (threadDelay, forkIO, killThread, ThreadId)
-import qualified Control.Exception as E
-import qualified Data.ByteString.Char8 as BSC
-import qualified Filesystem.Path.CurrentOS as FP
-import qualified Network.WebSockets as WS
-import qualified System.FSNotify.Devel as NDevel
-import qualified System.FSNotify as Notify
-
-import qualified Generate
-
-fileChangeApp :: FilePath -> WS.ServerApp
-fileChangeApp watchedFile pendingConnection =
- do connection <- WS.acceptRequest pendingConnection
-    Notify.withManager $ \notifyManager -> do
-        _ <- NDevel.treeExtExists notifyManager "." "elm" (sendHotSwap watchedFile connection)
-        keepAlive connection
-
-
-sendHotSwap :: FilePath -> WS.Connection -> FP.FilePath -> IO ()
-sendHotSwap watchedFile connection _ =
- do result <- liftIO (Generate.js watchedFile)
-    WS.sendTextData connection (BSC.pack result)
-
-
-keepAlive :: WS.Connection -> IO ()
-keepAlive connection =
-    loop
-  where
-    loop :: IO ()
-    loop = do
-      pingThread <- forkIO ping
-      listen pingThread
-
-    ping :: IO ()
-    ping = do
-      threadDelay (10 * 1000000) -- 10 seconds
-      WS.sendPing connection ("ping" :: BSC.ByteString) `E.catch` connectionClosed
-
-    connectionClosed :: E.SomeException -> IO ()
-    connectionClosed _ = return ()
-
-    listen :: ThreadId -> IO ()
-    listen pingThread = do
-      pong <- WS.receive connection
-      case pong of
-        WS.DataMessage _ -> listen pingThread
-        WS.ControlMessage controlMessage ->
-            case controlMessage of
-              WS.Ping _ -> listen pingThread
-              WS.Pong _ -> loop
-              WS.Close _ _ ->
-                  killThread pingThread >> return ()
diff --git a/server/Utils.hs b/server/Utils.hs
deleted file mode 100644
--- a/server/Utils.hs
+++ /dev/null
@@ -1,38 +0,0 @@
-{-# OPTIONS_GHC -Wall #-}
-module Utils where
-
-import System.Directory (doesFileExist)
-import System.Environment (getEnv)
-import System.FilePath ((</>))
-import System.IO.Error (tryIOError)
-import qualified Paths_elm_reactor as This
-
--- |The absolute path to a data file
-getDataFile :: FilePath -> IO FilePath
-getDataFile name = do
-  path <- This.getDataFileName name
-  exists <- doesFileExist path
-  if exists
-    then return path
-    else do
-      environment <- tryIOError (getEnv "ELM_HOME")
-      case environment of
-        Right env -> return (env </> "reactor" </> name)
-        Left _ ->
-          fail $ unlines
-            [ "Unable to find the ELM_HOME environment variable when searching"
-            , "for the " ++ name ++ " file."
-            , ""
-            , "If you installed Elm Platform with the Mac or Windows installer, it looks like"
-            , "ELM_HOME was not set automatically. Look up how to set environment variables"
-            , "on your platform and set ELM_HOME to the directory that contains Elm's static"
-            , "files:"
-            , ""
-            , "  * On Mac it is /usr/local/share/elm"
-            , "  * On Windows it is one of the following:"
-            , "      C:/Program Files/Elm Platform/0.13/share"
-            , "      C:/Program Files (x86)/Elm Platform/0.13/share"
-            , ""
-            , "If it seems like a more complex issue, please report it here:"
-            , "    <https://github.com/elm-lang/elm-platform/issues>"
-            ]
