diff --git a/docs/plans/2026-05-16-pay-salary-quick-action-plan.md b/docs/plans/2026-05-16-pay-salary-quick-action-plan.md
new file mode 100644
index 0000000..7f9ca3f
--- /dev/null
+++ b/docs/plans/2026-05-16-pay-salary-quick-action-plan.md
@@ -0,0 +1,260 @@
+# Pay Salary Quick Action — Implementation Plan
+
+> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development to implement this plan task-by-task (in-session, fresh subagent + 2-stage review per task). Each subagent uses superpowers:test-driven-development for the Django-render portion.
+
+**Goal:** Add a "Pay Salary" tile to the home dashboard's admin Quick Actions row that deep-links to `/payroll/?action=pay-salary`; the payroll page auto-clicks the existing Pay Salary button (clean slate → type=Salary → managers-only scope → modal open), then strips the param.
+
+**Architecture:** A plain `` tile (admin-only branch) + a ~10-line client-side deep-link hook that triggers the existing `paySalaryBtn`. No duplicated behaviour, no view/model/URL change; `?action=` is inert server-side.
+
+**Tech Stack:** Django 5.2.7 templates + vanilla JS; SQLite local (`USE_SQLITE=true`); Bootstrap 5.
+
+**Design doc:** `docs/plans/2026-05-16-pay-salary-quick-action-design.md` (commit `fb19655`).
+
+**Branch / baseline:** `ai-dev`, HEAD `fb19655`, **207/207 tests passing**. On top of the paused, un-pushed Manager/Salaried + pay-type-filter + Salary-auto-scope commits.
+
+**Test command (Git Bash, per CLAUDE.md):**
+```bash
+USE_SQLITE=true DJANGO_DEBUG=true python manage.py test core.tests -v 2
+```
+
+> **TDD note.** Task 1's Django-render behaviour (tile present, param
+> inert) **is** unit-testable — do real TDD there (failing test first).
+> The auto-click itself is pure browser JS with no server surface, so —
+> per the approved precedent (Task-3 toggle, Salary auto-scope) — it is
+> verified by Konrad's manual checklist, NOT a Django test. Do not add a
+> JS-source-sniffing test.
+
+> ⛔ **HARD STOP after Task 2.** Do NOT `git push`, do NOT deploy. Hand
+> back to Konrad for the manual checklist. Ships bundled with the rest
+> of the paused work in ONE push, on his explicit say-so only.
+
+---
+
+### Task 1: Tile + deep-link hook + render test
+
+**Files:**
+- Modify: `core/templates/core/index.html` — admin Quick Actions card (the "Run Payroll" tile is currently lines 208–211)
+- Modify: `core/templates/core/payroll_dashboard.html` — after the `if (paySalaryBtn) { … }` block (currently lines 2101–2117; insert before line 2119)
+- Test: `core/tests.py` — new class `PaySalaryQuickActionTests`, inserted immediately before `class WorkHistoryTeamFilterTests`
+
+**Step 1: Write the failing test**
+
+Insert this class immediately before `class WorkHistoryTeamFilterTests(TestCase):` in `core/tests.py` (reuse module-level `User`/`TestCase`/`reverse` already imported by neighbouring classes — do not add imports if present):
+
+```python
+class PaySalaryQuickActionTests(TestCase):
+ """Home dashboard 'Pay Salary' Quick Action: an admin sees a tile
+ that deep-links /payroll/?action=pay-salary; the param is inert
+ server-side (no view change). The auto-open click is client-side
+ JS, verified by manual checklist (not asserted here)."""
+
+ @classmethod
+ def setUpTestData(cls):
+ cls.admin = User.objects.create_user(
+ username='psqa_admin', password='pw',
+ is_staff=True, is_superuser=True,
+ )
+
+ def setUp(self):
+ self.client.force_login(self.admin)
+
+ def test_home_has_pay_salary_quick_action(self):
+ resp = self.client.get('/')
+ self.assertEqual(resp.status_code, 200)
+ # The tile links to the payroll dashboard with the deep-link param.
+ self.assertContains(resp, '?action=pay-salary')
+ # And is labelled "Pay Salary".
+ self.assertContains(resp, 'Pay Salary')
+
+ def test_payroll_dashboard_ignores_action_param(self):
+ # The param is purely a client-side signal; the view must not
+ # care about it — same 200 as a plain /payroll/ load.
+ resp = self.client.get('/payroll/?action=pay-salary')
+ self.assertEqual(resp.status_code, 200)
+```
+
+**Step 2: Run the tests, verify they FAIL**
+
+```bash
+USE_SQLITE=true DJANGO_DEBUG=true python manage.py test core.tests.PaySalaryQuickActionTests -v 2
+```
+Expected: `test_home_has_pay_salary_quick_action` FAILS (no `?action=pay-salary` in `/`). `test_payroll_dashboard_ignores_action_param` will likely already PASS (param already inert) — that's fine; it's a guard that must stay green.
+
+**Step 3: Add the home dashboard tile**
+
+In `core/templates/core/index.html`, the "Run Payroll" tile currently is (lines 208–211):
+
+```html
+
+
+ Run Payroll
+
+```
+
+Insert the new tile IMMEDIATELY AFTER that closing `` (line 211) and before the "View History" tile (``):
+
+```html
+ {# === PAY SALARY — quick path: opens the Pay-Salary modal on /payroll/ === #}
+ {# Same fa-user-tie icon as the payroll dashboard's Pay Salary button so #}
+ {# users have one mental model for "salary = fa-user-tie". #}
+
+
+ Pay Salary
+
+```
+
+Match the file's existing indentation (16 spaces for the ``). Each
+`{# #}` comment is a single self-contained line — do NOT let any `{#`
+span lines.
+
+**Step 4: Add the deep-link hook**
+
+In `core/templates/core/payroll_dashboard.html`, the `paySalaryBtn`
+wiring ends at line 2117 (` }` closing `if (paySalaryBtn) {`),
+followed by a blank line 2118 and the header-button comment at line
+2119. Insert this block on the blank line AFTER line 2117 and BEFORE
+the `// When the modal is opened from the HEADER button …` comment:
+
+```javascript
+ // === Quick-action deep-link: /payroll/?action=pay-salary ===
+ // The home dashboard "Pay Salary" Quick Action links here with this
+ // param. Auto-click the existing Pay Salary button (which does the
+ // clean-slate + type=Salary + managers-only scoping + modal open),
+ // then strip the param so a manual refresh or Back doesn't re-pop
+ // the modal. Best-effort — never let a deep-link quirk block the page.
+ try {
+ var _qsAction = new URLSearchParams(window.location.search).get('action');
+ if (_qsAction === 'pay-salary' && paySalaryBtn) {
+ paySalaryBtn.click();
+ var _u = new URL(window.location.href);
+ _u.searchParams.delete('action');
+ window.history.replaceState({}, '', _u.pathname + _u.search + _u.hash);
+ }
+ } catch (e) { /* deep-link is best-effort; never block the page */ }
+```
+
+Notes: `paySalaryBtn` is the `var` declared at line 2100 — in scope
+here. It must run AFTER its `addEventListener` (line 2102) so the click
+has a handler — this placement (after line 2117) guarantees that. Do
+NOT modify the `paySalaryBtn` click handler or any modal-reset logic.
+
+**Step 5: Guard greps**
+
+```bash
+grep -rn "^\s*{#" core/templates/core/index.html | awk -F: '$0 !~ /#}/ {print}'
+grep -rn "^\s*{#" core/templates/core/payroll_dashboard.html | awk -F: '$0 !~ /#}/ {print}'
+grep -c 'id="paySalaryBtn"' core/templates/core/payroll_dashboard.html
+grep -c 'action=pay-salary' core/templates/core/index.html
+```
+Expected: first two → no output; third → `1` (button id still unique, untouched); fourth → `1` (one new tile).
+
+**Step 6: Run tests, verify PASS**
+
+```bash
+USE_SQLITE=true DJANGO_DEBUG=true python manage.py test core.tests.PaySalaryQuickActionTests -v 2
+```
+Expected: 2 tests OK.
+
+Then full suite:
+```bash
+USE_SQLITE=true DJANGO_DEBUG=true python manage.py test core.tests -v 2
+```
+Expected: **208 tests OK** (207 baseline + 1 new render test; the param-inert test was already-green and stays green). If anything unrelated fails, STOP and report.
+
+**Step 7: Commit (local only, NO push, NEW commit)**
+
+```bash
+git add core/templates/core/index.html core/templates/core/payroll_dashboard.html core/tests.py
+git commit -m "feat: Pay Salary quick action on home dashboard (deep-link to modal)
+
+Admin Quick Actions tile → /payroll/?action=pay-salary; the payroll
+page auto-clicks the existing paySalaryBtn then strips the param.
+Reuses all existing Pay-Salary machinery; param inert server-side.
+
+Co-Authored-By: Claude Opus 4.7 (1M context) "
+```
+
+**Self-review:** `git show HEAD` — exactly 3 files; the tile is inside
+the admin Quick Actions card (between Run Payroll and View History); the
+hook is after the `if (paySalaryBtn){}` block (not inside it); no
+change to the paySalaryBtn handler or modal resets; greps clean; suite
+208.
+
+---
+
+### Task 2: Docs + final regression + HARD STOP
+
+**Files:**
+- Modify: `docs/plans/parked-work.md`
+- Modify: `CLAUDE.md`
+
+**Step 1: Full regression (anchor)**
+
+```bash
+USE_SQLITE=true DJANGO_DEBUG=true python manage.py test core.tests -v 2
+```
+Expected: **208 OK**. If not, STOP.
+
+**Step 2: Update `docs/plans/parked-work.md`**
+
+Read the file; find the paused Manager/Salaried entry (under "⏸ Paused
+… awaiting Konrad's verification"; already carries the pay-type-filter
+and Salary-auto-scope notes). Append, matching the file's prose style:
+
+> Also now: a home-dashboard admin Quick Actions tile **"Pay Salary"**
+> deep-links `/payroll/?action=pay-salary` and auto-opens the existing
+> Pay Salary modal (param stripped after). Design
+> `docs/plans/2026-05-16-pay-salary-quick-action-design.md`, plan
+> `docs/plans/2026-05-16-pay-salary-quick-action-plan.md`. Same HARD
+> STOP — bundled into the one push on Konrad's say-so.
+
+(If no such entry exists, add a short one under "⏸ Paused" matching the
+others' format. Report which case.)
+
+**Step 3: Update `CLAUDE.md`**
+
+In the "## Manager / Salaried pay (May 2026)" section, after the
+existing **"Salary picker safety:"** line, append one line in the same
+terse style:
+
+> **Pay Salary quick action:** the home dashboard's admin Quick Actions
+> row has a "Pay Salary" tile linking `/payroll/?action=pay-salary`;
+> `payroll_dashboard.html` JS auto-clicks the existing `paySalaryBtn`
+> on load when that param is present, then strips it via
+> `history.replaceState` (no re-pop on refresh). `?action=` is inert
+> server-side — no view/URL change.
+
+**Step 4: Verify docs**
+
+```bash
+grep -n "action=pay-salary\|Pay Salary quick action\|Pay Salary" docs/plans/parked-work.md CLAUDE.md
+```
+Expected: new lines present in both files; Markdown intact.
+
+**Step 5: Commit (local only, NO push, NEW commit)**
+
+```bash
+git add docs/plans/parked-work.md CLAUDE.md
+git commit -m "docs: note Pay Salary quick action (rides paused bundle)
+
+Co-Authored-By: Claude Opus 4.7 (1M context) "
+```
+
+**Self-review:** `git show --stat HEAD` — only the 2 doc files, additions only.
+
+---
+
+## ⛔ HARD STOP — hand back to Konrad
+
+After Task 2's commit:
+1. `git status` clean; `git log --oneline -3` shows the 2 new commits on `ai-dev` on top of `fb19655`.
+2. Full suite once more → **208/208 OK**.
+3. **Do NOT `git push`. Do NOT deploy.** Report the commit list + test count and point Konrad at the **Manual verification** section of `docs/plans/2026-05-16-pay-salary-quick-action-design.md` (7 steps).
+4. Push/deploy only on Konrad's explicit approval, bundled with the rest of the paused Manager/Salaried + pay-type-filter + Salary-auto-scope work in ONE push (github + gitea; deploy order: pull → migrate → collectstatic → restart last).
+
+## Notes
+
+- **DRY:** the tile just triggers the existing `paySalaryBtn`; all real behaviour stays in one place.
+- **YAGNI:** no view/URL/server handling of `?action=`; no generic deep-link framework; no supervisor entry.
+- **Why the hook sits after `if (paySalaryBtn){}`:** the click handler must be attached before we synthesise a click; this placement guarantees ordering and keeps `paySalaryBtn` in scope.
+- **No migration / view / URL change**; only one new Django render test by design (the auto-click is JS, manual-checklist verified — documented precedent).