diff --git a/book.toml b/book.toml
index 64ad53c..3f8e92f 100644
--- a/book.toml
+++ b/book.toml
@@ -18,6 +18,7 @@ preferred-dark-theme = "coal"
additional-css = [
"css/side-nav.css",
"css/header.css",
+ "css/footer.css",
"css/extended.css",
"css/highlight.css",
"css/highlight-dark.css",
diff --git a/css/discord.svg b/css/discord.svg
new file mode 100644
index 0000000..f455b72
--- /dev/null
+++ b/css/discord.svg
@@ -0,0 +1 @@
+
diff --git a/css/footer.css b/css/footer.css
new file mode 100644
index 0000000..31cf3ba
--- /dev/null
+++ b/css/footer.css
@@ -0,0 +1,92 @@
+/* Custom CSS for the Footer Component */
+
+:root {
+ --footer-color-primary: #000;
+ --footer-color-primary-inverted: #fff;
+ --footer-color-secondary: #19455e;
+ --footer-section-margin-bottom: 3rem;
+}
+
+.frqcy-footer {
+ background: var(--footer-color-primary-inverted);
+ z-index: 1;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ color: var(--footer-color-primary);
+ padding: var(--footer-section-margin-bottom) 1rem;
+}
+
+#frqcy-footer-logo {
+ display: block;
+ max-width: 257px;
+ width: 100%;
+ color: var(--footer-color-primary);
+ margin-bottom: var(--footer-section-margin-bottom);
+}
+
+#frqcy-footer-copyright {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ text-align: center;
+ width: 100%;
+ line-height: 1;
+ margin: 0 1rem var(--footer-section-margin-bottom) 1rem;
+}
+
+#frqcy-footer-copyright div.frqcy-footer-vbar {
+ width: 10%;
+ height: 2px;
+ background: var(--footer-color-primary);
+ justify-self: stretch;
+ margin: 1rem auto;
+}
+
+#frqcy-footer-copyright a {
+ color: var(--footer-color-primary);
+ padding: 0;
+}
+
+#frqcy-footer-copyright a:hover,
+#frqcy-footer-copyright a:visited:hover {
+ color: var(--footer-color-secondary);
+}
+
+.frqcy-footer .frqcy-footer-social-links {
+ display: flex;
+ flex-direction: row;
+ margin-bottom: var(--footer-section-margin-bottom);
+ width: 100%;
+ justify-content: center;
+}
+
+.frqcy-footer .frqcy-footer-social-links a {
+ cursor: pointer;
+ display: flex;
+ height: 100%;
+ margin: 1rem;
+ padding: 0.5rem;
+ border-radius: 0.5rem;
+ flex: 0 0 32px;
+ background: var(--footer-color-primary);
+ color: var(--footer-color-primary-inverted);
+}
+
+.frqcy-footer .frqcy-footer-social-links a:hover,
+.frqcy-footer .frqcy-footer-social-links a:visited:hover {
+ background: var(--footer-color-secondary);
+}
+
+/* Desktop */
+@media only screen and (min-width: 620px) {
+ #frqcy-footer-copyright {
+ flex-direction: row;
+ }
+
+ #frqcy-footer-copyright div.frqcy-footer-vbar {
+ width: 2px;
+ height: 100%;
+ margin: 0 2rem;
+ }
+}
diff --git a/css/header.css b/css/header.css
index 3cbe358..1966fe8 100644
--- a/css/header.css
+++ b/css/header.css
@@ -9,27 +9,30 @@
/* Everything is scoped to .frqcy-header */
.frqcy-header {
+ height: var(--header-height);
+ position: sticky;
+ top: 0;
+
+ width: 100vw;
+ padding: 0 16px;
+
font-family: "Newake", "Arial Black", Arial, sans-serif;
text-transform: uppercase;
color: var(--header-color-primary);
- height: 80px;
- background-color: var(--header-background);
- box-shadow: 0 4px 4px 0 #00000040;
- width: 100vw;
- position: fixed;
- top: 0;
- left: 0;
- z-index: 1000;
display: flex;
justify-content: space-between;
align-items: center;
- padding: 0 20px 0 40px;
box-sizing: border-box;
+
+ background-color: var(--header-background);
+ box-shadow: 0 4px 4px 0 #00000040;
+ width: 100vw;
+ z-index: 1000;
}
@media (min-width: 800px) {
.frqcy-header {
- padding: 0 80px;
+ padding: 0 62px;
}
}
@@ -38,7 +41,6 @@
}
.frqcy-header .header-logo {
- padding-right: 16px;
height: auto;
width: 236px;
color: var(--header-color-secondary);
diff --git a/css/side-nav.css b/css/side-nav.css
index 87b3929..c7566ff 100644
--- a/css/side-nav.css
+++ b/css/side-nav.css
@@ -73,6 +73,11 @@
margin-block-start: 4.5rem;
}
+/* n(1) is hidden, so we need to remove the margin from n(2) */
+#toc > .chapter li.chapter-item:nth-child(2) {
+ margin-block-start: 0;
+}
+
#toc > .chapter > li > a:first-of-type {
padding-inline-start: 1rem;
font-weight: bold;
diff --git a/css/x.svg b/css/x.svg
new file mode 100644
index 0000000..0ddfd95
--- /dev/null
+++ b/css/x.svg
@@ -0,0 +1 @@
+
diff --git a/theme/book.js b/theme/book.js
index c28b50d..78dd5cc 100644
--- a/theme/book.js
+++ b/theme/book.js
@@ -604,66 +604,3 @@ function playground_text(playground, hidden = true) {
document.scrollingElement.scrollTo({ top: 0, behavior: "smooth" });
});
})();
-
-(function controllMenu() {
- var menu = document.getElementById("menu-bar");
-
- (function controllPosition() {
- var scrollTop = document.scrollingElement.scrollTop;
- var prevScrollTop = scrollTop;
- var minMenuY = -menu.clientHeight - 50;
- // When the script loads, the page can be at any scroll (e.g. if you reforesh it).
- menu.style.top = scrollTop + "px";
- // Same as parseInt(menu.style.top.slice(0, -2), but faster
- var topCache = menu.style.top.slice(0, -2);
- menu.classList.remove("sticky");
- var stickyCache = false; // Same as menu.classList.contains('sticky'), but faster
- document.addEventListener(
- "scroll",
- function () {
- scrollTop = Math.max(document.scrollingElement.scrollTop, 0);
- // `null` means that it doesn't need to be updated
- var nextSticky = null;
- var nextTop = null;
- var scrollDown = scrollTop > prevScrollTop;
- var menuPosAbsoluteY = topCache - scrollTop;
- if (scrollDown) {
- nextSticky = false;
- if (menuPosAbsoluteY > 0) {
- nextTop = prevScrollTop;
- }
- } else {
- if (menuPosAbsoluteY > 0) {
- nextSticky = true;
- } else if (menuPosAbsoluteY < minMenuY) {
- nextTop = prevScrollTop + minMenuY;
- }
- }
- if (nextSticky === true && stickyCache === false) {
- menu.classList.add("sticky");
- stickyCache = true;
- } else if (nextSticky === false && stickyCache === true) {
- menu.classList.remove("sticky");
- stickyCache = false;
- }
- if (nextTop !== null) {
- menu.style.top = nextTop + "px";
- topCache = nextTop;
- }
- prevScrollTop = scrollTop;
- },
- { passive: true },
- );
- })();
- (function controllBorder() {
- function updateBorder() {
- if (menu.offsetTop === 0) {
- menu.classList.remove("bordered");
- } else {
- menu.classList.add("bordered");
- }
- }
- updateBorder();
- document.addEventListener("scroll", updateBorder, { passive: true });
- })();
-})();
diff --git a/theme/css/chrome.css b/theme/css/chrome.css
index 2a292cc..70c0f19 100644
--- a/theme/css/chrome.css
+++ b/theme/css/chrome.css
@@ -2,6 +2,54 @@
@import "variables.css";
+:target {
+ scroll-margin-top: calc(var(--header-height) + 20px);
+}
+
+/* GRID */
+#body-container {
+ min-height: 100vh;
+ display: grid;
+ grid:
+ [row1-start] "header header header header" auto [row1-end]
+ [row2-start] "sidebar sidebar-resize menu-bar content" 1fr [row2-end]
+ [row3-start] "footer footer footer footer" auto [row3-end]
+ / 0 0 auto 1fr;
+}
+
+.no-js #body-container {
+ display: grid;
+ grid:
+ [row1-start] "header header header" auto [row1-end]
+ [row2-start] "sidebar sidebar-resize menu-bar content" auto [row2-end]
+ [row3-start] "footer footer footer" auto [row3-end]
+ / 0 0 auto 1fr;
+}
+
+#header {
+ grid-area: header;
+}
+
+#sidebar {
+ grid-area: sidebar;
+}
+
+#sidebar-resize-handle {
+ grid-area: sidebar-resize;
+}
+
+#content {
+ grid-area: content;
+}
+
+#footer {
+ grid-area: footer;
+}
+
+#menu-bar {
+ grid-area: menu-bar;
+}
+
::-webkit-scrollbar {
background: var(--bg);
}
@@ -34,44 +82,22 @@ a > .hljs {
will want to reposition the viewport in a weird way.
*/
overflow-x: clip;
+ transition: 200ms;
}
/* Menu Bar */
-#menu-bar,
-#menu-bar-hover-placeholder {
- z-index: 101;
- margin: auto calc(0px - var(--page-padding));
-}
-
#menu-bar {
position: relative;
- display: flex;
- flex-wrap: wrap;
background-color: var(--bg);
- border-block-end-color: var(--bg);
- border-block-end-width: 1px;
- border-block-end-style: solid;
-}
-
-#menu-bar.sticky,
-.js #menu-bar-hover-placeholder:hover + #menu-bar,
-.js #menu-bar:hover,
-.js.sidebar-visible #menu-bar {
- position: -webkit-sticky;
- position: sticky;
- top: 80px !important;
}
-#menu-bar-hover-placeholder {
+.menu-bar-inner {
position: sticky;
- position: -webkit-sticky;
- top: 0;
- height: var(--menu-bar-height);
-}
-
-#menu-bar.bordered {
- border-block-end-color: var(--table-border-color);
+ top: var(--header-height);
+ display: flex;
+ align-items: flex-start;
+ flex-direction: column;
}
#menu-bar i,
@@ -102,38 +128,8 @@ a > .hljs {
margin: 0;
}
-.right-buttons {
- margin: 0 15px;
-}
-
-.right-buttons a {
- text-decoration: none;
-}
-
-.left-buttons {
- display: flex;
- margin: 0 5px;
-}
-
-.no-js .left-buttons button {
- display: none;
-}
-
.menu-title {
display: none;
- font-weight: 300;
- font-size: 2.4rem;
- line-height: var(--menu-bar-height);
- text-align: center;
- margin: 0;
- flex: 1;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
-.js .menu-title {
- cursor: pointer;
}
.menu-bar,
@@ -153,6 +149,11 @@ a > .hljs {
color: var(--icons-hover);
}
+.no-js #theme-toggle,
+.no-js #search-toggle {
+ display: none;
+}
+
/* Nav Icons */
.nav-chapters {
@@ -355,6 +356,12 @@ pre > .result {
/* Search */
+#search-wrapper {
+ position: sticky;
+ top: var(--header-height);
+ background-color: var(--bg);
+}
+
#searchresults a {
text-decoration: none;
}
@@ -454,22 +461,24 @@ ul#searchresults span.teaser em {
/* Sidebar */
.sidebar {
- position: fixed;
- left: 0;
- top: 0;
- bottom: 0;
- width: var(--sidebar-width);
font-size: 0.875em;
box-sizing: border-box;
- -webkit-overflow-scrolling: touch;
- overscroll-behavior-y: contain;
background-color: var(--sidebar-bg);
color: var(--sidebar-fg);
+ position: relative;
}
-[dir="rtl"] .sidebar {
- left: unset;
- right: 0;
+.sidebar .sidebar-scrollbox {
+ position: sticky;
+ top: 80px;
+ max-height: 100vh;
+ overflow-x: hidden;
+ -webkit-overflow-scrolling: touch;
+ overscroll-behavior-y: contain;
+}
+
+.sidebar .sidebar-contents {
+ padding: 10px 20px;
}
.sidebar-resizing {
@@ -479,61 +488,25 @@ ul#searchresults span.teaser em {
user-select: none;
}
-.no-js .sidebar,
-.js:not(.sidebar-resizing) .sidebar {
- transition: transform 0.3s;
- /* Animation: slide away */
-}
-
.sidebar code {
line-height: 2em;
}
-.sidebar .sidebar-scrollbox {
- overflow-y: auto;
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
- padding: 10px 20px;
-}
-
-.sidebar .sidebar-resize-handle {
- position: absolute;
+.sidebar-resize-handle {
cursor: col-resize;
- width: 0;
- right: calc(var(--sidebar-resize-indicator-width) * -1);
- top: 0;
- bottom: 0;
display: flex;
align-items: center;
+ margin-left: var(--sidebar-resize-indicator-space);
+ width: var(--sidebar-resize-indicator-width);
}
.sidebar-resize-handle .sidebar-resize-indicator {
- width: 100%;
+ display: none;
+ position: fixed;
+ top: 50%;
+ width: var(--sidebar-resize-indicator-width);
height: 12px;
background-color: var(--icons);
- margin-inline-start: var(--sidebar-resize-indicator-space);
-}
-
-[dir="rtl"] .sidebar .sidebar-resize-handle {
- left: calc(var(--sidebar-resize-indicator-width) * -1);
- right: unset;
-}
-
-.js .sidebar .sidebar-resize-handle {
- cursor: col-resize;
- width: calc(var(--sidebar-resize-indicator-width) - var(--sidebar-resize-indicator-space));
-}
-
-/* sidebar-hidden */
-#sidebar-toggle-anchor:not(:checked) ~ .sidebar {
- transform: translateX(calc(0px - var(--sidebar-width) - var(--sidebar-resize-indicator-width)));
- z-index: -1;
-}
-[dir="rtl"] #sidebar-toggle-anchor:not(:checked) ~ .sidebar {
- transform: translateX(calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width)));
}
.sidebar::-webkit-scrollbar {
@@ -545,27 +518,28 @@ ul#searchresults span.teaser em {
}
/* sidebar-visible */
-#sidebar-toggle-anchor:checked ~ .page-wrapper {
- transform: translateX(calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width)));
-}
-[dir="rtl"] #sidebar-toggle-anchor:checked ~ .page-wrapper {
- transform: translateX(calc(0px - var(--sidebar-width) - var(--sidebar-resize-indicator-width)));
+#sidebar-toggle-anchor:checked ~ #body-container {
+ /* On Mobile, max the width of the sidebar, but always leave room for the menu button */
+ grid-template-columns: var(--sidebar-width-mobile) 0 auto minmax(300px, 1fr);
}
+/* Desktop sidebar visible */
@media only screen and (min-width: 620px) {
- #sidebar-toggle-anchor:checked ~ .page-wrapper {
- transform: none;
- margin-inline-start: calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width));
+ #sidebar-toggle-anchor:checked ~ #body-container {
+ grid-template-columns:
+ var(--sidebar-width) var(--sidebar-resize-indicator-width) auto
+ minmax(300px, 1fr);
}
- [dir="rtl"] #sidebar-toggle-anchor:checked ~ .page-wrapper {
- transform: none;
+
+ .sidebar-resize-handle .sidebar-resize-indicator {
+ display: inherit;
}
}
.chapter {
list-style: none outside none;
padding-inline-start: 0;
- line-height: 2.2em;
+ line-height: 1;
}
.chapter ol {
@@ -682,11 +656,11 @@ ul#searchresults span.teaser em {
.theme-popup {
position: absolute;
left: 10px;
- top: var(--menu-bar-height);
+ top: 0;
z-index: 1000;
border-radius: 4px;
font-size: 0.7em;
- color: var(--fg);
+ color: var(--sidebar-fg);
background: var(--theme-popup-bg);
border: 1px solid var(--theme-popup-border);
margin: 0;
@@ -757,8 +731,10 @@ ul#searchresults span.teaser em {
height: 0.1em;
width: 100%;
opacity: 0;
- transition: opacity 300ms, transform 300ms;
- content: '';
+ transition:
+ opacity 300ms,
+ transform 300ms;
+ content: "";
transform: translate3d(-100%, 0, 0);
}
diff --git a/theme/css/general.css b/theme/css/general.css
index 0e78732..e31669a 100644
--- a/theme/css/general.css
+++ b/theme/css/general.css
@@ -121,15 +121,9 @@ h6:target::before {
scroll-margin-top: calc(var(--menu-bar-height));
}
-.page {
- outline: 0;
- padding: 0 var(--page-padding);
- margin-block-start: calc(0px - var(--menu-bar-height)); /* Compensate for the #menu-bar-hover-placeholder */
-}
.page-wrapper {
box-sizing: border-box;
background-color: var(--bg);
- padding-top: 80px;
}
.page-header {
@@ -159,22 +153,6 @@ h6:target::before {
width: 236px;
}
-.sidebar{
- margin-top: 80px
-}
-
-.no-js .page-wrapper,
-.js:not(.sidebar-resizing) .page-wrapper {
- transition:
- margin-left 0.3s ease,
- transform 0.3s ease; /* Animation: slide away */
-}
-[dir="rtl"] .js:not(.sidebar-resizing) .page-wrapper {
- transition:
- margin-right 0.3s ease,
- transform 0.3s ease; /* Animation: slide away */
-}
-
.content {
overflow-y: auto;
padding: 0 15px;
@@ -203,7 +181,7 @@ h6:target::before {
}
.content a {
text-decoration: none;
- color: var(--links)
+ color: var(--links);
}
.content a:hover {
text-decoration: underline;
diff --git a/theme/css/print.css b/theme/css/print.css
index e971616..9b51bf0 100644
--- a/theme/css/print.css
+++ b/theme/css/print.css
@@ -1,3 +1,11 @@
+#body-container {
+ min-height: 100vh;
+ display: grid;
+ grid:
+ [row2-start] "content" 1fr [row2-end]
+ / auto;
+}
+
#sidebar,
#menu-bar,
.nav-chapters,
diff --git a/theme/css/variables.css b/theme/css/variables.css
index b3e31e6..e91242c 100644
--- a/theme/css/variables.css
+++ b/theme/css/variables.css
@@ -2,13 +2,15 @@
:root {
--sidebar-width: 360px;
- --sidebar-resize-indicator-width: 8px;
+ --sidebar-width-mobile: calc(100vw - 50px);
+ --sidebar-resize-indicator-width: 4px;
--sidebar-resize-indicator-space: 2px;
--page-padding: 15px;
--content-max-width: 950px;
--menu-bar-height: 50px;
--mono-font: "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace;
--code-font-size: 0.875em /* please adjust the ace font size accordingly in editor.js */;
+ --header-height: 80px;
}
/* Themes */
@@ -29,13 +31,14 @@
--icons: #f1f1f1;
--icons-hover: #4ba0a5;
- --links: var(--sidebar-active);
+ --links: var(--sidebar-fg);
+ --links-hover: var(--sidebar-active);
--inline-code-color: #c5c8c6;
--theme-popup-bg: var(--sidebar-bg);
--theme-popup-border: var(--links);
- --theme-hover: var(--links);
+ --theme-hover: var(--sidebar-active);
--quote-bg: hsl(234, 21%, 18%);
--quote-border: hsl(234, 21%, 23%);
@@ -69,7 +72,6 @@
--bg: #fff;
--fg: #000;
--headers: #19455e;
- --headers-alt: #f77c47;
--sidebar-bg: #19455e;
--sidebar-fg: #fff;
@@ -82,14 +84,14 @@
--icons: #19455e;
--icons-hover: #4ba0a5;
- --links: var(--sidebar-active);
- --links-hover: var(--headers-alt);
+ --links: var(--sidebar-fg);
+ --links-hover: var(--sidebar-active);
--inline-code-color: #301900;
--theme-popup-bg: var(--sidebar-bg);
--theme-popup-border: var(--links);
- --theme-hover: var(--links);
+ --theme-hover: var(--sidebar-active);
--quote-bg: hsl(197, 37%, 96%);
--quote-border: hsl(197, 37%, 91%);
diff --git a/theme/header.hbs b/theme/header.hbs
index 8e272d8..baeab65 100644
--- a/theme/header.hbs
+++ b/theme/header.hbs
@@ -1,16 +1,11 @@
-