Die Motive dieser Site sind Strichzeichnungen: der Nighthog und sein Blechroboter, blaue Linien auf Schwarz, immer zu zweit, immer mit derselben Arbeitsteilung. Der Roboter arbeitet die Menge ab, der Hog urteilt. Ob diese Welt auch einen Cartoon-Strip trägt, war offen. Sie hat keinen Grauwert, keine Farbfläche, nichts, worin eine Sprechblase Halt findet. Hier ist die Antwort.

Roboter:Zwölf Meter. In einer Stunde!
Panel 1 von 2
Nighthog:Beeindruckend. Und jetzt komm da raus.
Panel 2 von 2Warum die Blasen leer bleiben
Kein Bildgenerator setzt zuverlässig Schrift. Umlaute verkrüppeln, Wörter verrutschen, aus „Zwölf” wird „Zwoolf”. Also werden die Blasen leer generiert, und zwar ausdrücklich: „One large EMPTY speech bubble, completely empty inside.” Der Text kommt danach.
Der naheliegende Weg wäre, ihn nach der Generierung ins PNG zu montieren, ein Dutzend Zeilen Pillow genügen dafür. Auf einer Site, die über Typografie und Flächen lebt, wäre eingebrannter Text aber die schlechtere Hälfte von allem: unscharf beim Zoomen, nicht markierbar, nicht durchsuchbar, für Screenreader unsichtbar, und jede Korrektur eines Tippfehlers heißt neu rendern. Der Text liegt deshalb in einer Datendatei und sitzt per CSS in der Blase. Was du oben liest, kannst du mit der Maus markieren.
Zwei Dateien, kein Bildtext
src/data/strips.ts ist die einzige Quelle. Eine Blase ist ein Text plus ihr
Sitz im Panel:
export interface Blase {
text: string;
sprecher: Sprecher; // trägt die Screenreader-Zuordnung
x: number; // Mitte der Blase, % der Panelbreite
y: number; // Mitte der Blase, % der Panelhöhe
breite: number; // Textspalte, % der Panelbreite
}
src/components/Strip.astro legt den Text darüber. Kein Island, kein
JavaScript, und die Schriftgröße hängt an der Panelbreite statt am Viewport:
.strip-blase {
position: absolute;
transform: translate(-50%, -50%);
font-family: var(--font-mono);
/* Skaliert mit dem Panel, nicht mit dem Viewport. */
font-size: clamp(0.6875rem, 3.2cqw, 1.05rem);
}
Dass in der Blase Monospace steht, war zuerst Verlegenheit und dann Absicht. Eine Comic-Schrift wäre in dieser Site ein Fremdkörper. JetBrains Mono liest sich in einer technischen Zeichnung wie die Beschriftung, die dort sowieso hingehört.
Der sprecher ist kein Zierfeld. Er wird zu einem sr-only-Präfix vor dem
Blasentext, deshalb liest ein Screenreader den Strip als Dialog vor: erst die
Szenenbeschreibung aus dem alt, dann „Roboter: Zwölf Meter. In einer
Stunde!“. Ein Strip mit eingebranntem Text ist an dieser Stelle einfach still.
Prozent statt Pixel
Die Koordinaten stehen in Prozent der Panelkante, nicht in Pixeln. Der Grund ist unspektakulär und hat sich sofort bezahlt: Die Rohbilder kommen mit 2048 Pixeln aus der Generierung, im Repo liegen sie mit 1024. Pixelkoordinaten hätten diesen Schritt nicht überlebt.
Was die Maschine nicht wollte
Der erste Versuch hatte drei Panels, weil Comics drei Panels haben. Das ging nicht auf. Ab Panel zwei gibt man das erste Panel als zusätzliche Referenz mit, damit der Ort derselbe bleibt, und das funktioniert erschreckend gut: Mörtelkübel, Kelle und die losen Ziegel standen in allen Panels an derselben Stelle. Nur klebt das Modell dann eben auch an der Komposition. „Closer medium shot” hat es ignoriert, und Panel eins und zwei waren fast dasselbe Bild. Ein stummer Mittel-Beat, den man nicht von seinem Vorgänger unterscheiden kann, erzählt nichts. Zwei Panels, Aufbau und Pointe, waren die Lösung.
Der zweite Widerstand waren die Maßlinien. Das Referenzbild ist der Hero der Startseite, und dort gehören dünne Maßpfeile zum Motiv. Sie im Prompt zu verbieten, reichte nicht, auch nicht in Großbuchstaben mit fünf Synonymen. Was ging: das fertige Bild noch einmal schicken und nur löschen lassen, mit der Auflage, alles andere unangetastet zu lassen. Ein Durchgang, danach war das Panel sauber.
Die Linien messen
Strichbilder dieser Site laufen über mix-blend-mode: lighten auf schwarzem
Grund. Schwarz ist für lighten neutral, damit ist der Bildgrund exakt die
Seitenfarbe. Was dabei auffällt, sobald zwei Bilder nebeneinander liegen: Die
Renders schwanken in der Linienhelligkeit. Die beiden Panels kamen mit
Luminanz-p99 182 und 177 aus der Generierung, und schon diese kleine Differenz
sieht man im Streifen. scripts/strip-panels.mjs misst deshalb jedes Panel und
zieht es per sharp.linear auf denselben Zielwert:
public/images/strip/zwoelf-meter-1.webp: p99 182 → gain 1.10
public/images/strip/zwoelf-meter-2.webp: p99 177 → gain 1.13
Ziel ist hier 200, nicht die 150 der Hintergrund-Motive. Ein Strip ist Inhalt bei voller Deckkraft und kein abgedimmter Hintergrund.
Ein Detail noch, gefunden beim Sichttest: Unter 40 rem stapeln die Panels, statt zu schrumpfen. Schrumpfende Panels drücken den Blasentext irgendwann aus der Blase, weil die Schrift eine Untergrenze hat und die Blase nicht. Der Strip wird auf dem Telefon also länger, nicht kleiner.