Sig select: caution tooltip, FLIP/FYI stat block, keyword display

- TarotCard.cautions JSONField + cautions_json property; migrations
  0027–0029 seed The Schizo (number=1) with 4 rival-interaction cautions
  (Roman-numeral card refs: I. The Pervert / II. The Occultist, etc.)
- Sig-select overlay: FLIP (stat-block toggle) + FYI (caution tooltip)
  buttons; nav PRV/NXT portaled outside tooltip at bottom corners (z-70);
  caution tooltip covers stat block (inset:0, z-60, Gaussian blur);
  tooltip click dismisses; FLIP/FYI fully dead while btn-disabled;
  nav wraps circularly (4/4 → 1/4, 1/4 → 4/4)
- SCSS: btn-disabled specificity fix (!important); btn-nav-left/right
  classes; sig-caution-* layout; stat-face keyword lists
- Jasmine suite expanded: stat block + FLIP (5 specs), caution tooltip
  (16 specs) including wrap-around and disabled-button behaviour
- IT tests: TarotCardCautionsTest (5), SigSelectRenderingTest (8)
- Role-card SVG icons added to static/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-04-07 00:22:04 -04:00
parent e2cc38686f
commit 520fdf7862
24 changed files with 1936 additions and 54 deletions

View File

@@ -92,6 +92,11 @@ def _notify_sig_reserved(room_id, card_id, role, reserved):
SLOT_ROLE_LABELS = {1: "PC", 2: "NC", 3: "EC", 4: "SC", 5: "AC", 6: "BC"}
_ROLE_SCRAWL_NAMES = {
"PC": "Player", "NC": "Narrator", "EC": "Economist",
"SC": "Shepherd", "AC": "Alchemist", "BC": "Builder",
}
def _gate_positions(room):
"""Return list of dicts [{slot, role_label, role_assigned}] for _table_positions.html."""
@@ -216,10 +221,16 @@ def _role_select_context(room, user):
if user.is_authenticated else []
)
active_slot = active_seat.slot_number if active_seat else None
_my_role = assigned_seats[0].role if assigned_seats else None
ctx = {
"card_stack_state": card_stack_state,
"starter_roles": starter_roles,
"assigned_seats": assigned_seats,
"my_tray_role": _my_role,
"my_tray_scrawl_static_path": (
f"apps/epic/icons/cards-roles/starter-role-{_ROLE_SCRAWL_NAMES[_my_role]}.svg"
if _my_role else None
),
"user_seat": user_seat,
"user_slots": list(
room.table_seats.filter(gamer=user, role__isnull=True)