~aasg/haunted-blog

d956bc0ed84b5d6ca9bec8d0a9b32fd9a35f483d — Aluísio Augusto Silva Gonçalves 1 year, 3 months ago
Commit current state of experimentation with Haunt
A  => .editorconfig +6 -0
@@ 1,6 @@
root = true

[*]
charset = utf-8
insert_final_newline = true
trim_trailing_whitespace = true

A  => .gitattributes +1 -0
@@ 1,1 @@
* text=auto

A  => .gitignore +1 -0
@@ 1,1 @@
/site/

A  => assets/icons/email.svg +1 -0
@@ 1,1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-mail" role="img"><title>Email</title><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline></svg>

A  => assets/icons/github.svg +1 -0
@@ 1,1 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>

A  => assets/icons/gitlab.svg +1 -0
@@ 1,1 @@
<svg role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>GitLab</title><path d="M4.844.904a1.007 1.007 0 00-.955.692l-2.53 7.783c0 .007-.005.012-.007.02L.07 13.335a1.437 1.437 0 00.522 1.607l11.072 8.045a.566.566 0 00.67-.004l11.074-8.04a1.436 1.436 0 00.522-1.61l-1.26-3.867a.547.547 0 00-.031-.104l-2.526-7.775a1.004 1.004 0 00-.957-.684.987.987 0 00-.949.69l-2.406 7.408H8.203l-2.41-7.408a.987.987 0 00-.943-.69h-.006zm-.006 1.42l2.174 6.678H2.674l2.164-6.678zm14.328 0l2.168 6.678h-4.342l2.174-6.678zm-10.594 7.81h6.862l-2.15 6.618L12 20.693 8.572 10.135zm-5.515.005h4.322l3.086 9.5-7.408-9.5zm13.568 0h4.326l-6.703 8.588-.709.914 2.959-9.108.127-.394zM2.1 10.762l6.978 8.947-7.818-5.682a.305.305 0 01-.112-.341l.952-2.924zm19.8 0l.952 2.922a.305.305 0 01-.11.341v.002l-7.82 5.68.025-.035 6.953-8.91Z"/></svg>

A  => assets/icons/linkedin.svg +1 -0
@@ 1,1 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>LinkedIn</title><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>

A  => assets/icons/matrix.svg +1 -0
@@ 1,1 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Matrix</title><path d="M.632.55v22.9H2.28V24H0V0h2.28v.55zm7.043 7.26v1.157h.033c.309-.443.683-.784 1.117-1.024.433-.245.936-.365 1.5-.365.54 0 1.033.107 1.481.314.448.208.785.582 1.02 1.108.254-.374.6-.706 1.034-.992.434-.287.95-.43 1.546-.43.453 0 .872.056 1.26.167.388.11.716.286.993.53.276.245.489.559.646.951.152.392.23.863.23 1.417v5.728h-2.349V11.52c0-.286-.01-.559-.032-.812a1.755 1.755 0 0 0-.18-.66 1.106 1.106 0 0 0-.438-.448c-.194-.11-.457-.166-.785-.166-.332 0-.6.064-.803.189a1.38 1.38 0 0 0-.48.499 1.946 1.946 0 0 0-.231.696 5.56 5.56 0 0 0-.06.785v4.768h-2.35v-4.8c0-.254-.004-.503-.018-.752a2.074 2.074 0 0 0-.143-.688 1.052 1.052 0 0 0-.415-.503c-.194-.125-.476-.19-.854-.19-.111 0-.259.024-.439.074-.18.051-.36.143-.53.282-.171.138-.319.337-.439.595-.12.259-.18.6-.18 1.02v4.966H5.46V7.81zm15.693 15.64V.55H21.72V0H24v24h-2.28v-.55z"/></svg>

