From 19d28342f09a798dddfd54800d90117446783c36 Mon Sep 17 00:00:00 2001
From: "minseok.park" <minseok.park@bankwareglobal.com>
Date: Thu, 11 Apr 2024 12:34:31 +0900
Subject: [PATCH] ui bundle test

---
 antora-playbook.yml               |    3 +-
 src/css/base.css                  |  149 ++++
 src/css/body.css                  |    5 +
 src/css/breadcrumbs.css           |   38 +
 src/css/doc.css                   | 1087 +++++++++++++++++++++++++++++
 src/css/footer.css                |   15 +
 src/css/header.css                |  327 +++++++++
 src/css/highlight.css             |  172 +++--
 src/css/main.css                  |   39 ++
 src/css/nav.css                   |  285 ++++++++
 src/css/page-versions.css         |   56 ++
 src/css/pagination.css            |   63 ++
 src/css/print.css                 |   88 +++
 src/css/site.css                  |   17 +
 src/css/toc.css                   |   98 +++
 src/css/toolbar.css               |   68 ++
 src/css/typeface-roboto-mono.css  |   39 ++
 src/css/typeface-roboto.css       |   71 ++
 src/css/vars.css                  |  146 ++++
 src/helpers/and.js                |    9 +
 src/helpers/detag.js              |    5 +
 src/helpers/eq.js                 |    3 +
 src/helpers/increment.js          |    3 +
 src/helpers/ne.js                 |    3 +
 src/helpers/not.js                |    3 +
 src/helpers/or.js                 |    9 +
 src/helpers/relativize.js         |   24 +
 src/helpers/year.js               |    3 +
 src/img/back.svg                  |   86 +++
 src/img/caret.svg                 |   63 ++
 src/img/chevron.svg               |   63 ++
 src/img/home-o.svg                |  124 ++++
 src/img/home.svg                  |  124 ++++
 src/img/menu.svg                  |  158 +++++
 src/img/octicons-16.svg           |   51 ++
 src/js/01-nav.js                  |  175 +++++
 src/js/02-on-this-page.js         |  115 +++
 src/js/03-fragment-jumper.js      |   43 ++
 src/js/04-page-versions.js        |   17 +
 src/js/05-mobile-navbar.js        |   20 +
 src/js/06-copy-to-clipboard.js    |   80 +++
 src/js/vendor/highlight.bundle.js |   43 ++
 src/layouts/404.hbs               |   11 +
 src/layouts/default.hbs           |   11 +
 src/partials/article-404.hbs      |   10 +
 src/partials/article.hbs          |    7 +
 src/partials/body.hbs             |    4 +
 src/partials/breadcrumbs.hbs      |   20 +
 src/partials/edit-this-page.hbs   |    5 +
 src/partials/footer-content.hbs   |    4 +
 src/partials/footer-scripts.hbs   |    5 +
 src/partials/footer.hbs           |    2 +
 src/partials/head-icons.hbs       |    1 +
 src/partials/head-info.hbs        |   20 +
 src/partials/head-meta.hbs        |    1 +
 src/partials/head-prelude.hbs     |    2 +
 src/partials/head-scripts.hbs     |    7 +
 src/partials/head-styles.hbs      |    1 +
 src/partials/head-title.hbs       |    1 +
 src/partials/head.hbs             |    7 +
 src/partials/header-content.hbs   |   45 ++
 src/partials/header-scripts.hbs   |    1 +
 src/partials/header.hbs           |    2 +
 src/partials/main.hbs             |   11 +
 src/partials/nav-explore.hbs      |   26 +
 src/partials/nav-menu.hbs         |   11 +
 src/partials/nav-toggle.hbs       |    1 +
 src/partials/nav-tree.hbs         |   21 +
 src/partials/nav.hbs              |    8 +
 src/partials/page-versions.hbs    |   12 +
 src/partials/pagination.hbs       |   16 +
 src/partials/toc.hbs              |    3 +
 src/partials/toolbar.hbs          |    9 +
 73 files changed, 4184 insertions(+), 91 deletions(-)
 create mode 100644 src/css/base.css
 create mode 100644 src/css/body.css
 create mode 100644 src/css/breadcrumbs.css
 create mode 100644 src/css/doc.css
 create mode 100644 src/css/footer.css
 create mode 100644 src/css/header.css
 create mode 100644 src/css/main.css
 create mode 100644 src/css/nav.css
 create mode 100644 src/css/page-versions.css
 create mode 100644 src/css/pagination.css
 create mode 100644 src/css/print.css
 create mode 100644 src/css/site.css
 create mode 100644 src/css/toc.css
 create mode 100644 src/css/toolbar.css
 create mode 100644 src/css/typeface-roboto-mono.css
 create mode 100644 src/css/typeface-roboto.css
 create mode 100644 src/css/vars.css
 create mode 100644 src/helpers/and.js
 create mode 100644 src/helpers/detag.js
 create mode 100644 src/helpers/eq.js
 create mode 100644 src/helpers/increment.js
 create mode 100644 src/helpers/ne.js
 create mode 100644 src/helpers/not.js
 create mode 100644 src/helpers/or.js
 create mode 100644 src/helpers/relativize.js
 create mode 100644 src/helpers/year.js
 create mode 100644 src/img/back.svg
 create mode 100644 src/img/caret.svg
 create mode 100644 src/img/chevron.svg
 create mode 100644 src/img/home-o.svg
 create mode 100644 src/img/home.svg
 create mode 100644 src/img/menu.svg
 create mode 100644 src/img/octicons-16.svg
 create mode 100644 src/js/01-nav.js
 create mode 100644 src/js/02-on-this-page.js
 create mode 100644 src/js/03-fragment-jumper.js
 create mode 100644 src/js/04-page-versions.js
 create mode 100644 src/js/05-mobile-navbar.js
 create mode 100644 src/js/06-copy-to-clipboard.js
 create mode 100644 src/js/vendor/highlight.bundle.js
 create mode 100644 src/layouts/404.hbs
 create mode 100644 src/layouts/default.hbs
 create mode 100644 src/partials/article-404.hbs
 create mode 100644 src/partials/article.hbs
 create mode 100644 src/partials/body.hbs
 create mode 100644 src/partials/breadcrumbs.hbs
 create mode 100644 src/partials/edit-this-page.hbs
 create mode 100644 src/partials/footer-content.hbs
 create mode 100644 src/partials/footer-scripts.hbs
 create mode 100644 src/partials/footer.hbs
 create mode 100644 src/partials/head-icons.hbs
 create mode 100644 src/partials/head-info.hbs
 create mode 100644 src/partials/head-meta.hbs
 create mode 100644 src/partials/head-prelude.hbs
 create mode 100644 src/partials/head-scripts.hbs
 create mode 100644 src/partials/head-styles.hbs
 create mode 100644 src/partials/head-title.hbs
 create mode 100644 src/partials/head.hbs
 create mode 100644 src/partials/header-content.hbs
 create mode 100644 src/partials/header-scripts.hbs
 create mode 100644 src/partials/header.hbs
 create mode 100644 src/partials/main.hbs
 create mode 100644 src/partials/nav-explore.hbs
 create mode 100644 src/partials/nav-menu.hbs
 create mode 100644 src/partials/nav-toggle.hbs
 create mode 100644 src/partials/nav-tree.hbs
 create mode 100644 src/partials/nav.hbs
 create mode 100644 src/partials/page-versions.hbs
 create mode 100644 src/partials/pagination.hbs
 create mode 100644 src/partials/toc.hbs
 create mode 100644 src/partials/toolbar.hbs

diff --git a/antora-playbook.yml b/antora-playbook.yml
index 7c372e3..3c16572 100644
--- a/antora-playbook.yml
+++ b/antora-playbook.yml
@@ -8,5 +8,6 @@ content:
     start_path: getting-started
 ui:
   bundle:
-    url: https://gitlab.com/antora/antora-ui-default/-/jobs/artifacts/HEAD/raw/build/ui-bundle.zip?job=bundle-stable
+    # url: https://gitlab.com/antora/antora-ui-default/-/jobs/artifacts/HEAD/raw/build/ui-bundle.zip?job=bundle-stable
+    url: https://https://gitlab.bwg.co.kr/test/swlab-docs-for-park/-/jobs/artifacts/HEAD/raw/build/ui-bundle.zip?job=bundle-stable
     snapshot: true
