diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,84 @@
+# [Movie Monad](https://github.com/lettier/movie-monad)
+
+## Changelog
+
+### 0.0.2.0
+
+#### Added
+
+- Hides the cursor and the on-screen controls when the mouse is idle
+- New Logo
+- URL support
+- Keyboard shortcuts
+- makefile
+- Icon
+- AppImage
+- AppImage installation script
+- Support for GTK 3.10
+- macOS screenshots
+- macOS build instructions
+- Screensaver and power management enable/disable
+- Video file path command line option that, if present, plays the video on window realized
+
+#### Changed
+
+- Cabal file
+    - Corrected source-repository
+- Logo
+- README
+- Dependencies
+- Icon
+- Play/Pause toggle to button
+- ICO file to PNG
+- Switched from GstVideoOverlay to GtkSink
+
+#### Removed
+
+- ExifTool requirement
+- Old logo PNG file
+- X11 dependency
+
+-------------------------------------------------------------------------------
+
+### 0.0.1.0
+
+#### Added
+
+- Fullscreen mode
+
+#### Changed
+
+- Screenshot
+- Main function
+    - Extracted callback functions into their own functions
+- Dependencies to match Hackage
+
+#### Removed
+
+- `lib` directory
+
+-------------------------------------------------------------------------------
+
+### 0.0.0.0
+
+#### Added
+
+- File Loader
+- Seek
+- Pause
+- Play
+- Window Width Selector
+- About
+- Screenshot
+- Logo
+- README
+- LICENSE
+- Documentation
+
+#### Changed
+
+-
+
+#### Removed
+
+-
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-![Movie Monad](https://i.imgur.com/Vt9Bipy.png)
+![Movie Monad](https://i.imgur.com/gdsyIMv.png)
 
 # Movie Monad
 
@@ -6,30 +6,157 @@
 
 ## Screenshots
 
-![GUI showing Sintel from the Blender Foundation](https://i.imgur.com/SLse3s9.jpg)
+![GUI showing Sintel from the Blender Foundation](https://i.imgur.com/UBNYbER.jpg)
 
-## Documentation
+![GUI showing Big Buck Bunny from the Blender Foundation](https://i.imgur.com/Tgmk7SW.png)
 
-[Let's make a GTK Video Player with Haskell](https://lettier.github.io/posts/2017-08-30-haskell-gtk-video-player.html)
+![GUI showing the About window as seen on the Mac](https://i.imgur.com/hiix2Wm.png)
 
-## Install
+## Features
 
-### GitHub
+* Local or remote video file playback
+    * `file://`
+    * `http://`
+    * `https://`
+* Window size selection
+* Fullscreen mode
+* Seek
+* Play and pause
+* Volume
+* Command line play
+    * `movie-monad ./path/to/video/file.mp4`
+    * `movie-monad http://www.domain.tld/path/to/video/file.mp4`
 
+## Keyboard Shortcuts
+
+* Mute/Unmute
+    * `m`
+    * `AudioMute`
+* Fullscreen/Windowed
+    * `f`
+* Show Controls
+    * `c`
+* Volume Up
+    * `ArrowUp`
+    * `AudioRaiseVolume`
+* Volume Down
+    * `ArrowDown`
+    * `AudioLowerVolume`
+* Play/Pause
+    * `Space`
+    * `AudioPlay`
+
+## Tested On
+
+### Linux
+
+* [Ubuntu 17.10](https://www.ubuntu.com/desktop)
+* [Ubuntu 16.04](https://www.ubuntu.com/desktop)
+* [Ubuntu 14.04](https://www.ubuntu.com/desktop)
+* [Linux Mint 18.2](https://linuxmint.com/)
+* [Manjaro 17.04](https://manjaro.org/)
+* [Deepin 15.4.1](https://www.deepin.org/en/dde/)
+* [Antergos 17.10](https://antergos.com/)
+
+### Mac
+
+* [macOS Sierra 10.12.6](https://en.wikipedia.org/wiki/MacOS_Sierra)
+
+## Dependencies
+
+### Run
+
+* [GTK+ >= 3.10](https://www.gtk.org/download/index.php)
+* [GStreamer >= 1.0](https://gstreamer.freedesktop.org/download/)
+    * [GStreamer Good Plug-ins](https://gstreamer.freedesktop.org/modules/gst-plugins-good.html)
+    * [GStreamer Bad Plug-ins](https://gstreamer.freedesktop.org/modules/gst-plugins-bad.html)
+
+### Build
+
+* [Haskell](https://www.haskell.org/platform/prior.html)
+    * GHC == 8.0.2
+
+## Install & Run
+
+### Linux
+
+#### AppImage
+
 ```bash
-# Install Git
-# Install XQuartz (https://www.xquartz.org/) if using Mac OSX or macOS
-# Install GTK+ 3.* (https://www.gtk.org/download/index.php)
-# Install Haskell
-# Install Haksell Stack
-# Install ExifTool
+# Install GTK+ >= 3.10 (https://www.gtk.org/download/index.php)
+# Install GStreamer >= 1.0 (https://gstreamer.freedesktop.org/download/)
+# Install GStreamer Good Plug-ins (https://gstreamer.freedesktop.org/modules/gst-plugins-good.html)
+# Install GStreamer Bad Plug-ins >= 1.8 (https://gstreamer.freedesktop.org/modules/gst-plugins-bad.html)
+# Visit https://github.com/lettier/movie-monad/releases
+# * equals the current version
+# Download the latest AppImage movie-monad-*-x86_64.AppImage
+wget https://github.com/lettier/movie-monad/releases/download/*/movie-monad-*-x86_64.AppImage
+chmod a+x movie-monad-*-x86_64.AppImage
+./movie-monad-*-x86_64.AppImage
+# If you would like to install the AppImage, you can run the following
+cd
+wget "https://raw.githubusercontent.com/lettier/movie-monad/master/packaging/linux/movie-monad-install.sh" -O "movie-monad-install.sh"
+chmod +x "movie-monad-install.sh"
+./movie-monad-install.sh
+```
+
+### Mac
+
+```bash
+# Install Homebrew (https://brew.sh/#install)
+cd ~/Downloads
+brew update && brew upgrade
+brew install git
 git clone https://github.com/lettier/movie-monad.git
-cd movie-monad/
+cd movie-monad
+brew cask install haskell-platform
+brew install pkg-config libffi libav libsvg librsvg libogg libvorbis openh264 theora \
+  gobject-introspection cairo gdk-pixbuf gsettings-desktop-schemas gtk+3 gtk-mac-integration \
+  gstreamer gst-libav gst-plugins-base gst-plugins-good
+brew install --with-gtk+3 gst-plugins-bad
 stack setup
+stack install hsc2hs
 stack install
-stack exec -- movie-monad
-# Or just `movie-monad` if `stack path | grep local-bin-path` is in your `echo $PATH`
+export PATH=$PATH:"$HOME/.local/bin/"
+movie-monad
 ```
+
+### [Hackage](https://hackage.haskell.org/package/movie-monad)
+
+```bash
+# Install GObject Introspection (https://wiki.gnome.org/action/show/Projects/GObjectIntrospection)
+# Install GTK+ >= 3.10 (https://www.gtk.org/download/index.php)
+# Install GStreamer >= 1.0 (https://gstreamer.freedesktop.org/download/)
+# Install GStreamer Good Plug-ins (https://gstreamer.freedesktop.org/modules/gst-plugins-good.html)
+# Install GStreamer Bad Plug-ins >= 1.8 (https://gstreamer.freedesktop.org/modules/gst-plugins-bad.html)
+# Install Cabal, GHC == 8.0.2 (https://www.haskell.org/platform/prior.html)
+# Install Cabal Install (https://www.haskell.org/platform/prior.html)
+cabal install movie-monad
+movie-monad
+```
+
+### [GitHub](https://github.com/lettier/movie-monad)
+
+```bash
+# Install GObject Introspection (https://wiki.gnome.org/action/show/Projects/GObjectIntrospection)
+# Install GTK+ >= 3.10 (https://www.gtk.org/download/index.php)
+# Install GStreamer >= 1.0 (https://gstreamer.freedesktop.org/download/)
+# Install GStreamer Good Plug-ins (https://gstreamer.freedesktop.org/modules/gst-plugins-good.html)
+# Install GStreamer Bad Plug-ins >= 1.8 (https://gstreamer.freedesktop.org/modules/gst-plugins-bad.html)
+# Install Git (https://git-scm.com/downloads)
+# Install GNU Make (https://www.gnu.org/software/make/)
+# Install Haskell, GHC == 8.0.2 (https://www.haskell.org/platform/prior.html)
+# Install Haksell Stack (https://www.haskell.org/platform/)
+git clone https://github.com/lettier/movie-monad.git
+cd movie-monad/
+make
+make install
+make run
+```
+
+## Developer Documentation
+
+[Let's make a GTK Video Player with Haskell](https://lettier.github.io/posts/2017-08-30-haskell-gtk-video-player.html)
 
 ## License
 
diff --git a/movie-monad.cabal b/movie-monad.cabal
--- a/movie-monad.cabal
+++ b/movie-monad.cabal
@@ -1,5 +1,5 @@
 name:                 movie-monad
-version:              0.0.1.0
+version:              0.0.2.0
 synopsis:             Plays videos using GStreamer and GTK+.
 description:          Desktop video player that uses GStreamer and GTK+.
 homepage:             https://github.com/lettier/movie-monad
@@ -8,38 +8,84 @@
 author:               Lettier
 maintainer:           Lettier
 copyright:            2017 David Lettier
-category:               Multimedia
+category:               Application
+                      , Multimedia
                       , Multimedia Player
                       , Video
 build-type:           Simple
-cabal-version:        >=1.10
+cabal-version:        >= 1.10
 extra-source-files:     README.md
                       , LICENSE
+                      , CHANGELOG.md
                       , ./src/dev/Paths_movie_monad.hs
                       , ./src/data/gui.glade
-data-files:           data/gui.glade
+                      , ./src/data/movie-monad-logo.svg
+                      , ./src/data/movie-monad-icon.png
+                      , ./src/Records.hs
+                      , ./src/Constants.hs
+                      , ./src/Window.hs
+                      , ./src/CommandLine.hs
+                      , ./src/Keyboard.hs
+                      , ./src/Mouse.hs
+                      , ./src/FileChooser.hs
+                      , ./src/Seek.hs
+                      , ./src/PlayPause.hs
+                      , ./src/VideoSizeSelector.hs
+                      , ./src/Fullscreen.hs
+                      , ./src/ErrorMessage.hs
+                      , ./src/About.hs
+                      , ./src/VideoInfo.hs
+                      , ./src/Playbin.hs
+                      , ./src/Uri.hs
+                      , ./src/Utils.hs
+                      , ./src/ScreensaverAndPowerManagement.hs
+data-files:             data/gui.glade
+                      , data/movie-monad-logo.svg
+                      , data/movie-monad-icon.png
 data-dir:             ./src/
 
 source-repository     head
   type:               git
-  location:           https://github.com/lettier/gifcurry.git
+  location:           https://github.com/lettier/movie-monad.git
 
 executable            movie-monad
   main-is:              Main.hs
   default-language:     Haskell2010
   build-depends:        base >= 4.7 && < 5
+                      , filepath == 1.4.*
+                      , system-fileio == 0.3.*
+                      , system-filepath == 0.4.*
                       , text == 1.2.*
+                      , time == 1.6.*
                       , process == 1.4.*
                       , MissingH == 1.4.*
-                      , haskell-gi-base == 0.20.*
-                      , gi-xlib == 2.0.*
+                      , network-uri == 2.6.*
+                      , haskell-gi-base == 0.20.4
                       , gi-gobject == 2.0.*
                       , gi-glib == 2.0.*
-                      , gi-gdkx11 == 3.0.*
-                      , gi-gstvideo == 1.0.*
                       , gi-gdk == 3.0.*
+                      , gi-gdkpixbuf == 2.0.*
                       , gi-gst == 1.0.*
-                      , gi-gtk == 3.0.*
-  ghc-options:        -threaded -with-rtsopts=-N -Wall
-  other-modules:      Paths_movie_monad
+                      , gi-gstvideo == 1.0.*
+                      , gi-gtk == 3.0.18
+  ghc-options:        -threaded -with-rtsopts=-N -Wall -freverse-errors
+  other-modules:        Paths_movie_monad
+                      , Records
+                      , Constants
+                      , Window
+                      , CommandLine
+                      , Keyboard
+                      , Mouse
+                      , FileChooser
+                      , Seek
+                      , PlayPause
+                      , VideoSizeSelector
+                      , Fullscreen
+                      , ErrorMessage
+                      , About
+                      , VideoInfo
+                      , Uri
+                      , Playbin
+                      , Utils
+                      , ScreensaverAndPowerManagement
   hs-source-dirs:     ./src/
diff --git a/src/About.hs b/src/About.hs
new file mode 100644
--- /dev/null
+++ b/src/About.hs
@@ -0,0 +1,39 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+module About where
+
+import Control.Monad
+import qualified GI.Gdk
+import qualified GI.Gtk
+
+import qualified Records as R
+
+addAboutHandler :: R.Application -> IO ()
+addAboutHandler
+  R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.aboutButton = aboutButton
+            , R.aboutDialog = aboutDialog
+          }
+    }
+  =
+  void (
+      GI.Gtk.onWidgetButtonReleaseEvent aboutButton (aboutButtonReleaseHandler aboutDialog)
+    )
+
+aboutButtonReleaseHandler ::
+  GI.Gtk.AboutDialog ->
+  GI.Gdk.EventButton ->
+  IO Bool
+aboutButtonReleaseHandler aboutDialog _ =
+  void (
+      GI.Gtk.onDialogResponse aboutDialog (\ _ -> GI.Gtk.widgetHide aboutDialog)
+    ) >>
+  void (
+      GI.Gtk.dialogRun aboutDialog
+    ) >>
+  return True
diff --git a/src/CommandLine.hs b/src/CommandLine.hs
new file mode 100644
--- /dev/null
+++ b/src/CommandLine.hs
@@ -0,0 +1,32 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+module CommandLine where
+
+import System.Environment
+import Data.Text
+import GI.Gtk
+
+import qualified Records as R
+import FileChooser
+import Uri
+import Utils
+
+playVideoFromCommandLineIfNeeded :: R.Application -> IO ()
+playVideoFromCommandLineIfNeeded
+  application@R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.fileChooserEntry = fileChooserEntry
+          }
+    }
+  = do
+  args <- getArgs
+  case args of
+    [] -> return ()
+    (filePath':_) -> do
+      filePath <- toAbsoluteUri filePath'
+      GI.Gtk.entrySetText fileChooserEntry (Data.Text.pack filePath)
+      fileChooserDialogResponseHandler application (enumToInt32 GI.Gtk.ResponseTypeOk)
diff --git a/src/Constants.hs b/src/Constants.hs
new file mode 100644
--- /dev/null
+++ b/src/Constants.hs
@@ -0,0 +1,17 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Constants where
+
+import Data.Text
+
+hideOnScreenControlsInterval :: Integral a => a
+hideOnScreenControlsInterval = 5
+
+invalidVideoWidgetName :: Data.Text.Text
+invalidVideoWidgetName = "invalid-video-widget"
diff --git a/src/ErrorMessage.hs b/src/ErrorMessage.hs
new file mode 100644
--- /dev/null
+++ b/src/ErrorMessage.hs
@@ -0,0 +1,42 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module ErrorMessage where
+
+import Control.Monad
+import Data.Text
+import Data.Int
+import qualified GI.Gtk
+
+import qualified Records as R
+
+addErrorMessageDialogHandler :: R.Application -> IO ()
+addErrorMessageDialogHandler
+  R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.errorMessageDialog = errorMessageDialog
+          }
+    }
+  =
+  void (GI.Gtk.onDialogResponse errorMessageDialog (errorMessageDialogResponseHandler errorMessageDialog))
+
+errorMessageDialogResponseHandler ::
+  GI.Gtk.MessageDialog ->
+  Int32 ->
+  IO ()
+errorMessageDialogResponseHandler errorMessageDialog _ =
+  GI.Gtk.widgetHide errorMessageDialog >>
+  GI.Gtk.setMessageDialogText errorMessageDialog "There was an error."
+
+runErrorMessageDialog ::
+  GI.Gtk.MessageDialog ->
+  Text ->
+  IO ()
+runErrorMessageDialog errorMessageDialog text =
+  GI.Gtk.setMessageDialogText errorMessageDialog text >>
+  void (GI.Gtk.dialogRun errorMessageDialog)
diff --git a/src/FileChooser.hs b/src/FileChooser.hs
new file mode 100644
--- /dev/null
+++ b/src/FileChooser.hs
@@ -0,0 +1,190 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module FileChooser where
+
+import Control.Monad
+import Data.Int
+import Data.Text
+import Data.IORef
+import qualified Network.URI
+import qualified GI.Gdk
+import qualified GI.Gtk
+import qualified GI.Gst
+
+import qualified Records as R
+import Constants
+import Window
+import PlayPause
+import ErrorMessage
+import VideoInfo
+import Playbin
+import Uri
+import Utils
+
+addFileChooserHandlers :: R.Application -> IO ()
+addFileChooserHandlers
+  application@R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.fileChooserButton = fileChooserButton
+            , R.fileChooserDialog = fileChooserDialog
+            , R.fileChooserWidget = fileChooserWidget
+            , R.fileChooserEntry = fileChooserEntry
+          }
+    }
+  =
+  void (GI.Gtk.onWidgetButtonReleaseEvent fileChooserButton (fileChooserButtonClickHandler application)) >>
+  void (GI.Gtk.onDialogResponse fileChooserDialog (fileChooserDialogResponseHandler application)) >>
+  void (GI.Gtk.onFileChooserSelectionChanged fileChooserWidget (fileChooserSelectionChangedHandler application)) >>
+  void (GI.Gtk.onEntryIconRelease fileChooserEntry (\ _ _ -> GI.Gtk.entrySetText fileChooserEntry ""))
+
+fileChooserDialogResponseHandler ::
+  R.Application ->
+  Int32 ->
+  IO ()
+fileChooserDialogResponseHandler
+  R.Application {
+        R.guiObjects = guiObjects@R.GuiObjects {
+              R.window = window
+            , R.fileChooserButton = fileChooserButton
+            , R.videoWidget = videoWidget
+            , R.seekScale = seekScale
+            , R.playPauseButton = playPauseButton
+            , R.videoWidthSelectionComboBox = videoWidthSelectionComboBox
+            , R.fullscreenButton = fullscreenButton
+            , R.fileChooserEntry = fileChooserEntry
+            , R.fileChooserButtonLabel = fileChooserButtonLabel
+            , R.volumeButton = volumeButton
+            , R.errorMessageDialog = errorMessageDialog
+            , R.fileChooserDialog = fileChooserDialog
+            , R.playImage = playImage
+            , R.pauseImage = pauseImage
+          }
+      , R.ioRefs = R.IORefs {
+              R.isWindowFullScreenRef = isWindowFullScreenRef
+            , R.videoInfoRef = videoInfoRef
+            , R.previousFileNamePathRef = previousFileNamePathRef
+          }
+      , R.playbin = playbin
+    }
+  responseId
+  = do
+  GI.Gtk.widgetHide fileChooserDialog
+  handleResponseType GI.Gtk.ResponseTypeOk
+  where
+    handleResponseType :: (Enum a, Ord a) => a -> IO ()
+    handleResponseType enum
+      | enumToInt32 enum == responseId = do
+        _ <- GI.Gst.elementSetState playbin GI.Gst.StateNull
+        filePathName <- GI.Gtk.entryGetText fileChooserEntry
+        let filePathNameStr = Data.Text.unpack filePathName
+        (_, fileNameEmpty) <- setFileChooserButtonLabel fileChooserButtonLabel filePathName
+        isWindowFullScreen <- readIORef isWindowFullScreenRef
+        videoWidthSelection <- getSelectedVideoWidth videoWidthSelectionComboBox
+        setPlaybinUriAndVolume playbin filePathNameStr volumeButton
+        handleFileName
+          fileNameEmpty
+          filePathNameStr
+          isWindowFullScreen
+          videoWidthSelection
+      | otherwise = do
+        filePathName <- readIORef previousFileNamePathRef
+        _ <- setFileChooserButtonLabel fileChooserButtonLabel filePathName
+        GI.Gtk.entrySetText fileChooserEntry filePathName
+    handleFileName ::
+      Bool ->
+      Prelude.String ->
+      Bool ->
+      Int ->
+      IO ()
+    handleFileName True _ _ _ = atomicWriteIORef videoInfoRef R.defaultVideoInfo >> resetWindow guiObjects
+    handleFileName
+      _
+      filePathNameStr
+      isWindowFullScreen
+      videoWidthSelection
+      = do
+      retrievedVideoInfo <- getVideoInfo videoInfoRef filePathNameStr
+      maybeWindowSize <- calculateWindowSize videoWidthSelection retrievedVideoInfo
+      GI.Gtk.widgetSetSensitive seekScale True
+      if R.isSeekable retrievedVideoInfo
+        then GI.Gtk.widgetShow seekScale
+        else GI.Gtk.widgetHide seekScale
+      case maybeWindowSize of
+        Nothing -> do
+          resetWindow guiObjects
+          runErrorMessageDialog
+            errorMessageDialog
+            (Data.Text.pack $ Prelude.concat ["\"", filePathNameStr, "\" is not a video."])
+        Just (width, height) -> do
+          videoWidgetName <- GI.Gtk.widgetGetName videoWidget
+          if videoWidgetName == invalidVideoWidgetName
+            then do
+              resetWindow guiObjects
+              runErrorMessageDialog
+                errorMessageDialog
+                "Cannot play the video. Please install the bad plugins, version 1.8 or higher, for GStreamer version 1."
+            else do
+              GI.Gtk.widgetShow videoWidget
+              GI.Gtk.widgetShow playPauseButton
+              GI.Gtk.widgetShow fullscreenButton
+              setPlayPauseButton playPauseButton playImage pauseImage True
+              unless isWindowFullScreen $
+                setWindowSize width height fileChooserButton videoWidget window
+              void $ GI.Gst.elementSetState playbin GI.Gst.StatePlaying
+
+fileChooserButtonClickHandler ::
+  R.Application ->
+  GI.Gdk.EventButton ->
+  IO Bool
+fileChooserButtonClickHandler
+  R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.fileChooserEntry = fileChooserEntry
+            , R.fileChooserDialog = fileChooserDialog
+          }
+      , R.ioRefs = R.IORefs {
+              R.previousFileNamePathRef = previousFileNamePathRef
+          }
+    }
+  _
+  = do
+  text <- GI.Gtk.entryGetText fileChooserEntry
+  atomicWriteIORef previousFileNamePathRef text
+  _ <- GI.Gtk.dialogRun fileChooserDialog
+  return True
+
+fileChooserSelectionChangedHandler ::
+  R.Application ->
+  IO ()
+fileChooserSelectionChangedHandler
+  R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.fileChooserWidget = fileChooserWidget
+            , R.fileChooserEntry = fileChooserEntry
+          }
+      , R.ioRefs = R.IORefs {
+              R.videoInfoRef = videoInfoRef
+          }
+    }
+  = do
+  maybeUri <- GI.Gtk.fileChooserGetUri fileChooserWidget
+  case maybeUri of
+    Nothing -> return ()
+    Just uri' -> do
+      let uri = Network.URI.unEscapeString $ Data.Text.unpack uri'
+      local <- isLocalFile uri
+      video <- R.isVideo <$> getVideoInfo videoInfoRef uri
+      GI.Gtk.entrySetText fileChooserEntry (if local && video then Data.Text.pack uri else "")
+
+setFileChooserButtonLabel :: GI.Gtk.Label -> Data.Text.Text -> IO (Data.Text.Text, Bool)
+setFileChooserButtonLabel fileChooserButtonLabel filePathName = do
+  let fileName = fileNameFromFilePathName filePathName
+  let fileNameEmpty = isTextEmpty fileName
+  GI.Gtk.labelSetText fileChooserButtonLabel (if fileNameEmpty then "Open" else fileName)
+  return (fileName, fileNameEmpty)
diff --git a/src/Fullscreen.hs b/src/Fullscreen.hs
new file mode 100644
--- /dev/null
+++ b/src/Fullscreen.hs
@@ -0,0 +1,53 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+module Fullscreen where
+
+import Control.Monad
+import Data.IORef
+import qualified GI.Gdk
+import qualified GI.Gtk
+
+import qualified Records as R
+
+addFullscreenButtonReleaseHandler :: R.Application -> IO ()
+addFullscreenButtonReleaseHandler
+  application@R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.fullscreenButton = fullscreenButton
+          }
+    }
+  =
+  void $ GI.Gtk.onWidgetButtonReleaseEvent fullscreenButton (fullscreenButtonReleaseHandler application)
+
+fullscreenButtonReleaseHandler ::
+  R.Application ->
+  GI.Gdk.EventButton ->
+  IO Bool
+fullscreenButtonReleaseHandler
+  R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.window = window
+            , R.fileChooserButton = fileChooserButton
+            , R.videoWidthSelectionComboBox = videoWidthSelectionComboBox
+          }
+      , R.ioRefs = R.IORefs {
+            R.isWindowFullScreenRef = isWindowFullScreenRef
+        }
+    }
+  _
+  = do
+  isWindowFullScreen <- readIORef isWindowFullScreenRef
+  if isWindowFullScreen
+    then do
+      GI.Gtk.widgetShow videoWidthSelectionComboBox
+      GI.Gtk.widgetShow fileChooserButton
+      void $ GI.Gtk.windowUnfullscreen window
+    else do
+      GI.Gtk.widgetHide videoWidthSelectionComboBox
+      GI.Gtk.widgetHide fileChooserButton
+      void $ GI.Gtk.windowFullscreen window
+  return True
diff --git a/src/Keyboard.hs b/src/Keyboard.hs
new file mode 100644
--- /dev/null
+++ b/src/Keyboard.hs
@@ -0,0 +1,74 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+module Keyboard where
+
+import Control.Monad
+import Data.IORef
+import qualified GI.Gdk
+import qualified GI.Gtk
+
+import qualified Records as R
+import Mouse
+import PlayPause
+import Fullscreen
+
+addKeyboardEventHandler :: R.Application -> IO ()
+addKeyboardEventHandler
+  application@R.Application {
+    R.guiObjects = R.GuiObjects {
+        R.window = window
+      }
+    }
+  =
+  void $ GI.Gtk.onWidgetKeyPressEvent window $ keyboardEventHandler application
+
+keyboardEventHandler ::
+  R.Application ->
+  GI.Gdk.EventKey ->
+  IO Bool
+keyboardEventHandler
+  application@R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.volumeButton = volumeButton
+          }
+      , R.ioRefs = R.IORefs {
+            R.videoInfoRef = videoInfoRef
+        }
+    }
+  eventKey
+  = do
+  videoInfoGathered <- readIORef videoInfoRef
+  let isVideo = R.isVideo videoInfoGathered
+  let volumeDelta = 0.05
+  oldVolume <- GI.Gtk.scaleButtonGetValue volumeButton
+  keyValue <- GI.Gdk.getEventKeyKeyval eventKey
+  eventButton <- GI.Gdk.newZeroEventButton
+  -- Mute Toggle
+  when (keyValue == GI.Gdk.KEY_m || keyValue == GI.Gdk.KEY_AudioMute) $ do
+    let newVolume = if oldVolume <= 0.0 then 0.5 else 0.0
+    GI.Gtk.scaleButtonSetValue volumeButton newVolume
+  -- Play/Pause Toggle
+  when ((keyValue == GI.Gdk.KEY_space || keyValue == GI.Gdk.KEY_AudioPlay) && isVideo) $
+    void $ playPauseButtonClickHandler application eventButton
+  -- Volume Up
+  when (keyValue == GI.Gdk.KEY_Up || keyValue == GI.Gdk.KEY_AudioRaiseVolume) $ do
+    let newVolume = if oldVolume >= 1.0 then 1.0 else oldVolume + volumeDelta
+    GI.Gtk.scaleButtonSetValue volumeButton newVolume
+  -- Volume Down
+  when (keyValue == GI.Gdk.KEY_Down || keyValue == GI.Gdk.KEY_AudioLowerVolume) $ do
+    let newVolume = if oldVolume <= 0.0 then 0.0 else oldVolume - volumeDelta
+    GI.Gtk.scaleButtonSetValue volumeButton newVolume
+  -- Show Controls
+  when (keyValue == GI.Gdk.KEY_c) $ do
+    eventMotion <- GI.Gdk.newZeroEventMotion
+    void $ windowMouseMoveHandler application eventMotion
+  -- Fullscreen Toggle
+  when (keyValue == GI.Gdk.KEY_f && isVideo) $ do
+    eventMotion <- GI.Gdk.newZeroEventMotion
+    void $ windowMouseMoveHandler application eventMotion
+    void $ fullscreenButtonReleaseHandler application eventButton
+  return True
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -10,26 +10,35 @@
 module Main where
 
 import Prelude
-import Foreign.C.Types
-import System.Process
-import System.Exit
-import Control.Monad
-import Control.Exception
-import Text.Read
+import System.Info
 import Data.IORef
 import Data.Maybe
-import Data.Int
 import Data.Text
 import Data.GI.Base
-import Data.GI.Base.Signals
 import Data.GI.Base.Properties
-import GI.GLib
 import GI.GObject
 import qualified GI.Gtk
 import GI.Gst
 import GI.GstVideo
-import GI.Gdk
-import GI.GdkX11
+import GI.GdkPixbuf
+
+import qualified Records as R
+import Constants
+import Window
+import CommandLine
+import Mouse
+import Keyboard
+import FileChooser
+import Seek
+import PlayPause
+import Fullscreen
+import ErrorMessage
+import About
+import VideoSizeSelector
+import Playbin
+import ScreensaverAndPowerManagement (disable, enable)
+import Utils
+
 import Paths_movie_monad
 
 -- Declare Element a type instance of IsVideoOverlay via a newtype wrapper
@@ -47,59 +56,119 @@
   builder <- GI.Gtk.builderNewFromFile (pack gladeFile)
 
   window <- builderGetObject GI.Gtk.Window builder "window"
-  fileChooserButton <- builderGetObject GI.Gtk.FileChooserButton builder "file-chooser-button"
-  drawingArea <- builderGetObject GI.Gtk.Widget builder "drawing-area"
+  fileChooserButton <- builderGetObject GI.Gtk.Button builder "file-chooser-button"
+  fileChooserButtonLabel <- builderGetObject GI.Gtk.Label builder "file-chooser-button-label"
+  fileChooserDialog <- builderGetObject GI.Gtk.Dialog builder "file-chooser-dialog"
+  fileChooserEntry <- builderGetObject GI.Gtk.Entry builder "file-chooser-entry"
+  fileChooserWidget <- builderGetObject GI.Gtk.FileChooserWidget builder "file-chooser-widget"
+  fileChooserCancelButton <- builderGetObject GI.Gtk.Button builder "file-chooser-cancel-button"
+  fileChooserOpenButton <- builderGetObject GI.Gtk.Button builder "file-chooser-open-button"
+  videoWidgetBox <- builderGetObject GI.Gtk.Box builder "video-widget-box"
+  bottomControlsGtkBox <- builderGetObject GI.Gtk.Box builder "bottom-controls-gtk-box"
   seekScale <- builderGetObject GI.Gtk.Scale builder "seek-scale"
-  onOffSwitch <- builderGetObject GI.Gtk.Switch builder "on-off-switch"
+  playPauseButton <- builderGetObject GI.Gtk.Button builder "play-pause-button"
+  playImage <- builderGetObject GI.Gtk.Image builder "play-image"
+  pauseImage <- builderGetObject GI.Gtk.Image builder "pause-image"
   volumeButton <- builderGetObject GI.Gtk.VolumeButton builder "volume-button"
-  desiredVideoWidthComboBox <- builderGetObject GI.Gtk.ComboBoxText builder "desired-video-width-combo-box"
+  videoWidthSelectionComboBox <- builderGetObject GI.Gtk.ComboBoxText builder "video-width-selection-combo-box"
   fullscreenButton <- builderGetObject GI.Gtk.Button builder "fullscreen-button"
+  bufferingSpinner <- builderGetObject GI.Gtk.Spinner builder "buffering-spinner"
   errorMessageDialog <- builderGetObject GI.Gtk.MessageDialog builder "error-message-dialog"
   aboutButton <- builderGetObject GI.Gtk.Button builder "about-button"
   aboutDialog <- builderGetObject GI.Gtk.AboutDialog builder "about-dialog"
 
-  playbin <- fromJust <$> GI.Gst.elementFactoryMake "playbin" (Just "MultimediaPlayer")
-
-  isWindowFullScreenRef <- newIORef False
-
-  _ <- GI.Gtk.onWidgetRealize drawingArea $ onDrawingAreaRealize drawingArea playbin fullscreenButton
+  logoFile <- getDataFileName "data/movie-monad-logo.svg"
+  logo <- GI.GdkPixbuf.pixbufNewFromFile (pack logoFile)
+  GI.Gtk.aboutDialogSetLogo aboutDialog (Just logo)
 
-  _ <- GI.Gtk.onFileChooserButtonFileSet fileChooserButton $
-    onFileChooserButtonFileSet
-      playbin
-      fileChooserButton
-      volumeButton
-      isWindowFullScreenRef
-      desiredVideoWidthComboBox
-      onOffSwitch
-      fullscreenButton
-      drawingArea
-      window
-      errorMessageDialog
+  -- Glade does not allow us to use the response ID nicknames so we programmatically set them here.
+  GI.Gtk.dialogAddActionWidget fileChooserDialog fileChooserCancelButton (enumToInt32 GI.Gtk.ResponseTypeCancel)
+  GI.Gtk.dialogAddActionWidget fileChooserDialog fileChooserOpenButton   (enumToInt32 GI.Gtk.ResponseTypeOk)
 
-  _ <- GI.Gtk.onSwitchStateSet onOffSwitch (onSwitchStateSet playbin)
+  isWindowFullScreenRef <- newIORef False
+  mouseMovedLastRef <- newIORef 0
+  previousFileNamePathRef <- newIORef ""
+  videoInfoRef <- newIORef R.defaultVideoInfo
 
-  _ <- GI.Gtk.onScaleButtonValueChanged volumeButton (onScaleButtonValueChanged playbin)
+  let ioRefs = R.IORefs {
+        R.isWindowFullScreenRef = isWindowFullScreenRef
+      , R.mouseMovedLastRef = mouseMovedLastRef
+      , R.previousFileNamePathRef = previousFileNamePathRef
+      , R.videoInfoRef = videoInfoRef
+    }
 
-  seekScaleHandlerId <- GI.Gtk.onRangeValueChanged seekScale (onRangeValueChanged playbin seekScale)
+  playbin <- fromJust <$> GI.Gst.elementFactoryMake "playbin" (Just "MultimediaPlayerPlaybin")
+  maybeGtkSink <- GI.Gst.elementFactoryMake "gtksink" (Just "MultimediaPlayerGtkSink")
+  videoWidget <-
+    case maybeGtkSink of
+      Nothing -> do
+        putStrLn "Could not create a GtkSink. Please install the bad plugins, version 1.8 or higher, for GStreamer 1."
+        drawingArea <- GI.Gtk.drawingAreaNew
+        GI.Gtk.widgetSetName drawingArea invalidVideoWidgetName
+        GI.Gtk.unsafeCastTo GI.Gtk.Widget drawingArea
+      Just gtkSink ->
+        fromJust <$> Data.GI.Base.Properties.getObjectPropertyObject gtkSink "widget" GI.Gtk.Widget
 
-  _ <- GI.GLib.timeoutAddSeconds GI.GLib.PRIORITY_DEFAULT 1 (updateSeekScale playbin seekScale seekScaleHandlerId)
+  Data.GI.Base.Properties.setObjectPropertyObject playbin "video-sink" maybeGtkSink
+  Data.GI.Base.Properties.setObjectPropertyBool   playbin "force-aspect-ratio" True
+  GI.Gtk.boxPackStart videoWidgetBox videoWidget True True 0
+  GI.Gtk.widgetSetHexpand videoWidget True
+  GI.Gtk.widgetSetVexpand videoWidget True
+  GI.Gtk.widgetSetSensitive videoWidget True
 
-  _ <- GI.Gtk.onComboBoxChanged desiredVideoWidthComboBox $
-      onComboBoxChanged fileChooserButton desiredVideoWidthComboBox drawingArea window
+  playbinBus <- GI.Gst.elementGetBus playbin
 
-  _ <- GI.Gtk.onWidgetButtonReleaseEvent fullscreenButton
-      (onFullscreenButtonRelease isWindowFullScreenRef desiredVideoWidthComboBox fileChooserButton window)
+  let guiObjects = R.GuiObjects {
+        R.window = window
+      , R.fileChooserButton = fileChooserButton
+      , R.fileChooserButtonLabel = fileChooserButtonLabel
+      , R.fileChooserDialog = fileChooserDialog
+      , R.fileChooserEntry = fileChooserEntry
+      , R.fileChooserWidget = fileChooserWidget
+      , R.fileChooserCancelButton = fileChooserCancelButton
+      , R.fileChooserOpenButton = fileChooserOpenButton
+      , R.videoWidget = videoWidget
+      , R.bottomControlsGtkBox = bottomControlsGtkBox
+      , R.seekScale = seekScale
+      , R.playPauseButton = playPauseButton
+      , R.playImage = playImage
+      , R.pauseImage = pauseImage
+      , R.volumeButton = volumeButton
+      , R.videoWidthSelectionComboBox = videoWidthSelectionComboBox
+      , R.fullscreenButton = fullscreenButton
+      , R.bufferingSpinner = bufferingSpinner
+      , R.errorMessageDialog = errorMessageDialog
+      , R.aboutButton = aboutButton
+      , R.aboutDialog = aboutDialog
+    }
 
-  _ <- GI.Gtk.onWidgetWindowStateEvent window (onWidgetWindowStateEvent isWindowFullScreenRef)
+  let application = R.Application {
+        R.guiObjects = guiObjects
+      , R.ioRefs = ioRefs
+      , R.playbin = playbin
+      , R.playbinBus = playbinBus
+    }
 
-  _ <- GI.Gtk.onWidgetButtonReleaseEvent aboutButton (onAboutButtonRelease aboutDialog)
+  addWindowHandlers application [playVideoFromCommandLineIfNeeded]
+  addPlaybinHandler application
+  addFileChooserHandlers application
+  addPlayPauseButtonClickHandler application
+  addSeekHandlers application
+  addVideoSizeSelectorHandler application
+  addFullscreenButtonReleaseHandler application
+  addWindowMouseMoveHandlers application
+  addAboutHandler application
+  addKeyboardEventHandler application
+  addErrorMessageDialogHandler application
 
-  _ <- GI.Gtk.onWidgetDestroy window (onWindowDestroy playbin)
+  let operatingSystem = System.Info.os
+  screenAndPowerManagementActions <- ScreensaverAndPowerManagement.disable operatingSystem
 
   GI.Gtk.widgetShowAll window
   GI.Gtk.main
 
+  ScreensaverAndPowerManagement.enable operatingSystem screenAndPowerManagementActions
+
 builderGetObject ::
   (GI.GObject.GObject b, GI.Gtk.IsBuilder a) =>
   (Data.GI.Base.ManagedPtr b -> b) ->
@@ -109,284 +178,3 @@
 builderGetObject objectTypeClass builder objectId =
   fromJust <$> GI.Gtk.builderGetObject builder (pack objectId) >>=
     GI.Gtk.unsafeCastTo objectTypeClass
-
-onDrawingAreaRealize ::
-  GI.Gtk.Widget ->
-  GI.Gst.Element ->
-  GI.Gtk.Button ->
-  GI.Gtk.WidgetRealizeCallback
-onDrawingAreaRealize drawingArea playbin fullscreenButton = do
-  gdkWindow <- fromJust <$> GI.Gtk.widgetGetWindow drawingArea
-  x11Window <- GI.Gtk.unsafeCastTo GI.GdkX11.X11Window gdkWindow
-
-  xid <- GI.GdkX11.x11WindowGetXid x11Window
-  let xid' = fromIntegral xid :: CUIntPtr
-
-  GI.GstVideo.videoOverlaySetWindowHandle (GstElement playbin) xid'
-
-  GI.Gtk.widgetHide fullscreenButton
-
-onFileChooserButtonFileSet ::
-  GI.Gst.Element ->
-  GI.Gtk.FileChooserButton ->
-  GI.Gtk.VolumeButton ->
-  IORef Bool ->
-  GI.Gtk.ComboBoxText ->
-  GI.Gtk.Switch ->
-  GI.Gtk.Button ->
-  GI.Gtk.Widget ->
-  GI.Gtk.Window ->
-  GI.Gtk.MessageDialog ->
-  GI.Gtk.FileChooserButtonFileSetCallback
-onFileChooserButtonFileSet
-  playbin
-  fileChooserButton
-  volumeButton
-  isWindowFullScreenRef
-  desiredVideoWidthComboBox
-  onOffSwitch
-  fullscreenButton
-  drawingArea
-  window
-  errorMessageDialog
-  = do
-  _ <- GI.Gst.elementSetState playbin GI.Gst.StateNull
-
-  filename <- fromJust <$> GI.Gtk.fileChooserGetFilename fileChooserButton
-
-  setPlaybinUriAndVolume playbin filename volumeButton
-
-  isWindowFullScreen <- readIORef isWindowFullScreenRef
-
-  desiredVideoWidth <- getDesiredVideoWidth desiredVideoWidthComboBox
-  maybeWindowSize <- getWindowSize desiredVideoWidth filename
-
-  case maybeWindowSize of
-    Nothing -> do
-      _ <- GI.Gst.elementSetState playbin GI.Gst.StatePaused
-      GI.Gtk.windowUnfullscreen window
-      GI.Gtk.switchSetActive onOffSwitch False
-      GI.Gtk.widgetHide fullscreenButton
-      GI.Gtk.widgetShow desiredVideoWidthComboBox
-      resetWindowSize desiredVideoWidth fileChooserButton drawingArea window
-      _ <- GI.Gtk.onDialogResponse errorMessageDialog (\ _ -> GI.Gtk.widgetHide errorMessageDialog)
-      void $ GI.Gtk.dialogRun errorMessageDialog
-    Just (width, height) -> do
-      _ <- GI.Gst.elementSetState playbin GI.Gst.StatePlaying
-      GI.Gtk.switchSetActive onOffSwitch True
-      GI.Gtk.widgetShow fullscreenButton
-      unless isWindowFullScreen $ setWindowSize width height fileChooserButton drawingArea window
-
-onSwitchStateSet ::
-  GI.Gst.Element ->
-  Bool ->
-  IO Bool
-onSwitchStateSet playbin switchOn = do
-  if switchOn
-    then void $ GI.Gst.elementSetState playbin GI.Gst.StatePlaying
-    else void $ GI.Gst.elementSetState playbin GI.Gst.StatePaused
-  return switchOn
-
-onScaleButtonValueChanged ::
-  GI.Gst.Element ->
-  Double ->
-  IO ()
-onScaleButtonValueChanged playbin volume =
-    void $ Data.GI.Base.Properties.setObjectPropertyDouble playbin "volume" volume
-
-onRangeValueChanged ::
-  GI.Gst.Element ->
-  GI.Gtk.Scale ->
-  IO ()
-onRangeValueChanged playbin seekScale = do
-  (couldQueryDuration, duration) <- GI.Gst.elementQueryDuration playbin GI.Gst.FormatTime
-
-  when couldQueryDuration $ do
-    percentage' <- GI.Gtk.rangeGetValue seekScale
-    let percentage = percentage' / 100.0
-    let position = fromIntegral (round ((fromIntegral duration :: Double) * percentage) :: Int) :: Int64
-    void $ GI.Gst.elementSeekSimple playbin GI.Gst.FormatTime [ GI.Gst.SeekFlagsFlush ] position
-
-updateSeekScale ::
-  GI.Gst.Element ->
-  GI.Gtk.Scale ->
-  Data.GI.Base.Signals.SignalHandlerId ->
-  IO Bool
-updateSeekScale playbin seekScale seekScaleHandlerId = do
-  (couldQueryDuration, duration) <- GI.Gst.elementQueryDuration playbin GI.Gst.FormatTime
-  (couldQueryPosition, position) <- GI.Gst.elementQueryPosition playbin GI.Gst.FormatTime
-
-  let percentage =
-        if couldQueryDuration && couldQueryPosition && duration > 0
-          then 100.0 * (fromIntegral position / fromIntegral duration :: Double)
-          else 0.0
-
-  GI.GObject.signalHandlerBlock seekScale seekScaleHandlerId
-  GI.Gtk.rangeSetValue seekScale percentage
-  GI.GObject.signalHandlerUnblock seekScale seekScaleHandlerId
-
-  return True
-
-onComboBoxChanged ::
-  GI.Gtk.FileChooserButton ->
-  GI.Gtk.ComboBoxText ->
-  GI.Gtk.Widget ->
-  GI.Gtk.Window ->
-  IO ()
-onComboBoxChanged
-  fileChooserButton
-  desiredVideoWidthComboBox
-  drawingArea
-  window
-  = do
-  filename' <- GI.Gtk.fileChooserGetFilename fileChooserButton
-  let filename = fromMaybe "" filename'
-
-  desiredVideoWidth <- getDesiredVideoWidth desiredVideoWidthComboBox
-  maybeWindowSize <- getWindowSize desiredVideoWidth filename
-
-  case maybeWindowSize of
-    Nothing -> resetWindowSize desiredVideoWidth fileChooserButton drawingArea window
-    Just (width, height) -> setWindowSize width height fileChooserButton drawingArea window
-
-onFullscreenButtonRelease ::
-  IORef Bool ->
-  GI.Gtk.ComboBoxText ->
-  GI.Gtk.FileChooserButton ->
-  GI.Gtk.Window ->
-  GI.Gdk.EventButton ->
-  IO Bool
-onFullscreenButtonRelease
-  isWindowFullScreenRef
-  desiredVideoWidthComboBox
-  fileChooserButton
-  window
-  _
-  = do
-  isWindowFullScreen <- readIORef isWindowFullScreenRef
-  if isWindowFullScreen
-    then do
-      GI.Gtk.widgetShow desiredVideoWidthComboBox
-      GI.Gtk.widgetShow fileChooserButton
-      void $ GI.Gtk.windowUnfullscreen window
-    else do
-      GI.Gtk.widgetHide desiredVideoWidthComboBox
-      GI.Gtk.widgetHide fileChooserButton
-      void $ GI.Gtk.windowFullscreen window
-  return True
-
-onWidgetWindowStateEvent ::
-  IORef Bool ->
-  GI.Gdk.EventWindowState ->
-  IO Bool
-onWidgetWindowStateEvent isWindowFullScreenRef eventWindowState = do
-  windowStates <- GI.Gdk.getEventWindowStateNewWindowState eventWindowState
-  let isWindowFullScreen = Prelude.foldl (\ acc x -> acc || GI.Gdk.WindowStateFullscreen == x) False windowStates
-  writeIORef isWindowFullScreenRef isWindowFullScreen
-  return True
-
-onAboutButtonRelease ::
-  GI.Gtk.AboutDialog ->
-  GI.Gdk.EventButton ->
-  IO Bool
-onAboutButtonRelease aboutDialog _ = do
-  _ <- GI.Gtk.onDialogResponse aboutDialog (\ _ -> GI.Gtk.widgetHide aboutDialog)
-  _ <- GI.Gtk.dialogRun aboutDialog
-  return True
-
-onWindowDestroy ::
-  GI.Gst.Element ->
-  IO ()
-onWindowDestroy playbin = do
-  _ <- GI.Gst.elementSetState playbin GI.Gst.StateNull
-  _ <- GI.Gst.objectUnref playbin
-  GI.Gtk.mainQuit
-
-setPlaybinUriAndVolume ::
-  GI.Gst.Element ->
-  Prelude.String ->
-  GI.Gtk.VolumeButton ->
-  IO ()
-setPlaybinUriAndVolume playbin filename volumeButton = do
-  let uri = "file://" ++ filename
-  volume <- GI.Gtk.scaleButtonGetValue volumeButton
-  Data.GI.Base.Properties.setObjectPropertyDouble playbin "volume" volume
-  Data.GI.Base.Properties.setObjectPropertyString playbin "uri" (Just $ pack uri)
-
-getVideoInfo :: Prelude.String -> Prelude.String -> IO (Maybe Prelude.String)
-getVideoInfo flag filename = do
-  (code, out, _) <- catch (
-      readProcessWithExitCode
-        "exiftool"
-        [flag, "-s", "-S", filename]
-        ""
-    ) (\ (_ :: Control.Exception.IOException) -> return (ExitFailure 1, "", ""))
-  if code == System.Exit.ExitSuccess
-    then return (Just out)
-    else return Nothing
-
-isVideo :: Prelude.String -> IO Bool
-isVideo filename = do
-  maybeOut <- getVideoInfo "-MIMEType" filename
-  case maybeOut of
-    Nothing -> return False
-    Just out -> return ("video" `isInfixOf` pack out)
-
-getWindowSize :: Int -> Prelude.String -> IO (Maybe (Int32, Int32))
-getWindowSize desiredVideoWidth filename =
-  isVideo filename >>=
-  getWidthHeightString >>=
-  splitWidthHeightString >>=
-  widthHeightToDouble >>=
-  ratio >>=
-  windowSize
-  where
-    getWidthHeightString :: Bool -> IO (Maybe Prelude.String)
-    getWidthHeightString False = return Nothing
-    getWidthHeightString True = getVideoInfo "-ImageSize" filename
-    splitWidthHeightString :: Maybe Prelude.String -> IO (Maybe [Text])
-    splitWidthHeightString Nothing = return Nothing
-    splitWidthHeightString (Just string) = return (Just (Data.Text.splitOn "x" (pack string)))
-    widthHeightToDouble :: Maybe [Text] -> IO (Maybe Double, Maybe Double)
-    widthHeightToDouble (Just (x:y:_)) = return (readMaybe (unpack x) :: Maybe Double, readMaybe (unpack y) :: Maybe Double)
-    widthHeightToDouble _ = return (Nothing, Nothing)
-    ratio :: (Maybe Double, Maybe Double) -> IO (Maybe Double)
-    ratio (Just width, Just height) =
-      if width <= 0.0 then return Nothing else return (Just (height / width))
-    ratio _ = return Nothing
-    windowSize :: Maybe Double -> IO (Maybe (Int32, Int32))
-    windowSize Nothing = return Nothing
-    windowSize (Just ratio') =
-      return (Just (fromIntegral desiredVideoWidth :: Int32, round ((fromIntegral desiredVideoWidth :: Double) *  ratio') :: Int32))
-
-getDesiredVideoWidth :: GI.Gtk.ComboBoxText -> IO Int
-getDesiredVideoWidth = fmap (\ x -> read (Data.Text.unpack x) :: Int) . GI.Gtk.comboBoxTextGetActiveText
-
-setWindowSize ::
-  Int32 ->
-  Int32 ->
-  GI.Gtk.FileChooserButton ->
-  GI.Gtk.Widget ->
-  GI.Gtk.Window ->
-  IO ()
-setWindowSize width height fileChooserButton drawingArea window = do
-  GI.Gtk.setWidgetWidthRequest fileChooserButton width
-
-  GI.Gtk.setWidgetWidthRequest drawingArea width
-  GI.Gtk.setWidgetHeightRequest drawingArea height
-
-  GI.Gtk.setWidgetWidthRequest window width
-  GI.Gtk.setWidgetHeightRequest window height
-  GI.Gtk.windowResize window width (if height <= 0 then 1 else height)
-
-resetWindowSize ::
-  (Integral a) =>
-  a ->
-  GI.Gtk.FileChooserButton ->
-  GI.Gtk.Widget ->
-  GI.Gtk.Window ->
-  IO ()
-resetWindowSize width' fileChooserButton drawingArea window = do
-  let width = fromIntegral width' :: Int32
-  GI.Gtk.widgetQueueDraw drawingArea
-  setWindowSize width 0 fileChooserButton drawingArea window
diff --git a/src/Mouse.hs b/src/Mouse.hs
new file mode 100644
--- /dev/null
+++ b/src/Mouse.hs
@@ -0,0 +1,69 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+module Mouse where
+
+import Control.Monad
+import Data.Maybe
+import Data.Text
+import Data.IORef
+import Data.Time.Clock.POSIX
+import qualified GI.Gdk
+import qualified GI.Gtk
+
+import qualified Records as R
+
+addWindowMouseMoveHandlers :: R.Application -> IO ()
+addWindowMouseMoveHandlers
+  application@R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.videoWidget = videoWidget
+            , R.seekScale = seekScale
+          }
+    }
+  =
+  void (GI.Gtk.onWidgetMotionNotifyEvent videoWidget (windowMouseMoveHandler application)) >>
+  void (GI.Gtk.onWidgetMotionNotifyEvent seekScale (windowMouseMoveHandler application))
+
+windowMouseMoveHandler ::
+  R.Application ->
+  GI.Gdk.EventMotion ->
+  IO Bool
+windowMouseMoveHandler
+  R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.window = window
+            , R.fileChooserButton = fileChooserButton
+            , R.bottomControlsGtkBox = bottomControlsGtkBox
+          }
+      , R.ioRefs = R.IORefs {
+            R.isWindowFullScreenRef = isWindowFullScreenRef
+          , R.mouseMovedLastRef = mouseMovedLastRef
+        }
+    }
+  _
+  = do
+  isWindowFullScreen <- readIORef isWindowFullScreenRef
+  unless isWindowFullScreen $ GI.Gtk.widgetShow fileChooserButton
+  GI.Gtk.widgetShow bottomControlsGtkBox
+  setCursor window Nothing
+  timeNow <- getPOSIXTime
+  atomicWriteIORef mouseMovedLastRef (round timeNow)
+  return False
+
+setCursor :: GI.Gtk.Window -> Maybe Text -> IO ()
+setCursor window Nothing =
+  fromJust <$> GI.Gtk.widgetGetWindow window >>=
+  flip GI.Gdk.windowSetCursor (Nothing :: Maybe GI.Gdk.Cursor)
+setCursor window (Just cursorType) = do
+  gdkWindow <- fromJust <$> GI.Gtk.widgetGetWindow window
+  maybeCursor <- makeCursor gdkWindow cursorType
+  GI.Gdk.windowSetCursor gdkWindow maybeCursor
+
+makeCursor :: GI.Gdk.Window -> Text -> IO (Maybe GI.Gdk.Cursor)
+makeCursor window cursorType =
+  GI.Gdk.windowGetDisplay window >>=
+  flip GI.Gdk.cursorNewFromName cursorType
diff --git a/src/PlayPause.hs b/src/PlayPause.hs
new file mode 100644
--- /dev/null
+++ b/src/PlayPause.hs
@@ -0,0 +1,81 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module PlayPause where
+
+import Control.Monad
+import Data.Text
+import qualified GI.Gdk
+import qualified GI.Gtk
+import qualified GI.Gst
+
+import qualified Records as R
+
+addPlayPauseButtonClickHandler :: R.Application -> IO ()
+addPlayPauseButtonClickHandler
+  application@R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.playPauseButton = playPauseButton
+          }
+    }
+  =
+  void $ GI.Gtk.onWidgetButtonReleaseEvent playPauseButton (playPauseButtonClickHandler application)
+
+playPauseButtonClickHandler ::
+  R.Application ->
+  GI.Gdk.EventButton ->
+  IO Bool
+playPauseButtonClickHandler
+  R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.playPauseButton = playPauseButton
+            , R.playImage = playImage
+            , R.pauseImage = pauseImage
+          }
+      , R.playbin = playbin
+    }
+  _
+  = do
+  isPlaying <- isPlayPauseButtonPlaying playPauseButton
+  if isPlaying
+    then do
+      setPlayPauseButton playPauseButton playImage pauseImage False
+      void $ GI.Gst.elementSetState playbin GI.Gst.StatePaused
+    else do
+      setPlayPauseButton playPauseButton playImage pauseImage True
+      void $ GI.Gst.elementSetState playbin GI.Gst.StatePlaying
+  return False
+
+setPlayPauseButton ::
+  GI.Gtk.Button ->
+  GI.Gtk.Image ->
+  GI.Gtk.Image ->
+  Bool ->
+  IO ()
+setPlayPauseButton playPauseButton _ pauseImage True = do
+  GI.Gtk.buttonSetImage playPauseButton (Just pauseImage)
+  GI.Gtk.widgetSetTooltipText playPauseButton (Just "Click to pause")
+setPlayPauseButton playPauseButton playImage _ False = do
+  GI.Gtk.buttonSetImage playPauseButton (Just playImage)
+  GI.Gtk.widgetSetTooltipText playPauseButton (Just "Click to play")
+
+isPlayPauseButtonPlaying ::
+  GI.Gtk.Button ->
+  IO Bool
+isPlayPauseButtonPlaying playPauseButton =
+  GI.Gtk.buttonGetImage playPauseButton >>= getImage >>= getName >>= getMatch
+  where
+    getImage :: Maybe GI.Gtk.Widget -> IO (Maybe GI.Gtk.Image)
+    getImage Nothing       = return Nothing
+    getImage (Just widget) = GI.Gtk.castTo GI.Gtk.Image widget
+    getName :: Maybe GI.Gtk.Image -> IO (Maybe Text)
+    getName Nothing        = return Nothing
+    getName (Just image)   = GI.Gtk.getImageStock image
+    getMatch :: Maybe Text -> IO Bool
+    getMatch Nothing       = return False
+    getMatch (Just text)   = return ("gtk-media-pause" == text)
diff --git a/src/Playbin.hs b/src/Playbin.hs
new file mode 100644
--- /dev/null
+++ b/src/Playbin.hs
@@ -0,0 +1,122 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Playbin where
+
+import Control.Monad
+import Data.Text
+import Data.GI.Base.Properties
+import GI.GLib
+import qualified GI.Gtk
+import qualified GI.Gst
+
+import qualified Records as R
+import Window
+import PlayPause
+import ErrorMessage
+import Uri
+
+addPlaybinHandler :: R.Application -> IO ()
+addPlaybinHandler
+  R.Application {
+        R.guiObjects = guiObjects@R.GuiObjects {
+              R.volumeButton = volumeButton
+          }
+      , R.playbin = playbin
+      , R.playbinBus = playbinBus
+    }
+  =
+  void(
+      GI.Gst.busAddWatch playbinBus GI.GLib.PRIORITY_DEFAULT (
+          pipelineBusMessageHandler
+            guiObjects
+            playbin
+        )
+    ) >>
+  void (
+      GI.Gtk.onScaleButtonValueChanged volumeButton (volumeButtonValueChangedHandler playbin)
+    )
+
+pipelineBusMessageHandler ::
+  R.GuiObjects ->
+  GI.Gst.Element ->
+  GI.Gst.Bus ->
+  GI.Gst.Message ->
+  IO Bool
+pipelineBusMessageHandler
+  guiObjects@R.GuiObjects {
+        R.seekScale = seekScale
+      , R.fileChooserEntry = fileChooserEntry
+      , R.fileChooserButtonLabel = fileChooserButtonLabel
+      , R.volumeButton = volumeButton
+      , R.errorMessageDialog = errorMessageDialog
+      , R.bufferingSpinner = bufferingSpinner
+      , R.playPauseButton = playPauseButton
+    }
+  playbin
+  _
+  message
+  = do
+  messageTypes <- GI.Gst.getMessageType message
+  let messageType = case messageTypes of
+                      [] -> GI.Gst.MessageTypeUnknown
+                      (msg:_) -> msg
+  entryText <- GI.Gtk.entryGetText fileChooserEntry
+  labelText <- GI.Gtk.labelGetText fileChooserButtonLabel
+  when (
+      messageType == GI.Gst.MessageTypeError &&
+      (
+        (not . Data.Text.null) entryText ||
+        labelText /= "Open"
+      )
+    ) $ do
+      (gError, text) <- GI.Gst.messageParseError message
+      gErrorText <- GI.Gst.gerrorMessage gError
+      Prelude.mapM_ print [text, "\n", gErrorText]
+      GI.Gtk.entrySetText fileChooserEntry ""
+      GI.Gtk.labelSetText fileChooserButtonLabel "Open"
+      _ <- GI.Gst.elementSetState playbin GI.Gst.StateNull
+      setPlaybinUriAndVolume playbin "" volumeButton
+      resetWindow guiObjects
+      runErrorMessageDialog
+        errorMessageDialog
+        (Data.Text.concat ["There was a problem trying to play the video \"", entryText, "\"."])
+  when (messageType == GI.Gst.MessageTypeBuffering) $ do
+    percent <- GI.Gst.messageParseBuffering message
+    isPlaying <- isPlayPauseButtonPlaying playPauseButton
+    if percent >= 100
+      then do
+        GI.Gtk.widgetHide bufferingSpinner
+        GI.Gtk.setSpinnerActive bufferingSpinner False
+        GI.Gtk.widgetSetSensitive seekScale True
+        when isPlaying $ void $ GI.Gst.elementSetState playbin GI.Gst.StatePlaying
+      else do
+        GI.Gtk.widgetShow bufferingSpinner
+        GI.Gtk.setSpinnerActive bufferingSpinner True
+        GI.Gtk.widgetSetSensitive seekScale False
+        void $ GI.Gst.elementSetState playbin GI.Gst.StatePaused
+    return ()
+  return True
+
+volumeButtonValueChangedHandler ::
+  GI.Gst.Element ->
+  Double ->
+  IO ()
+volumeButtonValueChangedHandler playbin volume =
+    void $ Data.GI.Base.Properties.setObjectPropertyDouble playbin "volume" volume
+
+setPlaybinUriAndVolume ::
+  GI.Gst.Element ->
+  Prelude.String ->
+  GI.Gtk.VolumeButton ->
+  IO ()
+setPlaybinUriAndVolume playbin fileName volumeButton = do
+  uri <- addUriSchemeIfNone fileName
+  volume <- GI.Gtk.scaleButtonGetValue volumeButton
+  Data.GI.Base.Properties.setObjectPropertyDouble playbin "volume" volume
+  Data.GI.Base.Properties.setObjectPropertyString playbin "uri" (Just $ pack uri)
diff --git a/src/Records.hs b/src/Records.hs
new file mode 100644
--- /dev/null
+++ b/src/Records.hs
@@ -0,0 +1,76 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+module Records where
+
+import Data.IORef
+import Data.Text
+import qualified GI.Gtk
+import qualified GI.Gst
+
+data VideoInfo = VideoInfo {
+      uri         :: Prelude.String
+    , isLocalFile :: Bool
+    , isVideo     :: Bool
+    , isSeekable  :: Bool
+    , videoWidth  :: Int
+    , videoHeight :: Int
+  }
+
+defaultVideoInfo :: VideoInfo
+defaultVideoInfo  = VideoInfo {
+      uri         = ""
+    , isLocalFile = False
+    , isVideo     = False
+    , isSeekable  = False
+    , videoWidth  = 800
+    , videoHeight = 600
+  }
+
+data GuiObjects = GuiObjects {
+      window :: GI.Gtk.Window
+    , fileChooserButton :: GI.Gtk.Button
+    , fileChooserButtonLabel :: GI.Gtk.Label
+    , fileChooserDialog :: GI.Gtk.Dialog
+    , fileChooserEntry :: GI.Gtk.Entry
+    , fileChooserWidget :: GI.Gtk.FileChooserWidget
+    , fileChooserCancelButton :: GI.Gtk.Button
+    , fileChooserOpenButton :: GI.Gtk.Button
+    , videoWidget :: GI.Gtk.Widget
+    , bottomControlsGtkBox :: GI.Gtk.Box
+    , seekScale :: GI.Gtk.Scale
+    , playPauseButton :: GI.Gtk.Button
+    , playImage :: GI.Gtk.Image
+    , pauseImage :: GI.Gtk.Image
+    , volumeButton :: GI.Gtk.VolumeButton
+    , videoWidthSelectionComboBox :: GI.Gtk.ComboBoxText
+    , fullscreenButton :: GI.Gtk.Button
+    , bufferingSpinner :: GI.Gtk.Spinner
+    , errorMessageDialog :: GI.Gtk.MessageDialog
+    , aboutButton :: GI.Gtk.Button
+    , aboutDialog :: GI.Gtk.AboutDialog
+  }
+
+data IORefs = IORefs {
+      isWindowFullScreenRef :: IORef Bool
+    , mouseMovedLastRef :: IORef Integer
+    , previousFileNamePathRef :: IORef Data.Text.Text
+    , videoInfoRef :: IORef VideoInfo
+  }
+
+data ScreensaverAndPowerManagementActions = ScreensaverAndPowerManagementActions {
+      disabledPowerManagement :: Bool
+    , disabledXScreensaver :: Bool
+    , disabledCinnamonScreensaver :: Bool
+    , disabledGnomeScreensaver :: Bool
+  }
+
+data Application = Application {
+      guiObjects :: GuiObjects
+    , ioRefs :: IORefs
+    , playbin :: GI.Gst.Element
+    , playbinBus :: GI.Gst.Bus
+  }
diff --git a/src/ScreensaverAndPowerManagement.hs b/src/ScreensaverAndPowerManagement.hs
new file mode 100644
--- /dev/null
+++ b/src/ScreensaverAndPowerManagement.hs
@@ -0,0 +1,108 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module ScreensaverAndPowerManagement where
+
+import System.Process
+import Control.Monad
+import Data.Text
+
+import qualified Records as R (ScreensaverAndPowerManagementActions(..))
+import Utils (safeRunProcessGetOutput, linuxProcessIsRunning, spawnLinuxProcessAndDisown)
+
+disable :: String -> IO R.ScreensaverAndPowerManagementActions
+disable "linux" = do
+  disabledPowerManagement <- disablePowerManagement
+  disabledXScreensaver <- disableXScreensaver
+  disabledCinnamonScreensaver <- disableCinnamonScreensaver
+  disabledGnomeScreensaver <- disableGnomeScreensaver
+  return R.ScreensaverAndPowerManagementActions {
+        R.disabledPowerManagement = disabledPowerManagement
+      , R.disabledXScreensaver = disabledXScreensaver
+      , R.disabledCinnamonScreensaver = disabledCinnamonScreensaver
+      , R.disabledGnomeScreensaver = disabledGnomeScreensaver
+    }
+disable _ =
+  return R.ScreensaverAndPowerManagementActions {
+        R.disabledPowerManagement = False
+      , R.disabledXScreensaver = False
+      , R.disabledCinnamonScreensaver = False
+      , R.disabledGnomeScreensaver = False
+    }
+
+enable :: String -> R.ScreensaverAndPowerManagementActions -> IO ()
+enable
+  "linux"
+  R.ScreensaverAndPowerManagementActions {
+        R.disabledPowerManagement = disabledPowerManagement
+      , R.disabledXScreensaver = disabledXScreensaver
+      , R.disabledCinnamonScreensaver = disabledCinnamonScreensaver
+      , R.disabledGnomeScreensaver = disabledGnomeScreensaver
+    }
+  = do
+  when disabledPowerManagement enablePowerManagement
+  when disabledXScreensaver enableXScreensaver
+  when disabledCinnamonScreensaver enableCinnamonScreensaver
+  when disabledGnomeScreensaver enableGnomeScreensaver
+  return ()
+enable _ _ = return ()
+
+disablePowerManagement :: IO Bool
+disablePowerManagement = do
+  (_, out, _) <- safeRunProcessGetOutput "xset" ["-q"]
+  let isEnabled =
+        Data.Text.isInfixOf "dpms is enabled" $
+          Data.Text.toLower $
+            Data.Text.pack out
+  if isEnabled
+    then do
+      _ <- System.Process.spawnCommand "sleep 1; xset -dpms s off"
+      return True
+    else return False
+
+enablePowerManagement :: IO ()
+enablePowerManagement =
+  void $
+    System.Process.spawnCommand "sleep 1; xset +dpms s on"
+
+disableXScreensaver :: IO Bool
+disableXScreensaver =
+  disableScreensaver
+    "xscreensaver"
+    "xscreensaver-command --exit"
+
+enableXScreensaver :: IO ()
+enableXScreensaver = spawnLinuxProcessAndDisown "xscreensaver -no-splash"
+
+disableCinnamonScreensaver :: IO Bool
+disableCinnamonScreensaver =
+  disableScreensaver
+    "cinnamon-screensaver"
+    "cinnamon-screensaver-command --exit"
+
+enableCinnamonScreensaver :: IO ()
+enableCinnamonScreensaver = spawnLinuxProcessAndDisown "cinnamon-screensaver"
+
+disableGnomeScreensaver :: IO Bool
+disableGnomeScreensaver =
+  disableScreensaver
+    "gnome-screensaver"
+    "gnome-screensaver-command --exit"
+
+enableGnomeScreensaver :: IO ()
+enableGnomeScreensaver = spawnLinuxProcessAndDisown "gnome-screensaver"
+
+disableScreensaver :: String -> String -> IO Bool
+disableScreensaver processName disableCommand = do
+  isRunning <- linuxProcessIsRunning processName
+  if isRunning
+    then do
+      spawnLinuxProcessAndDisown disableCommand
+      return True
+    else return False
diff --git a/src/Seek.hs b/src/Seek.hs
new file mode 100644
--- /dev/null
+++ b/src/Seek.hs
@@ -0,0 +1,93 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+module Seek where
+
+import Control.Monad
+import Data.IORef
+import Data.Int
+import Data.Time.Clock.POSIX
+import Data.GI.Base.Signals
+import GI.GLib
+import GI.GObject
+import qualified GI.Gtk
+import qualified GI.Gst
+
+import qualified Records as R
+
+addSeekHandlers :: R.Application -> IO ()
+addSeekHandlers
+  R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.seekScale = seekScale
+          }
+      , R.ioRefs = R.IORefs {
+              R.videoInfoRef = videoInfoRef
+        }
+      , R.playbin = playbin
+    }
+  = do
+  seekScaleHandlerId <- GI.Gtk.onRangeValueChanged seekScale (
+      onRangeValueChanged
+        playbin
+        seekScale
+        videoInfoRef
+    )
+  void (
+      GI.GLib.timeoutAdd GI.GLib.PRIORITY_DEFAULT 41 (
+          updateSeekScale
+            playbin
+            seekScale
+            seekScaleHandlerId
+        )
+    )
+
+seekRequestLastDeltaThreshold :: R.VideoInfo -> POSIXTime
+seekRequestLastDeltaThreshold R.VideoInfo { R.isLocalFile = True }  = 0.0
+seekRequestLastDeltaThreshold R.VideoInfo { R.isLocalFile = False } = 0.0
+
+onRangeValueChanged ::
+  GI.Gst.Element ->
+  GI.Gtk.Scale ->
+  IORef R.VideoInfo ->
+  IO ()
+onRangeValueChanged
+  playbin
+  seekScale
+  videoInfoRef
+  = do
+  (couldQueryDuration, duration) <- GI.Gst.elementQueryDuration playbin GI.Gst.FormatTime
+  when couldQueryDuration $ do
+    percentage' <- GI.Gtk.rangeGetValue seekScale
+    let percentage = percentage' / 100.0
+    let position = fromIntegral (round ((fromIntegral duration :: Double) * percentage) :: Int) :: Int64
+    void $ GI.Gst.elementSeekSimple playbin GI.Gst.FormatTime [ GI.Gst.SeekFlagsFlush ] position
+    videoInfoGathered <- readIORef videoInfoRef
+    -- When playing over a network (not local),
+    -- sending too many asynchronous seek requests will cause GStreamer to error.
+    -- Block until this seek request finishes which will block the main GTK main thread.
+    -- Note that by blocking here, the seek scale will not slide.
+    -- The user will have to point and click on the scale track.
+    unless (R.isLocalFile videoInfoGathered) $ void $ GI.Gst.elementGetState playbin GI.Gst.CLOCK_TIME_NONE
+
+updateSeekScale ::
+  GI.Gst.Element ->
+  GI.Gtk.Scale ->
+  Data.GI.Base.Signals.SignalHandlerId ->
+  IO Bool
+updateSeekScale
+  playbin
+  seekScale
+  seekScaleHandlerId
+  = do
+  (couldQueryDuration, duration) <- GI.Gst.elementQueryDuration playbin GI.Gst.FormatTime
+  (couldQueryPosition, position) <- GI.Gst.elementQueryPosition playbin GI.Gst.FormatTime
+  when (couldQueryDuration && couldQueryPosition && duration > 0) $ do
+    let percentage = 100.0 * (fromIntegral position / fromIntegral duration :: Double)
+    GI.GObject.signalHandlerBlock seekScale seekScaleHandlerId
+    GI.Gtk.rangeSetValue seekScale percentage
+    GI.GObject.signalHandlerUnblock seekScale seekScaleHandlerId
+  return True
diff --git a/src/Uri.hs b/src/Uri.hs
new file mode 100644
--- /dev/null
+++ b/src/Uri.hs
@@ -0,0 +1,66 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Uri where
+
+import System.FilePath
+import Filesystem
+import Filesystem.Path.CurrentOS
+import Data.Text
+
+removeFileUriScheme :: Prelude.String -> Prelude.String
+removeFileUriScheme str =
+  if hasFileUriScheme str
+    then Data.Text.unpack $ Data.Text.replace "file://" "" uri
+    else Data.Text.unpack uri
+  where
+    uri :: Data.Text.Text
+    uri = Data.Text.pack str
+
+hasFileUriScheme :: Prelude.String -> Bool
+hasFileUriScheme = hasUriScheme "file://"
+
+hasHttpUriScheme :: Prelude.String -> Bool
+hasHttpUriScheme str = isHttp || isHttps
+  where
+    isHttp :: Bool
+    isHttp  = hasUriScheme "http://"  str
+    isHttps :: Bool
+    isHttps = hasUriScheme "https://" str
+
+hasUriScheme :: Prelude.String -> Prelude.String -> Bool
+hasUriScheme scheme uri = toLower' scheme `Data.Text.isPrefixOf` toLower' uri
+  where
+    toLower' :: Prelude.String -> Text
+    toLower' = Data.Text.toLower . Data.Text.pack
+
+addUriSchemeIfNone :: Prelude.String -> IO Prelude.String
+addUriSchemeIfNone filePathName =
+  isLocalFile filePathName >>=
+  \ local ->
+    return $
+      if local
+        then if hasFileUriScheme filePathName then filePathName else "file://" ++ filePathName
+        else if hasHttpUriScheme filePathName then filePathName else "http://" ++ filePathName
+
+isLocalFile :: Prelude.String -> IO Bool
+isLocalFile = Filesystem.isFile . Filesystem.Path.CurrentOS.fromText . Data.Text.pack . removeFileUriScheme
+
+toAbsoluteUri :: String -> IO String
+toAbsoluteUri uri = do
+  cwd <- getWorkingDirectory
+  let cwd' = case toText cwd of
+              Right x -> x
+              Left  y -> y
+  isLocal <- isLocalFile uri
+  if not isLocal
+    then return uri
+    else
+      if isRelative uri
+        then return $ normalise $ combine (Data.Text.unpack cwd') uri
+        else return uri
diff --git a/src/Utils.hs b/src/Utils.hs
new file mode 100644
--- /dev/null
+++ b/src/Utils.hs
@@ -0,0 +1,58 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Utils where
+
+import System.Exit
+import System.Process
+import System.FilePath
+import Control.Monad
+import Control.Exception
+import Data.List
+import Data.Text
+import Data.Int
+import qualified GI.Gtk
+
+fileNameFromFilePathName :: Data.Text.Text -> Data.Text.Text
+fileNameFromFilePathName = Data.Text.pack . System.FilePath.takeFileName . Data.Text.unpack
+
+enumToInt32 :: (Enum a, Ord a) => a -> Int32
+enumToInt32 enum = fromIntegral (fromEnum enum) :: Int32
+
+isTextEmpty :: Data.Text.Text -> Bool
+isTextEmpty = Data.Text.null . Data.Text.strip
+
+getSelectedVideoWidth :: GI.Gtk.ComboBoxText -> IO Int
+getSelectedVideoWidth = fmap (\ x -> read (Data.Text.unpack x) :: Int) . GI.Gtk.comboBoxTextGetActiveText
+
+linuxProcessIsRunning :: String -> IO Bool
+linuxProcessIsRunning processName = do
+  (_, out, _) <- safeRunProcessGetOutput "pgrep" ["-f", processName]
+  return (not $ Data.List.null out)
+
+spawnLinuxProcessAndDisown :: String -> IO ()
+spawnLinuxProcessAndDisown processCommand =
+  void $
+    System.Process.spawnCommand
+      (
+              "nohup "
+          ++  processCommand
+          ++  " </dev/null &>/dev/null & disown"
+        )
+
+safeRunProcessGetOutput :: String -> [String] -> IO (System.Exit.ExitCode, String, String)
+safeRunProcessGetOutput processName args =
+  catch (
+      readProcessWithExitCode
+        processName
+        args
+        ""
+    ) (\ (e :: Control.Exception.IOException) ->
+        print e >>
+        return (ExitFailure 1, "", "")
+      )
diff --git a/src/VideoInfo.hs b/src/VideoInfo.hs
new file mode 100644
--- /dev/null
+++ b/src/VideoInfo.hs
@@ -0,0 +1,76 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module VideoInfo where
+
+import System.Exit
+import Text.Read
+import Data.Maybe
+import Data.Text
+import Data.IORef
+
+import qualified Records as R
+import Uri
+import Utils
+
+getVideoInfoRaw :: Prelude.String -> IO (Maybe Prelude.String)
+getVideoInfoRaw uri = do
+  (code, out, _) <- safeRunProcessGetOutput "gst-discoverer-1.0" [uri, "-v"]
+  if code == System.Exit.ExitSuccess
+    then return (Just out)
+    else return Nothing
+
+getVideoInfo :: IORef R.VideoInfo -> Prelude.String -> IO R.VideoInfo
+getVideoInfo videoInfoRef filePathName = do
+  videoInfoGathered <- readIORef videoInfoRef
+  uri <- addUriSchemeIfNone filePathName
+  cacheDo (R.uri videoInfoGathered == uri) videoInfoGathered uri
+  where
+    widthField :: Data.Text.Text
+    widthField = "width: "
+    heightField :: Data.Text.Text
+    heightField = "height: "
+    seekableField :: Data.Text.Text
+    seekableField = "seekable: "
+    cacheDo :: Bool -> R.VideoInfo -> Prelude.String -> IO R.VideoInfo
+    cacheDo True  videoInfoGathered _   = return videoInfoGathered
+    cacheDo False _                 uri = do
+      videoInfoRaw <- getVideoInfoRaw uri
+      processVideoInfoRaw videoInfoRaw uri
+    processVideoInfoRaw :: Maybe Prelude.String -> Prelude.String -> IO R.VideoInfo
+    processVideoInfoRaw Nothing _ = do
+      let videoInfoGathered = R.defaultVideoInfo
+      atomicWriteIORef videoInfoRef videoInfoGathered
+      return videoInfoGathered
+    processVideoInfoRaw (Just str) uri = do
+      let text      = Data.Text.toLower $ Data.Text.pack str
+      let textLines = Data.Text.lines text
+      let videoInfoGathered = R.VideoInfo {
+              R.uri          = uri
+            , R.isLocalFile  = hasFileUriScheme uri
+            , R.isVideo      = "video: video/" `Data.Text.isInfixOf` text
+            , R.isSeekable   = "yes" == getField seekableField textLines
+            , R.videoWidth   = getDimension R.videoWidth  widthField textLines
+            , R.videoHeight  = getDimension R.videoHeight heightField textLines
+          }
+      atomicWriteIORef videoInfoRef videoInfoGathered
+      return videoInfoGathered
+    getDimension :: (R.VideoInfo -> Int) -> Data.Text.Text -> [Data.Text.Text] -> Int
+    getDimension f field lines' = fromMaybe (
+        f R.defaultVideoInfo
+      ) (readMaybe (Data.Text.unpack $ getField field lines') :: Maybe Int)
+    getField :: Data.Text.Text -> [Data.Text.Text] -> Data.Text.Text
+    getField field =
+      Prelude.foldl (\ acc l ->
+          if not $ Data.Text.null acc
+            then acc
+            else if field `Data.Text.isInfixOf` l
+              then Data.Text.replace field "" $ Data.Text.strip l
+              else ""
+        ) ""
diff --git a/src/VideoSizeSelector.hs b/src/VideoSizeSelector.hs
new file mode 100644
--- /dev/null
+++ b/src/VideoSizeSelector.hs
@@ -0,0 +1,54 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+module VideoSizeSelector where
+
+import Control.Monad
+import Data.Text
+import qualified GI.Gtk
+
+import qualified Records as R
+import Window
+import VideoInfo
+import Utils
+
+addVideoSizeSelectorHandler :: R.Application -> IO ()
+addVideoSizeSelectorHandler
+  application@R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.videoWidthSelectionComboBox = videoWidthSelectionComboBox
+          }
+    }
+  = void (
+        GI.Gtk.onComboBoxChanged
+          videoWidthSelectionComboBox
+          (videoSizeSelectionHandler application)
+      )
+
+videoSizeSelectionHandler ::
+  R.Application ->
+  IO ()
+videoSizeSelectionHandler
+  R.Application {
+        R.guiObjects = guiObjects@R.GuiObjects {
+              R.window = window
+            , R.fileChooserButton = fileChooserButton
+            , R.videoWidget = videoWidget
+            , R.videoWidthSelectionComboBox = videoWidthSelectionComboBox
+            , R.fileChooserEntry = fileChooserEntry
+          }
+      , R.ioRefs = R.IORefs {
+              R.videoInfoRef = videoInfoRef
+        }
+    }
+  = do
+  filePathName <- Data.Text.unpack <$> GI.Gtk.entryGetText fileChooserEntry
+  videoWidthSelection <- getSelectedVideoWidth videoWidthSelectionComboBox
+  retrievedVideoInfo <- getVideoInfo videoInfoRef filePathName
+  maybeWindowSize <- calculateWindowSize videoWidthSelection retrievedVideoInfo
+  case maybeWindowSize of
+    Nothing -> resetWindow guiObjects
+    Just (width, height) -> setWindowSize width height fileChooserButton videoWidget window
diff --git a/src/Window.hs b/src/Window.hs
new file mode 100644
--- /dev/null
+++ b/src/Window.hs
@@ -0,0 +1,195 @@
+{-
+  Movie Monad
+  (C) 2017 David lettier
+  lettier.com
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+
+module Window where
+
+import GHC.Word
+import Control.Monad
+import Data.Int
+import Data.IORef
+import Data.Time.Clock.POSIX
+import GI.GLib
+import qualified GI.Gdk
+import qualified GI.Gtk
+import qualified GI.Gst
+
+import qualified Records as R
+import Constants
+import Mouse
+import PlayPause
+import Utils
+
+addWindowHandlers :: R.Application -> [R.Application -> IO ()] -> IO ()
+addWindowHandlers
+  application@R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.window = window
+            , R.videoWidget = videoWidget
+          }
+      , R.ioRefs = R.IORefs {
+              R.isWindowFullScreenRef = isWindowFullScreenRef
+          }
+      , R.playbin = playbin
+    }
+  functionsToRunOnWindowRealized
+  =
+  void (
+      GI.Gtk.onWidgetRealize videoWidget (
+          windowRealizedHandler
+            application
+            functionsToRunOnWindowRealized
+        )
+    ) >>
+  void (
+      GI.Gtk.onWidgetWindowStateEvent window (widgetWindowStateEventHandler isWindowFullScreenRef)
+    ) >>
+  void (
+      GI.Gtk.onWidgetDestroy window (windowDestroyHandler playbin)
+    ) >>
+  void (
+      GI.GLib.timeoutAddSeconds GI.GLib.PRIORITY_DEFAULT 1 (hideOnScreenControls application)
+    )
+
+windowRealizedHandler ::
+  R.Application ->
+  [R.Application -> IO ()] ->
+  GI.Gtk.WidgetRealizeCallback
+windowRealizedHandler
+  application@R.Application {
+        R.guiObjects = guiObjects@R.GuiObjects {
+              R.videoWidget = videoWidget
+            , R.seekScale = seekScale
+          }
+    }
+  functionsToRunOnWindowRealized
+  = do
+  let eventMask = enumToInt32 GI.Gdk.EventMaskAllEventsMask
+  GI.Gtk.widgetAddEvents videoWidget eventMask
+  GI.Gtk.widgetAddEvents seekScale eventMask
+  resetWindow guiObjects
+  mapM_ (\ f -> f application) functionsToRunOnWindowRealized
+
+widgetWindowStateEventHandler ::
+  IORef Bool ->
+  GI.Gdk.EventWindowState ->
+  IO Bool
+widgetWindowStateEventHandler isWindowFullScreenRef eventWindowState = do
+  windowStates <- GI.Gdk.getEventWindowStateNewWindowState eventWindowState
+  let isWindowFullScreen = Prelude.foldl (\ acc x ->
+          acc || GI.Gdk.WindowStateFullscreen == x
+        ) False windowStates
+  atomicWriteIORef isWindowFullScreenRef isWindowFullScreen
+  return True
+
+windowDestroyHandler ::
+  GI.Gst.Element ->
+  IO ()
+windowDestroyHandler playbin = do
+  _ <- GI.Gst.elementSetState playbin GI.Gst.StateNull
+  _ <- GI.Gst.objectUnref playbin
+  GI.Gtk.mainQuit
+
+hideOnScreenControls ::
+  R.Application ->
+  IO Bool
+hideOnScreenControls
+  R.Application {
+        R.guiObjects = R.GuiObjects {
+              R.window = window
+            , R.fileChooserButton = fileChooserButton
+            , R.bottomControlsGtkBox = bottomControlsGtkBox
+          }
+      , R.ioRefs = R.IORefs {
+            R.videoInfoRef = videoInfoRef
+          , R.mouseMovedLastRef = mouseMovedLastRef
+        }
+      , R.playbin = playbin
+    }
+  = do
+  isVideo <- R.isVideo <$> readIORef videoInfoRef
+  mouseMovedLast <- readIORef mouseMovedLastRef
+  timeNow <- fmap round getPOSIXTime
+  (_, playBinState, _) <- GI.Gst.elementGetState playbin (fromIntegral GI.Gst.MSECOND :: GHC.Word.Word64)
+  let isPlaying = GI.Gst.StatePlaying == playBinState
+  let delta = timeNow - mouseMovedLast
+  when (isPlaying && isVideo && delta >= hideOnScreenControlsInterval) $ do
+    GI.Gtk.widgetHide fileChooserButton
+    GI.Gtk.widgetHide bottomControlsGtkBox
+    setCursor window (Just "none")
+    atomicWriteIORef mouseMovedLastRef timeNow
+  return True
+
+calculateWindowSize :: Int -> R.VideoInfo -> IO (Maybe (Int32, Int32))
+calculateWindowSize videoWidthSelection retrievedVideoInfo =
+  widthHeightToDouble retrievedVideoInfo >>=
+  ratio >>=
+  windowSize
+  where
+    widthHeightToDouble :: R.VideoInfo -> IO (Maybe Double, Maybe Double)
+    widthHeightToDouble R.VideoInfo { R.isVideo = False } = return (Nothing, Nothing)
+    widthHeightToDouble R.VideoInfo { R.videoWidth = w, R.videoHeight = h } =
+      return (Just $ fromIntegral w :: Maybe Double, Just $ fromIntegral h :: Maybe Double)
+    ratio :: (Maybe Double, Maybe Double) -> IO (Maybe Double)
+    ratio (Just width, Just height) =
+      if width <= 0.0 then return Nothing else return (Just (height / width))
+    ratio _ = return Nothing
+    windowSize :: Maybe Double -> IO (Maybe (Int32, Int32))
+    windowSize Nothing = return Nothing
+    windowSize (Just ratio') =
+      return (
+          Just (
+                fromIntegral videoWidthSelection :: Int32
+              , round ((fromIntegral videoWidthSelection :: Double) *  ratio') :: Int32
+            )
+        )
+
+setWindowSize ::
+  Int32 ->
+  Int32 ->
+  GI.Gtk.Button ->
+  GI.Gtk.Widget ->
+  GI.Gtk.Window ->
+  IO ()
+setWindowSize width height fileChooserButton videoWidget window = do
+  GI.Gtk.setWidgetWidthRequest fileChooserButton width
+  GI.Gtk.setWidgetWidthRequest videoWidget width
+  GI.Gtk.setWidgetHeightRequest videoWidget height
+  GI.Gtk.setWidgetWidthRequest window width
+  GI.Gtk.setWidgetHeightRequest window height
+  GI.Gtk.windowResize window width (if height <= 0 then 1 else height)
+
+resetWindow ::
+  R.GuiObjects ->
+  IO ()
+resetWindow
+  R.GuiObjects {
+        R.window = window
+      , R.fileChooserButton = fileChooserButton
+      , R.videoWidget = videoWidget
+      , R.seekScale = seekScale
+      , R.playPauseButton = playPauseButton
+      , R.videoWidthSelectionComboBox = videoWidthSelectionComboBox
+      , R.fullscreenButton = fullscreenButton
+      , R.playImage = playImage
+      , R.pauseImage = pauseImage
+      , R.bottomControlsGtkBox = bottomControlsGtkBox
+    }
+  = do
+  videoWidthSelection <- getSelectedVideoWidth videoWidthSelectionComboBox
+  let width = fromIntegral videoWidthSelection :: Int32
+  GI.Gtk.windowUnfullscreen window
+  GI.Gtk.widgetHide videoWidget
+  GI.Gtk.widgetHide seekScale
+  GI.Gtk.widgetHide playPauseButton
+  GI.Gtk.widgetHide fullscreenButton
+  GI.Gtk.widgetShow fileChooserButton
+  GI.Gtk.widgetShow bottomControlsGtkBox
+  GI.Gtk.widgetShow videoWidthSelectionComboBox
+  setCursor window Nothing
+  setPlayPauseButton playPauseButton playImage pauseImage False
+  setWindowSize width 0 fileChooserButton videoWidget window
diff --git a/src/data/gui.glade b/src/data/gui.glade
--- a/src/data/gui.glade
+++ b/src/data/gui.glade
@@ -1,66 +1,165 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.20.0 -->
+<!-- Generated with glade 3.20.0 
+
+Copyright (c) 2017 David Lettier
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the <organization> nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Author: David Lettier
+
+-->
 <interface>
-  <requires lib="gtk+" version="3.20"/>
+  <requires lib="gtk+" version="3.10"/>
+  <!-- interface-license-type bsd3c -->
+  <!-- interface-name Movie Monad -->
+  <!-- interface-description A desktop video player built with Haskell that uses GStreamer and GTK+. -->
+  <!-- interface-copyright 2017 David Lettier -->
+  <!-- interface-authors David Lettier -->
   <object class="GtkImage" id="about-image">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
     <property name="stock">gtk-dialog-question</property>
   </object>
-  <object class="GtkAdjustment" id="adjustment1">
-    <property name="upper">100</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">10</property>
+  <object class="GtkButton" id="file-chooser-cancel-button">
+    <property name="label">gtk-cancel</property>
+    <property name="visible">True</property>
+    <property name="can_focus">True</property>
+    <property name="receives_default">True</property>
+    <property name="use_stock">True</property>
+    <property name="always_show_image">True</property>
   </object>
+  <object class="GtkButton" id="file-chooser-open-button">
+    <property name="label">gtk-open</property>
+    <property name="visible">True</property>
+    <property name="can_focus">True</property>
+    <property name="receives_default">True</property>
+    <property name="use_stock">True</property>
+    <property name="always_show_image">True</property>
+  </object>
   <object class="GtkImage" id="fullscreen-image">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
     <property name="stock">gtk-fullscreen</property>
   </object>
-  <object class="GtkWindow" id="window">
+  <object class="GtkImage" id="pause-image">
+    <property name="visible">True</property>
     <property name="can_focus">False</property>
+    <property name="stock">gtk-media-pause</property>
+  </object>
+  <object class="GtkImage" id="play-image">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="stock">gtk-media-play</property>
+  </object>
+  <object class="GtkAdjustment" id="seek-scale-adjustment">
+    <property name="upper">100</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkWindow" id="window">
+    <property name="can_focus">True</property>
     <property name="title" translatable="yes">Movie Monad</property>
     <property name="window_position">center</property>
-    <property name="icon_name">applications-multimedia</property>
+    <property name="icon">movie-monad-icon.png</property>
     <property name="gravity">center</property>
     <child>
-      <object class="GtkBox">
+      <object class="GtkBox" id="box-1">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="orientation">vertical</property>
         <child>
-          <object class="GtkBox">
+          <object class="GtkBox" id="box-2">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="hexpand">True</property>
             <property name="vexpand">True</property>
             <property name="orientation">vertical</property>
             <child>
-              <object class="GtkFileChooserButton" id="file-chooser-button">
+              <object class="GtkButton" id="file-chooser-button">
                 <property name="width_request">800</property>
                 <property name="visible">True</property>
                 <property name="app_paintable">True</property>
-                <property name="can_focus">False</property>
-                <property name="tooltip_text" translatable="yes">Select a video file.</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="tooltip_text" translatable="yes">Open a video file</property>
                 <property name="valign">start</property>
                 <property name="hexpand">True</property>
-                <property name="create_folders">False</property>
-                <property name="title" translatable="yes">Movie Monad</property>
+                <property name="relief">half</property>
+                <property name="image_position">right</property>
+                <property name="always_show_image">True</property>
+                <child>
+                  <object class="GtkBox" id="box-3">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkLabel" id="file-chooser-button-label">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">Open</property>
+                        <property name="justify">fill</property>
+                        <property name="ellipsize">end</property>
+                        <property name="single_line_mode">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkImage" id="open-image">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="stock">gtk-open</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="pack_type">end</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
               </object>
               <packing>
                 <property name="expand">False</property>
-                <property name="fill">True</property>
+                <property name="fill">False</property>
                 <property name="position">0</property>
               </packing>
             </child>
             <child>
-              <object class="GtkDrawingArea" id="drawing-area">
+              <object class="GtkBox" id="video-widget-box">
                 <property name="visible">True</property>
-                <property name="sensitive">False</property>
                 <property name="app_paintable">True</property>
-                <property name="can_focus">False</property>
+                <property name="can_focus">True</property>
                 <property name="hexpand">True</property>
                 <property name="vexpand">True</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <placeholder/>
+                </child>
               </object>
               <packing>
                 <property name="expand">True</property>
@@ -69,163 +168,209 @@
               </packing>
             </child>
             <child>
-              <object class="GtkScale" id="seek-scale">
+              <object class="GtkBox" id="bottom-controls-gtk-box">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
+                <property name="can_focus">False</property>
                 <property name="valign">end</property>
-                <property name="margin_left">5</property>
-                <property name="margin_right">5</property>
-                <property name="hexpand">True</property>
-                <property name="adjustment">adjustment1</property>
-                <property name="show_fill_level">True</property>
-                <property name="fill_level">100</property>
-                <property name="round_digits">0</property>
-                <property name="digits">-1</property>
-                <property name="draw_value">False</property>
-                <property name="value_pos">left</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkBox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="valign">end</property>
-            <property name="margin_bottom">5</property>
-            <property name="hexpand">True</property>
-            <child>
-              <object class="GtkSwitch" id="on-off-switch">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="tooltip_text" translatable="yes">Toggle on to play. Toggle off to pause.</property>
-                <property name="margin_left">5</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkVolumeButton" id="volume-button">
-                <property name="visible">True</property>
-                <property name="app_paintable">True</property>
-                <property name="can_focus">True</property>
-                <property name="focus_on_click">False</property>
-                <property name="receives_default">True</property>
-                <property name="double_buffered">False</property>
-                <property name="margin_left">5</property>
-                <property name="margin_right">5</property>
-                <property name="relief">none</property>
-                <property name="value">0.5</property>
-                <property name="size">button</property>
-                <property name="icons">audio-volume-muted-symbolic
+                <property name="orientation">vertical</property>
+                <property name="baseline_position">bottom</property>
+                <child>
+                  <object class="GtkScale" id="seek-scale">
+                    <property name="visible">True</property>
+                    <property name="app_paintable">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="valign">end</property>
+                    <property name="margin_left">5</property>
+                    <property name="margin_right">5</property>
+                    <property name="hexpand">True</property>
+                    <property name="adjustment">seek-scale-adjustment</property>
+                    <property name="show_fill_level">True</property>
+                    <property name="fill_level">100</property>
+                    <property name="round_digits">0</property>
+                    <property name="digits">-1</property>
+                    <property name="draw_value">False</property>
+                    <property name="value_pos">left</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkBox" id="box-4">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="valign">end</property>
+                    <property name="margin_top">5</property>
+                    <property name="margin_bottom">5</property>
+                    <property name="hexpand">True</property>
+                    <child>
+                      <object class="GtkButton" id="play-pause-button">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="tooltip_text" translatable="yes">Click to play</property>
+                        <property name="margin_left">5</property>
+                        <property name="margin_right">5</property>
+                        <property name="image">play-image</property>
+                        <property name="always_show_image">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkVolumeButton" id="volume-button">
+                        <property name="visible">True</property>
+                        <property name="app_paintable">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="focus_on_click">False</property>
+                        <property name="receives_default">True</property>
+                        <property name="double_buffered">False</property>
+                        <property name="margin_left">5</property>
+                        <property name="margin_right">5</property>
+                        <property name="relief">half</property>
+                        <property name="orientation">vertical</property>
+                        <property name="value">0.5</property>
+                        <property name="size">button</property>
+                        <property name="icons">audio-volume-muted-symbolic
 audio-volume-high-symbolic
 audio-volume-low-symbolic
 audio-volume-medium-symbolic</property>
-                <child internal-child="plus_button">
-                  <object class="GtkButton">
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="halign">center</property>
-                    <property name="valign">center</property>
-                    <property name="relief">none</property>
-                  </object>
-                </child>
-                <child internal-child="minus_button">
-                  <object class="GtkButton">
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="halign">center</property>
-                    <property name="valign">center</property>
-                    <property name="relief">none</property>
+                        <child internal-child="plus_button">
+                          <object class="GtkButton" id="volume-up-button">
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="halign">center</property>
+                            <property name="valign">center</property>
+                            <property name="relief">none</property>
+                          </object>
+                        </child>
+                        <child internal-child="minus_button">
+                          <object class="GtkButton" id="volume-down-button">
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="halign">center</property>
+                            <property name="valign">center</property>
+                            <property name="relief">none</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkComboBoxText" id="video-width-selection-combo-box">
+                        <property name="visible">True</property>
+                        <property name="app_paintable">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="tooltip_text" translatable="yes">Set the video width</property>
+                        <property name="margin_left">5</property>
+                        <property name="margin_right">5</property>
+                        <property name="active">1</property>
+                        <property name="has_frame">False</property>
+                        <property name="active_id">800</property>
+                        <items>
+                          <item id="320" translatable="yes">320</item>
+                          <item id="800" translatable="yes">800</item>
+                          <item id="1024" translatable="yes">1024</item>
+                          <item id="1152" translatable="yes">1152</item>
+                          <item id="1280" translatable="yes">1280</item>
+                          <item id="1360" translatable="yes">1360</item>
+                          <item id="1366" translatable="yes">1366</item>
+                          <item id="1440" translatable="yes">1440</item>
+                          <item id="1536" translatable="yes">1536</item>
+                          <item id="1600" translatable="yes">1600</item>
+                          <item id="1680" translatable="yes">1680</item>
+                          <item id="1920" translatable="yes">1920</item>
+                          <item id="2560" translatable="yes">2560</item>
+                          <item id="3440" translatable="yes">3440</item>
+                          <item id="3840" translatable="yes">3840</item>
+                        </items>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="fullscreen-button">
+                        <property name="app_paintable">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="receives_default">False</property>
+                        <property name="tooltip_text" translatable="yes">Toggle on or off fullscreen</property>
+                        <property name="margin_left">5</property>
+                        <property name="margin_right">5</property>
+                        <property name="image">fullscreen-image</property>
+                        <property name="relief">half</property>
+                        <property name="always_show_image">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">3</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSpinner" id="buffering-spinner">
+                        <property name="sensitive">False</property>
+                        <property name="app_paintable">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">5</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">4</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="about-button">
+                        <property name="visible">True</property>
+                        <property name="app_paintable">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="receives_default">False</property>
+                        <property name="tooltip_text" translatable="yes">About Movie Monad</property>
+                        <property name="margin_left">5</property>
+                        <property name="margin_right">5</property>
+                        <property name="image">about-image</property>
+                        <property name="relief">half</property>
+                        <property name="always_show_image">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="pack_type">end</property>
+                        <property name="position">5</property>
+                      </packing>
+                    </child>
                   </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
                 </child>
               </object>
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">False</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkComboBoxText" id="desired-video-width-combo-box">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="tooltip_text" translatable="yes">Set the max width.</property>
-                <property name="active">1</property>
-                <property name="has_frame">False</property>
-                <property name="active_id">800</property>
-                <items>
-                  <item id="320" translatable="yes">320</item>
-                  <item id="800" translatable="yes">800</item>
-                  <item id="1024" translatable="yes">1024</item>
-                  <item id="1152" translatable="yes">1152</item>
-                  <item id="1280" translatable="yes">1280</item>
-                  <item id="1360" translatable="yes">1360</item>
-                  <item id="1366" translatable="yes">1366</item>
-                  <item id="1440" translatable="yes">1440</item>
-                  <item id="1536" translatable="yes">1536</item>
-                  <item id="1600" translatable="yes">1600</item>
-                  <item id="1680" translatable="yes">1680</item>
-                  <item id="1920" translatable="yes">1920</item>
-                  <item id="2560" translatable="yes">2560</item>
-                  <item id="3440" translatable="yes">3440</item>
-                  <item id="3840" translatable="yes">3840</item>
-                </items>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="about-button">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="margin_right">5</property>
-                <property name="image">about-image</property>
-                <property name="always_show_image">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
                 <property name="pack_type">end</property>
                 <property name="position">3</property>
               </packing>
             </child>
-            <child>
-              <object class="GtkButton" id="fullscreen-button">
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="tooltip_text" translatable="yes">Toggle on or off fullscreen.</property>
-                <property name="image">fullscreen-image</property>
-                <property name="always_show_image">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">4</property>
-              </packing>
-            </child>
           </object>
           <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
           </packing>
         </child>
       </object>
@@ -236,7 +381,7 @@
   </object>
   <object class="GtkAboutDialog" id="about-dialog">
     <property name="can_focus">False</property>
-    <property name="title" translatable="yes">Movie Monad</property>
+    <property name="title" translatable="yes">Movie Monad - About</property>
     <property name="window_position">center</property>
     <property name="icon_name">dialog-information</property>
     <property name="type_hint">dialog</property>
@@ -244,8 +389,9 @@
     <property name="transient_for">window</property>
     <property name="attached_to">window</property>
     <property name="program_name">Movie Monad</property>
-    <property name="version">0.0.1.0</property>
-    <property name="copyright" translatable="yes">(C) 2017 David Lettier</property>
+    <property name="version">0.0.2.0</property>
+    <property name="copyright" translatable="yes">(C) 2017 David Lettier
+lettier.com</property>
     <property name="website">https://github.com/lettier/movie-monad</property>
     <property name="website_label" translatable="yes">Update</property>
     <property name="license">BSD 3-Clause License
@@ -278,15 +424,15 @@
 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</property>
     <property name="authors">David Lettier</property>
-    <property name="logo_icon_name">applications-multimedia</property>
+    <property name="logo">movie-monad-logo.svg</property>
     <property name="license_type">custom</property>
     <child internal-child="vbox">
-      <object class="GtkBox">
+      <object class="GtkBox" id="box-5">
         <property name="can_focus">False</property>
         <property name="orientation">vertical</property>
         <property name="spacing">2</property>
         <child internal-child="action_area">
-          <object class="GtkButtonBox">
+          <object class="GtkButtonBox" id="about-dialog-button-box">
             <property name="can_focus">False</property>
             <property name="layout_style">end</property>
           </object>
@@ -296,9 +442,6 @@
             <property name="position">0</property>
           </packing>
         </child>
-        <child>
-          <placeholder/>
-        </child>
       </object>
     </child>
     <child>
@@ -307,7 +450,7 @@
   </object>
   <object class="GtkMessageDialog" id="error-message-dialog">
     <property name="can_focus">False</property>
-    <property name="title" translatable="yes">Movie Monad</property>
+    <property name="title" translatable="yes">Movie Monad - Error</property>
     <property name="window_position">center</property>
     <property name="destroy_with_parent">True</property>
     <property name="icon_name">dialog-error</property>
@@ -319,15 +462,17 @@
     <property name="message_type">error</property>
     <property name="buttons">close</property>
     <property name="text" translatable="yes">There was an error.</property>
-    <property name="secondary_text" translatable="yes">Did you select a video file?
-Did you install ExifTool?</property>
+    <property name="secondary_text">If you feel like this is a bug, please visit &lt;a href="https://github.com/lettier/movie-monad/issues"&gt;the issue page&lt;/a&gt; to file a report.
+
+Thank you.</property>
+    <property name="secondary_use_markup">True</property>
     <child internal-child="vbox">
-      <object class="GtkBox">
+      <object class="GtkBox" id="box-6">
         <property name="can_focus">False</property>
         <property name="orientation">vertical</property>
         <property name="spacing">2</property>
         <child internal-child="action_area">
-          <object class="GtkButtonBox">
+          <object class="GtkButtonBox" id="error-message-dialog-action-area">
             <property name="can_focus">False</property>
             <property name="homogeneous">True</property>
             <property name="layout_style">expand</property>
@@ -336,6 +481,73 @@
             <property name="expand">False</property>
             <property name="fill">False</property>
             <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child>
+      <placeholder/>
+    </child>
+  </object>
+  <object class="GtkDialog" id="file-chooser-dialog">
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes">Movie Monad - Open a Video File</property>
+    <property name="type_hint">dialog</property>
+    <property name="transient_for">window</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="box-7">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <property name="baseline_position">top</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="file-chooser-dialog-action-area">
+            <property name="can_focus">False</property>
+            <property name="baseline_position">bottom</property>
+            <property name="layout_style">end</property>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="file-chooser-entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="tooltip_text" translatable="yes">Type in the path to a local file or URL</property>
+            <property name="has_frame">False</property>
+            <property name="truncate_multiline">True</property>
+            <property name="primary_icon_stock">gtk-edit</property>
+            <property name="secondary_icon_stock">gtk-clear</property>
+            <property name="primary_icon_activatable">False</property>
+            <property name="primary_icon_sensitive">False</property>
+            <property name="secondary_icon_tooltip_text" translatable="yes">Clear the video location</property>
+            <property name="placeholder_text" translatable="yes">Video Location</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFileChooserWidget" id="file-chooser-widget">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="create_folders">False</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
           </packing>
         </child>
       </object>
diff --git a/src/data/movie-monad-icon.png b/src/data/movie-monad-icon.png
new file mode 100644
Binary files /dev/null and b/src/data/movie-monad-icon.png differ
diff --git a/src/data/movie-monad-logo.svg b/src/data/movie-monad-logo.svg
new file mode 100644
--- /dev/null
+++ b/src/data/movie-monad-logo.svg
@@ -0,0 +1,768 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="200mm"
+   height="100mm"
+   viewBox="0 0 200 100"
+   version="1.1"
+   id="svg8"
+   inkscape:version="0.92.1 r"
+   sodipodi:docname="movie-monad-logo.svg"
+   inkscape:export-filename="/home/lettier/tmp/movie-monad-logo.png"
+   inkscape:export-xdpi="88.900002"
+   inkscape:export-ydpi="88.900002">
+  <defs
+     id="defs2">
+    <inkscape:path-effect
+       effect="bend_path"
+       id="path-effect10605"
+       is_visible="true"
+       bendpath="m 424.1184,110.88365 c 102.124,-4.64842 205.00309,-10.80704 299.39935,0"
+       prop_scale="1"
+       scale_y_rel="false"
+       vertical="false"
+       bendpath-nodetypes="cc" />
+    <inkscape:path-effect
+       effect="bounding_box"
+       id="path-effect10603"
+       is_visible="true"
+       linkedpath=""
+       visualbounds="false" />
+    <inkscape:path-effect
+       effect="fill_between_many"
+       id="path-effect10601"
+       is_visible="true"
+       linkedpaths="" />
+    <inkscape:path-effect
+       effect="rough_hatches"
+       id="path-effect10599"
+       is_visible="true"
+       direction="573.81807,105.88365 , 74.849838,0"
+       dist_rdm="75;1"
+       growth="0"
+       do_bend="true"
+       bender="573.81807,110.88365 , 5,0"
+       bottom_edge_variation="13.03522;1"
+       top_edge_variation="13.03522;1"
+       bottom_tgt_variation="0;1"
+       top_tgt_variation="0;1"
+       scale_bf="1"
+       scale_bb="1"
+       scale_tf="1"
+       scale_tb="1"
+       top_smth_variation="0;1"
+       bottom_smth_variation="0;1"
+       fat_output="true"
+       stroke_width_top="1"
+       stroke_width_bottom="1"
+       front_thickness="1"
+       back_thickness="0.25" />
+    <inkscape:path-effect
+       effect="powerstroke"
+       id="path-effect10597"
+       is_visible="true"
+       offset_points="0.2,1.5 | 1.5,1.5 | 2.8,1.5"
+       sort_points="true"
+       interpolator_type="CubicBezierFit"
+       interpolator_beta="0.81"
+       start_linecap_type="peak"
+       linejoin_type="extrp_arc"
+       miter_limit="4"
+       end_linecap_type="butt" />
+    <inkscape:path-effect
+       effect="roughen"
+       id="path-effect10595"
+       is_visible="true"
+       method="segments"
+       max_segment_size="10"
+       segments="2"
+       displace_x="10;1"
+       displace_y="10;1"
+       global_randomize="1;1"
+       handles="along"
+       shift_nodes="true"
+       fixed_displacement="false"
+       spray_tool_friendly="false" />
+    <inkscape:path-effect
+       effect="simplify"
+       id="path-effect10593"
+       is_visible="true"
+       steps="0"
+       threshold="0.002"
+       smooth_angles="0"
+       helper_size="5"
+       simplify_individual_paths="false"
+       simplify_just_coalesce="false" />
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;"
+       inkscape:isstock="true">
+      <path
+         id="path10335"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#57ace3;stroke-width:1pt;stroke-opacity:1;fill:#57ace3;fill-opacity:1"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="marker10589"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path10326"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#57ace3;stroke-width:1pt;stroke-opacity:1;fill:#57ace3;fill-opacity:1"
+         transform="scale(0.8) translate(12.5,0)" />
+    </marker>
+    <inkscape:path-effect
+       tgtlength_rdm="1;499169899"
+       tgtlength="60"
+       tgtscale="5"
+       tgt_places_rdmness="1;2340095931"
+       nbtangents="3"
+       tremble_frequency="0.01"
+       tremble_size="1;2147483646"
+       parallel_offset="0;618914966"
+       ends_tolerance="1;1"
+       strokeoverlap_rdm="1;1527224402"
+       strokeoverlap="1"
+       strokelength_rdm="1;693460889"
+       strokelength="100"
+       nbiter_approxstrokes="2"
+       is_visible="true"
+       id="path-effect10204"
+       effect="sketch" />
+    <linearGradient
+       id="linearGradient10200"
+       inkscape:collect="always">
+      <stop
+         id="stop10196"
+         offset="0"
+         style="stop-color:#57ace3;stop-opacity:1" />
+      <stop
+         id="stop10198"
+         offset="1"
+         style="stop-color:#e0437f;stop-opacity:0.89019608" />
+    </linearGradient>
+    <inkscape:path-effect
+       effect="taper_stroke"
+       id="path-effect10194"
+       is_visible="true"
+       stroke_width="5"
+       attach_start="0.99999"
+       end_offset="0.99999"
+       smoothing="0.1"
+       jointype="bevel"
+       miter_limit="100" />
+    <inkscape:path-effect
+       effect="taper_stroke"
+       id="path-effect10171"
+       is_visible="true"
+       stroke_width="1"
+       attach_start="0.2"
+       end_offset="0.2"
+       smoothing="0.5"
+       jointype="extrapolated"
+       miter_limit="100" />
+    <inkscape:path-effect
+       effect="simplify"
+       id="path-effect10169"
+       is_visible="true"
+       steps="19"
+       threshold="0.002"
+       smooth_angles="0"
+       helper_size="5"
+       simplify_individual_paths="false"
+       simplify_just_coalesce="false" />
+    <inkscape:path-effect
+       effect="roughen"
+       id="path-effect10167"
+       is_visible="true"
+       method="segments"
+       max_segment_size="9"
+       segments="2"
+       displace_x="1;1"
+       displace_y="1;1"
+       global_randomize="1;1"
+       handles="along"
+       shift_nodes="true"
+       fixed_displacement="false"
+       spray_tool_friendly="false" />
+    <inkscape:path-effect
+       effect="powerstroke"
+       id="path-effect10165"
+       is_visible="true"
+       offset_points="7.5,0.13229166"
+       sort_points="true"
+       interpolator_type="CubicBezierFit"
+       interpolator_beta="0.24"
+       start_linecap_type="butt"
+       linejoin_type="extrp_arc"
+       miter_limit="4"
+       end_linecap_type="butt" />
+    <inkscape:path-effect
+       effect="bend_path"
+       id="path-effect10163"
+       is_visible="true"
+       bendpath="M 6.8171912,228.1058 H 126.12427"
+       prop_scale="1"
+       scale_y_rel="false"
+       vertical="false" />
+    <inkscape:path-effect
+       effect="construct_grid"
+       id="path-effect10161"
+       is_visible="true"
+       nr_x="5"
+       nr_y="5" />
+    <inkscape:path-effect
+       effect="rough_hatches"
+       id="path-effect10159"
+       is_visible="true"
+       direction="66.722547,223.63972 , 30.669258,0"
+       dist_rdm="75;1"
+       growth="0"
+       do_bend="true"
+       bender="66.722547,228.63972 , 5,0"
+       bottom_edge_variation="4.25;1"
+       top_edge_variation="4.0490918;1"
+       bottom_tgt_variation="0;1"
+       top_tgt_variation="0;1"
+       scale_bf="1"
+       scale_bb="1"
+       scale_tf="1"
+       scale_tb="1"
+       top_smth_variation="0;1"
+       bottom_smth_variation="0;1"
+       fat_output="true"
+       stroke_width_top="1"
+       stroke_width_bottom="1"
+       front_thickness="1"
+       back_thickness="0.25" />
+    <inkscape:path-effect
+       effect="sketch"
+       id="path-effect10157"
+       is_visible="true"
+       nbiter_approxstrokes="5"
+       strokelength="10"
+       strokelength_rdm="0.3;1264792834"
+       strokeoverlap="0.3"
+       strokeoverlap_rdm="0.3;1"
+       ends_tolerance="0.1;1"
+       parallel_offset="1;1"
+       tremble_size="1;1"
+       tremble_frequency="0.01"
+       nbtangents="5"
+       tgt_places_rdmness="1;1"
+       tgtscale="10"
+       tgtlength="5"
+       tgtlength_rdm="0.3;1" />
+    <inkscape:path-effect
+       effect="sketch"
+       id="path-effect10155"
+       is_visible="true"
+       nbiter_approxstrokes="9"
+       strokelength="20"
+       strokelength_rdm="0.3;1580765317"
+       strokeoverlap="0"
+       strokeoverlap_rdm="0;797676426"
+       ends_tolerance="0;84877062"
+       parallel_offset="0.1;2147483646"
+       tremble_size="2;1740572465"
+       tremble_frequency="1"
+       nbtangents="4"
+       tgt_places_rdmness="1;1"
+       tgtscale="10"
+       tgtlength="10"
+       tgtlength_rdm="0.3;1" />
+    <inkscape:path-effect
+       effect="sketch"
+       id="path-effect10153"
+       is_visible="true"
+       nbiter_approxstrokes="1"
+       strokelength="100"
+       strokelength_rdm="1;693460889"
+       strokeoverlap="1"
+       strokeoverlap_rdm="1;1527224402"
+       ends_tolerance="1;1"
+       parallel_offset="1;618914966"
+       tremble_size="3;2147483646"
+       tremble_frequency="0.01"
+       nbtangents="3"
+       tgt_places_rdmness="1;2340095931"
+       tgtscale="5"
+       tgtlength="60"
+       tgtlength_rdm="1;499169899" />
+    <inkscape:path-effect
+       effect="taper_stroke"
+       id="path-effect9006"
+       is_visible="true"
+       stroke_width="20"
+       attach_start="0.99999"
+       end_offset="3.99999"
+       smoothing="0.5"
+       jointype="extrapolated"
+       miter_limit="200" />
+    <inkscape:path-effect
+       effect="roughen"
+       id="path-effect9004"
+       is_visible="true"
+       method="segments"
+       max_segment_size="10"
+       segments="2"
+       displace_x="10;1"
+       displace_y="10;1"
+       global_randomize="1;1"
+       handles="along"
+       shift_nodes="true"
+       fixed_displacement="false"
+       spray_tool_friendly="false" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect9002"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="sketch"
+       id="path-effect9000"
+       is_visible="true"
+       nbiter_approxstrokes="3"
+       strokelength="500"
+       strokelength_rdm="0.3;2971216357"
+       strokeoverlap="0.3"
+       strokeoverlap_rdm="0.3;2083033150"
+       ends_tolerance="0.1;1404504716"
+       parallel_offset="5;4166125628"
+       tremble_size="5;1181147172"
+       tremble_frequency="1"
+       nbtangents="20"
+       tgt_places_rdmness="1;296553611"
+       tgtscale="5"
+       tgtlength="100"
+       tgtlength_rdm="0.3;1794606228" />
+    <inkscape:path-effect
+       effect="ruler"
+       id="path-effect8998"
+       is_visible="true"
+       unit="px"
+       mark_distance="20"
+       mark_length="14"
+       minor_mark_length="7"
+       major_mark_steps="5"
+       shift="0"
+       offset="0"
+       mark_dir="left"
+       border_marks="both" />
+    <inkscape:path-effect
+       effect="simplify"
+       id="path-effect8996"
+       is_visible="true"
+       steps="29"
+       threshold="0.002"
+       smooth_angles="0"
+       helper_size="5"
+       simplify_individual_paths="false"
+       simplify_just_coalesce="false" />
+    <inkscape:path-effect
+       effect="show_handles"
+       id="path-effect8994"
+       is_visible="true"
+       nodes="true"
+       handles="true"
+       original_path="true"
+       scale_nodes_and_handles="10" />
+    <inkscape:path-effect
+       effect="sketch"
+       id="path-effect8992"
+       is_visible="true"
+       nbiter_approxstrokes="1"
+       strokelength="20"
+       strokelength_rdm="1;1"
+       strokeoverlap="1"
+       strokeoverlap_rdm="1;1"
+       ends_tolerance="0.1;1"
+       parallel_offset="0;1"
+       tremble_size="5;1"
+       tremble_frequency="1"
+       nbtangents="20"
+       tgt_places_rdmness="1;1"
+       tgtscale="10"
+       tgtlength="50"
+       tgtlength_rdm="0.3;1" />
+    <inkscape:path-effect
+       effect="powerstroke"
+       id="path-effect8990"
+       is_visible="true"
+       offset_points="3,0.25"
+       sort_points="true"
+       interpolator_type="Linear"
+       interpolator_beta="0.2"
+       start_linecap_type="butt"
+       linejoin_type="extrp_arc"
+       miter_limit="4"
+       end_linecap_type="butt" />
+    <inkscape:path-effect
+       effect="fill_between_strokes"
+       id="path-effect8988"
+       is_visible="true"
+       linkedpath=""
+       secondpath=""
+       reversesecond="false" />
+    <inkscape:path-effect
+       effect="fill_between_many"
+       id="path-effect8986"
+       is_visible="true"
+       linkedpaths="" />
+    <inkscape:path-effect
+       effect="gears"
+       id="path-effect8984"
+       is_visible="true"
+       teeth="10"
+       phi="5"
+       min_radius="5" />
+    <inkscape:path-effect
+       effect="rough_hatches"
+       id="path-effect8982"
+       is_visible="true"
+       direction="317.46248,263.61816 , 144.59689,0"
+       dist_rdm="75;1924315346"
+       growth="0"
+       do_bend="true"
+       bender="317.46248,268.61816 , 5,0"
+       bottom_edge_variation="13.811914;896150574"
+       top_edge_variation="13.811914;2070401107"
+       bottom_tgt_variation="0;815658193"
+       top_tgt_variation="0;1753223962"
+       scale_bf="1"
+       scale_bb="1"
+       scale_tf="1"
+       scale_tb="1"
+       top_smth_variation="0;1"
+       bottom_smth_variation="0;1"
+       fat_output="true"
+       stroke_width_top="1"
+       stroke_width_bottom="1"
+       front_thickness="1"
+       back_thickness="0.25" />
+    <inkscape:path-effect
+       effect="construct_grid"
+       id="path-effect8980"
+       is_visible="true"
+       nr_x="5"
+       nr_y="5" />
+    <linearGradient
+       id="linearGradient8935"
+       osb:paint="solid">
+      <stop
+         style="stop-color:#373737;stop-opacity:1;"
+         offset="0"
+         id="stop8933" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5282">
+      <stop
+         style="stop-color:#814dd2;stop-opacity:1;"
+         offset="0"
+         id="stop5278" />
+      <stop
+         style="stop-color:#b46bd3;stop-opacity:0.89019608"
+         offset="1"
+         id="stop5280" />
+    </linearGradient>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4997"
+         d="M 0,0 5,-5 -12.5,0 5,5 Z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lstart"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path4994"
+         d="M 0,0 5,-5 -12.5,0 5,5 Z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt"
+         transform="matrix(0.8,0,0,0.8,10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5282"
+       id="linearGradient5284"
+       x1="-119.13808"
+       y1="53.642838"
+       x2="-64.290207"
+       y2="53.285694"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5282"
+       id="linearGradient5300"
+       gradientUnits="userSpaceOnUse"
+       x1="-119.13808"
+       y1="53.642838"
+       x2="-58.218777"
+       y2="55.071407" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5282"
+       id="linearGradient5352"
+       gradientUnits="userSpaceOnUse"
+       x1="-119.13808"
+       y1="53.642838"
+       x2="-58.218777"
+       y2="55.071407" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5282"
+       id="linearGradient5354"
+       gradientUnits="userSpaceOnUse"
+       x1="-119.13808"
+       y1="53.642838"
+       x2="-64.290207"
+       y2="53.285694" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5282"
+       id="linearGradient4670"
+       gradientUnits="userSpaceOnUse"
+       x1="-119.13808"
+       y1="53.642838"
+       x2="-64.290207"
+       y2="53.285694" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5282"
+       id="linearGradient4678"
+       gradientUnits="userSpaceOnUse"
+       x1="-119.13808"
+       y1="53.642838"
+       x2="-64.290207"
+       y2="53.285694" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient10200"
+       id="linearGradient10134"
+       gradientUnits="userSpaceOnUse"
+       x1="109.73602"
+       y1="227.8952"
+       x2="192.22939"
+       y2="227.8952"
+       gradientTransform="matrix(3.7865563,-0.0047396,0.01655021,3.7724911,0.1767767,-743.59466)" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1"
+     inkscape:cx="150.91612"
+     inkscape:cy="299.37266"
+     inkscape:document-units="mm"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     showguides="false"
+     inkscape:guide-bbox="true"
+     inkscape:window-width="1920"
+     inkscape:window-height="1156"
+     inkscape:window-x="0"
+     inkscape:window-y="344"
+     inkscape:window-maximized="1"
+     inkscape:snap-global="false">
+    <sodipodi:guide
+       position="43.418068,28.252304"
+       orientation="1,0"
+       id="guide5364"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="7.4001037,11.264559"
+       orientation="1,0"
+       id="guide4628"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="76.491454,48.978922"
+       orientation="1,0"
+       id="guide4630"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="86.775231,47.758654"
+       orientation="1,0"
+       id="guide4645"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="95.872541,45.692643"
+       orientation="1,0"
+       id="guide4647"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="119.3082,86.310238"
+       orientation="0,1"
+       id="guide4649"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="87.006575,49.298283"
+       orientation="0,1"
+       id="guide4669"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="104.75846,51.385422"
+       orientation="1,0"
+       id="guide4671"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="41.353548,11.513509"
+       orientation="0,1"
+       id="guide4673"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="86.73606,46.345371"
+       orientation="0,1"
+       id="guide4675"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="38.89398,84.137282"
+       orientation="0,1"
+       id="guide4677"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="102.68449,51.22072"
+       orientation="1,0"
+       id="guide4693"
+       inkscape:locked="false" />
+    <inkscape:grid
+       type="xygrid"
+       id="grid4698" />
+    <sodipodi:guide
+       position="159.87448,27.351302"
+       orientation="1,0"
+       id="guide4710"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="112.62418,73.773699"
+       orientation="0,1"
+       id="guide8975"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="122.24405,66.315737"
+       orientation="0,1"
+       id="guide9906"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="120.16154,57.421367"
+       orientation="0,1"
+       id="guide9908"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="113.00189,59.859912"
+       orientation="1,0"
+       id="guide9910"
+       inkscape:locked="false" />
+    <sodipodi:guide
+       position="127.5477,68.84863"
+       orientation="0,1"
+       id="guide9916"
+       inkscape:locked="false" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata5">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-197)">
+    <path
+       id="path4657"
+       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:42.66666794px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';text-align:start;letter-spacing:-2.850003px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#2b2b2b;fill-opacity:1;fill-rule:nonzero;stroke:#0f0f0f;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       d="m 132.06601,248.47691 v 25.06876 l 2.94142,9.76581 h 7.51427 c 8.89726,0 17.3421,-3.56874 17.3421,-17.59324 0,-14.37636 -8.79666,-17.24133 -18.09606,-17.24133 z m 8.24394,5.98155 h 2.61379 c 4.82563,0 8.39484,1.91012 8.39484,11.25977 0,9.24913 -3.31763,11.61169 -8.29407,11.61169 h -2.71456 z m -27.95075,-5.98155 -7.59592,25.18607 0.003,9.6485 h 5.63273 l 1.75958,-7.48947 h 10.1539 l 1.80971,7.48947 h 8.72195 l -4.27932,-14.21257 0.016,-0.005 -6.21822,-20.61735 z m 4.87567,5.98155 3.66955,15.38148 h -7.33909 z m -41.385799,-5.98137 v 34.83455 h 7.339086 v -12.76769 c 0,-6.43418 -0.653097,-11.05867 -1.055232,-14.22549 l 10.053132,26.99318 h 10.505823 0.003 l -0.001,-2.78846 -0.002,0.008 v -11.04016 l -5.3e-4,-2.46031 h 5.3e-4 v -18.55339 h -7.389133 v 14.07459 c 0,5.57964 0.653473,10.15378 1.105877,12.96873 L 86.103741,248.47709 Z m -66.4031819,0 -2.6137936,34.83455 h 8.0424025 l 0.603581,-13.52165 c 0.201068,-4.8759 0.200974,-9.19902 -0.150895,-14.32626 l 5.730399,24.17889 h 7.791257 l 5.378484,-24.17889 c -0.251338,4.32296 -0.150566,9.35012 0.100767,14.22601 l 0.603062,13.6219 h 8.093046 l -2.61379,-34.83456 H 29.954716 l -4.875673,23.62543 -5.228104,-23.62543 z m 49.0809429,-0.8549 c -9.802067,0 -15.68328,6.88659 -15.68328,18.24695 0,11.61167 5.881213,18.29707 15.68328,18.29707 9.852331,0 15.733924,-6.88647 15.733924,-18.29707 0,-11.61169 -5.881593,-18.24695 -15.733924,-18.24695 z m 0,6.03219 c 4.67483,0 7.087938,3.41802 7.087938,12.21476 0,8.84699 -2.36284,12.26488 -7.087938,12.26488 -4.524031,0 -7.037298,-3.41789 -7.037298,-12.26488 0,-8.79674 2.412733,-12.21476 7.037298,-12.21476 z"
+       inkscape:connector-curvature="0" />
+    <g
+       id="flowRoot4616"
+       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:40px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';text-align:start;letter-spacing:0.38999996px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4670);stroke-width:1.13385832;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
+       transform="matrix(1.1781329,0,0,1.1781329,271.19496,167.28142)"
+       aria-label=" &gt; " />
+    <g
+       id="flowRoot4650"
+       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:40px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';text-align:start;letter-spacing:0.38999996px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4678);stroke-width:1.13385832;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
+       transform="matrix(1.1781329,0,0,1.1781329,268.90451,167.19108)"
+       aria-label="   &gt; " />
+    <g
+       id="flowRoot4642"
+       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:42.66666794px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';text-align:start;letter-spacing:-2.850003px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#373737;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       transform="matrix(1.1781329,0,0,1.1781329,258.78415,166.40418)"
+       aria-label="E" />
+    <path
+       id="path4667"
+       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:42.66666794px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Bold';text-align:start;letter-spacing:-2.850003px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#2b2b2b;fill-opacity:1;fill-rule:nonzero;stroke:#0f0f0f;stroke-width:0.26458333;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-dashoffset:0"
+       d="m 75.849287,210.69008 v 18.55338 h 5.3e-4 l -5.3e-4,2.46032 v 11.04015 l -0.0021,-0.008 -0.0011,2.78846 h 0.0031 10.505818 l 5.727817,-15.37994 7.234184,-19.45464 h -6.879603 l -10.304798,27.04331 c 0.4524,-2.81495 1.105876,-7.38907 1.105876,-12.9687 v -14.07459 z m 25.443413,0 -5.690095,15.30345 c -0.147037,1.99205 -0.249597,4.23297 -0.249597,6.76341 v 12.7677 h 7.339082 v -34.83457 z m 23.97704,5.88046 0.85453,-5.88124 h -21.36346 v 34.83503 h 21.36346 v -5.9315 H 113.0046 v -8.89726 h 10.70687 v -5.78071 H 113.0046 v -8.34432 z M 43.009437,245.52332 40.395553,210.68829 H 29.940016 l -4.875902,23.62549 -5.227765,-23.6255 H 9.431079 L 6.8171912,245.52332 H 14.859916 L 15.46312,232.0015 c 0.201072,-4.8759 0.201072,-9.19886 -0.150801,-14.3261 l 5.730438,24.17843 h 7.791382 l 5.378577,-24.17843 c -0.251343,4.32296 -0.150802,9.34967 0.100494,14.22557 l 0.603205,13.62235 z m 15.502409,-35.68953 c -9.802067,0 -15.68328,6.8866 -15.68328,18.24694 0,11.6117 5.881213,18.29708 15.68328,18.29708 9.852331,0 15.733924,-6.88646 15.733924,-18.29708 0,-11.61168 -5.881593,-18.24694 -15.733924,-18.24694 z m 0,6.0322 c 4.67483,0 7.087938,3.41802 7.087938,12.21475 0,8.847 -2.36284,12.26489 -7.087938,12.26489 -4.524031,0 -7.037298,-3.41789 -7.037298,-12.26489 0,-8.79672 2.412733,-12.21475 7.037298,-12.21475 z"
+       inkscape:connector-curvature="0" />
+    <path
+       style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:57.54236603px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Ultra-Bold';text-align:start;letter-spacing:-1.70070565px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:none;fill-opacity:1;stroke:url(#linearGradient10134);stroke-width:1.00000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       d="m 648.5341,87.310007 c -9.7121,4.127281 -19.42418,8.254548 -29.13624,12.381802 0.0453,11.073141 0.0905,22.146271 0.13585,33.219381 10.56235,4.42211 21.12472,8.84421 31.68712,13.2663 M 633.36752,96.140968 c -4.23915,1.801771 -8.47831,3.603539 -12.71747,5.405302 0.0167,3.72718 0.0333,7.45435 0.05,11.18152 m 2.04302,-3.85006 c 0.0397,8.61454 0.0794,17.22908 0.11908,25.84362 14.76048,6.17481 29.52092,12.34963 44.28132,18.52444 M 632.90195,139.0934 c 25.71117,10.75354 51.42244,21.50716 77.13382,32.26084 1.22807,-2.85848 2.45614,-5.71696 3.68421,-8.57544 m -6.90261,9.20272 c 1.03894,0.43471 2.07789,0.86942 3.11683,1.30413 3.95555,-9.19321 7.91108,-18.38642 11.86659,-27.57964 -7.57971,-2.95242 -15.15943,-5.90484 -22.73917,-8.85727 m 2.15824,-2.09073 c -15.67825,-6.11232 -31.35655,-12.22458 -47.03491,-18.33676 12.36993,-5.10497 24.73982,-10.20989 37.10967,-15.31477 m -16.53251,25.20037 c -6.44424,-2.51117 -12.8885,-5.02234 -19.33276,-7.53351 22.69625,-9.36273 45.39238,-18.72545 68.0884,-28.088151 -0.29141,-0.632498 -0.58281,-1.264996 -0.87422,-1.897494 m -69.22838,29.392715 c -0.24128,-0.094 -0.48257,-0.18796 -0.72385,-0.28193 22.68902,-9.36125 45.37812,-18.72258 68.06732,-28.083988 -3.57014,-7.743386 -7.14027,-15.486781 -10.71039,-23.230186 m -23.22126,33.437724 c 10.77256,-4.446834 21.54514,-8.893648 32.31774,-13.340443 -0.57171,-1.240078 -1.14341,-2.480156 -1.71512,-3.720233 m 1.23863,9.141077 c 0.75978,-0.313671 1.51956,-0.627341 2.27934,-0.941012 -4.03208,-8.753337 -8.06417,-17.506664 -12.09627,-26.259983 -0.56183,0.238567 -1.12367,0.477135 -1.68551,0.715703 m 12.5016,22.097459 c 0.0802,-0.03313 0.1605,-0.06626 0.24075,-0.09939 -4.03607,-8.751509 -8.07213,-17.503012 -12.10817,-26.254508 -9.87001,4.191186 -19.74,8.38238 -29.60997,12.573582 m 12.85578,-2.389769 c -22.05754,9.364824 -44.11497,18.729734 -66.17231,28.094728 m -107.274,4.187127 c -0.84131,0.3573 -1.68261,0.7146 -2.52392,1.07191 0.0163,3.90357 0.0326,7.80715 0.049,11.71072 m -3.93823,-4.9983 c 0.0401,8.6513 0.0803,17.3026 0.12039,25.9539 19.88934,8.31229 39.77866,16.6246 59.66795,24.93692 m -4.00821,-7.74504 c 11.9072,4.98365 23.81441,9.96729 35.72164,14.95091 0.91916,-2.13701 1.83832,-4.27401 2.75748,-6.41102 m -16.85174,2.4761 c 4.93606,2.06386 9.87212,4.12772 14.80817,6.19159 3.9554,-9.19637 7.91078,-18.39274 11.86615,-27.5891 -15.16944,-5.91319 -30.33891,-11.82637 -45.50842,-17.73953 m -0.0175,-0.31222 c -9.09947,-3.54582 -18.19894,-7.09162 -27.29839,-10.63741 9.38846,-3.87537 18.77693,-7.75073 28.1654,-11.62607 m -3.45166,4.69425 C 582.61769,102.37262 598.07784,95.991254 613.53799,89.609887 610.07395,82.0933 606.6099,74.576713 603.14586,67.060124 m 13.27545,22.437871 c 0.0236,-0.0097 0.0473,-0.0195 0.0709,-0.02925 -4.03355,-8.751194 -8.0671,-17.502379 -12.10065,-26.253557 -13.39917,5.691875 -26.79835,11.383767 -40.19755,17.075676 m 45.83217,-4.772545 c -1.7876,-3.875989 -3.57519,-7.751978 -5.36278,-11.627969 -9.37578,3.983924 -18.75156,7.967844 -28.12733,11.95176 m 31.84948,-3.206604 c -1.78706,-3.876259 -3.57412,-7.752517 -5.36119,-11.628776 -18.00377,7.649915 -36.00753,15.299838 -54.01126,22.94977 m 26.05047,-5.71335 c -6.70982,2.853463 -13.41964,5.706914 -20.12947,8.560353 m 12.32275,-9.896003 c -17.37721,7.384846 -34.75442,14.769727 -52.13162,22.154645 m -34.54308,3.084334 c 6.67582,4.1e-4 13.35163,8.2e-4 20.02744,0.001 1.3e-4,-1.26754 2.6e-4,-2.535071 4e-4,-3.802607 m -9.40351,8.965447 c 2.67224,-6.9e-4 5.34448,-0.001 8.01672,-0.002 -0.002,-10.545713 -0.004,-21.091419 -0.006,-31.637124 -13.34915,-0.0035 -26.69828,-0.0069 -40.04738,-0.01038 m 38.46844,20.870619 c 8.9e-4,-7.92388 0.002,-15.847764 0.003,-23.77165 -0.53954,3e-6 -1.07909,7e-6 -1.61863,1e-5 m 2.93627,18.341405 c -5.6e-4,-6.302839 -0.001,-12.60568 -0.002,-18.908526 -15.4422,0.0027 -30.88439,0.0054 -46.32658,0.0081 m 45.48451,12.828552 c 9.6e-4,-4.350837 0.002,-8.701673 0.003,-13.052506 -20.90549,-0.0024 -41.81103,-0.0048 -62.71661,-0.0072 m 65.58699,-1.54598 c -17.31771,-0.0021 -34.63544,-0.0042 -51.95318,-0.0062 m 32.6192,6.513975 c -17.50497,0.0034 -35.00998,0.0067 -52.51502,0.0099 2.4e-4,1.894165 4.7e-4,3.78833 7.1e-4,5.682494 m 36.51675,-11.129932 c -13.26226,-0.0036 -26.52453,-0.0071 -39.78682,-0.01065 7.6e-4,10.540165 0.002,21.080346 0.002,31.620542 0.54277,-1.4e-4 1.08555,-2.8e-4 1.62833,-4.3e-4 m 1.41106,-28.98446 c -1.56444,-8.4e-5 -3.12888,-1.68e-4 -4.69332,-2.52e-4 -6.9e-4,10.5424 -0.001,21.084802 -0.002,31.627202 8.20467,-4.4e-4 16.40934,-8.7e-4 24.61401,-0.001 M 426.5625,75.431744 c -4e-5,0.260418 -7e-5,0.520835 -10e-5,0.781252 m 2.74229,1.077147 c 4.6e-4,4.94823 9.2e-4,9.896459 0.001,14.844686 m -5.18108,-9.621664 c -0.002,8.346092 -0.004,16.692179 -0.007,25.038265 10.40075,-5.5e-4 20.80152,-0.001 31.20231,-0.002 M 429.5625,79.743633 c 4.7e-4,7.466811 9.4e-4,14.933626 0.001,22.400447 22.87234,-0.002 45.74463,-0.005 68.61687,-0.007 m -69.06358,44.11522 c 0.002,6.03419 0.003,12.06836 0.005,18.10254 8.29248,0.002 16.58496,0.005 24.87742,0.007 m -23.34184,-3.12116 c 20.17874,0.001 40.35759,0.002 60.53655,0.003 m -23.77935,-1.18297 c 10.52815,-0.001 21.0563,-0.002 31.58447,-0.003 -0.002,-11.50253 -0.005,-23.00505 -0.007,-34.50757 -1.27582,-1.3e-4 -2.55165,-2.7e-4 -3.82747,-4e-4 m -20.02132,38.25354 c 6.77082,-4.3e-4 13.54163,-8.6e-4 20.31244,-0.001 m -7.31097,-4.31121 c 4.10849,-4.6e-4 8.21698,-9.2e-4 12.32546,-0.001 0.003,-11.50258 0.005,-23.00515 0.008,-34.50769 -0.5369,-6e-5 -1.0738,-1.2e-4 -1.6107,-1.8e-4 m 2.79501,32.87573 c 2.9e-4,-1.82248 5.7e-4,-3.64497 8.6e-4,-5.46745 m -3.39149,0.62821 c 6.8e-4,-9.24988 0.001,-18.49975 0.002,-27.74963 -16.2697,1.5e-4 -32.53942,3e-4 -48.80914,4.5e-4 m 17.20351,1.51492 c -12.6271,-0.003 -25.25422,-0.006 -37.88136,-0.008 m 26.95033,1.07868 c -8.46134,5.8e-4 -16.92269,0.001 -25.38406,0.002 m 15.02401,-4.6814 c -6.03953,-0.001 -12.07906,-0.002 -18.1186,-0.004 2e-5,0.9914 4e-5,1.9828 6e-5,2.97421 m 1.86366,1.09184 c -0.98597,0 -1.97193,0 -2.9579,0 -2.1e-4,11.5013 -4.3e-4,23.0026 -6.5e-4,34.50389 12.38231,0 24.76462,-1e-5 37.14693,-3e-5 M 643.21578,45.707549 539.24227,89.88274 m 107.52106,-0.09641 -5.60853,2.382893 m -6.93873,48.252292 85.18969,35.63824"
+       transform="matrix(0.26458333,0,0,0.26458333,0,197)"
+       id="text10004"
+       inkscape:path-effect="#path-effect10153"
+       inkscape:original-d="M 708.97266 63.355469 L 619.80469 101.24023 L 619.94922 134.45312 L 709.44922 171.89453 L 721.31055 144.31055 L 652.99609 117.69531 L 721.07227 89.607422 L 708.97266 63.355469 z M 601.36133 63.490234 L 512.19336 101.375 L 512.33984 134.58789 L 601.83789 172.0293 L 613.70117 144.44531 L 545.38477 117.83008 L 613.46094 89.742188 L 601.36133 63.490234 z M 426.85156 73.822266 L 426.85156 105.45117 L 500.01367 105.45117 L 500.01367 73.822266 L 426.85156 73.822266 z M 426.47656 126.69727 L 426.47656 161.20117 L 500.01367 161.20117 L 500.01367 126.69727 L 426.47656 126.69727 z " />
+    <path
+       inkscape:original-d="m 708.97266,63.355469 -89.16797,37.884761 0.14453,33.21289 89.5,37.44141 11.86133,-27.58398 -68.31446,-26.61524 68.07618,-28.087888 z m -107.61133,0.134765 -89.16797,37.884766 0.14648,33.21289 89.49805,37.44141 11.86328,-27.58399 -68.3164,-26.61523 68.07617,-28.087892 z M 426.85156,73.822266 v 31.628904 h 73.16211 V 73.822266 Z m -0.375,52.875004 v 34.5039 h 73.53711 v -34.5039 z"
+       inkscape:path-effect="#path-effect10204;#path-effect10605"
+       id="path10202"
+       d="m 650.24158,82.877982 c -10.149,3.781746 -20.1801,7.698359 -30.11816,11.721213 3e-5,-0.006 -0.20722,33.232025 -0.20718,33.226045 10.46503,4.53182 20.80539,9.18012 30.97848,13.96782 M 633.98845,89.915578 c -4.37615,1.710896 -8.7325,3.44455 -13.07111,5.19858 1e-5,-4.22e-4 -0.0739,11.184852 -0.0739,11.184432 m 0.37278,-3.80672 c 1e-5,-0.002 -0.17855,25.85224 -0.17854,25.85018 14.60623,6.34072 28.96616,12.91035 42.96367,19.77137 m -31.31836,-14.0728 c 25.19686,11.26895 49.54864,23.28313 72.44078,36.37319 1.425,-2.72943 2.86187,-5.45508 4.31094,-8.17685 m -6.97533,6.68321 c 0.92922,0.52549 1.85609,1.05271 2.78058,1.58169 4.58684,-8.77946 9.29667,-17.51974 14.14,-26.21726 -6.95272,-3.77255 -14.01859,-7.44365 -21.18283,-11.02194 m 1.28755,-0.18554 c -14.8103,-7.42641 -30.04349,-14.4533 -45.56854,-21.15719 12.62298,-4.62803 25.39915,-9.03748 38.37817,-13.169505 m -18.7384,22.832935 c -6.26317,-2.87365 -12.58539,-5.68727 -18.95756,-8.44619 23.14078,-8.47619 46.79403,-16.213872 71.26656,-22.849679 -0.22872,-0.662637 -0.45816,-1.32517 -0.68831,-1.987601 m -71.06157,24.84294 c -2.7e-4,-1.2e-4 -0.71567,-0.30912 -0.71594,-0.30924 23.13582,-8.50099 46.78195,-16.269483 71.24507,-22.942194 -2.81444,-8.108272 -5.73549,-16.201083 -8.75553,-24.2782 m -26.09484,33.263656 c 11.29107,-3.630566 22.7343,-7.053436 34.3625,-10.229723 -0.45247,-1.298072 -0.90767,-2.595747 -1.36557,-3.893024 m -0.61775,6.067313 c 0.81699,-0.225925 1.63488,-0.450636 2.45368,-0.674118 -3.17802,-9.163387 -6.49223,-18.307041 -9.93162,-27.430627 -0.62069,0.179564 -1.24081,0.359777 -1.86037,0.540633 M 724.0723,88.77051 c -3e-5,7e-6 0.2599,-0.07099 0.25987,-0.07098 -3.19166,-9.161723 -6.51908,-18.303673 -9.97123,-27.425513 -10.91455,3.157907 -21.65447,6.515727 -32.24586,10.043417 m 11.85695,-2.48494 c -23.89196,7.592096 -46.99908,16.087727 -69.6127,25.151573 m -0.43513,1.234862 c -0.86165,0.346041 -1.7226,0.692905 -2.58285,1.040573 0,-6.33e-4 -0.0825,11.715567 -0.0825,11.714937 m -1.14486,-4.62264 c 2e-5,-0.003 -0.15936,25.9702 -0.15934,25.96762 19.67736,8.52605 38.90805,17.46409 57.40797,26.96703 m -5.17959,-4.09691 c 11.17635,5.63101 22.10189,11.45969 32.71559,17.51889 1.06572,-2.04091 2.13807,-4.0797 3.21719,-6.11634 m -16.16717,-0.69843 c 4.49732,2.4364 8.94519,4.91012 13.33928,7.42352 4.5879,-8.78027 9.29885,-17.52135 14.14335,-26.21966 -13.9167,-7.55194 -28.28634,-14.69746 -42.99029,-21.50586 m 3.21061,0.9872 c -8.79427,-4.11274 -17.71151,-8.10234 -26.72613,-11.98375 9.58254,-3.52225 19.25313,-6.91934 29.03349,-10.16553 m -6.29154,3.40821 c 16.00756,-5.449894 32.29758,-10.506011 48.96708,-15.053449 -2.73184,-7.869814 -5.56409,-15.725064 -8.48978,-23.565537 m 9.71116,23.601543 c -10e-6,10e-7 0.0757,-0.02052 0.0757,-0.02052 -3.1675,-9.168181 -6.47185,-18.316577 -9.90208,-27.444853 -14.82033,4.260532 -29.31841,8.892287 -43.55961,13.820057 m 47.96444,-1.481223 c -1.46923,-4.051074 -2.96412,-8.098229 -4.4837,-12.141437 -10.36636,2.98215 -20.57513,6.14594 -30.64872,9.46561 m 34.56626,1.430692 c -1.47476,-4.050136 -2.97506,-8.096352 -4.49994,-12.138618 -19.92545,5.740294 -39.26773,12.148987 -58.18539,19.043646 m 27.30172,-7.79642 c -7.20395,2.383141 -14.33903,4.845786 -21.41343,7.378487 m 13.91967,-6.239516 c -18.5565,6.309449 -36.66702,13.130413 -54.47416,20.298837 m -99.88694,-2.65901 c -3.7155,1.714952 -7.42448,3.435794 -11.12812,5.161624 -5e-5,-0.0011 0.51174,11.701562 0.51169,11.700442 m -1.16626,-9.974288 c -2e-5,7e-6 -0.10031,0.04677 -0.10032,0.04677 -4.9e-4,-0.01105 1.45405,33.189175 1.45357,33.178125 14.55592,5.39361 29.0225,10.86451 43.33592,16.46681 m -44.30591,-34.9574 c -1.2e-4,-0.003 0.76588,17.43323 0.76576,17.43045 2.49468,0.92414 4.98679,1.85054 7.47599,2.77947 m -7.79893,-15.73125 c -7e-5,-0.001 0.55089,12.57745 0.55083,12.57602 16.53412,6.12709 32.95515,12.35391 49.1696,18.75966 m -49.998,-25.64703 c -2e-5,-4.2e-4 0.29586,6.72017 0.29584,6.71975 21.69241,8.03149 43.19188,16.23317 64.28749,24.78382 m -55.73364,-22.29341 c 16.28094,6.07855 32.438,12.26676 48.38137,18.64074 M 538.6902,140.8996 c 13.05629,4.98649 26.008,10.06328 38.80781,15.27048 4.95988,2.02065 9.89517,4.0586 14.80138,6.11628 m -42.55708,-18.2693 c 9.31176,3.60951 18.56357,7.2712 27.73805,10.99979 8.32758,3.38914 16.58663,6.82714 24.75588,10.32545 2.01093,-4.82094 4.03838,-9.63839 6.08388,-14.45184 m -27.09202,6.54812 c 6.76764,2.77547 13.48728,5.58447 20.1474,8.43321 3.83317,-9.20422 7.72597,-18.39597 11.68893,-27.57166 -2.66267,-1.06719 -5.33325,-2.12724 -8.0111,-3.18056 m -17.67453,24.80734 c -4e-4,-1.6e-4 0.71086,0.29527 0.71045,0.2951 m 0.14227,0.48986 c 4.4971,1.87026 8.97094,3.75642 13.41807,5.66035 m -10.077,-3.99188 c 3.30432,1.38397 6.59552,2.77682 9.87223,4.17929 3.83114,-9.20405 7.72187,-18.39563 11.68269,-27.57116 -4.68134,-1.87728 -9.38733,-3.73251 -14.11434,-5.56781 m -3.47274,28.46872 c 2.50316,1.05575 4.99856,2.11681 7.4856,3.18351 3.84303,-9.20071 7.74681,-18.38849 11.72182,-27.55979 -12.43487,-4.99967 -25.04372,-9.84155 -37.75845,-14.5654 -3.78675,-1.40608 -7.58297,-2.80119 -11.38756,-4.18633 m 48.53565,21.61219 c -1.7e-4,4e-4 0.39568,-0.91478 0.39551,-0.91439 -12.35213,-4.96947 -24.87863,-9.78356 -37.51252,-14.48141 0,0 0,0 0,0 -0.002,-5.9e-4 -1.49386,-0.55438 -1.49544,-0.55497 m 14.92803,5.28113 c -4.46369,-1.70194 -8.94392,-3.38741 -13.43767,-5.05816 -10.77759,-4.00456 -21.6331,-7.92011 -32.54145,-11.76948 3.60412,-1.59924 7.21392,-3.19123 10.83049,-4.77515 m 3.29049,8.8856 c -4.50077,-1.62071 -9.01238,-3.22836 -13.53303,-4.82458 10.46006,-4.6382 20.96883,-9.21505 31.55249,-13.710221 6.70151,-2.847434 13.43404,-5.663734 20.20532,-8.439763 m -42.45719,26.470664 c -2.78088,-0.99541 -5.56571,-1.98604 -8.35408,-2.97227 3.53015,-1.56453 7.06581,-3.12201 10.60798,-4.67164 m -6.28221,1.12087 c 8.71898,-3.84186 17.47467,-7.63886 26.28214,-11.379291 6.23906,-2.650669 12.50495,-5.274355 18.80392,-7.863686 m -30.08413,13.695717 c 1.69004,-0.7302 3.38175,-1.45849 5.07524,-2.18477 m -3.70952,0.27076 c 3.29638,-1.42091 6.59931,-2.83445 9.90956,-4.240003 12.08898,-5.135115 24.2791,-10.168894 36.61561,-15.047723 -3.81907,-8.196246 -7.69879,-16.377835 -11.63022,-24.544496 m 7.66355,15.993468 c -2.66832,-5.660129 -5.36415,-11.313206 -8.08454,-16.959141 -6.13435,2.520141 -12.22725,5.075193 -18.28428,7.658738 m 21.8501,0.239974 c -1.19988,-2.513918 -2.40488,-5.026433 -3.61474,-7.537535 -5.45054,2.240469 -10.86844,4.508482 -16.25759,6.799535 m 12.33589,-6.475006 c -6.71417,2.780884 -13.37956,5.60218 -20.00355,8.455418 m 5.22362,-1.424866 c -2.09601,0.894819 -4.18772,1.793033 -6.27538,2.694375 -21.33032,9.189731 -42.27864,18.699376 -63.05589,28.36997 m 73.14903,-32.387689 c -3.37392,1.430271 -6.73645,2.869706 -10.08856,4.317204 -14.05547,6.056609 -27.94537,12.252172 -41.73006,18.541186 m 34.13573,-15.100677 c -13.55115,5.910939 -26.95746,11.944435 -40.27371,18.059191 M 567.455,71.414256 c -10.01024,4.371971 -19.94169,8.810224 -29.81644,13.298103 m 19.59924,-7.3737 c -15.52737,6.889358 -30.88337,13.926195 -46.1519,21.047284 -10e-5,-0.0022 0.70264,16.025187 0.70254,16.022947 m 0.87651,-18.197631 c -1.9e-4,8.6e-5 -0.35812,0.16672 -0.3583,0.166806 m 1.08448,0.822714 c -0.004,0.0019 -1.69243,0.788488 -1.69657,0.790417 -1.3e-4,-0.0029 0.84103,19.229244 0.8409,19.226364 m 0.27212,-20.309867 c -7.4e-4,3.43e-4 -0.71392,0.332461 -0.71466,0.332804 -4e-4,-0.0093 1.44469,33.189763 1.44429,33.180483 11.28017,4.18412 22.50656,8.41567 33.64949,12.71984 m -35.32215,-28.47471 c -1.1e-4,-0.002 0.69794,15.953 0.69784,15.95059 17.67814,6.55284 35.2254,13.22036 52.52747,20.09941 m -13.02727,-5.4797 c 6.64819,2.58659 13.26492,5.20045 19.84385,7.84699 m -14.54026,-5.47963 c 3.37527,1.32489 6.74192,2.65722 10.09913,3.9977 m -5.39559,-1.55982 c 5.16536,2.04368 10.30944,4.10566 15.42921,6.18851 8.03258,3.27252 16.00065,6.59042 23.88508,9.96399 3.57375,-8.58209 7.19933,-17.15333 10.88525,-25.71084 m -48.34658,8.62447 c 4.53399,1.79806 9.0515,3.61046 13.55048,5.43895 8.57906,3.49155 17.0857,7.03497 25.49668,10.6428 1.91851,-4.59483 3.85215,-9.18644 5.80223,-13.77439 m -41.52536,0.52971 c 3.42676,1.36777 6.84367,2.74402 10.24984,4.1295 8.35495,3.40329 16.64023,6.85569 24.83429,10.36877 3.83709,-9.20147 7.73433,-18.39024 11.70222,-27.56272 -5.91943,-2.37828 -11.87854,-4.72102 -17.86996,-7.03252 m 13.95351,4.36339 c -0.002,-8.8e-4 -1.79934,-0.7141 -1.80156,-0.71498 m 0.25261,1.27066 c -10.41553,-4.13 -20.94603,-8.15491 -31.55191,-12.09788 -10.5318,-3.91299 -21.13804,-7.741 -31.79532,-11.50531 -0.0133,0.006 3.63504,-1.60824 3.62177,-1.60235 m 48.0644,20.84878 c -4.71741,-1.82326 -9.45512,-3.62703 -14.20953,-5.41341 m 2.40101,-0.2426 c -2.69367,-1.01619 -5.39282,-2.02666 -8.09682,-3.03181 -10.38933,-3.85968 -20.85046,-7.63674 -31.36094,-11.3516 -0.0155,0.007 3.94411,-1.74382 3.92864,-1.73696 m 20.404,11.06404 c -7.93015,-2.91003 -15.89918,-5.77486 -23.89719,-8.60348 5.07413,-2.2482 10.15969,-4.48179 15.25969,-6.69847 m -13.61649,6.6743 c -0.009,-0.003 -3.05451,-1.07992 -3.06321,-1.08301 10.59224,-4.6966 21.23429,-9.33057 31.95333,-13.88081 7.21165,-3.062608 14.45934,-6.08915 21.75269,-9.068245 m -8.83881,3.866756 c 7.8818,-3.27547 15.81275,-6.500433 23.80517,-9.66031 -0.90933,-1.951335 -1.82211,-3.901839 -2.73821,-5.851509 m 2.26326,3.123733 c -3.697,-7.91409 -7.45009,-15.814457 -11.25119,-23.700854 -8.5632,3.512555 -17.0451,7.093405 -25.46084,10.725134 -4.85982,2.092681 -9.69974,4.201958 -14.52227,6.325955 M 445.3614,104.95449 c 9.76321,-0.4568 1.68049,-0.0787 11.4437,-0.53547 m -10.32307,0.17019 c 17.33768,-0.81149 34.68495,-1.62843 52.0441,-2.35925 0,2e-5 -0.46244,-11.003335 -0.46244,-11.003316 m -45.86213,13.509466 c 10.91926,-0.51038 21.84211,-1.01894 32.76916,-1.5028 m -10.72125,-0.82512 c 8.068,-0.3673 16.13869,-0.72521 24.21227,-1.06452 0.002,0.0444 -1.33216,-31.644111 -1.33029,-31.599679 -6.59025,0.277249 -13.17067,0.566548 -19.74138,0.862977 m 2.25651,0.535676 c -7.30576,0.326528 -36.16329,1.682218 -43.46906,2.008746 m 35.77617,-0.870836 c -10.80151,0.493925 -31.83544,1.492911 -42.63695,1.986836 m 3.35975,-1.504342 c 0.39499,-0.01836 -9.27129,0.428216 -8.87629,0.409857 -0.001,-0.02207 1.44614,31.619645 1.44513,31.597575 0.10366,-0.005 5.20914,-0.23889 5.31279,-0.24362 m -0.2042,-30.76454 c 0.20369,-0.0094 -6.92249,0.318369 -6.71879,0.308951 -9.8e-4,-0.02146 1.44069,31.616219 1.43972,31.594769 0.1859,-0.008 6.89529,-0.31723 7.08119,-0.32573 m -6.69291,-6.800598 c 0,-4e-6 0.3181,6.962618 0.3181,6.962618 0.24448,-0.0112 7.70616,-0.35518 7.95064,-0.36637 m -8.35402,-1.37166 c 0,0 0.0827,1.80758 0.0827,1.80758 3.0696,-0.14043 22.32683,-1.04088 25.39644,-1.18132 m 20.54416,-1.203 c 8.98418,-0.41193 17.97134,-0.81355 26.9618,-1.19215 0.002,0.0378 -1.33217,-31.639357 -1.33058,-31.601546 -10.17056,0.427545 -20.31809,0.883734 -30.44304,1.350483 m 30.68664,-0.72718 c -20.40193,0.858688 -40.71263,1.833171 -60.93582,2.777436 m 28.41997,-1.684025 c -4.1856,0.193669 -19.90118,0.931629 -24.08678,1.125298 m 22.17602,-1.068122 c -22.28414,1.034703 -17.10212,0.801742 -39.38626,1.836445 -1.4e-4,-0.0031 0.53538,11.761564 0.53524,11.758433 m 32.28599,-14.126315 c -95.89965,4.469127 62.94442,-2.937182 -32.95522,1.531945 -1e-4,-0.0021 0.45257,9.905323 0.45248,9.903238 M 448.9164,72.551881 c 11.72288,-0.549159 -36.94844,1.722573 -25.22557,1.173414 -0.001,-0.0234 1.44333,31.619995 1.44226,31.596595 6.6714,-0.30451 28.44286,-1.3283 35.11426,-1.63281 m -34.01902,1.55845 c 13.52181,-0.61825 30.67232,-1.43431 44.19413,-2.05256 m -9.57078,1.2155 c 12.84618,-0.5986 25.69748,-1.18633 38.55486,-1.72596 0.003,0.069 -1.20208,-28.704378 -1.19919,-28.635343 m -20.193,84.780593 c -0.21015,0.01 8.44865,-0.38035 8.2385,-0.37079 m -8.41912,0.49633 c 7.79028,-0.35489 15.56278,-0.70005 23.3177,-1.02705 0.007,0.17784 -1.4534,-34.65264 -1.44594,-34.47479 -7.23278,0.30417 -14.47002,0.62366 -21.7119,0.95178 m 9.43891,34.49345 c 4.35631,-0.19375 8.70702,-0.38336 13.05218,-0.56734 0.003,0.066 -1.45708,-34.542 -1.4543,-34.47599 -0.0565,0.002 -5.57864,0.23801 -5.63515,0.24039 m 7.67428,28.58029 c 0,0 -0.40982,-9.7569 -0.40982,-9.7569 m 0.84061,6.75643 c 0.001,0.0346 -1.11214,-26.54197 -1.1107,-26.50738 -17.97917,0.75429 -35.98538,1.60458 -54.02121,2.44789 m 55.01929,23.80495 c 0.007,0.15617 -0.85568,-20.45303 -0.84915,-20.29687 m 0.21924,1.51522 c 3.1e-4,0.008 -0.35042,-8.37985 -0.3501,-8.37232 -10.5658,0.44215 -21.14036,0.91746 -31.72418,1.40505 m 9.07703,1.51937 c -16.95737,0.77063 -35.92067,1.68342 -52.87805,2.45405 -0.001,-0.0286 1.56923,34.49986 1.56793,34.4713 0.058,-0.003 4.17146,-0.18972 4.22949,-0.19234 m -4.98992,-19.88834 c -3.8e-4,-0.008 0.87723,19.28496 0.87684,19.27656 18.6697,-0.84824 35.2157,-1.64809 53.8854,-2.49633 m 11.79856,0.1906 c -0.15774,0.007 8.99135,-0.38633 8.83362,-0.37944 -10e-6,-8e-5 -1.43579,-34.1165 -1.43579,-34.11659 m -1.69603,33.35019 c -0.0262,0.001 3.81643,-0.16203 3.79027,-0.16091 0.0157,0.37447 -1.4585,-34.85081 -1.44283,-34.47634 -0.0214,8.9e-4 -3.5105,0.14826 -3.53186,0.14915 m 4.61922,19.10912 c 0.004,0.0858 -0.78458,-18.76752 -0.78099,-18.68177 -24.53892,1.02893 -49.13037,2.23745 -73.78111,3.36364 m 73.39687,-3.66582 c 0,0 -0.0473,-1.127 -0.0473,-1.127 -8.93557,0.37427 -17.87744,0.77214 -26.82593,1.18099 m 15.15007,0.12688 c -0.22906,0.0101 -9.6177,0.43036 -9.84676,0.44045 m 1.52061,0.34501 c -16.24181,0.73155 -38.96197,1.82062 -55.20378,2.55217 -0.001,-0.0237 1.47431,32.45127 1.47323,32.42759 m 40.34148,-35.16514 c -25.12414,1.16377 -16.34142,0.76449 -41.46556,1.92826 -7.8e-4,-0.017 1.2093,26.53281 1.20852,26.51577 m 24.69571,-28.18027 c 9.53772,-0.44541 -35.81094,1.66128 -26.27322,1.21588 -0.001,-0.0299 1.57115,34.49543 1.56979,34.46556 0.0762,-0.003 4.73457,-0.2163 4.81073,-0.21977 m -2.79221,-33.16409 c 0.0241,-0.001 -2.59964,0.11865 -2.57549,0.11755 -4e-4,-0.009 0.8109,17.75591 0.8105,17.74721 m -1.05404,-3.95994 c -4.1e-4,-0.009 0.89319,19.58425 0.89278,19.57525 0.1,-0.005 5.38575,-0.24536 5.48572,-0.24989 m -0.33745,0.29462 c 18.27801,-0.83737 27.86561,-1.30104 46.14361,-2.13842 m -30.04463,0.96977 c 1.40741,-0.0658 6.09013,-0.28494 7.49755,-0.35072 m -6.93473,1.30994 c 17.84317,-0.83318 35.5931,-1.67079 53.25223,-2.41325 0.001,0.0251 -0.89222,-21.27408 -0.89117,-21.24899 M 645.91022,40.260018 C 621.98143,48.971525 598.82716,58.393162 576.151,68.183886 563.38251,73.685152 550.75083,79.301063 538.21074,84.99752 m 110.06472,-0.559322 c -1.94975,0.731393 -3.89521,1.467714 -5.83656,2.208758 m -8.17032,48.075284 c 27.78415,12.47907 54.52224,25.87525 79.38684,40.63376"
+       style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:57.54236603px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Ultra-Bold';text-align:start;letter-spacing:-1.70070565px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient10134);stroke-width:2.00000003;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"
+       transform="matrix(0.26458333,0,0,0.26458333,0,197)"
+       inkscape:connector-curvature="0" />
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11666656px;line-height:125%;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';text-align:start;letter-spacing:0px;word-spacing:-0.26458333px;writing-mode:lr-tb;text-anchor:start;fill:#b2b2b2;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
+       x="247.48691"
+       y="151.86511"
+       id="text4786"
+       transform="rotate(23.112766)"><tspan
+         sodipodi:role="line"
+         id="tspan4784"
+         x="247.48691"
+         y="151.86511"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11666656px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans';word-spacing:-0.26458333px;stroke-width:0.26458332px;fill:#b2b2b2;fill-opacity:1;">(C) DAVID LETTIER</tspan></text>
+  </g>
+</svg>
