# M6.6.1 — Pay-button QR popup modal (`/adults`, `/juniors`) > Plan-mode note: per project convention this plan should live at > `docs/plans/2026-05-08-1439-go-m6-6-1-payment-qr-modal.md`. The first > execution step after approval is to copy this file there. > Branch: `feat/go-m6-6-1-payment-qr-modal` off `main`. ## Context M6.6 ([docs/plans/2026-05-08-1334-go-m6-6-action-pages.md](docs/plans/2026-05-08-1334-go-m6-6-action-pages.md)) landed the backend `/qr` PNG endpoint plus `/sync-bank`, `/flush-cache`, `/version`. While doing it, the **client-side** half of the Pay flow was collapsed from a modal-with-details into a plain `` — clicking Pay now navigates the whole tab to the raw PNG. The Python app instead opens an in-page `#qrModal` showing the QR image *plus* labelled details (account, amount, message, title), then closes the modal on outside-click or `[close]` ([templates/adults.html:631-648](templates/adults.html#L631-L648), JS at [templates/adults.html:963-993](templates/adults.html#L963-L993)). This is the UX the user expects from the dashboard — staying on the table while displaying the QR is significantly more practical than losing context to a fullscreen image. M6.6.1 restores parity: the Pay/Pay-All buttons open an in-page `#qrModal`, identical in structure to the Python original, driven by a new vanilla-JS module `payment-qr.js` that mirrors the `member-detail.js` convention from M6.5. All the building blocks are already in place: - **`/qr` endpoint** ships PNGs ([go/internal/web/qr.go](go/internal/web/qr.go), tested by [TestServeQR](go/internal/web/html_handler_test.go#L207-L231)). - **CSS** for `#qrModal .modal-content`, `.qr-image`, `.qr-details` is already in [go/internal/web/static/css/app.css:445-478](go/internal/web/static/css/app.css#L445-L478) — lifted during M6.1. - **Template helpers** `qrHref` / `qrHrefAll` ([go/internal/web/render.go:63-85](go/internal/web/render.go#L63-L85)) already produce the correct query string + Czech `MM/YYYY` format for the `message=` param. They're useful for sanity (and for any no-JS fallback) but become dead code post-M6.6.1 — see §Out of scope. - **Bank account** is already exposed as `$.Data.BankAccount` to every template that has a Pay button. - **JS module convention**: `member-detail.js` is the M6.5 baseline — IIFE, `'use strict'`, event delegation off `data-*` attributes, no inline `onclick`, no globals leaked. ## Approach ### 1. Replace `` with ` ``` ```gotmpl ``` Why `