\ No newline at end of file
diff --git a/src/css/base.css b/src/css/base.css
new file mode 100644
index 0000000..cb25a92
--- /dev/null
+++ b/src/css/base.css
@@ -0,0 +1,149 @@
+*,
+*::before,
+*::after {
+  box-sizing: inherit;
+}
+
+html {
+  box-sizing: border-box;
+  font-size: var(--body-font-size);
+  height: 100%;
+  scroll-behavior: smooth;
+}
+
+@media screen and (min-width: 1024px) {
+  html {
+    font-size: var(--body-font-size--desktop);
+  }
+}
+
+body {
+  background: var(--body-background);
+  color: var(--body-font-color);
+  font-family: var(--body-font-family);
+  line-height: var(--body-line-height);
+  margin: 0;
+  tab-size: 4;
+  word-wrap: anywhere; /* aka overflow-wrap; used when hyphens are disabled or aren't sufficient */
+}
+
+a {
+  text-decoration: none;
+}
+
+a:hover {
+  text-decoration: underline;
+}
+
+a:active {
+  background-color: none;
+}
+
+code,
+kbd,
+pre {
+  font-family: var(--monospace-font-family);
+}
+
+b,
+dt,
+strong,
+th {
+  font-weight: var(--body-font-weight-bold);
+}
+
+sub,
+sup {
+  font-size: 75%;
+  line-height: 0;
+  position: relative;
+  vertical-align: baseline;
+}
+
+sub {
+  bottom: -0.25em;
+}
+
+sup {
+  top: -0.5em;
+}
+
+em em { /* stylelint-disable-line */
+  font-style: normal;
+}
+
+strong strong { /* stylelint-disable-line */
+  font-weight: normal;
+}
+
+button {
+  cursor: pointer;
+  font-family: inherit;
+  font-size: 1em;
+  line-height: var(--body-line-height);
+  margin: 0;
+}
+
+button::-moz-focus-inner {
+  border: none;
+  padding: 0;
+}
+
+summary {
+  cursor: pointer;
+  -webkit-tap-highlight-color: transparent;
+  outline: none;
+}
+
+table {
+  border-collapse: collapse;
+  word-wrap: normal; /* table widths aren't computed as expected when word-wrap is enabled */
+}
+
+object[type="image/svg+xml"]:not([width]) {
+  width: fit-content;
+}
+
+::placeholder {
+  opacity: 0.5;
+}
+
+@media (pointer: fine) {
+  @supports (scrollbar-width: thin) {
+    html {
+      scrollbar-color: var(--scrollbar-thumb-color) var(--scrollbar-track-color);
+    }
+
+    body * {
+      scrollbar-width: thin;
+      scrollbar-color: var(--scrollbar-thumb-color) transparent;
+    }
+  }
+
+  html::-webkit-scrollbar {
+    background-color: var(--scrollbar-track-color);
+    height: 12px;
+    width: 12px;
+  }
+
+  body ::-webkit-scrollbar {
+    height: 6px;
+    width: 6px;
+  }
+
+  ::-webkit-scrollbar-thumb {
+    background-clip: padding-box;
+    background-color: var(--scrollbar-thumb-color);
+    border: 3px solid transparent;
+    border-radius: 12px;
+  }
+
+  body ::-webkit-scrollbar-thumb {
+    border-width: 1.75px;
+    border-radius: 6px;
+  }
+
+  ::-webkit-scrollbar-thumb:hover {
+    background-color: var(--scrollbar_hover-thumb-color);
+  }
+}
diff --git a/src/css/body.css b/src/css/body.css
new file mode 100644
index 0000000..1d4db3d
--- /dev/null
+++ b/src/css/body.css
@@ -0,0 +1,5 @@
+@media screen and (min-width: 1024px) {
+  .body {
+    display: flex;
+  }
+}
diff --git a/src/css/breadcrumbs.css b/src/css/breadcrumbs.css
new file mode 100644
index 0000000..be11140
--- /dev/null
+++ b/src/css/breadcrumbs.css
@@ -0,0 +1,38 @@
+.breadcrumbs {
+  display: none;
+  flex: 1 1;
+  padding: 0 0.5rem 0 0.75rem;
+  line-height: var(--nav-line-height);
+}
+
+@media screen and (min-width: 1024px) {
+  .breadcrumbs {
+    display: block;
+  }
+}
+
+a + .breadcrumbs {
+  padding-left: 0.05rem;
+}
+
+.breadcrumbs ul {
+  display: flex;
+  flex-wrap: wrap;
+  margin: 0;
+  padding: 0;
+  list-style: none;
+}
+
+.breadcrumbs li {
+  display: inline;
+  margin: 0;
+}
+
+.breadcrumbs li::after {
+  content: "/";
+  padding: 0 0.5rem;
+}
+
+.breadcrumbs li:last-of-type::after {
+  content: none;
+}
diff --git a/src/css/doc.css b/src/css/doc.css
new file mode 100644
index 0000000..4acb338
--- /dev/null
+++ b/src/css/doc.css
@@ -0,0 +1,1087 @@
+.doc {
+  color: var(--doc-font-color);
+  font-size: var(--doc-font-size);
+  hyphens: auto;
+  line-height: var(--doc-line-height);
+  margin: var(--doc-margin);
+  max-width: var(--doc-max-width);
+  padding: 0 1rem 4rem;
+}
+
+@media screen and (min-width: 1024px) {
+  .doc {
+    flex: auto;
+    font-size: var(--doc-font-size--desktop);
+    margin: var(--doc-margin--desktop);
+    max-width: var(--doc-max-width--desktop);
+    min-width: 0;
+  }
+}
+
+.doc h1,
+.doc h2,
+.doc h3,
+.doc h4,
+.doc h5,
+.doc h6 {
+  color: var(--heading-font-color);
+  font-weight: var(--heading-font-weight);
+  hyphens: none;
+  line-height: 1.3;
+  margin: 1rem 0 0;
+}
+
+.doc > h1.page:first-child {
+  font-size: calc(36 / var(--rem-base) * 1rem);
+  margin: 1.5rem 0;
+}
+
+@media screen and (min-width: 769px) {
+  .doc > h1.page:first-child {
+    margin-top: 2.5rem;
+  }
+}
+
+.doc > h1.page:first-child + aside.toc.embedded {
+  margin-top: -0.5rem;
+}
+
+.doc > h2#name + .sectionbody {
+  margin-top: 1rem;
+}
+
+#preamble + .sect1,
+.doc .sect1 + .sect1 {
+  margin-top: 2rem;
+}
+
+.doc h1.sect0 {
+  background: var(--abstract-background);
+  font-size: 1.8em;
+  margin: 1.5rem -1rem 0;
+  padding: 0.5rem 1rem;
+}
+
+.doc h2:not(.discrete) {
+  border-bottom: 1px solid var(--section-divider-color);
+  margin-left: -1rem;
+  margin-right: -1rem;
+  padding: 0.4rem 1rem 0.1rem;
+}
+
+.doc h3:not(.discrete),
+.doc h4:not(.discrete) {
+  font-weight: var(--alt-heading-font-weight);
+}
+
+.doc h1 .anchor,
+.doc h2 .anchor,
+.doc h3 .anchor,
+.doc h4 .anchor,
+.doc h5 .anchor,
+.doc h6 .anchor {
+  position: absolute;
+  text-decoration: none;
+  width: 1.75ex;
+  margin-left: -1.5ex;
+  visibility: hidden;
+  font-size: 0.8em;
+  font-weight: normal;
+  padding-top: 0.05em;
+}
+
+.doc h1 .anchor::before,
+.doc h2 .anchor::before,
+.doc h3 .anchor::before,
+.doc h4 .anchor::before,
+.doc h5 .anchor::before,
+.doc h6 .anchor::before {
+  content: "\00a7";
+}
+
+.doc h1:hover .anchor,
+.doc h2:hover .anchor,
+.doc h3:hover .anchor,
+.doc h4:hover .anchor,
+.doc h5:hover .anchor,
+.doc h6:hover .anchor {
+  visibility: visible;
+}
+
+.doc p,
+.doc dl {
+  margin: 0;
+}
+
+.doc a {
+  color: var(--link-font-color);
+}
+
+.doc a:hover {
+  color: var(--link_hover-font-color);
+}
+
+.doc a.bare {
+  hyphens: none;
+}
+
+.doc a.unresolved {
+  color: var(--link_unresolved-font-color);
+}
+
+.doc i.fa {
+  hyphens: none;
+  font-style: normal;
+}
+
+.doc p code,
+.doc thead code,
+.doc .colist > table code {
+  color: var(--code-font-color);
+  background: var(--code-background);
+  border-radius: 0.25em;
+  font-size: 0.95em;
+  padding: 0.125em 0.25em;
+}
+
+.doc code,
+.doc pre {
+  hyphens: none;
+}
+
+.doc pre {
+  font-size: calc(16 / var(--rem-base) * 1rem);
+  line-height: 1.5;
+  margin: 0;
+}
+
+.doc blockquote {
+  margin: 0;
+}
+
+.doc .paragraph.lead > p {
+  font-size: calc(18 / var(--rem-base) * 1rem);
+}
+
+.doc .right {
+  float: right;
+}
+
+.doc .left {
+  float: left;
+}
+
+.doc .float-gap.right {
+  margin: 0 1rem 1rem 0;
+}
+
+.doc .float-gap.left {
+  margin: 0 0 1rem 1rem;
+}
+
+.doc .float-group::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.doc .text-left {
+  text-align: left;
+}
+
+.doc .text-center {
+  text-align: center;
+}
+
+.doc .text-right {
+  text-align: right;
+}
+
+.doc .text-justify {
+  text-align: justify;
+}
+
+.doc .stretch {
+  width: 100%;
+}
+
+.doc .big {
+  font-size: larger;
+}
+
+.doc .small {
+  font-size: smaller;
+}
+
+.doc .underline {
+  text-decoration: underline;
+}
+
+.doc .line-through {
+  text-decoration: line-through;
+}
+
+.doc .paragraph,
+.doc .dlist,
+.doc .hdlist,
+.doc .olist,
+.doc .ulist,
+.doc .exampleblock,
+.doc .imageblock,
+.doc .listingblock,
+.doc .literalblock,
+.doc .tabs,
+.doc .sidebarblock,
+.doc .verseblock,
+.doc .videoblock,
+.doc .quoteblock,
+.doc .partintro,
+.doc details,
+.doc hr {
+  margin: 1rem 0 0;
+}
+
+.doc > table.tableblock,
+.doc > table.tableblock + *,
+.doc .tablecontainer,
+.doc .tablecontainer + *,
+.doc :not(.tablecontainer) > table.tableblock,
+.doc :not(.tablecontainer) > table.tableblock + * {
+  margin-top: 1.5rem;
+}
+
+.doc table.tableblock {
+  font-size: calc(15 / var(--rem-base) * 1rem);
+}
+
+.doc p.tableblock + p.tableblock {
+  margin-top: 0.5rem;
+}
+
+.doc table.tableblock pre {
+  font-size: inherit;
+}
+
+.doc td.tableblock > .content {
+  word-wrap: anywhere; /* aka overflow-wrap; used when hyphens are disabled or aren't sufficient */
+}
+
+.doc td.tableblock > .content > :first-child {
+  margin-top: 0;
+}
+
+.doc table.tableblock th,
+.doc table.tableblock td {
+  padding: 0.5rem;
+}
+
+.doc table.tableblock,
+.doc table.tableblock > * > tr > * {
+  border: 0 solid var(--table-border-color);
+}
+
+.doc table.grid-all > * > tr > * {
+  border-width: 1px;
+}
+
+.doc table.grid-cols > * > tr > * {
+  border-width: 0 1px;
+}
+
+.doc table.grid-rows > * > tr > * {
+  border-width: 1px 0;
+}
+
+.doc table.grid-all > thead th,
+.doc table.grid-rows > thead th {
+  border-bottom-width: 2.5px;
+}
+
+.doc table.frame-all {
+  border-width: 1px;
+}
+
+.doc table.frame-ends {
+  border-width: 1px 0;
+}
+
+.doc table.frame-sides {
+  border-width: 0 1px;
+}
+
+.doc table.frame-none > colgroup + * > :first-child > *,
+.doc table.frame-sides > colgroup + * > :first-child > * {
+  border-top-width: 0;
+}
+
+/* NOTE let the grid win in case of frame-none */
+.doc table.frame-sides > :last-child > :last-child > * {
+  border-bottom-width: 0;
+}
+
+.doc table.frame-none > * > tr > :first-child,
+.doc table.frame-ends > * > tr > :first-child {
+  border-left-width: 0;
+}
+
+.doc table.frame-none > * > tr > :last-child,
+.doc table.frame-ends > * > tr > :last-child {
+  border-right-width: 0;
+}
+
+.doc table.stripes-all > tbody > tr,
+.doc table.stripes-odd > tbody > tr:nth-of-type(odd),
+.doc table.stripes-even > tbody > tr:nth-of-type(even),
+.doc table.stripes-hover > tbody > tr:hover {
+  background: var(--table-stripe-background);
+}
+
+.doc table.tableblock > tfoot {
+  background: var(--table-footer-background);
+}
+
+.doc .halign-left {
+  text-align: left;
+}
+
+.doc .halign-right {
+  text-align: right;
+}
+
+.doc .halign-center {
+  text-align: center;
+}
+
+.doc .valign-top {
+  vertical-align: top;
+}
+
+.doc .valign-bottom {
+  vertical-align: bottom;
+}
+
+.doc .valign-middle {
+  vertical-align: middle;
+}
+
+.doc .admonitionblock {
+  margin: 1.4rem 0 0;
+}
+
+.doc .admonitionblock p,
+.doc .admonitionblock td.content {
+  font-size: calc(16 / var(--rem-base) * 1rem);
+}
+
+.doc .admonitionblock td.content > :not(.title):first-child,
+.doc .admonitionblock td.content > .title + * {
+  margin-top: 0;
+}
+
+.doc .admonitionblock td.content pre {
+  font-size: calc(15 / var(--rem-base) * 1rem);
+}
+
+.doc .admonitionblock > table {
+  table-layout: fixed;
+  position: relative;
+  width: 100%;
+}
+
+.doc .admonitionblock td.content {
+  padding: 1rem 1rem 0.75rem;
+  background: var(--admonition-background);
+  width: 100%;
+  word-wrap: anywhere;
+}
+
+.doc .admonitionblock td.icon {
+  font-size: calc(15 / var(--rem-base) * 1rem);
+  left: 0;
+  line-height: 1;
+  padding: 0;
+  position: absolute;
+  top: 0;
+  transform: translate(-0.5rem, -50%);
+}
+
+.doc .admonitionblock td.icon i {
+  align-items: center;
+  border-radius: 0.45rem;
+  display: inline-flex;
+  filter: initial;
+  height: 1.25rem;
+  padding: 0 0.5rem;
+  vertical-align: initial;
+  width: fit-content;
+}
+
+.doc .admonitionblock td.icon i::after {
+  content: attr(title);
+  font-weight: var(--admonition-label-font-weight);
+  font-style: normal;
+  text-transform: uppercase;
+}
+
+.doc .admonitionblock td.icon i.icon-caution {
+  background-color: var(--caution-color);
+  color: var(--caution-on-color);
+}
+
+.doc .admonitionblock td.icon i.icon-important {
+  background-color: var(--important-color);
+  color: var(--important-on-color);
+}
+
+.doc .admonitionblock td.icon i.icon-note {
+  background-color: var(--note-color);
+  color: var(--note-on-color);
+}
+
+.doc .admonitionblock td.icon i.icon-tip {
+  background-color: var(--tip-color);
+  color: var(--tip-on-color);
+}
+
+.doc .admonitionblock td.icon i.icon-warning {
+  background-color: var(--warning-color);
+  color: var(--warning-on-color);
+}
+
+.doc .imageblock,
+.doc .videoblock {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+.doc .imageblock .content {
+  align-self: stretch;
+  text-align: center;
+}
+
+.doc .imageblock.text-left,
+.doc .videoblock.text-left {
+  align-items: flex-start;
+}
+
+.doc .imageblock.text-left .content {
+  text-align: left;
+}
+
+.doc .imageblock.text-right,
+.doc .videoblock.text-right {
+  align-items: flex-end;
+}
+
+.doc .imageblock.text-right .content {
+  text-align: right;
+}
+
+.doc .imageblock img,
+.doc .imageblock object,
+.doc .imageblock svg,
+.doc .image > img,
+.doc .image > object,
+.doc .image > svg {
+  display: inline-block;
+  height: auto;
+  max-width: 100%;
+  vertical-align: middle;
+}
+
+.doc .image:not(.left):not(.right) > img {
+  margin-top: -0.2em;
+}
+
+.doc .videoblock iframe,
+.doc .videoblock video {
+  max-width: 100%;
+  vertical-align: middle;
+}
+
+#preamble .abstract blockquote {
+  background: var(--abstract-background);
+  border-left: 5px solid var(--abstract-border-color);
+  color: var(--abstract-font-color);
+  font-size: calc(16 / var(--rem-base) * 1rem);
+  padding: 0.75em 1em;
+}
+
+.doc .quoteblock,
+.doc .verseblock {
+  background: var(--quote-background);
+  border-left: 5px solid var(--quote-border-color);
+  color: var(--quote-font-color);
+}
+
+.doc .quoteblock {
+  padding: 0.25rem 2rem 1.25rem;
+}
+
+.doc .quoteblock .attribution {
+  color: var(--quote-attribution-font-color);
+  font-size: calc(15 / var(--rem-base) * 1rem);
+  margin-top: 0.75rem;
+}
+
+.doc .quoteblock blockquote {
+  margin-top: 1rem;
+}
+
+.doc .quoteblock .paragraph {
+  font-style: italic;
+}
+
+.doc .quoteblock cite {
+  padding-left: 1em;
+}
+
+.doc .verseblock {
+  font-size: 1.15em;
+  padding: 1rem 2rem;
+}
+
+.doc .verseblock pre {
+  font-family: inherit;
+  font-size: inherit;
+}
+
+.doc ol,
+.doc ul {
+  margin: 0;
+  padding: 0 0 0 2rem;
+}
+
+.doc ul.checklist,
+.doc ul.none,
+.doc ol.none,
+.doc ul.no-bullet,
+.doc ol.unnumbered,
+.doc ul.unstyled,
+.doc ol.unstyled {
+  list-style-type: none;
+}
+
+.doc ul.no-bullet,
+.doc ol.unnumbered {
+  padding-left: 1.25rem;
+}
+
+.doc ul.unstyled,
+.doc ol.unstyled {
+  padding-left: 0;
+}
+
+.doc ul.circle {
+  list-style-type: circle;
+}
+
+.doc ul.disc {
+  list-style-type: disc;
+}
+
+.doc ul.square {
+  list-style-type: square;
+}
+
+.doc ul.circle ul:not([class]),
+.doc ul.disc ul:not([class]),
+.doc ul.square ul:not([class]) {
+  list-style: inherit;
+}
+
+.doc ol.arabic {
+  list-style-type: decimal;
+}
+
+.doc ol.decimal {
+  list-style-type: decimal-leading-zero;
+}
+
+.doc ol.loweralpha {
+  list-style-type: lower-alpha;
+}
+
+.doc ol.upperalpha {
+  list-style-type: upper-alpha;
+}
+
+.doc ol.lowerroman {
+  list-style-type: lower-roman;
+}
+
+.doc ol.upperroman {
+  list-style-type: upper-roman;
+}
+
+.doc ol.lowergreek {
+  list-style-type: lower-greek;
+}
+
+.doc ul.checklist {
+  padding-left: 1.75rem;
+}
+
+.doc ul.checklist p > i.fa-check-square-o:first-child,
+.doc ul.checklist p > i.fa-square-o:first-child {
+  display: inline-flex;
+  justify-content: center;
+  width: 1.25rem;
+  margin-left: -1.25rem;
+}
+
+.doc ul.checklist i.fa-check-square-o::before {
+  content: "\2713";
+}
+
+.doc ul.checklist i.fa-square-o::before {
+  content: "\274f";
+}
+
+.doc .dlist .dlist,
+.doc .dlist .olist,
+.doc .dlist .ulist,
+.doc .olist .dlist,
+.doc .olist .olist,
+.doc .olist .ulist,
+.doc .ulist .dlist,
+.doc .ulist .olist,
+.doc .ulist .ulist {
+  margin-top: 0.5rem;
+}
+
+.doc .olist li + li,
+.doc .ulist li + li {
+  margin-top: 0.5rem;
+}
+
+.doc .ulist .listingblock,
+.doc .olist .listingblock,
+.doc .admonitionblock .listingblock {
+  padding: 0;
+}
+
+.doc .admonitionblock .title,
+.doc .exampleblock .title,
+.doc .imageblock .title,
+.doc .literalblock .title,
+.doc .listingblock .title,
+.doc .openblock .title,
+.doc .videoblock .title,
+.doc table.tableblock caption {
+  color: var(--caption-font-color);
+  font-size: calc(16 / var(--rem-base) * 1rem);
+  font-style: var(--caption-font-style);
+  font-weight: var(--caption-font-weight);
+  hyphens: none;
+  letter-spacing: 0.01em;
+  padding-bottom: 0.075rem;
+}
+
+.doc table.tableblock caption {
+  text-align: left;
+}
+
+.doc .olist .title,
+.doc .ulist .title {
+  font-style: var(--caption-font-style);
+  font-weight: var(--caption-font-weight);
+  margin-bottom: 0.25rem;
+}
+
+.doc .imageblock .title,
+.doc .videoblock .title {
+  margin-top: 0.5rem;
+  padding-bottom: 0;
+}
+
+.doc details {
+  margin-left: 1rem;
+}
+
+.doc details > summary {
+  display: block;
+  position: relative;
+  line-height: var(--doc-line-height);
+  margin-bottom: 0.5rem;
+}
+
+.doc details > summary::-webkit-details-marker {
+  display: none;
+}
+
+.doc details > summary::before {
+  content: "";
+  border: solid transparent;
+  border-left-color: currentColor;
+  border-width: 0.3em 0 0.3em 0.5em;
+  position: absolute;
+  top: calc((var(--doc-line-height) * 0.5 - 0.3) * 1em);
+  left: -1rem;
+  transform: translateX(15%);
+}
+
+.doc details[open] > summary::before {
+  border-color: currentColor transparent transparent;
+  border-width: 0.5rem 0.3rem 0;
+  transform: translateY(15%);
+}
+
+.doc details > summary::after {
+  content: "";
+  width: 1rem;
+  height: 1em;
+  position: absolute;
+  top: calc((var(--doc-line-height) * 0.5 - 0.5) * 1em);
+  left: -1rem;
+}
+
+.doc details.result {
+  margin-top: 0.25rem;
+}
+
+.doc details.result > summary {
+  color: var(--caption-font-color);
+  font-style: italic;
+  margin-bottom: 0;
+}
+
+.doc details.result > .content {
+  margin-left: -1rem;
+}
+
+.doc .exampleblock > .content,
+.doc details.result > .content {
+  background: var(--example-background);
+  border: 0.25rem solid var(--example-border-color);
+  border-radius: 0.5rem;
+  padding: 0.75rem;
+}
+
+.doc .exampleblock > .content::after,
+.doc details.result > .content::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.doc .exampleblock > .content > :first-child,
+.doc details > .content > :first-child {
+  margin-top: 0;
+}
+
+.doc .sidebarblock {
+  background: var(--sidebar-background);
+  border-radius: 0.75rem;
+  padding: 0.75rem 1.5rem;
+}
+
+.doc .sidebarblock > .content > .title {
+  font-size: calc(22.5 / var(--rem-base) * 1rem);
+  font-weight: var(--alt-heading-font-weight);
+  line-height: 1.3;
+  margin-bottom: 0.5rem;
+  text-align: center;
+}
+
+.doc .sidebarblock > .content > .title + *,
+.doc .sidebarblock > .content > :not(.title):first-child {
+  margin-top: 0;
+}
+
+/* NEEDS REVIEW prevent pre in table from causing article to exceed bounds */
+.doc table.tableblock pre,
+.doc .listingblock.wrap pre {
+  white-space: pre-wrap;
+}
+
+.doc pre.highlight > code,
+.doc .listingblock pre:not(.highlight),
+.doc .literalblock pre {
+  background: var(--pre-background);
+  box-shadow: inset 0 0 1.75px var(--pre-border-color);
+  display: block;
+  overflow-x: auto;
+  padding: 0.875em;
+}
+
+.doc .listingblock > .content {
+  position: relative;
+}
+
+.doc .source-toolbox {
+  display: flex;
+  visibility: hidden;
+  position: absolute;
+  top: 0.25rem;
+  right: 0.5rem;
+  color: var(--pre-annotation-font-color);
+  font-family: var(--body-font-family);
+  font-size: calc(13 / var(--rem-base) * 1rem);
+  line-height: 1;
+  user-select: none;
+  white-space: nowrap;
+  z-index: 1;
+}
+
+.doc .listingblock:hover .source-toolbox {
+  visibility: visible;
+}
+
+.doc .source-toolbox .source-lang {
+  text-transform: uppercase;
+  letter-spacing: 0.075em;
+}
+
+.doc .source-toolbox > :not(:last-child)::after {
+  content: "|";
+  letter-spacing: 0;
+  padding: 0 1ch;
+}
+
+.doc .source-toolbox .copy-button {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  background: none;
+  border: none;
+  color: inherit;
+  outline: none;
+  padding: 0;
+  font-size: inherit;
+  line-height: inherit;
+  width: 1em;
+  height: 1em;
+}
+
+.doc .source-toolbox .copy-icon {
+  flex: none;
+  width: inherit;
+  height: inherit;
+}
+
+.doc .source-toolbox img.copy-icon {
+  filter: invert(50.2%);
+}
+
+.doc .source-toolbox svg.copy-icon {
+  fill: currentColor;
+}
+
+.doc .source-toolbox .copy-toast {
+  flex: none;
+  position: relative;
+  display: inline-flex;
+  justify-content: center;
+  margin-top: 1em;
+  background-color: var(--doc-font-color);
+  border-radius: 0.25em;
+  padding: 0.5em;
+  color: var(--color-white);
+  cursor: auto;
+  opacity: 0;
+  transition: opacity 0.5s ease 0.5s;
+}
+
+.doc .source-toolbox .copy-toast::after {
+  content: "";
+  position: absolute;
+  top: 0;
+  width: 1em;
+  height: 1em;
+  border: 0.55em solid transparent;
+  border-left-color: var(--doc-font-color);
+  transform: rotate(-90deg) translateX(50%) translateY(50%);
+  transform-origin: left;
+}
+
+.doc .source-toolbox .copy-button.clicked .copy-toast {
+  opacity: 1;
+  transition: none;
+}
+
+.doc .language-console .hljs-meta {
+  user-select: none;
+}
+
+.doc .dlist dt {
+  font-style: italic;
+}
+
+.doc .dlist dd {
+  margin: 0 0 0 1.5rem;
+}
+
+.doc .dlist dd + dt,
+.doc .dlist dd > p:first-child {
+  margin-top: 0.5rem;
+}
+
+.doc td.hdlist1,
+.doc td.hdlist2 {
+  padding: 0.5rem 0 0;
+  vertical-align: top;
+}
+
+.doc tr:first-child > .hdlist1,
+.doc tr:first-child > .hdlist2 {
+  padding-top: 0;
+}
+
+.doc td.hdlist1 {
+  font-weight: var(--body-font-weight-bold);
+  padding-right: 0.25rem;
+}
+
+.doc td.hdlist2 {
+  padding-left: 0.25rem;
+}
+
+.doc .colist {
+  font-size: calc(16 / var(--rem-base) * 1rem);
+  margin: 0.25rem 0 -0.25rem;
+}
+
+.doc .colist > table > tr > :first-child,
+.doc .colist > table > tbody > tr > :first-child {
+  padding: 0.25em 0.5rem 0;
+  vertical-align: top;
+}
+
+.doc .colist > table > tr > :last-child,
+.doc .colist > table > tbody > tr > :last-child {
+  padding: 0.25rem 0;
+}
+
+.doc .conum[data-value] {
+  border: 1px solid currentColor;
+  border-radius: 100%;
+  display: inline-block;
+  font-family: var(--body-font-family);
+  font-size: calc(13.5 / var(--rem-base) * 1rem);
+  font-style: normal;
+  line-height: 1.2;
+  text-align: center;
+  width: 1.25em;
+  height: 1.25em;
+  letter-spacing: -0.25ex;
+  text-indent: -0.25ex;
+}
+
+.doc .conum[data-value]::after {
+  content: attr(data-value);
+}
+
+.doc .conum[data-value] + b {
+  display: none;
+}
+
+.doc hr {
+  border: solid var(--section-divider-color);
+  border-width: 2px 0 0;
+  height: 0;
+}
+
+.doc b.button {
+  white-space: nowrap; /* effectively ignores hyphens setting */
+}
+
+.doc b.button::before {
+  content: "[";
+  padding-right: 0.25em;
+}
+
+.doc b.button::after {
+  content: "]";
+  padding-left: 0.25em;
+}
+
+.doc kbd {
+  display: inline-block;
+  font-size: calc(12 / var(--rem-base) * 1rem);
+  background: var(--kbd-background);
+  border: 1px solid var(--kbd-border-color);
+  border-radius: 0.25em;
+  box-shadow: 0 1px 0 var(--kbd-border-color), 0 0 0 0.1em var(--body-background) inset;
+  padding: 0.25em 0.5em;
+  vertical-align: text-bottom;
+  white-space: nowrap; /* effectively ignores hyphens setting */
+}
+
+.doc kbd,
+.doc .keyseq {
+  line-height: 1;
+}
+
+.doc .keyseq {
+  font-size: calc(16 / var(--rem-base) * 1rem);
+}
+
+.doc .keyseq kbd {
+  margin: 0 0.125em;
+}
+
+.doc .keyseq kbd:first-child {
+  margin-left: 0;
+}
+
+.doc .keyseq kbd:last-child {
+  margin-right: 0;
+}
+
+.doc .menuseq,
+.doc .path {
+  hyphens: none;
+}
+
+.doc .menuseq i.caret::before {
+  content: "\203a";
+  font-size: 1.1em;
+  font-weight: var(--body-font-weight-bold);
+  line-height: calc(1 / 1.1);
+}
+
+.doc :not(pre).nowrap {
+  white-space: nowrap;
+}
+
+.doc .nobreak {
+  hyphens: none;
+  word-wrap: normal;
+}
+
+.doc :not(pre).pre-wrap {
+  white-space: pre-wrap;
+}
+
+#footnotes {
+  font-size: 0.85em;
+  line-height: 1.5;
+  margin: 2rem -0.5rem 0;
+}
+
+.doc td.tableblock > .content #footnotes {
+  margin: 2rem 0 0;
+}
+
+#footnotes hr {
+  border-top-width: 1px;
+  margin-top: 0;
+  width: 20%;
+}
+
+#footnotes .footnote {
+  margin: 0.5em 0 0 1em;
+}
+
+#footnotes .footnote + .footnote {
+  margin-top: 0.25em;
+}
+
+#footnotes .footnote > a:first-of-type {
+  display: inline-block;
+  margin-left: -2em;
+  text-align: right;
+  width: 1.5em;
+}
diff --git a/src/css/footer.css b/src/css/footer.css
new file mode 100644
index 0000000..6521947
--- /dev/null
+++ b/src/css/footer.css
@@ -0,0 +1,15 @@
+footer.footer {
+  background-color: var(--footer-background);
+  color: var(--footer-font-color);
+  font-size: calc(15 / var(--rem-base) * 1rem);
+  line-height: var(--footer-line-height);
+  padding: 1.5rem;
+}
+
+.footer p {
+  margin: 0.5rem 0;
+}
+
+.footer a {
+  color: var(--footer-link-font-color);
+}
diff --git a/src/css/header.css b/src/css/header.css
new file mode 100644
index 0000000..9a2b294
--- /dev/null
+++ b/src/css/header.css
@@ -0,0 +1,327 @@
+@media screen and (max-width: 1023.5px) {
+  html.is-clipped--navbar {
+    overflow-y: hidden;
+  }
+}
+
+body {
+  padding-top: var(--navbar-height);
+}
+
+.navbar {
+  background: var(--navbar-background);
+  color: var(--navbar-font-color);
+  font-size: calc(16 / var(--rem-base) * 1rem);
+  height: var(--navbar-height);
+  position: fixed;
+  top: 0;
+  width: 100%;
+  z-index: var(--z-index-navbar);
+}
+
+.navbar a {
+  text-decoration: none;
+}
+
+.navbar-brand {
+  display: flex;
+  flex: auto;
+  padding-left: 1rem;
+}
+
+.navbar-brand .navbar-item {
+  color: var(--navbar-font-color);
+}
+
+.navbar-brand .navbar-item:first-child {
+  align-self: center;
+  padding: 0;
+  font-size: calc(22 / var(--rem-base) * 1rem);
+  flex-wrap: wrap;
+  line-height: 1;
+}
+
+.navbar-brand .navbar-item:first-child a {
+  color: inherit;
+  word-wrap: normal;
+}
+
+.navbar-brand .navbar-item:first-child :not(:last-child) {
+  padding-right: 0.375rem;
+}
+
+.navbar-brand .navbar-item.search {
+  flex: auto;
+  justify-content: flex-end;
+}
+
+#search-input {
+  color: #333;
+  font-family: inherit;
+  font-size: 0.95rem;
+  width: 150px;
+  border: 1px solid #dbdbdb;
+  border-radius: 0.1em;
+  line-height: 1.5;
+  padding: 0 0.25em;
+}
+
+#search-input:disabled {
+  background-color: #dbdbdb;
+  /* disable cursor */
+  cursor: not-allowed;
+  pointer-events: all !important;
+}
+
+#search-input:disabled::placeholder {
+  color: #4c4c4c;
+}
+
+#search-input:focus {
+  outline: none;
+}
+
+.navbar-burger {
+  background: none;
+  border: none;
+  outline: none;
+  line-height: 1;
+  position: relative;
+  width: 3rem;
+  padding: 0;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  margin-left: auto;
+  min-width: 0;
+}
+
+.navbar-burger span {
+  background-color: var(--navbar-font-color);
+  height: 1.5px;
+  width: 1rem;
+}
+
+.navbar-burger:not(.is-active) span {
+  transition: transform ease-out 0.25s, opacity 0s 0.25s, margin-top ease-out 0.25s 0.25s;
+}
+
+.navbar-burger span + span {
+  margin-top: 0.25rem;
+}
+
+.navbar-burger.is-active span + span {
+  margin-top: -1.5px;
+}
+
+.navbar-burger.is-active span:nth-child(1) {
+  transform: rotate(45deg);
+}
+
+.navbar-burger.is-active span:nth-child(2) {
+  opacity: 0;
+}
+
+.navbar-burger.is-active span:nth-child(3) {
+  transform: rotate(-45deg);
+}
+
+.navbar-item,
+.navbar-link {
+  color: var(--navbar-menu-font-color);
+  display: block;
+  line-height: var(--doc-line-height);
+  padding: 0.5rem 1rem;
+}
+
+.navbar-item.has-dropdown {
+  padding: 0;
+}
+
+.navbar-item .icon {
+  width: 1.25rem;
+  height: 1.25rem;
+  display: block;
+}
+
+.navbar-item .icon img,
+.navbar-item .icon svg {
+  fill: currentColor;
+  width: inherit;
+  height: inherit;
+}
+
+.navbar-link {
+  padding-right: 2.5em;
+}
+
+.navbar-dropdown .navbar-item {
+  padding-left: 1.5rem;
+  padding-right: 1.5rem;
+}
+
+.navbar-dropdown .navbar-item.has-label {
+  display: flex;
+  justify-content: space-between;
+}
+
+.navbar-dropdown .navbar-item small {
+  color: var(--toolbar-muted-color);
+  font-size: calc(12 / var(--rem-base) * 1rem);
+}
+
+.navbar-divider {
+  background-color: var(--navbar-menu-border-color);
+  border: none;
+  height: 1px;
+  margin: 0.25rem 0;
+}
+
+.navbar .button {
+  display: inline-flex;
+  align-items: center;
+  background: var(--navbar-button-background);
+  border: 1px solid var(--navbar-button-border-color);
+  border-radius: 0.15rem;
+  height: 1.75rem;
+  color: var(--navbar-button-font-color);
+  padding: 0 0.75em;
+  white-space: nowrap;
+}
+
+@media screen and (max-width: 768.5px) {
+  .navbar-brand .navbar-item.search {
+    padding-left: 0;
+    padding-right: 0;
+  }
+}
+
+@media screen and (min-width: 769px) {
+  #search-input {
+    width: 200px;
+  }
+}
+
+@media screen and (max-width: 1023.5px) {
+  .navbar-brand {
+    height: inherit;
+  }
+
+  .navbar-brand .navbar-item {
+    align-items: center;
+    display: flex;
+  }
+
+  .navbar-menu {
+    background: var(--navbar-menu-background);
+    box-shadow: 0 8px 16px rgba(10, 10, 10, 0.1);
+    max-height: var(--body-min-height);
+    overflow-y: auto;
+    overscroll-behavior: none;
+    padding: 0.5rem 0;
+  }
+
+  .navbar-menu:not(.is-active) {
+    display: none;
+  }
+
+  .navbar-menu a.navbar-item:hover,
+  .navbar-menu .navbar-link:hover {
+    background: var(--navbar-menu_hover-background);
+  }
+}
+
+@media screen and (min-width: 1024px) {
+  .navbar-burger {
+    display: none;
+  }
+
+  .navbar,
+  .navbar-menu,
+  .navbar-end {
+    display: flex;
+  }
+
+  .navbar-item,
+  .navbar-link {
+    display: flex;
+    position: relative;
+    flex: none;
+  }
+
+  .navbar-item:not(.has-dropdown),
+  .navbar-link {
+    align-items: center;
+  }
+
+  .navbar-item.is-hoverable:hover .navbar-dropdown {
+    display: block;
+  }
+
+  .navbar-link::after {
+    border-width: 0 0 1px 1px;
+    border-style: solid;
+    content: "";
+    display: block;
+    height: 0.5em;
+    pointer-events: none;
+    position: absolute;
+    transform: rotate(-45deg);
+    width: 0.5em;
+    margin-top: -0.375em;
+    right: 1.125em;
+    top: 50%;
+  }
+
+  .navbar-end > .navbar-item,
+  .navbar-end .navbar-link {
+    color: var(--navbar-font-color);
+  }
+
+  .navbar-end > a.navbar-item:hover,
+  .navbar-end .navbar-link:hover,
+  .navbar-end .navbar-item.has-dropdown:hover .navbar-link {
+    background: var(--navbar_hover-background);
+    color: var(--navbar-font-color);
+  }
+
+  .navbar-end .navbar-link::after {
+    border-color: currentColor;
+  }
+
+  .navbar-dropdown {
+    background: var(--navbar-menu-background);
+    border: 1px solid var(--navbar-menu-border-color);
+    border-top: none;
+    border-radius: 0 0 0.25rem 0.25rem;
+    display: none;
+    top: 100%;
+    left: 0;
+    min-width: 100%;
+    position: absolute;
+  }
+
+  .navbar-dropdown .navbar-item {
+    padding: 0.5rem 3rem 0.5rem 1rem;
+    white-space: nowrap;
+  }
+
+  .navbar-dropdown .navbar-item small {
+    position: relative;
+    right: -2rem;
+  }
+
+  .navbar-dropdown .navbar-item:last-child {
+    border-radius: inherit;
+  }
+
+  .navbar-dropdown.is-right {
+    left: auto;
+    right: 0;
+  }
+
+  .navbar-dropdown a.navbar-item:hover {
+    background: var(--navbar-menu_hover-background);
+  }
+}
diff --git a/src/css/highlight.css b/src/css/highlight.css
index f3192e4..9788ec0 100644
--- a/src/css/highlight.css
+++ b/src/css/highlight.css
@@ -1,94 +1,86 @@
-/*
+/*! Adapted from the GitHub style by Vasily Polovnyov <vast@whiteants.net> */
+.hljs-comment,
+.hljs-quote {
+  color: #998;
+  font-style: italic;
+}
 
