revert: keep the wordmark's original letter-spacing

Tightening the gaps bought letters a third taller at the same width,
which helped the hairlines — but it changed the logotype's character,
and the shop prefers the drawing as it was designed. The logo returns to
260x36 with its spacing intact.

The threshold fix that made the A's diagonal survive stays: that was a
separate problem and it is still solved.

lib/brand/tighten.ts and `npm run brand:variants` are kept rather than
deleted. Both are tested, the variants script is also how the threshold
itself was chosen, and a spacing decision is one to revisit by looking
at renders rather than by imagining them.

The logo's rendered size is still read from the PNG header rather than
copied into the renderer, which is what made this reversal a one-line
change with nothing to keep in sync.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012cSY9pVhZmJUKNN7wf1Myd
This commit is contained in:
2026-09-21 23:35:38 +02:00
co-authored by Claude Opus 5
parent 49f103c0a0
commit 879536986f
2 changed files with 9 additions and 25 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 505 B

After

Width:  |  Height:  |  Size: 393 B

+9 -25
View File
@@ -21,7 +21,6 @@ import path from 'node:path';
import sharp from 'sharp'; import sharp from 'sharp';
import { tighten } from '../lib/brand/tighten';
import { encodePng, toBitmap } from '../lib/screen/encode'; import { encodePng, toBitmap } from '../lib/screen/encode';
const LOGO_URL = const LOGO_URL =
@@ -30,15 +29,15 @@ const LOGO_URL =
/** Wide enough to read from the pavement, short enough for a 76px header. */ /** Wide enough to read from the pavement, short enough for a 76px header. */
const EINK_WIDTH = 260; const EINK_WIDTH = 260;
/** /*
* How many blank pixel columns may remain between two letters. * The wordmark keeps its original letter-spacing.
* *
* The logotype is drawn with wide spacing, which reads well on a website and * Compressing the gaps was tried: it buys letters a third taller at the same
* wastes a third of the width on a panel. Compressing the gaps lets the same * width, which helps the hairlines. It also changes the logotype's character,
* 260px hold letters a third taller — which the hairlines need more than the * and the shop prefers the drawing as it was designed. `lib/brand/tighten.ts`
* spacing does. Rendered at several values by `npm run brand:variants`. * and `npm run brand:variants` remain, so the decision can be revisited by
* looking rather than by imagining.
*/ */
const EINK_LETTER_GAP = 8;
/** /**
* Where grey becomes ink. * Where grey becomes ink.
@@ -67,25 +66,10 @@ async function main(): Promise<void> {
await writeFile(path.join(directory, 'logo.png'), original); await writeFile(path.join(directory, 'logo.png'), original);
const band = await findWordmarkBand(original); const band = await findWordmarkBand(original);
const cropped = await sharp(original)
// Tighten at full resolution, before any downscale: compressing columns that
// are already an average of ink and paper would smear the hairlines.
const full = await sharp(original)
.extract({ left: 0, top: band.top, width: band.width, height: band.height }) .extract({ left: 0, top: band.top, width: band.width, height: band.height })
.flatten({ background: '#ffffff' })
.greyscale()
.raw()
.toBuffer({ resolveWithObject: true });
const tightened = tighten(
{ data: full.data, width: full.info.width, height: full.info.height },
EINK_LETTER_GAP,
);
const cropped = await sharp(tightened.data, {
raw: { width: tightened.width, height: tightened.height, channels: 1 },
})
.resize({ width: EINK_WIDTH }) .resize({ width: EINK_WIDTH })
.flatten({ background: '#ffffff' })
.ensureAlpha() .ensureAlpha()
.raw() .raw()
.toBuffer({ resolveWithObject: true }); .toBuffer({ resolveWithObject: true });