Popups: render the source page's monogram in internal previews

Internal-page hover popups now show the source's monogram alongside
the title / abstract / metadata when one exists. Two-column grid is
gated on .has-monogram so popups for pieces without an authored mark
keep their default single-column body. The serialised SVG comes from
the rendered page's own .frontmatter-mark--monogram figure, excluded
when it is the symmetric-layout placeholder roundel so empty-slot
pieces do not get a fake mark in the preview.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Levi Neuwirth 2026-05-23 12:06:35 -04:00
parent a3b3457803
commit 70dda56625
2 changed files with 48 additions and 1 deletions

View File

@ -36,6 +36,40 @@
SHARED POPUP CONTENT SHARED POPUP CONTENT
============================================================ */ ============================================================ */
/* Internal-page popups with a monogram render in two columns:
the monogram on the left, title + abstract + meta on the right.
Without a monogram, the body fills normally (default block flow). */
.popup-internal.has-monogram {
display: grid;
grid-template-columns: 56px minmax(0, 1fr);
gap: 0.65rem;
align-items: start;
}
/* Source label spans both columns when a monogram is present so it
reads as the popup's source attribution, not as a column entry. */
.popup-internal.has-monogram > .popup-source {
grid-column: 1 / -1;
}
.popup-monogram {
grid-column: 1;
line-height: 0;
color: var(--text);
}
.popup-monogram svg {
display: block;
width: 100%;
height: auto;
color: inherit;
}
.popup-internal-body {
grid-column: 2;
min-width: 0;
}
.popup-title { .popup-title {
font-weight: 600; font-weight: 600;
color: var(--text); color: var(--text);

View File

@ -348,6 +348,16 @@
var titleEl = doc.querySelector('h1.page-title'); var titleEl = doc.querySelector('h1.page-title');
if (!titleEl) return null; if (!titleEl) return null;
/* Monogram \u2014 only when the source page renders a real
authored mark.svg (not the placeholder roundel that
the empty-frontmatter slot uses for symmetric layout).
Serialised as an outerHTML string and trusted as
already-sanitised SVG produced by our own build. */
var monoEl = doc.querySelector(
'figure.frontmatter-mark--monogram:not(.frontmatter-mark--placeholder) svg'
);
var mono = monoEl ? monoEl.outerHTML : '';
/* Abstract */ /* Abstract */
var abstrEl = doc.querySelector('.meta-description'); var abstrEl = doc.querySelector('.meta-description');
var abstract = abstrEl ? abstrEl.textContent.trim() : ''; var abstract = abstrEl ? abstrEl.textContent.trim() : '';
@ -375,13 +385,16 @@
].filter(Boolean).join(' · '); ].filter(Boolean).join(' · ');
return store(href, return store(href,
'<div class="popup-internal">' '<div class="popup-internal' + (mono ? ' has-monogram' : '') + '">'
+ srcHtml('internal', 'levineuwirth.org') + srcHtml('internal', 'levineuwirth.org')
+ (mono ? '<div class="popup-monogram" aria-hidden="true">' + mono + '</div>' : '')
+ '<div class="popup-internal-body">'
+ (tags ? '<div class="popup-tags">' + esc(tags) + '</div>' : '') + (tags ? '<div class="popup-tags">' + esc(tags) + '</div>' : '')
+ '<div class="popup-title">' + esc(titleEl.textContent.trim()) + '</div>' + '<div class="popup-title">' + esc(titleEl.textContent.trim()) + '</div>'
+ (authors ? '<div class="popup-authors">' + esc(authors) + '</div>' : '') + (authors ? '<div class="popup-authors">' + esc(authors) + '</div>' : '')
+ (abstract ? '<div class="popup-abstract">' + esc(abstract) + '</div>' : '') + (abstract ? '<div class="popup-abstract">' + esc(abstract) + '</div>' : '')
+ (stats ? '<div class="popup-meta">' + esc(stats) + '</div>' : '') + (stats ? '<div class="popup-meta">' + esc(stats) + '</div>' : '')
+ '</div>'
+ '</div>'); + '</div>');
}) })
.catch(function () { return null; }); .catch(function () { return null; });