Queens email branding: pink palette for girls program emails #413
Labels
No labels
domain:backend
domain:devops
domain:frontend
status:approved
status:in-progress
status:needs-fix
status:qa
type:bug
type:devops
type:feature
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/basketball-api#413
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Type
Feature
Lineage
Discovered during first-payment email validation (2026-04-09). Related to
forgejo_admin/basketball-api#369.Repo
forgejo_admin/basketball-apiUser Story
As a Queens (girls program) parent
I want emails branded with the Queens pink palette
So that the communication matches the Queens branding I see on the website and contract page
Context
Queens pink branding already exists across the platform:
src/app.css:27-31:.queens-activeswaps--color-redto#e91e8c,--color-red-hoverto#f23d9e+page.svelte:140-146: appliesqueens-activewhenisGirlsis truesrc/lib/program.svelte.js: kings/queens toggle used across 28 filesbasketball-api has Kings colors in
brand.pybut no Queens variant. Email system hardcodes_BRAND_RED = "#d42026"inemail.py:192and_brand_wrapper()atemail.py:200uses it for header borders, headings, CTAs, and links. No division context flows through the email pipeline.Colors are already decided —
#e91e8c(pink) and#f23d9e(pink hover) from the existing CSS. No design approval needed.File Targets
Files to modify:
src/basketball_api/brand.py— addCOLOR_QUEENS_PINK = "#e91e8c"andCOLOR_QUEENS_PINK_HOVER = "#f23d9e"src/basketball_api/services/email.py:192— add_BRAND_QUEENS_PINK = "#e91e8c"constant next to_BRAND_REDsrc/basketball_api/services/email.py:200— modify_brand_wrapper(tenant_name, body_html)to acceptaccent_color: str = _BRAND_REDparam. Replace all_BRAND_REDreferences inside the wrapper function body (header border, etc.) with theaccent_colorparametersrc/basketball_api/services/email.py— insend_first_payment_email()(~line 951), checkplayer.division == Division.girls. If true, passaccent_color=_BRAND_QUEENS_PINKto_brand_wrapper(). Also use Queens pink in any_BRAND_REDreferences inside the body_html construction (h3, cta button) for Queens players.src/basketball_api/models.py— already hasDivision.girlsat line 54, no change neededFiles NOT to touch:
_BRAND_REDuntil explicitly opted inAcceptance Criteria
brand.pyhasCOLOR_QUEENS_PINK = "#e91e8c"andCOLOR_QUEENS_PINK_HOVER = "#f23d9e"email.pyhas_BRAND_QUEENS_PINK = "#e91e8c"constant_brand_wrapper()accepts optionalaccent_colorparam, defaults to_BRAND_RED(backward compatible)_brand_wrapper()usesaccent_colorinstead of hardcoded_BRAND_REDsend_first_payment_email()passes Queens pink whenplayer.division == Division.girls_brand_wrapper()callers unchanged — still use defaultTest Expectations
_brand_wrapper()with no accent_color produces HTML containing#d42026_brand_wrapper()withaccent_color="#e91e8c"produces HTML containing#e91e8csend_first_payment_email()for aDivision.girlsplayer produces HTML containing#e91e8csend_first_payment_email()for aDivision.boysplayer produces HTML containing#d42026pytest tests/test_first_payment_email.py -vConstraints
#e91e8c(pink),#f23d9e(hover)accent_colorparam must be backward-compatible — existing callers of_brand_wrapper()don't changeplayer.division == Division.girls(same pattern as contract page'sisGirls)player.divisionis None, default to Kings red (treat as non-girls)Checklist
Related
westside-basketball— projectwestside-contracts/src/app.css:26-31westside-app/src/lib/program.svelte.jsScope Review: NEEDS_REFINEMENT
Review note:
review-910-2026-04-06Scope, approach, and traceability are sound. File targets all verified against
origin/main. Two refinements before promoting totodo:_BRAND_REDis atsrc/basketball_api/services/email.py:192(not 357), and_brand_wrapperis at line 200 (not 365). PRs #376 and #411 shifted lines after this issue was drafted.arch-basketball-apiandarch-emaillabels are present but no backing notes exist in pal-e-docs. Platform-wide gap, not unique to this ticket — should be tracked as separate backlog items but does not block this work.Decomposition: not needed. 2 files, 1 repo, 6 AC, 4 unit tests — well under the 5-minute rule.
Hard dependency on #369 (
send_first_payment_email) is satisfied (PR #376 merged Apr 7).Division.girls = "girls"confirmed inmodels.py:54. Backward-compatible default-param approach correctly insulates the 8 other_brand_wrappercallers.Scope Re-Review: READY
Review note:
review-910-2026-04-06-v2Line numbers verified against origin/main (
9c487dc):_BRAND_RED = "#d42026"at email.py:192 ✓def _brand_wrapperat email.py:200 ✓def send_first_payment_emailat email.py:951 ✓_brand_wrappercall insidesend_first_payment_emailat email.py:1039Previous NEEDS_REFINEMENT (stale 357 -> 192) is resolved. Traceability (story:WS-S7) valid. File targets all exist. No blocking dependencies. Fits single-agent pass.
Minor note (non-blocking): acceptance criterion says "All 7 other
_brand_wrapper()callers unchanged" but actual count on origin/main is 10 other callers (lines 343, 470, 665, 798, 906, 1408, 1512, 1853, 2000, 2180). Intent is clear — all existing callers must remain unchanged. Dev agent will see the real count.Ready to move backlog -> todo.