--- /dev/null
+#!/bin/sh
+# SPDX-FileCopyrightText: 2025 Lady <https://www.ladys.computer/about/#lady>
+# SPDX-License-Identifier: MPL-2.0
+
+SHELL = /bin/sh
+
+# This Source Code Form is subject to the terms of the Mozilla Public License, v 2.0.
+# If a copy of the M·P·L was not distributed with this file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
+
+# This make·file should be run from the root of the source directory.
+
+CAT := cat
+GIT := git
+MKDIR := mkdir
+PRINTF := printf
+SED := gsed
+TEST := test
+XARGS := xargs
+XSLTPROC := xsltproc
+
+LESML := LesML
+
+DOCDIR := doc
+
+PROJECT_NAME := C·Girls
+
+HEADER_FILES = $(sort $(patsubst ./%,%,$(shell find . '(' -path '.' -o -prune ')' -a -type f -a -name '*.h')))
+DOCUMENTATION_FILES = $(patsubst %.h,$(DOCDIR)/%.xhtml,$(HEADER_FILES))
+
+documentation : $(DOCDIR)/README.xhtml $(DOCUMENTATION_FILES) $(DOCDIR)/index.xhtml ;
+
+# (callable) Strip portions between `(*´ and `*)´ and collapse newlines in the argument.
+# Backslash sequences in the argument are handled ⅌ `printf´.
+# Single quotes must not appear in the argument or this will break.
+makeunreadable = $(shell LANG=C LC_ALL=C printf '%s\n' '$(subst $(newline),$(space),$1)' | $(SED) 's/^ *//;s/ *$$//;s/ *([*][^*]*[*]) *//g' | $(XARGS) -0 $(PRINTF) '%b\n')
+
+define readablesedcmd
+\\@^/[*]$$@,\\@^[\t]*[*]/$$@d; (*delete multiline comments*)
+\\@^/[*][^*]*.?[^/]*[*]/$$@d; (*delete singleline traditional comments*)
+\\@^//@d; (*delete singleline newstyle comments*)
+\\@^/[*][*]$$@s@^.*$$@@; (*delete start of documentation comments (leaving newline)*)
+\\@^ [*][*]//*$$@s@^.*$$@@; (*delete end of documentation comments (leaving newline)*)
+\\@^ [*][*]$$@s@$$@ @; (*add trailing space to empty documentation comment lines*)
+\\@^ [*][*] @!{\\@.@s@^@\t|`@;\\@.@s@$$@´@;}; (*format non·empty lines of code*)
+\\@^ [*][*] @{s@^ [*][*] [ \t]*@@;s@ :—@ :—@g;s@« @« @g;s@‹ @‹ @g;s@—: @—: @g;s@ »@ »@g;s@ ›@ ›@g;s@{<\\([^>]*\\)[.]h>}@{🔗`\\1`<./\\1>}@;}; (*drop prefix from documentation lines and format*)
+endef
+sedcmd := $(call makeunreadable,$(readablesedcmd))
+
+define readablestylesheet
+@charset "UTF-8";
+article{ Margin: Auto; Width: Min-Content; Max-Width: 100% }
+article::after{ Display: Block; Width: 31REM; Max-Width: 100%; Min-Width: 100%; Content: "" }
+blockquote>pre{ Margin: Auto; Width: 71CH; Max-Width: 100%; White-Space: Pre-Wrap }
+blockquote>pre+pre{ Margin-Top: 1LH }
+endef
+stylesheet := $(call makeunreadable,$(readablestylesheet))
+
+# The first argument should be shell commands producing Les·M·L; the second should be the title of the page.
+processlesml = { $(PRINTF) '%s\n' '<?xml version="1.0"?>' '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>$2</title><style>$(stylesheet)</style></head><body>'; { $(PRINTF) '%s\n%s' '<?xml version="1.0"?>' '<script xmlns="http://www.w3.org/1999/xhtml" type="text/lesml"><![CDATA['; $1; $(PRINTF) '\n%s\n' ']]></script>'; } | xsltproc $(LESML)/parser.xslt - | $(SED) '1{/^<?xml/d;}'; $(PRINTF) '%s\n' '</body></html>' ; }
+
+$(DOCUMENTATION_FILES) : $(DOCDIR)/%.xhtml : %.h $(LESML)/parser.xslt
+ @if $(TEST) '!' -d $(DOCDIR); then $(MKDIR) -p $(DOCDIR); fi
+ @$(PRINTF) '%s\n' 'Building documentation for <$<>…' >&2
+ @$(call processlesml,$(PRINTF) '%s\n\n' '#!lesml@en$$' '⁌ Documentation for `<$<>´'; $(SED) '$(sedcmd)' <'$<'; $(PRINTF) '\n\n%s' '⁂' 'A part of {🔗$(PROJECT_NAME) Documentation<./index.xhtml>}.',Documentation for <$<> | $(PROJECT_NAME) Documentation) >|'$@'
+
+
+$(DOCDIR)/README.xhtml : README $(LESML)/parser.xslt
+ @$(PRINTF) '%s\n' 'Building documentation README…' >&2
+ @$(call processlesml,$(CAT) README; $(PRINTF) '\n\n%s' '⁂' 'A part of {🔗$(PROJECT_NAME) Documentation<./index.xhtml>}.',$(PROJECT_NAME) Readme | $(PROJECT_NAME) Documentation) >|'$@'
+
+$(DOCDIR)/index.xhtml : FORCE $(LESML)/parser.xslt
+ @$(PRINTF) '%s\n' 'Building documentation index…' >&2
+ @$(call processlesml,$(PRINTF) '%s\n\n' '#!lesml@en$$' '⁌ $(PROJECT_NAME) Documentation' '• {🔗$(PROJECT_NAME) Readme<./README.xhtml>}'$(foreach header,$(HEADER_FILES), '• {🔗Documentation for `$(header)´<./$(patsubst %.h,./%.xhtml,$(header))>}'),$(PROJECT_NAME) Documentation) >|'$@'
+
+$(LESML)/parser.xslt : %/parser.xslt : FORCE
+ $(GIT) submodule update --init '$*'
+
+FORCE : ;
+.PHONY : FORCE documentation