A  => assets/icons/signature.svg +1 -0
@@ 1,1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 590 590"><title>Home</title><path d="M588.669 271.16c-59.435 20.513-110.652 7.638-112.385 5.91-77.35 114.227-313.463 181.66-304.182 117.951 22.168-39.47.91-89.46-54.996-96.93C48.693 316.374 52.59 311.716 19 318.512c-9.387 3.533-36.862-3.326-11.485-19.809 22.534-25.289 64.822-33.078 95.048-39.19 96.312-23.548 194.007-47.886 288.44-45.578l137.719-22.099 59.51-9.133z"/><path d="M368.804 208.952c-76.614 34.49-136.464 19.976-204.696 29.964-20.525 3.194-50.4 21.348-51.553-6.45L55.09 217.341c-11.989-5.87-7.277-12.935-5.116-19.817 35.067-14.369 119.823-29.707 86.39-16.414 92.559-17.57 255.32 17.923 232.44 27.842z"/><path fill="#001146" d="M152.907 190.482c-18.692-9.257 34.03 5.737 6.265 1.622l-3.192-.727zm435.103 76.58c1.2-2.973 3.805 2.92 0 0zm-483.603-43.668c-6.828-5.255 2.264 5.004 0 0zM119 180.614c4.62-4.044 5.377 3.915 0 0zm-67.674 35.864c-16.297-.854-18.627-16.94-1.352-18.954 6.82-6.088 34.38-11.053 12.652-1.53C49.33 199.05 40.81 210 55.872 217.137l-.782.204-3.763-.864zm35.777 5.256c-18.86-11.72 21.65 3.303 0 0zm15.46 37.78c9.086-4.054 22.44-10.622 5.53-6.82 5.865-10.62-17.705-29.414 4.462-20.228 2.642 26.145 34.428 5.425 51.553 6.45 37.862-7.769 75.622-16.485 114.206-20.172 30.058-4.093 60.339-6.548 90.49-9.792 6.59-9.414-32.5-10.12-43.113-13.767-20.853-8.176-42.263-6.129-63.395-12.19-41.624-5.488-84.395-9.51-125.932-1.885-22.51 1.696 11.052-14.528 20.36-9.997 37.652-4.07 74.792 5.724 112.43 5.47 37.597 4.712 74.166 15.67 110.92 24.588 17.58 9.296 36.726 6.443 55.332 2.946 31.303-2.385 62.295-8.176 93.316-12.28-21.153 5.834-44.472 9.446-66.722 12.792-23.688 3.31-46.88 9.474-70.996 9.307-62.688 6.104-125.717 10.82-187.464 23.74-34.254 3.942-66.523 17.22-100.465 22.308l-.513-.47zM281 262.644c11.37-3.036 17.906.93 1.73.594zM396.5 267c-18.972-1.56-37.96-3.31-57-3.667 33.742-2.423 67.84-1.216 101.584.86-5.823.15-26.537 1.824-37.334 2.918l-2.762.056zM0 304.83c17.21-19.08 41.715-30.724 66.236-37.22 11.116-8.183 31.687-2.06 7.764 2.026-22.66 6.653-45.555 16.042-64.008 30.753-1.56 3.131-6.695 7.087-9.992 4.44zm15.005 12.891c-1.628-9.594 29.924-5.957 40.607-11.876 16.039-2.477 42.63-9.217 52.888-4.818-27.845 7.786-56.947 10.086-85.05 16.931l-4.45.556zm469.829-46.983c-2.41-5.11-9.044 2.587 0 0zM198.5 418.637c-23.375 4.854-44.634-21.117-27-40.434 16.863-19.836 2.006-46.805-15.698-60.11-9.113-13.41-25.856-18.998-38.696-20.003 20.153-7.202-28.803-17.529-1.652-16.934 17.044 11.931 33.39 24.882 49.525 38.16 23.748 17.346 25.185 53.76 7.123 75.705-2.628 19.944 32.443 17.666 47.18 17.903 21.658-.863 42.704-6.305 64.176-9.104 25.29-3.852 45.625-20.868 69.604-28.787 38.405-16.267 73.54-42.558 98.237-76.306 6.033-12.146 5.778-18.658 12.936-30.064-12.908.292-16.603-7.446-1.525-5.289 11.626.51 50.148-1.207 46.86 4.797-16.06-.887-13.793 6.787-26.57 10.932 35.004 5.755 70.979-2.94 105.669-7.944-7.561 12.572-35.24 10.374-50.896 13.48-21.598.25-43.43 2.628-64.731 2.461-12.096 18.02-24.01 36.9-43.155 48.96-23.01 21.72-50.65 38.275-80.653 48.25-16.867 12.32-37.902 19.042-58.108 24.44-22.646 5.643-45.277 12.99-69.062 10.698-7.86-.114-15.715-.405-23.564-.81z"/></svg>

