aboutsummaryrefslogtreecommitdiffstats
path: root/code/frontpage/assets
diff options
context:
space:
mode:
Diffstat (limited to 'code/frontpage/assets')
-rw-r--r--code/frontpage/assets/fonts/.gitkeep0
-rw-r--r--code/frontpage/assets/images/default-image.pngbin0 -> 4694 bytes
-rw-r--r--code/frontpage/assets/js/alert-init.js5
-rw-r--r--code/frontpage/assets/js/alert.js20
-rw-r--r--code/frontpage/assets/js/app.js0
-rw-r--r--code/frontpage/assets/js/bootstrap.js2
-rw-r--r--code/frontpage/assets/js/clipboard.js37
-rw-r--r--code/frontpage/assets/js/darkmode-init.js21
-rw-r--r--code/frontpage/assets/js/darkmode.js38
-rw-r--r--code/frontpage/assets/js/highlight.js26
-rw-r--r--code/frontpage/assets/js/index.js179
-rw-r--r--code/frontpage/assets/js/instant.page.js1
-rw-r--r--code/frontpage/assets/js/katex.js10
-rw-r--r--code/frontpage/assets/js/lazysizes.js1
-rw-r--r--code/frontpage/assets/js/mermaid.js11
-rw-r--r--code/frontpage/assets/js/scroll-lock.js14
-rw-r--r--code/frontpage/assets/js/to-top.js20
-rw-r--r--code/frontpage/assets/js/vendor/.gitkeep0
-rw-r--r--code/frontpage/assets/scss/app.scss31
-rw-r--r--code/frontpage/assets/scss/common/_dark.scss582
-rw-r--r--code/frontpage/assets/scss/common/_global.scss288
-rw-r--r--code/frontpage/assets/scss/common/_variables.scss190
-rw-r--r--code/frontpage/assets/scss/components/_alerts.scss164
-rw-r--r--code/frontpage/assets/scss/components/_buttons.scss255
-rw-r--r--code/frontpage/assets/scss/components/_code.scss66
-rw-r--r--code/frontpage/assets/scss/components/_comments.scss30
-rw-r--r--code/frontpage/assets/scss/components/_details.scss77
-rw-r--r--code/frontpage/assets/scss/components/_forms.scss19
-rw-r--r--code/frontpage/assets/scss/components/_images.scss62
-rw-r--r--code/frontpage/assets/scss/components/_mermaid.scss8
-rw-r--r--code/frontpage/assets/scss/components/_search.scss91
-rw-r--r--code/frontpage/assets/scss/components/_syntax.scss62
-rw-r--r--code/frontpage/assets/scss/components/_tables.scss5
-rw-r--r--code/frontpage/assets/scss/layouts/_footer.scss20
-rw-r--r--code/frontpage/assets/scss/layouts/_header.scss493
-rw-r--r--code/frontpage/assets/scss/layouts/_pages.scss64
-rw-r--r--code/frontpage/assets/scss/layouts/_posts.scss57
-rw-r--r--code/frontpage/assets/scss/layouts/_sidebar.scss116
-rw-r--r--code/frontpage/assets/scss/vendor/.gitkeep0
39 files changed, 3065 insertions, 0 deletions
diff --git a/code/frontpage/assets/fonts/.gitkeep b/code/frontpage/assets/fonts/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/code/frontpage/assets/fonts/.gitkeep
diff --git a/code/frontpage/assets/images/default-image.png b/code/frontpage/assets/images/default-image.png
new file mode 100644
index 0000000..a34ff9f
--- /dev/null
+++ b/code/frontpage/assets/images/default-image.png
Binary files differ
diff --git a/code/frontpage/assets/js/alert-init.js b/code/frontpage/assets/js/alert-init.js
new file mode 100644
index 0000000..af3ac32
--- /dev/null
+++ b/code/frontpage/assets/js/alert-init.js
@@ -0,0 +1,5 @@
+Object.keys(localStorage).forEach(function(key) {
+ if (/^global-alert-/.test(key)) {
+ document.documentElement.setAttribute('data-global-alert', 'closed');
+ }
+}); \ No newline at end of file
diff --git a/code/frontpage/assets/js/alert.js b/code/frontpage/assets/js/alert.js
new file mode 100644
index 0000000..1956103
--- /dev/null
+++ b/code/frontpage/assets/js/alert.js
@@ -0,0 +1,20 @@
+var announcement = document.getElementById('announcement');
+
+if (announcement !== null) {
+
+ var id = announcement.dataset.id;
+
+ Object.keys(localStorage).forEach(function(key) {
+ if (/^global-alert-/.test(key)) {
+ if (key !== id ) {
+ localStorage.removeItem(key);
+ document.documentElement.removeAttribute('data-global-alert');
+ }
+ }
+ });
+
+ announcement.addEventListener('closed.bs.alert', () => {
+ localStorage.setItem(id, 'closed');
+ });
+
+} \ No newline at end of file
diff --git a/code/frontpage/assets/js/app.js b/code/frontpage/assets/js/app.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/code/frontpage/assets/js/app.js
diff --git a/code/frontpage/assets/js/bootstrap.js b/code/frontpage/assets/js/bootstrap.js
new file mode 100644
index 0000000..8d6da8d
--- /dev/null
+++ b/code/frontpage/assets/js/bootstrap.js
@@ -0,0 +1,2 @@
+import 'bootstrap/dist/js/bootstrap.bundle.min.js'
+// import 'bootstrap/dist/js/bootstrap.min.js'
diff --git a/code/frontpage/assets/js/clipboard.js b/code/frontpage/assets/js/clipboard.js
new file mode 100644
index 0000000..55eec7b
--- /dev/null
+++ b/code/frontpage/assets/js/clipboard.js
@@ -0,0 +1,37 @@
+import Clipboard from 'clipboard';
+
+var pre = document.getElementsByTagName('pre');
+
+for (var i = 0; i < pre.length; ++ i)
+{
+ var element = pre[i];
+ var mermaid = element.getElementsByClassName('language-mermaid')[0];
+
+ if (mermaid == null) {
+ element.insertAdjacentHTML('afterbegin', '<button class="btn btn-copy"></button>');
+ }
+}
+
+var clipboard = new Clipboard('.btn-copy', {
+
+ target: function(trigger) {
+ return trigger.nextElementSibling;
+ },
+
+});
+
+clipboard.on('success', function(e) {
+
+ /*
+ console.info('Action:', e.action);
+ console.info('Text:', e.text);
+ console.info('Trigger:', e.trigger);
+ */
+
+ e.clearSelection();
+});
+
+clipboard.on('error', function(e) {
+ console.error('Action:', e.action);
+ console.error('Trigger:', e.trigger);
+});
diff --git a/code/frontpage/assets/js/darkmode-init.js b/code/frontpage/assets/js/darkmode-init.js
new file mode 100644
index 0000000..0f3508d
--- /dev/null
+++ b/code/frontpage/assets/js/darkmode-init.js
@@ -0,0 +1,21 @@
+const globalDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
+const localMode = localStorage.getItem('theme');
+
+if (globalDark && (localMode === null)) {
+
+ localStorage.setItem('theme', 'dark');
+ document.documentElement.setAttribute('data-dark-mode', '');
+
+}
+
+if (globalDark && (localMode === 'dark')) {
+
+ document.documentElement.setAttribute('data-dark-mode', '');
+
+}
+
+if (localMode === 'dark') {
+
+ document.documentElement.setAttribute('data-dark-mode', '');
+
+}
diff --git a/code/frontpage/assets/js/darkmode.js b/code/frontpage/assets/js/darkmode.js
new file mode 100644
index 0000000..e81db47
--- /dev/null
+++ b/code/frontpage/assets/js/darkmode.js
@@ -0,0 +1,38 @@
+const mode = document.getElementById('mode');
+
+if (mode !== null) {
+
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
+
+ if (event.matches) {
+
+ localStorage.setItem('theme', 'dark');
+ document.documentElement.setAttribute('data-dark-mode', '');
+
+ } else {
+
+ localStorage.setItem('theme', 'light');
+ document.documentElement.removeAttribute('data-dark-mode');
+
+ }
+
+ })
+
+ mode.addEventListener('click', () => {
+
+ document.documentElement.toggleAttribute('data-dark-mode');
+ localStorage.setItem('theme', document.documentElement.hasAttribute('data-dark-mode') ? 'dark' : 'light');
+
+ });
+
+ if (localStorage.getItem('theme') === 'dark') {
+
+ document.documentElement.setAttribute('data-dark-mode', '');
+
+ } else {
+
+ document.documentElement.removeAttribute('data-dark-mode');
+
+ }
+
+}
diff --git a/code/frontpage/assets/js/highlight.js b/code/frontpage/assets/js/highlight.js
new file mode 100644
index 0000000..4ad6017
--- /dev/null
+++ b/code/frontpage/assets/js/highlight.js
@@ -0,0 +1,26 @@
+import hljs from 'highlight.js/lib/core';
+
+import javascript from 'highlight.js/lib/languages/javascript';
+import json from 'highlight.js/lib/languages/json';
+import bash from 'highlight.js/lib/languages/bash';
+import xml from 'highlight.js/lib/languages/xml';
+import ini from 'highlight.js/lib/languages/ini';
+import yaml from 'highlight.js/lib/languages/yaml';
+import markdown from 'highlight.js/lib/languages/markdown';
+import python from 'highlight.js/lib/languages/python';
+
+hljs.registerLanguage('javascript', javascript);
+hljs.registerLanguage('json', json);
+hljs.registerLanguage('bash', bash);
+hljs.registerLanguage('html', xml);
+hljs.registerLanguage('ini', ini);
+hljs.registerLanguage('toml', ini);
+hljs.registerLanguage('yaml', yaml);
+hljs.registerLanguage('md', markdown);
+hljs.registerLanguage('python', python);
+
+document.addEventListener('DOMContentLoaded', () => {
+ document.querySelectorAll('pre code:not(.language-mermaid)').forEach((block) => {
+ hljs.highlightElement(block);
+ });
+});
diff --git a/code/frontpage/assets/js/index.js b/code/frontpage/assets/js/index.js
new file mode 100644
index 0000000..15e09bb
--- /dev/null
+++ b/code/frontpage/assets/js/index.js
@@ -0,0 +1,179 @@
+var suggestions = document.getElementById('suggestions');
+var search = document.getElementById('search');
+
+if (search !== null) {
+ document.addEventListener('keydown', inputFocus);
+}
+
+function inputFocus(e) {
+ if (e.ctrlKey && e.key === '/' ) {
+ e.preventDefault();
+ search.focus();
+ }
+ if (e.key === 'Escape' ) {
+ search.blur();
+ suggestions.classList.add('d-none');
+ }
+}
+
+document.addEventListener('click', function(event) {
+
+ var isClickInsideElement = suggestions.contains(event.target);
+
+ if (!isClickInsideElement) {
+ suggestions.classList.add('d-none');
+ }
+
+});
+
+/*
+Source:
+ - https://dev.to/shubhamprakash/trap-focus-using-javascript-6a3
+*/
+
+document.addEventListener('keydown',suggestionFocus);
+
+function suggestionFocus(e) {
+ const suggestionsHidden = suggestions.classList.contains('d-none');
+ if (suggestionsHidden) return;
+
+ const focusableSuggestions= [...suggestions.querySelectorAll('a')];
+ if (focusableSuggestions.length === 0) return;
+
+ const index = focusableSuggestions.indexOf(document.activeElement);
+
+ if (e.key === "ArrowUp") {
+ e.preventDefault();
+ const nextIndex = index > 0 ? index - 1 : 0;
+ focusableSuggestions[nextIndex].focus();
+ }
+ else if (e.key === "ArrowDown") {
+ e.preventDefault();
+ const nextIndex= index + 1 < focusableSuggestions.length ? index + 1 : index;
+ focusableSuggestions[nextIndex].focus();
+ }
+
+}
+
+/*
+Source:
+ - https://github.com/nextapps-de/flexsearch#index-documents-field-search
+ - https://raw.githack.com/nextapps-de/flexsearch/master/demo/autocomplete.html
+*/
+
+(function(){
+
+ var index = new FlexSearch.Document({
+ tokenize: "forward",
+ cache: 100,
+ document: {
+ id: 'id',
+ store: [
+ "href", "title", "description"
+ ],
+ index: ["title", "description", "content"]
+ }
+ });
+
+
+ // Not yet supported: https://github.com/nextapps-de/flexsearch#complex-documents
+
+ /*
+ var docs = [
+ {{ range $index, $page := (where .Site.Pages "Section" "docs") -}}
+ {
+ id: {{ $index }},
+ href: "{{ .Permalink }}",
+ title: {{ .Title | jsonify }},
+ description: {{ .Params.description | jsonify }},
+ content: {{ .Content | jsonify }}
+ },
+ {{ end -}}
+ ];
+ */
+
+ // https://discourse.gohugo.io/t/range-length-or-last-element/3803/2
+
+ {{ $list := slice }}
+ {{- if and (isset .Site.Params.options "searchsectionsindex") (not (eq (len .Site.Params.options.searchSectionsIndex) 0)) }}
+ {{- if eq .Site.Params.options.searchSectionsIndex "ALL" }}
+ {{- $list = .Site.Pages }}
+ {{- else }}
+ {{- $list = (where .Site.Pages "Type" "in" .Site.Params.options.searchSectionsIndex) }}
+ {{- if (in .Site.Params.options.searchSectionsIndex "HomePage") }}
+ {{ $list = $list | append .Site.Home }}
+ {{- end }}
+ {{- end }}
+ {{- else }}
+ {{- $list = (where .Site.Pages "Section" "docs") }}
+ {{- end }}
+
+ {{ $len := (len $list) -}}
+
+ {{ range $index, $element := $list -}}
+ index.add(
+ {
+ id: {{ $index }},
+ href: "{{ .RelPermalink }}",
+ title: {{ .Title | jsonify }},
+ {{ with .Description -}}
+ description: {{ . | jsonify }},
+ {{ else -}}
+ description: {{ .Summary | plainify | jsonify }},
+ {{ end -}}
+ content: {{ .Plain | jsonify }}
+ }
+ );
+ {{ end -}}
+
+ search.addEventListener('input', show_results, true);
+
+ function show_results(){
+ const maxResult = 5;
+ var searchQuery = this.value;
+ var results = index.search(searchQuery, {limit: maxResult, enrich: true});
+
+ // flatten results since index.search() returns results for each indexed field
+ const flatResults = new Map(); // keyed by href to dedupe results
+ for (const result of results.flatMap(r => r.result)) {
+ if (flatResults.has(result.doc.href)) continue;
+ flatResults.set(result.doc.href, result.doc);
+ }
+
+ suggestions.innerHTML = "";
+ suggestions.classList.remove('d-none');
+
+ // inform user that no results were found
+ if (flatResults.size === 0 && searchQuery) {
+ const noResultsMessage = document.createElement('div')
+ noResultsMessage.innerHTML = `No results for "<strong>${searchQuery}</strong>"`
+ noResultsMessage.classList.add("suggestion__no-results");
+ suggestions.appendChild(noResultsMessage);
+ return;
+ }
+
+ // construct a list of suggestions
+ for(const [href, doc] of flatResults) {
+ const entry = document.createElement('div');
+ suggestions.appendChild(entry);
+
+ const a = document.createElement('a');
+ a.href = href;
+ entry.appendChild(a);
+
+ const title = document.createElement('span');
+ title.textContent = doc.title;
+ title.classList.add("suggestion__title");
+ a.appendChild(title);
+
+ const description = document.createElement('span');
+ description.textContent = doc.description;
+ description.classList.add("suggestion__description");
+ a.appendChild(description);
+
+ suggestions.appendChild(entry);
+
+ if(suggestions.childElementCount == maxResult) break;
+ }
+ }
+}());
diff --git a/code/frontpage/assets/js/instant.page.js b/code/frontpage/assets/js/instant.page.js
new file mode 100644
index 0000000..b394bcc
--- /dev/null
+++ b/code/frontpage/assets/js/instant.page.js
@@ -0,0 +1 @@
+import 'instant.page';
diff --git a/code/frontpage/assets/js/katex.js b/code/frontpage/assets/js/katex.js
new file mode 100644
index 0000000..e0543ea
--- /dev/null
+++ b/code/frontpage/assets/js/katex.js
@@ -0,0 +1,10 @@
+document.addEventListener('DOMContentLoaded', function() {
+ renderMathInElement(document.body, {
+ delimiters: [
+ {left: '$$', right: '$$', display: true},
+ {left: '$', right: '$', display: false},
+ {left: '\\(', right: '\\)', display: false},
+ {left: '\\[', right: '\\]', display: true},
+ ],
+ });
+});
diff --git a/code/frontpage/assets/js/lazysizes.js b/code/frontpage/assets/js/lazysizes.js
new file mode 100644
index 0000000..c12ed58
--- /dev/null
+++ b/code/frontpage/assets/js/lazysizes.js
@@ -0,0 +1 @@
+import 'lazysizes';
diff --git a/code/frontpage/assets/js/mermaid.js b/code/frontpage/assets/js/mermaid.js
new file mode 100644
index 0000000..98d67e1
--- /dev/null
+++ b/code/frontpage/assets/js/mermaid.js
@@ -0,0 +1,11 @@
+import mermaid from 'mermaid';
+
+var config = {
+ theme: 'default',
+ fontFamily: '-apple-system, blinkmacsystemfont, "Segoe UI", roboto, "Helvetica Neue", arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";',
+};
+
+document.addEventListener('DOMContentLoaded', () => {
+ mermaid.initialize(config);
+ mermaid.init(undefined, '.language-mermaid');
+});
diff --git a/code/frontpage/assets/js/scroll-lock.js b/code/frontpage/assets/js/scroll-lock.js
new file mode 100644
index 0000000..069b8c2
--- /dev/null
+++ b/code/frontpage/assets/js/scroll-lock.js
@@ -0,0 +1,14 @@
+// Adds scroll position lock for default docs sidebar
+
+if (document.querySelector('#sidebar-default') !== null) {
+ let sidebar = document.getElementById('sidebar-default');
+
+ let pos = sessionStorage.getItem('sidebar-scroll');
+ if (pos !== null) {
+ sidebar.scrollTop = parseInt(pos, 10);
+ }
+
+ window.addEventListener('beforeunload', () => {
+ sessionStorage.setItem('sidebar-scroll', sidebar.scrollTop);
+ });
+}
diff --git a/code/frontpage/assets/js/to-top.js b/code/frontpage/assets/js/to-top.js
new file mode 100644
index 0000000..3287f43
--- /dev/null
+++ b/code/frontpage/assets/js/to-top.js
@@ -0,0 +1,20 @@
+var topbutton = document.getElementById('toTop');
+
+if (topbutton !== null) {
+
+ topbutton.style.display = 'none';
+ window.onscroll = function() {
+ scrollFunction()
+ };
+
+}
+
+function scrollFunction() {
+
+ if (document.body.scrollTop > 40 || document.documentElement.scrollTop > 40) {
+ topbutton.style.display = 'block';
+ } else {
+ topbutton.style.display = 'none';
+ }
+
+}
diff --git a/code/frontpage/assets/js/vendor/.gitkeep b/code/frontpage/assets/js/vendor/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/code/frontpage/assets/js/vendor/.gitkeep
diff --git a/code/frontpage/assets/scss/app.scss b/code/frontpage/assets/scss/app.scss
new file mode 100644
index 0000000..e50a403
--- /dev/null
+++ b/code/frontpage/assets/scss/app.scss
@@ -0,0 +1,31 @@
+/** Import Bootstrap functions */
+@import "bootstrap/scss/functions";
+
+/** Import theme variables */
+@import "common/variables";
+
+/** Import Bootstrap */
+@import "bootstrap/scss/bootstrap";
+
+/** Import highlight.js */
+// @import "highlight.js/scss/github-dark-dimmed";
+
+/** Import theme styles */
+@import "common/global";
+@import "common/dark";
+@import "components/alerts";
+@import "components/buttons";
+@import "components/code";
+@import "components/details";
+@import "components/syntax";
+@import "components/comments";
+@import "components/forms";
+@import "components/images";
+@import "components/mermaid";
+@import "components/search";
+@import "components/tables";
+@import "layouts/footer";
+@import "layouts/header";
+@import "layouts/pages";
+@import "layouts/posts";
+@import "layouts/sidebar"; \ No newline at end of file
diff --git a/code/frontpage/assets/scss/common/_dark.scss b/code/frontpage/assets/scss/common/_dark.scss
new file mode 100644
index 0000000..2f77262
--- /dev/null
+++ b/code/frontpage/assets/scss/common/_dark.scss
@@ -0,0 +1,582 @@
+/** Theme variables */
+
+// Source: https://material.io/design/color/dark-theme.html
+
+$body-bg-dark: $gray-900;
+$body-overlay-dark: darken($body-bg-dark, 2.5%);
+
+/*
+$border-dark: darken($body-bg-dark, 2.5%);
+*/
+$border-dark: $gray-800;
+$body-color-dark: $gray-300;
+$dots-dark: darken($body-color-dark, 50%);
+
+$link-color-dark: $blue-300;
+$button-color-dark: $link-color-dark;
+$focus-color-dark: lighten($link-color-dark, 2.5%);
+
+$navbar-dark-color: $body-color-dark;
+$navbar-dark-hover-color: $link-color-dark;
+$navbar-dark-active-color: $link-color-dark;
+
+/** Theme styles */
+
+[data-dark-mode] body {
+ background: $body-bg-dark;
+ color: $body-color-dark;
+}
+
+[data-dark-mode] body a {
+ color: $link-color-dark;
+}
+
+[data-dark-mode] body a.text-body {
+ color: $body-color-dark !important;
+}
+
+[data-dark-mode] body .btn-primary {
+ @include button-variant($button-color-dark, $button-color-dark);
+
+ color: $body-bg-dark !important;
+}
+
+[data-dark-mode] body .btn-outline-primary {
+ @include button-outline-variant($button-color-dark, $button-color-dark);
+
+ color: $link-color-dark;
+}
+
+[data-dark-mode] body .btn-outline-primary:hover {
+ color: $body-bg-dark;
+}
+
+[data-dark-mode] body .btn-doks-light {
+ color: $navbar-dark-color;
+}
+
+[data-dark-mode] body .show > .btn-doks-light,
+[data-dark-mode] body .btn-doks-light:hover,
+[data-dark-mode] body .btn-doks-light:active {
+ color: $link-color-dark;
+}
+
+[data-dark-mode] body .btn-menu svg {
+ color: $body-color-dark;
+}
+
+[data-dark-mode] body .doks-sidebar-toggle {
+ color: $navbar-dark-color;
+}
+
+[data-dark-mode] body .btn-menu:hover,
+[data-dark-mode] body .btn-doks-light:hover,
+[data-dark-mode] body .doks-sidebar-toggle:hover {
+ background: $body-overlay-dark;
+}
+
+/*
+[data-dark-mode] body .dropdown-menu {
+ @extend .dropdown-menu-dark;
+}
+*/
+
+[data-dark-mode] body .navbar,
+[data-dark-mode] body .doks-subnavbar {
+ background-color: rgba(33, 37, 41, 0.95);
+ border-bottom: 1px solid $border-dark;
+}
+
+[data-dark-mode] body.home .navbar {
+ border-bottom: 0;
+}
+
+[data-dark-mode] body .offcanvas-header {
+ border-bottom: 1px solid $gray-800;
+}
+
+[data-dark-mode] body .offcanvas .nav-link {
+ color: $body-color-dark;
+}
+
+[data-dark-mode] body .offcanvas .nav-link:hover,
+[data-dark-mode] body .offcanvas .nav-link:focus {
+ color: $link-color-dark;
+}
+
+[data-dark-mode] body .offcanvas .nav-link.active {
+ color: $link-color-dark;
+}
+
+[data-dark-mode] body .navbar-light .navbar-brand {
+ color: $navbar-dark-color !important;
+}
+
+[data-dark-mode] body .navbar-light .navbar-nav .nav-link {
+ color: $navbar-dark-color;
+}
+
+[data-dark-mode] body .navbar-light .navbar-nav .nav-link:hover,
+[data-dark-mode] body .navbar-light .navbar-nav .nav-link:focus {
+ color: $navbar-dark-hover-color;
+}
+
+[data-dark-mode] body .navbar-light .navbar-nav .nav-link.disabled {
+ color: $navbar-dark-disabled-color;
+}
+
+[data-dark-mode] body .navbar-light .navbar-nav .show > .nav-link,
+[data-dark-mode] body .navbar-light .navbar-nav .active > .nav-link,
+[data-dark-mode] body .navbar-light .navbar-nav .nav-link.show,
+[data-dark-mode] body .navbar-light .navbar-nav .nav-link.active {
+ color: $navbar-dark-active-color;
+}
+
+[data-dark-mode] body .navbar-light .navbar-text {
+ color: $navbar-dark-color;
+}
+
+[data-dark-mode] body .alert-primary a {
+ color: $body-bg-dark;
+}
+
+[data-dark-mode] body .alert-doks {
+ background: $body-overlay-dark;
+ color: $body-color-dark;
+}
+
+[data-dark-mode] body .alert-doks a {
+ color: $link-color-dark;
+}
+
+[data-dark-mode] body .page-links a {
+ color: $body-color-dark;
+}
+
+[data-dark-mode] body .btn-toggle-nav a {
+ color: $body-color-dark;
+}
+
+[data-dark-mode] body .showcase-meta a {
+ color: $body-color-dark;
+}
+
+[data-dark-mode] body .showcase-meta a:hover,
+[data-dark-mode] body .showcase-meta a:focus {
+ color: $link-color-dark;
+}
+
+[data-dark-mode] body .docs-link:hover,
+[data-dark-mode] body .docs-link.active,
+[data-dark-mode] body .page-links a:hover {
+ text-decoration: none;
+ color: $link-color-dark;
+}
+
+[data-dark-mode] body .btn-toggle {
+ color: $body-color-dark;
+ background-color: transparent;
+ border: 0;
+}
+
+[data-dark-mode] body .btn-toggle:hover,
+[data-dark-mode] body .btn-toggle:focus {
+ color: $body-color-dark;
+}
+
+[data-dark-mode] body .btn-toggle::before {
+ width: 1.25em;
+ line-height: 0;
+ content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%28222, 226, 230, 0.75%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e");
+ transition: transform 0.35s ease;
+ transform-origin: 0.5em 50%;
+ margin-bottom: 0.125rem;
+}
+
+[data-dark-mode] body .btn-toggle[aria-expanded="true"] {
+ color: $body-color-dark;
+}
+
+[data-dark-mode] body .btn-toggle[aria-expanded="true"]::before {
+ transform: rotate(90deg);
+}
+
+[data-dark-mode] body .btn-toggle-nav a:hover,
+[data-dark-mode] body .btn-toggle-nav a:focus {
+ color: $link-color-dark;
+}
+
+[data-dark-mode] body .btn-toggle-nav a.active {
+ color: $link-color-dark;
+}
+
+[data-dark-mode] body .navbar-light .navbar-text a {
+ color: $navbar-dark-active-color;
+}
+
+[data-dark-mode] body .docs-links h3.sidebar-link a,
+[data-dark-mode] body .page-links h3.sidebar-link a {
+ color: $body-color-dark;
+}
+
+[data-dark-mode] body .navbar-light .navbar-text a:hover,
+[data-dark-mode] body .navbar-light .navbar-text a:focus {
+ color: $navbar-dark-active-color;
+}
+
+[data-dark-mode] body .navbar .btn-link {
+ color: $navbar-dark-color;
+}
+
+[data-dark-mode] body .content .btn-link {
+ color: $link-color-dark;
+}
+
+[data-dark-mode] body .content .btn-link:hover {
+ color: $link-color-dark;
+}
+
+[data-dark-mode] body .content img[src^="https://latex.codecogs.com/svg.latex"] {
+ filter: invert(1);
+}
+
+[data-dark-mode] body .navbar .btn-link:hover {
+ color: $navbar-dark-hover-color;
+}
+
+[data-dark-mode] body .navbar .btn-link:active {
+ color: $navbar-dark-active-color;
+}
+
+[data-dark-mode] body .form-control.is-search {
+ background: $body-overlay-dark;
+ border: 1px solid transparent;
+ color: $gray-300;
+
+ /*
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%236c757d' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-search'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");
+ background-repeat: no-repeat;
+ background-position: right calc(0.375em + 0.1875rem) center;
+ background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
+ */
+}
+
+[data-dark-mode] body .form-control.is-search:focus {
+ border: 1px solid $link-color-dark;
+}
+
+[data-dark-mode] body .doks-search::after {
+ color: $gray-300;
+ border: 1px solid $gray-700;
+}
+
+[data-dark-mode] body .text-dark {
+ color: $body-color-dark !important;
+}
+
+/*
+[data-dark-mode] body .navbar-form::after {
+ color: $gray-600;
+ border: 1px solid $gray-800;
+}
+*/
+
+[data-dark-mode] body .form-control {
+ color: $gray-300;
+}
+
+[data-dark-mode] body .form-control::placeholder {
+ color: $gray-400;
+ opacity: 1;
+}
+
+[data-dark-mode] body .border-top {
+ border-top: 1px solid $border-dark !important;
+}
+
+@include media-breakpoint-up(lg) {
+ [data-dark-mode] body .docs-sidebar {
+ order: 0;
+ border-right: 1px solid $border-dark;
+ }
+}
+
+[data-dark-mode] body .docs-navigation {
+ border-top: 1px solid $border-dark;
+}
+
+[data-dark-mode] body pre code::-webkit-scrollbar-thumb {
+ background: $gray-400;
+}
+
+[data-dark-mode] body code:not(.hljs) {
+ background: $body-overlay-dark;
+ color: $body-color-dark;
+}
+
+[data-dark-mode] body pre code:hover {
+ scrollbar-width: thin;
+ scrollbar-color: $border-dark transparent;
+}
+
+[data-dark-mode] body pre code::-webkit-scrollbar-thumb:hover {
+ background: $gray-500;
+}
+
+[data-dark-mode] body blockquote {
+ border-left: 3px solid $border-dark;
+}
+
+[data-dark-mode] body .footer {
+ border-top: 1px solid $border-dark;
+}
+
+[data-dark-mode] body .docs-links,
+[data-dark-mode] body .docs-toc {
+ scrollbar-width: thin;
+ scrollbar-color: $body-bg-dark $body-bg-dark;
+}
+
+[data-dark-mode] body .docs-links::-webkit-scrollbar,
+[data-dark-mode] body .docs-toc::-webkit-scrollbar {
+ width: 5px;
+}
+
+[data-dark-mode] body .docs-links::-webkit-scrollbar-track,
+[data-dark-mode] body .docs-toc::-webkit-scrollbar-track {
+ background: $body-bg-dark;
+}
+
+[data-dark-mode] body .docs-links::-webkit-scrollbar-thumb,
+[data-dark-mode] body .docs-toc::-webkit-scrollbar-thumb {
+ background: $body-bg-dark;
+}
+
+[data-dark-mode] body .docs-links:hover,
+[data-dark-mode] body .docs-toc:hover {
+ scrollbar-width: thin;
+ scrollbar-color: $border-dark $body-bg-dark;
+}
+
+[data-dark-mode] body .docs-links:hover::-webkit-scrollbar-thumb,
+[data-dark-mode] body .docs-toc:hover::-webkit-scrollbar-thumb {
+ background: $border-dark;
+}
+
+[data-dark-mode] body .docs-links::-webkit-scrollbar-thumb:hover,
+[data-dark-mode] body .docs-toc::-webkit-scrollbar-thumb:hover {
+ background: $border-dark;
+}
+
+[data-dark-mode] body .docs-links h3:not(:first-child) {
+ border-top: 1px solid $border-dark;
+}
+
+[data-dark-mode] body a.docs-link {
+ color: $body-color-dark;
+}
+
+[data-dark-mode] body .page-links li:not(:first-child) {
+ border-top: 1px dashed $border-dark;
+}
+
+[data-dark-mode] body .card {
+ background: $body-bg-dark;
+ border: 1px solid $border-dark;
+}
+
+[data-dark-mode] body .card.bg-light {
+ background: $body-overlay-dark !important;
+}
+
+[data-dark-mode] body .navbar .menu-icon .navicon {
+ background: $navbar-dark-color;
+}
+
+[data-dark-mode] body .navbar .menu-icon .navicon::before,
+[data-dark-mode] body .navbar .menu-icon .navicon::after {
+ background: $navbar-dark-color;
+}
+
+[data-dark-mode] body .logo-light {
+ display: none !important;
+}
+
+[data-dark-mode] body .logo-dark {
+ display: inline-block !important;
+}
+
+[data-dark-mode] body .bg-light {
+ background: darken($body-bg-dark, 1.5%) !important;
+}
+
+[data-dark-mode] body .bg-dots {
+ background-image: radial-gradient($dots-dark 15%, transparent 15%);
+}
+
+[data-dark-mode] body .text-muted {
+ color: darken($body-color-dark, 7.5%) !important;
+}
+
+[data-dark-mode] body .alert-primary {
+ background: $link-color-dark;
+ color: $body-bg-dark;
+}
+
+[data-dark-mode] body .figure-caption {
+ color: $body-color-dark;
+}
+
+[data-dark-mode] body table {
+ @extend .table-dark;
+}
+
+[data-dark-mode] body .copy-status::after {
+ content: "Copy";
+ display: block;
+ color: $body-color-dark;
+}
+
+[data-dark-mode] body .copy-status:hover::after {
+ content: "Copy";
+ display: block;
+ color: $link-color-dark;
+}
+
+[data-dark-mode] body .copy-status:focus::after,
+[data-dark-mode] body .copy-status:active::after {
+ content: "Copied";
+ display: block;
+ color: $link-color-dark;
+}
+
+/*
+[data-dark-mode] body .dropdown-toggle:focus,
+[data-dark-mode] body .doks-sidebar-toggle:focus {
+ box-shadow: 0 0 0 0.2rem $focus-color-dark;
+}
+*/
+
+[data-dark-mode] body .offcanvas {
+ background-color: $body-bg-dark;
+}
+
+[data-dark-mode] body .btn-close {
+ background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNkZWUyZTYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXgiPjxsaW5lIHgxPSIxOCIgeTE9IjYiIHgyPSI2IiB5Mj0iMTgiPjwvbGluZT48bGluZSB4MT0iNiIgeTE9IjYiIHgyPSIxOCIgeTI9IjE4Ij48L2xpbmU+PC9zdmc+");
+ background-size: 1.5rem;
+}
+
+@include media-breakpoint-up(md) {
+ [data-dark-mode] body .alert-dismissible .btn-close {
+ background-size: 1.25rem;
+ }
+}
+
+/*
+[data-dark-mode] body .btn-close:focus {
+ box-shadow: 0 0 0 0.2rem $focus-color-dark;
+}
+*/
+
+[data-dark-mode] .dropdown-item {
+ color: $body-bg-dark;
+}
+
+[data-dark-mode] body hr.text-black-50 {
+ color: $gray-600 !important;
+}
+
+[data-dark-mode] body .email-form .form-control {
+ background: $body-overlay-dark;
+ border: 1px solid transparent;
+}
+
+[data-dark-mode] body .email-form .form-control:focus {
+ border: 1px solid $link-color-dark;
+}
+
+[data-dark-mode] .page-link {
+ color: $link-color-dark;
+ background-color: transparent;
+ border: $pagination-border-width solid $border-dark;
+
+ &:hover {
+ color: $body-bg-dark;
+ background-color: $body-color-dark;
+ border-color: $body-color-dark;
+ }
+
+ &:focus {
+ color: $body-bg-dark;
+ background-color: $body-color-dark;
+ }
+}
+
+[data-dark-mode] .page-item {
+ &.active .page-link {
+ color: $body-bg-dark;
+
+ @include gradient-bg($link-color-dark);
+
+ border-color: $link-color-dark;
+ }
+
+ &.disabled .page-link {
+ color: $pagination-disabled-color;
+ background-color: $body-overlay-dark;
+ border-color: $border-dark;
+ }
+}
+
+[data-dark-mode] .dropdown-menu {
+ background: $body-overlay-dark;
+}
+
+[data-dark-mode] .dropdown-menu .dropdown-item {
+ color: $body-color-dark;
+}
+
+[data-dark-mode] .dropdown-menu .dropdown-item:hover {
+ color: $link-color-dark;
+ background: $body-bg-dark;
+}
+
+[data-dark-mode] .dropdown-menu .dropdown-item.active,
+[data-dark-mode] .dropdown-menu .dropdown-item:focus {
+ color: $link-color-dark;
+ background: $body-bg-dark;
+}
+
+[data-dark-mode] .doks-navbar .dropdown-item.current,
+[data-dark-mode] .doks-subnavbar .dropdown-item.current {
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23dee2e6' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");
+ background-repeat: no-repeat;
+ background-position: right 1rem top 0.6rem;
+ background-size: 0.75rem 0.75rem;
+}
+
+[data-dark-mode] details {
+ border: 1px solid $border-dark;
+}
+
+[data-dark-mode] summary:hover {
+ background: $body-overlay-dark;
+}
+
+[data-dark-mode] details[open] > summary {
+ border-bottom: 1px solid $border-dark;
+}
+
+[data-dark-mode] details summary::before {
+ content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%28222, 226, 230, 0.75%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e");
+}
+
+[data-dark-mode] #toc a.active {
+ color: $link-color-dark;
+}
+
+[data-dark-mode] .btn-light {
+ color: $link-color-dark;
+ background: $body-overlay-dark;
+ border: 1px solid $body-overlay-dark;
+}
diff --git a/code/frontpage/assets/scss/common/_global.scss b/code/frontpage/assets/scss/common/_global.scss
new file mode 100644
index 0000000..475ca6d
--- /dev/null
+++ b/code/frontpage/assets/scss/common/_global.scss
@@ -0,0 +1,288 @@
+.contributors .content,
+.blog .content,
+.page .content,
+.error404 .content,
+.docs.list .content,
+.tutorial.list .content,
+.showcase.list .content,
+.categories.list .content,
+.tags.list .content {
+ padding-top: 1rem;
+ padding-bottom: 3rem;
+}
+
+.content img {
+ max-width: 100%;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+.h1,
+.h2,
+.h3,
+.h4,
+.h5,
+.h6 {
+ margin: 2rem 0 1rem;
+}
+
+.offcanvas-header {
+ border-bottom: 1px solid $gray-300;
+ padding-top: 1.0625rem;
+ padding-bottom: 0.8125rem;
+}
+
+h5.offcanvas-title {
+ margin: 0;
+}
+
+body.docs {
+ padding-top: 0 !important;
+}
+
+@include media-breakpoint-up(md) {
+ body {
+ font-size: $font-size-md;
+
+ /*
+ padding-top: 4rem !important;
+ */
+ }
+
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6,
+ .h1,
+ .h2,
+ .h3,
+ .h4,
+ .h5,
+ .h6 {
+ margin-bottom: 1.125rem;
+ }
+}
+
+.home h1 {
+ /* font-size: calc(1.375rem + 1.5vw); */
+ font-size: calc(1.875rem + 1.5vw);
+}
+
+a:hover,
+a:focus {
+ text-decoration: underline;
+}
+
+a.btn:hover,
+a.btn:focus {
+ text-decoration: none;
+}
+
+.section {
+ padding-top: 5rem;
+ padding-bottom: 5rem;
+}
+
+.section-md {
+ padding-top: 3rem;
+ padding-bottom: 3rem;
+}
+
+.section-sm {
+ padding-top: 1rem;
+ padding-bottom: 1rem;
+}
+
+/*
+.section svg {
+ display: inline-block;
+ width: 2rem;
+ height: 2rem;
+ vertical-align: text-top;
+}
+*/
+
+/*
+body {
+ padding-top: 3.5625rem;
+}
+*/
+
+.docs-sidebar {
+ order: 2;
+}
+
+@include media-breakpoint-up(lg) {
+ .docs-sidebar {
+ order: 0;
+ border-right: 1px solid $gray-200;
+ }
+
+ @supports ((position:-webkit-sticky) or (position:sticky)) {
+ .docs-sidebar {
+ position: -webkit-sticky;
+ position: sticky;
+ top: 4rem;
+ z-index: 1000;
+ height: calc(100vh - 4rem);
+ }
+
+ .docs-sidebar-top {
+ top: 0;
+ }
+ }
+}
+
+@include media-breakpoint-up(xl) {
+ .docs-sidebar {
+ flex: 0 1 320px;
+ }
+}
+
+.docs-links {
+ padding-bottom: 5rem;
+}
+
+@include media-breakpoint-up(lg) {
+ @supports ((position: -webkit-sticky) or (position: sticky)) {
+ .docs-links {
+ max-height: calc(100vh - 4rem);
+ overflow-y: scroll;
+ }
+ }
+}
+
+@include media-breakpoint-up(lg) {
+ .docs-links {
+ display: block;
+ width: auto;
+ margin-right: -1.5rem;
+ padding-bottom: 4rem;
+ }
+}
+
+.docs-toc {
+ order: 2;
+}
+
+@supports ((position:-webkit-sticky) or (position:sticky)) {
+ .docs-toc {
+ position: -webkit-sticky;
+ position: sticky;
+ top: 4rem;
+ height: calc(100vh - 4rem);
+ overflow-y: auto;
+ }
+
+ .docs-toc-top {
+ top: 0;
+ }
+}
+
+.docs-content {
+ padding-bottom: 3rem;
+ order: 1;
+}
+
+.docs-navigation {
+ border-top: 1px solid $gray-200;
+ margin-top: 2rem;
+ margin-bottom: 0;
+ padding-top: 2rem;
+}
+
+.docs-navigation a {
+ font-size: $font-size-base * 0.9;
+}
+
+@include media-breakpoint-up(lg) {
+ .docs-navigation {
+ margin-bottom: -1rem;
+ }
+
+ .docs-navigation a {
+ font-size: $font-size-base;
+ }
+}
+
+.navbar a:hover,
+.navbar a:focus {
+ text-decoration: none;
+}
+
+#TableOfContents ul,
+#toc ul {
+ padding-left: 0;
+ list-style: none;
+}
+
+#toc a.active {
+ color: $primary;
+ font-weight: 500;
+}
+
+::selection {
+ background: rgba(212, 53, 159, 0.2);
+}
+
+.bg-dots {
+ background-image: radial-gradient($gray-300 15%, transparent 15%);
+ background-position: 0 0;
+ background-size: 1rem 1rem;
+ -webkit-mask: linear-gradient(to top, #fff, transparent);
+ mask: linear-gradient(to top, #fff, transparent);
+ width: 100%;
+ height: 9rem;
+ margin-top: -10rem;
+ z-index: -1;
+}
+
+.bg-dots-md {
+ margin-top: -11rem;
+}
+
+.bg-dots-lg {
+ margin-top: -12rem;
+}
+
+// https://fossheim.io/writing/posts/css-text-gradient/
+.gradient-text {
+ background-color: $primary;
+ background-image: linear-gradient(90deg, $primary, $blue-300 50%, $pink-500);
+ background-size: 100%;
+ background-repeat: repeat;
+ -webkit-background-clip: text;
+ -moz-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ -moz-text-fill-color: transparent;
+}
+
+.katex {
+ font-size: $font-size-md;
+}
+
+.card-bar {
+ border-top: 4px solid;
+ border-image-source: linear-gradient(90deg, $primary, #8ed6fb 50%, #d32e9d);
+ border-image-slice: 1;
+}
+
+.modal-backdrop {
+ background-color: #fff;
+}
+
+.modal-backdrop.show {
+ opacity: 0.7;
+}
+
+@include media-breakpoint-up(md) {
+ .modal-backdrop.show {
+ opacity: 0;
+ }
+}
diff --git a/code/frontpage/assets/scss/common/_variables.scss b/code/frontpage/assets/scss/common/_variables.scss
new file mode 100644
index 0000000..2737ce0
--- /dev/null
+++ b/code/frontpage/assets/scss/common/_variables.scss
@@ -0,0 +1,190 @@
+// Color system
+
+$white: #fff;
+$gray-100: #f8f9fa;
+$gray-200: #e9ecef;
+$gray-300: #dee2e6;
+$gray-400: #ced4da;
+$gray-500: #adb5bd;
+$gray-600: #6c757d;
+$gray-700: #495057;
+$gray-800: #343a40;
+$gray-900: #212529;
+$black: #000;
+
+$yellow: #ffe000;
+$black: #1d2d35;
+$beige: #fbf7f0;
+
+// $red: #e55235;
+$purple: #5d2f86;
+$brown: #aa9c84;
+
+$blue-300: #8ed6fb;
+$pink-100: #fcfaff;
+$pink-500: #d32e9d;
+
+$primary: $purple;
+
+$color-btn-bg: $pink-500;
+$color-btn-border: darken($pink-500, 5%);
+$color-btn-text: $white;
+
+// Options
+//
+// Quickly modify global styling by enabling or disabling optional features.
+
+$enable-caret: true;
+$enable-rounded: true;
+$enable-shadows: false;
+$enable-gradients: false;
+$enable-transitions: true;
+$enable-reduced-motion: true;
+$enable-smooth-scroll: true;
+$enable-grid-classes: true;
+$enable-button-pointers: true;
+$enable-rfs: true;
+$enable-validation-icons: true;
+$enable-negative-margins: true;
+$enable-deprecation-messages: true;
+$enable-important-utilities: true;
+
+/** Bootstrap navbar fix (https://git.io/fADqW) */
+$navbar-dark-toggler-icon-bg: none;
+$navbar-light-toggler-icon-bg: none;
+
+// Options
+//
+// Quickly modify global styling by enabling or disabling optional features.
+
+// $enable-responsive-font-sizes: true;
+
+// Body
+//
+// Settings for the `<body>` element.
+
+$body-bg: $white;
+$body-color: $black;
+
+// Links
+//
+// Style anchor elements.
+
+$link-color: $primary;
+$link-decoration: none;
+
+// Grid containers
+//
+// Define the maximum width of `.container` for different screen sizes.
+
+$container-max-widths: (
+ sm: 540px,
+ md: 720px,
+ lg: 960px,
+ xl: 1240px,
+ xxl: 1320px
+);
+
+@include _assert-ascending($container-max-widths, "$container-max-widths");
+
+// Grid columns
+//
+// Set the number of columns and specify the width of the gutters.
+
+$grid-columns: 16;
+$grid-gutter-width: 48px;
+$grid-row-columns: 6;
+
+// Components
+//
+// Define common padding and border radius sizes and more.
+
+$border-color: $gray-200;
+
+// Typography
+//
+// Font, line-height, and color for body text, headings, and more.
+
+// stylelint-disable value-keyword-case
+$font-family-sans-serif: -apple-system, blinkmacsystemfont, "Segoe UI", roboto, "Helvetica Neue", arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+$font-family-monospace: "Jetbrains Mono", sfmono-regular, menlo, monaco, consolas, "Liberation Mono", "Courier New", monospace;
+$font-family-base: $font-family-sans-serif;
+// stylelint-enable value-keyword-case
+
+$font-size-base: 1rem; // Assumes the browser default, typically `16px`
+$font-size-xl: $font-size-base * 1.375;
+$font-size-lg: $font-size-base * 1.25;
+$font-size-md: $font-size-base * 1.125;
+$font-size-sm: $font-size-base * 0.875;
+
+// $line-height-base: 1.5;
+
+$headings-font-family: null;
+$headings-font-weight: 700;
+
+$lead-font-weight: 400;
+
+// Spacing
+//
+// Control the default styling of most Bootstrap elements by modifying these
+// variables. Mostly focused on spacing.
+// You can add more entries to the $spacers map, should you need more variation.
+
+$spacer: 1rem;
+
+// Navbar
+
+$navbar-padding-y: $spacer / 2;
+$navbar-padding-x: null;
+
+$navbar-nav-link-padding-x: 0.5rem;
+
+$navbar-light-color: $black;
+$navbar-light-hover-color: $primary;
+$navbar-light-active-color: $primary;
+
+// Cards
+
+$card-border-color: $gray-200;
+
+// Alerts
+//
+// Define alert colors, border radius, and padding.
+
+$alert-padding-y: $spacer;
+$alert-padding-x: $spacer * 1.5;
+$alert-margin-bottom: 0;
+$alert-border-radius: 0;
+$alert-link-font-weight: $headings-font-weight;
+$alert-border-width: 0;
+
+$alert-bg-scale: 0;
+$alert-border-scale: 0;
+$alert-color-scale: 0;
+
+// docsearch
+$dropdown-config: (
+ main-color: $purple,
+ layout-type: normal,
+ layout-width: normal,
+ layout-alignment: align,
+ background-color: $white,
+ border-radius: 4,
+ border-width: 1,
+ border-color: $gray-200,
+ box-shadow: none,
+ branding-position: bottom,
+ spacing: normal,
+ include-desc: yes,
+ background-category-header: $white,
+ font-size: normal,
+ header-color: $black,
+ title-color: $black,
+ subtitle-color: $black,
+ text-color: $black,
+ highlight-color: $purple,
+ highlight-opacity: 0.1,
+ highlight-type: underline
+);
+
+$input-btn-focus-width: 0; \ No newline at end of file
diff --git a/code/frontpage/assets/scss/components/_alerts.scss b/code/frontpage/assets/scss/components/_alerts.scss
new file mode 100644
index 0000000..0e4ed83
--- /dev/null
+++ b/code/frontpage/assets/scss/components/_alerts.scss
@@ -0,0 +1,164 @@
+.alert {
+ font-family: $font-family-monospace;
+ font-size: $font-size-sm;
+}
+
+.alert-icon {
+ margin-right: 0.75rem;
+}
+
+.docs main .alert {
+ margin: 2rem -1.5rem;
+}
+
+.alert .alert-link {
+ text-decoration: underline;
+}
+
+.alert-doks {
+ background: $beige;
+ color: $black;
+}
+
+/*
+.alert-light {
+ color: #215888;
+ background: linear-gradient(-45deg, rgb(212, 245, 255), rgb(234, 250, 255), rgb(234, 250, 255), #d3f6ef);
+}
+
+.alert-light .alert-link {
+ color: #215888;
+}
+*/
+
+.alert-white {
+ background-color: rgba(255, 255, 255, 0.95);
+}
+
+.alert-primary {
+ color: $white;
+ background-color: $primary;
+}
+
+.alert a {
+ text-decoration: underline;
+}
+
+.alert-primary .alert-link {
+ color: $white;
+}
+
+/*
+.alert-primary {
+ color: #084298;
+ background-color: #cfe2ff;
+ border-color: #b6d4fe;
+}
+
+.alert-primary .alert-link {
+ color: #06357a;
+}
+*/
+
+.alert-secondary {
+ color: #41464b;
+ background-color: #e2e3e5;
+ border-color: #d3d6d8;
+}
+
+.alert-secondary .alert-link {
+ color: #34383c;
+}
+
+.alert-success {
+ color: #0f5132;
+ background-color: #d1e7dd;
+ border-color: #badbcc;
+}
+
+.alert-success .alert-link {
+ color: #0c4128;
+}
+
+.alert-info {
+ color: #055160;
+ background-color: #cff4fc;
+ border-color: #b6effb;
+}
+
+.alert-info .alert-link {
+ color: #04414d;
+}
+
+.alert-warning {
+ color: #664d03;
+ background-color: #fff3cd;
+ border-color: #ffecb5;
+}
+
+.alert-warning .alert-link {
+ color: #523e02;
+}
+
+.alert-danger {
+ color: #842029;
+ background-color: #f8d7da;
+ border-color: #f5c2c7;
+}
+
+.alert-danger .alert-link {
+ color: #6a1a21;
+}
+
+.alert-light {
+ color: #636464;
+ background-color: #fefefe;
+ border-color: #fdfdfe;
+}
+
+.alert-light .alert-link {
+ color: #4f5050;
+}
+
+.alert-dark {
+ color: #141619;
+ background-color: #d3d3d4;
+ border-color: #bcbebf;
+}
+
+.alert-dark .alert-link {
+ color: #101214;
+}
+
+.alert .alert-link:hover,
+.alert .alert-link:focus {
+ text-decoration: none;
+}
+
+.alert-dismissible .btn-close {
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ right: 1rem;
+ z-index: 2;
+ padding: 0.5rem;
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-x'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");
+ background-size: 1.5rem;
+ filter: invert(1) grayscale(100%) brightness(200%);
+}
+
+@include media-breakpoint-up(md) {
+ .alert-dismissible .btn-close {
+ background-size: 1.25rem;
+ }
+}
+
+[data-global-alert="closed"] #announcement {
+ display: none;
+}
+
+.alert code {
+ background: darken($beige, 5%);
+ color: $black;
+ padding: 0.25rem 0.5rem;
+}
diff --git a/code/frontpage/assets/scss/components/_buttons.scss b/code/frontpage/assets/scss/components/_buttons.scss
new file mode 100644
index 0000000..e923ab3
--- /dev/null
+++ b/code/frontpage/assets/scss/components/_buttons.scss
@@ -0,0 +1,255 @@
+.navbar .btn-link {
+ color: $navbar-light-color;
+ padding: 0.4375rem 0;
+}
+
+#mode {
+ padding: 0.5rem;
+}
+
+.btn-link:focus {
+ outline: 0;
+ box-shadow: none;
+}
+
+#navigation {
+ margin-left: 1.25rem;
+}
+
+@include media-breakpoint-up(lg) {
+ #mode {
+ margin-left: 0.5rem;
+ margin-right: 0.25rem;
+ }
+
+ .navbar .btn-link {
+ padding: 0.5625em 0.25rem 0.5rem 0.125rem;
+ }
+}
+
+.navbar .btn-link:hover {
+ color: $navbar-light-hover-color;
+}
+
+.navbar .btn-link:active {
+ color: $navbar-light-active-color;
+}
+
+body .toggle-dark {
+ display: block;
+}
+
+body .toggle-light {
+ display: none;
+}
+
+[data-dark-mode] body .toggle-light {
+ display: block;
+}
+
+[data-dark-mode] body .toggle-dark {
+ display: none;
+}
+
+pre {
+ position: relative;
+}
+
+@include media-breakpoint-down(md) {
+ .btn-copy {
+ display: none;
+ }
+}
+
+.btn-copy {
+ transition: opacity 0.3s ease-in-out;
+ visibility: hidden !important;
+ position: absolute;
+ right: 0.25rem;
+ top: 0.25rem;
+ z-index: 10;
+ font-family: $font-family-sans-serif;
+ font-size: $font-size-sm;
+ padding: 0.25rem 0.5rem;
+ color: $color-btn-text;
+ background-color: $color-btn-bg;
+ border-color: $color-btn-border;
+}
+
+.btn-copy:hover {
+ color: $color-btn-text;
+ background-color: lighten($color-btn-bg, 5%);
+ border-color: lighten($color-btn-border, 15%);
+}
+
+.btn-copy:focus {
+ color: $color-btn-text;
+ background-color: $color-btn-bg;
+ border-color: lighten($color-btn-border, 15%);
+ box-shadow: none;
+}
+
+.btn-copy:active,
+.btn-copy.active {
+ color: $color-btn-text;
+ background-color: $color-btn-bg;
+ border-color: lighten($color-btn-border, 15%);
+}
+
+.btn-copy:active:focus,
+.btn-copy.active:focus {
+ box-shadow: none;
+}
+
+@include media-breakpoint-up(md) {
+ pre:hover .btn-copy {
+ visibility: visible !important;
+ }
+}
+
+.btn-copy::after {
+ content: "Copy";
+ display: block;
+ color: $color-btn-text;
+}
+
+.btn-copy:hover::after {
+ content: "Copy";
+ display: block;
+ color: $color-btn-text;
+}
+
+.btn-copy:focus::after,
+.btn-copy:active::after {
+ content: "Copied";
+ display: block;
+ color: $color-btn-text;
+}
+
+.collapsible-sidebar {
+ margin: 2.125rem 0;
+}
+
+.btn-toggle {
+ display: inline-flex;
+ align-items: center;
+ padding: 0.25rem 0.5rem 0.25rem 0;
+ font-weight: $headings-font-weight;
+ font-size: $font-size-base;
+ text-transform: uppercase;
+ color: $body-color;
+ background-color: transparent;
+ border: 0;
+}
+
+.btn-toggle:hover,
+.btn-toggle:focus {
+ color: $body-color;
+ background-color: transparent;
+ outline: 0;
+ box-shadow: none;
+}
+
+.btn-toggle::before {
+ width: 1.25em;
+ line-height: 0;
+ content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%2829, 45, 53, 0.75%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e");
+ transition: transform 0.35s ease;
+ transform-origin: 0.5em 50%;
+ margin-bottom: 0.125rem;
+}
+
+.btn-toggle[aria-expanded="true"] {
+ color: $body-color;
+}
+
+.btn-toggle[aria-expanded="true"]::before {
+ transform: rotate(90deg);
+}
+
+.btn-toggle-nav a {
+ display: inline-flex;
+ padding: 0.1875rem 0.5rem;
+ margin-top: 0.125rem;
+ margin-left: 1.25rem;
+ text-decoration: none;
+}
+
+.btn-toggle-nav a:hover,
+.btn-toggle-nav a:focus {
+ background-color: transparent;
+ color: $link-color;
+}
+
+.btn-toggle-nav a.active {
+ color: $link-color;
+}
+
+.dropdown-menu {
+ /*
+ width: 100%;
+ */
+
+ width: auto;
+}
+
+@include media-breakpoint-up(lg) {
+ .dropdown-menu {
+ width: auto;
+ }
+}
+
+.doks-navbar .dropdown-menu,
+.doks-subnavbar .dropdown-menu {
+ font-size: 0.875rem;
+}
+
+.doks-navbar .dropdown-item.current,
+.doks-subnavbar .dropdown-item.current {
+ font-weight: 600;
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23292b2c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");
+ background-repeat: no-repeat;
+ background-position: right 1rem top 0.6rem;
+ background-size: 0.75rem 0.75rem;
+}
+
+.btn-close {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-x'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");
+ background-size: 1.5rem;
+}
+
+.offcanvas-header .btn-close {
+ margin-right: 0 !important;
+}
+
+.dropdown-toggle::after {
+ display: none;
+}
+
+.dropdown-caret {
+ margin-left: -0.1875rem;
+ margin-right: -0.3125rem;
+}
+
+.dropdown-menu-main .dropdown-item {
+ color: inherit;
+ font-size: $font-size-base;
+ font-weight: 400;
+ text-decoration: none;
+}
+
+.dropdown-menu-main .dropdown-item:hover {
+ background-color: transparent;
+ color: $primary;
+}
+
+.dropdown-menu-main .dropdown-item.active {
+ color: $primary;
+ font-weight: 400;
+ text-decoration: none;
+ background-color: inherit;
+}
+
+.dropdown-menu-main .dropdown-item.active:hover {
+ background-color: transparent;
+}
diff --git a/code/frontpage/assets/scss/components/_code.scss b/code/frontpage/assets/scss/components/_code.scss
new file mode 100644
index 0000000..84ad2bc
--- /dev/null
+++ b/code/frontpage/assets/scss/components/_code.scss
@@ -0,0 +1,66 @@
+pre,
+code,
+kbd,
+samp {
+ font-family: $font-family-monospace;
+ font-size: $font-size-sm;
+ border-radius: $border-radius;
+}
+
+code {
+ background: $beige;
+ color: $black;
+ padding: 0.25rem 0.5rem;
+}
+
+pre {
+ margin: 2rem 0;
+}
+
+pre code {
+ display: block;
+ overflow-x: auto;
+ line-height: $line-height-base;
+ padding: 1.25rem 1.5rem;
+ tab-size: 4;
+ scrollbar-width: thin;
+ scrollbar-color: transparent transparent;
+}
+
+.hljs {
+ padding: 1.5rem !important;
+}
+
+@include media-breakpoint-down(sm) {
+ pre,
+ code,
+ kbd,
+ samp {
+ border-radius: 0;
+ }
+
+ pre {
+ margin: 2rem -1.5rem;
+ }
+}
+
+pre code::-webkit-scrollbar {
+ height: 5px;
+}
+
+pre code::-webkit-scrollbar-thumb {
+ background: $gray-400;
+}
+
+pre code:hover {
+ scrollbar-width: thin;
+ scrollbar-color: $gray-500 transparent;
+}
+
+pre code::-webkit-scrollbar-thumb:hover {
+ background: $gray-500;
+}
+
+code.language-mermaid {
+ background: none;
+}
diff --git a/code/frontpage/assets/scss/components/_comments.scss b/code/frontpage/assets/scss/components/_comments.scss
new file mode 100644
index 0000000..18f610c
--- /dev/null
+++ b/code/frontpage/assets/scss/components/_comments.scss
@@ -0,0 +1,30 @@
+.comment-list {
+ @extend .list-unstyled;
+}
+
+.comment-list ol {
+ list-style: none;
+}
+
+.comment-form p {
+ @extend .form-group !optional;
+}
+
+.comment-form input[type="text"],
+.comment-form input[type="email"],
+.comment-form input[type="url"],
+.comment-form textarea {
+ @extend .form-control;
+}
+
+.comment-form input[type="submit"] {
+ @extend .btn;
+ @extend .btn-secondary;
+}
+
+blockquote {
+ margin-bottom: 1rem;
+ font-size: 1.25rem;
+ border-left: 3px solid $gray-300;
+ padding-left: 1rem;
+}
diff --git a/code/frontpage/assets/scss/components/_details.scss b/code/frontpage/assets/scss/components/_details.scss
new file mode 100644
index 0000000..fb719d3
--- /dev/null
+++ b/code/frontpage/assets/scss/components/_details.scss
@@ -0,0 +1,77 @@
+details {
+ display: block;
+ border: 1px solid $gray-200;
+ border-radius: 0.25rem;
+ padding: 0.5rem 1rem 0;
+ margin: 0.5rem 0;
+}
+
+/*
+details summary {
+ &::marker {
+ content: "";
+ }
+}
+*/
+
+summary {
+ list-style: none;
+ display: inline-block;
+ width: calc(100% + 2rem);
+ margin: -0.5rem -1rem 0;
+ padding: 0.5rem 0.75rem;
+}
+
+summary::-webkit-details-marker {
+ display: none;
+}
+
+summary:hover {
+ background: $gray-100;
+}
+
+details summary::before {
+ display: inline-block;
+ content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%2829, 45, 53, 0.75%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e");
+ transition: transform 0.35s ease;
+ transform-origin: center center;
+ margin-right: 0.375rem;
+}
+
+details[open] > summary::before {
+ transform: rotate(90deg);
+}
+
+/*
+details summary > * {
+ display: inline-block;
+}
+*/
+
+details[open] {
+ padding: 0.5rem 1rem;
+}
+
+details[open] > summary {
+ border-bottom: 1px solid $gray-300;
+ margin-bottom: 0.5rem;
+}
+
+details h2,
+details h3,
+details h4 {
+ margin: 1rem 0 0.5rem;
+}
+
+details p:last-child {
+ margin-bottom: 0;
+}
+
+details ul,
+details ol {
+ margin-bottom: 0;
+}
+
+details pre {
+ margin: 0 0 1rem;
+}
diff --git a/code/frontpage/assets/scss/components/_forms.scss b/code/frontpage/assets/scss/components/_forms.scss
new file mode 100644
index 0000000..9732838
--- /dev/null
+++ b/code/frontpage/assets/scss/components/_forms.scss
@@ -0,0 +1,19 @@
+/** Search form */
+.search-form {
+ @extend .form-inline !optional;
+}
+
+.search-form label {
+ @extend .form-group;
+
+ font-weight: normal;
+}
+
+.search-form .search-field {
+ @extend .form-control;
+}
+
+.search-form .search-submit {
+ @extend .btn;
+ @extend .btn-secondary;
+}
diff --git a/code/frontpage/assets/scss/components/_images.scss b/code/frontpage/assets/scss/components/_images.scss
new file mode 100644
index 0000000..efe3d1c
--- /dev/null
+++ b/code/frontpage/assets/scss/components/_images.scss
@@ -0,0 +1,62 @@
+figure {
+ margin: 0 0 1rem;
+ display: inline-block;
+}
+
+figure img {
+ margin-bottom: 0.5rem;
+ line-height: 1;
+ max-width: 100%;
+ height: auto;
+}
+
+figure figcaption {
+ margin: 0.25rem 0 0.75rem;
+ font-size: 0.875em;
+ color: #6c757d;
+}
+
+.figure-caption {
+ margin: 0.25rem 0 0.75rem;
+}
+
+figure.wide {
+ margin: 2rem -1.5rem;
+}
+
+figure.wide .figure-caption {
+ margin: 0.25rem 1.5rem 0.75rem;
+}
+
+@include media-breakpoint-up(md) {
+ figure.wide {
+ margin: 2rem -2.5rem;
+ }
+
+ figure.wide .figure-caption {
+ margin: 0.25rem 2.5rem 0.75rem;
+ }
+}
+
+@include media-breakpoint-up(lg) {
+ figure.wide {
+ margin: 2rem -5rem;
+ }
+
+ figure.wide .figure-caption {
+ margin: 0.25rem 5rem 0.75rem;
+ }
+}
+
+.blur-up {
+ filter: blur(5px);
+}
+
+.blur-up.lazyloaded {
+ filter: unset;
+}
+
+.img-simple {
+ margin-top: 0.375rem;
+ margin-bottom: 1.25rem;
+}
diff --git a/code/frontpage/assets/scss/components/_mermaid.scss b/code/frontpage/assets/scss/components/_mermaid.scss
new file mode 100644
index 0000000..3ff2488
--- /dev/null
+++ b/code/frontpage/assets/scss/components/_mermaid.scss
@@ -0,0 +1,8 @@
+.mermaid {
+ margin: 1.5rem 0;
+ padding: 1.5rem;
+}
+
+.mermaid svg {
+ height: auto;
+}
diff --git a/code/frontpage/assets/scss/components/_search.scss b/code/frontpage/assets/scss/components/_search.scss
new file mode 100644
index 0000000..531121a
--- /dev/null
+++ b/code/frontpage/assets/scss/components/_search.scss
@@ -0,0 +1,91 @@
+.navbar-form {
+ position: relative;
+}
+
+#suggestions {
+ position: absolute;
+ right: 0;
+ margin-top: 0.5rem;
+ width: calc(100vw - 3rem);
+ max-width: calc(400px - 3rem);
+ z-index: $zindex-dropdown;
+
+ @include media-breakpoint-up(md) {
+ right: -2rem;
+ }
+
+ @include media-breakpoint-up(lg) {
+ right: 0;
+ }
+}
+
+#suggestions a,
+.suggestion__no-results {
+ padding: 0.75rem;
+ margin: 0 0.5rem;
+}
+
+#suggestions a {
+ display: block;
+ text-decoration: none;
+}
+
+#suggestions a:focus {
+ background: $gray-100;
+ outline: 0;
+}
+
+#suggestions div:not(:first-child) {
+ border-top: 1px dashed $gray-200;
+}
+
+#suggestions div:first-child {
+ margin-top: 0.5rem;
+}
+
+#suggestions div:last-child {
+ margin-bottom: 0.5rem;
+}
+
+#suggestions a:hover {
+ background: $gray-100;
+}
+
+#suggestions span {
+ display: flex;
+ font-size: $font-size-base;
+}
+
+.suggestion__title {
+ font-weight: $headings-font-weight;
+ color: $black;
+}
+
+.suggestion__description,
+.suggestion__no-results {
+ color: $gray-700;
+}
+
+@include media-breakpoint-up(lg) {
+ #suggestions {
+ width: 31.125rem;
+ max-width: 31.125rem;
+ }
+
+ #suggestions a {
+ display: flex;
+ }
+
+ .suggestion__title {
+ width: 9rem;
+ padding-right: 1rem;
+ border-right: 1px solid $gray-200;
+ display: inline-block;
+ text-align: right;
+ }
+
+ .suggestion__description {
+ width: 19rem;
+ padding-left: 1rem;
+ }
+}
diff --git a/code/frontpage/assets/scss/components/_syntax.scss b/code/frontpage/assets/scss/components/_syntax.scss
new file mode 100644
index 0000000..2be315d
--- /dev/null
+++ b/code/frontpage/assets/scss/components/_syntax.scss
@@ -0,0 +1,62 @@
+/*
+
+Based on Ascetic by (c) Ivan Sagalaev <Maniac@SoftwareManiacs.Org>
+
+*/
+
+.hljs {
+ display: block;
+ overflow-x: auto;
+ padding: 1.25rem 1.5rem;
+ background: $beige;
+ color: $body-color;
+}
+
+.hljs-string,
+.hljs-variable,
+.hljs-template-variable,
+.hljs-symbol,
+.hljs-bullet,
+.hljs-section,
+.hljs-addition,
+.hljs-attribute,
+.hljs-link {
+ color: $pink-500;
+}
+
+.hljs-comment,
+.hljs-quote,
+.hljs-meta,
+.hljs-deletion {
+ color: #888;
+}
+
+.hljs-keyword,
+.hljs-selector-tag,
+.hljs-section,
+.hljs-name,
+.hljs-type,
+.hljs-strong {
+ font-weight: bold;
+}
+
+.hljs-emphasis {
+ font-style: italic;
+}
+
+[data-dark-mode] body .hljs {
+ background: $body-overlay-dark;
+ color: $body-color-dark;
+}
+
+[data-dark-mode] body .hljs-string,
+[data-dark-mode] body .hljs-variable,
+[data-dark-mode] body .hljs-template-variable,
+[data-dark-mode] body .hljs-symbol,
+[data-dark-mode] body .hljs-bullet,
+[data-dark-mode] body .hljs-section,
+[data-dark-mode] body .hljs-addition,
+[data-dark-mode] body .hljs-attribute,
+[data-dark-mode] body .hljs-link {
+ color: $blue-300;
+}
diff --git a/code/frontpage/assets/scss/components/_tables.scss b/code/frontpage/assets/scss/components/_tables.scss
new file mode 100644
index 0000000..b1f8c2e
--- /dev/null
+++ b/code/frontpage/assets/scss/components/_tables.scss
@@ -0,0 +1,5 @@
+table {
+ @extend .table;
+
+ margin: 3rem 0;
+}
diff --git a/code/frontpage/assets/scss/layouts/_footer.scss b/code/frontpage/assets/scss/layouts/_footer.scss
new file mode 100644
index 0000000..7d21811
--- /dev/null
+++ b/code/frontpage/assets/scss/layouts/_footer.scss
@@ -0,0 +1,20 @@
+.footer {
+ border-top: 1px solid $gray-200;
+ padding-top: 1.125rem;
+ padding-bottom: 1.125rem;
+}
+
+.footer ul {
+ margin-bottom: 0;
+}
+
+.footer li {
+ font-size: $font-size-sm;
+ margin-bottom: 0;
+}
+
+@include media-breakpoint-up(md) {
+ .footer li {
+ font-size: $font-size-base;
+ }
+}
diff --git a/code/frontpage/assets/scss/layouts/_header.scss b/code/frontpage/assets/scss/layouts/_header.scss
new file mode 100644
index 0000000..a0b4a0a
--- /dev/null
+++ b/code/frontpage/assets/scss/layouts/_header.scss
@@ -0,0 +1,493 @@
+.banner .nav li {
+ @extend .nav-item;
+}
+
+.banner .nav a {
+ @extend .nav-link;
+}
+
+.navbar-text {
+ margin-left: 1rem;
+}
+
+.navbar-brand {
+ font-weight: $headings-font-weight;
+}
+
+/*
+.navbar-light .navbar-brand,
+.navbar-light .navbar-brand:hover,
+.navbar-light .navbar-brand:active {
+ color: $body-color;
+}
+
+.navbar-light .navbar-nav .active .nav-link {
+ color: $primary;
+}
+*/
+
+.navbar {
+ z-index: 1000;
+ background-color: rgba(255, 255, 255, 0.95);
+ border-bottom: 1px solid $gray-200;
+
+ /*
+ margin-top: 4px;
+ */
+}
+
+@include media-breakpoint-up(lg) {
+ .navbar {
+ z-index: 1025;
+ padding-top: 0.25rem;
+ padding-bottom: 0.25rem;
+ }
+}
+
+@include media-breakpoint-up(md) {
+ .navbar-brand {
+ font-size: $font-size-xl;
+ }
+
+ .navbar-text {
+ margin-left: 1.25rem;
+ }
+}
+
+.navbar-nav {
+ flex-direction: row;
+}
+
+.nav-item {
+ margin-left: 0;
+}
+
+@include media-breakpoint-up(md) {
+ .nav-item {
+ margin-left: 0.5rem;
+ }
+}
+
+/*
+@include media-breakpoint-down(sm) {
+ .nav-item:first-child {
+ margin-left: 0;
+ }
+}
+*/
+
+@include media-breakpoint-down(md) {
+ .navbar .container {
+ padding-left: 1.5rem;
+ padding-right: 1.5rem;
+ }
+}
+
+.break {
+ flex-basis: 100%;
+ height: 0;
+}
+
+button#doks-languages {
+ margin: 0.25rem 0 0;
+
+ @include media-breakpoint-up(lg) {
+ margin: 0.25rem 0.5rem 0 0.25rem;
+ }
+}
+
+button#doks-versions {
+ margin: 0.25rem 0 0;
+
+ @include media-breakpoint-up(lg) {
+ margin: 0.25rem 0.5rem 0 0.25rem;
+ }
+}
+
+.offcanvas .nav-link {
+ color: $body-color;
+}
+
+.doks-subnavbar {
+ background-color: rgba(255, 255, 255, 0.95);
+ border-bottom: 1px solid $gray-200;
+}
+
+.doks-subnavbar .nav-link {
+ padding: 0.5rem 1.5rem 0.5rem 0;
+}
+
+.doks-subnavbar .nav-link:first-child {
+ padding: 0.5rem 1.5rem 0.5rem 0;
+}
+
+.offcanvas .nav-link:hover,
+.offcanvas .nav-link:focus {
+ color: $link-color;
+}
+
+.offcanvas .nav-link.active {
+ color: $link-color;
+}
+
+/*
+.navbar {
+ background-color: rgba(255, 255, 255, 0.95);
+ border-bottom: 1px solid $gray-200;
+ margin-top: 4px;
+}
+*/
+
+.header-bar {
+ border-top: 4px solid;
+ border-image-source: linear-gradient(90deg, $primary, #8ed6fb 50%, #d32e9d);
+ border-image-slice: 1;
+}
+
+.offcanvas .header-bar {
+ margin-bottom: -4px;
+}
+
+.home .navbar {
+ border-bottom: 0;
+}
+
+/*
+.navbar-form {
+ position: relative;
+ margin-top: 0.25rem;
+}
+*/
+
+@include media-breakpoint-up(md) {
+ .navbar-brand {
+ margin-right: 0.75rem !important;
+ }
+
+ .main-nav .nav-item:first-child .nav-link,
+ .social-nav .nav-item:first-child .nav-link {
+ padding-left: 0;
+ }
+
+ .main-nav .nav-item:last-child .nav-link,
+ .social-nav .nav-item:last-child .nav-link {
+ padding-right: 0;
+ }
+
+ .doks-search {
+ max-width: 20rem;
+ margin-top: 0.125rem;
+ margin-bottom: 0.125rem;
+ }
+
+ /*
+ .navbar-form {
+ margin-top: 0;
+ margin-left: 6rem;
+ margin-right: 1.5rem;
+ }
+ */
+}
+
+.form-control.is-search {
+ padding-right: 4rem;
+ border: 1px solid transparent;
+ background: $gray-100;
+
+ @include media-breakpoint-up(md) {
+ width: calc(100% + 2rem);
+ }
+
+ @include media-breakpoint-up(lg) {
+ width: 100%;
+ }
+}
+
+.form-control.is-search:focus {
+ border: 1px solid $primary;
+}
+
+.doks-search::after {
+ position: absolute;
+ top: 0.4625rem;
+ right: 0.5375rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 1.5rem;
+ padding-right: 0.3125rem;
+ padding-left: 0.3125rem;
+ font-size: $font-size-base * 0.75;
+ color: $gray-700;
+ content: "Ctrl + /";
+ border: 1px solid $gray-300;
+ border-radius: 0.25rem;
+
+ @include media-breakpoint-up(md) {
+ right: -1.4625rem;
+ }
+
+ @include media-breakpoint-up(lg) {
+ right: 0.3125rem;
+ }
+}
+
+/*
+@include media-breakpoint-up(lg) {
+ .navbar-form {
+ margin-left: 15rem;
+ }
+}
+
+@include media-breakpoint-up(xl) {
+ .navbar-form {
+ margin-left: 30rem;
+ }
+}
+*/
+
+/*
+.form-control.is-search {
+*/
+
+/*
+ padding-right: calc(1.5em + 0.75rem);
+ */
+
+/*
+ padding-right: 2.5rem;
+ background: $gray-100;
+ border: 0;
+ */
+
+/*
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%236c757d' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-search'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");
+ background-repeat: no-repeat;
+ background-position: right calc(0.375em + 0.1875rem) center;
+ background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
+ */
+
+/*
+}
+*/
+
+/*
+.navbar-form::after {
+ position: absolute;
+ top: 0.4625rem;
+ right: 0.5375rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 1.5rem;
+ padding-right: 0.4375rem;
+ padding-left: 0.4375rem;
+ font-size: $font-size-base * 0.75;
+ color: $gray-700;
+ content: "/";
+ border: 1px solid $gray-300;
+ border-radius: 0.25rem;
+}
+*/
+
+/*! purgecss start ignore */
+.algolia-autocomplete {
+ display: flex !important;
+}
+
+.algolia-autocomplete .ds-dropdown-menu {
+ box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;
+}
+
+@include media-breakpoint-down(sm) {
+ .algolia-autocomplete .ds-dropdown-menu {
+ max-width: 512px !important;
+ min-width: 312px !important;
+ width: auto !important;
+ }
+
+ .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column {
+ font-weight: normal;
+ }
+
+ .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column::after {
+ content: "/";
+ margin-right: 0.25rem;
+ }
+}
+
+.algolia-autocomplete .algolia-docsearch-suggestion--category-header {
+ color: $black;
+}
+
+.algolia-autocomplete .algolia-docsearch-suggestion--title {
+ margin-bottom: 0;
+}
+
+.algolia-autocomplete .algolia-docsearch-suggestion--highlight {
+ padding: 0 0.05em;
+}
+
+.algolia-autocomplete .algolia-docsearch-footer {
+ margin-top: 1rem;
+ margin-right: 0.5rem;
+ margin-bottom: 0.5rem;
+}
+
+/*! purgecss end ignore */
+
+/*
+ * Source: https://medium.com/creative-technology-concepts-code/responsive-mobile-dropdown-navigation-using-css-only-7218e4498a99
+*/
+
+/* Style the menu icon for the dropdown */
+
+.navbar .menu-icon {
+ cursor: pointer;
+
+ /* display: inline-block; */
+
+ /* float: right; */
+ padding: 1.125rem 0.625rem;
+ margin: 0 0 0 -0.625rem;
+
+ /* position: relative; */
+ user-select: none;
+}
+
+.navbar .menu-icon .navicon {
+ background: $navbar-light-color;
+ display: block;
+ height: 2px;
+ position: relative;
+ transition: background 0.2s ease-out;
+ width: 18px;
+}
+
+.navbar .menu-icon .navicon::before,
+.navbar .menu-icon .navicon::after {
+ background: $navbar-light-color;
+ content: "";
+ display: block;
+ height: 100%;
+ position: absolute;
+ transition: all 0.2s ease-out;
+ width: 100%;
+}
+
+.navbar .menu-icon .navicon::before {
+ top: 5px;
+}
+
+.navbar .menu-icon .navicon::after {
+ top: -5px;
+}
+
+/* Add the icon and menu animations when the checkbox is clicked */
+
+.navbar .menu-btn {
+ display: none;
+}
+
+.navbar .menu-btn:checked ~ .navbar-collapse {
+ display: block;
+ max-height: 100vh;
+}
+
+.navbar .menu-btn:checked ~ .menu-icon .navicon {
+ background: transparent;
+}
+
+.navbar .menu-btn:checked ~ .menu-icon .navicon::before {
+ transform: rotate(-45deg);
+}
+
+.navbar .menu-btn:checked ~ .menu-icon .navicon::after {
+ transform: rotate(45deg);
+}
+
+.navbar .menu-btn:checked ~ .menu-icon:not(.steps) .navicon::before,
+.navbar .menu-btn:checked ~ .menu-icon:not(.steps) .navicon::after {
+ top: 0;
+}
+
+.btn-menu {
+ margin-left: 1rem;
+ border: transparent;
+}
+
+.btn-doks-light {
+ border: transparent;
+}
+
+.btn-menu,
+.doks-sidebar-toggle {
+ padding-right: 0.25rem;
+ padding-left: 0.25rem;
+ margin-right: -0.5rem;
+}
+
+.btn-menu:hover,
+.btn-doks-light:hover,
+.doks-sidebar-toggle:hover {
+ background: $pink-100;
+ border: transparent;
+}
+
+.btn-menu:focus,
+.btn-doks-light:focus,
+.doks-sidebar-toggle:focus,
+.doks-mode-toggle:focus {
+ outline: 0;
+ border: transparent;
+}
+
+.doks-sidebar-toggle .doks-collapse,
+.doks-toc-toggle .doks-collapse {
+ display: none;
+}
+
+.doks-sidebar-toggle:not(.collapsed) .doks-expand,
+.doks-toc-toggle:not(.collapsed) .doks-expand {
+ display: none;
+}
+
+.doks-sidebar-toggle:not(.collapsed) .doks-collapse,
+.doks-toc-toggle:not(.collapsed) .doks-collapse {
+ display: inline-block;
+}
+
+.navbar-light .navbar-brand,
+.navbar-light .navbar-brand:hover,
+.navbar-light .navbar-brand:active {
+ color: $body-color;
+}
+
+.navbar-light .navbar-nav .active .nav-link {
+ color: $primary;
+}
+
+.dropdown-divider {
+ border-top: 1px dashed $gray-200;
+}
+
+.dropdown-item:hover {
+ background: $gray-100;
+}
+
+.dropdown-item:active {
+ color: inherit;
+}
+
+.social-link {
+ padding-left: 0.5rem;
+
+ @include media-breakpoint-up(md) {
+ padding-left: 0;
+ }
+
+ @include media-breakpoint-up(lg) {
+ padding-right: 0.5rem;
+ padding-left: 0.5rem;
+ }
+}
diff --git a/code/frontpage/assets/scss/layouts/_pages.scss b/code/frontpage/assets/scss/layouts/_pages.scss
new file mode 100644
index 0000000..405ede9
--- /dev/null
+++ b/code/frontpage/assets/scss/layouts/_pages.scss
@@ -0,0 +1,64 @@
+.docs-content > h2[id]::before,
+.docs-content > h3[id]::before,
+.docs-content > h4[id]::before {
+ display: block;
+ height: 6rem;
+ margin-top: -6rem;
+ content: "";
+}
+
+.anchor {
+ visibility: hidden;
+}
+
+h1:hover a,
+h2:hover a,
+h3:hover a,
+h4:hover a {
+ visibility: visible;
+ text-decoration: none;
+}
+
+.card-list {
+ margin-top: 2.25rem;
+}
+
+.page-footer-meta {
+ margin-top: 3rem;
+}
+
+.edit-page,
+.last-modified {
+ font-size: $font-size-sm;
+ margin-top: 0.25rem;
+ margin-bottom: 0.25rem;
+}
+
+@include media-breakpoint-up(md) {
+ .edit-page,
+ .last-modified {
+ font-size: $font-size-base;
+ margin-top: 0.75rem;
+ margin-bottom: 0.25rem;
+ }
+}
+
+.edit-page svg,
+.last-modified svg {
+ margin-right: 0.25rem;
+ margin-bottom: 0.25rem;
+}
+
+p.meta {
+ margin-top: 0.5rem;
+ font-size: $font-size-base;
+}
+
+.breadcrumb {
+ margin-top: 2.25rem;
+ font-size: $font-size-base;
+}
+
+.page-link:hover {
+ text-decoration: none;
+}
diff --git a/code/frontpage/assets/scss/layouts/_posts.scss b/code/frontpage/assets/scss/layouts/_posts.scss
new file mode 100644
index 0000000..27d316a
--- /dev/null
+++ b/code/frontpage/assets/scss/layouts/_posts.scss
@@ -0,0 +1,57 @@
+.home .card,
+.contributors.list .card,
+.blog.list .card,
+.blog.single .card,
+.categories.list .card,
+.tags.list .card {
+ margin-top: 2rem;
+ margin-bottom: 2rem;
+ transition: transform 0.3s;
+}
+
+.home .card:hover,
+.contributors.list .card:hover,
+.blog.list .card:hover,
+.blog.single .card:hover,
+.categories.list .card:hover,
+.tags.list .card:hover {
+ transform: scale(1.025);
+}
+
+.contributors.list .card.card-terms:hover,
+.categories.list .card.card-terms:hover,
+.tags.list .card.card-terms:hover {
+ transform: none;
+}
+
+.home .card-body,
+.contributors.list .card-body,
+.blog.list .card-body,
+.blog.single .card-body,
+.categories.list .card-body,
+.tags.list .card-body {
+ padding: 0 2rem 1rem;
+}
+
+.contributors.list .card-terms .card-body,
+.categories.list .card-terms .card-body,
+.tags.list .card-terms .card-body {
+ padding: 1rem;
+}
+
+.blog-header {
+ text-align: center;
+ margin-bottom: 2rem;
+}
+
+.blog-footer {
+ text-align: center;
+}
+
+.related-posts {
+ margin-top: 4rem;
+}
+
+h2.section-title {
+ margin-bottom: 1.25rem;
+}
diff --git a/code/frontpage/assets/scss/layouts/_sidebar.scss b/code/frontpage/assets/scss/layouts/_sidebar.scss
new file mode 100644
index 0000000..88959bf
--- /dev/null
+++ b/code/frontpage/assets/scss/layouts/_sidebar.scss
@@ -0,0 +1,116 @@
+.docs-links,
+.docs-toc {
+ scrollbar-width: thin;
+ scrollbar-color: $white $white;
+}
+
+.docs-links::-webkit-scrollbar,
+.docs-toc::-webkit-scrollbar {
+ width: 5px;
+}
+
+.docs-links::-webkit-scrollbar-track,
+.docs-toc::-webkit-scrollbar-track {
+ background: $white;
+}
+
+.docs-links::-webkit-scrollbar-thumb,
+.docs-toc::-webkit-scrollbar-thumb {
+ background: $white;
+}
+
+.docs-links:hover,
+.docs-toc:hover {
+ scrollbar-width: thin;
+ scrollbar-color: $gray-200 $white;
+}
+
+.docs-links:hover::-webkit-scrollbar-thumb,
+.docs-toc:hover::-webkit-scrollbar-thumb {
+ background: $gray-200;
+}
+
+.docs-links::-webkit-scrollbar-thumb:hover,
+.docs-toc::-webkit-scrollbar-thumb:hover {
+ background: $gray-200;
+}
+
+.docs-links h3,
+.page-links h3 {
+ text-transform: uppercase;
+ font-size: $font-size-base;
+ margin: 1.25rem 0 0.5rem;
+ padding: 1.5rem 0 0;
+}
+
+@include media-breakpoint-up(lg) {
+ .docs-links h3,
+ .page-links h3 {
+ margin: 1.125rem 1.5rem 0.75rem 0;
+ padding: 1.375rem 0 0;
+ }
+}
+
+.docs-links h3:not(:first-child) {
+ border-top: 1px solid $gray-200;
+}
+
+a.docs-link {
+ color: $body-color;
+ display: block;
+ padding: 0.125rem 0;
+ font-size: $font-size-base;
+}
+
+.page-links li {
+ margin-top: 0.375rem;
+ padding-top: 0.375rem;
+}
+
+.page-links li ul li {
+ border-top: none;
+ padding-left: 1rem;
+ margin-top: 0.125rem;
+ padding-top: 0.125rem;
+}
+
+.page-links li:not(:first-child) {
+ border-top: 1px dashed $gray-200;
+}
+
+.page-links a {
+ color: $body-color;
+ display: block;
+ padding: 0.125rem 0;
+ font-size: $font-size-base * 0.9375;
+}
+
+.docs-link:hover,
+.docs-link.active,
+.page-links a:hover {
+ text-decoration: none;
+ color: $link-color;
+}
+
+.nav-link.active,
+.dropdown-menu-main .dropdown-item.active,
+.docs-link.active {
+ font-weight: 500;
+}
+
+.docs-links h3.sidebar-link,
+.page-links h3.sidebar-link {
+ text-transform: none;
+ font-size: $font-size-md;
+ font-weight: normal;
+}
+
+.docs-links h3.sidebar-link a,
+.page-links h3.sidebar-link a {
+ color: $body-color;
+}
+
+.docs-links h3.sidebar-link a:hover,
+.page-links h3.sidebar-link a:hover {
+ text-decoration: underline;
+}
diff --git a/code/frontpage/assets/scss/vendor/.gitkeep b/code/frontpage/assets/scss/vendor/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/code/frontpage/assets/scss/vendor/.gitkeep