commit 865e0761a7d3d115d301428154875d7a6e1a976b
parent e90d2e4e519da21046cdaca6f2de673f18a89675
Author: Armaan Bhojwani <me@armaanb.net>
Date: Sun, 15 May 2022 14:00:27 -0400
Switch to suckless ssg
Diffstat:
10 files changed, 976 insertions(+), 37 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,7 @@
+# these files are ignored by git.
+*.html
+!/*.html
+*.gph
+!/*.gph
+build-page
+test
diff --git a/.gitmodules b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "smu"]
+ path = smu
+ url = https://github.com/Gottox/smu
diff --git a/CNAME b/CNAME
@@ -1 +0,0 @@
-kisscommunity.org
-\ No newline at end of file
diff --git a/Makefile b/Makefile
@@ -0,0 +1,13 @@
+CFLAGS = -Wall -Wextra -std=c99 -pedantic
+LDFLAGS = -static -s
+
+all: html
+
+html: build-page
+ find wiki -type d -exec sh -ec './build-page "$$0" >$$0/index.html' {} \;
+
+build-page: build-page.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ build-page.c
+
+clean:
+ rm -f build-page
diff --git a/build-page.c b/build-page.c
@@ -0,0 +1,309 @@
+#define _POSIX_C_SOURCE 200809L
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <dirent.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define CONVERTER "smu", "-n"
+#define LEN(x) (sizeof(x) / sizeof(x[0]))
+
+char *html_header =
+ "<!doctype html>\n"
+ "<html>\n"
+ "<head>\n"
+ "\t<meta charset=\"utf-8\"/>\n"
+ "\t<title>KISS Community Wiki</title>\n"
+ "\t<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\"/>\n"
+ "</head>\n";
+
+char *html_nav_bar = "\t<span class=\"right\">\n"
+ "\t\t<a href=\"https://github.com/kiss-community\">Github</a>\n"
+ "\t\t<a href=\"https://kisslinux.org\">Official site</a>\n"
+ "\t</span>\n";
+
+char *html_footer = "</html>\n";
+
+void die_perror(char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fputs(": ", stderr);
+ perror(NULL);
+ exit(1);
+}
+
+void die(char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+ exit(1);
+}
+
+char *xstrdup(const char *s) {
+ char *p = strdup(s);
+
+ if (!p)
+ die_perror("strdup");
+
+ return p;
+}
+
+int stat_isdir(const char *f) {
+ struct stat s;
+
+ if (stat(f, &s) == -1) {
+ perror(f);
+ return 0;
+ }
+ return S_ISDIR(s.st_mode);
+}
+
+int stat_isfile(const char *f) {
+ struct stat s;
+
+ if (stat(f, &s) == -1) {
+ return 0;
+ }
+ return S_ISREG(s.st_mode);
+}
+
+int spawn_wait(char **argv) {
+ int status;
+
+ switch (fork()) {
+ case 0:
+ execvp(argv[0], argv);
+ exit(126);
+ case -1:
+ return -1;
+ }
+ if (wait(&status) == -1)
+ return -1;
+
+ return WIFEXITED(status) ? 0 : -1;
+}
+
+void print_name(const char *name) {
+ int c;
+
+ for (; (c = *name); ++name)
+ putchar((c == '_' || c == '-') ? ' ' : c);
+}
+
+void print_nav_bar(char *domain) {
+ struct domain *d;
+
+ puts("<div id=\"menu\">");
+ puts("\t<a href=\"/\"><b>KISS Community Wiki</b></a>\n");
+
+ fputs(html_nav_bar, stdout);
+ puts("</div>");
+}
+
+int qsort_strcmp(const void *a, const void *b) {
+ return strcmp(*(const char **)a, *(const char **)b);
+}
+
+int has_subdirs(char *this) {
+ DIR *dp;
+ struct dirent *de;
+ char newdir[PATH_MAX];
+ int dir;
+
+ if ((dp = opendir(this ? this : ".")) == NULL)
+ die_perror("opendir: %s", this ? this : ".");
+
+ dir = 0;
+ while (dir == 0 && (de = readdir(dp))) {
+ if (de->d_name[0] == '.')
+ continue;
+ snprintf(newdir, sizeof(newdir), this ? "%2$s/%1$s" : "%s", de->d_name,
+ this);
+ if (stat_isdir(newdir))
+ dir = 1;
+ }
+ closedir(dp);
+
+ return dir;
+}
+
+void menu_panel(char *domain, char *page, char *this, int depth) {
+ DIR *dp;
+ struct dirent *de;
+ char newdir[PATH_MAX];
+ char *d_list[PATH_MAX], *d;
+ size_t d_len, l;
+ int i, highlight;
+
+ if ((dp = opendir(this ? this : ".")) == NULL)
+ die_perror("opendir: %s", this ? this : ".");
+
+ d_len = 0;
+ while (d_len < LEN(d_list) && (de = readdir(dp)))
+ d_list[d_len++] = xstrdup(de->d_name);
+ closedir(dp);
+
+ qsort(d_list, d_len, sizeof *d_list, qsort_strcmp);
+
+ for (l = 0; l < d_len; free(d_list[l++])) {
+ d = d_list[l];
+ if (*d == '.')
+ continue;
+ snprintf(newdir, sizeof(newdir), this ? "%2$s/%1$s" : "%s", d, this);
+ if (!stat_isdir(newdir))
+ continue;
+
+ highlight = page && !strncmp(newdir, page, strlen(newdir)) &&
+ strchr("/", page[strlen(newdir)]); /* / or NUL */
+
+ for (i = 0; i < depth + 1; ++i)
+ putchar('\t');
+ fputs("<li>", stdout);
+ if (highlight) {
+ printf("<a href=\"/%s/\"><b>", newdir);
+ print_name(d);
+ fputs("/</b></a>", stdout);
+ } else {
+ printf("<a href=\"/%s/\">", newdir);
+ print_name(d);
+ fputs("/</a>", stdout);
+ }
+
+ if (highlight && has_subdirs(newdir)) {
+ putchar('\n');
+ for (i = 0; i < depth + 2; ++i)
+ putchar('\t');
+ puts("<ul>");
+ menu_panel(domain, page, newdir, depth + 1);
+ for (i = 0; i < depth + 2; ++i)
+ putchar('\t');
+ puts("</ul>");
+ for (i = 0; i < depth + 1; ++i)
+ putchar('\t');
+ }
+ puts("</li>");
+ }
+}
+
+void print_menu_panel(char *domain, char *page) {
+ fputs("<div id=\"nav\">\n\t<ul>\n\t<li>", stdout);
+ if (!page)
+ puts("<a href=\"/\"><b>Home</b></a></li>");
+ else
+ puts("<a href=\"/\">Home</a></li>");
+ menu_panel(domain, page, NULL, 0);
+ puts("\t</ul>");
+ puts("</div>");
+}
+
+void print_content(char *domain, char *page) {
+ char indexmd[PATH_MAX];
+ char indextxt[PATH_MAX];
+ char *argv[] = {CONVERTER, indexmd, NULL};
+
+ snprintf(indexmd, sizeof(indexmd), page ? "%2$s/%1$s" : "%s", "index.md",
+ page);
+ snprintf(indextxt, sizeof(indextxt), page ? "%2$s/%1$s" : "%s", "index.txt",
+ page);
+
+ puts("<div id=\"main\">\n");
+ if (stat_isfile(indexmd)) {
+ fflush(stdout);
+ if (spawn_wait(argv) == -1)
+ die_perror("spawn: %s/%s/%s", domain, page, indexmd);
+ } else if (stat_isfile(indextxt)) {
+ puts("<pre>");
+ FILE *fptr = fopen(indextxt, "r");
+ char c = fgetc(fptr);
+ while (c != EOF) {
+ printf("%c", c);
+ c = fgetc(fptr);
+ }
+
+ fclose(fptr);
+ puts("</pre>");
+ }
+
+ puts("</div>\n");
+}
+
+void print_footer(void) { fputs(html_footer, stdout); }
+
+int has_index(char *this) {
+ DIR *dp;
+ struct dirent *de;
+ char newdir[PATH_MAX];
+ int index;
+
+ if ((dp = opendir(this ? this : ".")) == NULL)
+ die_perror("opendir: %s", this ? this : ".");
+
+ index = 0;
+ while (index == 0 && (de = readdir(dp))) {
+ if (de->d_name[0] == '.')
+ continue;
+ snprintf(newdir, sizeof(newdir), this ? "%2$s/%1$s" : "%s", de->d_name,
+ this);
+ if (stat_isfile(newdir) && strcmp(de->d_name, "index.md") == 0)
+ index = 1;
+ }
+ closedir(dp);
+
+ return index;
+}
+
+void usage(char *argv0) { die("usage: %s [-g] directory", argv0); }
+
+int main(int argc, char *argv[]) {
+ char *domain = NULL, *page;
+ int i, j;
+
+ for (i = 1; i < argc; i++) {
+ if (argv[i][0] != '-') {
+ if (domain)
+ usage(argv[0]);
+ domain = argv[i];
+ continue;
+ }
+ for (j = 1; j < argv[i][j]; j++) {
+ switch (argv[i][j]) {
+ default:
+ usage(argv[0]);
+ }
+ }
+ }
+ if (domain == NULL)
+ usage(argv[0]);
+
+ domain = xstrdup(domain);
+ if ((page = strchr(domain, '/'))) {
+ *page++ = '\0';
+ if (strlen(page) == 0)
+ page = NULL;
+ }
+ if (chdir(domain) == -1)
+ die_perror("chdir: %s", domain);
+
+ puts(html_header);
+ print_nav_bar(domain);
+ puts("<div id=\"content\">");
+ print_menu_panel(domain, page);
+ print_content(domain, page);
+ puts("</div>\n");
+ print_footer();
+
+ return 0;
+}
diff --git a/index.html b/index.html
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <title>KISS Community</title>
- <meta charset="utf-8">
- <meta name="description" content="KISS Linux Community">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <style>body {max-width: 1000px}</style>
-</head>
-
-<body>
-<h1>KISS Linux Community</h1>
-<blockquote>
- when dylan says "no", we say "maybe"
-</blockquote>
-<blockquote>
- <a href="https://kisslinux.org/">KISS Linux</a> is an independent Linux(R) distribution with a focus on simplicity and the concept of less is more.
-</blockquote>
-
-<h2>Connect</h2>
-<ul>
- <li>Chat over <a href="ircs://irc.libera.chat:6697/kisslinux">IRC</a></li>
- <li>Chat <a href="https://web.libera.chat/#kisslinux">on the web</a></li>
- <li>Browse <a href="https://libera.irclog.whitequark.org/kisslinux">the latest chat logs</a></li>
-</ul>
-
-<h2>Discover</h2>
-<ul>
- <li>Search through <a href="https://jedahan.com/kiss-find">all community packages</a></li>
- <li>Discover more <a href="https://github.com/kiss-community/awesome-kiss">awesome kiss projects</a></li>
- <li>Visit our <a href="https://github.com/kiss-community/">community github</a></li>
-</ul>
-
-</body>
-</html>
diff --git a/smu b/smu
@@ -0,0 +1 @@
+Subproject commit e62f23808b865f9a6919a8090e34a436b9582588
diff --git a/wiki/Style_Guide/index.txt b/wiki/Style_Guide/index.txt
@@ -0,0 +1,473 @@
+PACKAGE STYLE GUIDE
+________________________________________________________________________________
+
+This document is a style guide which will double as documentation for a possible
+package linter in the future. Every package in the Official Repositories and the
+Community repository adheres to this style guide.
+
+NOTE: Exceptions are made where it makes sense.
+
+
+MAINTAINERSHIP
+________________________________________________________________________________
+
+* Each package has a set maintainer stored via git commits. Use 'git log' or
+ 'kiss-maintainer pkg' to find the maintainer's contact information.
+
+* Only the maintainer of a package has the ability to make changes to said
+ package. Any pull requests by a non-maintainer for a package will be closed.
+
+* If you would like to make a change to an existing package, contact the
+ maintainer and they will do so on your behalf.
+
+* If the maintainer leaves a package out of date and does not respond in a
+ reasonable time frame, the package will be orphaned and up for grabs.
+
+* If no one steps forward to adopt an orphaned package, it will be dropped from
+ the repositories.
+
+
+GENERAL
+________________________________________________________________________________
+
+
+ [0000]----------------------------------------------------------------------
+
+ Package is not suitable for inclusion in the Community repository. The same
+ rules above may apply to other software at the discretion of the BDFL.
+
+ Examples: ConsoleKit, dbus, electron, gettext, gtk2, intltool, libsn,
+ logind, pam, pipewire, polkit, pulseaudio, systemd, wayland and
+ all Desktop Environments.
+
+
+ [0001]----------------------------------------------------------------------
+
+ No new packages shall use Python 2 as it will be removed once Chromium drops
+ it as a dependency.
+
+
+ [0002]----------------------------------------------------------------------
+
+ Packages which are binaries should contain the suffix '-bin' to reflect
+ this fact. Similarly, packages which pull from git should contain the
+ suffix '-git'. The version of git packages should also be set to 'git'.
+
+
+
+BUILD
+________________________________________________________________________________
+
+
+ [0200]----------------------------------------------------------------------
+
+ This guide should be used alongside shellcheck and not in place of it.
+
+
+ [0201]----------------------------------------------------------------------
+
+ All shell code must pass the shellcheck linter. Any false-positives or
+ intended behavior must have a rationale attached with the exclusion.
+
+ # Disable warning as CFLAGS must work this way.
+ # shellcheck disable=2086
+ "${CC:-cc}" $CFLAGS ...
+
+
+ [0202]----------------------------------------------------------------------
+
+ Use 4 spaces for indentation.
+
+
+ [0203]----------------------------------------------------------------------
+
+ Lines should not exceed 80 characters in length.
+
+
+ [0204]----------------------------------------------------------------------
+
+ All packages must use the POSIX shell shebang with '-e' to exit on error.
+ Additionally, '-ef' can be used if word-splitting is required.
+
+ There must also be a blank line directly below the shebang.
+
+ #!/bin/sh -e
+
+ # Code starts here.
+
+
+ [0205]----------------------------------------------------------------------
+
+ All comments must start with a capital letter and use proper spelling,
+ grammar and punctuation.
+
+ # This is a comment.
+
+
+ [0206]----------------------------------------------------------------------
+
+ Leave comments to explain *why* the code is needed and not *what* it does.
+
+ Bad:
+
+ # Create a directory.
+ mkdir -p "$1/usr/bin"
+
+ Good:
+
+ # 'make install' doesn't create the directory.
+ mkdir -p "$1/usr/bin"
+
+
+ [0207]----------------------------------------------------------------------
+
+ Avoid adding braces around variables if unneeded.
+
+ Bad: printf '%s\n' "${var}"
+ Good: printf '%s\n' "$var"
+ Good: printf '%s\n' "${var}.${var2}"
+
+
+ [0208]----------------------------------------------------------------------
+
+ Avoid quotes when unneeded.
+
+ Bad: [ "$var" = "test" ]
+ Good: [ "$var" = test ]
+
+ Bad: install -Dm755 "file" "$1/usr/bin/file"
+ Good: install -Dm755 file "$1/usr/bin/file"
+
+
+ [0209]----------------------------------------------------------------------
+
+ Quote entire strings instead of variables.
+
+ Bad: install -Dm644 cat "$1"/usr/bin/cat
+ Good: install -Dm644 cat "$1/usr/bin/cat"
+
+
+ [0210]----------------------------------------------------------------------
+
+ Align arguments in blocks of command calls.
+
+ Bad:
+
+ install -D file.h "$1/usr/include/file.h"
+ install -D libfile.so "$1/usr/lib/libfile.so"
+
+ Good:
+
+ install -D file.h "$1/usr/include/file.h"
+ install -D libfile.so "$1/usr/lib/libfile.so"
+
+
+ [0211]----------------------------------------------------------------------
+
+ Use 'install' instead of ...
+
+ Bad:
+
+ mkdir -p "$1/usr/bin"
+ cp ls "$1/usr/bin/"
+
+ Good:
+
+ install -Dm755 ls "$1/usr/bin/ls"
+
+
+ [0212]----------------------------------------------------------------------
+
+ Prefer $CC to ...
+
+ Bad: gcc -o file file.c
+ Good: "${CC:-cc}" -o file file.c
+
+
+ [0213]----------------------------------------------------------------------
+
+ Always use '-p' with 'mkdir'.
+
+
+
+GNU AUTOTOOLS
+________________________________________________________________________________
+
+
+ [0400]----------------------------------------------------------------------
+
+ Use the following style:
+
+ ./configure \
+ --prefix=/usr \
+ --more_args_here
+
+ make
+ make DESTDIR="$1" install
+
+
+ [0401]----------------------------------------------------------------------
+
+ Avoid running ./autogen.sh, autoreconf or similar tools prior to starting
+ the build process. If there are no pre-generated configure or Makefiles, an
+ alternate source must be sought.
+
+ An exception can be made for packages in which no such source exists. If
+ autogen.sh or autoreconf are required, prefer autoreconf.
+
+
+
+MESON
+________________________________________________________________________________
+
+
+ [0600]----------------------------------------------------------------------
+
+ Use the following style:
+
+ export DESTDIR="$1"
+
+ meson \
+ --prefix=/usr \
+ -Dexample=false \
+ . output
+
+ ninja -C output
+ ninja -C output install
+
+
+
+CMAKE
+________________________________________________________________________________
+
+
+ [0800]----------------------------------------------------------------------
+
+ Use the following style:
+
+ export DESTDIR="$1"
+
+ cmake -B build \
+ -DCMAKE_INSTALL_PREFIX=/usr \
+ -DFLAG=1
+
+ cmake --build build
+ cmake --install build
+
+
+
+MAKE
+________________________________________________________________________________
+
+
+ [1000]----------------------------------------------------------------------
+
+ Use one of the following style when applicable:
+
+ make
+ make DESTDIR="$1" PREFIX=/usr install
+
+
+ make PREFIX=/usr
+ make DESTDIR="$1" install
+
+
+ make PREFIX=/usr
+ make DESTDIR="$1" PREFIX=/usr install
+
+
+ For packages which require a few variables be set, prefer this style.
+
+ make \
+ PREFIX=/usr \
+ SBINDIR=/usr/bin \
+ OPT="$CFLAGS"
+
+ make \
+ DESTDIR="$1" \
+ PREFIX=/usr \
+ install
+
+
+ For packages which require the variables be set for all calls to make,
+ prefer this style.
+
+ mk() {
+ make \
+ PREFIX=/usr \
+ DESTDIR="$1" \
+ EXAMPLE=1 \
+ "$@"
+ }
+
+ mk
+ mk install
+
+
+
+RUST
+________________________________________________________________________________
+
+
+ [1050]----------------------------------------------------------------------
+
+ Use the following style:
+
+ cargo build --release
+
+ install -Dm755 target/release/rg "$1/usr/bin/rg"
+
+
+
+GO
+________________________________________________________________________________
+
+
+ [1100]----------------------------------------------------------------------
+
+ Use the following style:
+
+ export GOPATH="$PWD/go"
+ export GO111MODULE=on
+
+ go build \
+ -modcacherw \
+ -trimpath
+
+ install -Dm755 lazygit "$1/usr/bin/lazygit"
+
+ Note: If the directory 'vendor' is available in the root directory of the
+ source, the preffered method is to omit GOPATH and GO111MODULE and use:
+
+ go build \
+ -mod=vendor \
+ -further-options
+
+ to prevent cluttering $HOME and enable offline building.
+
+PYTHON
+________________________________________________________________________________
+
+
+ [1150]----------------------------------------------------------------------
+
+ Use the following style:
+
+ python setup.py build
+ python setup.py install --prefix=/usr --root="$1"
+
+
+
+DEPENDS
+________________________________________________________________________________
+
+
+ [1201]----------------------------------------------------------------------
+
+ This dependency is unneeded and can be removed.
+
+
+ [1202]----------------------------------------------------------------------
+
+ This dependency is implicit. Some packages are assumed to always be
+ available. This dependency can be removed.
+
+ Examples: gcc, make, musl.
+
+
+ [1203]----------------------------------------------------------------------
+
+ This dependency needs 'make' as it is only required during build time.
+
+ Common Examples: autoconf, automake, cmake, meson.
+
+
+ [1204]----------------------------------------------------------------------
+
+ This dependency doesn't need 'make' as it is required during runtime.
+
+
+ [1205]----------------------------------------------------------------------
+
+ The depends list must be sorted.
+
+
+ [1206]----------------------------------------------------------------------
+
+ The depends file is empty and should be removed.
+
+
+
+SOURCES
+________________________________________________________________________________
+
+
+ [1401]----------------------------------------------------------------------
+
+ Use a HTTPS source if at all possible.
+
+
+ [1402]----------------------------------------------------------------------
+
+ Don't specify patches remotely. Store them as a part of the package's
+ repository files.
+
+ Bad: https://example.com/fix-build.patch
+ Good: patches/fix-build.patch
+
+
+ [1403]----------------------------------------------------------------------
+
+ Don't use a git repository in place of a release tarball unless it makes
+ sense to do so.
+
+
+ [1404]----------------------------------------------------------------------
+
+ Drop www. and .git from all sources if possible.
+
+
+
+VERSION
+________________________________________________________________________________
+
+
+ [1601]----------------------------------------------------------------------
+
+ Version doesn't match upstream.
+
+
+ [1602]----------------------------------------------------------------------
+
+ Use 'git' in place of '9999'.
+
+
+ [1603]----------------------------------------------------------------------
+
+ Missing relative version number.
+
+ Bad: 1.0.0
+ Good: 1.0.0 1
+
+
+
+PATCHES
+________________________________________________________________________________
+
+
+ [1800]----------------------------------------------------------------------
+
+ Use the following style:
+
+ patch -p1 < patch.patch
+
+ # If there is more than one patch.
+ for patch in *.patch; do
+ patch -p1 < "$patch"
+ done
+
+
+ [1801]----------------------------------------------------------------------
+
+ All patches should use the same strip amount. If this is not possible,
+ modify the patches. Strip amount is controlled by the -p flag.
diff --git a/wiki/index.md b/wiki/index.md
@@ -0,0 +1,11 @@
+# KISS Linux Community
+
+> when dylan says "no", we say "maybe"
+
+> [KISS Linux](https://kisslinux.org/) is an independent Linux(R) distribution with a focus on simplicity and the concept of less is more.
+
+We're on irc at #kisslinux on [libera.chat](irc://irc.libera.chat) [(logs are available here)](https://libera.irclog.whitequark.org/kisslinux).
+
+Development occurs on [Github/kiss-community](https://github.com/kiss-community/)
+
+[Community package listing](https://jedahan.com/kiss-find)
diff --git a/wiki/style.css b/wiki/style.css
@@ -0,0 +1,159 @@
+body {
+ font-family: sans-serif;
+ padding: 0;
+ margin: 0;
+}
+
+pre, code {
+ margin: 0;
+}
+
+a {
+ color: #005386;
+}
+
+#header a, #nav a, #menu a {
+ text-decoration: none;
+}
+
+#nav a:hover {
+ background-color: #ddd;
+}
+
+#menu {
+ clear: both;
+ color: #069;
+ overflow: hidden;
+ background-color: #17a;
+ padding: 0.7ex;
+ border-top: 1px solid #ccc;
+ border-bottom: 1px solid #069;
+}
+
+#menu a {
+ padding: 0.5ex 1ex;
+ color: #fff;
+}
+
+#menu a:hover {
+ background-color: #069;
+}
+
+#header {
+ background-color: #eee;
+ clear: both;
+ color: #555;
+ font-size: 1.78em;
+ padding: 0.7ex 0.7ex 0.7ex 0.7em;
+}
+
+#headerLink {
+ color: #17a;
+ margin-left: 5px;
+}
+
+h1 {
+ margin: 1em 1ex 0.5ex 0;
+ font-size: 1.4em;
+}
+
+h2 {
+ margin: 1em 1ex 0.5ex 0;
+ font-size: 1.3em;
+}
+
+h3 {
+ margin: 1em 1ex 0.5ex 0;
+ font-size: 1.0em;
+}
+
+h4 {
+ margin: 1em 1ex 0.5ex 0;
+ font-size: 0.9em;
+}
+
+#headerSubtitle {
+ font-size: 0.75em;
+ font-style: italic;
+ margin-left: 1em;
+}
+
+#content {
+ clear: both;
+ margin: 0;
+ padding: 0;
+}
+
+#nav {
+ float: left;
+ margin: 0 1px 0 0;
+ padding: 1em 0;
+ border-right: 1px dotted #ccc;
+ width: 200px;
+}
+
+#nav ul {
+ margin: 0;
+ padding: 0;
+}
+
+#nav li {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+#nav li ul {
+ padding-left: 0.6em !important;
+}
+
+#nav li a {
+ display: block;
+ margin: 0;
+ padding: 0.8ex 2em 0.8ex 1em;
+}
+
+#main {
+ margin: 0 0 0 200px;
+ max-width: 50em;
+ padding: 1.5em;
+}
+
+.left {
+ float: left;
+ margin: 0;
+ padding: 0;
+}
+
+.right {
+ float: right;
+ margin: 0;
+ padding: 0;
+}
+
+
+@media (prefers-color-scheme: dark) {
+ body {
+ background-color: #000;
+ color: #bdbdbd;
+ }
+ #menu {
+ border-top: 1px solid #222;
+ }
+ #header {
+ background-color: #111;
+ }
+ #nav a:hover {
+ background-color: #222;
+ }
+ blockquote, pre, code {
+ background-color: #111;
+ border-color: #222;
+ }
+ a {
+ color: #56c8ff;
+ }
+ #main img[src$=svg] {
+ filter: invert(1);
+ }
+}