A  => haunt.scm +134 -0
@@ 1,134 @@
(use-modules (haunt asset)
             (haunt builder blog)
             (haunt builder atom)
             (haunt builder assets)
             (haunt html)
             (haunt reader commonmark)
             (haunt page)
             (haunt post)
             (haunt site)
             (ice-9 match)
             (ice-9 textual-ports)
             (srfi srfi-1)
             (srfi srfi-19)
             (sxml match)
             (sxml simple)
             (sxml transform))

(define %site-root "/")

(define (read-asset path)
  (call-with-input-file path get-string-all))

(define (h-link name uri)
  `(a (@ (href ,uri)) ,name))

(define (h-icon name)
  (let ((icon-path (string-append "assets/icons/" name ".svg")))
    `(raw ,(read-asset icon-path))))

(define (h-icon-link icon-name uri)
  `(a (@ (href ,uri)
          (class "icon"))
       ,(h-icon icon-name)))

(define (first-paragraph post)
  (let loop ((sxml (post-sxml post))
             (result '()))
    (match sxml
           (() (reverse result))
           ((or (('p ...) _ ...) (paragraph _ ...))
            (reverse (cons paragraph result)))
           ((head . tail)
            (loop tail (cons head result))))))

(define aasg-theme
  (theme #:name "aasg"
         #:layout
         (lambda (site title body)
           `((doctype "html")
             (html (@ (xmlns:svg "http://www.w3.org/2000/svg"))
               (head
                 (meta (@ (charset "utf-8")))
                 (meta (@ (name "viewport")
                          (content "width=device-width, initial-scale=1")))
                 (title ,(string-append title " — " (site-title site)))
                 (link (@ (rel "stylesheet")
                          (href "https://unpkg.com/@fraction/base16-css@1.1.0/src/base16-default-dark.css")))
                 (link (@ (rel "stylesheet")
                          (href ,(string-append %site-root "css/a11y.css"))))
                 (link (@ (rel "stylesheet")
                          (href ,(string-append %site-root "css/classless.css"))))
                 (link (@ (rel "stylesheet")
                          (href ,(string-append %site-root "css/site.css")))))
               (body
                     (header
                       (nav (@ (class "links"))
                            (ul
                              (li ,(h-icon-link "signature" "/"))
                              (li ,(h-icon-link "email" "mailto:aluisio@aasg.name"))
                              (li ,(h-icon-link "matrix" "https://matrix.to/#/@aasg:aasg.name"))
                              (li ,(h-icon-link "github" "https://github.com/AluisioASG"))
                              (li ,(h-icon-link "gitlab" "https://gitlab.com/AluisioASG"))
                              (li ,(h-icon-link "linkedin" "https://www.linkedin.com/in/aasg/")))))
                     ,body
                     (footer (p 
                               (a (@ (rel "license")
                                     (href "https://creativecommons.org/licenses/by-sa/4.0/")
                                     (title "CC-BY-SA 4.0"))
                                  "🅭🅯🄎")
                               " Aluísio Augusto Silva Gonçalves. "
                               ,(about-site-page-link "About this site.")))))))
         #:post-template
         (lambda (post)
           `((time ,(date->string (post-date post) "~1"))
             (h1 (@ (class "title"))
                 ,(post-ref post 'title))
             (div (@ (class "post"))
                  ,(post-sxml post))))
         #:collection-template
         (lambda (site title posts prefix)
           (define (post-uri post)
             (string-append %site-root (or prefix "")
                            (site-post-slug site post) ".html"))
           `((h1, "Hi!")
             (h1 ,title)
             ,(map (lambda (post)
                     `(article
                        (h2 ,(h-link (post-ref post 'title) (post-uri post)))
                        (time ,(date->string (post-date post) "~1"))
                        ,(first-paragraph post)
                        ,(h-link "continue…" (post-uri post))))
                   posts)))))

(define (static-page file-name title body)
  (lambda (site posts)
    (make-page file-name
               (with-layout aasg-theme site title body)
               sxml->html)))

(define (about-site-page-link text)
  (h-link text (string-append %site-root "about-site.html")))
(define about-site-page
  (static-page
    "about-site.html"
    "About this site"
    `((h1 "About this site")
      (section (@ (id "license"))
               (h2 "License")
               (p "The text and images in this website are, unless indicated otherwise, licensed under the "
                  ,(h-link "Creative Commons Attribution-ShareAlike 4.0 International" "https://creativecommons.org/licenses/by-sa/4.0/")
                  ".")
               (p "Unless otherwise indicated, specifically for code snippets in this website that are not part of another body of work, all copyright and related or neighbouring rights are waived, as specified by the "
                  ,(h-link "CC0 1.0 Universal Public Domain Dedication" "https://creativecommons.org/publicdomain/zero/1.0/")
                  ".")))))

(site #:title "aasg's haunting test website"
      #:domain "aasg.name"
      #:default-metadata
      '((author . "Aluísio Augusto Silva Gonçalves"))
      #:readers (list commonmark-reader)
      #:builders (list (blog #:theme aasg-theme)
                       (atom-feed)
                       about-site-page
                       (static-directory "static/css" "css")))

A  => posts/hello.md +7 -0
@@ 1,7 @@
title: First post!
date: 2018-03-13 18:00
tags: hello
summary: hello!
---

Hello, world!

A  => static/css/a11y.css +58 -0
@@ 1,58 @@
/*
Copyright (c) 2019 Mike Engel <mike@mike-engel.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

*:focus:not(:focus-visible),
*::before:focus:not(:focus-visible),
*::after:focus:not(:focus-visible) {
  outline: none;
}

/* https://medium.com/@matuzo/writing-css-with-accessibility-in-mind-8514a0007939 */
.visually-hidden {
  position: absolute;
  white-space: nowrap;
  width: 1px;
  height: 1px;
  overflow: hidden;
  border: 0;
  padding: 0;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  margin: -1px;
}

/* https://www.scottohara.me/blog/2019/01/12/lists-and-safari.html */
.plain-list {
  list-style: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'/%3E");
  padding-left: 0;
}

/* prettier-ignore */
@media(prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition: none !important;
    animation: none !important;
    scroll-behavior: auto !important;
  }
}

