## Implementation Plan
### Changes required
1. **Profile social buttons (`templates/profile/profile.html`)**
- Add ` ` immediately after the button text inside each of the six `` elements at lines 68, 72, 77, 81, 86, 90.
- Pattern: `Text `
2. **Reaction chips (`templates/_reaction_bar.html`)**
- Add ` ` as a child of the `` at line 7 (the reaction chip button).
3. **Award submission (`templates/_award_form.html` – verify actual template name, likely `devplacepy/templates/...`; if not found search for `award` template that contains the submit button)**
- Add ` ` inside the submit button in the award form.
- In `static/js/AwardGiver.js` line 44, change `submitBtn.disabled = true` to also add the `is-loading` class: `submitBtn.classList.add('is-loading'); submitBtn.disabled = true;`. Ensure the class is removed on completion (in the `.then`/`.catch` or corresponding path).
4. **Create post form (`static/js/FormManager.js` around line 35, `initPostForm()` method)**
- Remove the line that sets `submitBtn.textContent = 'Posting...'`.
- Instead, add `submitBtn.classList.add('is-loading')` and `submitBtn.disabled = true` on form submission.
- Ensure the create post button's HTML markup (in the relevant template, e.g., `_post_form.html` or similar) contains ` `.
- If the button already has some text (e.g., "Post"), leave it unchanged; the spinner will appear next to it.
### Definition of Done
- [ ] All four gap items modified as described above.
- [ ] Command `pip install -e '.[dev]' -q && make test-unit` exits with code 0 (all tests pass).
- [ ] Command `pip install -q ruff && ruff check .` reports zero errors.
- [ ] For each modified button in a browser (or by inspecting rendered HTML):
- The `` element contains a child ` `.
- On form submission or action trigger, the `is-loading` class is applied, and the spinner becomes visible (via CSS `.btn.is-loading .btn-spinner`).
- [ ] The post creation form no longer changes the button text to "Posting..." but uses the spinner animation instead.