The margin rail hangs off an absolutely-positioned column, so its cards add no layout height. On her live document that meant four 173px cards anchored inside 126px of text: a 714px stack over a page whose scrollHeight equalled its clientHeight. The lower cards weren't far from their sentence, they were off-screen with nothing to scroll. The rail now reports how far its resolved stack reaches and the wrapper takes that as a minimum height, so the space those cards occupy is real, scrollable page. minHeight never shrinks the column, so a rail that fits beside its text is unaffected. Scrolling into that space would have carried every sentence off the top, so the prose is pinned while the stack overhangs it. The offset is min(0, port - content): prose shorter than the viewport pins at the top, taller prose pins by its bottom edge, keeping the last lines visible — those are the ones the overhanging cards flag. The prose box has to stay at its natural height. Keeping the old h-full made it measure the wrapper this change had just grown, reporting the cards' height as the text's own, so the pin could never trip. Verified in a browser at the review's 1517x810, driven offline by the rule pack: 8 cards over 95px of prose gained 675px of scroll where there was none, the last card lands fully in view with the text still on screen, tall prose pins bottom-anchored without disturbing ordinary scrolling, and hover-linking still glows the right span. Claude-Session: https://claude.ai/code/session_016y6gyuHkQXPiEuW8RGQyua
🌸 Petal
A self-hosted, privacy-first writing editor with warm bubbly design, auto-save, and
local-LLM grammar/ESL suggestions. See petal-spec.md for the full
design spec and BUILD_PLAN.md for build progress.
Stack
Go + chi backend · SQLite (modernc, pure Go) · React + Vite + Tiptap + Tailwind v4 frontend ·
local vLLM/Ollama for AI suggestions. Single-binary deployment (frontend embedded via go:embed).
Local development
Two processes during development:
# 1. Backend (serves /api on :8080)
go run ./cmd/server
# 2. Frontend dev server (HMR on :5173, proxies /api → :8080)
cd web && npm install && npm run dev
Open http://localhost:5173 while developing.
Production build (single binary)
cd web && npm run build # emits web/dist (embedded by the Go binary)
cd .. && go build -o petal ./cmd/server
./petal # serves UI + API on :8080
Configuration is via environment variables — copy .env.example to .env.
Deployment
docker compose up -d --build # petal + the two Piper read-aloud sidecars
Behind Traefik on the parodia.dev VPS; vLLM stays on millenia over headscale.
Full runbook — first deploy, the LLM link, backups and restore — in
deploy/README.md.
Status
Early build, multi-session. Auth (Authentik OIDC) is next; Copyleaks plagiarism is
still parked — see BUILD_PLAN.md.