A  => static/css/classless.css +686 -0
@@ 1,686 @@
/* Classless.css v0.9

Copyright (c) 2020 Emanuel Regnath

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

---

Modified by Aluísio Augusto Silva Gonçalves to use CSS variables for colors.

---

Table of Contents:
 0. Variables
 1. Base Tags
 2. Extra Tags
 3. Classes 
*/

/* 0. Variables
–––––––––––––––––––––––––––––––––––––––––––– */

:root {
  --text-primary: #424456;
  --text-secondary: #777;
  --text-actionable: #0065bd;
  --text-active: #00c5bd;
  --background: #fff;
  --background-highlighted: #f4f5f6;
  --border: #d1d1d1;
  --border-active: #3273dc;
  --mark: #007c30;
}

/* 1. Base Tags 
–––––––––––––––––––––––––––––––––––––––––––– */

/* Reset: basic margins for block elements  */
* {
  box-sizing: border-box;
  border-spacing: 0;
}
header,
footer,
figure,
table,
video,
blockquote,
ul,
ol,
dl,
fieldset,
pre,
pre > code {
  display: block;
  margin: 0.5rem 0rem 1rem;
  width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
}
body {
  margin: auto;
  max-width: 50rem;
  padding: 2rem 0.5rem 0rem;
  overflow-x: hidden;
  background-color: var(--background);
}
footer {
  margin: 10rem 0rem 0rem;
}

/* text */
:root {
  font: 13pt "Open Sans", sans-serif;
  line-height: 1.5;
  color: var(--text-primary);
}
small,
sub,
sup {
  font-size: 75%;
}