-Atom One Dark by Daniel Gamage
-Original One Dark Syntax theme from https://github.com/atom/one-dark-syntax
+.hljs-keyword,
+.hljs-selector-tag,
+.hljs-subst {
+  color: #333;
+  font-weight: var(--monospace-font-weight-bold);
+}
 
-base:    #282c34
-mono-1:  #abb2bf
-mono-2:  #818896
-mono-3:  #5c6370
-hue-1:   #56b6c2
-hue-2:   #61aeee
-hue-3:   #c678dd
-hue-4:   #98c379
-hue-5:   #e06c75
-hue-5-2: #be5046
-hue-6:   #d19a66
-hue-6-2: #e6c07b
+.hljs-number,
+.hljs-literal,
+.hljs-variable,
+.hljs-template-variable,
+.hljs-tag .hljs-attr {
+  color: #008080;
+}
 
-*/
+.hljs-string,
+.hljs-doctag {
+  color: #d14;
+}
 
-.hljs {
-    color: #abb2bf;
-    background: #282c34;
-  }
-  
-  .hljs-comment,
-  .hljs-quote {
-    color: #5c6370;
-    font-style: italic;
-  }
-  
-  .hljs-doctag,
-  .hljs-keyword,
-  .hljs-formula {
-    color: #c678dd;
-  }
-  
-  .hljs-section,
-  .hljs-name,
-  .hljs-selector-tag,
-  .hljs-deletion,
-  .hljs-subst {
-    color: #e06c75;
-  }
-  
-  .hljs-literal {
-    color: #56b6c2;
-  }
-  
-  .hljs-string,
-  .hljs-regexp,
-  .hljs-addition,
-  .hljs-attribute,
-  .hljs-meta .hljs-string {
-    color: #98c379;
-  }
-  
-  .hljs-attr,
-  .hljs-variable,
-  .hljs-template-variable,
-  .hljs-type,
-  .hljs-selector-class,
-  .hljs-selector-attr,
-  .hljs-selector-pseudo,
-  .hljs-number {
-    color: #d19a66;
-  }
-  
-  .hljs-symbol,
-  .hljs-bullet,
-  .hljs-link,
-  .hljs-meta,
-  .hljs-selector-id,
-  .hljs-title {
-    color: #61aeee;
-  }
-  
-  .hljs-built_in,
-  .hljs-title.class_,
-  .hljs-class .hljs-title {
-    color: #e6c07b;
-  }
-  
-  .hljs-emphasis {
-    font-style: italic;
-  }
-  
-  .hljs-strong {
-    font-weight: bold;
-  }
-  
-  .hljs-link {
-    text-decoration: underline;
-  }
\ No newline at end of file
+.hljs-title,
+.hljs-section,
+.hljs-selector-id {
+  color: #900;
+  font-weight: var(--monospace-font-weight-bold);
+}
+
+.hljs-subst {
+  font-weight: normal;
+}
+
+.hljs-type,
+.hljs-class .hljs-title {
+  color: #458;
+  font-weight: var(--monospace-font-weight-bold);
+}
+
+.hljs-tag,
+.hljs-name,
+.hljs-attribute {
+  color: #000080;
+  font-weight: normal;
+}
+
+.hljs-regexp,
+.hljs-link {
+  color: #009926;
+}
+
+.hljs-symbol,
+.hljs-bullet {
+  color: #990073;
+}
+
+.hljs-built_in,
+.hljs-builtin-name {
+  color: #0086b3;
+}
+
+.hljs-meta {
+  color: #999;
+  font-weight: var(--monospace-font-weight-bold);
+}
+
+.hljs-deletion {
+  background: #fdd;
+}
+
+.hljs-addition {
+  background: #dfd;
+}
+
+.hljs-emphasis {
+  font-style: italic;
+}
+
+.hljs-strong {
+  font-weight: var(--monospace-font-weight-bold);
+}
diff --git a/src/css/main.css b/src/css/main.css
new file mode 100644
index 0000000..83a333c
--- /dev/null
+++ b/src/css/main.css
@@ -0,0 +1,39 @@
+body.-toc aside.toc.sidebar {
+  display: none;
+}
+
+@media screen and (max-width: 1023.5px) {
+  aside.toc.sidebar {
+    display: none;
+  }
+
+  main > .content {
+    overflow-x: auto;
+  }
+}
+
+@media screen and (min-width: 1024px) {
+  main {
+    flex: auto;
+    min-width: 0; /* min-width: 0 required for flexbox to constrain overflowing elements */
+  }
+
+  main > .content {
+    display: flex;
+  }
+
+  aside.toc.embedded {
+    display: none;
+  }
+
+  aside.toc.sidebar {
+    flex: 0 0 var(--toc-width);
+    order: 1;
+  }
+}
+
+@media screen and (min-width: 1216px) {
+  aside.toc.sidebar {
+    flex-basis: var(--toc-width--widescreen);
+  }
+}
diff --git a/src/css/nav.css b/src/css/nav.css
new file mode 100644
index 0000000..807a9fc
--- /dev/null
+++ b/src/css/nav.css
@@ -0,0 +1,285 @@
+@media screen and (max-width: 1023.5px) {
+  html.is-clipped--nav {
+    overflow-y: hidden;
+  }
+}
+
+.nav-container {
+  position: fixed;
+  top: var(--navbar-height);
+  left: 0;
+  width: 100%;
+  font-size: calc(17 / var(--rem-base) * 1rem);
+  z-index: var(--z-index-nav);
+  visibility: hidden;
+}
+
+@media screen and (min-width: 769px) {
+  .nav-container {
+    width: var(--nav-width);
+  }
+}
+
+@media screen and (min-width: 1024px) {
+  .nav-container {
+    font-size: calc(15.5 / var(--rem-base) * 1rem);
+    flex: none;
+    position: static;
+    top: 0;
+    visibility: visible;
+  }
+}
+
+.nav-container.is-active {
+  visibility: visible;
+}
+
+.nav {
+  background: var(--nav-background);
+  position: relative;
+  top: var(--toolbar-height);
+  height: var(--nav-height);
+}
+
+@media screen and (min-width: 769px) {
+  .nav {
+    box-shadow: 0.5px 0 3px var(--nav-border-color);
+  }
+}
+
+@media screen and (min-width: 1024px) {
+  .nav {
+    top: var(--navbar-height);
+    box-shadow: none;
+    position: sticky;
+    height: var(--nav-height--desktop);
+  }
+}
+
+.nav a {
+  color: inherit;
+}
+
+.nav .panels {
+  display: flex;
+  flex-direction: column;
+  height: inherit;
+}
+
+.nav-panel-menu {
+  overflow-y: scroll;
+  overscroll-behavior: none;
+  height: var(--nav-panel-menu-height);
+}
+
+.nav-panel-menu:not(.is-active) .nav-menu {
+  opacity: 0.75;
+}
+
+.nav-panel-menu:not(.is-active)::after {
+  content: "";
+  background: rgba(0, 0, 0, 0.5);
+  display: block;
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+}
+
+.nav-menu {
+  min-height: 100%;
+  padding: 0.5rem 0.75rem;
+  line-height: var(--nav-line-height);
+  position: relative;
+}
+
+.nav-menu-toggle {
+  background: transparent url(../img/octicons-16.svg#view-unfold) no-repeat center / 100% 100%;
+  border: none;
+  float: right;
+  height: 1em;
+  margin-right: -0.5rem;
+  opacity: 0.75;
+  outline: none;
+  padding: 0;
+  position: sticky;
+  top: calc((var(--nav-line-height) - 1 + 0.5) * 1rem);
+  visibility: hidden;
+  width: 1em;
+}
+
+.nav-menu-toggle.is-active {
+  background-image: url(../img/octicons-16.svg#view-fold);
+}
+
+.nav-panel-menu.is-active:hover .nav-menu-toggle {
+  visibility: visible;
+}
+
+.nav-menu h3.title {
+  color: var(--nav-heading-font-color);
+  font-size: inherit;
+  font-weight: var(--body-font-weight-bold);
+  margin: 0;
+  padding: 0.25em 0 0.125em;
+}
+
+.nav-list {
+  list-style: none;
+  margin: 0 0 0 0.75rem;
+  padding: 0;
+}
+
+.nav-menu > .nav-list + .nav-list {
+  margin-top: 0.5rem;
+}
+
+.nav-item {
+  margin-top: 0.5em;
+}
+
+/* adds some breathing room below a nested list */
+.nav-item-toggle ~ .nav-list {
+  padding-bottom: 0.125rem;
+}
+
+/* matches list without a title */
+.nav-item[data-depth="0"] > .nav-list:first-child {
+  display: block;
+  margin: 0;
+}
+
+.nav-item:not(.is-active) > .nav-list {
+  display: none;
+}
+
+.nav-item-toggle {
+  background: transparent url(../img/caret.svg) no-repeat center / 50%;
+  border: none;
+  outline: none;
+  line-height: inherit;
+  padding: 0;
+  position: absolute;
+  height: calc(var(--nav-line-height) * 1em);
+  width: calc(var(--nav-line-height) * 1em);
+  margin-top: -0.05em;
+  margin-left: calc(var(--nav-line-height) * -1em);
+}
+
+.nav-item.is-active > .nav-item-toggle {
+  transform: rotate(90deg);
+}
+
+.is-current-page > .nav-link,
+.is-current-page > .nav-text {
+  font-weight: var(--body-font-weight-bold);
+}
+
+.nav-panel-explore {
+  background: var(--nav-background);
+  display: flex;
+  flex-direction: column;
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+}
+
+.nav-panel-explore:not(:first-child) {
+  top: auto;
+  max-height: var(--nav-panel-explore-height);
+}
+
+.nav-panel-explore .context {
+  font-size: calc(15 / var(--rem-base) * 1rem);
+  flex-shrink: 0;
+  color: var(--nav-muted-color);
+  box-shadow: 0 -1px 0 var(--nav-panel-divider-color);
+  padding: 0 0.5rem;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  line-height: 1;
+  height: var(--drawer-height);
+}
+
+.nav-panel-explore:not(:first-child) .context {
+  cursor: pointer;
+}
+
+.nav-panel-explore .context .version {
+  display: flex;
+  align-items: inherit;
+}
+
+.nav-panel-explore .context .version::after {
+  content: "";
+  background: url(../img/chevron.svg) no-repeat center right / auto 100%;
+  width: 1.25em;
+  height: 0.75em;
+}
+
+.nav-panel-explore .components {
+  line-height: var(--nav-line-height);
+  flex-grow: 1;
+  box-shadow: inset 0 1px 5px var(--nav-panel-divider-color);
+  background: var(--nav-secondary-background);
+  padding: 0.75rem 0.75rem 0 0.75rem;
+  margin: 0;
+  overflow-y: scroll;
+  overscroll-behavior: none;
+  max-height: 100%;
+  display: block;
+}
+
+.nav-panel-explore:not(.is-active) .components {
+  display: none;
+}
+
+.nav-panel-explore .component {
+  display: block;
+}
+
+.nav-panel-explore .component + .component {
+  margin-top: 0.75rem;
+}
+
+.nav-panel-explore .component:last-child {
+  margin-bottom: 0.75rem;
+}
+
+.nav-panel-explore .component .title {
+  font-weight: var(--body-font-weight-bold);
+  text-indent: 0.375rem hanging;
+}
+
+.nav-panel-explore .versions {
+  display: flex;
+  flex-wrap: wrap;
+  padding-left: 0;
+  margin: -0.125rem -0.375rem 0 0.375rem;
+  line-height: 1;
+  list-style: none;
+}
+
+.nav-panel-explore .component .version {
+  margin: 0.375rem 0.375rem 0 0;
+}
+
+.nav-panel-explore .component .version a {
+  background: var(--nav-border-color);
+  border-radius: 0.25rem;
+  white-space: nowrap;
+  padding: 0.25em 0.5em;
+  display: inherit;
+  opacity: 0.75;
+}
+
+.nav-panel-explore .component .is-current a {
+  background: var(--nav-heading-font-color);
+  color: var(--nav-secondary-background);
+  font-weight: var(--body-font-weight-bold);
+  opacity: 1;
+}
diff --git a/src/css/page-versions.css b/src/css/page-versions.css
new file mode 100644
index 0000000..5658aae
--- /dev/null
+++ b/src/css/page-versions.css
@@ -0,0 +1,56 @@
+.page-versions {
+  margin: 0 0.2rem 0 auto;
+  position: relative;
+  line-height: 1;
+}
+
+@media screen and (min-width: 1024px) {
+  .page-versions {
+    margin-right: 0.7rem;
+  }
+}
+
+.page-versions .version-menu-toggle {
+  color: inherit;
+  background: url(../img/chevron.svg) no-repeat;
+  background-position: right 0.5rem top 50%;
+  background-size: auto 0.75em;
+  border: none;
+  outline: none;
+  line-height: inherit;
+  padding: 0.5rem 1.5rem 0.5rem 0.5rem;
+  position: relative;
+  z-index: var(--z-index-page-version-menu);
+}
+
+.page-versions .version-menu {
+  display: flex;
+  min-width: 100%;
+  flex-direction: column;
+  align-items: flex-end;
+  background: linear-gradient(to bottom, var(--page-version-menu-background) 0%, var(--page-version-menu-background) 100%) no-repeat;
+  padding: 1.375rem 1.5rem 0.5rem 0.5rem;
+  position: absolute;
+  top: 0;
+  right: 0;
+  white-space: nowrap;
+}
+
+.page-versions:not(.is-active) .version-menu {
+  display: none;
+}
+
+.page-versions .version {
+  display: block;
+  padding-top: 0.5rem;
+}
+
+.page-versions .version.is-current {
+  display: none;
+}
+
+.page-versions .version.is-missing {
+  color: var(--page-version-missing-font-color);
+  font-style: italic;
+  text-decoration: none;
+}
diff --git a/src/css/pagination.css b/src/css/pagination.css
new file mode 100644
index 0000000..e3f2d49
--- /dev/null
+++ b/src/css/pagination.css
@@ -0,0 +1,63 @@
+nav.pagination {
+  display: flex;
+  border-top: 1px solid var(--toolbar-border-color);
+  line-height: 1;
+  margin: 2rem -1rem -1rem;
+  padding: 0.75rem 1rem 0;
+}
+
+nav.pagination span {
+  display: flex;
+  flex: 50%;
+  flex-direction: column;
+}
+
+nav.pagination .prev {
+  padding-right: 0.5rem;
+}
+
+nav.pagination .next {
+  margin-left: auto;
+  padding-left: 0.5rem;
+  text-align: right;
+}
+
+nav.pagination span::before {
+  color: var(--toolbar-muted-color);
+  font-size: 0.75em;
+  padding-bottom: 0.1em;
+}
+
+nav.pagination .prev::before {
+  content: "Prev";
+}
+
+nav.pagination .next::before {
+  content: "Next";
+}
+
+nav.pagination a {
+  font-weight: var(--body-font-weight-bold);
+  line-height: 1.3;
+  position: relative;
+}
+
+nav.pagination a::before,
+nav.pagination a::after {
+  color: var(--toolbar-muted-color);
+  font-weight: normal;
+  font-size: 1.5em;
+  line-height: 0.75;
+  position: absolute;
+  top: 0;
+  width: 1rem;
+}
+
+nav.pagination .prev a::before {
+  content: "\2039";
+  transform: translateX(-100%);
+}
+
+nav.pagination .next a::after {
+  content: "\203a";
+}
diff --git a/src/css/print.css b/src/css/print.css
new file mode 100644
index 0000000..62fc6b4
--- /dev/null
+++ b/src/css/print.css
@@ -0,0 +1,88 @@
+@page {
+  margin: 0.5in;
+}
+
+@media print {
+  .hide-for-print {
+    display: none !important;
+  }
+
+  html {
+    font-size: var(--body-font-size--print);
+  }
+
+  a {
+    color: inherit !important;
+    text-decoration: underline;
+  }
+
+  a.bare,
+  a[href^="#"],
+  a[href^="mailto:"] {
+    text-decoration: none;
+  }
+
+  tr,
+  img,
+  object,
+  svg {
+    page-break-inside: avoid;
+  }
+
+  thead {
+    display: table-header-group;
+  }
+
+  pre {
+    hyphens: none;
+    white-space: pre-wrap;
+  }
+
+  body {
+    padding-top: 2rem;
+  }
+
+  .navbar {
+    background: none;
+    color: inherit;
+    position: absolute;
+  }
+
+  .navbar * {
+    color: inherit !important;
+  }
+
+  .navbar > :not(.navbar-brand),
+  .nav-container,
+  .toolbar,
+  aside.toc,
+  nav.pagination {
+    display: none;
+  }
+
+  .doc {
+    color: inherit;
+    margin: auto;
+    max-width: none;
+    padding-bottom: 2rem;
+  }
+
+  .doc .admonitionblock td.icon {
+    color-adjust: exact;
+  }
+
+  .doc .listingblock code[data-lang]::before {
+    display: block;
+  }
+
+  footer.footer {
+    background: none;
+    border-top: 1px solid var(--panel-border-color);
+    color: var(--quote-attribution-font-color);
+    padding: 0.25rem 0.5rem 0;
+  }
+
+  .footer * {
+    color: inherit;
+  }
+}
diff --git a/src/css/site.css b/src/css/site.css
new file mode 100644
index 0000000..36e1767
--- /dev/null
+++ b/src/css/site.css
@@ -0,0 +1,17 @@
+@import "typeface-roboto.css";
+@import "typeface-roboto-mono.css";
+@import "vars.css";
+@import "base.css";
+@import "body.css";
+@import "nav.css";
+@import "main.css";
+@import "toolbar.css";
+@import "breadcrumbs.css";
+@import "page-versions.css";
+@import "toc.css";
+@import "doc.css";
+@import "pagination.css";
+@import "header.css";
+@import "footer.css";
+@import "highlight.css";
+@import "print.css";
diff --git a/src/css/toc.css b/src/css/toc.css
new file mode 100644
index 0000000..dc33497
--- /dev/null
+++ b/src/css/toc.css
@@ -0,0 +1,98 @@
+.toc-menu {
+  color: var(--toc-font-color);
+}
+
+.toc.sidebar .toc-menu {
+  margin-right: 0.75rem;
+  position: sticky;
+  top: var(--toc-top);
+}
+
+.toc .toc-menu h3 {
+  color: var(--toc-heading-font-color);
+  font-size: calc(16 / var(--rem-base) * 1rem);
+  font-weight: var(--body-font-weight-bold);
+  line-height: 1.3;
+  margin: 0 -0.5px;
+  padding-bottom: 0.25rem;
+}
+
+.toc.sidebar .toc-menu h3 {
+  display: flex;
+  flex-direction: column;
+  height: 2.5rem;
+  justify-content: flex-end;
+}
+
+.toc .toc-menu ul {
+  font-size: calc(15 / var(--rem-base) * 1rem);
+  line-height: var(--toc-line-height);
+  list-style: none;
+  margin: 0;
+  padding: 0;
+}
+
+.toc.sidebar .toc-menu ul {
+  max-height: var(--toc-height);
+  overflow-y: auto;
+  overscroll-behavior: none;
+}
+
+@supports (scrollbar-width: none) {
+  .toc.sidebar .toc-menu ul {
+    scrollbar-width: none;
+  }
+}
+
+.toc .toc-menu ul::-webkit-scrollbar {
+  width: 0;
+  height: 0;
+}
+
+@media screen and (min-width: 1024px) {
+  .toc .toc-menu h3 {
+    font-size: calc(15 / var(--rem-base) * 1rem);
+  }
+
+  .toc .toc-menu ul {
+    font-size: calc(13.5 / var(--rem-base) * 1rem);
+  }
+}
+
+.toc .toc-menu li {
+  margin: 0;
+}
+
+.toc .toc-menu li[data-level="2"] a {
+  padding-left: 1.25rem;
+}
+
+.toc .toc-menu li[data-level="3"] a {
+  padding-left: 2rem;
+}
+
+.toc .toc-menu a {
+  color: inherit;
+  border-left: 2px solid var(--toc-border-color);
+  display: inline-block;
+  padding: 0.25rem 0 0.25rem 0.5rem;
+  text-decoration: none;
+}
+
+.sidebar.toc .toc-menu a {
+  display: block;
+  outline: none;
+}
+
+.toc .toc-menu a:hover {
+  color: var(--link-font-color);
+}
+
+.toc .toc-menu a.is-active {
+  border-left-color: var(--link-font-color);
+  color: var(--doc-font-color);
+}
+
+.sidebar.toc .toc-menu a:focus {
+  background: var(--panel-background);
+}
diff --git a/src/css/toolbar.css b/src/css/toolbar.css
new file mode 100644
index 0000000..7f38488
--- /dev/null
+++ b/src/css/toolbar.css
@@ -0,0 +1,68 @@
+.toolbar {
+  color: var(--toolbar-font-color);
+  align-items: center;
+  background-color: var(--toolbar-background);
+  box-shadow: 0 1px 0 var(--toolbar-border-color);
+  display: flex;
+  font-size: calc(15 / var(--rem-base) * 1rem);
+  height: var(--toolbar-height);
+  justify-content: flex-start;
+  position: sticky;
+  top: var(--navbar-height);
+  z-index: var(--z-index-toolbar);
+}
+
+.toolbar a {
+  color: inherit;
+}
+
+.nav-toggle {
+  background: url(../img/menu.svg) no-repeat 50% 47.5%;
+  background-size: 49%;
+  border: none;
+  outline: none;
+  line-height: inherit;
+  padding: 0;
+  height: var(--toolbar-height);
+  width: var(--toolbar-height);
+  margin-right: -0.25rem;
+}
+
+@media screen and (min-width: 1024px) {
+  .nav-toggle {
+    display: none;
+  }
+}
+
+.nav-toggle.is-active {
+  background-image: url(../img/back.svg);
+  background-size: 41.5%;
+}
+
+.home-link {
+  display: block;
+  background: url(../img/home-o.svg) no-repeat center;
+  height: calc(var(--toolbar-height) / 2);
+  width: calc(var(--toolbar-height) / 2);
+  margin: calc(var(--toolbar-height) / 4);
+}
+
+.home-link:hover,
+.home-link.is-current {
+  background-image: url(../img/home.svg);
+}
+
+.edit-this-page {
+  display: none;
+  padding-right: 0.5rem;
+}
+
+@media screen and (min-width: 1024px) {
+  .edit-this-page {
+    display: block;
+  }
+}
+
+.toolbar .edit-this-page a {
+  color: var(--toolbar-muted-color);
+}
diff --git a/src/css/typeface-roboto-mono.css b/src/css/typeface-roboto-mono.css
new file mode 100644
index 0000000..b25128c
--- /dev/null
+++ b/src/css/typeface-roboto-mono.css
@@ -0,0 +1,39 @@
+@font-face {
+  font-family: "Roboto Mono";
+  font-style: normal;
+  font-weight: 400;
+  src:
+    url(~@fontsource/roboto-mono/files/roboto-mono-latin-400-normal.woff2) format("woff2"),
+    url(~@fontsource/roboto-mono/files/roboto-mono-latin-400-normal.woff) format("woff");
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+
+/*
+@font-face {
+  font-family: "Roboto Mono";
+  font-style: normal;
+  font-weight: 400;
+  src: url(~@fontsource/roboto-mono/files/roboto-mono-cyrillic-400-normal.woff2) format("woff2");
+  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+*/
+
+@font-face {
+  font-family: "Roboto Mono";
+  font-style: normal;
+  font-weight: 600;
+  src:
+    url(~@fontsource/roboto-mono/files/roboto-mono-latin-500-normal.woff2) format("woff2"),
+    url(~@fontsource/roboto-mono/files/roboto-mono-latin-500-normal.woff) format("woff");
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+
+/*
+@font-face {
+  font-family: "Roboto Mono";
+  font-style: normal;
+  font-weight: 600;
+  src: url(~@fontsource/roboto-mono/files/roboto-mono-cyrillic-500-normal.woff2) format("woff2");
+  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+*/
diff --git a/src/css/typeface-roboto.css b/src/css/typeface-roboto.css
new file mode 100644
index 0000000..931cc2c
--- /dev/null
+++ b/src/css/typeface-roboto.css
@@ -0,0 +1,71 @@
+@font-face {
+  font-family: "Roboto";
+  font-style: normal;
+  font-weight: 400;
+  src:
+    url(~@fontsource/roboto/files/roboto-latin-400-normal.woff2) format("woff2"),
+    url(~@fontsource/roboto/files/roboto-latin-400-normal.woff) format("woff");
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+
+@font-face {
+  font-family: "Roboto";
+  font-style: normal;
+  font-weight: 400;
+  src: url(~@fontsource/roboto/files/roboto-cyrillic-400-normal.woff2) format("woff2");
+  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+
+@font-face {
+  font-family: "Roboto";
+  font-style: italic;
+  font-weight: 400;
+  src:
+    url(~@fontsource/roboto/files/roboto-latin-400-italic.woff2) format("woff2"),
+    url(~@fontsource/roboto/files/roboto-latin-400-italic.woff) format("woff");
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+
+@font-face {
+  font-family: "Roboto";
+  font-style: italic;
+  font-weight: 400;
+  src: url(~@fontsource/roboto/files/roboto-cyrillic-400-italic.woff2) format("woff2");
+  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+
+@font-face {
+  font-family: "Roboto";
+  font-style: normal;
+  font-weight: 600;
+  src:
+    url(~@fontsource/roboto/files/roboto-latin-500-normal.woff2) format("woff2"),
+    url(~@fontsource/roboto/files/roboto-latin-500-normal.woff) format("woff");
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+
+@font-face {
+  font-family: "Roboto";
+  font-style: normal;
+  font-weight: 600;
+  src: url(~@fontsource/roboto/files/roboto-cyrillic-500-normal.woff2) format("woff2");
+  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+
+@font-face {
+  font-family: "Roboto";
+  font-style: italic;
+  font-weight: 600;
+  src:
+    url(~@fontsource/roboto/files/roboto-latin-500-italic.woff2) format("woff2"),
+    url(~@fontsource/roboto/files/roboto-latin-500-italic.woff) format("woff");
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+
+@font-face {
+  font-family: "Roboto";
+  font-style: italic;
+  font-weight: 600;
+  src: url(~@fontsource/roboto/files/roboto-cyrillic-500-italic.woff2) format("woff2");
+  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
diff --git a/src/css/vars.css b/src/css/vars.css
new file mode 100644
index 0000000..91c9c09
--- /dev/null
+++ b/src/css/vars.css
@@ -0,0 +1,146 @@
+:root {
+  /* colors */
+  --color-white: #fff;
+  --color-smoke-10: #fefefe;
+  --color-smoke-30: #fafafa;
+  --color-smoke-50: #f5f5f5;
+  --color-smoke-70: #f0f0f0;
+  --color-smoke-90: #e1e1e1;
+  --color-gray-10: #c1c1c1;
+  --color-gray-30: #9c9c9c;
+  --color-gray-40: #8e8e8e;
+  --color-gray-50: #808080;
+  --color-gray-70: #5d5d5d;
+  --color-jet-20: #4a4a4a;
+  --color-jet-30: #424242;
+  --color-jet-50: #333;
+  --color-jet-70: #222;
+  --color-jet-80: #191919;
+  --color-black: #000;
+  /* fonts */
+  --rem-base: 18; /* used to compute rem value from desired pixel value (e.g., calc(18 / var(--rem-base) * 1rem) = 18px) */
+  --body-font-size: 1.0625em; /* 17px */
+  --body-font-size--desktop: 1.125em; /* 18px */
+  --body-font-size--print: 0.9375em; /* 15px */
+  --body-line-height: 1.15;
+  --body-font-color: var(--color-jet-70);
+  --body-font-family: "Roboto", sans-serif;
+  --body-font-weight-bold: 600;
+  --monospace-font-family: "Roboto Mono", monospace;
+  --monospace-font-weight-bold: 600;
+  /* base */
+  --body-background: var(--color-white);
+  --panel-background: var(--color-smoke-30);
+  --panel-border-color: var(--color-smoke-90);
+  --scrollbar-track-color: var(--color-smoke-30);
+  --scrollbar-thumb-color: var(--color-gray-10);
+  --scrollbar_hover-thumb-color: var(--color-gray-30);
+  /* navbar */
+  --navbar-background: var(--color-jet-80);
+  --navbar-font-color: var(--color-white);
+  --navbar_hover-background: var(--color-black);
+  --navbar-button-background: var(--color-white);
+  --navbar-button-border-color: var(--panel-border-color);
+  --navbar-button-font-color: var(--body-font-color);
+  --navbar-menu-border-color: var(--panel-border-color);
+  --navbar-menu-background: var(--color-white);
+  --navbar-menu-font-color: var(--body-font-color);
+  --navbar-menu_hover-background: var(--color-smoke-50);
+  /* nav */
+  --nav-background: var(--panel-background);
+  --nav-border-color: var(--color-gray-10);
+  --nav-line-height: 1.35;
+  --nav-heading-font-color: var(--color-jet-30);
+  --nav-muted-color: var(--color-gray-70);
+  --nav-panel-divider-color: var(--color-smoke-90);
+  --nav-secondary-background: var(--color-smoke-70);
+  /* toolbar */
+  --toolbar-background: var(--panel-background);
+  --toolbar-border-color: var(--panel-border-color);
+  --toolbar-font-color: var(--color-gray-70);
+  --toolbar-muted-color: var(--color-gray-40);
+  --page-version-menu-background: var(--color-smoke-70);
+  --page-version-missing-font-color: var(--color-gray-40);
+  /* admonitions */
+  --caution-color: #a0439c;
+  --caution-on-color: var(--color-white);
+  --important-color: #d32f2f;
+  --important-on-color: var(--color-white);
+  --note-color: #217ee7;
+  --note-on-color: var(--color-white);
+  --tip-color: #41af46;
+  --tip-on-color: var(--color-white);
+  --warning-color: #e18114;
+  --warning-on-color: var(--color-white);
+  /* doc */
+  --doc-font-color: var(--color-jet-50);
+  --doc-font-size: inherit;
+  --doc-font-size--desktop: calc(17 / var(--rem-base) * 1rem);
+  --doc-line-height: 1.6;
+  --doc-margin: 0 auto;
+  --doc-margin--desktop: 0 2rem;
+  --heading-font-color: var(--color-jet-80);
+  --heading-font-weight: normal;
+  --alt-heading-font-weight: var(--body-font-weight-bold);
+  --section-divider-color: var(--panel-border-color);
+  --link-font-color: #1565c0;
+  --link_hover-font-color: #104d92;
+  --link_unresolved-font-color: var(--important-color);
+  --abstract-background: var(--color-smoke-70);
+  --abstract-font-color: var(--color-jet-20);
+  --abstract-border-color: var(--panel-border-color);
+  --admonition-background: var(--panel-background);
+  --admonition-label-font-weight: var(--body-font-weight-bold);
+  --caption-font-color: var(--color-gray-70);
+  --caption-font-style: italic;
+  --caption-font-weight: var(--body-font-weight-bold);
+  --code-background: var(--panel-background);
+  --code-font-color: var(--body-font-color);
+  --example-background: var(--color-white);
+  --example-border-color: var(--color-gray-70);
+  --kbd-background: var(--panel-background);
+  --kbd-border-color: var(--color-gray-10);
+  --pre-background: var(--panel-background);
+  --pre-border-color: var(--panel-border-color);
+  --pre-annotation-font-color: var(--color-gray-50);
+  --quote-background: var(--panel-background);
+  --quote-border-color: var(--color-gray-70);
+  --quote-font-color: var(--color-gray-70);
+  --quote-attribution-font-color: var(--color-gray-40);
+  --sidebar-background: var(--color-smoke-90);
+  --table-border-color: var(--panel-border-color);
+  --table-stripe-background: var(--panel-background);
+  --table-footer-background: linear-gradient(to bottom, var(--color-smoke-70) 0%, var(--color-white) 100%);
+  /* toc */
+  --toc-font-color: var(--nav-muted-color);
+  --toc-heading-font-color: var(--doc-font-color);
+  --toc-border-color: var(--panel-border-color);
+  --toc-line-height: 1.2;
+  /* footer */
+  --footer-line-height: var(--doc-line-height);
+  --footer-background: var(--color-smoke-90);
+  --footer-font-color: var(--color-gray-70);
+  --footer-link-font-color: var(--color-jet-80);
+  /* dimensions and positioning */
+  --navbar-height: calc(63 / var(--rem-base) * 1rem);
+  --toolbar-height: calc(45 / var(--rem-base) * 1rem);
+  --drawer-height: var(--toolbar-height);
+  --body-top: var(--navbar-height);
+  --body-min-height: calc(100vh - var(--body-top));
+  --nav-height: calc(var(--body-min-height) - var(--toolbar-height));
+  --nav-height--desktop: var(--body-min-height);
+  --nav-panel-menu-height: calc(100% - var(--drawer-height));
+  --nav-panel-explore-height: calc(50% + var(--drawer-height));
+  --nav-width: calc(270 / var(--rem-base) * 1rem);
+  --toc-top: calc(var(--body-top) + var(--toolbar-height));
+  --toc-height: calc(100vh - var(--toc-top) - 2.5rem);
+  --toc-width: calc(162 / var(--rem-base) * 1rem);
+  --toc-width--widescreen: calc(216 / var(--rem-base) * 1rem);
+  --doc-max-width: calc(720 / var(--rem-base) * 1rem);
+  --doc-max-width--desktop: calc(828 / var(--rem-base) * 1rem);
+  /* stacking */
+  --z-index-nav: 1;
+  --z-index-toolbar: 2;
+  --z-index-page-version-menu: 3;
+  --z-index-navbar: 4;
+}
diff --git a/src/helpers/and.js b/src/helpers/and.js
new file mode 100644
index 0000000..5637b15
--- /dev/null
+++ b/src/helpers/and.js
@@ -0,0 +1,9 @@
+'use strict'
+
+module.exports = (...args) => {
+  const numArgs = args.length
+  if (numArgs === 3) return args[0] && args[1]
+  if (numArgs < 3) throw new Error('{{and}} helper expects at least 2 arguments')
+  args.pop()
+  return args.every((it) => it)
+}
diff --git a/src/helpers/detag.js b/src/helpers/detag.js
new file mode 100644
index 0000000..e32f147
--- /dev/null
+++ b/src/helpers/detag.js
@@ -0,0 +1,5 @@
+'use strict'
+
+const TAG_ALL_RX = /<[^>]+>/g
+
+module.exports = (html) => html && html.replace(TAG_ALL_RX, '')
diff --git a/src/helpers/eq.js b/src/helpers/eq.js
new file mode 100644
index 0000000..16dc287
--- /dev/null
+++ b/src/helpers/eq.js
@@ -0,0 +1,3 @@
+'use strict'
+
+module.exports = (a, b) => a === b
diff --git a/src/helpers/increment.js b/src/helpers/increment.js
new file mode 100644
index 0000000..bb8f7e1
--- /dev/null
+++ b/src/helpers/increment.js
@@ -0,0 +1,3 @@
+'use strict'
+
+module.exports = (value) => (value || 0) + 1
diff --git a/src/helpers/ne.js b/src/helpers/ne.js
new file mode 100644
index 0000000..245f03b
--- /dev/null
+++ b/src/helpers/ne.js
@@ -0,0 +1,3 @@
+'use strict'
+
+module.exports = (a, b) => a !== b
diff --git a/src/helpers/not.js b/src/helpers/not.js
new file mode 100644
index 0000000..8b3aa91
--- /dev/null
+++ b/src/helpers/not.js
@@ -0,0 +1,3 @@
+'use strict'
+
+module.exports = (val) => !val
diff --git a/src/helpers/or.js b/src/helpers/or.js
new file mode 100644
index 0000000..eb53907
--- /dev/null
+++ b/src/helpers/or.js
@@ -0,0 +1,9 @@
+'use strict'
+
+module.exports = (...args) => {
+  const numArgs = args.length
+  if (numArgs === 3) return args[0] || args[1]
+  if (numArgs < 3) throw new Error('{{or}} helper expects at least 2 arguments')
+  args.pop()
+  return args.some((it) => it)
+}
diff --git a/src/helpers/relativize.js b/src/helpers/relativize.js
new file mode 100644
index 0000000..7989319
--- /dev/null
+++ b/src/helpers/relativize.js
@@ -0,0 +1,24 @@
+'use strict'
+
+const { posix: path } = require('path')
+
+module.exports = (to, from, ctx) => {
+  if (!to) return '#'
+  if (to.charAt() !== '/') return to
+  // NOTE only legacy invocation provides both to and from
+  if (!ctx) from = (ctx = from).data.root.page.url
+  if (!from) return (ctx.data.root.site.path || '') + to
+  let hash = ''
+  const hashIdx = to.indexOf('#')
+  if (~hashIdx) {
+    hash = to.slice(hashIdx)
+    to = to.slice(0, hashIdx)
+  }
+  if (to === from) return hash || (isDir(to) ? './' : path.basename(to))
+  const rel = path.relative(path.dirname(from + '.'), to)
+  return rel ? (isDir(to) ? rel + '/' : rel) + hash : (isDir(to) ? './' : '../' + path.basename(to)) + hash
+}
+
+function isDir (str) {
+  return str.charAt(str.length - 1) === '/'
+}
diff --git a/src/helpers/year.js b/src/helpers/year.js
new file mode 100644
index 0000000..aa38992
--- /dev/null
+++ b/src/helpers/year.js
@@ -0,0 +1,3 @@
+'use strict'
+
+module.exports = () => new Date().getFullYear().toString()
diff --git a/src/img/back.svg b/src/img/back.svg
new file mode 100644
index 0000000..1a66e8d
--- /dev/null
+++ b/src/img/back.svg
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ 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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="100"
+ height="100"
+ viewBox="0 0 100 100"
+ version="1.1"
+ inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
+ sodipodi:docname="back.svg"
+ enable-background="new">
+<title>Left arrow</title>
+<sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="6.108138"
+ inkscape:cx="21.142679"
+ inkscape:cy="42.629076"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ units="px"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="1920"
+ inkscape:window-height="1001"
+ inkscape:window-x="0"
+ inkscape:window-y="41"
+ inkscape:window-maximized="1"
+ scale-x="1" />
+<metadata>
+<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>Left arrow</dc:title>
+<dc:creator>
+<cc:Agent>
+<dc:title>Sarah White</dc:title>
+</cc:Agent>
+</dc:creator>
+<dc:publisher>
+<cc:Agent>
+<dc:title>OpenDevise Inc.</dc:title>
+</cc:Agent>
+</dc:publisher>
+<cc:license
+ rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
+</cc:Work>
+<cc:License
+ rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
+<cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction" />
+<cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution" />
+<cc:requires
+ rdf:resource="http://creativecommons.org/ns#Notice" />
+<cc:requires
+ rdf:resource="http://creativecommons.org/ns#Attribution" />
+<cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+<cc:requires
+ rdf:resource="http://creativecommons.org/ns#ShareAlike" />
+</cc:License>
+</rdf:RDF>
+</metadata>
+<g
+ transform="translate(-3.926492e-7,-270.54187)">
+<path
+ d="m 50.000978,280.44162 -40.1010516,40.10025 40.1010516,40.10025 5.6556,-5.65551 -30.434757,-30.44194 h 64.878253 v -8.0056 H 25.221821 l 30.434757,-30.44001 z" />
+</g>
+</svg>
diff --git a/src/img/caret.svg b/src/img/caret.svg
new file mode 100644
index 0000000..faea566
--- /dev/null
+++ b/src/img/caret.svg
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="30"
+   height="30"
+   viewBox="0 0 30 30"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="caret.svg">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="16"
+     inkscape:cx="31.65919"
+     inkscape:cy="23.730414"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     units="px"
+     inkscape:window-width="2688"
+     inkscape:window-height="1478"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata7">
+    <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="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-1022.3622)">
+    <path
+       style="opacity:1;fill:#c1c1c1;fill-opacity:1;stroke:#c1c1c1;stroke-width:1.99999976;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       d="m 10.18745,1025.362 14.0001,12.0002 -14.0001,12.0001 z"
+       id="rect3338"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccc"
+       inkscape:transform-center-x="-2.1875" />
+  </g>
+</svg>
diff --git a/src/img/chevron.svg b/src/img/chevron.svg
new file mode 100644
index 0000000..836c90f
--- /dev/null
+++ b/src/img/chevron.svg
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="30"
+   height="30"
+   viewBox="0 0 30 30"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="chevron.svg">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="22.627417"
+     inkscape:cx="10.05311"
+     inkscape:cy="10.530062"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     units="px"
+     inkscape:window-width="2560"
+     inkscape:window-height="1406"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata7">
+    <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="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-1022.3622)">
+    <path
+       style="opacity:1;fill:#5d5d5d;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 3.6699219,6.5898438 1.4550781,8.6152344 15,23.374272 28.544922,8.6152344 26.330078,6.5898438 15,18.759498 Z"
+       transform="translate(0,1022.3622)"
+       id="rect4136"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccc" />
+  </g>
+</svg>
diff --git a/src/img/home-o.svg b/src/img/home-o.svg
new file mode 100644
index 0000000..02e64b8
--- /dev/null
+++ b/src/img/home-o.svg
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   x="0px"
+   y="0px"
+   viewBox="0 0 100 100"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="home.svg">
+  <metadata
+     id="metadata12">
+    <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>
+  <defs
+     id="defs10">
+    <inkscape:path-effect
+       is_visible="true"
+       id="path-effect4225"
+       effect="spiro" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4221"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4213"
+       is_visible="true" />
+    <inkscape:path-effect
+       is_visible="true"
+       id="path-effect4209"
+       effect="spiro" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4204"
+       is_visible="true" />
+    <inkscape:path-effect
+       is_visible="true"
+       id="path-effect4191"
+       effect="spiro" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4187"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4183"
+       is_visible="true" />
+    <inkscape:path-effect
+       is_visible="true"
+       id="path-effect4179"
+       effect="spiro" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4173"
+       is_visible="true" />
+    <inkscape:path-effect
+       is_visible="true"
+       id="path-effect4169"
+       effect="spiro" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4165"
+       is_visible="true" />
+  </defs>
+  <sodipodi:namedview
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="2560"
+     inkscape:window-height="1406"
+     id="namedview8"
+     showgrid="false"
+     inkscape:zoom="8.1458701"
+     inkscape:cx="33.343764"
+     inkscape:cy="44.907032"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g4" />
+  <g
+     transform="translate(0,-952.36218)"
+     id="g4">
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#222;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
+       d="M 50.019531 13.576172 L 21.439453 39.115234 L 21.419922 86.460938 L 42.925781 86.460938 L 42.951172 61.294922 L 57.048828 61.294922 L 57.074219 86.460938 L 78.619141 86.460938 L 78.638672 39.150391 L 50.019531 13.576172 z "
+       id="path4175"
+       transform="translate(0,952.36218)" />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#222;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 63.815035,25.903568 0,-9.217018 8.656932,0 -2e-6,16.95383 z"
+       id="path4193"
+       transform="translate(0,952.36218)"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;fill-rule:evenodd;stroke:#222;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 21.43888,991.47783 -9.98234,8.92037"
+       id="path4177" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;fill-rule:evenodd;stroke:#222;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 88.58189,1000.3982 -9.94315,-8.88535"
+       id="path4170" />
+  </g>
+</svg>
diff --git a/src/img/home.svg b/src/img/home.svg
new file mode 100644
index 0000000..06ca956
--- /dev/null
+++ b/src/img/home.svg
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   x="0px"
+   y="0px"
+   viewBox="0 0 100 100"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="home-hovered.svg">
+  <metadata
+     id="metadata12">
+    <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>
+  <defs
+     id="defs10">
+    <inkscape:path-effect
+       is_visible="true"
+       id="path-effect4225"
+       effect="spiro" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4221"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4213"
+       is_visible="true" />
+    <inkscape:path-effect
+       is_visible="true"
+       id="path-effect4209"
+       effect="spiro" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4204"
+       is_visible="true" />
+    <inkscape:path-effect
+       is_visible="true"
+       id="path-effect4191"
+       effect="spiro" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4187"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4183"
+       is_visible="true" />
+    <inkscape:path-effect
+       is_visible="true"
+       id="path-effect4179"
+       effect="spiro" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4173"
+       is_visible="true" />
+    <inkscape:path-effect
+       is_visible="true"
+       id="path-effect4169"
+       effect="spiro" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4165"
+       is_visible="true" />
+  </defs>
+  <sodipodi:namedview
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="2560"
+     inkscape:window-height="1406"
+     id="namedview8"
+     showgrid="false"
+     inkscape:zoom="8.1458701"
+     inkscape:cx="-15.147065"
+     inkscape:cy="42.942846"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g4" />
+  <g
+     transform="translate(0,-952.36218)"
+     id="g4">
+    <path
+       style="fill:#222;fill-rule:evenodd;stroke:#222;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
+       d="M 50.019531 13.576172 L 21.439453 39.115234 L 21.419922 86.460938 L 42.925781 86.460938 L 42.951172 61.294922 L 57.048828 61.294922 L 57.074219 86.460938 L 78.619141 86.460938 L 78.638672 39.150391 L 50.019531 13.576172 z "
+       id="path4175"
+       transform="translate(0,952.36218)" />
+    <path
+       style="fill:#222;fill-rule:evenodd;stroke:#222;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
+       d="m 63.815035,25.903568 0,-9.217018 8.656932,0 -2e-6,16.95383 z"
+       id="path4193"
+       transform="translate(0,952.36218)"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;fill-rule:evenodd;stroke:#222;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 21.43888,991.47783 -9.98234,8.92037"
+       id="path4177" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;fill-rule:evenodd;stroke:#222;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 88.58189,1000.3982 -9.94315,-8.88535"
+       id="path4170" />
+  </g>
+</svg>
diff --git a/src/img/menu.svg b/src/img/menu.svg
new file mode 100644
index 0000000..211102b
--- /dev/null
+++ b/src/img/menu.svg
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   x="0px"
+   y="0px"
+   viewBox="0 0 100 100"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="menu.svg">
+  <metadata
+     id="metadata12">
+    <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>
+  <defs
+     id="defs10">
+    <inkscape:path-effect
+       is_visible="true"
+       id="path-effect4225"
+       effect="spiro" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4221"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4213"
+       is_visible="true" />
+    <inkscape:path-effect
+       is_visible="true"
+       id="path-effect4209"
+       effect="spiro" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4204"
+       is_visible="true" />
+    <inkscape:path-effect
+       is_visible="true"
+       id="path-effect4191"
+       effect="spiro" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4187"
+       is_visible="true" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4183"
+       is_visible="true" />
+    <inkscape:path-effect
+       is_visible="true"
+       id="path-effect4179"
+       effect="spiro" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4173"
+       is_visible="true" />
+    <inkscape:path-effect
+       is_visible="true"
+       id="path-effect4169"
+       effect="spiro" />
+    <inkscape:path-effect
+       effect="spiro"
+       id="path-effect4165"
+       is_visible="true" />
+  </defs>
+  <sodipodi:namedview
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="2560"
+     inkscape:window-height="1406"
+     id="namedview8"
+     showgrid="false"
+     inkscape:zoom="5.76"
+     inkscape:cx="14.532031"
+     inkscape:cy="43.425849"
+     inkscape:window-x="0"
+     inkscape:window-y="1440"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g4" />
+  <g
+     transform="translate(0,-952.36218)"
+     id="g4">
+    <g
+       id="g4238"
+       transform="translate(-1.5e-6,-0.2053541)">
+      <path
+         sodipodi:nodetypes="cc"
+         inkscape:connector-curvature="0"
+         id="path4149"
+         d="m 35,972.34003 55.000003,0"
+         style="fill:none;fill-rule:evenodd;stroke:#222;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647" />
+      <rect
+         y="964.84003"
+         x="10"
+         height="15"
+         width="15"
+         id="rect4184"
+         style="opacity:1;fill:#222;fill-opacity:1;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <path
+         style="fill:none;fill-rule:evenodd;stroke:#222;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
+         d="m 42.999999,1016.2452 44.999999,0"
+         id="path4180"
+         inkscape:connector-curvature="0"
+         sodipodi:nodetypes="cc" />
+      <rect
+         style="opacity:1;fill:#222;fill-opacity:1;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect4186"
+         width="10"
+         height="10"
+         x="23"
+         y="1011.2452" />
+      <path
+         sodipodi:nodetypes="cc"
+         inkscape:connector-curvature="0"
+         id="path4182"
+         d="m 42.999999,1035.295 44.999999,0"
+         style="fill:none;fill-rule:evenodd;stroke:#222;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647" />
+      <rect
+         y="1030.295"
+         x="23"
+         height="10"
+         width="10"
+         id="rect4188"
+         style="opacity:1;fill:#222;fill-opacity:1;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <path
+         sodipodi:nodetypes="cc"
+         inkscape:connector-curvature="0"
+         id="path4210"
+         d="m 42.999999,997.1955 44.999999,0"
+         style="fill:none;fill-rule:evenodd;stroke:#222;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647" />
+      <rect
+         y="992.1955"
+         x="23"
+         height="10"
+         width="10"
+         id="rect4212"
+         style="opacity:1;fill:#222;fill-opacity:1;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    </g>
+  </g>
+</svg>
diff --git a/src/img/octicons-16.svg b/src/img/octicons-16.svg
new file mode 100644
index 0000000..0e8ab39
--- /dev/null
+++ b/src/img/octicons-16.svg
@@ -0,0 +1,51 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
+  <title>Octicons (16px subset)</title>
+  <desc>Octicons v11.2.0 by GitHub - https://primer.style/octicons/ - License: MIT</desc>
+  <metadata
+    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#">
+    <rdf:RDF>
+      <cc:Work rdf:about="">
+        <dc:title>@primer/octicons</dc:title>
+        <dc:identifier>11.2.0</dc:identifier>
+        <dc:description>A scalable set of icons handcrafted with &lt;3 by GitHub</dc:description>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>GitHub</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:rights>
+          <cc:Agent>
+            <dc:title>Copyright (c) 2020 GitHub Inc.</dc:title>
+          </cc:Agent>
+        </dc:rights>
+        <cc:license rdf:resource="https://opensource.org/licenses/MIT" />
+        <dc:relation>https://primer.style/octicons/</dc:relation>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <symbol id="icon-clippy" viewBox="0 0 16 16">
+    <path
+       fill-rule="evenodd"
+       d="M5.75 1a.75.75 0 00-.75.75v3c0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75v-3a.75.75 0 00-.75-.75h-4.5zm.75 3V2.5h3V4h-3zm-2.874-.467a.75.75 0 00-.752-1.298A1.75 1.75 0 002 3.75v9.5c0 .966.784 1.75 1.75 1.75h8.5A1.75 1.75 0 0014 13.25v-9.5a1.75 1.75 0 00-.874-1.515.75.75 0 10-.752 1.298.25.25 0 01.126.217v9.5a.25.25 0 01-.25.25h-8.5a.25.25 0 01-.25-.25v-9.5a.25.25 0 01.126-.217z" />
+  </symbol>
+
+  <symbol id="icon-fold" viewBox="0 0 16 16">
+    <path d="M10.896 2H8.75V.75a.75.75 0 0 0-1.5 0V2H5.104a.25.25 0 0 0-.177.427l2.896 2.896a.25.25 0 0 0 .354 0l2.896-2.896A.25.25 0 0 0 10.896 2ZM8.75 15.25a.75.75 0 0 1-1.5 0V14H5.104a.25.25 0 0 1-.177-.427l2.896-2.896a.25.25 0 0 1 .354 0l2.896 2.896a.25.25 0 0 1-.177.427H8.75v1.25Zm-6.5-6.5a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5ZM6 8a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1 0-1.5h.5A.75.75 0 0 1 6 8Zm2.25.75a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5ZM12 8a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1 0-1.5h.5A.75.75 0 0 1 12 8Zm2.25.75a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5Z" />
+  </symbol>
+
+  <symbol id="icon-unfold" viewBox="0 0 16 16">
+    <path d="m8.177.677 2.896 2.896a.25.25 0 0 1-.177.427H8.75v1.25a.75.75 0 0 1-1.5 0V4H5.104a.25.25 0 0 1-.177-.427L7.823.677a.25.25 0 0 1 .354 0ZM7.25 10.75a.75.75 0 0 1 1.5 0V12h2.146a.25.25 0 0 1 .177.427l-2.896 2.896a.25.25 0 0 1-.354 0l-2.896-2.896A.25.25 0 0 1 5.104 12H7.25v-1.25Zm-5-2a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5ZM6 8a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1 0-1.5h.5A.75.75 0 0 1 6 8Zm2.25.75a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5ZM12 8a.75.75 0 0 1-.75.75h-.5a.75.75 0 0 1 0-1.5h.5A.75.75 0 0 1 12 8Zm2.25.75a.75.75 0 0 0 0-1.5h-.5a.75.75 0 0 0 0 1.5h.5Z" />
+  </symbol>
+
+  <use href="#icon-clippy" width="16" height="16" x="0" y="0" />
+  <view id="view-clippy" viewBox="0 0 16 16" />
+
+  <use href="#icon-fold" width="16" height="16" x="0" y="16" />
+  <view id="view-fold" viewBox="0 16 16 16" />
+
+  <use href="#icon-unfold" width="16" height="16" x="0" y="32" />
+  <view id="view-unfold" viewBox="0 32 16 16" />
+</svg>
diff --git a/src/js/01-nav.js b/src/js/01-nav.js
new file mode 100644
index 0000000..02ebe5d
--- /dev/null
+++ b/src/js/01-nav.js
@@ -0,0 +1,175 @@
+;(function () {
+  'use strict'
+
+  var SECT_CLASS_RX = /^sect(\d)$/
+
+  var navContainer = document.querySelector('.nav-container')
+  if (!navContainer) return
+  var navToggle = document.querySelector('.nav-toggle')
+  var nav = navContainer.querySelector('.nav')
+  var navMenuToggle = navContainer.querySelector('.nav-menu-toggle')
+
+  navToggle.addEventListener('click', showNav)
+  navContainer.addEventListener('click', trapEvent)
+
+  var menuPanel = navContainer.querySelector('[data-panel=menu]')
+  if (!menuPanel) return
+  var explorePanel = navContainer.querySelector('[data-panel=explore]')
+
+  var currentPageItem = menuPanel.querySelector('.is-current-page')
+  var originalPageItem = currentPageItem
+  if (currentPageItem) {
+    activateCurrentPath(currentPageItem)
+    scrollItemToMidpoint(menuPanel, currentPageItem.querySelector('.nav-link'))
+  } else {
+    menuPanel.scrollTop = 0
+  }
+
+  find(menuPanel, '.nav-item-toggle').forEach(function (btn) {
+    var li = btn.parentElement
+    btn.addEventListener('click', toggleActive.bind(li))
+    var navItemSpan = findNextElement(btn, '.nav-text')
+    if (navItemSpan) {
+      navItemSpan.style.cursor = 'pointer'
+      navItemSpan.addEventListener('click', toggleActive.bind(li))
+    }
+  })
+
+  if (navMenuToggle && menuPanel.querySelector('.nav-item-toggle')) {
+    navMenuToggle.style.display = ''
+    navMenuToggle.addEventListener('click', function () {
+      var collapse = !this.classList.toggle('is-active')
+      find(menuPanel, '.nav-item > .nav-item-toggle').forEach(function (btn) {
+        collapse ? btn.parentElement.classList.remove('is-active') : btn.parentElement.classList.add('is-active')
+      })
+      if (currentPageItem) {
+        if (collapse) activateCurrentPath(currentPageItem)
+        scrollItemToMidpoint(menuPanel, currentPageItem.querySelector('.nav-link'))
+      } else {
+        menuPanel.scrollTop = 0
+      }
+    })
+  }
+
+  if (explorePanel) {
+    explorePanel.querySelector('.context').addEventListener('click', function () {
+      // NOTE logic assumes there are only two panels
+      find(nav, '[data-panel]').forEach(function (panel) {
+        panel.classList.toggle('is-active')
+      })
+    })
+  }
+
+  // NOTE prevent text from being selected by double click
+  menuPanel.addEventListener('mousedown', function (e) {
+    if (e.detail > 1) e.preventDefault()
+  })
+
+  function onHashChange () {
+    var navLink
+    var hash = window.location.hash
+    if (hash) {
+      if (hash.indexOf('%')) hash = decodeURIComponent(hash)
+      navLink = menuPanel.querySelector('.nav-link[href="' + hash + '"]')
+      if (!navLink) {
+        var targetNode = document.getElementById(hash.slice(1))
+        if (targetNode) {
+          var current = targetNode
+          var ceiling = document.querySelector('article.doc')
+          while ((current = current.parentNode) && current !== ceiling) {
+            var id = current.id
+            // NOTE: look for section heading
+            if (!id && (id = SECT_CLASS_RX.test(current.className))) id = (current.firstElementChild || {}).id
+            if (id && (navLink = menuPanel.querySelector('.nav-link[href="#' + id + '"]'))) break
+          }
+        }
+      }
+    }
+    var navItem
+    if (navLink) {
+      navItem = navLink.parentNode
+    } else if (originalPageItem) {
+      navLink = (navItem = originalPageItem).querySelector('.nav-link')
+    } else {
+      return
+    }
+    if (navItem === currentPageItem) return
+    find(menuPanel, '.nav-item.is-active').forEach(function (el) {
+      el.classList.remove('is-active', 'is-current-path', 'is-current-page')
+    })
+    navItem.classList.add('is-current-page')
+    currentPageItem = navItem
+    activateCurrentPath(navItem)
+    scrollItemToMidpoint(menuPanel, navLink)
+  }
+
+  if (menuPanel.querySelector('.nav-link[href^="#"]')) {
+    if (window.location.hash) onHashChange()
+    window.addEventListener('hashchange', onHashChange)
+  }
+
+  function activateCurrentPath (navItem) {
+    var ancestorClasses
+    var ancestor = navItem.parentNode
+    while (!(ancestorClasses = ancestor.classList).contains('nav-menu')) {
+      if (ancestor.tagName === 'LI' && ancestorClasses.contains('nav-item')) {
+        ancestorClasses.add('is-active', 'is-current-path')
+      }
+      ancestor = ancestor.parentNode
+    }
+    navItem.classList.add('is-active')
+  }
+
+  function toggleActive () {
+    if (this.classList.toggle('is-active')) {
+      var padding = parseFloat(window.getComputedStyle(this).marginTop)
+      var rect = this.getBoundingClientRect()
+      var menuPanelRect = menuPanel.getBoundingClientRect()
+      var overflowY = (rect.bottom - menuPanelRect.top - menuPanelRect.height + padding).toFixed()
+      if (overflowY > 0) menuPanel.scrollTop += Math.min((rect.top - menuPanelRect.top - padding).toFixed(), overflowY)
+    }
+  }
+
+  function showNav (e) {
+    if (navToggle.classList.contains('is-active')) return hideNav(e)
+    trapEvent(e)
+    var html = document.documentElement
+    html.classList.add('is-clipped--nav')
+    navToggle.classList.add('is-active')
+    navContainer.classList.add('is-active')
+    var bounds = nav.getBoundingClientRect()
+    var expectedHeight = window.innerHeight - Math.round(bounds.top)
+    if (Math.round(bounds.height) !== expectedHeight) nav.style.height = expectedHeight + 'px'
+    html.addEventListener('click', hideNav)
+  }
+
+  function hideNav (e) {
+    trapEvent(e)
+    var html = document.documentElement
+    html.classList.remove('is-clipped--nav')
+    navToggle.classList.remove('is-active')
+    navContainer.classList.remove('is-active')
+    html.removeEventListener('click', hideNav)
+  }
+
+  function trapEvent (e) {
+    e.stopPropagation()
+  }
+
+  function scrollItemToMidpoint (panel, el) {
+    var rect = panel.getBoundingClientRect()
+    var effectiveHeight = rect.height
+    var navStyle = window.getComputedStyle(nav)
+    if (navStyle.position === 'sticky') effectiveHeight -= rect.top - parseFloat(navStyle.top)
+    panel.scrollTop = Math.max(0, (el.getBoundingClientRect().height - effectiveHeight) * 0.5 + el.offsetTop)
+  }
+
+  function find (from, selector) {
+    return [].slice.call(from.querySelectorAll(selector))
+  }
+
+  function findNextElement (from, selector) {
+    var el = from.nextElementSibling
+    return el && selector ? el[el.matches ? 'matches' : 'msMatchesSelector'](selector) && el : el
+  }
+})()
diff --git a/src/js/02-on-this-page.js b/src/js/02-on-this-page.js
new file mode 100644
index 0000000..f3b2732
--- /dev/null
+++ b/src/js/02-on-this-page.js
@@ -0,0 +1,115 @@
+;(function () {
+  'use strict'
+
+  var sidebar = document.querySelector('aside.toc.sidebar')
+  if (!sidebar) return
+  if (document.querySelector('body.-toc')) return sidebar.parentNode.removeChild(sidebar)
+  var levels = parseInt(sidebar.dataset.levels || 2, 10)
+  if (levels < 0) return
+
+  var articleSelector = 'article.doc'
+  var article = document.querySelector(articleSelector)
+  if (!article) return
+  var headingsSelector = []
+  for (var level = 0; level <= levels; level++) {
+    var headingSelector = [articleSelector]
+    if (level) {
+      for (var l = 1; l <= level; l++) headingSelector.push((l === 2 ? '.sectionbody>' : '') + '.sect' + l)
+      headingSelector.push('h' + (level + 1) + '[id]' + (level > 1 ? ':not(.discrete)' : ''))
+    } else {
+      headingSelector.push('h1[id].sect0')
+    }
+    headingsSelector.push(headingSelector.join('>'))
+  }
+  var headings = find(headingsSelector.join(','), article.parentNode)
+  if (!headings.length) return sidebar.parentNode.removeChild(sidebar)
+
+  var lastActiveFragment
+  var links = {}
+  var list = headings.reduce(function (accum, heading) {
+    var link = document.createElement('a')
+    link.textContent = heading.textContent
+    links[(link.href = '#' + heading.id)] = link
+    var listItem = document.createElement('li')
+    listItem.dataset.level = parseInt(heading.nodeName.slice(1), 10) - 1
+    listItem.appendChild(link)
+    accum.appendChild(listItem)
+    return accum
+  }, document.createElement('ul'))
+
+  var menu = sidebar.querySelector('.toc-menu')
+  if (!menu) (menu = document.createElement('div')).className = 'toc-menu'
+
+  var title = document.createElement('h3')
+  title.textContent = sidebar.dataset.title || 'Contents'
+  menu.appendChild(title)
+  menu.appendChild(list)
+
+  var startOfContent = !document.getElementById('toc') && article.querySelector('h1.page ~ :not(.is-before-toc)')
+  if (startOfContent) {
+    var embeddedToc = document.createElement('aside')
+    embeddedToc.className = 'toc embedded'
+    embeddedToc.appendChild(menu.cloneNode(true))
+    startOfContent.parentNode.insertBefore(embeddedToc, startOfContent)
+  }
+
+  window.addEventListener('load', function () {
+    onScroll()
+    window.addEventListener('scroll', onScroll)
+  })
+
+  function onScroll () {
+    var scrolledBy = window.pageYOffset
+    var buffer = getNumericStyleVal(document.documentElement, 'fontSize') * 1.15
+    var ceil = article.offsetTop
+    if (scrolledBy && window.innerHeight + scrolledBy + 2 >= document.documentElement.scrollHeight) {
+      lastActiveFragment = Array.isArray(lastActiveFragment) ? lastActiveFragment : Array(lastActiveFragment || 0)
+      var activeFragments = []
+      var lastIdx = headings.length - 1
+      headings.forEach(function (heading, idx) {
+        var fragment = '#' + heading.id
+        if (idx === lastIdx || heading.getBoundingClientRect().top + getNumericStyleVal(heading, 'paddingTop') > ceil) {
+          activeFragments.push(fragment)
+          if (lastActiveFragment.indexOf(fragment) < 0) links[fragment].classList.add('is-active')
+        } else if (~lastActiveFragment.indexOf(fragment)) {
+          links[lastActiveFragment.shift()].classList.remove('is-active')
+        }
+      })
+      list.scrollTop = list.scrollHeight - list.offsetHeight
+      lastActiveFragment = activeFragments.length > 1 ? activeFragments : activeFragments[0]
+      return
+    }
+    if (Array.isArray(lastActiveFragment)) {
+      lastActiveFragment.forEach(function (fragment) {
+        links[fragment].classList.remove('is-active')
+      })
+      lastActiveFragment = undefined
+    }
+    var activeFragment
+    headings.some(function (heading) {
+      if (heading.getBoundingClientRect().top + getNumericStyleVal(heading, 'paddingTop') - buffer > ceil) return true
+      activeFragment = '#' + heading.id
+    })
+    if (activeFragment) {
+      if (activeFragment === lastActiveFragment) return
+      if (lastActiveFragment) links[lastActiveFragment].classList.remove('is-active')
+      var activeLink = links[activeFragment]
+      activeLink.classList.add('is-active')
+      if (list.scrollHeight > list.offsetHeight) {
+        list.scrollTop = Math.max(0, activeLink.offsetTop + activeLink.offsetHeight - list.offsetHeight)
+      }
+      lastActiveFragment = activeFragment
+    } else if (lastActiveFragment) {
+      links[lastActiveFragment].classList.remove('is-active')
+      lastActiveFragment = undefined
+    }
+  }
+
+  function find (selector, from) {
+    return [].slice.call((from || document).querySelectorAll(selector))
+  }
+
+  function getNumericStyleVal (el, prop) {
+    return parseFloat(window.getComputedStyle(el)[prop])
+  }
+})()
diff --git a/src/js/03-fragment-jumper.js b/src/js/03-fragment-jumper.js
new file mode 100644
index 0000000..bff0896
--- /dev/null
+++ b/src/js/03-fragment-jumper.js
@@ -0,0 +1,43 @@
+;(function () {
+  'use strict'
+
+  var article = document.querySelector('article.doc')
+  if (!article) return
+  var toolbar = document.querySelector('.toolbar')
+  var supportsScrollToOptions = 'scrollTo' in document.documentElement
+
+  function decodeFragment (hash) {
+    return hash && (~hash.indexOf('%') ? decodeURIComponent(hash) : hash).slice(1)
+  }
+
+  function computePosition (el, sum) {
+    return article.contains(el) ? computePosition(el.offsetParent, el.offsetTop + sum) : sum
+  }
+
+  function jumpToAnchor (e) {
+    if (e) {
+      if (e.altKey || e.ctrlKey) return
+      window.location.hash = '#' + this.id
+      e.preventDefault()
+    }
+    var y = computePosition(this, 0) - toolbar.getBoundingClientRect().bottom
+    var instant = e === false && supportsScrollToOptions
+    instant ? window.scrollTo({ left: 0, top: y, behavior: 'instant' }) : window.scrollTo(0, y)
+  }
+
+  window.addEventListener('load', function jumpOnLoad (e) {
+    var fragment, target
+    if ((fragment = decodeFragment(window.location.hash)) && (target = document.getElementById(fragment))) {
+      jumpToAnchor.call(target, false)
+      setTimeout(jumpToAnchor.bind(target, false), 250)
+    }
+    window.removeEventListener('load', jumpOnLoad)
+  })
+
+  Array.prototype.slice.call(document.querySelectorAll('a[href^="#"]')).forEach(function (el) {
+    var fragment, target
+    if ((fragment = decodeFragment(el.hash)) && (target = document.getElementById(fragment))) {
+      el.addEventListener('click', jumpToAnchor.bind(target))
+    }
+  })
+})()
diff --git a/src/js/04-page-versions.js b/src/js/04-page-versions.js
new file mode 100644
index 0000000..c4c1378
--- /dev/null
+++ b/src/js/04-page-versions.js
@@ -0,0 +1,17 @@
+;(function () {
+  'use strict'
+
+  var toggle = document.querySelector('.page-versions .version-menu-toggle')
+  if (!toggle) return
+
+  var selector = document.querySelector('.page-versions')
+
+  toggle.addEventListener('click', function (e) {
+    selector.classList.toggle('is-active')
+    e.stopPropagation() // trap event
+  })
+
+  document.documentElement.addEventListener('click', function () {
+    selector.classList.remove('is-active')
+  })
+})()
diff --git a/src/js/05-mobile-navbar.js b/src/js/05-mobile-navbar.js
new file mode 100644
index 0000000..d85abb2
--- /dev/null
+++ b/src/js/05-mobile-navbar.js
@@ -0,0 +1,20 @@
+;(function () {
+  'use strict'
+
+  var navbarBurger = document.querySelector('.navbar-burger')
+  if (!navbarBurger) return
+  navbarBurger.addEventListener('click', toggleNavbarMenu.bind(navbarBurger))
+
+  function toggleNavbarMenu (e) {
+    e.stopPropagation() // trap event
+    document.documentElement.classList.toggle('is-clipped--navbar')
+    navbarBurger.setAttribute('aria-expanded', this.classList.toggle('is-active'))
+    var menu = document.getElementById(this.getAttribute('aria-controls') || this.dataset.target)
+    if (menu.classList.toggle('is-active')) {
+      menu.style.maxHeight = ''
+      var expectedMaxHeight = window.innerHeight - Math.round(menu.getBoundingClientRect().top)
+      var actualMaxHeight = parseInt(window.getComputedStyle(menu).maxHeight, 10)
+      if (actualMaxHeight !== expectedMaxHeight) menu.style.maxHeight = expectedMaxHeight + 'px'
+    }
+  }
+})()
diff --git a/src/js/06-copy-to-clipboard.js b/src/js/06-copy-to-clipboard.js
new file mode 100644
index 0000000..8c9d698
--- /dev/null
+++ b/src/js/06-copy-to-clipboard.js
@@ -0,0 +1,80 @@
+;(function () {
+  'use strict'
+
+  var CMD_RX = /^\$ (\S[^\\\n]*(\\\n(?!\$ )[^\\\n]*)*)(?=\n|$)/gm
+  var LINE_CONTINUATION_RX = /( ) *\\\n *|\\\n( ?) */g
+  var TRAILING_SPACE_RX = / +$/gm
+
+  var config = (document.getElementById('site-script') || { dataset: {} }).dataset
+  var supportsCopy = window.navigator.clipboard
+  var svgAs = config.svgAs
+  var uiRootPath = (config.uiRootPath == null ? window.uiRootPath : config.uiRootPath) || '.'
+
+  ;[].slice.call(document.querySelectorAll('.doc pre.highlight, .doc .literalblock pre')).forEach(function (pre) {
+    var code, language, lang, copy, toast, toolbox
+    if (pre.classList.contains('highlight')) {
+      code = pre.querySelector('code')
+      if ((language = code.dataset.lang) && language !== 'console') {
+        ;(lang = document.createElement('span')).className = 'source-lang'
+        lang.appendChild(document.createTextNode(language))
+      }
+    } else if (pre.innerText.startsWith('$ ')) {
+      var block = pre.parentNode.parentNode
+      block.classList.remove('literalblock')
+      block.classList.add('listingblock')
+      pre.classList.add('highlightjs', 'highlight')
+      ;(code = document.createElement('code')).className = 'language-console hljs'
+      code.dataset.lang = 'console'
+      code.appendChild(pre.firstChild)
+      pre.appendChild(code)
+    } else {
+      return
+    }
+    ;(toolbox = document.createElement('div')).className = 'source-toolbox'
+    if (lang) toolbox.appendChild(lang)
+    if (supportsCopy) {
+      ;(copy = document.createElement('button')).className = 'copy-button'
+      copy.setAttribute('title', 'Copy to clipboard')
+      if (svgAs === 'svg') {
+        var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
+        svg.setAttribute('class', 'copy-icon')
+        var use = document.createElementNS('http://www.w3.org/2000/svg', 'use')
+        use.setAttribute('href', uiRootPath + '/img/octicons-16.svg#icon-clippy')
+        svg.appendChild(use)
+        copy.appendChild(svg)
+      } else {
+        var img = document.createElement('img')
+        img.src = uiRootPath + '/img/octicons-16.svg#view-clippy'
+        img.alt = 'copy icon'
+        img.className = 'copy-icon'
+        copy.appendChild(img)
+      }
+      ;(toast = document.createElement('span')).className = 'copy-toast'
+      toast.appendChild(document.createTextNode('Copied!'))
+      copy.appendChild(toast)
+      toolbox.appendChild(copy)
+    }
+    pre.parentNode.appendChild(toolbox)
+    if (copy) copy.addEventListener('click', writeToClipboard.bind(copy, code))
+  })
+
+  function extractCommands (text) {
+    var cmds = []
+    var m
+    while ((m = CMD_RX.exec(text))) cmds.push(m[1].replace(LINE_CONTINUATION_RX, '$1$2'))
+    return cmds.join(' && ')
+  }
+
+  function writeToClipboard (code) {
+    var text = code.innerText.replace(TRAILING_SPACE_RX, '')
+    if (code.dataset.lang === 'console' && text.startsWith('$ ')) text = extractCommands(text)
+    window.navigator.clipboard.writeText(text).then(
+      function () {
+        this.classList.add('clicked')
+        this.offsetHeight // eslint-disable-line no-unused-expressions
+        this.classList.remove('clicked')
+      }.bind(this),
+      function () {}
+    )
+  }
+})()
diff --git a/src/js/vendor/highlight.bundle.js b/src/js/vendor/highlight.bundle.js
new file mode 100644
index 0000000..fe8ae5d
--- /dev/null
+++ b/src/js/vendor/highlight.bundle.js
@@ -0,0 +1,43 @@
+;(function () {
+  'use strict'
+
+  var hljs = require('highlight.js/lib/highlight')
+  hljs.registerLanguage('asciidoc', require('highlight.js/lib/languages/asciidoc'))
+  hljs.registerLanguage('bash', require('highlight.js/lib/languages/bash'))
+  hljs.registerLanguage('clojure', require('highlight.js/lib/languages/clojure'))
+  hljs.registerLanguage('cpp', require('highlight.js/lib/languages/cpp'))
+  hljs.registerLanguage('cs', require('highlight.js/lib/languages/cs'))
+  hljs.registerLanguage('css', require('highlight.js/lib/languages/css'))
+  hljs.registerLanguage('diff', require('highlight.js/lib/languages/diff'))
+  hljs.registerLanguage('dockerfile', require('highlight.js/lib/languages/dockerfile'))
+  hljs.registerLanguage('elixir', require('highlight.js/lib/languages/elixir'))
+  hljs.registerLanguage('go', require('highlight.js/lib/languages/go'))
+  hljs.registerLanguage('groovy', require('highlight.js/lib/languages/groovy'))
+  hljs.registerLanguage('haskell', require('highlight.js/lib/languages/haskell'))
+  hljs.registerLanguage('java', require('highlight.js/lib/languages/java'))
+  hljs.registerLanguage('javascript', require('highlight.js/lib/languages/javascript'))
+  hljs.registerLanguage('json', require('highlight.js/lib/languages/json'))
+  hljs.registerLanguage('julia', require('highlight.js/lib/languages/julia'))
+  hljs.registerLanguage('kotlin', require('highlight.js/lib/languages/kotlin'))
+  hljs.registerLanguage('lua', require('highlight.js/lib/languages/lua'))
+  hljs.registerLanguage('markdown', require('highlight.js/lib/languages/markdown'))
+  hljs.registerLanguage('nix', require('highlight.js/lib/languages/nix'))
+  hljs.registerLanguage('none', require('highlight.js/lib/languages/plaintext'))
+  hljs.registerLanguage('objectivec', require('highlight.js/lib/languages/objectivec'))
+  hljs.registerLanguage('perl', require('highlight.js/lib/languages/perl'))
+  hljs.registerLanguage('php', require('highlight.js/lib/languages/php'))
+  hljs.registerLanguage('properties', require('highlight.js/lib/languages/properties'))
+  hljs.registerLanguage('puppet', require('highlight.js/lib/languages/puppet'))
+  hljs.registerLanguage('python', require('highlight.js/lib/languages/python'))
+  hljs.registerLanguage('ruby', require('highlight.js/lib/languages/ruby'))
+  hljs.registerLanguage('rust', require('highlight.js/lib/languages/rust'))
+  hljs.registerLanguage('scala', require('highlight.js/lib/languages/scala'))
+  hljs.registerLanguage('shell', require('highlight.js/lib/languages/shell'))
+  hljs.registerLanguage('sql', require('highlight.js/lib/languages/sql'))
+  hljs.registerLanguage('swift', require('highlight.js/lib/languages/swift'))
+  hljs.registerLanguage('xml', require('highlight.js/lib/languages/xml'))
+  hljs.registerLanguage('yaml', require('highlight.js/lib/languages/yaml'))
+  ;[].slice.call(document.querySelectorAll('pre code.hljs[data-lang]')).forEach(function (node) {
+    hljs.highlightBlock(node)
+  })
+})()
diff --git a/src/layouts/404.hbs b/src/layouts/404.hbs
new file mode 100644
index 0000000..8caab1d
--- /dev/null
+++ b/src/layouts/404.hbs
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+{{> head defaultPageTitle='Page Not Found'}}
+  </head>
+  <body class="status-404">
+{{> header}}
+{{> body}}
+{{> footer}}
+  </body>
+</html>
diff --git a/src/layouts/default.hbs b/src/layouts/default.hbs
new file mode 100644
index 0000000..c5282ec
--- /dev/null
+++ b/src/layouts/default.hbs
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+{{> head defaultPageTitle='Untitled'}}
+  </head>
+  <body class="article{{#with (or page.attributes.role page.role)}} {{{this}}}{{/with}}">
+{{> header}}
+{{> body}}
+{{> footer}}
+  </body>
+</html>
diff --git a/src/partials/article-404.hbs b/src/partials/article-404.hbs
new file mode 100644
index 0000000..436b280
--- /dev/null
+++ b/src/partials/article-404.hbs
@@ -0,0 +1,10 @@
+<article class="doc">
+<h1 class="page">{{{or page.title 'Page Not Found'}}}</h1>
+<div class="paragraph">
+<p>The page you&#8217;re looking for does not exist. It may have been moved. You can{{#with site.homeUrl}} return to the <a href="{{{this}}}">start page</a>, or{{/with}} follow one of the links in the navigation to the left.</p>
+</div>
+<div class="paragraph">
+<p>If you arrived on this page by clicking on a link, please notify the owner of the site that the link is broken.
+If you typed the URL of this page manually, please double check that you entered the address correctly.</p>
+</div>
+</article>
diff --git a/src/partials/article.hbs b/src/partials/article.hbs
new file mode 100644
index 0000000..81dac29
--- /dev/null
+++ b/src/partials/article.hbs
@@ -0,0 +1,7 @@
+<article class="doc">
+{{#with page.title}}
+<h1 class="page">{{{this}}}</h1>
+{{/with}}
+{{{page.contents}}}
+{{> pagination}}
+</article>
diff --git a/src/partials/body.hbs b/src/partials/body.hbs
new file mode 100644
index 0000000..4a0ac25
--- /dev/null
+++ b/src/partials/body.hbs
@@ -0,0 +1,4 @@
+<div class="body">
+{{> nav}}
+{{> main}}
+</div>
diff --git a/src/partials/breadcrumbs.hbs b/src/partials/breadcrumbs.hbs
new file mode 100644
index 0000000..24b6fb0
--- /dev/null
+++ b/src/partials/breadcrumbs.hbs
@@ -0,0 +1,20 @@
+<nav class="breadcrumbs" aria-label="breadcrumbs">
+  {{#if page.breadcrumbs}}
+  <ul>
+    {{#with page.componentVersion}}
+    {{#if (and ./title (ne ./title @root.page.breadcrumbs.0.content))}}
+    <li><a href="{{{relativize ./url}}}">{{{./title}}}</a></li>
+    {{/if}}
+    {{/with}}
+    {{#each page.breadcrumbs}}
+    <li>
+    {{~#if (and ./url (eq ./urlType 'internal'))~}}
+    <a href="{{{relativize ./url}}}">{{{./content}}}</a>
+    {{~else~}}
+    {{{./content}}}
+    {{~/if~}}
+    </li>
+    {{/each}}
+  </ul>
+  {{/if}}
+</nav>
diff --git a/src/partials/edit-this-page.hbs b/src/partials/edit-this-page.hbs
new file mode 100644
index 0000000..27946f4
--- /dev/null
+++ b/src/partials/edit-this-page.hbs
@@ -0,0 +1,5 @@
+{{#if (and page.fileUri (not env.CI))}}
+<div class="edit-this-page"><a href="{{page.fileUri}}">Edit this Page</a></div>
+{{else if (and page.editUrl (or env.FORCE_SHOW_EDIT_PAGE_LINK (not page.origin.private)))}}
+<div class="edit-this-page"><a href="{{page.editUrl}}">Edit this Page</a></div>
+{{/if}}
diff --git a/src/partials/footer-content.hbs b/src/partials/footer-content.hbs
new file mode 100644
index 0000000..cdeeb47
--- /dev/null
+++ b/src/partials/footer-content.hbs
@@ -0,0 +1,4 @@
+<footer class="footer">
+  <p>This page was built using the Antora default UI.</p>
+  <p>The source code for this UI is licensed under the terms of the MPL-2.0 license.</p>
+</footer>
diff --git a/src/partials/footer-scripts.hbs b/src/partials/footer-scripts.hbs
new file mode 100644
index 0000000..3d9b577
--- /dev/null
+++ b/src/partials/footer-scripts.hbs
@@ -0,0 +1,5 @@
+<script id="site-script" src="{{{uiRootPath}}}/js/site.js" data-ui-root-path="{{{uiRootPath}}}"></script>
+<script async src="{{{uiRootPath}}}/js/vendor/highlight.js"></script>
+{{#if env.SITE_SEARCH_PROVIDER}}
+{{> search-scripts}}
+{{/if}}
diff --git a/src/partials/footer.hbs b/src/partials/footer.hbs
new file mode 100644
index 0000000..9d49017
--- /dev/null
+++ b/src/partials/footer.hbs
@@ -0,0 +1,2 @@
+{{> footer-content}}
+{{> footer-scripts}}
diff --git a/src/partials/head-icons.hbs b/src/partials/head-icons.hbs
new file mode 100644
index 0000000..4400e2f
--- /dev/null
+++ b/src/partials/head-icons.hbs
@@ -0,0 +1 @@
+    {{!-- <link rel="icon" href="{{{uiRootPath}}}/img/favicon.ico" type="image/x-icon"> --}}
diff --git a/src/partials/head-info.hbs b/src/partials/head-info.hbs
new file mode 100644
index 0000000..07efba1
--- /dev/null
+++ b/src/partials/head-info.hbs
@@ -0,0 +1,20 @@
+    {{#with page.canonicalUrl}}
+    <link rel="canonical" href="{{{this}}}">
+    {{/with}}
+    {{#unless (eq page.attributes.pagination undefined)}}
+    {{#with page.previous}}
+    <link rel="prev" href="{{{relativize ./url}}}">
+    {{/with}}
+    {{#with page.next}}
+    <link rel="next" href="{{{relativize ./url}}}">
+    {{/with}}
+    {{/unless}}
+    {{#with page.description}}
+    <meta name="description" content="{{{detag this}}}">
+    {{/with}}
+    {{#with page.keywords}}
+    <meta name="keywords" content="{{{this}}}">
+    {{/with}}
+    {{#with (or antoraVersion site.antoraVersion)}}
+    <meta name="generator" content="Antora {{{this}}}">
+    {{/with}}
diff --git a/src/partials/head-meta.hbs b/src/partials/head-meta.hbs
new file mode 100644
index 0000000..1aef0af
--- /dev/null
+++ b/src/partials/head-meta.hbs
@@ -0,0 +1 @@
+    {{!-- Add additional meta tags here --}}
diff --git a/src/partials/head-prelude.hbs b/src/partials/head-prelude.hbs
new file mode 100644
index 0000000..a8b267d
--- /dev/null
+++ b/src/partials/head-prelude.hbs
@@ -0,0 +1,2 @@
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width,initial-scale=1">
diff --git a/src/partials/head-scripts.hbs b/src/partials/head-scripts.hbs
new file mode 100644
index 0000000..8dbc7d0
--- /dev/null
+++ b/src/partials/head-scripts.hbs
@@ -0,0 +1,7 @@
+    {{#with site.keys.googleAnalytics}}
+    <script async src="https://www.googletagmanager.com/gtag/js?id={{this}}"></script>
+    <script>function gtag(){dataLayer.push(arguments)};window.dataLayer=window.dataLayer||[];gtag('js',new Date());gtag('config','{{this}}')</script>
+    {{/with}}
+    {{!--
+    <script>var uiRootPath = '{{{uiRootPath}}}'</script>
+    --}}
diff --git a/src/partials/head-styles.hbs b/src/partials/head-styles.hbs
new file mode 100644
index 0000000..d6839e5
--- /dev/null
+++ b/src/partials/head-styles.hbs
@@ -0,0 +1 @@
+    <link rel="stylesheet" href="{{{uiRootPath}}}/css/site.css">
diff --git a/src/partials/head-title.hbs b/src/partials/head-title.hbs
new file mode 100644
index 0000000..924fcac
--- /dev/null
+++ b/src/partials/head-title.hbs
@@ -0,0 +1 @@
+    <title>{{{detag (or page.title defaultPageTitle)}}}{{#with site.title}} :: {{this}}{{/with}}</title>
diff --git a/src/partials/head.hbs b/src/partials/head.hbs
new file mode 100644
index 0000000..7dd18b2
--- /dev/null
+++ b/src/partials/head.hbs
@@ -0,0 +1,7 @@
+{{> head-prelude}}
+{{> head-title}}
+{{> head-info}}
+{{> head-styles}}
+{{> head-meta}}
+{{> head-scripts}}
+{{> head-icons}}
diff --git a/src/partials/header-content.hbs b/src/partials/header-content.hbs
new file mode 100644
index 0000000..f11bd60
--- /dev/null
+++ b/src/partials/header-content.hbs
@@ -0,0 +1,45 @@
+<header class="header">
+  <nav class="navbar">
+    <div class="navbar-brand">
+      <a class="navbar-item" href="{{{or site.url siteRootPath}}}">{{site.title}}</a>
+      {{#if env.SITE_SEARCH_PROVIDER}}
+      <div class="navbar-item search hide-for-print">
+        <div id="search-field" class="field">
+          <input id="search-input" type="text" placeholder="Search the docs"{{#if page.home}} autofocus{{/if}}>
+        </div>
+      </div>
+      {{/if}}
+      <button class="navbar-burger" aria-controls="topbar-nav" aria-expanded="false" aria-label="Toggle main menu">
+        <span></span>
+        <span></span>
+        <span></span>
+      </button>
+    </div>
+    <div id="topbar-nav" class="navbar-menu">
+      <div class="navbar-end">
+        <a class="navbar-item" href="#">Home</a>
+        <div class="navbar-item has-dropdown is-hoverable">
+          <a class="navbar-link" href="#">Products</a>
+          <div class="navbar-dropdown">
+            <a class="navbar-item" href="#">Product A</a>
+            <a class="navbar-item" href="#">Product B</a>
+            <a class="navbar-item" href="#">Product C</a>
+          </div>
+        </div>
+        <div class="navbar-item has-dropdown is-hoverable">
+          <a class="navbar-link" href="#">Services</a>
+          <div class="navbar-dropdown">
+            <a class="navbar-item" href="#">Service A</a>
+            <a class="navbar-item" href="#">Service B</a>
+            <a class="navbar-item" href="#">Service C</a>
+          </div>
+        </div>
+        <div class="navbar-item">
+          <span class="control">
+            <a class="button is-primary" href="#">Download</a>
+          </span>
+        </div>
+      </div>
+    </div>
+  </nav>
+</header>
diff --git a/src/partials/header-scripts.hbs b/src/partials/header-scripts.hbs
new file mode 100644
index 0000000..b9e907c
--- /dev/null
+++ b/src/partials/header-scripts.hbs
@@ -0,0 +1 @@
+{{!-- Add header scripts here --}}
diff --git a/src/partials/header.hbs b/src/partials/header.hbs
new file mode 100644
index 0000000..8a39422
--- /dev/null
+++ b/src/partials/header.hbs
@@ -0,0 +1,2 @@
+{{> header-scripts}}
+{{> header-content}}
diff --git a/src/partials/main.hbs b/src/partials/main.hbs
new file mode 100644
index 0000000..d3e2411
--- /dev/null
+++ b/src/partials/main.hbs
@@ -0,0 +1,11 @@
+<main class="article">
+{{> toolbar}}
+  <div class="content">
+{{#if (eq page.layout '404')}}
+{{> article-404}}
+{{else}}
+{{> toc}}
+{{> article}}
+{{/if}}
+  </div>
+</main>
diff --git a/src/partials/nav-explore.hbs b/src/partials/nav-explore.hbs
new file mode 100644
index 0000000..1b14168
--- /dev/null
+++ b/src/partials/nav-explore.hbs
@@ -0,0 +1,26 @@
+<div class="nav-panel-explore{{#unless page.navigation}} is-active{{/unless}}" data-panel="explore">
+  {{#if page.component}}
+  <div class="context">
+    <span class="title">{{page.component.title}}</span>
+    <span class="version">{{#if (or page.componentVersion.version (ne page.componentVersion.displayVersion 'default'))}}{{page.componentVersion.displayVersion}}{{/if}}</span>
+  </div>
+  {{/if}}
+  <ul class="components">
+    {{#each site.components}}
+    <li class="component{{#if (eq this @root.page.component)}} is-current{{/if}}">
+      <div class="title"><a href="{{{relativize ./url}}}">{{{./title}}}</a></div>
+      {{#if (or ./versions.[1] ./versions.[0].version (ne ./versions.[0].displayVersion 'default'))}}
+      <ul class="versions">
+        {{#each ./versions}}
+        <li class="version
+          {{~#if (and (eq .. @root.page.component) (eq this @root.page.componentVersion))}} is-current{{/if~}}
+          {{~#if (eq this ../latest)}} is-latest{{/if}}">
+          <a href="{{{relativize ./url}}}">{{./displayVersion}}</a>
+        </li>
+        {{/each}}
+      </ul>
+      {{/if}}
+    </li>
+    {{/each}}
+  </ul>
+</div>
diff --git a/src/partials/nav-menu.hbs b/src/partials/nav-menu.hbs
new file mode 100644
index 0000000..95cf7a5
--- /dev/null
+++ b/src/partials/nav-menu.hbs
@@ -0,0 +1,11 @@
+{{#with page.navigation}}
+<div class="nav-panel-menu is-active" data-panel="menu">
+  <nav class="nav-menu">
+    <button class="nav-menu-toggle" aria-label="Toggle expand/collapse all" style="display: none"></button>
+    {{#with @root.page.componentVersion}}
+    <h3 class="title"><a href="{{{relativize ./url}}}">{{./title}}</a></h3>
+    {{/with}}
+{{> nav-tree navigation=this}}
+  </nav>
+</div>
+{{/with}}
diff --git a/src/partials/nav-toggle.hbs b/src/partials/nav-toggle.hbs
new file mode 100644
index 0000000..0f11e25
--- /dev/null
+++ b/src/partials/nav-toggle.hbs
@@ -0,0 +1 @@
+<button class="nav-toggle"></button>
diff --git a/src/partials/nav-tree.hbs b/src/partials/nav-tree.hbs
new file mode 100644
index 0000000..79e3c1e
--- /dev/null
+++ b/src/partials/nav-tree.hbs
@@ -0,0 +1,21 @@
+{{#if navigation.length}}
+<ul class="nav-list">
+  {{#each navigation}}
+  <li class="nav-item{{#if (eq ./url @root.page.url)}} is-current-page{{/if}}" data-depth="{{or ../level 0}}">
+    {{#if ./content}}
+    {{#if ./items.length}}
+    <button class="nav-item-toggle"></button>
+    {{/if}}
+    {{#if ./url}}
+    <a class="nav-link" href="
+      {{~#if (eq ./urlType 'internal')}}{{{relativize ./url}}}
+      {{~else}}{{{./url}}}{{~/if}}">{{{./content}}}</a>
+    {{else}}
+    <span class="nav-text">{{{./content}}}</span>
+    {{/if}}
+    {{/if}}
+{{> nav-tree navigation=./items level=(increment ../level)}}
+  </li>
+  {{/each}}
+</ul>
+{{/if}}
diff --git a/src/partials/nav.hbs b/src/partials/nav.hbs
new file mode 100644
index 0000000..7e0f091
--- /dev/null
+++ b/src/partials/nav.hbs
@@ -0,0 +1,8 @@
+<div class="nav-container"{{#if page.component}} data-component="{{page.component.name}}" data-version="{{page.version}}"{{/if}}>
+  <aside class="nav">
+    <div class="panels">
+{{> nav-menu}}
+{{> nav-explore}}
+    </div>
+  </aside>
+</div>
diff --git a/src/partials/page-versions.hbs b/src/partials/page-versions.hbs
new file mode 100644
index 0000000..a9792db
--- /dev/null
+++ b/src/partials/page-versions.hbs
@@ -0,0 +1,12 @@
+{{#with page.versions}}
+<div class="page-versions">
+  <button class="version-menu-toggle" title="Show other versions of page">{{@root.page.componentVersion.displayVersion}}</button>
+  <div class="version-menu">
+    {{#each this}}
+    <a class="version
+      {{~#if (eq ./version @root.page.version)}} is-current{{/if~}}
+      {{~#if ./missing}} is-missing{{/if}}" href="{{{relativize ./url}}}">{{./displayVersion}}</a>
+    {{/each}}
+  </div>
+</div>
+{{/with}}
diff --git a/src/partials/pagination.hbs b/src/partials/pagination.hbs
new file mode 100644
index 0000000..ba9d704
--- /dev/null
+++ b/src/partials/pagination.hbs
@@ -0,0 +1,16 @@
+{{#unless (eq page.attributes.pagination undefined)}}
+{{#if (or page.previous page.next)}}
+<nav class="pagination">
+  {{#if (ne page.attributes.pagination 'next')}}
+  {{#with page.previous}}
+  <span class="prev"><a href="{{{relativize ./url}}}">{{{./content}}}</a></span>
+  {{/with}}
+  {{/if}}
+  {{#if (ne page.attributes.pagination 'prev')}}
+  {{#with page.next}}
+  <span class="next"><a href="{{{relativize ./url}}}">{{{./content}}}</a></span>
+  {{/with}}
+  {{/if}}
+</nav>
+{{/if}}
+{{/unless}}
diff --git a/src/partials/toc.hbs b/src/partials/toc.hbs
new file mode 100644
index 0000000..163bad7
--- /dev/null
+++ b/src/partials/toc.hbs
@@ -0,0 +1,3 @@
+<aside class="toc sidebar" data-title="{{{or page.attributes.toctitle 'Contents'}}}" data-levels="{{{or page.attributes.toclevels 2}}}">
+  <div class="toc-menu"></div>
+</aside>
diff --git a/src/partials/toolbar.hbs b/src/partials/toolbar.hbs
new file mode 100644
index 0000000..797aa05
--- /dev/null
+++ b/src/partials/toolbar.hbs
@@ -0,0 +1,9 @@
+<div class="toolbar" role="navigation">
+{{> nav-toggle}}
+  {{#with site.homeUrl}}
+  <a href="{{{relativize this}}}" class="home-link{{#if @root.page.home}} is-current{{/if}}"></a>
+  {{/with}}
+{{> breadcrumbs}}
+{{> page-versions}}
+{{> edit-this-page}}
+</div>
-- 
2.18.1