");
+}
+
+/^>/ { # Blockquotes
+ if (! (tag == "blockquote")) tag = "blockquote";
+ sub(/^>[ \t]*/,"");
+ esc($0);
+}
+
+/^#+/ { # Headers
+ match($0, /^#+/);
+ if (! (tag == "h" RLENGTH)) {
+ buflush();
+ tag = "h" RLENGTH;
+ }
+ sub(/^#+[ \t]*/,"");
+ esc($0);
+}
+
+/^$/ {
+ buflush();
+ tag = "";
+}
+
+/./ {
+ if (! tag) tag = "p";
+ if (! BUF) bufpush("<" tag ">");
+ bufpush($0);
+}
+
+END { buflush(); }
diff --git a/ht.sh b/ht.sh
new file mode 100755
index 0000000..de58fe1
--- /dev/null
+++ b/ht.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+# HAT TRICK
+# (C) 2022 C. Duckworth
+
+[ "x$DEBUG" = "xYES" ] && set -x
+
+: "${HTDAT:=$(date +%s)}"
+: "${HTTMP:=/tmp/ht}"; mkdir -p "$HTTMP"
+: "${HTENV:=$HTTMP/env-$HTDAT.sh}"
+: "${HTBOD:=$HTTMP/bod-$HTDAT.txt}"
+export HTDAT HTTMP HTENV HTBOD
+
+HT_TMPL_COUNT=1
+HT_TMPL_PRE=:
+
+print() { # print STRING...
+ ## A sane version of `echo`.
+ printf '%s\n' "$*"
+}
+
+htt() { # htt FILES...
+ # Like `cat`, but with templating.
+ ht_end="ht_main_$HTDAT_$HT_TMPL_COUNT" # be extra double sure
+ eval "$(print "cat <<$ht_end"; cat "$@"; print; print "$ht_end")"
+ HT_TMPL_COUNT=$(expr $HT_TMPL_COUNT + 1)
+}
+
+ht_build_env() { # ht_build_env FILE...
+ print "body() { cat \"$HTBOD\"; }" > "$HTENV"
+ while read -r line; do
+ case "$line" in
+ *@@*:*@@*) # "simple" metadata; just a string
+ print "$line" |
+ sed 's/.*@@\([^:]*\): \?\(.*\)@@.*/\1() { print "\2"; }/'
+ ;;
+ *@@*::*@@*) # "complex" metadata: can be anything
+ print "$line" |
+ sed 's/.*@@\([^:]*\):: \?\(.*\)@@.*/\1() { \2 ; }/'
+ ;;
+ esac >> "$HTENV"
+ # Still print the line to the body (no need to escape or w/e)
+ print "$line" >> "$HTBOD"
+ done
+ env | grep '^HT' | sort | uniq >> "$HTENV"
+}
+
+ht_main() { # main TEMPLATE < INPUT
+ ## Apply TEMPLATE to INPUT and print it.
+ # TEMPLATE will be interpreted as a heredoc.
+ if [ $# -eq 0 ]; then
+ print "ht.sh TEMPLATE < INPUT" >&2
+ exit 1
+ fi
+
+ eval "ht_build_env; . \"$HTENV\"; print \"\$(htt \"\$@\")\";";
+}
+
+# To keep this POSIX-compliant, we can't use a bashism like
+# [[ "$0" == # "$BASH_SOURCE[0]" ]]. However, there are still ways to guess
+# whether the user is sourcing this file as a library or executing it as a
+# script.
+
+case "$0" in
+ *ht.sh) ht_main "$@" ;;
+ *) print "Sourcing ht.sh" ;;
+esac
diff --git a/ideas.org b/ideas.org
new file mode 100644
index 0000000..27b15e5
--- /dev/null
+++ b/ideas.org
@@ -0,0 +1,8 @@
+#+TITLE: ideas for hat-trick
+
+* Syntax: ht.awk
+
+It'd be great to have a format that could triple into HTML, Gemini, and Gopher. Gemini-like, line-based syntax would be easiest to work with, i think.
+
+The current separation into paragraphs with blocks is a good idea. Also, starting a line with ~<~ /within/ a paragraph could be a good signal that the following is HTML code. Maybe auto-close the tag?
+
diff --git a/src/_foot.htm b/src/_foot.htm
new file mode 100644
index 0000000..287b2ba
--- /dev/null
+++ b/src/_foot.htm
@@ -0,0 +1,6 @@
+
+