/* headings */
h1,
h2,
h3,
h4,
h5,
h6 {
  margin: 1.5em 0 0em;
  padding: 0.3em 0;
}
h1 {
  font-size: 2.5em;
  font-weight: 300;
}
h2 {
  font-size: 2em;
  font-weight: 300;
}
h3 {
  font-size: 1.5em;
  font-weight: 400;
}
h4 {
  font-size: 1.1em;
  font-weight: 700;
  margin: 0.5em 0 0em;
}
h5 {
  font-size: 1.2em;
  font-weight: 400;
  margin-top: 0.5em;
  color: var(--text-secondary);
}
h6 {
  font-size: 1em;
  font-weight: 700;
}
p strong {
  color: var(--text-primary);
  font-weight: bold;
  font-size: 1em;
}

/* lists */
li,
dd {
  margin-bottom: 0.5rem;
}
dt {
  font-weight: bold;
}

/* tables */
td,
th {
  padding: 0.5rem 1.5rem;
  text-align: right;
  border-bottom: 0.1rem solid var(--border);
  white-space: nowrap;
}
td:first-child,
th:first-child {
  padding-left: 0;
  text-align: left;
}
td:last-child,
th:last-child {
  padding-right: 0;
}
tr:hover {
  background-color: var(--background-highlighted);
}

/* figures */
img {
  max-width: 100%;
}
figure {
  text-align: center;
}
figure > img {
  display: block;
  margin: 0.5em auto;
}
figcaption,
caption {
  color: var(--text-secondary);
  margin-bottom: 1rem;
}

/*code*/
pre > code {
  margin: 0;
  padding: 0.5rem 1rem;
  border-left: 0.3rem solid var(--border-active);
  background-color: var(--background-highlighted);
}
code,
kbd,
samp {
  padding: 0.3em;
  background: var(--background-highlighted);
  white-space: pre;
  font-size: 90%;
}

/* links */
a {
  color: var(--text-actionable);
  text-decoration: none;
  cursor: pointer;
}
a:hover,
button:not([disabled]):hover {
  color: var(--text-active);
  border-color: var(--text-active);
}

/* forms and inputs */
textarea,
input,
button,
select {
  border-radius: 0.3rem;
  border: 0.1rem solid var(--border);
  padding: 0.3rem;
  outline: none;
}
button {
  padding: 0.7rem 1rem;
  cursor: pointer;
  font-weight: bold;
  letter-spacing: 0.1rem;
  color: var(--text-actionable);
  background-color: var(--background-highlighted);
  border: 0.1rem solid var(--text-actionable);
}

/* misc */
blockquote {
  border-left: 0.3rem solid var(--border);
  padding: 1rem 1.5rem;
}
hr {
  border: 0;
  border-top: 0.1rem solid var(--border);
}

/* 2. Extra Tags 
–––––––––––––––––––––––––––––––––––––––––––––––––––––– */

/* Extra: non-clashing headings */
h1 + h2,
h2 + h3,
h3 + h4,
h4 + h5,
h5 + h6 {
  margin-top: 0.5em;
  padding-top: 0;
}

/* Extra: side menu */
main aside {
  position: absolute;
  margin-left: 50.5rem;
  max-width: 10rem;
  font-size: smaller;
}
@media (max-width: 73rem) {
  main aside {
    position: relative;
    margin: 1rem 0;
  }
}

/* Extra: navbar  */
body nav {
  width: 100%;
  min-height: 3rem;
  background-color: var(--background-highlighted);
  border-bottom: solid 0.1rem var(--border);
}
body > nav {
  position: fixed;
  top: 0;
  left: 0;
}
nav ul:first-child {
  list-style-type: none;
  margin: auto;
  max-width: 50rem;
  padding: 0 0.5rem;
  overflow: visible;
}
nav ul:first-child > li {
  margin: 0;
  padding: 0.8rem 1rem;
  position: relative;
  float: left;
}
nav ul:first-child > li:first-child {
  padding-left: 0;
}
nav ul > li > ul {
  display: none;
  width: auto;
  position: absolute;
  padding: 1rem 2.5rem 0rem;
  background-color: var(--background-highlighted);
  z-index: 2;
}
nav ul > li > ul > li {
  white-space: nowrap;
}
nav ul > li:hover > ul {
  display: block;
}
nav + main,
nav + header {
  margin-top: 3rem;
}

