Lots of fixes to pagination, l10n, tutorial, css ...
diff --git a/Makefile.PL b/Makefile.PL
index 0fa8bc5..6517dce 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -19,15 +19,11 @@
     'Mojolicious::Plugin::Notifications' => 0.04,
     'Mojolicious::Plugin::MailException' => 0.18,
     'Mojolicious::Plugin::CHI' => 0.09,
+    'Cache::FastMmap' => 0,
 
     # Currently only on GitHub
     'Mojolicious::Plugin::Search' => 0.04,
-    'Cache::FastMmap' => 0,
-    'Mojolicious::Plugin::Number::Commify' => '0.022',
-    'Mojolicious::Plugin::AssetPack' => 0.23,
-    'JavaScript::Minifier::XS' => 0.09,
-    'CSS::Minifier::XS' => 0.09,
-    'CSS::Sass' => '0.8.1'
+    'Mojolicious::Plugin::Localize' => 0.08
   },
   test => {
     TESTS => 't/*.t'
diff --git a/dev/scss/main/kwic.scss b/dev/scss/main/kwic.scss
index 3676663..7284311 100644
--- a/dev/scss/main/kwic.scss
+++ b/dev/scss/main/kwic.scss
@@ -5,7 +5,7 @@
 
 #search {
   position: relative;
-  margin-bottom: 44px;
+  margin-bottom: 30px;
   overflow: visible;
 
   &.match {
@@ -84,7 +84,7 @@
 //      @include light-noise;
       position: relative;
       > div {
-	min-height: 42pt;
+	min-height: 20pt;
 	> div.snippet {
 	  background-color: $light-orange;
 	  > * {
diff --git a/dev/scss/main/logos.scss b/dev/scss/main/logos.scss
index 1512a56..c2caa70 100644
--- a/dev/scss/main/logos.scss
+++ b/dev/scss/main/logos.scss
@@ -44,7 +44,8 @@
   font-size: 85%;
   right: 0;
   width: 100%;
-  margin-left: $standard-margin;
+  margin-left: ($standard-margin / 2);
+
   padding-left: 60%;
   > div {
     border-top: 26px solid $dark-orange;
@@ -103,10 +104,3 @@
   text-align: center;
   width: 100%;
 }
-
-/*
-#leibniz-logo, #ids-logo {
-  height: (130 / 20) + em;
-}
-
-*/
\ No newline at end of file
diff --git a/dev/scss/main/pagination.scss b/dev/scss/main/pagination.scss
index d057dd0..ef5eb34 100644
--- a/dev/scss/main/pagination.scss
+++ b/dev/scss/main/pagination.scss
@@ -25,8 +25,8 @@
    */
   font-size: 0;
   position: fixed;
-  right: 20px;
-  bottom: 24px;
+  right: ($standard-margin / 4);
+  bottom: ($standard-margin / 2);
   z-index: 400;
   padding: 0;
   height: auto;
diff --git a/dev/scss/main/resultinfo.scss b/dev/scss/main/resultinfo.scss
index 8717f72..93b1714 100644
--- a/dev/scss/main/resultinfo.scss
+++ b/dev/scss/main/resultinfo.scss
@@ -17,3 +17,16 @@
   font-weight: bold;
 }
 
+#no-results {
+  margin: 0 auto;
+  text-align: center;
+  code {
+    &::before {
+      content : open-quote;
+    }
+    &::after {
+      content : close-quote;
+    }
+    font-weight: bold;
+  }
+}
diff --git a/kalamar.conf b/kalamar.conf
index 2375936..ae026dc 100644
--- a/kalamar.conf
+++ b/kalamar.conf
@@ -1,6 +1,17 @@
+# Based on Mojolicious::Plugin::Number::Commify
+my $THOUSAND_SEP_RE = qr/(
+  ^[-+]?           # beginning of number.
+  \d+?             # first digits before first comma
+  (?=              # followed by, (but not included in the match) :
+    (?>(?:\d{3})+) # some positive multiple of three digits.
+    (?!\d)         # an *exact* multiple, not x * 3 + 1 or whatever.
+  )|               # or:
+  \G\d{3}          # after the last group, get three digits
+  (?=\d)           # but they have to have more digits after them.
+)/x;
+
 {
   Kalamar => {
-#    'api-0.1' => 'http://10.0.10.13:8888/api/v0.1/'
     'api-0.1' => 'http://10.0.10.13:7070/api/v0.1/'
   },
   Notifications => {
@@ -14,11 +25,6 @@
     api => 'http://10.0.10.13:7070/api/v0.1/'
   },
   CHI => {
-#    session_cache => {
-#      driver     => 'FastMmap',
-#      root_dir   => app->home . '/cache/session',
-#      cache_size => '3m'
-#    },
     default => {
       driver => 'FastMmap',
       root_dir => app->home . '/cache/data',
@@ -32,17 +38,24 @@
     proxy => 1
   },
   'TagHelpers-Pagination' => {
-    prev => '<span><i class="fa fa-caret-left"></i></span>',
-    next => '<span><i class="fa fa-caret-right"></i></span>',
-    ellipsis => '<span><i class="fa fa-ellipsis-h"></i></span>',
+    prev      => '<span><span>&lt;</span></span>',
+    next      => '<span><span>&lt;</span></span>',
+    ellipsis  => '<a class="ellipsis"><span><span>...</span></span></a>',
     separator => '',
-    current => '<span>{current}</span>',
-    page => '<span>{page}</span>'
+    current   => '<span>{current}</span>',
+    page      => '<span>{page}</span>'
   },
   Localize => {
     dict => {
       _ => sub { $_->locale },
       de => {
+        numf => sub {
+	  shift;
+	  my %val = @_;
+	  my $num = $val{number} or return 0;
+	  $num =~ s/$THOUSAND_SEP_RE/$1\./g;
+	  return $num;
+        },
 	about => 'Über KorAP',
 	login => 'Anmelden',
 	searchtitle => 'KorAP: Finde "<%= $q %>" (<%= $ql %>)',
@@ -56,14 +69,25 @@
 	tutorial => 'Einführung',
 	pubOn => 'veröffentlicht am',
 	matchCount => 'Treffer',
+	noMatches => 'Es wurden keine Treffer für <code><%= stash("q") %></code> gefunden.',
 	jsFile => 'kalamar-<%= $Kalamar::VERSION %>-en.js',
 	korap => {
 	  -short => 'KorAP',
-	  long => 'KorAP - Korpusanalyseplattform der nächsten Generation',
+	  desc => 'KorAP - Korpusanalyseplattform der nächsten Generation',
 	  overview => 'KorAP - Übersicht',
 	},
+	template => {
+	  intro => 'de/intro'
+	}
       },
       -en => {
+        numf => sub {
+	  shift;
+	  my %val = @_;
+	  my $num = $val{number} or return 0;
+	  $num =~ s/$THOUSAND_SEP_RE/$1\,/g;
+	  return $num;
+        },
 	about => 'About KorAP',
 	login => 'Login',
 	go => 'Go!',
@@ -74,13 +98,14 @@
 	with => 'with',
 	pubOn => 'published on',
 	matchCount => '<%= num($found, "match", "matches") %>',
+	noMatches => 'There were no matches for <code><%= stash("q") %></code>.',
 	glimpse => 'Sample',
 	faq => 'F.A.Q.',
 	tutorial => 'Tutorial',
 	jsFile => 'kalamar-<%= $Kalamar::VERSION %>-en.js',
 	korap => {
 	  -short => 'KorAP',
-	  long => 'KorAP - Corpus Analysis Platform',
+	  desc => 'KorAP - Corpus Analysis Platform',
 	  overview => 'KorAP - Overview'
 	}
       }
diff --git a/lib/Kalamar.pm b/lib/Kalamar.pm
index aea95f5..d5fb248 100644
--- a/lib/Kalamar.pm
+++ b/lib/Kalamar.pm
@@ -36,7 +36,6 @@
     'Search',                 # Abstract Search framework
     'CHI',                    # Global caching mechanism
     'TagHelpers::Pagination', # Pagination widget
-    'Number::Commify',        # Localize numbers
     'KalamarHelpers'          # Specific Helpers for Kalamar
 
   ) {
@@ -74,3 +73,11 @@
 
 
 __END__
+
+=pod
+
+To get started, you'll need npm. Then you can install and run grunt:
+
+sudo npm install -g grunt-cli
+npm install
+grunt
diff --git a/lib/Kalamar/Controller/Search.pm b/lib/Kalamar/Controller/Search.pm
index 09ab580..13af8c5 100644
--- a/lib/Kalamar/Controller/Search.pm
+++ b/lib/Kalamar/Controller/Search.pm
@@ -10,7 +10,7 @@
 
   # No query
   unless ($query) {
-    return $c->render(template => 'intro');
+    return $c->render(template => $c->loc('template_intro', 'intro'));
   };
 
   # Base parameters for remote access
diff --git a/lib/Kalamar/Plugin/KalamarHelpers.pm b/lib/Kalamar/Plugin/KalamarHelpers.pm
index 5434cd1..be86f56 100644
--- a/lib/Kalamar/Plugin/KalamarHelpers.pm
+++ b/lib/Kalamar/Plugin/KalamarHelpers.pm
@@ -32,6 +32,8 @@
   );
 
   # Documentation link
+  # TODO: Support opener mechanism, so the link will open the embedded
+  # documentation in case it's not there.
   $mojo->helper(
     doc_link_to => sub {
       my $c = shift;
@@ -53,6 +55,24 @@
     }
   );
 
+  $mojo->helper(
+    doc_opener => sub {
+      my $c = shift;
+      my $cb = pop;
+      my $page = pop;
+      my $scope = shift;
+      my $url;
+      if ($page) {
+	$url = $c->url_for('doc', page => $page, scope => $scope);
+	$url->path->canonicalize;
+      }
+      else {
+	$url = $c->url_for('doc_start');
+      };
+      return $c->link_to($cb->($c), $url);
+    }
+  );
+
 
   # Documentation navigation helper
   $mojo->helper(
@@ -180,6 +200,14 @@
       $c->stash('kalamar.test_port' => 0);
       return 0;
     });
+
+  # Create links in the tutorial that make sure the current position is preserved,
+  # in case the tutorial was opened embedded
+  $mojo->helper(
+    kalamar_tut_link_to => sub {
+      return '[TODO]';
+    }
+  );
 };
 
 
diff --git a/t/doc.t b/t/doc.t
new file mode 100644
index 0000000..476d4bf
--- /dev/null
+++ b/t/doc.t
@@ -0,0 +1,27 @@
+use Mojo::Base -strict;
+use lib '../lib', 'lib';
+use Test::More;
+use Test::Mojo;
+
+# Test the documentation
+
+my $t = Test::Mojo->new('Kalamar');
+
+$t->get_ok('/doc/ql/poliqarp-plus')
+  ->status_is(200)
+  ->text_like('title', qr/poliqarp/i)
+  ->element_exists('aside.active')
+  ->element_exists('main.tutorial')
+  ->element_exists('header')
+  ->element_exists('aside nav')
+  ->content_is('');
+
+$t->get_ok('/doc/ql/poliqarp-plus?embedded=true')
+  ->status_is(200)
+  ->text_like('title', qr/poliqarp/i)
+  ->element_exists('aside.active')
+  ->element_exists('main.tutorial')
+  ->element_exists_not('header');
+
+
+done_testing();
diff --git a/t/docnavi.t b/t/docnavi.t
new file mode 100644
index 0000000..a9dc149
--- /dev/null
+++ b/t/docnavi.t
@@ -0,0 +1,211 @@
+use Mojo::Base -strict;
+use lib '../lib', 'lib';
+use Mojolicious::Lite;
+use Test::More;
+use Test::Mojo;
+
+my $t = Test::Mojo->new;
+my $app = $t->app;
+
+# Add additional plugin path
+push(@{$app->plugins->namespaces}, 'Kalamar::Plugin');
+
+# Establish test route
+$app->routes->get('/doc/(*scope)/:page')->to(cb => sub {})->name('doc');
+
+# Load plugin to test
+$app->plugin('KalamarHelpers');
+
+my $navi = [
+  {
+    id => 'korap',
+    title => 'KorAP'
+  }
+];
+
+my $render = $app->doc_navi($navi);
+like($render, qr!/doc/korap!, 'Path matches doc/korap');
+like($render, qr!KorAP!, 'Title matches');
+
+$navi = [
+  {
+    id => 'korap',
+    title => 'KorAP'
+  },
+  {
+    id => 'krill',
+    title => 'Krill'
+  }
+];
+
+$render = $app->doc_navi($navi);
+like($render, qr!/doc/korap!, 'Path matches doc/korap');
+like($render, qr!KorAP!, 'Title matches');
+like($render, qr!/doc/krill!, 'Path matches doc/krill');
+like($render, qr!Krill!, 'Title matches');
+
+$navi = [
+  {
+    id => 'korap',
+    title => 'KorAP',
+    items => [
+      {
+	id => 'krill',
+	title => 'Krill',
+      }
+    ]
+  },
+  {
+    id => 'faq',
+    title => 'F.A.Q.'
+  }
+];
+
+$render = $app->doc_navi($navi);
+like($render, qr!/doc/korap!, 'Path matches doc/korap');
+like($render, qr!/doc/korap/krill!, 'Path matches korap/krill');
+like($render, qr!/doc/faq!, 'Path matches doc/faq');
+
+$navi = [
+  {
+    id => 'korap',
+    title => 'KorAP',
+    items => [
+      {
+	id => 'krill',
+	title => 'Krill',
+      },
+      {
+	id => 'koral',
+	title => 'Koral'
+      }
+    ]
+  },
+  {
+    title => 'Query Languages',
+    id => 'ql',
+    items => [
+      {
+	title => 'Cosmas II',
+	id => 'cosmas2'
+      },
+      {
+	'title' => 'Poliqarp+',
+	'id' => 'poliqarp-plus',
+	items => [
+	  {
+	    "title" => "Simple Segments",
+	    "id" => "#segments"
+	  },
+	  {
+	    "title" => "Complex Segments",
+	    "id" => "#complex"
+	  }
+	]
+      }
+    ]
+  },
+  {
+    id => 'faq',
+    title => 'F.A.Q.'
+  }
+];
+
+$render = $app->doc_navi($navi);
+like($render, qr!/doc/korap!, 'Path matches doc/korap');
+like($render, qr!/doc/korap/krill!, 'Path matches korap/krill');
+like($render, qr!/doc/korap/koral!, 'Path matches korap/koral');
+like($render, qr!/doc/ql!, 'Path matches doc/ql');
+like($render, qr!/doc/ql/cosmas2!, 'Path matches doc/ql/cosmas2');
+like($render, qr!/doc/ql/poliqarp-plus!, 'Path matches doc/ql/poliqarp-plus');
+like($render, qr!/doc/ql/poliqarp-plus#segments!,
+     'Path matches doc/ql/poliqarp-plus#segments');
+like($render, qr!/doc/ql/poliqarp-plus#complex!,
+     'Path matches doc/ql/poliqarp-plus#complex');
+like($render, qr!/doc/faq!, 'Path matches doc/faq');
+
+
+my $c = $app->build_controller;
+$c->stash(page => 'korap');
+$render = $c->doc_navi($navi);
+like($render, qr!/doc/korap!, 'Path matches doc/korap');
+like($render, qr!/doc/korap/krill!, 'Path matches korap/krill');
+like($render, qr!/doc/ql!, 'Path matches doc/ql');
+like($render, qr!/doc/ql/poliqarp-plus#segments!,
+     'Path matches doc/ql/poliqarp-plus#segments');
+like($render, qr!/doc/ql/poliqarp-plus#complex!,
+     'Path matches doc/ql/poliqarp-plus#complex');
+like($render, qr!class="active".*?KorAP!, 'Active value for KorAP');
+
+$c->stash(page => 'poliqarp-plus');
+$render = $c->doc_navi($navi);
+like($render, qr!/doc/korap!, 'Path matches doc/korap');
+like($render, qr!/doc/korap/krill!, 'Path matches korap/krill');
+like($render, qr!/doc/ql!, 'Path matches doc/ql');
+like($render, qr!/doc/ql/poliqarp-plus#segments!,
+     'Path matches doc/ql/poliqarp-plus#segments');
+like($render, qr!/doc/ql/poliqarp-plus#complex!,
+     'Path matches doc/ql/poliqarp-plus#complex');
+like($render, qr!class="active".*?Poliqarp\+!, 'Active value for Poliqarp+');
+
+
+$navi = [
+  {
+    id => 'korap',
+    title => 'KorAP',
+    items => [
+      {
+	id => 'krill',
+	title => 'Krill',
+      },
+      {
+	id => 'koral',
+	title => 'Koral'
+      }
+    ]
+  },
+  {
+    title => 'Query Languages',
+    id => 'ql',
+    items => [
+      {
+	title => 'Cosmas II',
+	id => 'cosmas2'
+      },
+      {
+	'title' => 'Poliqarp+',
+	'id' => 'poliqarp-plus',
+	'class' => 'folded',
+	items => [
+	  {
+	    "title" => "Simple Segments",
+	    "id" => "#segments"
+	  },
+	  {
+	    "title" => "Complex Segments",
+	    "id" => "#complex"
+	  }
+	]
+      }
+    ]
+  },
+  {
+    id => 'faq',
+    title => 'F.A.Q.'
+  }
+];
+$render = $c->doc_navi($navi);
+
+like($render, qr!/doc/korap!, 'Path matches doc/korap');
+like($render, qr!/doc/korap/krill!, 'Path matches korap/krill');
+like($render, qr!/doc/ql!, 'Path matches doc/ql');
+like($render, qr!/doc/ql/poliqarp-plus#segments!,
+     'Path matches doc/ql/poliqarp-plus#segments');
+like($render, qr!/doc/ql/poliqarp-plus#complex!,
+     'Path matches doc/ql/poliqarp-plus#complex');
+like($render, qr!class="folded active".*?Poliqarp\+!, 'Active and folded value for Poliqarp+');
+
+done_testing;
+
+__END__
+
diff --git a/templates/partial/header.html.ep b/templates/partial/header.html.ep
index a994af1..d33e45d 100644
--- a/templates/partial/header.html.ep
+++ b/templates/partial/header.html.ep
@@ -1,7 +1,6 @@
 <header>
   <a href="/"
-     class="logo"
-     title="<%= title %>"><h1><span><%= title %></span></h1></a>
+     class="logo"><h1><span><%= title() // loc('korap_desc') %></span></h1></a>
   <div class="button top">
 <!--
     <a href="#"
diff --git a/templates/search.html.ep b/templates/search.html.ep
index b6f8d4d..eeb65a9 100644
--- a/templates/search.html.ep
+++ b/templates/search.html.ep
@@ -1,19 +1,19 @@
 % layout 'main', title => loc('searchtitle', q => search->query, ql => search->query_language);
 
 <div class="resultinfo">
-%#  <div id="pagination"><%= pagination(search->start_page, $pages, $url) =%></div>
+  <div id="pagination"><%= pagination(search->start_page, search->total_pages, url_with->query(['p' => '{page}'])) =%></div>
 
 % my $found = search->total_results;
 % if ($found != -1) {
-%   my $found_text = $found;
+%   my $found_text = loc('numf', number => $found);
 %   if (search->time_exceeded) {
-%     $found_text = '> ' . $found;
+%     $found_text = '> ' . $found_text;
 %   };
   <p class="found"><span id="total-results"><%= $found_text %></span> <%= loc('matchCount', found => $found) %></p>
+%# <% if (search->benchmark) { %> (~ <%= search->benchmark %>)<% } %>
 % } else {
   <p></p>
 % };
-%#   <% if (search->benchmark) { %> in <%= search->benchmark %><% } %>
 </div>
 
 % if (search->total_results != 0 && search->results->size) {
@@ -24,4 +24,6 @@
 %   end
   </ol>
 </div>
+% } else {
+<p id="no-results"><%== loc 'noMatches', q => search->query %></p>
 % }