summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--agpl.c3
-rw-r--r--bin/beef.c2
-rw-r--r--bin/bit.y2
-rw-r--r--bin/c11.l2
-rw-r--r--bin/dehtml.l2
-rw-r--r--bin/downgrade.c2
-rw-r--r--bin/dtch.c2
-rw-r--r--bin/ever.c2
-rw-r--r--bin/freecell.c2
-rw-r--r--bin/git-comment.pl2
-rw-r--r--bin/hilex.c4
-rw-r--r--bin/hilex.h2
-rw-r--r--bin/make.l2
-rw-r--r--bin/man1/when.134
-rw-r--r--bin/mdoc.l2
-rw-r--r--bin/modem.c2
-rw-r--r--bin/mtags.c2
-rw-r--r--bin/nudge.c2
-rw-r--r--bin/order.y2
-rw-r--r--bin/pbd.c2
-rw-r--r--bin/png.h2
-rw-r--r--bin/pngo.c2
-rw-r--r--bin/psf2png.c2
-rw-r--r--bin/ptee.c2
-rw-r--r--bin/quick.c2
-rw-r--r--bin/relay.c2
-rw-r--r--bin/scheme.c2
-rw-r--r--bin/shotty.l6
-rw-r--r--bin/title.c2
-rw-r--r--bin/when.y130
-rw-r--r--bin/xx.c2
-rw-r--r--doc/pdf/.gitignore1
-rw-r--r--doc/pdf/Makefile31
-rw-r--r--doc/zlib/adler32.32
-rw-r--r--doc/zlib/adler32_combine.32
-rw-r--r--doc/zlib/compress.32
-rw-r--r--doc/zlib/compressBound.32
-rw-r--r--doc/zlib/crc32.32
-rw-r--r--doc/zlib/crc32_combine.32
-rw-r--r--doc/zlib/deflate.32
-rw-r--r--doc/zlib/deflateBound.32
-rw-r--r--doc/zlib/deflateCopy.32
-rw-r--r--doc/zlib/deflateEnd.32
-rw-r--r--doc/zlib/deflateGetDictionary.32
-rw-r--r--doc/zlib/deflateInit.32
-rw-r--r--doc/zlib/deflateInit2.32
-rw-r--r--doc/zlib/deflateParams.32
-rw-r--r--doc/zlib/deflatePending.32
-rw-r--r--doc/zlib/deflatePrime.32
-rw-r--r--doc/zlib/deflateReset.32
-rw-r--r--doc/zlib/deflateSetDictionary.32
-rw-r--r--doc/zlib/deflateSetHeader.32
-rw-r--r--doc/zlib/deflateTune.32
-rw-r--r--doc/zlib/gzbuffer.32
-rw-r--r--doc/zlib/gzclose.32
-rw-r--r--doc/zlib/gzdirect.32
-rw-r--r--doc/zlib/gzeof.32
-rw-r--r--doc/zlib/gzerror.32
-rw-r--r--doc/zlib/gzflush.32
-rw-r--r--doc/zlib/gzfread.32
-rw-r--r--doc/zlib/gzfwrite.32
-rw-r--r--doc/zlib/gzgetc.32
-rw-r--r--doc/zlib/gzgets.32
-rw-r--r--doc/zlib/gzoffset.32
-rw-r--r--doc/zlib/gzopen.32
-rw-r--r--doc/zlib/gzprintf.32
-rw-r--r--doc/zlib/gzputc.32
-rw-r--r--doc/zlib/gzputs.32
-rw-r--r--doc/zlib/gzread.32
-rw-r--r--doc/zlib/gzseek.32
-rw-r--r--doc/zlib/gzsetparams.32
-rw-r--r--doc/zlib/gzungetc.32
-rw-r--r--doc/zlib/gzwrite.32
-rw-r--r--doc/zlib/inflate.32
-rw-r--r--doc/zlib/inflateBack.32
-rw-r--r--doc/zlib/inflateBackEnd.32
-rw-r--r--doc/zlib/inflateBackInit.32
-rw-r--r--doc/zlib/inflateCopy.32
-rw-r--r--doc/zlib/inflateEnd.32
-rw-r--r--doc/zlib/inflateGetDictionary.32
-rw-r--r--doc/zlib/inflateGetHeader.32
-rw-r--r--doc/zlib/inflateInit.32
-rw-r--r--doc/zlib/inflateInit2.32
-rw-r--r--doc/zlib/inflateMark.32
-rw-r--r--doc/zlib/inflatePrime.32
-rw-r--r--doc/zlib/inflateReset.32
-rw-r--r--doc/zlib/inflateSetDictionary.32
-rw-r--r--doc/zlib/inflateSync.32
-rw-r--r--doc/zlib/uncompress.32
-rw-r--r--doc/zlib/zlibCompileFlags.32
-rw-r--r--doc/zlib/zlibVersion.32
-rw-r--r--gpl.c3
-rw-r--r--home/.config/git/config6
-rw-r--r--home/.ssh/config3
-rw-r--r--home/.xsession7
-rw-r--r--txt/books.txt15
-rw-r--r--txt/shows.txt1
-rw-r--r--txt/tweets.txt32
-rw-r--r--www/causal.agency/.gitignore3
-rw-r--r--www/causal.agency/Makefile11
-rw-r--r--www/causal.agency/alpha.html92
-rw-r--r--www/causal.agency/index.715
-rw-r--r--www/causal.agency/lands.html176
-rw-r--r--www/causal.agency/style.css5
-rw-r--r--www/git.causal.agency/.gitignore1
-rw-r--r--www/git.causal.agency/Makefile11
-rw-r--r--www/git.causal.agency/filter.c10
-rw-r--r--www/git.causal.agency/index.781
-rw-r--r--www/photo.causal.agency/.gitignore2
-rw-r--r--www/photo.causal.agency/2024-04-10/IMG_0832.txt6
-rw-r--r--www/photo.causal.agency/2024-04-10/IMG_0850.txt6
-rw-r--r--www/photo.causal.agency/2024-04-10/IMG_0852.txt4
-rw-r--r--www/photo.causal.agency/2024-04-10/IMG_0858.txt6
-rw-r--r--www/photo.causal.agency/2024-04-10/IMG_0859.txt6
-rw-r--r--www/photo.causal.agency/2024-04-10/IMG_0865.txt2
-rw-r--r--www/photo.causal.agency/2024-04-10/IMG_0890.txt9
-rw-r--r--www/photo.causal.agency/2024-04-14/IMG_1054.txt5
-rw-r--r--www/photo.causal.agency/2024-04-14/IMG_1058.txt6
-rw-r--r--www/photo.causal.agency/2024-04-14/IMG_1066.txt10
-rw-r--r--www/photo.causal.agency/2024-04-19/IMG_1158.txt6
-rw-r--r--www/photo.causal.agency/2024-04-20/IMG_1225.txt8
-rw-r--r--www/photo.causal.agency/2024-04-20/IMG_1234.txt8
-rw-r--r--www/photo.causal.agency/2024-04-20/IMG_1245.txt17
-rw-r--r--www/photo.causal.agency/2024-04-20/IMG_1253.txt7
-rw-r--r--www/photo.causal.agency/2024-04-20/IMG_1254.txt8
-rw-r--r--www/photo.causal.agency/2024-04-30/IMG_1619.txt8
-rw-r--r--www/photo.causal.agency/generate.sh211
-rw-r--r--www/photo.causal.agency/rsync.sh5
-rw-r--r--www/temp.causal.agency/up.c2
-rw-r--r--www/text.causal.agency/037-care.748
-rw-r--r--www/text.causal.agency/039-apologies.781
-rw-r--r--www/text.causal.agency/040-sound-memory.7165
-rw-r--r--www/text.causal.agency/041-albums-2022.7185
-rw-r--r--www/text.causal.agency/042-comfort-music.762
-rw-r--r--www/text.causal.agency/043-little-blessings.778
-rw-r--r--www/text.causal.agency/Makefile11
-rw-r--r--www/text.causal.agency/feed.sh1
137 files changed, 1597 insertions, 225 deletions
diff --git a/agpl.c b/agpl.c
index 58a88fc4..e7682757 100644
--- a/agpl.c
+++ b/agpl.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2022  June McEnroe <june@causal.agency>
+/* Copyright (C) 2024  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
@@ -17,4 +17,3 @@
 #include <err.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <sysexits.h>
diff --git a/bin/beef.c b/bin/beef.c
index b2579b73..556f3088 100644
--- a/bin/beef.c
+++ b/bin/beef.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2019  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/bit.y b/bin/bit.y
index ab310492..1119bce6 100644
--- a/bin/bit.y
+++ b/bin/bit.y
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2019  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/c11.l b/bin/c11.l
index a4b8c25a..b1f0b960 100644
--- a/bin/c11.l
+++ b/bin/c11.l
@@ -1,4 +1,4 @@
-/* Copyright (C) 2020  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2020  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/dehtml.l b/bin/dehtml.l
index 3f2de592..799f0926 100644
--- a/bin/dehtml.l
+++ b/bin/dehtml.l
@@ -1,4 +1,4 @@
-/* Copyright (C) 2021  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2021  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/downgrade.c b/bin/downgrade.c
index d4c5b598..31019714 100644
--- a/bin/downgrade.c
+++ b/bin/downgrade.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2021  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2021  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/dtch.c b/bin/dtch.c
index 2aea53ae..026493dd 100644
--- a/bin/dtch.c
+++ b/bin/dtch.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2017-2019  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2017-2019  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/ever.c b/bin/ever.c
index f983912b..f8ff943b 100644
--- a/bin/ever.c
+++ b/bin/ever.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2017  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2017  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/freecell.c b/bin/freecell.c
index 11bed1c0..fbc0fe22 100644
--- a/bin/freecell.c
+++ b/bin/freecell.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019, 2021  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2019, 2021  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/git-comment.pl b/bin/git-comment.pl
index 5100941f..5352702d 100644
--- a/bin/git-comment.pl
+++ b/bin/git-comment.pl
@@ -1,5 +1,5 @@
 #!/usr/bin/env perl
-# Copyright (C) 2021  C. McEnroe <june@causal.agency>
+# Copyright (C) 2021  June McEnroe <june@causal.agency>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/hilex.c b/bin/hilex.c
index 0bcc5c7f..7d7b3f2d 100644
--- a/bin/hilex.c
+++ b/bin/hilex.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2020  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2020  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
@@ -53,7 +53,7 @@ static const struct {
 	{ &LexC, "c", "[.][chlmy]$", NULL },
 	{ &LexMake, "make", "[.](mk|am)$|^Makefile$", NULL },
 	{ &LexMdoc, "mdoc", "[.][1-9]$", "^[.]Dd" },
-	{ &LexSh, "sh", "[.]sh$|^[.](profile|shrc)$", "^#![ ]?/bin/sh" },
+	{ &LexSh, "sh", "[.]sh$|^[.](profile|shrc)$", "^#![ ]?/bin/k?sh" },
 	{ &LexText, "text", "[.]txt$", NULL },
 };
 
diff --git a/bin/hilex.h b/bin/hilex.h
index 882b5f95..b57fc8cc 100644
--- a/bin/hilex.h
+++ b/bin/hilex.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2020  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2020  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/make.l b/bin/make.l
index ae1be2f5..6296716d 100644
--- a/bin/make.l
+++ b/bin/make.l
@@ -1,4 +1,4 @@
-/* Copyright (C) 2020  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2020  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/man1/when.1 b/bin/man1/when.1
index 0b473573..3f2735f7 100644
--- a/bin/man1/when.1
+++ b/bin/man1/when.1
@@ -1,4 +1,4 @@
-.Dd July 24, 2019
+.Dd September 19, 2022
 .Dt WHEN 1
 .Os
 .
@@ -9,6 +9,8 @@
 .Sh SYNOPSIS
 .Nm
 .Op Ar expr
+.Nm
+.Cm -
 .
 .Sh DESCRIPTION
 .Nm
@@ -18,24 +20,32 @@ If no
 is given,
 expressions are read
 from standard input.
+If
+.Cm -
+is given,
+the intervals between each named date
+and today are printed.
 .
 .Pp
 The grammar is as follows:
 .Bl -tag -width Ds
 .It Sy \&.
 Today's date.
+The empty expression is equivalent.
+.
+.It Ar name Op Sy = Ar date
+A named date.
+Names are alphanumeric including underscores.
 .
 .It Ar month Ar date Op Ar year
 A full date,
 or a date in the current year.
-.Ar month
-must be at least three letters.
+Months can be abbreviated to three letters.
 .
 .It Ar day
 A day of the week
 in the current week.
-.Ar day
-must be at least three letters.
+Days can be abbreviated to three letters.
 .
 .It Sy < Ar date
 The date one week before.
@@ -65,6 +75,14 @@ A number of months.
 A number of years.
 .El
 .
+.Sh FILES
+The file
+.Pa $XDG_CONFIG_HOME/when/dates
+or
+.Pa ~/.config/when/dates
+is read before any other expressions,
+if it exists.
+.
 .Sh EXAMPLES
 .Bl -tag -width "Dec 25 - ."
 .It Ic Dec 25 - \&.
@@ -74,3 +92,9 @@ The date next Friday.
 .It Ic \&. + 2w
 Your last day at work.
 .El
+.Pp
+Checking a milestone:
+.Bd -literal -offset indent
+$ echo 'hrt = oct 15 2021' >> ~/.config/when/dates
+$ when -hrt
+.Ed
diff --git a/bin/mdoc.l b/bin/mdoc.l
index f29b6ceb..b6deacbe 100644
--- a/bin/mdoc.l
+++ b/bin/mdoc.l
@@ -1,4 +1,4 @@
-/* Copyright (C) 2020  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2020  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/modem.c b/bin/modem.c
index 2133ae08..4392e071 100644
--- a/bin/modem.c
+++ b/bin/modem.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2018  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/mtags.c b/bin/mtags.c
index 11cd9c8a..5c1a057e 100644
--- a/bin/mtags.c
+++ b/bin/mtags.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2021  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2021  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/nudge.c b/bin/nudge.c
index 108d2459..8ae916eb 100644
--- a/bin/nudge.c
+++ b/bin/nudge.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2020  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2020  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/order.y b/bin/order.y
index c2e87971..b3cbf2df 100644
--- a/bin/order.y
+++ b/bin/order.y
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2019  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/pbd.c b/bin/pbd.c
index 2fd401ae..9f47b63e 100644
--- a/bin/pbd.c
+++ b/bin/pbd.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2017  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2017  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/png.h b/bin/png.h
index 15b6d13d..0df4699b 100644
--- a/bin/png.h
+++ b/bin/png.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2018  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/pngo.c b/bin/pngo.c
index ba90889a..eb51ccc2 100644
--- a/bin/pngo.c
+++ b/bin/pngo.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2021  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2018, 2021  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/psf2png.c b/bin/psf2png.c
index 1aaa8635..c36238a0 100644
--- a/bin/psf2png.c
+++ b/bin/psf2png.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2018  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/ptee.c b/bin/ptee.c
index 8374bd8f..52350a21 100644
--- a/bin/ptee.c
+++ b/bin/ptee.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2019  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/quick.c b/bin/quick.c
index edf35a3b..d814873d 100644
--- a/bin/quick.c
+++ b/bin/quick.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2021  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2021  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/relay.c b/bin/relay.c
index aa7913c9..fd799462 100644
--- a/bin/relay.c
+++ b/bin/relay.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2019  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/scheme.c b/bin/scheme.c
index 33fd8b60..2bae8f82 100644
--- a/bin/scheme.c
+++ b/bin/scheme.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018, 2019  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2018, 2019  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/shotty.l b/bin/shotty.l
index ff78d241..dcac43ec 100644
--- a/bin/shotty.l
+++ b/bin/shotty.l
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019, 2021  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2019, 2021  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
@@ -181,13 +181,13 @@ ESC \x1B
 		| (wchar_t)(yytext[1] & 0x3F);
 	return Data;
 }
-[\xE0-\xEF][\x80-\xBF]{2} {
+[\xE0-\xEF]([\x80-\xBF]{2}) {
 	ch = (wchar_t)(yytext[0] & 0x0F) << 12
 		| (wchar_t)(yytext[1] & 0x3F) << 6
 		| (wchar_t)(yytext[2] & 0x3F);
 	return Data;
 }
-[\xF0-\xF7][\x80-\xBF]{3} {
+[\xF0-\xF7]([\x80-\xBF]{3}) {
 	ch = (wchar_t)(yytext[0] & 0x07) << 18
 		| (wchar_t)(yytext[1] & 0x3F) << 12
 		| (wchar_t)(yytext[2] & 0x3F) << 6
diff --git a/bin/title.c b/bin/title.c
index 82f89d95..47ff720a 100644
--- a/bin/title.c
+++ b/bin/title.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2019  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/bin/when.y b/bin/when.y
index 64859da7..46651ebb 100644
--- a/bin/when.y
+++ b/bin/when.y
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019  June McEnroe <june@causal.agency>
+/* Copyright (C) 2019, 2022  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
@@ -18,6 +18,9 @@
 
 #include <ctype.h>
 #include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <strings.h>
@@ -30,12 +33,13 @@ static int yylex(void);
 #define YYSTYPE struct tm
 
 static const char *Days[7] = {
-	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+	"Sunday", "Monday", "Tuesday", "Wednesday",
+	"Thursday", "Friday", "Saturday",
 };
 
 static const char *Months[12] = {
-	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+	"January", "February", "March", "April", "May", "June",
+	"July", "August", "September", "October", "November", "December",
 };
 
 static const struct tm Week = { .tm_mday = 7 };
@@ -117,7 +121,10 @@ static struct tm dateDiff(struct tm a, struct tm b) {
 		.tm_mon = a.tm_mon - b.tm_mon,
 		.tm_mday = a.tm_mday - b.tm_mday,
 	};
-	if (a.tm_mon < b.tm_mon) {
+	if (
+		a.tm_mon < b.tm_mon ||
+		(a.tm_mon == b.tm_mon && a.tm_mday < b.tm_mday)
+	) {
 		diff.tm_year--;
 		diff.tm_mon += 12;
 	}
@@ -130,15 +137,50 @@ static struct tm dateDiff(struct tm a, struct tm b) {
 	return diff;
 }
 
+static struct {
+	size_t cap, len;
+	struct tm *ptr;
+} dates;
+
+static struct tm getDate(const char *name) {
+	for (size_t i = 0; i < dates.len; ++i) {
+		if (!strcmp(dates.ptr[i].tm_zone, name)) return dates.ptr[i];
+	}
+	return (struct tm) {0};
+}
+
+static void setDate(const char *name, struct tm date) {
+	for (size_t i = 0; i < dates.len; ++i) {
+		if (strcmp(dates.ptr[i].tm_zone, name)) continue;
+		char *tm_zone = dates.ptr[i].tm_zone;
+		dates.ptr[i] = date;
+		dates.ptr[i].tm_zone = tm_zone;
+		return;
+	}
+	if (dates.len == dates.cap) {
+		dates.cap = (dates.cap ? dates.cap * 2 : 8);
+		dates.ptr = realloc(dates.ptr, sizeof(*dates.ptr) * dates.cap);
+		if (!dates.ptr) err(EX_OSERR, "realloc");
+	}
+	dates.ptr[dates.len] = date;
+	dates.ptr[dates.len].tm_zone = strdup(name);
+	if (!dates.ptr[dates.len].tm_zone) err(EX_OSERR, "strdup");
+	dates.len++;
+}
+
+static bool silent;
+
 static void printDate(struct tm date) {
+	if (silent) return;
 	printf(
-		"%s %s %d %d\n",
+		"%.3s %.3s %d %d\n",
 		Days[date.tm_wday], Months[date.tm_mon],
 		date.tm_mday, 1900 + date.tm_year
 	);
 }
 
 static void printScalar(struct tm scalar) {
+	if (silent) return;
 	if (scalar.tm_year) printf("%dy ", scalar.tm_year);
 	if (scalar.tm_mon) printf("%dm ", scalar.tm_mon);
 	if (scalar.tm_mday % 7) {
@@ -161,9 +203,9 @@ static void printScalar(struct tm scalar) {
 
 %}
 
-%token Number Month Day
+%token Name Number Month Day
 %left '+' '-'
-%right '<' '>'
+%right '=' '<' '>'
 
 %%
 
@@ -174,6 +216,8 @@ expr:
 
 date:
 	dateLit
+	| Name { $$ = getDate($1.tm_zone); free($1.tm_zone); }
+	| Name '=' date { setDate($1.tm_zone, $3); free($1.tm_zone); $$ = $3; }
 	| '(' date ')' { $$ = $2; }
 	| '<' date { $$ = dateSub($2, Week); }
 	| '>' date { $$ = dateAdd($2, Week); }
@@ -223,35 +267,77 @@ static int yylex(void) {
 		return Number;
 	}
 
-	for (int i = 0; i < 7; ++i) {
-		if (strncasecmp(input, Days[i], 3)) continue;
-		while (isalpha(*input)) input++;
-		yylval.tm_wday = i;
-		return Day;
+	size_t len;
+	for (len = 0; isalnum(input[len]) || input[len] == '_'; ++len);
+
+	if (len >= 3) {
+		for (int i = 0; i < 7; ++i) {
+			if (strncasecmp(input, Days[i], len)) continue;
+			yylval.tm_wday = i;
+			input += len;
+			return Day;
+		}
+
+		for (int i = 0; i < 12; ++i) {
+			if (strncasecmp(input, Months[i], len)) continue;
+			yylval.tm_mon = i;
+			input += len;
+			return Month;
+		}
 	}
 
-	for (int i = 0; i < 12; ++i) {
-		if (strncasecmp(input, Months[i], 3)) continue;
-		while (isalpha(*input)) input++;
-		yylval.tm_mon = i;
-		return Month;
+	if (len && (len != 1 || !strchr("dwmy", *input))) {
+		yylval.tm_zone = strndup(input, len);
+		if (!yylval.tm_zone) err(EX_OSERR, "strndup");
+		input += len;
+		return Name;
 	}
 
 	return *input++;
 }
 
 int main(int argc, char *argv[]) {
+	size_t cap = 0;
+	char *line = NULL;
+
+	char path[PATH_MAX];
+	const char *configHome = getenv("XDG_CONFIG_HOME");
+	if (configHome) {
+		snprintf(path, sizeof(path), "%s/when/dates", configHome);
+	} else {
+		snprintf(path, sizeof(path), "%s/.config/when/dates", getenv("HOME"));
+	}
+
+	FILE *file = fopen(path, "r");
+	if (file) {
+		silent = true;
+		while (0 < getline(&line, &cap, file)) {
+			input = line;
+			yyparse();
+		}
+		fclose(file);
+		silent = false;
+	} else if (errno != ENOENT) {
+		err(EX_CONFIG, "%s", path);
+	}
+
 	if (argc > 1) {
-		input = argv[1];
-		return yyparse();
+		if (strcmp(argv[1], "-")) {
+			input = argv[1];
+			return yyparse();
+		} else {
+			for (size_t i = 0; i < dates.len; ++i) {
+				printf("%s: ", dates.ptr[i].tm_zone);
+				printScalar(dateDiff(today(), dates.ptr[i]));
+			}
+			return EX_OK;
+		}
 	}
 
 	struct tm date = today();
 	printDate(date);
 	printf("\n");
 
-	char *line = NULL;
-	size_t cap = 0;
 	while (0 < getline(&line, &cap, stdin)) {
 		if (line[0] == '\n') continue;
 
diff --git a/bin/xx.c b/bin/xx.c
index 6d04f2f5..39d7ec07 100644
--- a/bin/xx.c
+++ b/bin/xx.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2017  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2017  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/doc/pdf/.gitignore b/doc/pdf/.gitignore
deleted file mode 100644
index a1363379..00000000
--- a/doc/pdf/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.pdf
diff --git a/doc/pdf/Makefile b/doc/pdf/Makefile
deleted file mode 100644
index 7afbdcf2..00000000
--- a/doc/pdf/Makefile
+++ /dev/null
@@ -1,31 +0,0 @@
-PDFS += abi.pdf
-PDFS += c11.pdf
-PDFS += elf.pdf
-PDFS += intel-64-opt.pdf
-PDFS += intel-64-sdm-vol-1.pdf
-PDFS += intel-64-sdm-vol-2.pdf
-PDFS += intel-64-sdm-vol-3.pdf
-PDFS += intel-64-sdm-vol-4.pdf
-PDFS += multiboot.pdf
-
-ELF = https://refspecs.linuxbase.org/elf
-INTEL = https://software.intel.com/sites/default/files/managed
-
-URL.abi.pdf = ${ELF}/x86_64-abi-0.99.pdf
-URL.c11.pdf = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
-URL.elf.pdf = ${ELF}/elf.pdf
-URL.intel-64-opt.pdf = ${INTEL}/9e/bc/64-ia-32-architectures-optimization-manual.pdf
-URL.intel-64-sdm-vol-1.pdf = ${INTEL}/a4/60/253665-sdm-vol-1.pdf
-URL.intel-64-sdm-vol-2.pdf = ${INTEL}/a4/60/325383-sdm-vol-2abcd.pdf
-URL.intel-64-sdm-vol-3.pdf = ${INTEL}/a4/60/325384-sdm-vol-3abcd.pdf
-URL.intel-64-sdm-vol-4.pdf = ${INTEL}/22/0d/335592-sdm-vol-4.pdf
-URL.multiboot.pdf = https://www.gnu.org/software/grub/manual/multiboot/multiboot.pdf
-
-all: ${PDFS}
-
-${PDFS}:
-	curl -Lf -o $@ ${URL.$@}
-	chmod a-w $@
-
-clean:
-	rm -f ${PDFS}
diff --git a/doc/zlib/adler32.3 b/doc/zlib/adler32.3
index d713d952..c58a34e7 100644
--- a/doc/zlib/adler32.3
+++ b/doc/zlib/adler32.3
@@ -58,7 +58,7 @@ if (adler != original_adler) error();
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/adler32_combine.3 b/doc/zlib/adler32_combine.3
index 861f235b..55e801e9 100644
--- a/doc/zlib/adler32_combine.3
+++ b/doc/zlib/adler32_combine.3
@@ -56,7 +56,7 @@ the result has no meaning or utility.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/compress.3 b/doc/zlib/compress.3
index 22b229ee..16445e2f 100644
--- a/doc/zlib/compress.3
+++ b/doc/zlib/compress.3
@@ -77,7 +77,7 @@ parameter is invalid.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/compressBound.3 b/doc/zlib/compressBound.3
index 5800e2ba..d61891eb 100644
--- a/doc/zlib/compressBound.3
+++ b/doc/zlib/compressBound.3
@@ -37,7 +37,7 @@ call to allocate the destination buffer.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/crc32.3 b/doc/zlib/crc32.3
index 3c9cc8c4..a42df2af 100644
--- a/doc/zlib/crc32.3
+++ b/doc/zlib/crc32.3
@@ -59,7 +59,7 @@ if (crc != original_crc) error();
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/crc32_combine.3 b/doc/zlib/crc32_combine.3
index 2f79f623..b25da679 100644
--- a/doc/zlib/crc32_combine.3
+++ b/doc/zlib/crc32_combine.3
@@ -47,7 +47,7 @@ and
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/deflate.3 b/doc/zlib/deflate.3
index 7df313ee..be182d96 100644
--- a/doc/zlib/deflate.3
+++ b/doc/zlib/deflate.3
@@ -363,7 +363,7 @@ to continue compressing.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/deflateBound.3 b/doc/zlib/deflateBound.3
index 63e80246..be97494c 100644
--- a/doc/zlib/deflateBound.3
+++ b/doc/zlib/deflateBound.3
@@ -64,7 +64,7 @@ are used.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/deflateCopy.3 b/doc/zlib/deflateCopy.3
index f30d6301..f20e0a9e 100644
--- a/doc/zlib/deflateCopy.3
+++ b/doc/zlib/deflateCopy.3
@@ -59,7 +59,7 @@ in both source and destination.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/deflateEnd.3 b/doc/zlib/deflateEnd.3
index e24259a3..0abaabe1 100644
--- a/doc/zlib/deflateEnd.3
+++ b/doc/zlib/deflateEnd.3
@@ -43,7 +43,7 @@ may be set but then points to a static string
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/deflateGetDictionary.3 b/doc/zlib/deflateGetDictionary.3
index 403f6d10..b9dabfe2 100644
--- a/doc/zlib/deflateGetDictionary.3
+++ b/doc/zlib/deflateGetDictionary.3
@@ -72,7 +72,7 @@ if the stream state is inconsistent.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/deflateInit.3 b/doc/zlib/deflateInit.3
index a893dd91..52179883 100644
--- a/doc/zlib/deflateInit.3
+++ b/doc/zlib/deflateInit.3
@@ -171,7 +171,7 @@ if there is no error message.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/deflateInit2.3 b/doc/zlib/deflateInit2.3
index 6a581ef8..a7d68b99 100644
--- a/doc/zlib/deflateInit2.3
+++ b/doc/zlib/deflateInit2.3
@@ -220,7 +220,7 @@ is set to null if there is no error message.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/deflateParams.3 b/doc/zlib/deflateParams.3
index 8e770d4e..9eb5ca16 100644
--- a/doc/zlib/deflateParams.3
+++ b/doc/zlib/deflateParams.3
@@ -116,7 +116,7 @@ with more output space.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/deflatePending.3 b/doc/zlib/deflatePending.3
index 1ce40fc2..35fa6d38 100644
--- a/doc/zlib/deflatePending.3
+++ b/doc/zlib/deflatePending.3
@@ -49,7 +49,7 @@ if the source stream state was inconsistent.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/deflatePrime.3 b/doc/zlib/deflatePrime.3
index 639e715a..10a2924b 100644
--- a/doc/zlib/deflatePrime.3
+++ b/doc/zlib/deflatePrime.3
@@ -57,7 +57,7 @@ if the source stream state was inconsistent.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/deflateReset.3 b/doc/zlib/deflateReset.3
index 7309ac15..1a18c507 100644
--- a/doc/zlib/deflateReset.3
+++ b/doc/zlib/deflateReset.3
@@ -50,7 +50,7 @@ being
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/deflateSetDictionary.3 b/doc/zlib/deflateSetDictionary.3
index c2c9d7c2..3e66d3cf 100644
--- a/doc/zlib/deflateSetDictionary.3
+++ b/doc/zlib/deflateSetDictionary.3
@@ -135,7 +135,7 @@ for raw deflate
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/deflateSetHeader.3 b/doc/zlib/deflateSetHeader.3
index 6fec645c..03d4f4d3 100644
--- a/doc/zlib/deflateSetHeader.3
+++ b/doc/zlib/deflateSetHeader.3
@@ -173,7 +173,7 @@ if the source stream state was inconsistent.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/deflateTune.3 b/doc/zlib/deflateTune.3
index 7269dec0..ea4dd915 100644
--- a/doc/zlib/deflateTune.3
+++ b/doc/zlib/deflateTune.3
@@ -63,7 +63,7 @@ for an invalid deflate stream.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzbuffer.3 b/doc/zlib/gzbuffer.3
index de7c706a..92438c48 100644
--- a/doc/zlib/gzbuffer.3
+++ b/doc/zlib/gzbuffer.3
@@ -52,7 +52,7 @@ such as being called too late.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzclose.3 b/doc/zlib/gzclose.3
index 77eae11e..bfcc583e 100644
--- a/doc/zlib/gzclose.3
+++ b/doc/zlib/gzclose.3
@@ -90,7 +90,7 @@ on success.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzdirect.3 b/doc/zlib/gzdirect.3
index 8fa26aae..640fd4c5 100644
--- a/doc/zlib/gzdirect.3
+++ b/doc/zlib/gzdirect.3
@@ -78,7 +78,7 @@ which may not be desired.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzeof.3 b/doc/zlib/gzeof.3
index 26c415fe..ba823aa6 100644
--- a/doc/zlib/gzeof.3
+++ b/doc/zlib/gzeof.3
@@ -56,7 +56,7 @@ end of file was detected.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzerror.3 b/doc/zlib/gzerror.3
index 13dcddd4..a9e175fc 100644
--- a/doc/zlib/gzerror.3
+++ b/doc/zlib/gzerror.3
@@ -68,7 +68,7 @@ that is being written concurrently.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzflush.3 b/doc/zlib/gzflush.3
index b93c03e7..476f7c09 100644
--- a/doc/zlib/gzflush.3
+++ b/doc/zlib/gzflush.3
@@ -66,7 +66,7 @@ see function
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzfread.3 b/doc/zlib/gzfread.3
index 66231cc3..7bf57fc5 100644
--- a/doc/zlib/gzfread.3
+++ b/doc/zlib/gzfread.3
@@ -100,7 +100,7 @@ and the error state is set to
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzfwrite.3 b/doc/zlib/gzfwrite.3
index 38383a33..6835db3a 100644
--- a/doc/zlib/gzfwrite.3
+++ b/doc/zlib/gzfwrite.3
@@ -68,7 +68,7 @@ and the error state is set to
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzgetc.3 b/doc/zlib/gzgetc.3
index 93a90edd..db9143ec 100644
--- a/doc/zlib/gzgetc.3
+++ b/doc/zlib/gzgetc.3
@@ -48,7 +48,7 @@ or error.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzgets.3 b/doc/zlib/gzgets.3
index 2a329e9e..c1435b39 100644
--- a/doc/zlib/gzgets.3
+++ b/doc/zlib/gzgets.3
@@ -60,7 +60,7 @@ are indeterminate.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzoffset.3 b/doc/zlib/gzoffset.3
index cbb78a77..b03c557e 100644
--- a/doc/zlib/gzoffset.3
+++ b/doc/zlib/gzoffset.3
@@ -44,7 +44,7 @@ returns -1.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzopen.3 b/doc/zlib/gzopen.3
index e3cb4cbd..9da647e1 100644
--- a/doc/zlib/gzopen.3
+++ b/doc/zlib/gzopen.3
@@ -254,7 +254,7 @@ for the routine
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzprintf.3 b/doc/zlib/gzprintf.3
index 26961f34..a2a241a2 100644
--- a/doc/zlib/gzprintf.3
+++ b/doc/zlib/gzprintf.3
@@ -64,7 +64,7 @@ This can be determined using
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzputc.3 b/doc/zlib/gzputc.3
index 161e5631..66897b5e 100644
--- a/doc/zlib/gzputc.3
+++ b/doc/zlib/gzputc.3
@@ -36,7 +36,7 @@ or -1 in case of error.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzputs.3 b/doc/zlib/gzputs.3
index f5d1fd84..71833ab2 100644
--- a/doc/zlib/gzputs.3
+++ b/doc/zlib/gzputs.3
@@ -34,7 +34,7 @@ or -1 in case of error.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzread.3 b/doc/zlib/gzread.3
index 84439eaa..4118eca7 100644
--- a/doc/zlib/gzread.3
+++ b/doc/zlib/gzread.3
@@ -108,7 +108,7 @@ and the error state is set to
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzseek.3 b/doc/zlib/gzseek.3
index cd85fd4c..a14b2db6 100644
--- a/doc/zlib/gzseek.3
+++ b/doc/zlib/gzseek.3
@@ -101,7 +101,7 @@ would be before the current position.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzsetparams.3 b/doc/zlib/gzsetparams.3
index ff544d23..f6ff9ed7 100644
--- a/doc/zlib/gzsetparams.3
+++ b/doc/zlib/gzsetparams.3
@@ -44,7 +44,7 @@ if there is a memory allocation error.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzungetc.3 b/doc/zlib/gzungetc.3
index 90cdafc7..fbe9371c 100644
--- a/doc/zlib/gzungetc.3
+++ b/doc/zlib/gzungetc.3
@@ -60,7 +60,7 @@ or -1 on failure.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/gzwrite.3 b/doc/zlib/gzwrite.3
index 606d89f4..73407ef5 100644
--- a/doc/zlib/gzwrite.3
+++ b/doc/zlib/gzwrite.3
@@ -32,7 +32,7 @@ or 0 in case of error.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/inflate.3 b/doc/zlib/inflate.3
index ca90c270..255e0f84 100644
--- a/doc/zlib/inflate.3
+++ b/doc/zlib/inflate.3
@@ -391,7 +391,7 @@ is to be attempted.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/inflateBack.3 b/doc/zlib/inflateBack.3
index 59d5f8cb..fcda7452 100644
--- a/doc/zlib/inflateBack.3
+++ b/doc/zlib/inflateBack.3
@@ -278,7 +278,7 @@ cannot return
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/inflateBackEnd.3 b/doc/zlib/inflateBackEnd.3
index eeb88636..39fbea8f 100644
--- a/doc/zlib/inflateBackEnd.3
+++ b/doc/zlib/inflateBackEnd.3
@@ -36,7 +36,7 @@ if the stream state was inconsistent.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/inflateBackInit.3 b/doc/zlib/inflateBackInit.3
index 483edda5..d029542e 100644
--- a/doc/zlib/inflateBackInit.3
+++ b/doc/zlib/inflateBackInit.3
@@ -77,7 +77,7 @@ does not match the version of the header file.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/inflateCopy.3 b/doc/zlib/inflateCopy.3
index 53b30edf..167b879b 100644
--- a/doc/zlib/inflateCopy.3
+++ b/doc/zlib/inflateCopy.3
@@ -52,7 +52,7 @@ in both source and destination.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/inflateEnd.3 b/doc/zlib/inflateEnd.3
index 9b18226b..54945b50 100644
--- a/doc/zlib/inflateEnd.3
+++ b/doc/zlib/inflateEnd.3
@@ -37,7 +37,7 @@ if the stream state was inconsistent.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/inflateGetDictionary.3 b/doc/zlib/inflateGetDictionary.3
index e70ee736..9290850c 100644
--- a/doc/zlib/inflateGetDictionary.3
+++ b/doc/zlib/inflateGetDictionary.3
@@ -62,7 +62,7 @@ if the stream state is inconsistent.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/inflateGetHeader.3 b/doc/zlib/inflateGetHeader.3
index f77670f2..57f7c443 100644
--- a/doc/zlib/inflateGetHeader.3
+++ b/doc/zlib/inflateGetHeader.3
@@ -163,7 +163,7 @@ if the source stream state was inconsistent.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/inflateInit.3 b/doc/zlib/inflateInit.3
index 186b058a..66a1d4f7 100644
--- a/doc/zlib/inflateInit.3
+++ b/doc/zlib/inflateInit.3
@@ -94,7 +94,7 @@ is set to null if there is no error message.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/inflateInit2.3 b/doc/zlib/inflateInit2.3
index a630f12a..5b8b49ac 100644
--- a/doc/zlib/inflateInit2.3
+++ b/doc/zlib/inflateInit2.3
@@ -174,7 +174,7 @@ is set to null if there is no error message.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/inflateMark.3 b/doc/zlib/inflateMark.3
index 2d15993d..90e2ee0b 100644
--- a/doc/zlib/inflateMark.3
+++ b/doc/zlib/inflateMark.3
@@ -81,7 +81,7 @@ or -65536 if the provided source stream state was inconsistent.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/inflatePrime.3 b/doc/zlib/inflatePrime.3
index c89dc2c5..66953665 100644
--- a/doc/zlib/inflatePrime.3
+++ b/doc/zlib/inflatePrime.3
@@ -66,7 +66,7 @@ if the source stream state was inconsistent.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/inflateReset.3 b/doc/zlib/inflateReset.3
index a8d2e219..53c4ffe2 100644
--- a/doc/zlib/inflateReset.3
+++ b/doc/zlib/inflateReset.3
@@ -74,7 +74,7 @@ parameter is invalid.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/inflateSetDictionary.3 b/doc/zlib/inflateSetDictionary.3
index 0e3c60c7..291c97e8 100644
--- a/doc/zlib/inflateSetDictionary.3
+++ b/doc/zlib/inflateSetDictionary.3
@@ -78,7 +78,7 @@ doesn't match the expected one
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/inflateSync.3 b/doc/zlib/inflateSync.3
index 35264ddd..56d3ca28 100644
--- a/doc/zlib/inflateSync.3
+++ b/doc/zlib/inflateSync.3
@@ -65,7 +65,7 @@ until success or the end of the input data.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/uncompress.3 b/doc/zlib/uncompress.3
index d951da9b..1047ad91 100644
--- a/doc/zlib/uncompress.3
+++ b/doc/zlib/uncompress.3
@@ -85,7 +85,7 @@ with the uncompressed data up to that point.
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/zlibCompileFlags.3 b/doc/zlib/zlibCompileFlags.3
index 465195c2..59cc24a8 100644
--- a/doc/zlib/zlibCompileFlags.3
+++ b/doc/zlib/zlibCompileFlags.3
@@ -156,7 +156,7 @@ not secure!
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/doc/zlib/zlibVersion.3 b/doc/zlib/zlibVersion.3
index 35a9854b..04377527 100644
--- a/doc/zlib/zlibVersion.3
+++ b/doc/zlib/zlibVersion.3
@@ -38,7 +38,7 @@ and
 This manual page was converted from
 .In zlib.h
 to mdoc format by
-.An C. McEnroe Aq Mt june@causal.agency .
+.An June McEnroe Aq Mt june@causal.agency .
 .
 .Sh AUTHORS
 .An Jean-loup Gailly Aq Mt jloup@gzip.org
diff --git a/gpl.c b/gpl.c
index 8634449b..8ff4916d 100644
--- a/gpl.c
+++ b/gpl.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2022  June McEnroe <june@causal.agency>
+/* Copyright (C) 2024  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -17,4 +17,3 @@
 #include <err.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <sysexits.h>
diff --git a/home/.config/git/config b/home/.config/git/config
index b4c5d97f..c990de2c 100644
--- a/home/.config/git/config
+++ b/home/.config/git/config
@@ -2,6 +2,9 @@
 	name = June McEnroe
 	email = june@causal.agency
 
+[branch]
+	sort = committerdate
+
 [commit]
 	verbose = true
 
@@ -24,5 +27,8 @@
 [pretty]
 	log = %Cred%h %Creset%s%C(yellow)%d %Cgreen(%ar) %Cblue<%aN>
 
+[alias]
+	forgive = blame
+
 [include]
 	path = ./private
diff --git a/home/.ssh/config b/home/.ssh/config
index b2035a81..f579ae9f 100644
--- a/home/.ssh/config
+++ b/home/.ssh/config
@@ -1,9 +1,10 @@
 IgnoreUnknown Include
 Include config_private
 
+AddKeysToAgent yes
 SendEnv LANG LC_*
 
-Host monday beastie puffy toaster tux progynova
+Host tuesday beastie puffy toaster tux progynova
 	HostName %h.local
 	ForwardAgent yes
 	RemoteForward 7062 127.0.0.1:7062
diff --git a/home/.xsession b/home/.xsession
index a51d52f2..1e05126c 100644
--- a/home/.xsession
+++ b/home/.xsession
@@ -4,8 +4,11 @@ export LC_CTYPE=en_US.UTF-8
 xset r rate 175 m 5/4 0
 xmodmap ~/.config/X/modmap
 xrdb -load ~/.config/X/resources
-xsetroot -bitmap /usr/X11R6/include/X11/bitmaps/xsnow \
-	-bg rgb:14/13/0E -fg rgb:7A/49/55 
+
+fg=998D6B
+command -v scheme && fg=$(scheme -p $(jot -r 1 1 8))
+xsetroot -bitmap /usr/X11R6/include/X11/bitmaps/escherknot \
+	-bg '#14130E' -fg "#${fg}"
 
 xterm -name clock -geometry 14x1-0+0 -sl 0 -e clock &
 exec cwm -c ~/.config/cwm/cwmrc
diff --git a/txt/books.txt b/txt/books.txt
index 23710ff0..7ebae70c 100644
--- a/txt/books.txt
+++ b/txt/books.txt
@@ -1,5 +1,20 @@
+[ 2023 ]
+
+  7. ★★☆ Alix E. Harrow, Starling House
+  6. ★★☆ Alix E. Harrow, A Mirror Mended
+  5. ★★★ Alix E. Harrow, A Spindle Splintered
+  4. ★★☆ Alyson Greaves, The Sisters of Dorley (ch. 1-15)
+  3. ★☆☆ Nnedi Okorafor, Noor
+  2. ★★☆ Nnedi Okorafor, Remote Control
+  1. ★★☆ Becky Chambers, A Prayer for the Crown-Shy
+
 [ 2022 ]
 
+ 15. ★★★ Becky Chambers, The Long Way To a Small Angry Planet
+ 14. ★★★ ed. Tristan Taormino, Take Me There
+ 13. ★★★★ Becky Chambers, A Closed and Common Orbit
+ 12. ★★☆ Sybil Lamb, I've Got a Time Bomb
+ 11. ☆☆☆ Ruth Ozeki, The Book of Form and Emptiness
  10. ★☆☆ Sally Rooney, Conversations With Friends
   9. ★☆☆ Sally Rooney, Normal People
   8. ★★★ Andrea Stewart, The Bone Shard Emperor
diff --git a/txt/shows.txt b/txt/shows.txt
index a2998e23..2abacf5b 100644
--- a/txt/shows.txt
+++ b/txt/shows.txt
@@ -1,3 +1,4 @@
+2022-12-18 (SAT) LINGUA IGNOTA
 2022-06-04 (MAI) Honeydrip, MAGELLA, BACKXWASH
 2020-01-23 (La Sala Rossa) Secondsight, BIG|BRAVE
 2019-12-10 (Casa del Popolo) meth, Street Sects
diff --git a/txt/tweets.txt b/txt/tweets.txt
deleted file mode 100644
index 240351ec..00000000
--- a/txt/tweets.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-triangle forum
-https://twitter.com/g0m/status/963890156477603841
-
-damn ya ass fat what's ya pronouns?
-https://twitter.com/msbigmilk/status/1291218055939448833
-
-afab
-https://twitter.com/ErisGael/status/1257524779046907904
-
-chaos emeralds
-https://twitter.com/ErisGael/status/1190147736244490240
-
-might as well salivate
-https://twitter.com/prawn_meat/status/857444039833944064
-
-notifications
-https://twitter.com/WTMMP/status/1259694226595610629
-
-all robot & computers
-https://twitter.com/cryptcrier/status/1238339418160680960
-
-the wet world
-https://twitter.com/TragicAllyHere/status/1137187876507140098
-
-a purchase?
-https://twitter.com/pant_leg/status/1027693563604230144
-
-influencer
-https://twitter.com/witchpuppy/status/974690828257054721
-
--Wint-conversion
-https://twitter.com/jckarter/status/967802665080995840
diff --git a/www/causal.agency/.gitignore b/www/causal.agency/.gitignore
index 7935a3c1..b00b1c3c 100644
--- a/www/causal.agency/.gitignore
+++ b/www/causal.agency/.gitignore
@@ -1,3 +1,4 @@
-*.html
+index.html
+leveler.html
 scheme.css
 scheme.png
diff --git a/www/causal.agency/Makefile b/www/causal.agency/Makefile
index 75849db0..8c74f8f1 100644
--- a/www/causal.agency/Makefile
+++ b/www/causal.agency/Makefile
@@ -1,11 +1,14 @@
 WEBROOT = /var/www/causal.agency
 
-FILES = index.html style.css scheme.css scheme.png
+GEN = index.html scheme.css scheme.png
+FILES = ${GEN} style.css alpha.html lands.html
 
 all: ${FILES}
 
-index.html: index.7
-	mandoc -T html -O style=style.css index.7 > index.html
+.SUFFIXES: .7 .html
+
+.7.html:
+	mandoc -T html -O style=style.css $< > $@
 
 scheme.css:
 	scheme -st > scheme.css
@@ -17,4 +20,4 @@ install: ${FILES}
 	install -C -m 644 ${FILES} ${WEBROOT}
 
 clean:
-	rm -f index.html scheme.css scheme.png
+	rm -f ${GEN}
diff --git a/www/causal.agency/alpha.html b/www/causal.agency/alpha.html
new file mode 100644
index 00000000..0d83f530
--- /dev/null
+++ b/www/causal.agency/alpha.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>all 26 letters of the alphabet RANKED</title>
+<style>
+body, button { font-size: 200%; text-align: center; }
+button { margin: 1em; padding: 1ch; }
+button#shuffle { font-size: 100%; }
+</style>
+
+which letter do you like more?
+<p>
+<button id="a">A</button>
+<button id="b">B</button>
+<p>
+<details>
+<summary>current ranking</summary>
+<p>
+<span id="ranking">ABCDEFGHIJKLMNOPQRSTUVWXYZ</span>
+<p>
+<button id="shuffle">reshuffle</button>
+</details>
+
+<script>
+let buttonA = document.getElementById("a");
+let buttonB = document.getElementById("b");
+let ranking = document.getElementById("ranking");
+
+let alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
+let rand = (bound) => Math.floor(Math.random() * bound);
+function shuffle() {
+	for (let i = alpha.length - 1; i > 0; --i) {
+		let j = rand(i + 1);
+		let x = alpha[i];
+		alpha[i] = alpha[j];
+		alpha[j] = x;
+	}
+}
+if (localStorage.getItem("alpha")) {
+	alpha = localStorage.getItem("alpha").split("");
+} else {
+	shuffle();
+}
+
+let index = 0;
+let even = true;
+function choose(o) {
+	if (o == "b") {
+		let x = alpha[index];
+		alpha[index] = alpha[index + 1];
+		alpha[index + 1] = x;
+	}
+	index += 2;
+	if (index > alpha.length - 2) {
+		even = !even;
+		index = (even ? 0 : 1);
+	}
+	update();
+}
+
+document.onkeydown = function(event) {
+	if (event.key.toUpperCase() == alpha[index]) {
+		choose("a");
+	} else if (event.key.toUpperCase() == alpha[index + 1]) {
+		choose("b");
+	}
+}
+
+function update() {
+	localStorage.setItem("alpha", alpha.join(""));
+	ranking.innerText = alpha.join("");
+	let a = buttonA;
+	let b = buttonB;
+	if (rand(2)) {
+		a = buttonB;
+		b = buttonA;
+	}
+	let lc = (c) => c;
+	if (rand(2)) lc = (c) => c.toLowerCase();
+	a.innerText = lc(alpha[index]);
+	b.innerText = lc(alpha[index + 1]);
+	a.onclick = () => choose("a");
+	b.onclick = () => choose("b");
+}
+update();
+
+document.getElementById("shuffle").onclick = function() {
+	if (confirm("Are you SURE you want to throw away all your hard work?")) {
+		shuffle();
+		update();
+	}
+}
+</script>
diff --git a/www/causal.agency/index.7 b/www/causal.agency/index.7
index c270f477..1e019574 100644
--- a/www/causal.agency/index.7
+++ b/www/causal.agency/index.7
@@ -1,10 +1,10 @@
-.Dd November  3, 2021
+.Dd April 18, 2024
 .Dt CAUSAL.AGENCY 7
 .Os "Causal Agency"
 .
 .Sh NAME
 .Nm june
-.Nd computer enthusiast (her)
+.Nd computer enthusiast (she/her)
 .
 .Sh SYNOPSIS
 .Nm mail
@@ -29,6 +29,8 @@ and experience more magic.
 \(em
 .Lk https://text.causal.agency words
 \(em
+.Lk https://photo.causal.agency photos
+\(em
 .Lk /list/ mailist
 .
 .Pp
@@ -42,7 +44,7 @@ a cosy IRC client
 a full-text search IRC logger
 .It Lk https://git.causal.agency/scooper/about scooper
 a web interface for litterbox
-.It Lk https://git.causal.agency/catsit/about catsit
+.It Lk https://git.causal.agency/kitd/about kitd
 a process supervisor
 .It Lk https://git.causal.agency/imbox/about "imbox & git-fetch-email"
 a tool to pull patches out of IMAP
@@ -64,4 +66,11 @@ an earthy terminal colour scheme
 .El
 .
 .Sh SEE ALSO
+.Bl -bullet
+.It
 .Lk /bin/ bin
+.It
+.Lk lands.html "Magic lands quiz"
+.It
+.Lk alpha.html "alphabet ranking game"
+.El
diff --git a/www/causal.agency/lands.html b/www/causal.agency/lands.html
new file mode 100644
index 00000000..7aaadd80
--- /dev/null
+++ b/www/causal.agency/lands.html
@@ -0,0 +1,176 @@
+<!DOCTYPE html>
+<title>Lands Quiz</title>
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<style>
+html { font: 14pt sans-serif; line-height: 1.5em; }
+body { padding: 1em 1ch; max-width: 78ch; margin: auto; }
+h1 { text-align: center; }
+h2 { margin-top: 0; }
+button { font-size: 100%; padding: 0.5em 1ch; }
+img { max-width: 100%; }
+div.cols { display: grid; grid-template-columns: 1fr 1fr; gap: 2ch; }
+</style>
+
+<h1 id="loading">Loading...</h1>
+<h1 id="error" hidden>Failed to load cards :(</h1>
+
+<div id="game" hidden>
+<h1>Magic Lands Quiz</h1>
+<p>Try to guess the colours of mana each land produces!</p>
+<div class="cols">
+	<div>
+		<img id="back" src="https://backs.scryfall.io/normal/0/a/0aeebaf5-8c7d-4636-9e82-8c27447861f7.jpg">
+		<a id="link" target="_blank">
+			<img id="image1" hidden>
+			<img id="image2" hidden>
+		</a>
+	</div>
+	<div>
+		<h2 id="name"></h2>
+		<input type="checkbox" id="w"> <label for="w">White</label><br>
+		<input type="checkbox" id="u"> <label for="u">Blue</label><br>
+		<input type="checkbox" id="b"> <label for="b">Black</label><br>
+		<input type="checkbox" id="r"> <label for="r">Red</label><br>
+		<input type="checkbox" id="g"> <label for="g">Green</label><br>
+		<p><button id="submit">Submit</button></p>
+		<h3>Score: <span id="score">0</span>/<span id="total">0</span></h3>
+	</div>
+</div>
+</div>
+
+<script>
+function shuffle(arr) {
+	let rand = (bound) => Math.floor(Math.random() * bound);
+	for (let i = arr.length-1; i > 0; --i) {
+		let j = rand(i+1);
+		let x = arr[i];
+		arr[i] = arr[j];
+		arr[j] = x;
+	}
+}
+
+const CardBack =
+"https://backs.scryfall.io/normal/0/a/0aeebaf5-8c7d-4636-9e82-8c27447861f7.jpg";
+
+function hideCard() {
+	document.getElementById("back").hidden = false;
+	document.getElementById("image1").hidden = true;
+	document.getElementById("image2").hidden = true;
+}
+
+function showCard(card) {
+	document.getElementById("back").hidden = true;
+	document.getElementById("link").href = card.scryfall_uri;
+	let image1 = document.getElementById("image1");
+	let image2 = document.getElementById("image2");
+	if (card.card_faces) {
+		image1.src = card.card_faces[0].image_uris.normal;
+		image2.src = card.card_faces[1].image_uris.normal;
+		image1.hidden = false;
+		image2.hidden = false;
+	} else {
+		image1.src = card.image_uris.normal;
+		image1.hidden = false;
+	}
+}
+
+function resetChecks() {
+	for (let c of "wubrg") {
+		let input = document.getElementById(c);
+		input.checked = false;
+		input.disabled = false;
+		input.labels[0].style.fontWeight = "normal";
+	}
+}
+
+function checkChecks(card) {
+	let score = 0;
+	let total = 0;
+	let checked = 0;
+	for (let c of "wubrg") {
+		let input = document.getElementById(c);
+		let produced = card.produced_mana.includes(c.toUpperCase());
+		if (produced) {
+			total++;
+			input.labels[0].style.fontWeight = "bold";
+			if (input.checked) score++;
+		}
+		if (input.checked) checked++;
+		input.disabled = true;
+	}
+	if (checked > total) score -= (checked - total);
+	if (score < 0) score = 0;
+	return { score: score, total: total };
+}
+
+document.onkeydown = function(event) {
+	for (let c of "wubrg") {
+		if (event.key == c) {
+			let input = document.getElementById(c);
+			if (!input.disabled) input.checked ^= true;
+		}
+	}
+	if (event.key == "Enter") {
+		document.getElementById("submit").click();
+	}
+}
+
+let score = 0;
+let total = 0;
+let cards = [];
+let card = null;
+
+function nextCard() {
+	hideCard();
+	resetChecks();
+	card = cards.shift();
+	document.getElementById("name").innerText = card.name;
+}
+
+document.getElementById("submit").onclick = function() {
+	if (card) {
+		let { score: cardScore, total: cardTotal } = checkChecks(card);
+		total += cardTotal;
+		score += cardScore;
+		document.getElementById("score").innerText = score;
+		document.getElementById("total").innerText = total;
+		showCard(card);
+		card = null;
+		if (cards.length) {
+			this.innerText = "Next card";
+		} else {
+			this.disabled = true;
+			this.innerText = "No more cards";
+		}
+	} else {
+		nextCard();
+		this.innerText = "Submit";
+	}
+}
+
+function loadCards(resp) {
+	let loading = document.getElementById("loading");
+	let error = document.getElementById("error");
+	let game = document.getElementById("game");
+	if (resp.status != 200) {
+		loading.hidden = true;
+		error.hidden = false;
+	}
+	resp.json().then((json) => {
+		cards.push(...json.data);
+		if (json.has_more) {
+			setTimeout(() => fetch(json.next_page).then(loadCards), 50);
+		} else {
+			loading.hidden = true;
+			game.hidden = false;
+			shuffle(cards);
+			nextCard();
+		}
+	});
+}
+
+const Search =
+"https://api.scryfall.com/cards/search?q=t:land+id>=2+produces>=2+produces!=wubrg";
+fetch(Search).then(loadCards);
+
+</script>
diff --git a/www/causal.agency/style.css b/www/causal.agency/style.css
index 368d8da1..265c62c2 100644
--- a/www/causal.agency/style.css
+++ b/www/causal.agency/style.css
@@ -11,6 +11,11 @@ dl.Bl-diag > dt { font-weight: bold; }
 code.Nm, code.Fl, code.Cm, code.Ic, code.In, code.Fd, code.Fn,
 code.Cd { font-weight: bold; font-family: inherit; }
 
+div.head, div.foot { display: flex; justify-content: space-between; }
+.head-ltitle, .foot-date { flex: 1; }
+.head-vol { flex: 0 1 auto; text-align: center; }
+.head-rtitle, .foot-os { flex: 1; text-align: right; }
+
 html { font-family: monospace; line-height: 1.25em; }
 body { max-width: 80ch; margin: 1em auto; padding: 0 1ch; }
 table { border-collapse: collapse; }
diff --git a/www/git.causal.agency/.gitignore b/www/git.causal.agency/.gitignore
index 25e26cc8..eaed8039 100644
--- a/www/git.causal.agency/.gitignore
+++ b/www/git.causal.agency/.gitignore
@@ -1,3 +1,4 @@
+*.html
 about-filter
 compress
 ctags
diff --git a/www/git.causal.agency/Makefile b/www/git.causal.agency/Makefile
index f05d4a4a..86b9f3eb 100644
--- a/www/git.causal.agency/Makefile
+++ b/www/git.causal.agency/Makefile
@@ -2,6 +2,7 @@ PREFIX = /var/www
 CONFDIR = ${PREFIX}/conf
 DATADIR = ${PREFIX}/cgit
 BINDIR = ${PREFIX}/bin
+WEBROOT = ${PREIFX}/git.causal.agency
 
 CFLAGS += -Wall -Wextra
 LDFLAGS = -static -pie
@@ -17,7 +18,9 @@ BINS += mtags
 BINS += owner-filter
 BINS += source-filter
 
-all: ${BINS}
+HTMLS = index.html
+
+all: ${BINS} ${HTMLS}
 
 compress ctags mandoc:
 	${MAKE} -C /usr/src/usr.bin/$@ LDFLAGS='${LDFLAGS}'
@@ -35,12 +38,16 @@ hilex htagml mtags:
 about-filter email-filter owner-filter source-filter: filter
 	ln -f filter $@
 
+index.html: index.7
+	mandoc -Thtml -Ostyle=https://causal.agency/style.css index.7 >index.html
+
 install: cgitrc custom.css ${BINS}
 	install -m 644 cgitrc ${CONFDIR}
 	install -m 644 custom.css ${DATADIR}
 	install -d -o www -g daemon ${PREFIX}/cache/cgit
 	install -d -m 1700 -o www -g daemon ${PREFIX}/tmp
 	install -s ${BINS} ${BINDIR}
+	install -m 644 ${HTMLS} ${WEBROOT}
 
 clean:
-	rm -f compress filter ${BINS}
+	rm -f compress filter ${BINS} ${HTMLS}
diff --git a/www/git.causal.agency/filter.c b/www/git.causal.agency/filter.c
index 9ed9ee17..7c7e9320 100644
--- a/www/git.causal.agency/filter.c
+++ b/www/git.causal.agency/filter.c
@@ -32,12 +32,8 @@ static int email(void) {
 	size_t cap = 0;
 	char *buf = NULL;
 	if (getline(&buf, &cap, stdin) < 0) err(1, "getline");
-	long x = 1;
-	for (char *ch = buf; *ch && *ch != ' '; ++ch) {
-		x *= *ch;
-	}
-	if (buf[0] == 'C' && x == 1251729952200L) {
-		printf("C.%s", buf + strcspn(buf, " "));
+	if (buf[0] == 'C' && !strncmp(&buf[strcspn(buf, " ")], " McEnroe", 8)) {
+		printf("June%s", &buf[strcspn(buf, " ")]);
 	} else {
 		printf("%s", buf);
 	}
@@ -143,6 +139,7 @@ static int source(int argc, char *argv[]) {
 }
 
 int main(int argc, char *argv[]) {
+#ifdef __OpenBSD__
 	int error;
 	switch (getprogname()[0]) {
 		break; case 'a': error = pledge("stdio exec", NULL);
@@ -150,6 +147,7 @@ int main(int argc, char *argv[]) {
 		break; default:  error = pledge("stdio", NULL);
 	}
 	if (error) err(1, "pledge");
+#endif
 	switch (getprogname()[0]) {
 		case 'a': return about(argc, argv);
 		case 'e': return email();
diff --git a/www/git.causal.agency/index.7 b/www/git.causal.agency/index.7
new file mode 100644
index 00000000..58a40dfe
--- /dev/null
+++ b/www/git.causal.agency/index.7
@@ -0,0 +1,81 @@
+.Dd January 12, 2024
+.Dt GIT.CAUSAL.AGENCY 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm causal agency
+.Nd \(dqI think some people from the Gentoo project are behind this.\(dq
+.
+.Sh DESCRIPTION
+basically cgit (awful software)
+getting hammered by web crawlers
+keeps making my machine crash.
+this static page will be here
+until I can find a better solution.
+clone urls and tarball urls are still functional.
+.
+.Bl -tag
+.It src \(em dontfiles
+.Dl git clone https://git.causal.agency/src
+.It ascii.town
+.Bl -tag
+.It torus \(em collaborative ASCII art
+.Dl git clone https://git.causal.agency/torus
+.It play \(em some games for SSH
+.Dl git clone https://git.causal.agency/play
+.El
+.It email
+.Bl -tag
+.It imbox \(em IMAP to mbox
+.Dl git clone https://git.causal.agency/imbox
+.It bubger \(em IMAP archive generator
+.Dl git clone https://git.causal.agency/bubger
+.It notemap \(em notemap
+.Dl git clone https://git.causal.agency/notemap
+.El
+.It forks
+.Bl -tag
+.It shulker \(em Discord to vanilla Minecraft bridge
+.Dl git clone https://git.causal.agency/shulker
+.It cgit-pink \(em web frontend for git
+.Dl git clone https://git.causal.agency/cgit-pink
+.It dash \(em patched shell with cmake build
+.Dl git clone https://git.causal.agency/dash
+.El
+.It games
+.Bl -tag
+.It wep \(em Windows Entertainment Pack recreations
+.Dl git clone https://git.causal.agency/wep
+.It cards \(em CARDS.DLL loader for SDL
+.Dl git clone https://git.causal.agency/cards
+.El
+.It irc
+.Bl -tag
+.It scooper \(em web interface for litterbox
+.Dl git clone https://git.causal.agency/scooper
+.It litterbox \(em IRC logger
+.Dl git clone https://git.causal.agency/litterbox
+.It pounce \(em IRC bouncer
+.Dl git clone https://git.causal.agency/pounce
+.It catgirl \(em IRC client
+.Dl git clone https://git.causal.agency/catgirl
+.El
+.It ports
+.Bl -tag
+.It jorts \(em my own ports tree for macOS
+.Dl git clone https://git.causal.agency/jorts
+.It exman \(em manuals for other systems
+.Dl git clone https://git.causal.agency/exman
+.It libretls \(em libtls for OpenSSL
+.Dl git clone https://git.causal.agency/libretls
+.It ports \(em Fx and Ox ports for this software
+.Dl git clone https://git.causal.agency/ports
+.El
+.It system
+.Bl -tag
+.It kitd \(em process supervisor for OpenBSD
+.Dl git clone https://git.causal.agency/kitd
+.It catsit \(em (deprecated) process supervisor
+.Dl git clone https://git.causal.agency/catsit
+.El
+.El
diff --git a/www/photo.causal.agency/.gitignore b/www/photo.causal.agency/.gitignore
new file mode 100644
index 00000000..a5f66a9d
--- /dev/null
+++ b/www/photo.causal.agency/.gitignore
@@ -0,0 +1,2 @@
+static/
+*.JPG
diff --git a/www/photo.causal.agency/2024-04-10/IMG_0832.txt b/www/photo.causal.agency/2024-04-10/IMG_0832.txt
new file mode 100644
index 00000000..65724024
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-10/IMG_0832.txt
@@ -0,0 +1,6 @@
+a red brick wall with some faded black graffiti.
+in the lower third, some bricks are missing
+from the outer layer in an arc shape.
+along the bottom is a ledge of conrete
+lightly covered in brick dust and chunks
+below the missing areas above.
diff --git a/www/photo.causal.agency/2024-04-10/IMG_0850.txt b/www/photo.causal.agency/2024-04-10/IMG_0850.txt
new file mode 100644
index 00000000..4cbb3def
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-10/IMG_0850.txt
@@ -0,0 +1,6 @@
+grey steel beams of a building in early construction
+on a background of blue sky with some light clouds.
+the beams are intersecting at odd points,
+implying the final building will not be a simple box.
+the sun casts dark shadows into the interiors
+of the I-shaped metal.
diff --git a/www/photo.causal.agency/2024-04-10/IMG_0852.txt b/www/photo.causal.agency/2024-04-10/IMG_0852.txt
new file mode 100644
index 00000000..707d7cd6
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-10/IMG_0852.txt
@@ -0,0 +1,4 @@
+in the foreground, a metal construction fence.
+behind that, the bright red arm of a sort of small crane.
+the arm is horizontal and crushing a perpendicular piece of fence,
+which has deformed smoothly under it.
diff --git a/www/photo.causal.agency/2024-04-10/IMG_0858.txt b/www/photo.causal.agency/2024-04-10/IMG_0858.txt
new file mode 100644
index 00000000..42f243e4
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-10/IMG_0858.txt
@@ -0,0 +1,6 @@
+an uneven grid of old wooden-framed windows in an alley.
+the red paint on the frames is peeling badly,
+completely stripped in some spots.
+in the reflections of the lower windows
+we see the roofs of the opposite buildings
+and hints of clouds in the sky.
diff --git a/www/photo.causal.agency/2024-04-10/IMG_0859.txt b/www/photo.causal.agency/2024-04-10/IMG_0859.txt
new file mode 100644
index 00000000..ca33d7e0
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-10/IMG_0859.txt
@@ -0,0 +1,6 @@
+an old backetball hoop mounted in an alley.
+the backboard has been graffitied
+and vines have invaded.
+a few red strands of net are left hanging from the hoop.
+the fence behind is painted with a design of yellow, purple, white and blue.
+it's the kind of hoop airbud might be hanging around.
diff --git a/www/photo.causal.agency/2024-04-10/IMG_0865.txt b/www/photo.causal.agency/2024-04-10/IMG_0865.txt
new file mode 100644
index 00000000..7a955fc2
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-10/IMG_0865.txt
@@ -0,0 +1,2 @@
+deep tire tread pressed into mud in the center of an alley.
+a small branch of evergreen lies to one side.
diff --git a/www/photo.causal.agency/2024-04-10/IMG_0890.txt b/www/photo.causal.agency/2024-04-10/IMG_0890.txt
new file mode 100644
index 00000000..9d2cdc43
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-10/IMG_0890.txt
@@ -0,0 +1,9 @@
+a pipe coming out of a light brown brick wall.
+the pipe comes out of a metal square in the centre of the wall,
+travels up and left for a bit,
+before continuing straight up out of frame.
+opposite, in the bottom right,
+is the top of a red metal grate in front
+of a ground-level window.
+the brick below where the pipe enters the wall
+is stained dark.
diff --git a/www/photo.causal.agency/2024-04-14/IMG_1054.txt b/www/photo.causal.agency/2024-04-14/IMG_1054.txt
new file mode 100644
index 00000000..f4803ee2
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-14/IMG_1054.txt
@@ -0,0 +1,5 @@
+a short wall of natural rock,
+all broken up somewhat neatly
+along horizontal and vertical lines.
+most of the rock is cool grey,
+while some parts are warm brown.
diff --git a/www/photo.causal.agency/2024-04-14/IMG_1058.txt b/www/photo.causal.agency/2024-04-14/IMG_1058.txt
new file mode 100644
index 00000000..21aeb189
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-14/IMG_1058.txt
@@ -0,0 +1,6 @@
+moss on a bit of exposed natural rock
+surrounded by mostly brown grass.
+there is shorter, darker green and brown moss,
+as well as longer lighter green moss.
+some small pieces of the rock are broken off
+and lay in little piles.
diff --git a/www/photo.causal.agency/2024-04-14/IMG_1066.txt b/www/photo.causal.agency/2024-04-14/IMG_1066.txt
new file mode 100644
index 00000000..81747287
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-14/IMG_1066.txt
@@ -0,0 +1,10 @@
+two green buds on the end of a thin branch
+on a blurry brown backdrop.
+the branch enters the frame
+from the bottom left corner,
+and there are three other pairs of buds
+along it,
+out of focus.
+there is a hint of another bebudded branch
+in the background,
+but there is otherwise very little green.
diff --git a/www/photo.causal.agency/2024-04-19/IMG_1158.txt b/www/photo.causal.agency/2024-04-19/IMG_1158.txt
new file mode 100644
index 00000000..e18bd6c7
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-19/IMG_1158.txt
@@ -0,0 +1,6 @@
+a glowing amber street lamp
+affixed to a telephone pole.
+across its round top
+there is peeling grey-brown paint.
+the lamp is surrounded
+by out of focus bare tree branches.
diff --git a/www/photo.causal.agency/2024-04-20/IMG_1225.txt b/www/photo.causal.agency/2024-04-20/IMG_1225.txt
new file mode 100644
index 00000000..525a4bf3
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-20/IMG_1225.txt
@@ -0,0 +1,8 @@
+close up of a squirrel atop a dark wood fence.
+its tail is curled on its back
+and it's facing left but looking at the camera.
+there are crumbs of dirt
+around its mouth and whiskers.
+you can see the little claws
+of its front paw in the foreground,
+while the other paw is curled to its chest.
diff --git a/www/photo.causal.agency/2024-04-20/IMG_1234.txt b/www/photo.causal.agency/2024-04-20/IMG_1234.txt
new file mode 100644
index 00000000..faee1be9
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-20/IMG_1234.txt
@@ -0,0 +1,8 @@
+a pigeon standing upright on some concrete.
+it's a usual grey city pigeon,
+with a mix of light and dark feathers
+on its wings,
+purple and green areas up its neck,
+and red feet.
+in the blurred background
+another pigeon is strutting past.
diff --git a/www/photo.causal.agency/2024-04-20/IMG_1245.txt b/www/photo.causal.agency/2024-04-20/IMG_1245.txt
new file mode 100644
index 00000000..c971da91
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-20/IMG_1245.txt
@@ -0,0 +1,17 @@
+a tall shot of the back of a beautifully coloured building.
+the brick wall has been painted a sort of pink,
+or at least it's faded to that colour.
+there is a splotch in the middle
+where the paint has worn off the brick,
+along with some stray bricks
+elsewhere that have been replaced.
+the spiral stairs descending
+from the back balconies of two floors
+have also been painted red,
+but have faded to pink
+closer to the top.
+everything is a little crooked.
+the old wooden-framed windows
+on the left,
+the more recently replaced doors,
+and the balconies.
diff --git a/www/photo.causal.agency/2024-04-20/IMG_1253.txt b/www/photo.causal.agency/2024-04-20/IMG_1253.txt
new file mode 100644
index 00000000..5158c533
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-20/IMG_1253.txt
@@ -0,0 +1,7 @@
+a CCTV camera on the corner
+of a black corrugated metal building.
+it's mounted on a beige rusting bracket
+coming off the wall at a right angle.
+it's an old-style boxy camera
+with a little hood.
+who knows if it's still connected to anything?
diff --git a/www/photo.causal.agency/2024-04-20/IMG_1254.txt b/www/photo.causal.agency/2024-04-20/IMG_1254.txt
new file mode 100644
index 00000000..4780f8b5
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-20/IMG_1254.txt
@@ -0,0 +1,8 @@
+a white pigeon walking in a paved alley.
+its visible eye is a beautiful dark orange,
+slightly lighter around its pupil.
+its mostly white plumage
+is dotted here and there by darker feathers,
+and its tail feathers in particular are dark.
+there's a hint of small green feathers
+around its neck.
diff --git a/www/photo.causal.agency/2024-04-30/IMG_1619.txt b/www/photo.causal.agency/2024-04-30/IMG_1619.txt
new file mode 100644
index 00000000..27f87311
--- /dev/null
+++ b/www/photo.causal.agency/2024-04-30/IMG_1619.txt
@@ -0,0 +1,8 @@
+the seat of a rusted metal stool out in the way
+with a shallow pool of water on it.
+in the center is a handle-shaped hole,
+which is raised slightly,
+causing the water to pool further
+around the edges.
+there is a single fallen light green tree bud
+just near the hole.
diff --git a/www/photo.causal.agency/generate.sh b/www/photo.causal.agency/generate.sh
new file mode 100644
index 00000000..4b30db92
--- /dev/null
+++ b/www/photo.causal.agency/generate.sh
@@ -0,0 +1,211 @@
+#!/bin/sh
+set -eu
+
+mkdir -p static/preview static/thumbnail
+
+resize() {
+	local photo=$1 size=$2 output=$3
+	if ! test -f $output; then
+		# FIXME: convert complains about not understanding XML
+		echo $output >&2
+		convert $photo -auto-orient -thumbnail $size $output 2>/dev/null ||:
+	fi
+}
+
+preview() {
+	local photo=$1
+	local preview=preview/${photo##*/}
+	resize $photo 25% static/$preview
+	echo $preview
+}
+
+thumbnail() {
+	local photo=$1
+	local thumbnail=thumbnail/${photo##*/}
+	resize $photo 5% static/$thumbnail
+	echo $thumbnail
+}
+
+encode() {
+	sed '
+		s/&/\&amp;/g
+		s/</\&lt;/g
+		s/"/\&quot;/g
+	' "$@"
+}
+
+page_title() {
+	date -j -f '%F' $1 '+%B %e, %Y'
+}
+
+page_head() {
+	local date=$1
+	local title=$(page_title $date)
+	cat <<-EOF
+	<!DOCTYPE html>
+	<meta charset="utf-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1.0">
+	<link rel="alternate" type="application/atom+xml" href="../feed.atom">
+	<title>${title}</title>
+	<style>
+	html { color: #bbb; background-color: black; font-family: sans-serif; }
+	figure { margin: 1em; padding-top: 0.5em; text-align: center; }
+	img { max-width: calc(100vw - 2.5em); max-height: calc(100vh - 2.5em); }
+	details { max-width: 78ch; margin: 0.5em auto; }
+	</style>
+	<h1>${title}</h1>
+	EOF
+}
+
+photo_info() {
+	local photo=$1
+	ExposureTime=
+	FNumber=
+	FocalLength=
+	PhotographicSensitivity=
+	eval $(
+		identify -format '%[EXIF:*]' $photo 2>/dev/null |
+		grep -E 'ExposureTime|FNumber|FocalLength|PhotographicSensitivity' |
+		sed 's/^exif://'
+	)
+}
+
+photo_id() {
+	local photo=$1
+	photo=${photo##*/}
+	photo=${photo%%.*}
+	echo $photo
+}
+
+page_photo() {
+	local photo=$1 preview=$2 description=$3
+	if ! test -f $description; then
+		description=/dev/null
+	fi
+	photo_info $photo
+	cat <<-EOF
+	<figure id="$(photo_id $photo)">
+		<a href="${photo##*/}">
+			<img src="../${preview}" alt="$(encode $description)">
+		</a>
+		<figcaption>
+			${ExposureTime} ·
+			ƒ/$(bc -S 1 -e ${FNumber}) ·
+			$(bc -e ${FocalLength}) mm ·
+			${PhotographicSensitivity} ISO
+			<details>
+				<summary>description</summary>
+				$(encode $description)
+			</details>
+		</figcaption>
+	</figure>
+	EOF
+}
+
+index_head() {
+	cat <<-EOF
+	<!DOCTYPE html>
+	<meta charset="utf-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1.0">
+	<link rel="alternate" type="application/atom+xml" href="feed.atom">
+	<title>Photos</title>
+	<style>
+	html { color: #bbb; background-color: black; font-family: sans-serif; }
+	a { text-decoration: none; color: inherit; }
+	</style>
+	EOF
+}
+
+index_page() {
+	local date=$1 root=${2:-}
+	cat <<-EOF
+	<h1><a href="${root}${root:+/}${date}/">$(page_title $date)</a></h1>
+	EOF
+}
+
+index_photo() {
+	local date=$1 photo=$2 thumbnail=$3 root=${4:-}
+	cat <<-EOF
+	<a href="${root}${root:+/}${date}/#$(photo_id $photo)">
+		<img src="${root}${root:+/}${thumbnail}">
+	</a>
+	EOF
+}
+
+Root=https://photo.causal.agency
+
+atom_head() {
+	local updated=$(date -u '+%FT%TZ')
+	cat <<-EOF
+	<?xml version="1.0" encoding="utf-8"?>
+	<feed xmlns="http://www.w3.org/2005/Atom">
+	<title>Photos</title>
+	<author><name>june</name><email>june@causal.agency</email></author>
+	<link href="${Root}"/>
+	<link rel="self" href="${Root}/feed.atom"/>
+	<id>${Root}/</id>
+	<updated>${updated}</updated>
+	EOF
+}
+
+atom_entry_head() {
+	local date=$1
+	local updated=$(
+		date -ju -f '%s' $(stat -f '%m' static/${date}/index.html) '+%FT%TZ'
+	)
+	cat <<-EOF
+	<entry>
+	<title>$(page_title $date)</title>
+	<link href="${Root}/${date}/"/>
+	<id>${Root}/${date}/</id>
+	<updated>${updated}</updated>
+	<content type="html">
+	EOF
+}
+
+atom_entry_tail() {
+	cat <<-EOF
+	</content>
+	</entry>
+	EOF
+}
+
+atom_tail() {
+	cat <<-EOF
+	</feed>
+	EOF
+}
+
+set --
+for date in 20*; do
+	mkdir -p static/${date}
+	page=static/${date}/index.html
+	if ! test -f $page; then
+		echo $page >&2
+		page_head $date >$page
+		for photo in ${date}/*.JPG; do
+			preview=$(preview $photo)
+			if ! test -f static/${photo}; then
+				ln $photo static/${photo}
+			fi
+			page_photo $photo $preview ${photo%.JPG}.txt >>$page
+		done
+	fi
+	set -- $date "$@"
+done
+
+echo static/index.html >&2
+index_head >static/index.html
+echo static/feed.atom >&2
+atom_head >static/feed.atom
+for date; do
+	index_page $date >>static/index.html
+	atom_entry_head $date >>static/feed.atom
+	for photo in ${date}/*.JPG; do
+		thumbnail=$(thumbnail $photo)
+		index_photo $date $photo $thumbnail >>static/index.html
+		index_photo $date $photo $thumbnail $Root | encode >>static/feed.atom
+	done
+	atom_entry_tail >>static/feed.atom
+done
+atom_tail >>static/feed.atom
diff --git a/www/photo.causal.agency/rsync.sh b/www/photo.causal.agency/rsync.sh
new file mode 100644
index 00000000..957911d2
--- /dev/null
+++ b/www/photo.causal.agency/rsync.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+set -eu
+
+sh generate.sh
+rsync -av static/ scout:/var/www/photo.causal.agency
diff --git a/www/temp.causal.agency/up.c b/www/temp.causal.agency/up.c
index 4b83b564..561a8901 100644
--- a/www/temp.causal.agency/up.c
+++ b/www/temp.causal.agency/up.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2020  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2020  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
diff --git a/www/text.causal.agency/037-care.7 b/www/text.causal.agency/037-care.7
index 83fef1dd..052a4727 100644
--- a/www/text.causal.agency/037-care.7
+++ b/www/text.causal.agency/037-care.7
@@ -27,6 +27,10 @@ Prices obviously change,
 by which I mean they inevitably go up,
 but I'm gonna give the amounts I paid
 in 2021\(en2022.
+Also if you want more details
+about any of this
+please email me.
+I will be happy to tell you all about it.
 .
 .Ss Medication
 I get HRT through
@@ -65,21 +69,27 @@ for my current prescription
 on the public plan.
 .
 .Ss Hair removal
-I've gotten laser hair removal treatments
-at Dermamode with Audrey.
-They're very nice there.
-The initial consultation was over the phone.
-I paid $1350 for 6 treatments,
-in two installments
-at the first and second appointments,
-plus the ~$200 tax on that
-before the first appointment,
-I think.
-It hasn't gone well for me so far,
-but I'm hoping it will
-now that my testosterone levels
-have dropped.
-I will report back.
+I tried laser hair removal,
+for longer than I should have.
+It was a waste of time and money.
+Do not believe any arguments about
+its convenience over electrolysis.
+.
+.Pp
+I've started getting electrolysis done
+with Dimi.
+Again,
+feel free to email me for contact info.
+He is very good and can do long sessions.
+I really don't find it very painful,
+which I think is partly my own pain tolerance
+and partly good equipment and skill.
+I've also found that taking acetaminophen beforehand
+and dressing warmly to keep my body relaxed help.
+I've paid $85 for hour-long sessions
+and $160 for two-hour sessions.
+I'm still early in treatment,
+but I'm really happy with the results so far!
 .
 .Ss Sex & name change
 The form for this is
@@ -101,7 +111,8 @@ so I made a donation to P10.
 .
 .Pp
 I paid $144 to file mine
-but it's now $148.
+but it's now FREE
+the first time you do it.
 Also $17 to mail it.
 Surprisingly,
 I got an acknowledgment letter
@@ -140,10 +151,7 @@ if I find one.
 Ok I know this isn't trans-specific
 but at least for me getting piercings
 was gender-affirming.
-And I don't mean like
-getting your ears pierced
-is some kind of female rite of passage,
-because that's not even what I got done.
+Cuz I got nipple piercings lol.
 Anyway,
 I went to Mauve.
 They're super nice,
diff --git a/www/text.causal.agency/039-apologies.7 b/www/text.causal.agency/039-apologies.7
new file mode 100644
index 00000000..1b15076a
--- /dev/null
+++ b/www/text.causal.agency/039-apologies.7
@@ -0,0 +1,81 @@
+.Dd September 19, 2022
+.Dt APOLOGIES 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Apologies
+.Nd making them
+.
+.Sh DESCRIPTION
+Apologies are very important to me.
+Unfortunately
+I've only recently realized
+how valuable they are.
+I've tried to think about
+what makes a good apology,
+since it's not something
+I was ever taught.
+This is the advice
+I came up with for myself,
+on how to apologize.
+.
+.Bl -enum
+.It
+Make the apology.
+This is the most important part.
+If you feel guilty
+for something you've done,
+or think you might have hurt someone,
+apologize.
+Even if they don't need an apology,
+saying sorry won't hurt.
+And start with that.
+Literally say
+.Dq I'm sorry .
+Sometimes people forget that.
+.Pp
+On the other side,
+if you've been hurt by someone,
+and you trust them,
+let them know.
+Give them a chance to apologize.
+People don't always realize
+they've made a mistake.
+.
+.It
+Explain what you did wrong.
+I think it's important
+for the other person
+to know you understand
+how you've messed up.
+Really think about this!
+It's what will help you learn.
+If you know you've hurt someone
+but you're not sure why,
+you can try asking them.
+Take their answer seriously.
+.
+.It
+Don't make excuses.
+Do not talk about yourself.
+Don't even mention
+how you were feeling stressed that day,
+or whatever.
+It's not relevant.
+We all make mistakes,
+we all have bad days.
+.
+.It
+Commit to doing better.
+Try to learn from your mistakes.
+Say it won't happen again.
+Literally say
+.Dq I won't do that again .
+And then try your hardest to make that true.
+An apology is a commitment,
+not something you're done with
+once you've said it.
+.El
+.
+.Sh AUTHORS
+.An june Aq Mt june@causal.agency
diff --git a/www/text.causal.agency/040-sound-memory.7 b/www/text.causal.agency/040-sound-memory.7
new file mode 100644
index 00000000..c995de08
--- /dev/null
+++ b/www/text.causal.agency/040-sound-memory.7
@@ -0,0 +1,165 @@
+.Dd November 14, 2022
+.Dt SOUND-MEMORY 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Sound Memory
+.Nd associations
+.
+.Sh DESCRIPTION
+.Ss Talking Heads \(em "Remain In Light"
+The first time I gave this album a serious listen
+was when I was going for several-hour walks
+at 4 in the morning in,
+I think,
+fall 2020.
+I would stay up all night,
+go out walking at 4am
+for a couple hours,
+come home,
+eat
+.Dq breakfast
+and go to sleep.
+I listened to this album
+walking on completely empty
+big city streets
+in the dark.
+.
+.Ss Buffy Sainte-Marie \(em Up Where We Belong
+I started listening to this album
+after hearing it many mornings
+walking into the cafe on my block
+back in 2019.
+I could tell Vincent was working
+if I heard this when I opened the door.
+.
+.Ss Molasses \(em Trilogie: Toil & Peaceful Life
+I listened to this when I had 8am classes
+in CEGEP.
+In particular my first semester philosophy course,
+which was in the forum.
+I usually got there even earlier
+because of how the bus schedules worked out.
+There was another girl in my class,
+who I always sat next to,
+who also got there early,
+but we never spoke outside of class.
+.
+.Ss Arcade Fire \(em Funeral
+This album just feels like walking outside
+in fresh snow in early winter,
+you know?
+.
+.Ss Molasses \(em Trouble at Jinx Hotel
+I listened to this when I was looking for an apartment.
+I specifically remember listening to it
+walking down Clark toward my new place
+to pick up my keys.
+.
+.Ss Arcade Fire \(em Neon Bible
+The song
+.Dq "No Cars Go"
+is strongly associated for me
+with my earliest gender feelings.
+It's how I date when I first
+started to feel like something was wrong.
+The Suburbs was released in 2010,
+so I was probably listening to Neon Bible
+in 2011.
+Ten years between that
+and coming out.
+.
+.Ss "Do Make Say Think" \(em "You You're a History In Rust"
+I remember hearing
+.Dq "A Tender History In Rust"
+for the first time
+at the office of my first job.
+Me and my coworkers stayed late,
+probably on a Friday night,
+drinking free tech startup booze.
+.
+.Ss mewithoutYou \(em It's All Crazy! It's All False! It's All a Dream! It's Alright
+I exclusively listened to this album
+on a high school trip to Europe.
+Every morning when we got on the bus,
+I heard
+.Dq Every Thought a Thought of You
+and every night before bed
+I listened to
+.Dq The King Beetle on a Coconut Estate .
+.
+.Ss Arcade Fire \(em The Suburbs
+I listened to this album a tonne
+when I was playing
+Minecraft and Urban Terror
+with my online friends
+while I was in high school.
+In particular I remember
+a backyard shed World of Padman map
+and the apartments Minecraft world.
+.
+.Ss Arcade Fire \(em Reflektor
+I associate
+.Dq Afterlife
+with the walk between Laurier metro
+and my first job,
+in the winter.
+Must've just been how the timing worked out
+with my commute at the time.
+.
+.Ss Swans \(em To Be Kind
+I listened to this on one of my playthroughs
+of Half-Life 2.
+In particular I associate
+.Dq Bring the Sun / Toussaint L'Ouverture
+with the Water Hazard chapter.
+.
+.Ss Wrekmeister Harmonies \(em Light Falls
+For a while I put this on whenever I
+left my apartment to go somewhere
+and it was already dark,
+so probably winter.
+.
+.Ss St. Vincent \(em MASSEDUCTION
+This,
+along with the next one,
+I think were all I listened to
+on a family vacation
+to Quebec City and New Brunswick
+some years ago.
+.
+.Ss SOPHIE \(em Oil of Every Pearl's Un-Insides
+Many hours on the road
+on that family vacation.
+Two albums on repeat.
+.
+.Ss Julia Holter \(em Aviary
+This is another album
+I listened to when I was taking
+walks at 4am.
+I wasn't in a good place.
+Yet.
+.
+.Ss Beep Test \(em Laugh Track
+A tape from the first act
+at one of my favourite shows
+I've ever been to,
+at La Sotterenea
+in Suoni 2019.
+I wish I had been out already.
+.
+.Ss The Armed \(em Only Love
+The third of the albums I listened to
+on those dark walks.
+I listened to it loud,
+this album's mixing needs it.
+.
+.Ss Eliza Kavtion \(em The Rez That Summer
+A favourite local artist.
+I remember vividly the first time
+I heard her play,
+opening for Wrekmeister Harmonies
+at La Vitrola in 2018.
+.
+.Sh AUTHORS
+.An june Aq Mt june@causal.agency
diff --git a/www/text.causal.agency/041-albums-2022.7 b/www/text.causal.agency/041-albums-2022.7
new file mode 100644
index 00000000..48bd3c3d
--- /dev/null
+++ b/www/text.causal.agency/041-albums-2022.7
@@ -0,0 +1,185 @@
+.Dd December 21, 2022
+.Dt ALBUMS-2022 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm albums 2022
+.Nd review
+.
+.Sh DESCRIPTION
+it's the year-end review
+of albums I listened to.
+same as last year,
+I added any albums I got into
+this year to a playlist.
+I've actually done that
+every year since 2018.
+maybe I'll review
+those old playlists some time.
+.
+.Ss ZHAOZE \(em SUMMER INSECTS TALK ABOUT ICE (2021)
+it's a five-and-a-half-minute album!
+you can loop it however long you want.
+it's really lovely.
+.Pp
+favourite track:
+ON HORSEBACK, TO FARAWAY
+.
+.Ss KATE BUSH \(em HOUNDS OF LOVE (1985)
+first of all I do not watch that one show.
+I've known that track for a while actually.
+I mean I probably first heard the CHROMATICS cover.
+but anyway,
+I think someone mentioned this album
+on IRC at just the right time
+and I put it on.
+the second half really shines tbh.
+love a concept album.
+.Pp
+favourite tracks:
+RUNNING UP THAT HILL,
+HOUNDS OF LOVE,
+AND DREAM OF SHEEP,
+WATCHING YOU WITHOUT ME,
+THE MORNING FOG.
+.
+.Ss GODSPEED YOU! BLACK EMPEROR \(em ALL LIGHTS FUCKED ON THE HAIRY AMP DROOLING (1994)
+didn't expect to hear this probably ever.
+still wild that it finally got uploaded.
+and to be honest I'm a little mad
+that it's actually good.
+like yeah it's not a godspeed album
+but it holds up as a tape on its own.
+it's the kind of shit I listen to.
+also can't believe some people
+still thought it was fake.
+like have you not heard
+any other efrim menuck projects?
+.Pp
+favourite tracks:
+$13.13,
+DIMINISHING SHINE,
+DADMOMDADDY,
+333 FRAMES PER SECOND,
+ALL ANGELS GONE.
+.
+.Ss BLACK DRESSES \(em FORGET YOUR OWN FACE (2022)
+woops I think I only listened to this like twice.
+will need to revisit it later for sure.
+I'll like it.
+.
+.Ss BACKXWASH \(em I LIE HERE BURIED WITH MY RINGS AND MY DRESSES (2021)
+only got into this album
+after hearing it live this summer.
+was the first show I went to in years
+and it was really fucking good.
+gotta listen to this shit loud.
+sampling godspeed for a beat fucks.
+honestly back to back bangers.
+.Pp
+favourite tracks:
+I LIE HERE BURIED WITH MY RINGS AND MY DRESSES,
+TERROR PACKETS,
+SONG OF SINNERS,
+BURN TO ASHES.
+.
+.Ss PHILIP GLASS ENSEMBLE \(em EINSTEIN ON THE BEACH (1979)
+actually just the knee plays
+because I can't be bothered
+listening to all of it.
+and I'm embarrassed by how much
+I enjoy this avant-garde bullshit.
+like ok just sing repeating numbers at me
+and my brain is happy.
+what is this?
+my kink?
+anyway I also have kind of an obsession
+with the
+.Dq story of love
+in knee 5.
+I fucking hate it.
+but it's delivered so well.
+and that violin though!
+.Pp
+favourite tracks:
+KNEE 1,
+KNEE 5.
+.
+.Ss KANYE WEST \(em YEEZUS (2013)
+ok look I listened to this
+before recent events.
+what the fuck.
+it's a really good album though?
+pretty sure I listened to it
+because bound 2 kept getting in my head,
+because of that minecraft parody parody
+wayne did ages ago.
+.Pp
+favourite tracks:
+BLACK SKINHEAD,
+HOLD MY LIQUOR,
+BLOOD ON THE LEAVES,
+BOUND 2.
+.
+.Ss FLYING RACCOON SUIT \(em AFTERGLOW (2021)
+I've listened to the whole album
+a few times
+but I'm mostly just here
+for the title track.
+this also happened to be
+dropped in IRC at just the right time.
+good ska-punk-type shit.
+and I like lisps ok.
+.Pp
+favourite track:
+AFTERGLOW.
+.
+.Ss RAMSHACKLE GLORY \(em LIVE THE DREAM (2011)
+one of those albums
+I don't know why I took so long
+to get to.
+I've been listening to johnny hobo
+since I was like in high school.
+ramshackle is a little more hopeful
+and I love that.
+your heart is a muscle the size of your fist.
+keep on loving.
+keep on fighting.
+.Pp
+favourite tracks:
+WE ARE ALL COMPOST IN TRAINING,
+NEVER COMING HOME,
+YOUR HEART IS A MUSCLE THE SIZE OF YOUR FIST.
+.
+.Ss LES RALLIZES D\('ENUD\('ES \(em THE OZ TAPES (2022)
+a pleasant surprise in someone's playlist.
+lately I've been listening to this
+in the metro to or from electrolysis.
+it's good listening for that.
+bold to have two versions
+of the same 24-minute song
+on the same release.
+.Pp
+favourite tracks:
+A SHADOW ON OUR JOY,
+THE LAST ONE_1970 (ver.2).
+.
+.Ss LINGUA IGNOTA \(em SINNER GET READY (2021)
+another I'm only getting into
+after hearing it live.
+just last sunday actually.
+was a good show.
+people will go wild
+to hear a cover live for real.
+.Pp
+favourite tracks:
+I WHO BEND THE TALL GRASSES,
+PENNSYLVANIA FURNACE,
+PERPETUAL FLAME OF CENTRALIA.
+.
+.Sh AUTHORS
+.An june Aq Mt june@causal.agency
+.Pp
+I started writing this
+before I saw LINGUA IGNOTA.
+good thing I waited.
diff --git a/www/text.causal.agency/042-comfort-music.7 b/www/text.causal.agency/042-comfort-music.7
new file mode 100644
index 00000000..445e04c3
--- /dev/null
+++ b/www/text.causal.agency/042-comfort-music.7
@@ -0,0 +1,62 @@
+.Dd February 23, 2024
+.Dt COMFORT-MUSIC 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm comfort music
+.Nd feel better
+.
+.Sh DESCRIPTION
+it's been a while.
+and I'm on almost no sleep
+and haven't eaten a real meal
+since noon.
+which is a state I've written
+at least a couple posts in before,
+so what better time
+to return to what has apparently
+become this blog's format:
+lists of some music I like.
+.
+.Pp
+this is a list of music that comforts me.
+.
+.Bl -bullet
+.It
+knee play 5, from einstein on the beach.
+I like the organ and the counting and the cadence of the story.
+.It
+low \(em words.
+and I'm tired.
+.It
+godspeed you! black emperor \(em storm.
+this is like my original comfort music.
+been listening to it since I was teenage.
+the grooves are worn deep in my mind.
+.It
+set fire to flames \(em love song for 15 ontario (w/ singing police car).
+I like how it ends.
+.It
+va, from the beginner's guide.
+I think that's the whole point.
+though maybe it's too sad
+to be truly comforting.
+.It
+undertale, from undertale.
+what can I say?
+.It
+wrekmeister harmonies \(em covered in blood from invisible wounds.
+I find quite a bit of the album comforting really.
+I'm picking this one because I like the cadence
+of the lyrics.
+.It
+lingua ignota \(em pennsylvania furnace and perpetual flame of centralia.
+these are really my go to in recent times.
+I like waiting for the next line.
+.El
+.
+.Sh AUTHORS
+.An june Aq Mt june@causal.agency
+.Pp
+I don't think I've said anything
+very interesting here.
diff --git a/www/text.causal.agency/043-little-blessings.7 b/www/text.causal.agency/043-little-blessings.7
new file mode 100644
index 00000000..957c6289
--- /dev/null
+++ b/www/text.causal.agency/043-little-blessings.7
@@ -0,0 +1,78 @@
+.Dd March 24, 2024
+.Dt LITTLE-BLESSINGS 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm little blessings
+.Nd life's
+.
+.Sh DESCRIPTION
+today I went out to go around.
+run some errands and do some shopping.
+along the way I was given
+several of life's little blessings.
+.
+.Pp
+while walking on ste-cath
+between berri and complexe desjardins,
+there was a somewhat disheveled man
+walking in the same direction and singing.
+he had a beautiful voice.
+he was singing a sad song in french,
+and he sung it well and enunciated every word.
+.
+.Pp
+in the mcdonald's at complexe desjardins,
+while waiting for my order,
+there were what appeared to be
+a teenager and her younger brother,
+who must have been
+looking at the display of
+current happy meal toys.
+the teenager was playing smash or pass,
+to the amusement of the younger one.
+they got ice cream
+and ate it across the room from me downstairs.
+.
+.Pp
+later,
+taking the 24 home from atwater
+carrying my new vacuum cleaner,
+the bus got lost.
+I think the driver missed the stop
+and tried to compensate
+by turning north onto peel
+and stopping there.
+but then he had to keep going up peel.
+he turned right onto docteur-penfield,
+which just brings you further up the mountain.
+when it met des pins,
+he turned left and pulled over,
+asking for guidance over the radio.
+we got moving again,
+back towards peel.
+that's how I ended up
+on a 24
+.Dq sherbrooke
+east,
+facing west on des pins.
+it was actually quite scenic.
+and amusing.
+I was in no rush.
+.
+.Pp
+after getting back onto sherbrooke,
+the bus had to take another detour,
+this one planned.
+so my ride on the 24,
+which normally only drives on sherbrooke,
+ended up going on peel,
+docteur-penfield,
+des pins,
+de bleury,
+ren\('e-l\('evesque
+and saint-laurent.
+it was a very exciting bus trip.
+.
+.Sh AUTHORS
+.An june Aq Mt june@causal.agency
diff --git a/www/text.causal.agency/Makefile b/www/text.causal.agency/Makefile
index c5555274..a8683a20 100644
--- a/www/text.causal.agency/Makefile
+++ b/www/text.causal.agency/Makefile
@@ -38,15 +38,24 @@ TXTS += 035-addendum-2021.txt
 TXTS += 036-compassion.txt
 TXTS += 037-care.txt
 TXTS += 038-agency.txt
+TXTS += 039-apologies.txt
+TXTS += 040-sound-memory.txt
+TXTS += 041-albums-2022.txt
+TXTS += 042-comfort-music.txt
+TXTS += 043-little-blessings.txt
 
 all: colb ${TXTS}
 
-.SUFFIXES: .7 .txt
+.SUFFIXES: .7 .fmt .txt
 
 .7.txt:
 	mandoc -T utf8 $< | ./colb > $@
 	touch -m -r $< $@
 
+.fmt.txt:
+	fmt $< | sed '1,/^$$/d' > $@
+	touch -m -r $< $@
+
 feed.atom: feed.sh colb ${TXTS}
 	sh feed.sh > feed.atom
 
diff --git a/www/text.causal.agency/feed.sh b/www/text.causal.agency/feed.sh
index 668046ef..71bbf662 100644
--- a/www/text.causal.agency/feed.sh
+++ b/www/text.causal.agency/feed.sh
@@ -27,6 +27,7 @@ set -- *.txt
 shift $(( $# - 20 ))
 for txt; do
 	entry="${txt%.txt}.7"
+	test -f "$entry" || entry="${txt%.txt}.fmt"
 	date=$(grep '^[.]Dd' "$entry" | cut -c 5-)
 	title=$(grep -m 1 '^[.]Nm' "$entry" | cut -c 5- | encode)
 	summary=$(grep '^[.]Nd' "$entry" | cut -c 5- | encode)