/* Extra: forms and inputs advanced styling */
fieldset {
  border-radius: 0rem;
  border: 0.1rem solid var(--border);
}
textarea:focus,
input:not([type="checkbox"]):not([type="radio"]):hover,
select:hover {
  border: 0.1rem solid var(--text-active);
}
textarea:focus,
input:not([type="checkbox"]):not([type="radio"]):focus {
  border: 0.1rem solid var(--border-active);
  box-shadow: 0 0 5px var(--border-active);
}
button[disabled] {
  color: var(--text-secondary);
  border-color: var(--border);
}

/* misc */
q:before {
  content: "\201C";
}
q q:before {
  content: "\2018";
}
q:after {
  content: "\201D";
}
q q:after {
  content: "\2019";
}
summary {
  font-weight: bold;
  cursor: pointer;
  margin: 0.5rem 0;
}
time {
  color: var(--text-secondary);
}
mark {
  background-color: transparent;
  color: var(--mark);
  text-decoration: underline solid var(--mark);
}

/* 3. Bootstrap Compatibile Classes
–––––––––––––––––––––––––––––––––––––––––––––––––––––– */

/* grid */
.row {
  display: flex;
  margin: 0 -0.5rem;
  align-items: stretch;
}
.row [class*="col"] {
  padding: 0 0.5rem;
}
.row .col {
  flex: 1 1 100%;
}
.row .col-2 {
  flex: 0 0 16.66%;
}
.row .col-3 {
  flex: 0 0 25%;
}
.row .col-4 {
  flex: 0 0 33.33%;
}
.row .col-6 {
  flex: 0 0 50%;
}

/* cards */
.card {
  display: block;
  margin: 0.5rem 0;
  padding: 0.5rem 1rem 0.5rem;
  border-radius: 0.3rem;
  box-shadow: 0.1rem 0.1rem 0.4rem 0 var(--text-secondary);
}

/* align */
.align-top {
  vertical-align: top;
}
.align-middle {
  vertical-align: middle;
}
.align-bottom {
  vertical-align: bottom;
}
.align-baseline {
  vertical-align: baseline;
}

.text-left {
  text-align: left;
}
.text-right {
  text-align: right;
}
.text-center {
  text-align: center;
}

.float-left {
  float: left !important;
}
.float-right {
  float: right !important;
}
.clearfix {
  display: flow-root;
}

/* colors */
.text-black {
  color: #000;
}
.text-white {
  color: #fff;
}
.text-primary {
  color: var(--text-actionable);
}
.text-secondary {
  color: #333;
}

.bg-white {
  background-color: #fff;
}
.bg-light {
  background-color: var(--background-highlighted);
}
.bg-primary {
  background-color: var(--text-actionable);
}
.bg-secondary {
  background-color: var(--border);
}

/* spacing */
.w-25 {
  width: 25% !important;
}
.w-33 {
  width: 33.33% !important;
}
.w-50 {
  width: 50% !important;
}
.w-75 {
  width: 75% !important;
}
.w-100 {
  width: 100% !important;
}

/* margins */
.mx-auto {
  margin-left: auto;
  margin-right: auto;
}

.m-0,
.mx-0,
.mr-0 {
  margin-right: 0rem !important;
}
.m-0,
.mx-0,
.ml-0 {
  margin-left: 0rem !important;
}
.m-0,
.my-0,
.mt-0 {
  margin-top: 0rem !important;
}
.m-0,
.my-0,
.mb-0 {
  margin-bottom: 0rem !important;
}

.m-05,
.mx-05,
.mr-05 {
  margin-right: 0.5rem !important;
}
.m-05,
.mx-05,
.ml-05 {
  margin-left: 0.5rem !important;
}
.m-05,
.my-05,
.mt-05 {
  margin-top: 0.5rem !important;
}
.m-05,
.my-05,
.mb-05 {
  margin-bottom: 0.5rem !important;
}

