feat: tighten the wordmark's letter-spacing for the panel

The logotype is drawn with wide spacing — handsome on a website, and a
third of the panel's header width spent on nothing. The spacing is
artwork, not typesetting, so no property adjusts it; but every pixel
column between two letters is blank, and a blank column carries no
shape. Dropping most of them moves the letters together without altering
a single letterform.

At the same 260px the capitals are now a third taller, which the
hairlines needed more than the spacing did: the A of ITA reads at a
glance instead of being rescued by a threshold.

Done at full resolution, before the downscale. Compressing columns that
are already an average of ink and paper would smear exactly the strokes
this logo can least afford to lose.

The rendered size is now read from the PNG's own header rather than kept
as a constant beside it. The spacing is adjustable and every value
changes the height; a number copied into the renderer would have drifted
and squashed the logo with nothing failing to say so.

`npm run brand:variants` renders the spacings side by side, magnified,
since this is a decision to be looked at rather than reasoned about.

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:32:19 +02:00
co-authored by Claude Opus 5
parent 61074d02f9
commit 49f103c0a0
9 changed files with 266 additions and 42 deletions
+13
View File
@@ -0,0 +1,13 @@
import { describe, expect, it } from 'vitest';
import { encodePng, toBitmap } from './encode';
import { readPngSize } from './logo';
describe('readPngSize', () => {
it('reads the dimensions a PNG declares', () => {
// Built rather than fixtured, so the test cannot drift from the encoder.
const rgba = Buffer.alloc(17 * 5 * 4, 255);
const png = encodePng(toBitmap(rgba, 17, 5));
expect(readPngSize(png)).toEqual({ width: 17, height: 5 });
});
});