Compare commits

..

4 commits

Author SHA1 Message Date
58119f5968
feat: Add character-dialog shortcode and stylesheet
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline failed
2025-11-11 23:34:40 -06:00
3cc62444fc
feat: Add article element for blog-specific page rendering 2025-11-11 23:34:40 -06:00
a37436de6a
fead: add character individual poses 2025-11-11 23:34:40 -06:00
6ac6f9b9d7
feat: add character ref sheets and description 2025-11-11 23:34:39 -06:00
33 changed files with 139 additions and 0 deletions

View file

@ -0,0 +1,30 @@
# Characters
Imaginary friends that help me inject personality into my articles. These are
anthropomorphized versions of animals that I have known in real life. I tried to
draw them roughly in the style of Chris Pasquini, but failed myself, then tried
using Perplexity's image generation. The style isn't quite the same, but I like
it for these animals. Also, Perplexity does a horrible job of labeling images,
so ignore the ref sheet emotion labels.
## Spawn of Satan (aka Spawn aka SOS)
![Spawn ref sheet](spawn/_ref-body-perplexity.png)
Spawn of Satan is the name Travis gave to the cannulated cow, and it stuck.
Spawn is old and cynical after having every professor with a new idea experiment
on her. After being in academia for so long, she knows her way around
mathematics and the scientific method reasonably well, even if she's never
formally taken a college course in the sciences. She is the realist to any blog
post's optimist.
## Whelen
![Whelen ref sheet](whelen/_ref-body-perplexity.png)
Whelen is a happy-go-lucky German Shepherd/Husky mix puppy. He's been to school
once - and that was just to get neutered - so his knowledge of math and science,
heck, even of the humanities, isn't very good. He is very naive and thinks
everyone is nice and wants to be his friend, but he is also friendly to everyone
and is very vocal when he feels left out. He will step in when any blog post is
getting too technical and demand an explanation for real people (dogs?).

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 850 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

View file

@ -185,6 +185,8 @@
"URW Bookman L", "Georgia Pro", Georgia, serif;
--font-family-slab-serif: Rockwell, "Rockwell Nova", "Roboto Slab",
"DejaVu Serif", "Sitka Small", serif;
--font-family-transitional: Charter, "Bitstream Charter", "Sitka Text",
Cambria, serif;
--font-family-system-ui: system-ui, sans-serif;
--font-family-monospace: "Nimbus Mono PS", "Courier New", monospace;
}
@ -272,6 +274,34 @@ main {
flex-direction: column;
}
article p,
.character-dialog-text,
article li {
font-family: var(--font-family-transitional);
font-size: 1.15rem;
text-justify: inter-word;
text-align: justify;
hyphens: auto;
}
article > p {
text-indent: 2ch;
line-height: 1.5em;
}
article h1 + p,
article h2 + p,
article h3 + p,
article h4 + p,
article h5 + p,
article h6 + p {
text-indent: 0;
}
.footnotes p {
font-size: smaller;
}
figure {
border-color: var(--container-border);
border-width: 1.5pt;
@ -572,6 +602,55 @@ figcaption .mono {
max-width: 100%;
}
.character-dialog {
display: grid;
width: calc(100% - 1rem);
grid-template-columns: 5rem 1fr;
grid-template-rows: auto auto;
gap: 1em;
margin: 0.5rem;
}
.character-avatar {
display: grid;
max-width: 100%;
grid-row: 1 / span 2;
grid-column: 1;
align-self: start;
align-items: center;
justify-items: center;
min-width: 5rem;
min-height: 5rem;
border-radius: 5rem;
align-items: center;
border-style: solid;
border-color: var(--nav-button-background-hover);
background-color: var(--cowhide-2);
}
.character-avatar > img {
max-width: 4rem;
max-height: 4rem;
}
.character-dialog-bubble {
display: grid;
grid-template-rows: auto auto;
align-self: start;
border-radius: 0.5em;
border-width: 0.2rem;
border-color: var(--nav-button-background);
border-style: outset;
row-gap: 0.5rem;
padding: 0.5rem;
background-color: var(--container-border);
min-height: 5rem;
}
.character-dialog-title {
font-weight: bolder;
}
/*
Helper classes
*/

View file

@ -0,0 +1,6 @@
{{ define "main" }}
<article>
<h1>{{ .Title }}</h1>
{{ .Content }}
</article>
{{ end }}

View file

@ -0,0 +1,24 @@
{{ $character := .Get 0 }}
{{ $position := .Get 1 }}
{{ $emotion := .Get 2 }}
{{ $resourceName := print "characters/" $character "/" $position "-" $emotion ".png" }}
{{ $characterImageResource := resources.Get $resourceName }}
{{ $resizedCharacterImage := $characterImageResource.Resize "x100" }}
<div class="character-dialog">
<div class="character-avatar">
<img
src="{{ $resizedCharacterImage.Permalink }}"
alt="thumbnail of {{ $character }} in {{ $emotion }} state"
/>
</div>
<div class="character-dialog-bubble">
<div class="character-dialog-title">
{{ $character | humanize }}
</div>
<div class="character-dialog-text">{{ .Inner | markdownify }}</div>
</div>
</div>