.m-1,
.mx-1,
.mr-1 {
  margin-right: 1rem !important;
}
.m-1,
.mx-1,
.ml-1 {
  margin-left: 1rem !important;
}
.m-1,
.my-1,
.mt-1 {
  margin-top: 1rem !important;
}
.m-1,
.my-1,
.mb-1 {
  margin-bottom: 1rem !important;
}

.m-2,
.mx-2,
.mr-2 {
  margin-right: 2rem !important;
}
.m-2,
.mx-2,
.ml-2 {
  margin-left: 2rem !important;
}
.m-2,
.my-2,
.mt-2 {
  margin-top: 2rem !important;
}
.m-2,
.my-2,
.mb-2 {
  margin-bottom: 2rem !important;
}

/* pading */
.p-0,
.px-0,
.pr-0 {
  padding-right: 0rem !important;
}
.p-0,
.px-0,
.pl-0 {
  padding-left: 0rem !important;
}
.p-0,
.py-0,
.pt-0 {
  padding-top: 0rem !important;
}
.p-0,
.py-0,
.pb-0 {
  padding-bottom: 0rem !important;
}

.p-05,
.px-05,
.pr-05 {
  padding-right: 0.5rem !important;
}
.p-05,
.px-05,
.pl-05 {
  padding-left: 0.5rem !important;
}
.p-05,
.py-05,
.pt-05 {
  padding-top: 0.5rem !important;
}
.p-05,
.py-05,
.pb-05 {
  padding-bottom: 0.5rem !important;
}

.p-1,
.px-1,
.pr-1 {
  padding-right: 1rem !important;
}
.p-1,
.px-1,
.pl-1 {
  padding-left: 1rem !important;
}
.p-1,
.py-1,
.pt-1 {
  padding-top: 1rem !important;
}
.p-1,
.py-1,
.pb-1 {
  padding-bottom: 1rem !important;
}

.p-2,
.px-2,
.pr-2 {
  padding-right: 2rem !important;
}
.p-2,
.px-2,
.pl-2 {
  padding-left: 2rem !important;
}
.p-2,
.py-2,
.pt-2 {
  padding-top: 2rem !important;
}
.p-2,
.py-2,
.pb-2 {
  padding-bottom: 2rem !important;
}

/* responsive, smaller than */
@media (max-width: 40em) {
  .row {
    flex-direction: column !important;
  }
  nav ul:first-child > li:first-child:after {
    content: "\25BE";
    padding-left: 0.5rem;
  }
  nav ul:first-child > li:not(:first-child) {
    display: none;
  }
  nav ul:first-child:hover > li {
    display: block;
    float: none !important;
  }
}
@media (min-width: 40em) {
  [class*="col"] > * {
    margin-top: 1rem !important;
  }
}
@media (max-width: 61rem) {
  aside {
    position: relative;
    margin: 0.5rem 0;
  }
}

A  => static/css/site.css +50 -0
@@ 1,50 @@
:root {
  --text-primary: var(--base05);
  --text-secondary: var(--base04);
  --text-actionable: var(--base0D);
  --text-active: var(--base0C);
  --background: var(--base00);
  --background-highlighted: --var(--base01);
  --border: var(--base02);
  --border-active: var(--base03);
  --mark: var(--base0B);
}

/*
@media (prefers-color-scheme: dark) {
  :root {
    --text-primary: #424456;
    --text-secondary: #777;
    --text-actionable: #0065bd;
    --text-active: #00c5bd;
    --background: #fff;
    --background-highlighted: #f4f5f6;
    --border: #d1d1d1;
    --border-active: #3273dc;
    --mark: #007c30;
  }
}
*/

footer {
  border-top: 0.1rem solid var(--border);
}

footer p {
  margin-top: 0.3rem;
}

.icon svg {
  width: 24px;
  height: 24px;
  stroke: var(--text-secondary);
}

.icon svg:not(.feather) {
  fill: var(--text-secondary);
}

/* Align nav bar dropdown with icons. */
nav.links ul:first-child > li:first-child::after {
  vertical-align: top;
}