{% extends "core/base.html" %} {% load static %} {% block title_text %}Game Sea{% endblock title_text %} {% block header_text %}GameSea{% endblock header_text %} {% block content %} {# note.js exposes window.Brief — needed by BOTH the no-sig branch's #} {# sign-gate Brief partial AND the with-sig branch's Default-deck + #} {# Free-draw-locked Briefs. Hoisted out of the branches so it loads #} {# exactly once regardless of which path the user is on (note.js #} {# declares `const Brief = ...` at global scope — a second load would #} {# SyntaxError on re-declaration). #}
{% if not user_has_sig %} {# Sprint 4b sign-gate — DRYly Brief-banner'd (was inline div #} {# .my-sea-sign-gate, refactored 2026-05-22 to use the project- #} {# wide `.note-banner` portal via `Brief.showBanner`). NVM lives #} {# inside the Brief shell; FYI links to /billboard/my-sign/. #} {# Page body stays empty — the Brief is the entire no-sig UX. #} {% include "apps/gameboard/_partials/_my_sea_sign_gate_brief.html" %} {% else %} {% if not show_picker %} {# Sprint 5 iter 1 — DRAW SEA landing UX. DRY table hex from #} {# the room shell (.room-shell > .room-table > … > .table-hex) #} {# w. 6 chair seats labeled 1C-6C as placeholders for the #} {# friend-invite feature per the My Sea roadmap architectural #} {# anchor "Six chairs retained even in solo". #} {# #} {# Iter 6b — landing primary-btn state machine, 3-way: #} {# • FREE DRAW (`#id_draw_sea_btn`) when no active quota row #} {# (fresh user OR >24h since last draw); #} {# • PAID DRAW (`#id_my_sea_paid_draw_btn`) when the user has #} {# deposited a token via the gatekeeper but hasn't yet #} {# committed it; one-click POST commits + redirects to #} {# fresh-quota /gameboard/my-sea/. #} {# • GATE VIEW (`#id_my_sea_gate_view_btn`) when the user's #} {# quota row exists, the hand is empty, AND no deposit yet #} {# (post-DEL state). Routes to the Sprint-6 gatekeeper. #} {# Seat 1 (`data-slot="1"`) carries `.seated` + `.fa-circle- #} {# check` when the user's hand is non-empty (server-rendered #} {# so reloads preserve the state). Otherwise `.fa-ban`. Other #} {# 5 seats are placeholders for the future friend-invite #} {# feature — always banned in solo my-sea. #}
{% if show_paid_draw %} {# PAID DRAW — two underlying states collapse into one #} {# button (user-spec 2026-05-23): #} {# • `deposit_reserved` → POST commits the deposited #} {# token via `my_sea_paid_draw` + redirects to picker. #} {# • `paid_through` (token already spent this cycle, #} {# hand still empty) → POST is a no-op commit branch #} {# in the view; the view redirects to picker anyway. #}
{% csrf_token %}
{% elif show_gate_view %} {% else %} {% endif %}
{% for n in "123456" %} {# Chair-position labels (1C-6C). No roles in #} {# my-sea (this is the solo draw flow); using #} {# `.seat-position-label` instead of the room's #} {# `.seat-role-label` to keep the no-role #} {# semantics clean. `.position-status-icon` + #} {# `.fa-ban` are unchanged — already role- #} {# agnostic in _room.scss. #}
{{ n }}C
{% endfor %}
{% endif %} {# Picker phase — per-spread flexible layout. Sig pins .sea- #} {# pos-core; the 6 surrounding positions all render in DOM #} {# so the SPREAD dropdown can swap `.my-sea-cross[data- #} {# spread]` between the 4 three-card variants (each w. its #} {# own 3-position subset + draw order) + the 2 six-card #} {# Celtic Cross variants (all 6 surrounding positions). #} {# Each empty slot carries a `.sea-pos-label` caption (re- #} {# appropriated from the GRAVITY/LEVITY .sea-stack-name look) #} {# that JS updates per spread. #} {# #} {# `id="id_sea_overlay"` aliases the picker to what SeaDeal #} {# binds to (the gameroom uses the same ID on a different #} {# page — no DOM collision since my-sea + gameroom never co- #} {# exist in one DOM). FLIP click delegates to SeaDeal. #} {# openStage(), which fills the slot AND opens the portaled #} {# stage modal w. SPIN / FYI controls. #} {# Iter 4b — DEL guard reuses the shared `#id_guard_portal` #} {# from base.html (the same one the room's gear-menu DEL btn #} {# uses). Gaussian-glass tooltip positioned above the DEL btn,#} {# no backdrop. The picker IIFE below invokes it via #} {# `window.showGuard(delBtn, "Are you sure?", confirmFn, null,#} {# {yesLabel: "DEL"})` when DEL is clicked post-lock. #} {# Sprint 5 iter 4a — shuffled deck (levity + gravity halves, #} {# sig excluded) embedded as JSON; JS reads on init and #} {# pops from the relevant pile on each deposit. #} {{ sea_deck_data|json_script:"id_my_sea_deck" }} {# StageCard + SeaDeal — both bind to `#id_sea_overlay` (the #} {# my-sea-picker) + `#id_sea_stage` (the stage partial) on #} {# DOMContentLoaded; openStage() runs on FLIP click below. #} {# Brief 'Default deck warning' banner — lifted verbatim from #} {# /billboard/my-sign/'s no-equipped-deck path. Same copy, #} {# same FYI (→ /gameboard/) + NVM (dismiss + proceed) actions.#} {# Tagged w. .my-sea-intro-banner so FTs disambiguate from #} {# any other Briefs on the page. note.js itself is hoisted #} {# to the top of {% block content %} (single load per page). #} {% if active_draw %} {# Iter 4b — saved-draw Brief. Standard portaled banner via #} {# Brief.showBanner (Gaussian-glass bg, atop-h2 positioning); #} {# the on-LOCK-success path inside the picker IIFE calls the #} {# same `window._showFreeDrawLockedBrief` so a freshly-locked #} {# hand gets the identical UX without a page reload. Pass an #} {# ISO timestamp (`|date:'c'`) so note.js's `
{% endblock content %}