66.155.40.160

As of: Nov 28, 2022 2:24am UTC | Latest

Basic Information

Reverse DNS
meyerweb.com
OS
Red Hat Enterprise Linux 7
Network
COGECO-PEER1 (CA)
Routing
66.155.40.0/21  via  AS13768
Protocols
22/SSH , 25/SMTP , 53/DNS , 80/HTTP , 110/POP3 , 143/IMAP , 443/HTTP , 465/SMTP , 587/SMTP , 993/IMAP , 995/POP3 , 2077/HTTP , 2078/HTTP , 2079/HTTP , 2080/HTTP , 2082/HTTP , 2083/HTTP , 2086/HTTP , 2091/HTTP , 2095/HTTP , 2096/HTTP

22/SSH TCP
Observed Nov 27, 2022 at 8:50pm UTC


View All Data

Software

linux
OpenBSD OpenSSH 7.4

Details

Host Key
Algorithm
ecdsa-sha2-nistp256
Fingerprint
f0880fb40dc6a95b8f8dbe2ecb44b6ac78e4eb1290743808eeac84b9ef902ad5
Negotiated
Key Exchange
[email protected]
Symmetric Cipher
aes128-ctr [] aes128-ctr []
MAC
hmac-sha2-256 [] hmac-sha2-256 []

25/SMTP TCP
Observed Nov 27, 2022 at 1:59pm UTC


View All Data

Software

linux
exim 4.95

Details

Banner
220-morse.multipattern.com ESMTP Exim 4.95 #2 Sun, 27 Nov 2022 14:00:00 +0000 
220-We do not authorize the use of this system to transport unsolicited, 
220 and/or bulk e-mail.
EHLO
250-morse.multipattern.com Hello www.censys.io [167.94.145.57]
250-SIZE 52428800
250-8BITMIME
250-PIPELINING
250-PIPE_CONNECT
250-AUTH PLAIN LOGIN
250-STARTTLS
250 HELP
Start TLS
220 TLS go ahead

TLS

Fingerprint
JA3S
303951d4c50efb2e991652225a6f02b1
Handshake
Version Selected
TLSv1_2
Cipher Selected
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Leaf Certificate
cdf0ba93b94a16ad390eaddf891e310fd7e54439a50c20eb1197f04395ae3a57
CN=morse.multipattern.com
C=US, ST=TX, L=Houston, O=cPanel\, Inc., CN=cPanel\, Inc. Certification Authority
Issuer Chain

53/DNS UDP
Observed Nov 27, 2022 at 11:02am UTC


View All Data

Software

ISC BIND 9.11.4-P2
Red Hat Enterprise Linux 7

Details

Server Type
AUTHORITATIVE
R Code
REFUSED

80/HTTP TCP
Observed Nov 28, 2022 at 2:22am UTC


View All Data Go

Software

Apache HTTPD

Details

http://66.155.40.160
Request
GET /
Protocol
HTTP/1.1
Status Code
302
Status Reason
Found
Body Hash
sha1:af854f52b13ede123525f56f420b002e5677a525
HTML Title
302 Found
Response Body
# Found

The document has moved [here](https://66.155.40.160/).

110/POP3 TCP
Observed Nov 27, 2022 at 11:11am UTC


View All Data

Software

Dovecot

Details

Banner
+OK Dovecot ready.
Start TLS
+OK Begin TLS negotiation now.

TLS

Fingerprint
JA3S
303951d4c50efb2e991652225a6f02b1
Handshake
Version Selected
TLSv1_2
Cipher Selected
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Leaf Certificate
cdf0ba93b94a16ad390eaddf891e310fd7e54439a50c20eb1197f04395ae3a57
CN=morse.multipattern.com
C=US, ST=TX, L=Houston, O=cPanel\, Inc., CN=cPanel\, Inc. Certification Authority
Issuer Chain

143/IMAP TCP
Observed Nov 27, 2022 at 5:29pm UTC


View All Data

Software

linux

Details

Banner
* OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE NAMESPACE LITERAL+ STARTTLS AUTH=PLAIN AUTH=LOGIN] Dovecot ready.
Start TLS
a001 OK Begin TLS negotiation now.

TLS

Fingerprint
JA3S
303951d4c50efb2e991652225a6f02b1
Handshake
Version Selected
TLSv1_2
Cipher Selected
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Leaf Certificate
cdf0ba93b94a16ad390eaddf891e310fd7e54439a50c20eb1197f04395ae3a57
CN=morse.multipattern.com
C=US, ST=TX, L=Houston, O=cPanel\, Inc., CN=cPanel\, Inc. Certification Authority
Issuer Chain

443/HTTP TCP
Observed Nov 28, 2022 at 2:22am UTC


View All Data Go

Software

Apache HTTPD

Details

https://66.155.40.160
Request
GET /
Protocol
HTTP/1.1
Status Code
200
Status Reason
OK
Body Hash
sha1:3211b81f2e9524766579faf4892076f6cb3fa697
HTML Title
meyerweb.com
Response Body
# [meyerweb.com](/)

Main content Navigation links Footer

  * [Post Archives](/eric/thoughts/)
  * [CSS Work](/eric/css/)
  * [Toolbox](/eric/tools/)
  * [Writing](/eric/writing.html)
  * [Speaking](/eric/talks/)
  * [Other Stuff](/other/)
  * [About this site](/ui/about.html)

## [Masked Gradient Dashed
Lines](https://meyerweb.com/eric/thoughts/2022/10/27/masked-gradient-dashed-
lines/ "Permanent Link: Masked Gradient Dashed Lines")

_Published 1 month past_

