Files
python-tdd/src/templates/apps/gameboard/room.html
Disco DeDisco e512e94056 ROLE SELECT: block role pick without deck; SigSelect qualifier spec fix — TDD
- role-select.js: _showNoDeckWarning(stack) intercepts at openFan() — fan never
  opens when data-equipped-deck=""; warning positioned fixed over card-stack via
  getBoundingClientRect(); .guard-actions wrapper for FYI/.btn-caution + NVM/.btn-cancel
- room.html: card-stack gains data-equipped-deck="{{ equipped_deck_id|default:'' }}"
- room view context: equipped_deck_id added
- _room.scss: .role-no-deck-warning — glass guard style matching #id_guard_portal
- _base.scss + _room.scss: guard portal + no-deck warning opacity 0.5 → 0.75
  (matches .tt tooltip; light-palette handled via --tooltip-bg CSS var)
- RoleSelectSpec.js: 8 Jasmine specs — no-deck (fan blocked, warning, FYI/NVM,
  no duplicate, no POST) + deck-present pass-through; afterEach cleans up warning
- SigSelectSpec.js: card fixture gains data-levity-qualifier + data-gravity-qualifier;
  all "Leavened" expectations updated to "Elevated"

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 23:52:22 -04:00

118 lines
7.0 KiB
HTML

{% extends "core/base.html" %}
{% load static %}
{% block title_text %}Gameboard{% endblock title_text %}
{% block header_text %}<span>Game</span>room{% endblock header_text %}
{% block content %}
<div class="room-page" data-room-id="{{ room.id }}"
{% if room.table_status %}data-select-role-url="{% url 'epic:select_role' room.id %}"{% endif %}>
<div id="id_aperture_fill"></div>
<div class="room-shell">
<div id="id_game_table" class="room-table">
{% if room.table_status == "ROLE_SELECT" %}
<div id="id_pick_sigs_wrap"{% if starter_roles|length < 6 %} style="display:none"{% endif %}>
<form method="POST" action="{% url 'epic:pick_sigs' room.id %}">
{% csrf_token %}
<button id="id_pick_sigs_btn" type="submit" class="btn btn-primary">PICK<br>SIGS</button>
</form>
</div>
{% endif %}
<div class="room-table-scene">
<div class="table-hex-border">
<div class="table-hex">
<div class="table-center">
{% if room.table_status == "ROLE_SELECT" %}
{% if card_stack_state %}
<div class="card-stack" data-state="{{ card_stack_state }}"
data-starter-roles="{{ starter_roles|join:',' }}"
data-user-slots="{{ user_slots|join:',' }}"
data-active-slot="{{ active_slot }}"
data-equipped-deck="{{ equipped_deck_id|default:'' }}">
{% if card_stack_state == "ineligible" %}
<i class="fa-solid fa-ban"></i>
{% endif %}
</div>
{% endif %}
{% endif %}
{% if room.table_status == "SKY_SELECT" %}
{% if sky_confirmed %}
<button id="id_pick_sea_btn" class="btn btn-primary">PICK<br>SEA</button>
{% else %}
<button id="id_pick_sky_btn" class="btn btn-primary">PICK<br>SKY</button>
{% endif %}
{% elif room.table_status == "SIG_SELECT" %}
<button id="id_pick_sky_btn" class="btn btn-primary" style="display:none">PICK<br>SKY</button>
{% if polarity_done %}
<p id="id_hex_waiting_msg">{% if user_polarity == "levity" %}Gravity settling . . .{% else %}Levity appraising . . .{% endif %}</p>
{% endif %}
{% endif %}
</div>
</div>
</div>
{# Seats — fa-chair layout persists from ROLE_SELECT through SIG_SELECT #}
{% for pos in gate_positions %}
<div class="table-seat{% if pos.role_label in starter_roles %} role-confirmed{% endif %}"
data-slot="{{ pos.slot.slot_number }}" data-role="{{ pos.role_label }}">
<i class="fa-solid fa-chair"></i>
<span class="seat-role-label">{{ pos.role_label }}</span>
{% if pos.role_label in starter_roles %}
<i class="position-status-icon fa-solid fa-circle-check"></i>
{% else %}
<i class="position-status-icon fa-solid fa-ban"></i>
{% endif %}
</div>
{% endfor %}
</div>
</div>
</div>
{# Sig Select overlay — suppressed once this gamer's polarity sigs are assigned #}
{% if room.table_status == "SIG_SELECT" and user_polarity and not polarity_done %}
{% include "apps/gameboard/_partials/_sig_select_overlay.html" %}
{% endif %}
{# Natus (Pick Sky) overlay — natal chart entry #}
{% if room.table_status == "SKY_SELECT" and not sky_confirmed %}
{% include "apps/gameboard/_partials/_natus_overlay.html" %}
{% endif %}
{# Natus tooltip: sibling of .natus-overlay, not inside .natus-modal-wrap (which has transform) #}
{% if room.table_status == "SKY_SELECT" and not sky_confirmed %}
<div id="id_natus_tooltip" class="tt" style="display:none;"></div>
<div id="id_natus_tooltip_2" class="tt" style="display:none;"></div>
{% endif %}
{# Sea (Pick Sea) overlay — Celtic Cross spread entry #}
{% if room.table_status == "SKY_SELECT" and sky_confirmed %}
{% include "apps/gameboard/_partials/_sea_overlay.html" %}
{% endif %}
{% if room.gate_status != "RENEWAL_DUE" and room.table_status != "SIG_SELECT" %}
{% include "apps/gameboard/_partials/_table_positions.html" %}
{% endif %}
{% if not room.table_status and room.gate_status != "RENEWAL_DUE" %}
{% include "apps/gameboard/_partials/_gatekeeper.html" %}
{% endif %}
{% if room.table_status %}
<div id="id_tray_wrap"{% if room.table_status == "ROLE_SELECT" and starter_roles|length < 6 %} class="role-select-phase"{% endif %}>
<div id="id_tray_handle">
<div id="id_tray_grip"></div>
<button id="id_tray_btn" aria-label="Open seat tray">
<i class="fa-solid fa-dice-d20"></i>
</button>
</div>
<div id="id_tray" style="display:none"><div id="id_tray_grid" data-role-icons-url="{% static 'apps/epic/icons/cards-roles/' %}">{% if my_tray_role %}<div class="tray-cell tray-role-card" data-role="{{ my_tray_role }}"><img src="{% static my_tray_scrawl_static_path %}" alt="{{ my_tray_role }}"></div>{% else %}<div class="tray-cell"></div>{% endif %}{% if my_tray_sig %}<div class="tray-cell tray-sig-card"><img src="{% static 'apps/epic/icons/cards-sigs/Blank.svg' %}" alt="{{ my_tray_sig.name }}"></div>{% else %}<div class="tray-cell"></div>{% endif %}{% for i in "345678" %}<div class="tray-cell"></div>{% endfor %}</div></div>
</div>
{% endif %}
{% include "apps/gameboard/_partials/_room_gear.html" %}
</div>
{% endblock content %}
{% block scripts %}
<script src="{% static 'apps/epic/room.js' %}"></script>
<script src="{% static 'apps/epic/gatekeeper.js' %}"></script>
<script src="{% static 'apps/epic/role-select.js' %}"></script>
<script src="{% static 'apps/epic/sig-select.js' %}"></script>
<script src="{% static 'apps/epic/tray.js' %}"></script>
{% endblock scripts %}