diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml
index b88834e827c56c5baae20fd0684fb88b19886ce1..bdfde2a0eaa2b6a85494f07775e56a275798a51f 100644
--- a/.github/release-drafter.yml
+++ b/.github/release-drafter.yml
@@ -1,5 +1,6 @@
 references:
   - v+
+  - master
 name-template: 'v$RESOLVED_VERSION 🌈'
 tag-template: 'v$RESOLVED_VERSION'
 categories:
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..5f0ddaeb639e0ba85e3f3f87813a68fba4c0daec
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,13 @@
+FROM ruby:2.6
+
+ENV LC_ALL C.UTF-8
+ENV LANG en_US.UTF-8
+ENV LANGUAGE en_US.UTF-8
+
+WORKDIR /usr/src/app
+
+COPY Gemfile just-the-docs.gemspec ./
+RUN gem install bundler && bundle install
+
+EXPOSE 4000
+
diff --git a/README.md b/README.md
index 90dfb6fdbf4be746464c7fbb8e0f9ad585114e4a..4d1c1e889f5d6e5aaac95ed0899d7ec42c3a559f 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,10 @@ Or install it yourself as:
 
     $ gem install just-the-docs
 
+Alternatively, you can run it inside Docker while developing your site
+
+    $ docker-compose up
+
 ## Usage
 
 [View the documentation](https://pmarsceill.github.io/just-the-docs/) for usage information.
diff --git a/_config.yml b/_config.yml
index 51161b000743f051ac4bda0edb07e4eb90bfa0b3..a6f02ed04ad67af91e3504eb3873f773da35e7aa 100644
--- a/_config.yml
+++ b/_config.yml
@@ -16,7 +16,7 @@
 title: Just the Docs
 description: A Jekyll theme for documentation
 baseurl: "/just-the-docs" # the subpath of your site, e.g. /blog
-url: "https://pmarsceill.github.io" # the base hostname & protocol for your site, e.g. http://example.com
+url: "https://pdmosses.github.io" # the base hostname & protocol for your site, e.g. http://example.com
 
 permalink: pretty
 exclude: ["node_modules/", "*.gemspec", "*.gem", "Gemfile", "Gemfile.lock", "package.json", "package-lock.json",  "script/", "LICENSE.txt", "lib/", "bin/", "README.md", "Rakefile"
@@ -107,6 +107,11 @@ ga_tracking_anonymize_ip: true # Use GDPR compliant Google Analytics settings (t
 plugins:
   - jekyll-seo-tag
 
+kramdown:
+  syntax_highlighter_opts:
+    block:
+      line_numbers: false
+
 compress_html:
   clippings: all
   comments: all
@@ -114,3 +119,5 @@ compress_html:
   startings: []
   blanklines: false
   profile: false
+  # ignore:
+  #   envs: all
diff --git a/_includes/fix_linenos.html b/_includes/fix_linenos.html
new file mode 100644
index 0000000000000000000000000000000000000000..6243fb093e2c4433e956980548dc9ea5859e15a2
--- /dev/null
+++ b/_includes/fix_linenos.html
@@ -0,0 +1,65 @@
+{%- comment -%}
+This file can be used to fix the HTML produced by Jekyll for highlighted
+code with line numbers.
+
+It works with `{% highlight some_language linenos %}...{% endhighlight %}`
+and with the Kramdown option to add line numbers to fenced code.
+
+The implementation was derived from the workaround provided by 
+Dmitry Hrabrov (DeXP) at
+https://github.com/penibelst/jekyll-compress-html/issues/71#issuecomment-188144901
+
+EXPLANATION
+
+The HTML produced by Rouge highlighting with lie numbers is of the form
+`code table`. Jekyll (<= 4.1.1) always wraps the highlighted HTML
+with `pre`. This wrapping is not only unnecessary, but also transforms
+the conforming HTML produced by Rouge to non-conforming HTML, which
+results in HTML validation error reports. 
+
+The fix removes the outer `pre` tags whenever they contain the pattern
+`<table class="rouge-table">`.
+  
+Apart from avoiding HTML validation errors, the fix allows the use of
+the [Jekyll layout for compressing HTML](http://jch.penibelst.de),
+which relies on `pre` tags not being nested, according to
+https://github.com/penibelst/jekyll-compress-html/issues/71#issuecomment-172069842 
+
+USAGE
+
+(Any names can be used for `some_var` and `some_language`.)
+
+{% capture some_var %}
+{% highlight some_language linenos %}
+Some code
+{% endhighlight %}
+{% endcapture %}
+{% include fix_linenos.html code=some_var %}
+
+For code fences:
+
+{% capture some_var %}
+```some_language
+Some code
+```
+{% endcapture %}
+{% assign some_var = some_var | markdownify %}
+{% include fix_linenos.html code=some_var %}
+
+CAVEATS
+
+The above does not work when `Some code` happens to contain the matched string 
+`<table class="rouge-table">`.
+
+The use of this file overwrites the variable `fix_linenos_code` with `nil`.
+
+{%- endcomment -%}
+
+{% assign fix_linenos_code = include.code %}
+{% if fix_linenos_code contains '<table class="rouge-table">' %}
+  {% assign fix_linenos_code = fix_linenos_code | replace: '<pre class="highlight">', '<pre>' %}
+  {% assign fix_linenos_code = fix_linenos_code | replace: "<pre><code", "<code" %}
+  {% assign fix_linenos_code = fix_linenos_code | replace: "</code></pre>", "</code>" %}
+{% endif %}
+{{ fix_linenos_code }}
+{% assign fix_linenos_code = nil %}
diff --git a/_includes/head.html b/_includes/head.html
index 4f22497bb19f1c3cb3dff6771d3c8c8f37c63c3b..c0f73d7409de9ee518b6e166d106edb2b49a4c99 100644
--- a/_includes/head.html
+++ b/_includes/head.html
@@ -10,9 +10,9 @@
     {% endif %}
   {% endunless %}
 
-  <link rel="shortcut icon" href="{{ 'favicon.ico' | absolute_url }}" type="image/x-icon">
+  <link rel="shortcut icon" href="{{ 'favicon.ico' | relative_url }}" type="image/x-icon">
 
-  <link rel="stylesheet" href="{{ '/assets/css/just-the-docs-default.css' | absolute_url }}">
+  <link rel="stylesheet" href="{{ '/assets/css/just-the-docs-default.css' | relative_url }}">
 
   {% if site.ga_tracking != nil %}
     <script async src="https://www.googletagmanager.com/gtag/js?id={{ site.ga_tracking }}"></script>
@@ -27,9 +27,9 @@
   {% endif %}
 
   {% if site.search_enabled != false %}
-    <script type="text/javascript" src="{{ '/assets/js/vendor/lunr.min.js' | absolute_url }}"></script>
+    <script type="text/javascript" src="{{ '/assets/js/vendor/lunr.min.js' | relative_url }}"></script>
   {% endif %}
-  <script type="text/javascript" src="{{ '/assets/js/just-the-docs.js' | absolute_url }}"></script>
+  <script type="text/javascript" src="{{ '/assets/js/just-the-docs.js' | relative_url }}"></script>
 
   <meta name="viewport" content="width=device-width, initial-scale=1">
 
diff --git a/_includes/vendor/anchor_headings.html b/_includes/vendor/anchor_headings.html
index 985f448bff00b3b527a21d7d8e127d9d529c1c72..e9ca8626c7d6e40152dcab41d9e21e79bdf0323d 100755
--- a/_includes/vendor/anchor_headings.html
+++ b/_includes/vendor/anchor_headings.html
@@ -1,18 +1,44 @@
 {% capture headingsWorkspace %}
   {% comment %}
-    Version 1.0.3
+    Copyright (c) 2018 Vladimir "allejo" Jimenez
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use,
+    copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following
+    conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+    OTHER DEALINGS IN THE SOFTWARE.
+  {% endcomment %}
+  {% comment %}
+    Version 1.0.7
       https://github.com/allejo/jekyll-anchor-headings
 
     "Be the pull request you wish to see in the world." ~Ben Balter
 
     Usage:
-      {% include anchor_headings.html html=content %}
+      {% include anchor_headings.html html=content anchorBody="#" %}
 
     Parameters:
       * html          (string) - the HTML of compiled markdown generated by kramdown in Jekyll
 
     Optional Parameters:
       * beforeHeading (bool)   : false  - Set to true if the anchor should be placed _before_ the heading's content
+      * anchorAttrs   (string) :  ''    - Any custom HTML attributes that will be added to the `<a>` tag; you may NOT use `href`, `class` or `title`;
+                                          the `%heading%` and `%html_id%` placeholders are available
       * anchorBody    (string) :  ''    - The content that will be placed inside the anchor; the `%heading%` placeholder is available
       * anchorClass   (string) :  ''    - The class(es) that will be used for each anchor. Separate multiple classes with a space
       * anchorTitle   (string) :  ''    - The `title` attribute that will be used for anchors
@@ -42,17 +68,22 @@
     {% assign nextChar = node | replace: '"', '' | strip | slice: 0, 1 %}
     {% assign headerLevel = nextChar | times: 1 %}
 
-    <!-- If the level is cast to 0, it means it's not a h1-h6 tag, so let's try to fix it -->
+    <!-- If the level is cast to 0, it means it's not a h1-h6 tag, so let's see if we need to fix it -->
     {% if headerLevel == 0 %}
-      {% if nextChar != '<' and nextChar != '' %}
+      <!-- Split up the node based on closing angle brackets and get the first one. -->
+      {% assign firstChunk = node | split: '>' | first %}
+
+      <!-- If the first chunk does NOT contain a '<', that means we've broken another HTML tag that starts with 'h' -->
+      {% unless firstChunk contains '<' %}
         {% capture node %}<h{{ node }}{% endcapture %}
-      {% endif %}
+      {% endunless %}
 
       {% capture edited_headings %}{{ edited_headings }}{{ node }}{% endcapture %}
       {% continue %}
     {% endif %}
 
-    {% assign _workspace = node | split: '</h' %}
+    {% capture _closingTag %}</h{{ headerLevel }}>{% endcapture %}
+    {% assign _workspace = node | split: _closingTag %}
     {% assign _idWorkspace = _workspace[0] | split: 'id="' %}
     {% assign _idWorkspace = _idWorkspace[1] | split: '"' %}
     {% assign html_id = _idWorkspace[0] %}
@@ -64,7 +95,7 @@
     {% capture anchor %}{% endcapture %}
 
     {% if html_id and headerLevel >= minHeader and headerLevel <= maxHeader %}
-      {% capture anchor %}href="#{{ html_id}}" aria-labelledby="{{ html_id}}"{% endcapture %}
+      {% capture anchor %}href="#{{ html_id }}"{% endcapture %}
 
       {% if include.anchorClass %}
         {% capture anchor %}{{ anchor }} class="{{ include.anchorClass }}"{% endcapture %}
@@ -74,6 +105,10 @@
         {% capture anchor %}{{ anchor }} title="{{ include.anchorTitle | replace: '%heading%', header }}"{% endcapture %}
       {% endif %}
 
+      {% if include.anchorAttrs %}
+        {% capture anchor %}{{ anchor }} {{ include.anchorAttrs | replace: '%heading%', header | replace: '%html_id%', html_id }}{% endcapture %}
+      {% endif %}
+
       {% capture anchor %}<a {{ anchor }}>{{ include.anchorBody | replace: '%heading%', header | default: '' }}</a>{% endcapture %}
 
       <!-- In order to prevent adding extra space after a heading, we'll let the 'anchor' value contain it -->
@@ -93,8 +128,17 @@
           {{ header }}{{ anchor }}
         {% endif %}
         {{ include.bodySuffix }}
-      </h{{ _workspace | last }}
+      </h{{ headerLevel }}>
     {% endcapture %}
+
+    <!--
+    If we have content after the `</hX>` tag, then we'll want to append that here so we don't lost any content.
+    -->
+    {% assign chunkCount = _workspace | size %}
+    {% if chunkCount > 1 %}
+      {% capture new_heading %}{{ new_heading }}{{ _workspace | last }}{% endcapture %}
+    {% endif %}
+
     {% capture edited_headings %}{{ edited_headings }}{{ new_heading }}{% endcapture %}
   {% endfor %}
 {% endcapture %}{% assign headingsWorkspace = '' %}{{ edited_headings | strip }}
diff --git a/_layouts/default.html b/_layouts/default.html
index 1d41a7115a90ff3a234df067ec502dbbf7bef426..4c48ae70f511268cd309a9ec79514335e8e8cd83 100644
--- a/_layouts/default.html
+++ b/_layouts/default.html
@@ -48,7 +48,22 @@ layout: table_wrappers
       </a>
     </div>
     <nav role="navigation" aria-label="Main" id="site-nav" class="site-nav">
-      {% include nav.html %}
+      {% if site.just_the_docs.collections %}
+        {% assign collections_size = site.just_the_docs.collections | size %}
+        {% for collection_entry in site.just_the_docs.collections %}
+          {% assign collection_key = collection_entry[0] %}
+          {% assign collection_value = collection_entry[1] %}
+          {% assign collection = site[collection_key] %}
+          {% if collection_value.nav_exclude != true %}
+            {% if collections_size > 1 %}
+              <div class="nav-category">{{ collection_value.name }}</div>
+            {% endif %}
+            {% include nav.html pages=collection %}
+          {% endif %}
+        {% endfor %}
+      {% else %}
+        {% include nav.html pages=site.html_pages %}
+      {% endif %}
     </nav>
     <footer class="site-footer">
       This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.
@@ -101,7 +116,7 @@ layout: table_wrappers
       {% endunless %}
       <div id="main-content" class="main-content" role="main">
         {% if site.heading_anchors != false %}
-          {% include vendor/anchor_headings.html html=content beforeHeading="true" anchorBody="<svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><use xlink:href=\"#svg-link\"></use></svg>" anchorClass="anchor-heading" %}
+          {% include vendor/anchor_headings.html html=content beforeHeading="true" anchorBody="<svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><use xlink:href=\"#svg-link\"></use></svg>" anchorClass="anchor-heading" anchorAttrs="aria-labelledby=\"%html_id%\"" %}
         {% else %}
           {{ content }}
         {% endif %}
diff --git a/_sass/code.scss b/_sass/code.scss
index affc8aa42f432458e207dfec32f79146167a6c61..ead2c5f5f3d371c84a2091f59c58ab721a93e2da 100644
--- a/_sass/code.scss
+++ b/_sass/code.scss
@@ -11,23 +11,96 @@ code {
   border-radius: $border-radius;
 }
 
-pre.highlight,
-figure.highlight {
+// Content structure for highlighted code blocks using fences or Liquid
+//
+// ```[LANG]...```, no kramdown line_numbers:
+//   div.[language-LANG.]highlighter-rouge > div.highlight > pre.highlight > code
+//
+// ```[LANG]...```, kramdown line_numbers = true:
+//   div.[language-LANG.]highlighter-rouge > div.highlight > pre.highlight > code
+//   > div.table-wrapper > table.rouge-table > tbody > tr
+//   > td.rouge-gutter.gl > pre.lineno
+//   | td.rouge-code > pre
+//
+// {% highlight LANG %}...{% endhighlight %}:
+//   figure.highlight > pre > code.language-LANG
+//
+// {% highlight LANG linenos %}...{% endhighlight %}:
+//   figure.highlight > pre > code.language-LANG
+//   > div.table-wrapper > table.rouge-table > tbody > tr
+//   > td.gutter.gl > pre.lineno
+//   | td.code > pre
+//
+// fix_linenos removes the outermost pre when it encloses table.rouge-table
+//
+// See docs/index-test.md for some tests.
+//
+// No kramdown line_numbers: fences and Liquid highlighting look the same.
+// Kramdown line_numbers = true: fences have a wider gutter than with Liquid?
+
+// ```[LANG]...```
+div.highlighter-rouge {
   padding: $sp-3;
   margin-top: 0;
-  margin-bottom: 0;
+  margin-bottom: $sp-3;
   background-color: $code-background-color;
   border-radius: $border-radius;
+  box-shadow: none;
   -webkit-overflow-scrolling: touch;
 
+  div.highlight,
+  pre.highlight,
   code {
     padding: 0;
+    margin: 0;
     border: 0;
   }
 }
 
-.highlighter-rouge {
+// {% highlight LANG %}...{% endhighlight %},
+// {% highlight LANG linenos %}...{% endhighlight %}:
+figure.highlight {
+  padding: $sp-3;
+  margin-top: 0;
   margin-bottom: $sp-3;
+  background-color: $code-background-color;
+  border-radius: $border-radius;
+  box-shadow: none;
+  -webkit-overflow-scrolling: touch;
+
+  pre,
+  code {
+    padding: 0;
+    margin: 0;
+    border: 0;
+  }
+}
+
+// ```[LANG]...```, kramdown line_numbers = true,
+// {% highlight LANG linenos %}...{% endhighlight %}:
+.highlight .table-wrapper {
+  padding: 0;
+  margin: 0;
+  border: 0;
+  box-shadow: none;
+
+  td,
+  pre {
+    @include fs-2;
+    min-width: 0;
+    padding: 0;
+    background-color: $code-background-color;
+    border: 0;
+  }
+
+  td.gl {
+    padding-right: $sp-3;
+  }
+
+  pre {
+    margin: 0;
+    line-height: 2;
+  }
 }
 
 .highlight .c {
diff --git a/_sass/content.scss b/_sass/content.scss
index 113e7334900440b7e454f630d38d271f1c7c7d08..bc906edd9621767491ebbe75a12b9019a486e0c4 100644
--- a/_sass/content.scss
+++ b/_sass/content.scss
@@ -109,7 +109,7 @@
 
   dl {
     display: grid;
-    grid-template-columns: max-content 1fr;
+    grid-template: auto / 10em 1fr;
   }
 
   dt,
@@ -118,16 +118,18 @@
   }
 
   dt {
+    grid-column: 1;
+    font-weight: 500;
     text-align: right;
-
     &::after {
       content: ":";
     }
   }
 
   dd {
+    grid-column: 2;
+    margin-bottom: 0;
     margin-left: 1em;
-    font-weight: 500;
   }
 
   .anchor-heading {
diff --git a/_sass/navigation.scss b/_sass/navigation.scss
index 0417b4c40d6c0b0c5cfbda16da8d89d8853c6116..521c15fa152a0973a5273f14c423b3328306ff30 100644
--- a/_sass/navigation.scss
+++ b/_sass/navigation.scss
@@ -131,6 +131,29 @@
   }
 }
 
+.nav-category {
+  padding-top: $sp-2;
+  padding-right: $gutter-spacing-sm;
+  padding-bottom: $sp-2;
+  padding-left: $gutter-spacing-sm;
+  font-weight: 600;
+  text-align: end;
+  text-transform: uppercase;
+  border-bottom: $border $border-color;
+  @include fs-2;
+
+  @include mq(md) {
+    padding-right: $gutter-spacing;
+    padding-left: $gutter-spacing;
+    margin-top: $gutter-spacing-sm;
+    text-align: start;
+
+    &:first-child {
+      margin-top: 0;
+    }
+  }
+}
+
 // Aux nav
 
 .aux-nav {
diff --git a/_sass/support/_variables.scss b/_sass/support/_variables.scss
index b97b14e808b1ec8a8a21bba4a6c2dfbba535d597..a185e5e96a5a6940bf67af7b13ad36eabe7dc548 100644
--- a/_sass/support/_variables.scss
+++ b/_sass/support/_variables.scss
@@ -2,14 +2,32 @@
 // Typography
 //
 
-$body-font-family: -apple-system, BlinkMacSystemFont, "helvetica neue",
-  helvetica, roboto, noto, "segoe ui", arial, sans-serif !default;
+$body-font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
+  Roboto, "Helvetica Neue", Arial, sans-serif !default;
 $mono-font-family: "SFMono-Regular", Menlo, Consolas, Monospace !default;
 $root-font-size: 16px !default; // Base font-size for rems
 $body-line-height: 1.4 !default;
 $content-line-height: 1.6 !default;
 $body-heading-line-height: 1.25 !default;
 
+//
+// Font size
+// `-sm` suffix is the size at the small (and above) media query
+//
+
+$font-size-1: 9px !default;
+$font-size-1-sm: 10px !default;
+$font-size-2: 11px !default; //h4 - uppercased!, h6 not uppercased, text-small
+$font-size-3: 12px !default; //h5
+$font-size-4: 15px !default;
+$font-size-5: 16px !default; //h3
+$font-size-6: 18px !default; //h2
+$font-size-7: 24px !default;
+$font-size-8: 32px !default; //h1
+$font-size-9: 36px !default;
+$font-size-10: 42px !default;
+$font-size-10-sm: 48px !default;
+
 //
 // Colors
 //
diff --git a/_sass/support/mixins/_typography.scss b/_sass/support/mixins/_typography.scss
index 1718a932f575bfa81f44b6c419ceda443f4f01e2..5207fcd13ac46ff818f870c00dedf647bfc4d206 100644
--- a/_sass/support/mixins/_typography.scss
+++ b/_sass/support/mixins/_typography.scss
@@ -1,86 +1,84 @@
-// Font size
-
 @mixin fs-1 {
-  font-size: 9px !important;
+  font-size: $font-size-1 !important;
 
   @include mq(sm) {
-    font-size: 10px !important;
+    font-size: $font-size-1-sm !important;
   }
 }
 
 @mixin fs-2 {
-  font-size: 11px !important;
+  font-size: $font-size-2 !important;
 
   @include mq(sm) {
-    font-size: 12px !important;
+    font-size: $font-size-3 !important;
   }
 }
 
 @mixin fs-3 {
-  font-size: 12px !important;
+  font-size: $font-size-3 !important;
 
   @include mq(sm) {
-    font-size: 14px !important;
+    font-size: $font-size-4 !important;
   }
 }
 
 @mixin fs-4 {
-  font-size: 15px !important;
+  font-size: $font-size-4 !important;
 
   @include mq(sm) {
-    font-size: 16px !important;
+    font-size: $font-size-5 !important;
   }
 }
 
 @mixin fs-5 {
-  font-size: 16px !important;
+  font-size: $font-size-5 !important;
 
   @include mq(sm) {
-    font-size: 18px !important;
+    font-size: $font-size-6 !important;
   }
 }
 
 @mixin fs-6 {
-  font-size: 18px !important;
+  font-size: $font-size-6 !important;
 
   @include mq(sm) {
-    font-size: 24px !important;
+    font-size: $font-size-7 !important;
     line-height: $body-heading-line-height;
   }
 }
 
 @mixin fs-7 {
-  font-size: 24px !important;
+  font-size: $font-size-7 !important;
   line-height: $body-heading-line-height;
 
   @include mq(sm) {
-    font-size: 32px !important;
+    font-size: $font-size-8 !important;
   }
 }
 
 @mixin fs-8 {
-  font-size: 32px !important;
+  font-size: $font-size-8 !important;
   line-height: $body-heading-line-height;
 
   @include mq(sm) {
-    font-size: 36px !important;
+    font-size: $font-size-9 !important;
   }
 }
 
 @mixin fs-9 {
-  font-size: 36px !important;
+  font-size: $font-size-9 !important;
   line-height: $body-heading-line-height;
 
   @include mq(sm) {
-    font-size: 42px !important;
+    font-size: $font-size-10 !important;
   }
 }
 
 @mixin fs-10 {
-  font-size: 42px !important;
+  font-size: $font-size-10 !important;
   line-height: $body-heading-line-height;
 
   @include mq(sm) {
-    font-size: 48px !important;
+    font-size: $font-size-10-sm !important;
   }
 }
diff --git a/_sass/typography.scss b/_sass/typography.scss
index 3749d43b334e0efc8c5f606a006f4e9f4a6fc968..cadee362dcfd8da77fc9b5cbdccb93283cc83d3b 100644
--- a/_sass/typography.scss
+++ b/_sass/typography.scss
@@ -27,6 +27,10 @@ h4,
   letter-spacing: 0.1em;
 }
 
+h4 code {
+  text-transform: none;
+}
+
 h5,
 .text-epsilon {
   @include fs-3;
diff --git a/assets/js/zzzz-search-data.json b/assets/js/zzzz-search-data.json
index 0a6c3e5c89046ea68923a53cec7d7f5e7b2794fe..6235244d31dbe00641446e906bdf5d38ded9c9fa 100644
--- a/assets/js/zzzz-search-data.json
+++ b/assets/js/zzzz-search-data.json
@@ -2,8 +2,21 @@
 permalink: /assets/js/search-data.json
 ---
 {
-  {%- assign i = 0 -%}
-  {% for page in site.html_pages %}
+{%- assign i = 0 -%}
+{%- assign pages_array = '' | split: '' -%}
+{%- assign pages_array = pages_array | push: site.html_pages -%}
+{%- if site.just_the_docs.collections -%}
+  {%- for collection_entry in site.just_the_docs.collections -%}
+    {%- assign collection_key = collection_entry[0] -%}
+    {%- assign collection_value = collection_entry[1] -%}
+    {%- assign collection = site[collection_key] -%}
+    {%- if collection_value.search_exclude != true -%}
+      {%- assign pages_array = pages_array | push: collection -%}
+    {%- endif -%}
+  {%- endfor -%}
+{%- endif -%}
+{%- for pages in pages_array -%}
+  {%- for page in pages -%}
     {%- if page.title and page.search_exclude != true -%}
       {%- assign page_content = page.content -%}
       {%- assign heading_level = site.search.heading_level | default: 2 -%}
@@ -14,7 +27,7 @@ permalink: /assets/js/search-data.json
       {%- endfor -%}
       {%- assign parts = page_content | split: '<h1' -%}
       {%- assign title_found = false -%}
-      {% for part in parts offset: 1 %}
+      {%- for part in parts offset: 1 -%}
         {%- assign titleAndContent = part | split: '</h1>' -%}
         {%- assign title = titleAndContent[0] | replace_first: '>', '<h1>' | split: '<h1>' -%}
         {%- assign title = title[1] | strip_html -%}
@@ -54,5 +67,6 @@ permalink: /assets/js/search-data.json
         {%- assign i = i | plus: 1 -%}
       {%- endunless -%}
     {%- endif -%}
-  {% endfor %}
+  {%- endfor -%}
+{%- endfor %}
 }
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..576c7ed3620ad8c71e2e360fe64145f69458b64e
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,14 @@
+version: "3.5"
+
+services:
+  jekyll:
+    build:
+      context: ./
+    ports:
+      - 4000:4000
+    volumes:
+      - .:/usr/src/app
+    stdin_open: true
+    tty: true
+    command: bundle exec jekyll serve -H 0.0.0.0 -t
+
diff --git a/docs/configuration.md b/docs/configuration.md
index 65471d23c75d7e5d2d4d8d69b86ad72f2c5fc325..8b5cb9781f857b300ed212a3c1c9b9d0bb7b34d6 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -22,6 +22,54 @@ Just the Docs has some specific configuration parameters that can be defined in
 
 View this site's [_config.yml](https://github.com/pmarsceill/just-the-docs/tree/master/_config.yml) file as an example.
 
+## Document collections
+
+By default, the navigation and search include normal [pages](https://jekyllrb.com/docs/pages/).
+Instead, you can also use [Jekyll collections](https://jekyllrb.com/docs/collections/) which group documents semantically together.
+
+For example, put all your documentation files in the `_docs` folder and create the `docs` collection:
+```yaml
+# Define Jekyll collections
+collections:
+  # Define a collection named "docs", its documents reside in the "_docs" directory
+  docs:
+    permalink: "/:collection/:path/"
+    output: true
+
+just_the_docs:
+  # Define which collections are used in just-the-docs
+  collections:
+    # Reference the "docs" collection
+    docs:
+      # Give the collection a name
+      name: Documentation
+      # Exclude the collection from the navigation
+      # Supports true or false (default)
+      nav_exclude: false
+      # Exclude the collection from the search
+      # Supports true or false (default)
+      search_exclude: false
+```
+
+You can reference multiple collections.
+This creates categories in the navigation with the configured names.
+```yaml
+collections:
+  docs:
+    permalink: "/:collection/:path/"
+    output: true
+  tutorials:
+    permalink: "/:collection/:path/"
+    output: true
+
+just_the_docs:
+  collections:
+    docs:
+      name: Documentation
+    tutorials:
+      name: Tutorials
+```
+
 ## Site logo
 
 ```yaml
diff --git a/docs/index-test.md b/docs/index-test.md
index 967ba6f6e5590c4702b0a4163a0b6a3819c7fc3a..8a9046a8ca557514ea5794885a5bc69edb9d7303 100644
--- a/docs/index-test.md
+++ b/docs/index-test.md
@@ -39,7 +39,7 @@ GitHubPages::Dependencies.gems.each do |gem, version|
 end
 ```
 
-#### [](#header-4)Header 4
+#### [](#header-4)Header 4 `with code not transformed`
 
 *   This is an unordered list following a header.
 *   This is an unordered list following a header.
@@ -140,6 +140,37 @@ end
 <dd>Green</dd>
 </dl>
 
+#### Multiple description terms and values
+
+Term
+: Brief description of Term
+
+Longer Term
+: Longer description of Term,
+  possibly more than one line
+
+Term
+: First description of Term,
+  possibly more than one line
+
+: Second description of Term,
+  possibly more than one line
+
+Term1
+Term2
+: Single description of Term1 and Term2,
+  possibly more than one line
+
+Term1
+Term2
+: First description of Term1 and Term2,
+  possibly more than one line
+
+: Second description of Term1 and Term2,
+  possibly more than one line
+  
+### More code
+
 ```
 Long, single-line code blocks should not wrap. They should horizontally scroll if they are too long. This line should be long enough to demonstrate this.
 ```
diff --git a/docs/ui-components/code.md b/docs/ui-components/code.md
index e53a90de42fefdd9117d9771d62051776299688a..b8136a3508d6cb45c6b5f2e8f91b98dbb2849ae7 100644
--- a/docs/ui-components/code.md
+++ b/docs/ui-components/code.md
@@ -2,6 +2,7 @@
 layout: default
 title: Code
 parent: UI Components
+has_children: true
 nav_order: 6
 ---
 
diff --git a/docs/ui-components/linenos.md b/docs/ui-components/linenos.md
new file mode 100644
index 0000000000000000000000000000000000000000..b13e6c91a70afe210c0faff98e4888b9ac8c8549
--- /dev/null
+++ b/docs/ui-components/linenos.md
@@ -0,0 +1,124 @@
+---
+layout: default
+title: Code with line numbers
+parent: Code
+grand_parent: UI Components
+---
+
+# Configuration options
+
+The default settings for HTML compression are incompatible with the HTML
+produced by Jekyll (4.1.1 or earlier) for line numbers from highlighted code
+-- both when using Kramdown code fences and when using Liquid highlight tags.
+
+To avoid non-conforming HTML and unsatisfactory layout, HTML compression
+can be turned off by using the following configuration option:
+
+{% highlight yaml %}
+compress_html:
+  ignore:
+    envs: all
+{% endhighlight %}
+
+When using Kramdown code fences, line numbers are turned on globally by the
+following configuration option:
+
+{% highlight yaml %}
+kramdown:
+  syntax_highlighter_opts:
+    block:
+      line_numbers: false
+{% endhighlight %}
+
+Line numbers can then be suppressed locally using Liquid tags (_without_ the
+`linenos` option) instead of fences:
+
+{% highlight yaml %}
+{% raw %}{% highlight some_language %}
+Some code
+{% endhighlight %}{% endraw %}
+{% endhighlight %}
+
+# Workarounds
+
+To use HTML compression together with line numbers, all highlighted code
+needs to be wrapped using one of the following workarounds.
+(The variable name `some_var` can be changed to avoid clashes; it can also
+be replaced by `code` -- but note that `code=code` cannot be removed).
+
+## Code fences
+
+{% highlight default %}
+{% raw %}{% capture some_var %}
+```some_language
+Some code
+```
+{% endcapture %}
+{% assign some_var = some_var | markdownify %}
+{% include fix_linenos.html code=some_var %}{% endraw %}
+{% endhighlight %}
+
+## Liquid highlighting
+
+{% highlight default %}
+{% raw %}{% capture some_var %}
+{% highlight some_language linenos %}
+Some code
+{% endhighlight %}
+{% endcapture %}
+{% include fix_linenos.html code=some_var %}{% endraw %}
+{% endhighlight %}
+
+_Credit:_ The original version of the above workaround was suggested by
+Dmitry Hrabrov at
+<https://github.com/penibelst/jekyll-compress-html/issues/71#issuecomment-188144901>.
+
+# Examples
+
+```
+Some unknown code in fences
+```
+
+```js
+// Javascript code with syntax highlighting in fences
+var fun = function lang(l) {
+  dateformat.i18n = require('./lang/' + l)
+  return true;
+}
+```
+
+```ruby
+# Ruby code with syntax highlighting in fences
+GitHubPages::Dependencies.gems.each do |gem, version|
+  s.add_dependency(gem, "= #{version}")
+end
+```
+
+{% highlight ruby %}
+# Ruby code with syntax highlighting using Liquid
+GitHubPages::Dependencies.gems.each do |gem, version|
+  s.add_dependency(gem, "= #{version}")
+end
+{% endhighlight %}
+
+{% capture code %}
+{% highlight ruby linenos %}
+# Ruby code with syntax highlighting and fixed line numbers using Liquid
+GitHubPages::Dependencies.gems.each do |gem, version|
+  s.add_dependency(gem, "= #{version}")
+end
+{% endhighlight %}
+{% endcapture %}
+{% include fix_linenos.html code=code %}
+{% assign code = nil %}
+
+With the default configuration options, the following example illustrates
+the incorrect formatting arising from the incompatibility of HTML compression
+and the non-conforming HTML produced by Jekyll for line numbers:
+
+{% highlight ruby linenos %}
+# Ruby code with syntax highlighting and unfixed line numbers using Liquid
+GitHubPages::Dependencies.gems.each do |gem, version|
+  s.add_dependency(gem, "= #{version}")
+end
+{% endhighlight %}
diff --git a/docs/ui-components/typography.md b/docs/ui-components/typography.md
index 2838a795fff7a83c2250204d8e83e1a1969b489d..b879c95299a0406bac8d5e4917bf3acd7e5e1d0a 100644
--- a/docs/ui-components/typography.md
+++ b/docs/ui-components/typography.md
@@ -21,7 +21,7 @@ nav_order: 1
 By default, Just the Docs uses a native system font stack for sans-serif fonts:
 
 ```scss
--apple-system, BlinkMacSystemFont, "helvetica neue", helvetica, roboto, noto, "segoe ui", arial, sans-serif
+system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif
 ```
 
 ABCDEFGHIJKLMNOPQRSTUVWXYZ
diff --git a/just-the-docs.gemspec b/just-the-docs.gemspec
index c41ddaacbcf36c1ec97c01d6dee35e69314fede8..6d6d47e0900b255d695ff5d7bb54b755fd456d12 100644
--- a/just-the-docs.gemspec
+++ b/just-the-docs.gemspec
@@ -2,12 +2,12 @@
 
 Gem::Specification.new do |spec|
   spec.name          = "just-the-docs"
-  spec.version       = "0.3.1"
+  spec.version       = "0.3.2"
   spec.authors       = ["Patrick Marsceill"]
   spec.email         = ["patrick.marsceill@gmail.com"]
 
   spec.summary       = %q{A modern, highly customizable, and responsive Jekyll theme for documention with built-in search.}
-  spec.homepage      = "https://github.com/pmarsceill/just-the-docs"
+  spec.homepage      = "https://github.com/pdmosses/just-the-docs"
   spec.license       = "MIT"
 
   spec.files         = `git ls-files -z`.split("\x0").select { |f| f.match(%r{^(assets|bin|_layouts|_includes|lib|Rakefile|_sass|LICENSE|README)}i) }
diff --git a/lib/tasks/search.rake b/lib/tasks/search.rake
index 8e6305a6115a4f4f642ec859222b722b12dd5ef3..aac66bb6877b5c33c73d3d4ba66ebe0fc66e417f 100644
--- a/lib/tasks/search.rake
+++ b/lib/tasks/search.rake
@@ -12,8 +12,21 @@ namespace :search do
 permalink: /assets/js/search-data.json
 ---
 {
-  {%- assign i = 0 -%}
-  {% for page in site.html_pages %}
+{%- assign i = 0 -%}
+{%- assign pages_array = '' | split: '' -%}
+{%- assign pages_array = pages_array | push: site.html_pages -%}
+{%- if site.just_the_docs.collections -%}
+  {%- for collection_entry in site.just_the_docs.collections -%}
+    {%- assign collection_key = collection_entry[0] -%}
+    {%- assign collection_value = collection_entry[1] -%}
+    {%- assign collection = site[collection_key] -%}
+    {%- if collection_value.search_exclude != true -%}
+      {%- assign pages_array = pages_array | push: collection -%}
+    {%- endif -%}
+  {%- endfor -%}
+{%- endif -%}
+{%- for pages in pages_array -%}
+  {%- for page in pages -%}
     {%- if page.title and page.search_exclude != true -%}
       {%- assign page_content = page.content -%}
       {%- assign heading_level = site.search.heading_level | default: 2 -%}
@@ -24,7 +37,7 @@ permalink: /assets/js/search-data.json
       {%- endfor -%}
       {%- assign parts = page_content | split: \'<h1\' -%}
       {%- assign title_found = false -%}
-      {% for part in parts offset: 1 %}
+      {%- for part in parts offset: 1 -%}
         {%- assign titleAndContent = part | split: \'</h1>\' -%}
         {%- assign title = titleAndContent[0] | replace_first: \'>\', \'<h1>\' | split: \'<h1>\' -%}
         {%- assign title = title[1] | strip_html -%}
@@ -47,7 +60,7 @@ permalink: /assets/js/search-data.json
     "doc": {{ page.title | jsonify }},
     "title": {{ title | jsonify }},
     "content": {{ content | replace: \'</h\', \' . </h\' | replace: \'<hr\', \' . <hr\' | replace: \'</p\', \' . </p\' | replace: \'<ul\', \' . <ul\' | replace: \'</ul\', \' . </ul\' | replace: \'<ol\', \' . <ol\' | replace: \'</ol\', \' . </ol\' | replace: \'</tr\', \' . </tr\' | replace: \'<li\', \' | <li\' | replace: \'</li\', \' | </li\' | replace: \'</td\', \' | </td\' | replace: \'<td\', \' | <td\' | replace: \'</th\', \' | </th\' | replace: \'<th\', \' | <th\' | strip_html | remove: \'Table of contents\' | normalize_whitespace | replace: \'. . .\', \'.\' | replace: \'. .\', \'.\' | replace: \'| |\', \'|\' | append: \' \' | jsonify }},
-    "url": "{{ url | absolute_url }}",
+    "url": "{{ url | relative_url }}",
     "relUrl": "{{ url }}"
   }
         {%- assign i = i | plus: 1 -%}
@@ -58,13 +71,14 @@ permalink: /assets/js/search-data.json
     "doc": {{ page.title | jsonify }},
     "title": {{ page.title | jsonify }},
     "content": {{ parts[0] | replace: \'</h\', \' . </h\' | replace: \'<hr\', \' . <hr\' | replace: \'</p\', \' . </p\' | replace: \'<ul\', \' . <ul\' | replace: \'</ul\', \' . </ul\' | replace: \'<ol\', \' . <ol\' | replace: \'</ol\', \' . </ol\' | replace: \'</tr\', \' . </tr\' | replace: \'<li\', \' | <li\' | replace: \'</li\', \' | </li\' | replace: \'</td\', \' | </td\' | replace: \'<td\', \' | <td\' | replace: \'</th\', \' | </th\' | replace: \'<th\', \' | <th\' | strip_html | remove: \'Table of contents\' | normalize_whitespace | replace: \'. . .\', \'.\' | replace: \'. .\', \'.\' | replace: \'| |\', \'|\' | append: \' \' | jsonify }},
-    "url": "{{ page.url | absolute_url }}",
+    "url": "{{ page.url | relative_url }}",
     "relUrl": "{{ page.url }}"
   }
         {%- assign i = i | plus: 1 -%}
       {%- endunless -%}
     {%- endif -%}
-  {% endfor %}
+  {%- endfor -%}
+{%- endfor %}
 }'
     end
     puts 'Done.'
diff --git a/package-lock.json b/package-lock.json
index 9aa116972f476a2e4409233300b5d227c2ba1abf..1c7aeaf12a58d63516a9c1dba0792be12646a829 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "just-the-docs",
-  "version": "0.3.0",
+  "version": "0.3.1",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -276,9 +276,9 @@
       }
     },
     "@primer/css": {
-      "version": "14.4.0",
-      "resolved": "https://registry.npmjs.org/@primer/css/-/css-14.4.0.tgz",
-      "integrity": "sha512-o9DwcAH43jZNDC/rPLjsYTU/I1LsHIgIQlSO3X8vZV2u65LmWeA5jHI2cSadZYN3N0Gm0Soh0zVYuhh7kMskXA==",
+      "version": "15.1.0",
+      "resolved": "https://registry.npmjs.org/@primer/css/-/css-15.1.0.tgz",
+      "integrity": "sha512-UmmfjwA26FhOGBMuAfJQOBeRHz9YUcw7khPtifp7K+VyTDEhLnJPRTdApxtivH69vHTkSJ3rh/W1gWYolrLgVA==",
       "dev": true,
       "requires": {
         "@primer/octicons": "^9.1.1"
@@ -2831,9 +2831,9 @@
       }
     },
     "lodash": {
-      "version": "4.17.15",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+      "version": "4.17.19",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+      "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
       "dev": true
     },
     "log-symbols": {
@@ -3753,9 +3753,9 @@
       "dev": true
     },
     "prettier": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz",
-      "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==",
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.1.tgz",
+      "integrity": "sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw==",
       "dev": true
     },
     "prettier-linter-helpers": {
diff --git a/package.json b/package.json
index 49fd3df10e0f20ac2ada893eaa2380a0b57e40eb..5b4868422cda079b446afa7273b6057f1e12a2f7 100644
--- a/package.json
+++ b/package.json
@@ -1,13 +1,13 @@
 {
   "name": "just-the-docs",
-  "version": "0.3.1",
+  "version": "0.3.2",
   "description": "A modern Jekyll theme for documentation",
   "repository": "pmarsceill/just-the-docs",
   "license": "MIT",
   "bugs": "https://github.com/pmarsceill/just-the-docs/issues",
   "devDependencies": {
-    "@primer/css": "^14.4.0",
-    "prettier": "^2.0.5",
+    "@primer/css": "^15.1.0",
+    "prettier": "^2.1.1",
     "stylelint": "^13.6.1",
     "stylelint-config-prettier": "^8.0.2",
     "stylelint-config-primer": "^9.0.0",