I talked in my last post about [how I used linear gradients to recreate dashed
lines](https://meyerweb.com/eric/thoughts/2022/10/19/a-dashing-navbar-
solution/) for the navlinks and navbar of
[wpewebkit.org](https://wpewebkit.org), but that wasn’t the last instance of
dashing gradients in the design. I had occasion to use that technique again,
except this time as a way to create a gradient dash. I mean, a dashed line
that has a visible gradient from one color to another, as well as a dashed
line that’s constructed using a linear gradient. Only this time, the dashed
gradient is used to create the gaps, not the dashes.

To set the stage, here’s the bit of the design I had to create:

[![](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
connect-01.png)](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
connect-01.png) Design!

The vertical dashed line down the left side of the design is a dashed linear
gradient, but that’s not actually relevant. It could have been a dashed border
style, or an SVG, or really anything. And that image on the right is a PNG,
but that’s also not really relevant. What’s relevant is I had to make sure the
image was centered in the content column, and yet its dashed line connected to
the left-side dashed line, regardless of where the image landed in the actual
content.

Furthermore, the colors of the two dashed lines were different at the point I
was doing the implementation: the left-side line was flat black, and the line
in the image was more of a dark gray. I could have just connected a dark gray
line to the black, but it didn’t look right. A color transition was needed,
while still being a dashed line.

Ideally, I was looking for a solution that would allow a smooth color fade
over the connecting line’s length while _also_ allowing the page background
color to show through. Because the page background might sometimes be white
and sometimes be a light blue and might in the future be lime green wavy
pattern or something, who knows.

So I used a dashed linear gradient as a mask. The CSS goes like this:

    
    
    .banner::before {
    	content: '';
    	position: absolute;
    	top: 50%;
    	left: -5rem;
    	width: 5rem;
    	height: 1px;
    	background: linear-gradient(90deg, #222, #888);
    	mask-image: repeating-linear-gradient(
    		270deg, transparent, #999 1px 3px, transparent 4px 7px);
    }

Please allow me to break it down a step at a time.

First, there’s the positioning of the pseudo-element, reaching leftward `5rem`
from the left edge of the content column, which here I’ve annotated with a red
outline. (I prefer outlines to borders because outlines don’t participate in
layout, so they can’t shift things around.)

    
    
    .banner::before {
    	content: '';
    	position: absolute;
    	top: 50%;
    	left: -5rem;
    	width: 5rem;
    	height: 1px;
    }

[![](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
connect-02.png)](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
connect-02.png) The very skinny-short red box is where the connecting line
needs to be drawn.

To that pseudo-element, I added a 90-degree-pointing linear gradient from
black to gray to its background.

    
    
    	…
    	background: linear-gradient(90deg, #222, #888);
    }

[![](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
connect-03.png)](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
connect-03.png) The gradient filling the entire background of the pseudo-
element.

The pseudo-element does happen to touch the end of one of the vertical dashes,
but that’s purely by coincidence. It could have landed anywhere, including
between two dashes.

So now it was time for a mask. CSS Masks are images used to hide parts of an
element based on the contents of the masking image, usually its alpha channel.
(Using luminosity to define transparency levels via the `mask-mode` property
is also an option, but [Chrome doesn’t support
that](https://developer.mozilla.org/en-US/docs/Web/CSS/mask-
mode#browser_compatibility) as yet.) For example, you can use small images to
clip off the corners of an element.

In this case, I defined a repeating linear gradient because I knew what size
the dashes should be, and I didn’t want to mess with `mask-size` and `mask-
repeat` (ironically enough, as you’ll see in a bit). This way, the mask is
100% the size of the element’s box, and I just need to repeat the gradient
pattern however many times are necessary to cross the entire width of the
element’s background.

Given the design constraints, I wanted the dash pattern to start from the
right side, the one next to the image, and repeat leftward, to ensure that the
dash pattern would look unbroken. Thus I set its direction to be 270 degrees.
Here I’ll have it alternate between red and transparent, because the actual
color used for the opaque parts of the mask doesn’t matter, only its opacity:

    
    
    	…
    	mask-image: repeating-linear-gradient(
    		270deg, transparent, red 1px 3px, transparent 4px 7px);
    }

[![](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
connect-04.png)](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
connect-04.png) The pseudo-element being masked over and over again to create
a dashed line that allows the backdrop to show through.

The way the mask works, the transparent parts of the masking image cause the
corresponding parts of the element to be transparent  — to be clipped away, in
effect. The opaque parts, whatever color they actually have, cause the
corresponding parts of the element to be drawn. Thus, the parts of the
background’s black-to-gray gradient that line up with the opaque parts of the
mask are rendered, and the rest of the gradient is not. Thus, a color-fading
dashed line.

This is actually why I separated the ends of the color stops by a pixel: by
defining a one-pixel distance for the transition from transparent to opaque
(and vice versa), the browser fills those pixels in with something partway
between those two states. It’s probably 50% opaque, but that’s really up to
the browser.

[![](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
connect-05.png)](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
connect-05.png) The pixels of the repeating gradient pattern, shown here in
the reading order of the CSS value. In practice, this pattern is flipped
horizontally, since its gradient arrow points to 270 degrees (leftward).

The result is a softening effect, which matches well with the dashed line in
the image itself and doesn’t look out of place when it meets up with the left-
hand vertical dashed line.

At least, everything I just showed you is what happens in Firefox, which
proudly supports all the masking properties. In Chromium and WebKit browsers,
you need vendor prefixes for masking to work. So here’s how the CSS turned
out:

    
    
    .banner::before {
    	content: '';
    	position: absolute;
    	top: 50%;
    	left: -5rem;
    	width: 5rem;
    	height: 1px;
    	background: linear-gradient(90deg, #222, #888);
    	-webkit-mask-image: repeating-linear-gradient(
    		270deg, transparent, red 1px 3px, transparent 4px 7px);
    	mask-image: repeating-linear-gradient(
    		270deg, transparent, red 1px 3px, transparent 4px 7px);
    }

And that’s where we were at launch.

It still bugged me a little, though, because the dashes I created were one
pixel tall, but the dashes in the image weren’t. They were more like a pixel
and a half tall once you take the aliasing into account, so they probably
started out 2 (or more) pixels tall and then got scaled down. The transition
from those visually-slightly-larger dashes to the crisply-one-pixel-tall
pseudo-element didn’t look quite right.

I’d hoped that just increasing the height of the pseudo-element to `2px` would
work, but that made the line look too thick. That meant I’d have to basically
recreate the aliasing myself.

At first I considered leaving the mask as it was and setting up two linear
gradients, the existing one on the bottom and a lighter one on top. Instead, I
chose to keep the single background gradient and set up two masks, the
original on the bottom and a more transparent one on top. Which meant I’d have
to size and place them, and keep them from tiling. So, despite my earlier
avoidance, I had to mess with mask sizing and repeating anyway.

    
    
    mask-image:
    	repeating-linear-gradient(
    		270deg, transparent, #89A4 1px 3px, transparent 4px 7px),
    	repeating-linear-gradient(
    		270deg, transparent, #89A 1px 3px, transparent 4px 7px);
    	mask-size: 100% 1px;
    	mask-repeat: no-repeat;
    	mask-position: 100% 0%, 100% 100%;

[![](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
connect-06.png)](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
connect-06.png) Two masks, one effect.

And that’s how it stands as of today.

In the end, this general technique is pretty much infinitely adaptable, in
that you could define any dash pattern you like and have it repeat over a
gradient, background image, or even just a plain background color. It could be
used to break up an element containing text, so it looks like the text has
been projected onto a thick dashed line, or put some diagonal slashes through
text, or an image, or a combination.

SLASHED TEXT

No PNG, no SVG, just text and CSS.

Or use a tiled radial gradient to make your own dotted line, one that’s fully
responsive without ever clipping a dot partway through. Wacky line patterns
with tiled, repeated conic gradients? Sure, why not?

The point being, masks let you break up the rectangularity of elements, which
can go a long way toward making designs feel more alive. Give ’em a try and
see what you come up with!

  * [Masked Gradient Dashed Lines](https://meyerweb.com/eric/thoughts/2022/10/27/masked-gradient-dashed-lines/) was published on Thursday, October 27th, 2022.
  * It was assigned to the [CSS](https://meyerweb.com/eric/thoughts/category/tech/css/) and [Web](https://meyerweb.com/eric/thoughts/category/tech/web/) categories.
  * There has been [one reply](https://meyerweb.com/eric/thoughts/2022/10/27/masked-gradient-dashed-lines/#comments).

* * *

## [A Dashing Navbar
Solution](https://meyerweb.com/eric/thoughts/2022/10/19/a-dashing-navbar-
solution/ "Permanent Link: A Dashing Navbar Solution")

_Published 1 month, 1 week past_

One of the many things [Igalia](https://igalia.com/) does is maintain an
official port of WebKit for embedded devices called WPE WebKit, and as you
might expect, it has [a web site](https://wpewebkit.org/). The design had
gotten a little stale since its launch a few years ago, so we asked Denis
Radenković at [38one](http://38one.com/) to come up with a new design, which
we launched yesterday. And I got to turn it into HTML and CSS! Which was
mostly normal stuff, margins and font sizing and all that, but also had some
bits that called for some creativity.

There was one aspect of the design that I honestly thought wasn’t going to be
possible, which was the way the “current page” link in the site navbar
connected up to the rest of the page’s design via a dashed line. You can see
it on the site, or in this animation about how each navlink was designed to
appear.

[![](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-navbar-
anim.gif)](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-navbar-
anim.gif) Navigation link styles, not including the Home button, which is
essentially the same but not nearly as obvious because of its specific layout.

I thought about using bog-standard dashed element borders: one on a filler
element or pseudo-element that spanned the mostly-empty left side of the
navbar, and one on each navlink before the current one, and then… I don’t
know. I didn’t get that far, because I realized the dashed borders would
almost certainly stutter, visually. What I mean is, the dashes wouldn’t follow
a regular on-off pattern, which would look fairly broken.

My next thought was to figure out how to size a filler element or pseudo-
element so that it was the exact width needed to reach the middle of the
active navlink. Maybe there’s a clever way to do that with just HTML and CSS,
but I couldn’t think of a way to do it that wasn’t either structurally
nauseating or dependent on me writing clever JavaScript. So I tossed that
idea, though I’ll return to it at the end of the post.

In the end, it was the interim development styles that eventually got me
there. See, while building out other parts of the design, I just threw a
dashed border on the bottom of the navbar, which (as is the way of borders)
spanned its entire bottom edge. At some point I glanced up at it and thought,
_If only I could figure out a mask that would clip off the part of the border
I don’t need._ And slowly, I realized that with a little coding sleight-of-
hand, I could almost exactly do that.

First, I removed the bottom border from the navbar and replaced it with a
dashed linear gradient background, like this:

    
    
    nav.global {
    	background-image: linear-gradient(
    		90deg,
    		currentColor 25%,
    		transparent 25% 75%,
    		currentColor 75%
    	);
    	background-position: 0 100%;
    	background-size: 8px 1px;
    	background-repeat: repeat-x;
    }

(Okay, I actually used the `background` shorthand form of the above — `linear-
gradient(…) 0 100% / 8px 1px repeat-x` — but the result is the same.)

I thought about using `repeating-linear-gradient`, which would have let me
skip having to declare a `background-repeat`, but would have required me to
size the gradient’s color stops using length units instead of percentages. I
liked how, with the above, I could set the color stops with percentages, and
then experiment with the size of the image using `background-size`. (`7px
1px`? `9px 1px`? `8px 1.33px`? Tried ’em all, and then some.) But that’s
mostly a personal preference, not based in any obvious performance or clarity
win, so if you want to try this with a repeating gradient, go for it.

But wait. What was the point of recreating the border’s built-in dash effect
with a gradient background? Well, as I said, it made it easier to experiment
with different sizes. It also allowed me to create a dash pattern that would
be very consistent across browsers, which `border-style` dashes very much are
not.

But primarily, I wanted the dashes to be in the background of the navbar
because I could then add small solid-color gradients to the backgrounds of the
navlinks that come after the active one.

    
    
    nav.global li.currentPage ~ li {
    	background: linear-gradient(0deg, #FFF 2px, transparent 2px);
    }

That selects all the following-sibling list items of the `currentPage`-classed
list item, which here is the “Learn & Discover” link.

    
    
    <ul class="about off">
    	<li><a class="nav-link" href="…">Home</a></li>
    	<li class="currentPage"><a class="nav-link" href="…">Learn &amp; Discover</a></li>
    	<li><a class="nav-link" href="…">Blog</a></li>
    	<li><a class="nav-link" href="…">Developers</a></li>
    	<li><a class="btn cta" href="…">Get Started</a></li>
    </ul>

Here’s the result, with the gradient set to be visible with a pinkish fill
instead of `#FFF` so we can see it:

[![](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
navbar-1.gif)](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
navbar-1.gif) The “masking” gradients, here set to be a nicely rosy pink
instead of the usual solid white.

You can see how the pink hides the dashes. In the actual styles, because the
`#FFF` is the same as the design’s page background, those list items’
background gradients are placed over top of (and thus hide) the navbar’s
background dash.

I should point out that the color stop on the white solid gradient could have
been at `1px` rather than `2px` and still worked, but I decided to give myself
a little bit of extra coverage, just for peace of mind. I should also point
out that I didn’t just fill the backgrounds of the list items with
`background-color: #FFF` because the navbar has a semitransparent white
background fill and a blurring `background-filter`, so the page content can be
hazily visible through the navbar, as shown here.

[![](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
navbar-2.gif)](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
navbar-2.gif) The backdrop-blurring of content behind the navbar, not blurring
nearly as much as I thought they should, but oh well.

The white line is slightly suboptimal in this situation, but it doesn’t really
stand out and does add a tiny bit of visual accent to the navbar’s edge, so I
was willing to go with it.

The next step was a little trickier: there needs to be a vertical dashed line
“connecting” to the navbar’s dashed line at the horizontal center of the link,
_and also_ the navbar’s dashed line needs to be hidden, but only to the right
of the vertical dashed line. I thought about doing two background gradients on
the list item, one for the vertical dashed line and one for the white “mask”,
but I realized that constraining the vertical dashed line to be half the
height of the list item while also getting the repeating pattern correct was
too much for my brain to figure out.

Instead, I positioned and sized a generated pseudo-element like this:

    
    
    nav.global ul li.currentPage {
    	position: relative;
    }
    nav.global ul li.currentPage::before {
    	content: '';
    	position: absolute;
    	z-index: 1;
    	top: 50%;
    	bottom: 0;
    	left: 50%;
    	right: 0;
    	background:
    		linear-gradient(180deg,
    			currentColor 25%,
    			transparent 25% 75%, 
    			currentColor 75%) 0 0 / 1px 8px repeat-y, 
    		linear-gradient(0deg, #FFFF 2px, transparent 2px);
    	background-size: 1px 0.5em, auto;
    }

That has the generated pseudo-element fill the bottom right quadrant of the
active link’s list item, with a vertical dashed linear gradient running along
its left edge and a solid white two-pixel gradient along its bottom edge, with
the solid white below the vertical dash. Here it is, with the background
pinkishly filled in to be visible behind the two gradients.

[![](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
navbar-3-1.gif)](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-
navbar-3-1.gif) That’s the `::before` with its background filled in a rosy
pink instead of the usual transparency.

With that handled, the last step was to add the dash across the bottom of the
current-page link and then mask the vertical line with a background color,
like so:

    
    
    nav.global ul li.currentPage a {
    	position: relative;
    	z-index: 2;
    	background: var(--dashH); /* converted the dashes to variables */
    	background-size: 0.5em 1px;
    	background-position: 50% 100%;
    	background-color: #FFF;
    }

And that was it. Now, any of the navbar links can be flagged as the current
page (with a `class` of `currentPage` on the enclosing list item) and will
automatically link up with the dashes across the bottom of the navbar, with
the remainder of that navbar dash hidden by the various solid white gradient
background images.

[![](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-navbar-
anim.gif)](https://meyerweb.com/eric/thoughts/wp-content/uploads/wpe-navbar-
anim.gif) An animation of the link styles, only now you know how they work.

So, it’s kind of a hack, and I wish there were a cleaner way to do this. And
maybe there is! I pondered setting up a fine-grained grid and adding an SVG
with a dashed path, or maybe a filler `<span>`, to join the current link to
the line. That also feels like a hack, but maybe less of one. Or maybe not!

What I believe I want are the capabilities promised by the [Anchored
Positioning](http://tabatkins.github.io/specs/css-anchor-position/) proposal.
I _think_ I could have done something like:

    
    
    nav.global {position: relative;}
    nav.global .currentPage {anchor-name: --navLink;}
    nav.global::before {
    	position: absolute;
    	left: 0;
    	bottom: 0;
    	right: var(--center);
    	--center: anchor(--navLink 50%);
    	top: anchor(--navLink bottom);
    }

…and then used that to run the dashed line over from the left side of the page
to underneath the midpoint of the current link, and then up to the bottom edge
of that link. Which would have done away with the need for the `li ~ li`
overlaid-background hack, and nearly all the other hackery. I mean, I enjoy
hackery as much as the next codemonaut, but I’m happier when the hacks are
more elegant and minimal.

  * [A Dashing Navbar Solution](https://meyerweb.com/eric/thoughts/2022/10/19/a-dashing-navbar-solution/) was published on Wednesday, October 19th, 2022.
  * It was assigned to the [CSS](https://meyerweb.com/eric/thoughts/category/tech/css/) and [Web](https://meyerweb.com/eric/thoughts/category/tech/web/) categories.
  * There have been [no replies](https://meyerweb.com/eric/thoughts/2022/10/19/a-dashing-navbar-solution/#respond).

* * *

## [Nuclear Targeted
Footnotes](https://meyerweb.com/eric/thoughts/2022/09/12/nuclear-footnotes/
"Permanent Link: Nuclear Targeted Footnotes")

_Published 2 months, 2 weeks past_

One of the more interesting design challenges of [The Effects of Nuclear
Weapons](https://meyerweb.com/eric/thoughts/2022/08/09/recreating-the-effects-
of-nuclear-weapons-for-the-web/) was the fact that, like many technical texts,
it has footnotes. Not a huge number, and in fact one chapter has none at all,
but they couldn’t be ignored. And I didn’t want them to be inline between
paragraphs or stuck into the middle of the text.

This was actually a case where Chris and I decided to depart a bit from the
print layout, because in print a chapter has many pages, but online it has a
single page. So we turned the footnotes into endnotes, and collected them all
near the end of each chapter.

Originally I had thought about putting footnotes off to one side in desktop
views, such as in the right-hand grid gutter. After playing with some rough
prototypes, I realized this wasn’t going to go the way I wanted it to, and
would likely make life difficult in a variety of display sizes between the
“big desktop monitor” and “mobile device” realms. I don’t know, maybe I gave
up too easily, but Chris and I had already decided that endnotes were an
acceptable adaptation and I decided to roll with that.

So here’s how the footnotes work. First off, in the main-body text, a footnote
marker is wrapped in a `<sup>` element and is a link that points at a named
anchor in the endnotes. (I may go back and replace all the superscript
elements with styled `<mark>` elements, but for now, they’re superscript
elements.) Here’s [an example from the beginning of Chapter
I](https://atomicarchive.com/resources/documents/effects/glasstone-
dolan/chapter1.html#%C2%A71.01), which also has a cross-reference link in it,
classed as such even though we don’t actually style them any differently than
other links.

    
    
    This is true for a conventional “high explosive,” such as TNT, as well as for a nuclear (or atomic) explosion,<sup><a href="#fnote01">1</a></sup> although the energy is produced in quite different ways (<a href="#§1.11" class="xref">§ 1.11</a>).

Then, down near the end of the document, there’s a section that contains an
ordered list. Inside that list are the endnotes, which are in part marked up
like this:

    
    
    <li id="fnote01"><sup>1</sup> The terms “nuclear” and atomic” may be used interchangeably so far as weapons, explosions, and energy are concerned, but “nuclear” is preferred for the reason given in <a href="#§1.11" class="xref">§ 1.11</a>.

The list item markers are switched off with CSS, and superscripted numbers
stand in their place. I do it that way because the footnote numbers are
important to the content, but also have specific presentation demands that are
difficult  — nay, impossible — to pull off with normal markers, like raising
them superscript-style. (List markers are only affected by [a very limited set
of properties](https://drafts.csswg.org/css-lists-3/#marker-properties).)

In order to get the footnote text to align along the start (left) edge of
their content and have the numbers hang off the side, I elected to use the old
negative-text-indent-positive-padding trick:

    
    
    .endnotes li {
    	padding-inline-start: 0.75em;
    	text-indent: -0.75em;
    }

That works great as long as there are never any double-digit footnote numbers,
which was indeed the case… until [Chapter
VIII](https://atomicarchive.com/resources/documents/effects/glasstone-
dolan/chapter8.html). Dang it.

So, for any footnote number above 9, I needed a different set of values for
the indent-padding trick, and I didn’t feel like adding in a bunch of
`greater-than-nine` classes. [Following-sibling
combinator](https://developer.mozilla.org/en-
US/docs/Web/CSS/General_sibling_combinator) to the rescue!

    
    
    .endnotes li:nth-of-type(9) ~ li {
    	margin-inline-start: -0.33em;
    	padding-inline-start: 1.1em;
    	text-indent: -1.1em;
    }

The extra negative start margin is necessary solely to get the text in the
list items to align horizontally, though unnecessary if you don’t care about
that sort of thing.

Okay, so the endnotes looked right when seen in their list, but I needed a way
to get back to the referring paragraph after reading a footnote. Thus, some
“backjump” links got added to each footnote, pointing back to the paragraph
that referred to them.

    
    
    <span class="backjump">[ref. <a href="#§1.01">§ 1.01</a>]</span>

With that, a reader can click/tap a footnote number to jump to the
corresponding footnote, then click/tap the reference link to get back to where
they started. Which is fine, as far as it goes, but that idea of having
footnotes appear in context hadn’t left me. I decided I’d make them happen,
one way or another.

(Throughout all this, I wished more than once [the HTML 3.0 proposal for
`<fn>`](https://www.w3.org/MarkUp/html3/footnotes.html) had gone somewhere
other than the dustbin of history and the industry’s collective memory hole.
Ah, well.)

I was thinking I’d need some kind of JavaScript thing to swap element nodes
around when it occurred to me that clicking a footnote number would make the
corresponding footnote list item a target, and if an element is a target, it
can be styled using the `:target` pseudo-class. Making it appear in context
could be a simple matter of positioning it in the viewport, rather than with
relation to the document. And so:

    
    
    .endnotes li:target {
    	position: fixed;
    	bottom: 0;
    	padding-block: 2em 4em;
    	padding-inline: 2em;
    	margin-inline: -2em 0;
    	border-top: 1px solid;
    	background: #FFF;
    	box-shadow: 0 0 3em 3em #FFF;
    	max-width: 45em;
    }

That is to say, when an endnote list item is targeted, it’s fixedly positioned
against the bottom of the viewport and given some padding and background and a
top border and a box shadow, so it has a bit of a halo above it that sets it
apart from the content it’s overlaying. It actually looks pretty sweet, if I
do say so myself, and allows the reader to see footnotes without having to
jump back and forth on the page. Now all I needed was a way to make the
footnote go away.

Again I thought about going the JavaScript route, but I’m trying to keep to
[the Web’s slower pace
layers](https://adactio.com/articles/16334#World%20Wide%20Web) as much as
possible in this project for maximum compatibility over time and technology.
Thus, every footnote gets a “close this” link right after the backjump link,
marked up like this:

    
    
    <a href="#fnclosed" class="close">X</a></li>

(I realize that probably looks a little weird, but hang in there and hopefully
I can clear it up in the next few paragraphs.)

So every footnote ends with two links, one to jump to the paragraph (or
heading) that referred to it, which is unnecessary when the footnote has
popped up due to user interaction; and then, one to make the footnote go away,
which is unnecessary when looking at the list of footnotes at the end of the
chapter. It was time to juggle display and visibility values to make each
appear only when necessary.

    
    
    .endnotes li .close {
    	display: none;
    	visibility: hidden;
    }
    .endnotes li:target .close {
    	display: block;
    	visibility: visible;
    }
    .endnotes li:target .backjump {
    	display: none;
    	visibility: hidden;
    }

Thus, the “close this” links are hidden by default, and revealed when the list
item is targeted and thus pops up. By contrast, the backjump links are shown
by default, and hidden when the list item is targeted.

As it now stands, this approach has some upsides and some downsides. One
upside is that, since a URL with an identifier fragment is distinct from the
URL of the page itself, you can dismiss a popped-up footnote with the
browser’s Back button. On kind of the same hand, though, one downside is that
since a URL with an identifier fragment is distinct from the URL of the page
itself, if you consistently use the “close this” link to dismiss a popped-up
footnote, the browser history gets cluttered with the opened and closed states
of various footnotes.

This is bad because you can get partway through a chapter, look at a few
footnotes, and then decide you want to go back one page by hitting the Back
button, at which point you discover have to go back through all those footnote
states in the history before you actually go back one page.

I feel like this is a thing I can (probably should) address by layering
progressively-enhancing JavaScript over top of all this, but I’m still not
quite sure how best to go about it. Should I add event handlers and such so
the fragment-identifier stuff is suppressed and the URL never actually
changes? Should I add listeners that will silently rewrite the browser history
as needed to avoid this? Ya got me. Suggestions or pointers to live examples
of solutions to similar problems are welcomed in the comments below.

Less crucially, the way the footnote just appears and disappears bugs me a
little, because it’s easy to miss if you aren’t looking in the right place. My
first thought was that it would be nice to have the footnote unfurl from the
bottom of the page, but it’s basically impossible (so far as I can tell) to
animate the height of an element from `0` to `auto`. You also can’t animate
something like `bottom: calc(-1 * calculated-height)` to `0` because there is
no CSS keyword (so far as I know) that returns the calculated height of an
element. And you can’t really animate from `top: 100vh` to `bottom: 0` because
animations are of a property’s values, not across properties.

I’m currently considering a quick animation from something like `bottom:
-50em` to `0`, going on the assumption that no footnote will ever be more than
50 em tall, regardless of the display environment. But that means short
footnotes will slide in later than tall footnotes, and probably appear to move
faster. Maybe that’s okay? Maybe I should do more of a fade-and-scale-in thing
instead, which will be visually consistent regardless of footnote size. Or I
could have them 3D-pivot up from the bottom edge of the viewport! Or maybe
this is another place to layer a little JS on top.

Or maybe I’ve overlooked something that will let me unfurl the way I first
envisioned with just HTML and CSS, a clever new technique I’ve missed or an
old solution I’ve forgotten. As before, comments with suggestions are welcome.

  * [Nuclear Targeted Footnotes](https://meyerweb.com/eric/thoughts/2022/09/12/nuclear-footnotes/) was published on Monday, September 12th, 2022.
  * It was assigned to the [CSS](https://meyerweb.com/eric/thoughts/category/tech/css/), [Design](https://meyerweb.com/eric/thoughts/category/design/), and [Projects](https://meyerweb.com/eric/thoughts/category/personal/projects/) categories.
  * There have been [eleven replies](https://meyerweb.com/eric/thoughts/2022/09/12/nuclear-footnotes/#comments).

* * *

## [Table Column Alignment with Variable
Transforms](https://meyerweb.com/eric/thoughts/2022/08/15/table-column-
alignment-with-variable-transforms/ "Permanent Link: Table Column Alignment
with Variable Transforms")

_Published 3 months, 1 week past_

One of the bigger challenges of [recreating The Effects of Nuclear Weapons for
the Web](https://meyerweb.com/eric/thoughts/2022/08/09/recreating-the-effects-
of-nuclear-weapons-for-the-web/) was its tables. It was easy enough to turn
tab-separated text and numbers into table markup, but the column alignment
almost broke me.

To illustrate what I mean, here are just a few examples of columns that had to
be aligned.

[ ![](https://meyerweb.com/eric/thoughts/wp-content/uploads/enw-data-tables-
bare.jpg) ![](https://meyerweb.com/eric/thoughts/wp-content/uploads/enw-data-
tables-lined.jpg) ](https://meyerweb.com/eric/thoughts/wp-content/uploads/enw-
data-tables-lined.jpg)

A few of the many tables in the book and their fascinating column alignments.
(Hover/focus this figure to start a cyclic animation fading some alignment
lines in and out. Sorry if that doesn’t work for you, mobile readers.)

At first I naïvely thought, “No worries, I can right- or left-align most of
these columns and figure out the rest later.” But then I looked at the
centered column headings, and how the column contents were essentially
centered on the headings while having their own internal horizontal alignment
logic, and realized all my dreams of simple fixes were naught but ashes.

My next thought was to put blank spacer columns between the columns of visible
content, since table layout doesn’t honor the `gap` property, and then set a
fixed width for various columns. I really didn’t like all the empty-cell spam
that would require, even with liberal application of the `rowspan` attribute,
and it felt overly fragile  — any shifts in font face (say, on an older or
niche system) might cause layout upset within the visible columns, such as
wrapping content that shouldn’t be wrapped or content overlapping other
content. I felt like there was a better answer.

I also thought about segregating every number and symbol (including decimal
separators) into separate columns, like this:

    
    
    <tr>
      <th>Neutrinos from fission products</th>
      <td>10</td> 
      <td></td>
      <td></td>
    </tr>
    <tr class="total">
      <th>Total energy per fission</th>
      <td>200</td>
      <td>±</td>
      <td>6</td>
    </tr>

Then I contemplated what that would do to screen readers and the document
structure in general, and after the nausea subsided, I decided to look
elsewhere.

It was at that point I thought about using spacer `<span>`s. Like, anywhere I
needed some space next to text in order to move it to one side or the other,
I’d throw in something like one of these:

    
    
    <span class="spacer"></span>
    <span style="display: inline; width: 2ch;"></span>

Again, the markup spam repulsed me, but there was the kernel of an idea in
there… and when I combined it with the truism “CSS doesn’t care what you
expect elements to look or act like”, I’d hit upon my solution.

Let’s return to [Table
1.43](https://atomicarchive.com/resources/documents/effects/glasstone-
dolan/chapter1.html#tbl1-43), which I used as an illustration in [the
announcement post](https://meyerweb.com/eric/thoughts/2022/08/09/recreating-
the-effects-of-nuclear-weapons-for-the-web/). It’s shown here in its not-
aligned and aligned states, with borders added to the table-cell elements.

[![](https://meyerweb.com/eric/thoughts/wp-content/uploads/enw-data-
tables-1-43.jpg)](https://meyerweb.com/eric/thoughts/wp-content/uploads/enw-
data-tables-1-43.jpg) Table 1.43 before and after the cells are shifted to
make their contents visually align.

This is exactly the same table, only with cells shifted to one side or another
in the second case. To make this happen, I first set up a series of CSS rules:

    
    
    figure.table .lp1 {transform: translateX(0.5ch);}
    figure.table .lp2 {transform: translateX(1ch);}
    figure.table .lp3 {transform: translateX(1.5ch);}
    figure.table .lp4 {transform: translateX(2ch);}
    figure.table .lp5 {transform: translateX(2.5ch);}
    
    figure.table .rp1 {transform: translateX(-0.5ch);}
    figure.table .rp2 {transform: translateX(-1ch);}

For a given class, the table cell is translated along the X axis by the
declared number of `ch` units. Yes, that means the table cells sharing a
column no longer actually sit in the column. No, I don’t care — and neither,
as I said, does CSS.

I chose the labels `lp` and `rp` for “left pad” and “right pad”, in part as a
callback to [the left-pad
debacle](https://www.theregister.com/2016/03/23/npm_left_pad_chaos/) of yore
even though it has basically nothing to do with what I’m doing here. (Many of
my class names are private jokes to myself. We take our pleasures where we
can.) The number in each class name represents the number of “characters” to
pad, which here increment by half-`ch` measures. Since I was trying to move
things by characters, using the unit that looks like it’s a character measure
(even though [it really
isn’t](https://meyerweb.com/eric/thoughts/2018/06/28/what-is-the-css-ch-
unit/)) made sense to me.

With those rules set up, I could add simple classes to table cells that needed
to be shifted, like so:

    
    
    <td class="lp3">5 ± 0.5</td>
    
    <td class="rp2">10</td>

That was most of the solution, but it turned out to not be quite enough. See,
things like decimal places and commas aren’t as wide as the numbers
surrounding them, and sometimes that was enough to prevent a specific cell
from being able to line up with the rest of its column. There were also
situations where the data cells could all be aligned with each other, but were
unacceptably offset from the column header, which was nearly always centered.

So I decided to `calc()` the crap out of this to add the flexibility a custom
property can provide. First, I set a sitewide variable:

    
    
    body {
    	--offset: 0ch;
    }

I then added that variable to the various transforms:

    
    
    figure.table .lp1 {transform: translateX(calc(0.5ch + var(--offset)));}
    figure.table .lp2 {transform: translateX(calc(1ch   + var(--offset)));}
    figure.table .lp3 {transform: translateX(calc(1.5ch + var(--offset)));}
    figure.table .lp4 {transform: translateX(calc(2ch   + var(--offset)));}
    figure.table .lp5 {transform: translateX(calc(2.5ch + var(--offset)));}
    
    figure.table .rp1 {transform: translateX(calc(-0.5ch + var(--offset)));}
    figure.table .rp2 {transform: translateX(calc(-1ch   + var(--offset)));}

Why use a variable at all? Because it allows me to define offsets specific to
a given table, or even specific to certain table cells within a table.
Consider the styles embedded along with Table 3.66:

    
    
    #tbl3-66 tbody tr:first-child td:nth-child(1),
    #tbl3-66 tbody td:nth-child(7) {
    	--offset: 0.25ch;
    }
    #tbl3-66 tbody td:nth-child(4) {
    	--offset: 0.1ch;	
    }

Yeah. The first cell of the first row and the seventh cell of every row in the
table body needed to be shoved over an extra quarter-`ch`, and the fourth cell
in every table-body row (under the heading “Sp”) got a tenth-`ch` nudge. You
can judge [the
results](https://atomicarchive.com/resources/documents/effects/glasstone-
dolan/chapter3.html#tbl3-66) for yourself.

So, in the end, I needed only sprinkle class names around table markup where
needed, and add a little extra offset via a custom property that I could scope
to exactly where needed. Sure, the whole setup is hackier than a panel of
professional political pundits, but it works, and to my mind, it beats the
alternatives.

I’d have been a lot happier if I could have aligned some of the columns on a
specific character. I think I still would have needed the left- and right-pad
approach, but there were a lot of columns where I could have reduced or
eliminated all the classes. A quarter-century ago, [HTML 4 had this
capability](https://www.w3.org/TR/html4/struct/tables.html#adef-align-TD), in
that you could write:

    
    
    <COLGROUP>
    	<COL>
    	<COL>
    	<COL align="±">
    </COLGROUP>

CSS2 was also given this power via `text-align`, where you could [give it a
string value in order to specify horizontal
alignment](https://www.w3.org/TR/1998/REC-CSS2-19980512/tables.html#column-
alignment).

But browsers never really supported these features, even if some of them do
[still have bugs open on the
issue](https://bugzilla.mozilla.org/show_bug.cgi?id=2212). (I chuckle aridly
every time I go there and see “Opened 24 years ago” a few lines above “Status:
NEW”.) I know it’s not top of anybody’s wish list, but I wouldn’t mind seeing
that capability return, somehow. Maybe as something that could be used in Grid
column tracks as well as table columns.

I also found myself really pining for the ability to use `attr()` here, which
would have allowed me to drop the classes and use `data-*` attributes on the
table cells to say how far to shift them. I could even have dropped the offset
variable. Instead, it could have looked something like this:

    
    
    <td data-pad="3.25">5 ± 0.5</td>
    
    <td data-pad="-1.9">10</td>
    
    
    figure.table *[data-pad] {transform: translateX(attr(data-pad,'ch'));}
    

Alas, `attr()` is confined to the `content` property, and the idea of letting
it be used more widely remains unrealized.

Anyway, that was my journey into recreating mid-20th-Century table column
alignment on the Web. It’s true that sufficiently old browsers won’t get the
fancy alignment due to not supporting custom properties or `calc()`, but the
data will all still be there. It just won’t have the very specific column
alignment, that’s all. Hooray for progressive enhancement!

  * [Table Column Alignment with Variable Transforms](https://meyerweb.com/eric/thoughts/2022/08/15/table-column-alignment-with-variable-transforms/) was published on Monday, August 15th, 2022.
  * It was assigned to the [Browsers](https://meyerweb.com/eric/thoughts/category/tech/browsers/), [CSS](https://meyerweb.com/eric/thoughts/category/tech/css/), [Hacks](https://meyerweb.com/eric/thoughts/category/hacks/), [Standards](https://meyerweb.com/eric/thoughts/category/tech/standards/), and [Web](https://meyerweb.com/eric/thoughts/category/tech/web/) categories.
  * There have been [three replies](https://meyerweb.com/eric/thoughts/2022/08/15/table-column-alignment-with-variable-transforms/#comments).

* * *

## [Recreating “The Effects of Nuclear Weapons” for the
Web](https://meyerweb.com/eric/thoughts/2022/08/09/recreating-the-effects-of-
nuclear-weapons-for-the-web/ "Permanent Link: Recreating “The Effects of
Nuclear Weapons” for the Web")

_Published 3 months, 2 weeks past_

In my [previous post](https://meyerweb.com/eric/thoughts/2022/04/26/flexibly-
centering-an-element-with-side-aligned-content/), I wrote about a way to
center elements based on their content, without forcing the element to be a
specific width, while preserving the interior text alignment. In this post,
I’d like to talk about why I developed that technique.

Near the beginning of this year, fellow Web nerd and nuclear history buff
Chris Griffith mentioned a project to put an entire book online: The Effects
of Nuclear Weapons by Samuel Glasstone and Philip J. Dolan, specifically the
third (1977) edition. Like Chris, I own a physical copy of this book, and in
fact, the information and tools therein were critical to the creation of
[HYDEsim](https://meyerweb.com/eric/tools/gmap/hydesim.html), way back in the
Aughts. I acquired it while in pursuit of my degree in History, for which I
studied the Cold War and the policy effects of the nuclear arms race, from the
first bombers to the Strategic Defense Initiative.

I was immediately intrigued by the idea and volunteered my technical services,
which Chris accepted. So we started taking the OCR output of a PDF scan of the
book, cleaning up the myriad errors, re-typing the bits the OCR mangled too
badly to just clean up, structuring it all with HTML, converting figures to
PNGs and photos to JPGs, and styling the whole thing for publication, working
after hours and in odd down times to bring this historical document to the Web
in a widely accessible form. The result of all that work [is now
online](https://atomicarchive.com/resources/documents/effects/glasstone-
dolan/).

That linked page is the best example of the technique I wrote about in the
aforementioned [previous
post](https://meyerweb.com/eric/thoughts/2022/04/26/flexibly-centering-an-
element-with-side-aligned-content/): as a Table of Contents, none of the lines
actually get long enough to wrap. Rather than figuring out the exact length of
the longest line and centering based on that, I just let CSS do the work for
me.

There were a number of other things I invented (probably re-invented) as we
progressed. Footnotes appear at the bottom of pages when the footnote number
is activated through the use of the `:target` pseudo-class and some fixed
positioning. It’s not completely where I wanted it to be, but I think the rest
will require JS to pull off, and my aim was to keep the scripting to an
absolute minimum.

[![](https://meyerweb.com/eric/thoughts/wp-content/uploads/enw-math-
crop.png)](https://meyerweb.com/eric/thoughts/wp-content/uploads/enw-math-
crop.png) LaTeX and MathJax made writing and rendering this sort of thing very
easy.

I couldn’t keep the scripting to zero, because we decided early on to use
[MathJax](https://www.mathjax.org/) for the many formulas and other
mathematical expressions found throughout the text. I’d never written LaTeX
before, and was very quickly impressed by how compact and yet powerful the
syntax is.

Over time, I do hope to replace the MathJax-parsed LaTeX with raw MathML for
both accessibility and project-weight reasons, but as of this writing,
Chromium lacks even halfway-decent MathML support, so we went with the more
widely-supported solution. (My colleague [Frédéric
Wang](https://www.igalia.com/team/fwang) at [Igalia](https://igalia.com/) is
pushing hard to fix this sorry state of affairs in Chromium, so I do have
hopes for a migration to MathML… some day.)

The figures (as distinct from the photos) throughout the text presented an
interesting challenge. To look at them, you’d think SVG would be the ideal
image format. Had they come as vector images, I’d agree, but they’re raster
scans. I tried recreating one or two in hand-crafted SVG and quickly
determined the effort to create each was significant, and really only worked
for the figures that weren’t charts, graphs, or other presentations of data.
For anything that _was_ a chart or graph, the risk of introducing inaccuracies
was too high, and again, each would have required an inordinate amount of
effort to get even close to correct. That’s particularly true considering that
without knowing what font face was being used for the text labels in the
figures, they’d have to be recreated with paths or polygons or whatever,
driving the cost-to-recreate astronomically higher.

So I made the figures PNGs that are mostly transparent, except for the places
where there was ink on the paper. After any necessary straightening and some
imperfection cleanup in [Acorn](https://flyingmeat.com/acorn/), I then ran the
PNGs through the color-index optimization process I [wrote about back in
2020](https://meyerweb.com/eric/thoughts/2020/04/22/better-image-optimization-
by-restricting-the-color-index/), which got them down to an average of 75
kilobytes each, ranging from 443KB down to 7KB.

At the 11th hour, still secretly hoping for a magic win, I ran them all
through [svgco.de](https://svgco.de) to see if we could get automated savings.
Of the 161 figures, exactly eight of them were made smaller, which is not a
huge surprise, given the source material. So, I saved those eight for possible
future updates and plowed ahead with the optimized PNGs. Will I return to this
again in the future? Probably. It bugs me that the figures could be better,
and yet aren’t.

It also bugs me that we didn’t get all of the figures and photos fully
described in `alt` text. I did write up alternative text for the figures in
[Chapter I](https://atomicarchive.com/resources/documents/effects/glasstone-
dolan/chapter1.html), and a few of the photos have semi-decent captions, but
this was something we didn’t see all the way through, and like I say, that
bugs me. If it also bugs you, please feel free to fork [the
repository](https://github.com/chrisgriffith/glasstone-dolan/) and submit a
pull request with good `alt` text. Or, if you prefer, you could [open an
issue](https://github.com/chrisgriffith/glasstone-dolan/issues) and include
your suggested `alt` text that way. By the image, by the section, by the
chapter: whatever you can contribute would be appreciated.

Those image captions, by the way? In the printed text, they’re laid out as a
label (e.g., “Figure 1.02”) and then the caption text follows. But when the
text wraps, it doesn’t wrap below the label. Instead, it wraps in its own
self-contained block instead, with the text fully justified except for the
last line, which is centered. _Centered!_ So I set up the markup and CSS like
this:

    
    
    <figure>
    	<img src="…" alt="…" loading="lazy">
    	<figcaption>
    		<span>Figure 1.02.</span> <span>Effects of a nuclear explosion.</span>
    	</figcaption>
    </figure>
    
    
    figure figcaption {
    	display: grid;
    	grid-template-columns: max-content auto;
    	gap: 0.75em;
    	justify-content: center;
    	text-align: justify;
    	text-align-last: center;
    }

Oh CSS Grid, how I adore thee. And you too, CSS box alignment. You made this
little bit of historical recreation so easy, it felt like cheating.

[![](https://meyerweb.com/eric/thoughts/wp-content/uploads/enw-
table-1-43.png)](https://meyerweb.com/eric/thoughts/wp-content/uploads/enw-
table-1-43.png) Look at the way it’s all supposed to line up on the ± and one
number doesn’t even have a ± and that decimal is just hanging out there in
space like it’s no big deal. LOOK AT IT.

Some other things weren’t easy. The data tables, for example, have a tendency
to align columns on the decimal place, even when most but not all of the
numbers are integers. Long, long ago, it was proposed that `text-align` be
allowed a string value, something like `text-align: '.'`, which you could then
apply to a table column and have everything line up on that character. For a
variety of reasons, this was never implemented, a fact which frosts my windows
to this day. In general, I mean, though _particularly_ so for this project.
The lack of it made keeping the presentation historically accurate a right
pain, one I may get around to writing about, if I ever overcome my shame.
_[Editor’s note:[he overcame that
shame](https://meyerweb.com/eric/thoughts/2022/08/15/table-column-alignment-
with-variable-transforms/).]_

There are two things about the book that we deliberately chose not to
faithfully recreate. The first is the font face. My best guess is that the
book was typeset using something from the
[Century](https://docs.microsoft.com/en-us/typography/font-list/century)
family, possibly Century Schoolbook (the New version of which was a particular
favorite of mine in college). The very-widely-installed
[Cambria](https://docs.microsoft.com/en-us/typography/font-list/cambria) seems
fairly similar, at least to my admittedly untrained eye, and furthermore was
designed specifically for screen media, so I went with `body` text styling no
more complicated than this:

    
    
    body {
    	font: 1em/1.35 Cambria, Times, serif;
    	hyphens: auto;
    }

I suppose I could have tracked down a free version of Century and used it as a
custom font, but I couldn’t justify the performance cost in both download and
rendering speed to myself and any future readers. And the result really did
seem close enough to the original to accept.

The second thing we didn’t recreate is the printed-page layout, which is two-
column. That sort of layout can work very well on the book page; it almost
always stinks on a Web page. Thus, the content of the book is rendered online
in a single column. The exceptions are the chapter-ending Bibliography
sections and [the book’s
Index](https://atomicarchive.com/resources/documents/effects/glasstone-
dolan/bookindex.html), both of which contain content compact and granular
enough that we could get away with the original layout.

There’s a lot more I could say about how this style or that pattern came
about, and maybe someday I will, but for now let me leave you with this: all
these decisions are subject to change, and open to input. If you come up with
a superior markup scheme for any of the bits of the book, we’re happy to look
at pull requests or issues, and to act on them. It is, as we say in [our
preface to the online
edition](https://atomicarchive.com/resources/documents/effects/glasstone-
dolan/preface2022.html), a living project.

We also hope that, by laying bare the grim reality of these horrific weapons,
we can contribute in some small way to making them a dead and buri

TLS

Fingerprint
JA3S
475c9302dc42b2751db9edcac3b74891
Handshake
Version Selected
TLSv1_3
Cipher Selected
TLS_CHACHA20_POLY1305_SHA256
Leaf Certificate
05da37879a05d1d9394f7183063020cb9ec594f53e03b07077c0ec2ecfc4c655
CN=meyerweb.com
C=US, O=Let's Encrypt, CN=R3
Issuer Chain

465/SMTP TCP
Observed Nov 27, 2022 at 6:00pm UTC


View All Data

Software

linux
exim 4.95

Details

Banner
220-morse.multipattern.com ESMTP Exim 4.95 #2 Sun, 27 Nov 2022 18:00:51 +0000 
220-We do not authorize the use of this system to transport unsolicited, 
220 and/or bulk e-mail.
EHLO
250-morse.multipattern.com Hello scanner-04.ch1.censys-scanner.com [162.142.125.10]
250-SIZE 52428800
250-8BITMIME
250-PIPELINING
250-PIPE_CONNECT
250-AUTH PLAIN LOGIN
250 HELP

TLS

Fingerprint
JA3S
303951d4c50efb2e991652225a6f02b1
Handshake
Version Selected
TLSv1_2
Cipher Selected
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Leaf Certificate
cdf0ba93b94a16ad390eaddf891e310fd7e54439a50c20eb1197f04395ae3a57
CN=morse.multipattern.com
C=US, ST=TX, L=Houston, O=cPanel\, Inc., CN=cPanel\, Inc. Certification Authority
Issuer Chain

587/SMTP TCP
Observed Nov 27, 2022 at 11:27pm UTC


View All Data

Software

exim 4.95

Details

Banner
220-morse.multipattern.com ESMTP Exim 4.95 #2 Sun, 27 Nov 2022 23:27:01 +0000 
220-We do not authorize the use of this system to transport unsolicited, 
220 and/or bulk e-mail.
EHLO
250-morse.multipattern.com Hello scanner-05.ch1.censys-scanner.com [162.142.125.213]
250-SIZE 52428800
250-8BITMIME
250-PIPELINING
250-PIPE_CONNECT
250-AUTH PLAIN LOGIN
250-STARTTLS
250 HELP
Start TLS
220 TLS go ahead

TLS

Fingerprint
JA3S
303951d4c50efb2e991652225a6f02b1
Handshake
Version Selected
TLSv1_2
Cipher Selected
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Leaf Certificate
cdf0ba93b94a16ad390eaddf891e310fd7e54439a50c20eb1197f04395ae3a57
CN=morse.multipattern.com
C=US, ST=TX, L=Houston, O=cPanel\, Inc., CN=cPanel\, Inc. Certification Authority
Issuer Chain

993/IMAP TCP
Observed Nov 27, 2022 at 3:44pm UTC


View All Data

Software

linux

Details

Banner
* OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE NAMESPACE LITERAL+ AUTH=PLAIN AUTH=LOGIN] Dovecot ready.

TLS

Fingerprint
JARM
15d2ad16d29d29d00015d2ad15d29de87e6567d901388794cb6a875a1928aa
JA3S
303951d4c50efb2e991652225a6f02b1
Handshake
Version Selected
TLSv1_2
Cipher Selected
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Leaf Certificate
cdf0ba93b94a16ad390eaddf891e310fd7e54439a50c20eb1197f04395ae3a57
CN=morse.multipattern.com
C=US, ST=TX, L=Houston, O=cPanel\, Inc., CN=cPanel\, Inc. Certification Authority
Issuer Chain

995/POP3 TCP
Observed Nov 27, 2022 at 8:56pm UTC


View All Data

Software

linux
Dovecot

Details

Banner
+OK Dovecot ready.

TLS

Fingerprint
JA3S
303951d4c50efb2e991652225a6f02b1
Handshake
Version Selected
TLSv1_2
Cipher Selected
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Leaf Certificate
cdf0ba93b94a16ad390eaddf891e310fd7e54439a50c20eb1197f04395ae3a57
CN=morse.multipattern.com
C=US, ST=TX, L=Houston, O=cPanel\, Inc., CN=cPanel\, Inc. Certification Authority
Issuer Chain

2077/HTTP TCP
Observed Nov 27, 2022 at 2:56pm UTC


View All Data Go

Software

cPanel

Details

http://66.155.40.160:2077
Request
GET /
Protocol
HTTP/1.1
Status Code
302
Status Reason
Moved

2078/HTTP TCP
Observed Nov 27, 2022 at 3:48am UTC


View All Data Go

Software

cPanel

Details

https://66.155.40.160:2078
Request
GET /
Protocol
HTTP/1.1
Status Code
401
Status Reason
Unauthorized
Body Hash
sha1:90fb262bd867d1869c94dd3cb195f7e08398e35d
Response Body
Authorization Required

TLS

Fingerprint
JARM
29d29d15d29d29d00029d29d29d29dea0f89a2e5fb09e4d8e099befed92cfa
JA3S
ccc514751b175866924439bdbb5bba34
Handshake
Version Selected
TLSv1_2
Cipher Selected
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Leaf Certificate
cdf0ba93b94a16ad390eaddf891e310fd7e54439a50c20eb1197f04395ae3a57
CN=morse.multipattern.com
C=US, ST=TX, L=Houston, O=cPanel\, Inc., CN=cPanel\, Inc. Certification Authority
Issuer Chain

2079/HTTP TCP
Observed Nov 27, 2022 at 12:33pm UTC


View All Data Go

Software

cPanel

Details

http://66.155.40.160:2079
Request
GET /
Protocol
HTTP/1.1
Status Code
302
Status Reason
Moved

2080/HTTP TCP
Observed Nov 27, 2022 at 2:41pm UTC


View All Data Go

Software

cPanel

Details

https://66.155.40.160:2080
Request
GET /
Protocol
HTTP/1.1
Status Code
401
Status Reason
Unauthorized
Body Hash
sha1:90fb262bd867d1869c94dd3cb195f7e08398e35d
Response Body
Authorization Required

TLS

Fingerprint
JARM
29d29d15d29d29d00029d29d29d29dea0f89a2e5fb09e4d8e099befed92cfa
JA3S
ccc514751b175866924439bdbb5bba34
Handshake
Version Selected
TLSv1_2
Cipher Selected
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Leaf Certificate
cdf0ba93b94a16ad390eaddf891e310fd7e54439a50c20eb1197f04395ae3a57
CN=morse.multipattern.com
C=US, ST=TX, L=Houston, O=cPanel\, Inc., CN=cPanel\, Inc. Certification Authority
Issuer Chain

2082/HTTP TCP
Observed Nov 27, 2022 at 3:20am UTC


View All Data Go

Details

http://66.155.40.160:2082
Request
GET /
Protocol
HTTP/1.1
Status Code
301
Status Reason
Moved
Body Hash
sha1:edc572e37a1ed0684c38325f38b33ed1b5dcbf43
Response Body

2083/HTTP TCP
Observed Nov 27, 2022 at 5:35am UTC


View All Data Go

Software

cPanel

Details

https://66.155.40.160:2083
Request
GET /
Protocol
HTTP/1.1
Status Code
200
Status Reason
OK
Body Hash
sha1:d00efdebea4f9dcb65362162ffafdf7cee8ad31f
HTML Title
cPanel Login
Response Body
![Error](/cPanel_magic_revision_1610662436/unprotected/cpanel/images/notice-
error.png) JavaScript is disabled in your browser. For cPanel to function
properly, you must enable JavaScript. If you do not enable JavaScript, certain
features in cPanel will not function correctly.

You have logged out.

The system has detected that you are using Internet Explorer 11. cPanel & WHM
no longer supports Internet Explorer 11. For more information, read the
[cPanel Blog](https://go.cpanel.net/ie11deprecation "cPanel Blog").

Please select a locale:

[X Close](javascript:void\(0\))

[Deutsch](?locale=de)

[English](?locale=en)

[español de España](?locale=es_es)

[i_en](?locale=i_en)

[русский](?locale=ru)

![logo](/cPanel_magic_revision_1610662436/unprotected/cpanel/images/cpanel-
logo.svg)

Continue

Username

Password

Log in

Change locale DeutschEnglishespañol de Españai_enрусский Change

  * [Deutsch](/?locale=de)
  * [English](/?locale=en)
  * [español de España](/?locale=es_es)
  * [i_en](/?locale=i_en)
  * [русский](/?locale=ru)

Select a locale: [English](javascript:void\(0\) "Change locale")

Copyright© 2022 cPanel, L.L.C.  
[Privacy Policy](https://go.cpanel.net/privacy)

TLS

Fingerprint
JA3S
ccc514751b175866924439bdbb5bba34
Handshake
Version Selected
TLSv1_2
Cipher Selected
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Leaf Certificate
cdf0ba93b94a16ad390eaddf891e310fd7e54439a50c20eb1197f04395ae3a57
CN=morse.multipattern.com
C=US, ST=TX, L=Houston, O=cPanel\, Inc., CN=cPanel\, Inc. Certification Authority
Issuer Chain

2086/HTTP TCP
Observed Nov 27, 2022 at 8:14pm UTC


View All Data Go

Software

cPanel WHM

Details

http://66.155.40.160:2086
Request
GET /
Protocol
HTTP/1.0
Status Code
401
Status Reason
Access Denied
Body Hash
sha1:3790b698b61ecff0af4b50bafabd9f4e2adf3f0f
HTML Title
WHM Login
Response Body
## HTTP error 401

##

You do not have permission to access this page.

Copyright© 2022 cPanel, L.L.C.  
[Privacy Policy](https://go.cpanel.net/privacy)

2091/HTTP TCP
Observed Nov 26, 2022 at 12:35am UTC


View All Data Go

Software

linux
cPanel

Details

https://66.155.40.160:2091
Request
GET /
Protocol
HTTP/1.1
Status Code
401
Status Reason
Unauthorized
Body Hash
sha1:90fb262bd867d1869c94dd3cb195f7e08398e35d
Response Body
Authorization Required

TLS

Fingerprint
JARM
29d29d15d29d29d00029d29d29d29dea0f89a2e5fb09e4d8e099befed92cfa
JA3S
ccc514751b175866924439bdbb5bba34
Handshake
Version Selected
TLSv1_2
Cipher Selected
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Leaf Certificate
cdf0ba93b94a16ad390eaddf891e310fd7e54439a50c20eb1197f04395ae3a57
CN=morse.multipattern.com
C=US, ST=TX, L=Houston, O=cPanel\, Inc., CN=cPanel\, Inc. Certification Authority
Issuer Chain

2095/HTTP TCP
Observed Nov 26, 2022 at 12:21pm UTC


View All Data Go

Details

http://66.155.40.160:2095
Request
GET /
Protocol
HTTP/1.1
Status Code
301
Status Reason
Moved
Body Hash
sha1:f39325044ecf5ec9d3e8364db0674c02f10ed4fb
Response Body

2096/HTTP TCP
Observed Nov 28, 2022 at 2:06am UTC


View All Data Go

Software

cPanel

Details

https://66.155.40.160:2096
Request
GET /
Protocol
HTTP/1.1
Status Code
200
Status Reason
OK
Body Hash
sha1:f1176a7e0bdfa44ff6418db778f9aa46148e33fe
HTML Title
Webmail Login
Response Body
![Error](/cPanel_magic_revision_1610662436/unprotected/cpanel/images/notice-
error.png) JavaScript is disabled in your browser. For Webmail to function
properly, you must enable JavaScript. If you do not enable JavaScript, certain
features in Webmail will not function correctly.

You have logged out.

The system has detected that you are using Internet Explorer 11. cPanel & WHM
no longer supports Internet Explorer 11. For more information, read the
[cPanel Blog](https://go.cpanel.net/ie11deprecation "cPanel Blog").

Please select a locale:

[X Close](javascript:void\(0\))

[Deutsch](?locale=de)

[English](?locale=en)

[español de España](?locale=es_es)

[i_en](?locale=i_en)

[русский](?locale=ru)

![logo](/cPanel_magic_revision_1610662436/unprotected/cpanel/images/webmail-
logo.svg)

Continue

Email Address

Password

Log in

Change locale DeutschEnglishespañol de Españai_enрусский Change

  * [Deutsch](/?locale=de)
  * [English](/?locale=en)
  * [español de España](/?locale=es_es)
  * [i_en](/?locale=i_en)
  * [русский](/?locale=ru)

Select a locale: [English](javascript:void\(0\) "Change locale")

Copyright© 2022 cPanel, L.L.C.  
[Privacy Policy](https://go.cpanel.net/privacy)

TLS

Fingerprint
JA3S
ccc514751b175866924439bdbb5bba34
Handshake
Version Selected
TLSv1_2
Cipher Selected
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Leaf Certificate
cdf0ba93b94a16ad390eaddf891e310fd7e54439a50c20eb1197f04395ae3a57
CN=morse.multipattern.com
C=US, ST=TX, L=Houston, O=cPanel\, Inc., CN=cPanel\, Inc. Certification Authority
Issuer Chain

Geographic Location

City
Los Angeles
State
California
Country
United States (US)
Coordinates
34.0544, -118.2441
Timezone
America/Los_Angeles