diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..31b1afb
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,127 @@
+# Changelog
+
+What changed, newest first. One entry per round that went out as an image, with
+the digests, so it stays possible to tell what is actually running on the server.
+
+Digests are recorded from the registry (`docker buildx imagetools inspect`),
+not from the output of `docker push`.
+
+---
+
+## 2026-08-11 — The writing column
+
+**Images**
+- `inknote-web` — see the entry below this one; the web image was rebuilt after
+ the revert, and the digest is written in when it is pushed
+- `inknote-server` — unchanged, `sha256:1648498f…`
+
+**Changed**
+- The note column is centred again. It had been pinned to the left margin so the
+ start of every line would always be in the same place; on a wide window that
+ left the whole right half of the pane as one dead block.
+- A page surface was drawn behind the text to give that block a meaning, and
+ reverted the same day: it made the sheet sit hard against the left edge, which
+ was worse than the problem it solved.
+
+---
+
+## 2026-08-11 — Pages, typefaces, alignment
+
+**Images** — web `sha256:3b040d99…`, server `sha256:1648498f…`
+
+**Added**
+- **Page count while writing.** The toolbar says *Page 2 of 4*, in the same words
+ the PDF reader uses. Pages are counted, never stored: the note stays one
+ document, and a test asserts no page ever reaches the stored body.
+- **The typeface is a per-account setting** — serif, sans or mono, chosen under
+ Account → Profile. On the account rather than in the browser, so it follows you
+ to the phone.
+- **Text alignment**, with its own TipTap extension rather than the official one,
+ so the schema stays in files this project owns. Left is the default and is
+ never written into the document. In Markdown, non-left blocks travel as
+ `
` — the one form most readers still honour — and the importer
+ reads it back onto the paragraphs.
+
+**Fixed**
+- The Markdown exporter did not put a blank line between top-level blocks, so
+ consecutive paragraphs ran together in other readers.
+
+---
+
+## 2026-08-11 — English throughout, and the PDF toolbar
+
+**Added**
+- **Search inside a notebook**, from the note list. The sidebar's global search
+ was removed: searching from inside a notebook should mean searching *that*
+ notebook.
+- **New note / Upload PDF / Import Markdown** all live under the one `+` button.
+
+**Changed**
+- The interface is English throughout. It had drifted into two languages.
+- The two visibility switches — drawing and margin notes — sit together at the
+ far right of the PDF toolbar, because they mean the same kind of thing.
+- The drawing tools appear next to the *Draw* button, not past everything else.
+- A separator is renamed and removed by right-click, with a confirmation for the
+ removal.
+
+**Fixed**
+- Hiding the drawing also hid the margin notes. Each switch now hides only its
+ own thing.
+
+---
+
+## 2026-08-10 — Notes on passages
+
+**Added**
+- **Pinned notes in a PDF.** A remark can be attached to a passage, and is shown
+ in the margin beside the page — not written on top of it. On a phone, where
+ there is no margin, the same notes open as a bottom sheet.
+- **Margin notes can be linked from the notes panel**, so a pinned remark can be
+ written about at length and still lead back to the passage it came from.
+
+**Fixed**
+- A grey drag indicator stayed visible in the note list after a drag. It was a
+ `borderTop` sitting beside a `border` shorthand in one style object.
+- The server stored an overlay holding only pinned notes as `NULL`, throwing
+ every one of them away, because it counted strokes and nothing else.
+
+---
+
+## 2026-08-09 — Arranging a notebook
+
+**Added**
+- **Sorting per notebook**, remembered on the notebook itself, including an
+ arrangement made by hand — which comes back intact after filtering.
+- **Separators** to group notes inside a hand-made arrangement.
+- **Markdown import**, single files or a ZIP this app exported.
+- **Moving notes between notebooks.**
+
+**Fixed**
+- Switching to Draw shrank the page from 733px to 460px. The editor was a flex
+ item at the default `flex: 0 1 auto`, so it was only as wide as its widest row
+ — the toolbar, which loses a dozen buttons in Draw.
+
+---
+
+## 2026-08-08 — PDFs
+
+**Added**
+- Import a PDF, read it, select its text, draw on each page, and export it with
+ the drawings written in.
+- Notes written beside a PDF.
+- Uploaded files are encrypted at rest, like note bodies already were, and stored
+ as deduplicated, content-addressed attachments.
+- Unused attachments are freed; versions are kept by count rather than by age.
+- Export as Markdown or PDF; the browser suites moved into the repository.
+
+**Changed**
+- Vector clocks were never read. Replaced with a conflict check that works.
+- Public sign-up removed — an administrator creates the accounts.
+
+---
+
+## Earlier
+
+TipTap editor, version history, full-text search and attachments (2026-08-07);
+drawing sync with WebP/JPEG support (2026-06-21); the first syncing alpha and PWA
+(2026-02-18).
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..84ba6b8
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,77 @@
+# InkNote – Projektkonventionen für Claude Code
+
+Selbst gehostete Notiz-App, privat produktiv im Einsatz. Änderungen laufen auf
+echten Daten – im Zweifel erst fragen, nicht erst ausprobieren.
+
+Die ausführliche Beschreibung steht im [readme.md](readme.md); diese Datei hält
+nur fest, was beim Arbeiten gilt und sich nicht aus dem Code ergibt.
+
+## Feste Regeln
+
+Diese Punkte sind Entscheidungen von Marc, keine offenen Fragen:
+
+- **Backend immer mit Docker starten**, nie mit `go run` o. Ä.
+ `docker compose -f docker-compose.dev.yml up -d --build`
+- **Direkt auf `main` pushen.** Keine Feature-Branches, kein PR-Umweg.
+- **Kein Backup-Feature bauen.** Die Daten liegen über Bind-Mounts auf dem Host
+ (`INKNOTE_DATA_DIR`, Standard `/srv/inknote`), und was den Host sichert –
+ Proxmox Backup – sichert damit auch InkNote.
+- **Die Verschlüsselung bleibt.** Notizinhalte, Zeichnungen und hochgeladene
+ Dateien liegen AES-256-GCM-verschlüsselt auf dem Server. Nichts davon
+ entfernen, um etwas anderes einfacher zu machen.
+- **Keine öffentliche Registrierung.** Konten legt ein Administrator an. Ein
+ Admin darf anlegen, löschen und Passwörter zurücksetzen – aber **keine**
+ weiteren Admins ernennen und **keine** fremden Konten umbenennen.
+- **Bundle-Größe bleibt, wie sie ist.** Bewusst so entschieden.
+- **Dashboard und Seitenleiste sind vertagt.** Die offenen Befunde dazu sind
+ bekannt; nicht ungefragt damit anfangen.
+
+## Tests
+
+Beides muss vor einem Push grün sein.
+
+```bash
+# Unit (224 Tests, ~4 s)
+docker run --rm -v "$PWD/frontend:/w" -w /w node:20-alpine npx vitest run
+
+# Browser, zwölf Suiten (~263 Checks) – braucht den Dev-Stack
+./e2e/run.sh # alle
+./e2e/run.sh editor drawing # einzelne
+```
+
+Die Browser-Suiten melden sich mit Marcs Admin-Konto an (`INKNOTE_ADMIN` /
+`INKNOTE_ADMIN_PASS`, Standard `marc`/`geheim123`) und legen sich damit
+Wegwerf-Nutzer an. Sie laufen gegen `./data`, nicht gegen `/srv/inknote`.
+Screenshots landen in `e2e/shots/` und sind gitignored.
+
+`attachments-lifecycle` ruft `POST /admin/housekeeping` auf – das schreibt auf
+echten Daten. Nicht gegen die Produktionsinstanz laufen lassen.
+
+## Ausliefern
+
+```bash
+./build.sh # baut beide Images und schiebt sie ins Gitea-Registry
+```
+
+Nur das Image bauen, das sich geändert hat. Nach dem Push den Digest bei der
+Registry gegenprüfen, nicht nur der Ausgabe von `docker push` glauben:
+
+```bash
+docker buildx imagetools inspect gitea.honeyy.duckdns.org/docker/inknote-web:latest
+```
+
+Auf dem Server: `docker compose pull && docker compose up -d`.
+
+## Änderungen festhalten
+
+Jede Runde, die als Image rausgeht, bekommt einen Eintrag in
+[CHANGELOG.md](CHANGELOG.md) – mit den Image-Digests, damit später nachvollziehbar
+ist, was auf dem Server läuft. Der `readme.md` beschreibt den *jetzigen* Stand
+und wird mitgeändert, wenn sich Verhalten ändert; das Changelog beschreibt den
+Weg dahin.
+
+## Stil
+
+Der Code erklärt in Kommentaren das *Warum*, nicht das *Was* – oft mit dem
+Fehler, den die Zeile verhindert. Neue Kommentare in dem Ton, englisch wie der
+Rest. Die Oberfläche ist durchgehend englisch, das Gespräch mit Marc deutsch.
diff --git a/readme.md b/readme.md
index 55a4c0c..f0907f1 100644
--- a/readme.md
+++ b/readme.md
@@ -47,6 +47,8 @@ inknote/
├── docker-compose.dev.yml # Build from source for local work
├── .env.example # Copy to .env — Compose reads it from here
├── build.sh # Build & push images to Gitea
+├── CHANGELOG.md # What changed per released image, with digests
+├── CLAUDE.md # Conventions and standing decisions for this repo
├── backend/
│ ├── server.js # Express API + WebSocket server
│ ├── sync-client.js # Client-side sync engine library
@@ -371,10 +373,17 @@ state of their own, so they can be read on their own.
## Setting a note
-**Left-aligned, with the column against the margin.** A column that floats in the
-middle moves as the window is resized, so the start of every line lands somewhere
-new; against the margin it is always in the same place. About 73 characters to
-the line — measured, not guessed.
+**A centred column, about 73 characters to the line** — measured, not guessed.
+Past roughly 84 the eye stops reliably finding the start of the next line, so the
+column is capped well before the pane runs out.
+
+It was pinned to the left margin for a while, on the reasoning that a column
+which floats in the middle moves as the window is resized. True, but it traded
+that for something worse: on a wide window the entire right half of the pane
+became one dead block. A page surface was then drawn behind the text to give that
+block a meaning, which only moved the problem — the whole sheet sat hard against
+the left edge. Centred, the same leftover space reads as two margins and needs no
+explaining.
**The typeface is a per-account setting** (Account → Profile): serif, sans or
mono. On the account rather than in the browser, because a choice about how your
@@ -383,7 +392,7 @@ every device. The server accepts those three values and drops anything else —
that column is written by a browser, so it is an input like any other.
**Pages are counted, not stored.** The toolbar says *Page 2 of 4* in the same
-words the PDF reader uses, and a hairline marks where each one ends. A page is
+words the PDF reader uses, and a dashed rule marks where each one ends. A page is
the same 3:4 the canvas uses, so "page 2" means the same thing writing or
drawing. The note itself stays one continuous document — Markdown has no page,
and a test asserts none ever reaches the stored body. The current page is the one