{% load static %}
{% comment %}
DRAW SEA — Sea Select felt (2026-06-07), mirroring Sky Select's form→wheel
scroll-snap. The felt starts with the spread OPTIONS (.sea-options-col, page 1):
the .sea-select combobox (the two Celtic Cross spreads only) + a mini shape
preview + OK + AUTO DRAW + DEL. Clicking OK confirms the spread → the options
shunt DOWN and the spread CROSS (.sea-cross-col, w. the Gravity/Levity deck
stacks) takes page 1 via scroll-snap (scroll down to find the options again).
NO modal, NO corner NVM. The burger #id_sea_btn is the post-completion REOPEN
affordance (active only once the spread is complete, like the sky btn) — NOT
active during drawing. Each draw persists onto the seat's Character.celtic_cross
via epic:sea_save. `?seat` threads the CARTE-selected seat onto the action URLs.
{% endcomment %}
<div class="sea-page sea-page--room{% if saved_by_position %} sea-spread-chosen{% endif %}" id="id_sea_page">
<div id="id_sea_overlay" class="sea-overlay-content"
     data-sea-deck-url="{% url 'epic:sea_deck' room.id %}{% if current_slot %}?seat={{ current_slot }}{% endif %}"
     data-sea-save-url="{% url 'epic:sea_save' room.id %}{% if current_slot %}?seat={{ current_slot }}{% endif %}"
     data-sea-delete-url="{% url 'epic:sea_delete' room.id %}{% if current_slot %}?seat={{ current_slot }}{% endif %}"
     data-sea-user-polarity="{{ user_polarity }}">

    {# ── OPTIONS section — page 1 initially; shunts to page 2 on OK. The select #}
    {# form + preview + the OK / AUTO DRAW / DEL actions. NO deck stacks here.    #}
    <div class="sea-options-col">
        <div class="sea-form-col">
            <div class="sea-form-main">
                <div class="sea-field">
                    <label for="id_sea_spread" id="id_sea_spread_label">Spread</label>
                    <p class="sea-reversal-hint">{{ stack_reversal_pct|default:25 }}% reversals</p>
                    {# Two Celtic Cross 6-card spreads only (user-spec 2026-06-07). #}
                    <input type="hidden" id="id_sea_spread" name="spread" autocomplete="off"
                           value="{{ sea_default_spread }}">
                    {# Combobox + OK on one row — OK confirms the spread → shunts.   #}
                    {# OK gains .btn-disabled + × the moment the first card is drawn  #}
                    {# (the spread is then locked, the select disables, DEL enables). #}
                    <div class="sea-select-row">
                        <div class="sea-select"
                             data-combobox
                             data-combobox-target="id_sea_spread"
                             role="combobox"
                             aria-expanded="false"
                             aria-haspopup="listbox"
                             aria-labelledby="id_sea_spread_label"
                             tabindex="0">
                            <span class="sea-select-current">{% if sea_default_spread == "escape-velocity" %}Celtic Cross,<br>Escape Velocity{% else %}Celtic Cross,<br>Rider-Waite-Smith{% endif %}</span>
                            <span class="sea-select-arrow" aria-hidden="true">▾</span>
                            <ul class="sea-select-list" role="listbox">
                                {% if user_polarity == "levity" %}
                                    <li role="option" data-value="waite-smith"     aria-selected="{% if sea_default_spread == 'escape-velocity' %}false{% else %}true{% endif %}">Celtic Cross,<br>Rider-Waite-Smith</li>
                                    <li role="option" data-value="escape-velocity" aria-selected="{% if sea_default_spread == 'escape-velocity' %}true{% else %}false{% endif %}">Celtic Cross,<br>Escape Velocity</li>
                                {% else %}
                                    <li role="option" data-value="escape-velocity" aria-selected="{% if sea_default_spread == 'waite-smith' %}false{% else %}true{% endif %}">Celtic Cross,<br>Escape Velocity</li>
                                    <li role="option" data-value="waite-smith"     aria-selected="{% if sea_default_spread == 'waite-smith' %}true{% else %}false{% endif %}">Celtic Cross,<br>Rider-Waite-Smith</li>
                                {% endif %}
                            </ul>
                        </div>
                        <button type="button" id="id_sea_confirm_spread" class="btn btn-confirm{% if saved_by_position %} btn-disabled{% endif %}">{% if saved_by_position %}&times;{% else %}OK{% endif %}</button>
                    </div>
                </div>

                {# Miniaturized spread preview — shape only, never dealt to. Shows  #}
                {# the chosen spread's shape before OK reveals the real cross.      #}
                {% include "apps/gameboard/_partials/_sea_spread_preview.html" with preview_spread=sea_default_spread sig=my_tray_sig %}
            </div>

            <div class="sea-form-actions">
                {# AUTO DRAW commits the remaining hand in one POST + animates onto  #}
                {# the cross (confirms the spread first if not yet). DEL clears.     #}
                <button type="button"
                        id="id_sea_action_btn"
                        class="btn btn-primary{% if hand_complete %} btn-disabled{% endif %}"
                        data-state="{% if hand_complete %}complete{% else %}auto-draw{% endif %}">AUTO<br>DRAW</button>
                <button type="button"
                        id="id_sea_del"
                        class="btn btn-danger{% if not saved_by_position %} btn-disabled{% endif %}">{% if saved_by_position %}DEL{% else %}&times;{% endif %}</button>
            </div>
        </div>
    </div>

    {# ── CROSS section — hidden until OK; then order:-1 takes page 1. The REAL   #}
    {# deal target (.my-sea-cross) + the Gravity/Levity deck stacks (FLIP).       #}
    <div class="sea-cross-col">
        <div class="sea-cards-col">
            <div class="sea-cross my-sea-cross" data-spread="{{ sea_default_spread }}">
                <div class="sea-crucifix-cell sea-pos-crown">
                    <span class="sea-pos-label" data-position="crown"></span>
                    {% include "apps/gameboard/_partials/_my_sea_slot.html" with position="crown" saved=saved_by_position.crown crossing=False %}
                </div>
                <div class="sea-crucifix-cell sea-pos-leave">
                    <span class="sea-pos-label" data-position="leave"></span>
                    {% include "apps/gameboard/_partials/_my_sea_slot.html" with position="leave" saved=saved_by_position.leave crossing=False %}
                </div>
                <div class="sea-crucifix-cell sea-pos-core">
                    {# Center significator — supply the card-FACE image when the sig's #}
                    {# deck has one (mirrors my_sea); else the corner-rank + suit-icon  #}
                    {# text thumbnail. my_tray_sig.deck_variant is the card's OWN deck  #}
                    {# (Sig Select picks from the Role Select contributed deck).        #}
                    <div class="sig-stage-card sea-sig-card{% if my_tray_sig.deck_variant.has_card_images %} sig-stage-card--image{% endif %}" style="--sig-card-w: 4rem"{% if my_tray_sig %} data-card-id="{{ my_tray_sig.id }}" data-arcana-key="{{ my_tray_sig.arcana }}"{% endif %}>
                        {% if my_tray_sig %}
                            {% if my_tray_sig.deck_variant.has_card_images %}
                                <img class="sig-stage-card-img" src="{{ my_tray_sig.image_url }}" alt="{{ my_tray_sig.name }}">
                            {% else %}
                                <span class="fan-corner-rank">{{ my_tray_sig.corner_rank }}</span>
                                {% if my_tray_sig.suit_icon %}<i class="fa-solid {{ my_tray_sig.suit_icon }}"></i>{% endif %}
                            {% endif %}
                        {% endif %}
                    </div>
                    <div class="sea-pos-cover">
                        <span class="sea-pos-label" data-position="cover"></span>
                        {% include "apps/gameboard/_partials/_my_sea_slot.html" with position="cover" saved=saved_by_position.cover crossing=False %}
                    </div>
                    <div class="sea-pos-cross">
                        <span class="sea-pos-label" data-position="cross"></span>
                        {% include "apps/gameboard/_partials/_my_sea_slot.html" with position="cross" saved=saved_by_position.cross crossing=True %}
                    </div>
                </div>
                <div class="sea-crucifix-cell sea-pos-loom">
                    <span class="sea-pos-label" data-position="loom"></span>
                    {% include "apps/gameboard/_partials/_my_sea_slot.html" with position="loom" saved=saved_by_position.loom crossing=False %}
                </div>
                <div class="sea-crucifix-cell sea-pos-lay">
                    <span class="sea-pos-label" data-position="lay"></span>
                    {% include "apps/gameboard/_partials/_my_sea_slot.html" with position="lay" saved=saved_by_position.lay crossing=False %}
                </div>
            </div>
        </div>

        {# ALWAYS two stacks (Gravity + Levity) — the gamer draws from EITHER      #}
        {# populated half (sea_deck returns both), even a CARTE monodeck.          #}
        <div class="my-sea-stacks-wrap">
            <div class="sea-stacks">
                <span class="sea-stacks-label">DECKS</span>
                <div class="sea-deck-stack sea-deck-stack--gravity">
                    <div class="sea-stack-face">
                        <button class="btn btn-reveal sea-stack-flip{% if hand_complete %} btn-disabled{% endif %}" type="button">{% if hand_complete %}&times;{% else %}FLIP{% endif %}</button>
                    </div>
                    <span class="sea-stack-name">Gravity</span>
                </div>
                <div class="sea-deck-stack sea-deck-stack--levity">
                    <div class="sea-stack-face">
                        <button class="btn btn-reveal sea-stack-flip{% if hand_complete %} btn-disabled{% endif %}" type="button">{% if hand_complete %}&times;{% else %}FLIP{% endif %}</button>
                    </div>
                    <span class="sea-stack-name">Levity</span>
                </div>
            </div>
        </div>
    </div>

    {# Sea stage — portaled big-card viewer (position:fixed, escapes the snap). #}
    {# `sea_stage_dubbo` flags the gameroom's cloned two-toned dubbodeck so the #}
    {# FLIP-back polarity tint applies HERE only (my_sea/visit draw a monodeck  #}
    {# that is never cloned — no tint there). See _card-deck.scss.              #}
    {% include "apps/gameboard/_partials/_sea_stage.html" with sea_stage_dubbo=True %}
</div>
</div>

<script>
(function () {
  'use strict';

  var page    = document.getElementById('id_sea_page');
  var overlay = document.getElementById('id_sea_overlay');
  if (!page || !overlay) return;

  // ── Per-spread draw order + labels — the two Celtic Cross variants only.
  var DRAW_ORDER = {
    'waite-smith':     ['cover', 'cross', 'crown', 'lay',   'loom',  'leave'],
    'escape-velocity': ['cover', 'cross', 'lay',   'leave', 'crown', 'loom'],
  };
  var POSITION_LABELS = {
    'waite-smith':     { crown: 'Crown', leave: 'Behind', cover: 'Cover', cross: 'Cross', loom: 'Before', lay: 'Beneath' },
    'escape-velocity': { crown: 'Crown', leave: 'Leave',  cover: 'Cover', cross: 'Cross', loom: 'Loom',   lay: 'Lay' },
  };

  var hidden    = overlay.querySelector('#id_sea_spread');
  var cross     = overlay.querySelector('.my-sea-cross');
  var preview   = overlay.querySelector('.sea-cross--preview');
  var actionBtn = overlay.querySelector('#id_sea_action_btn');
  var delBtn    = overlay.querySelector('#id_sea_del');
  var okBtn     = overlay.querySelector('#id_sea_confirm_spread');
  var seaSelect = overlay.querySelector('[data-combobox][data-combobox-target="id_sea_spread"]');
  if (!hidden || !cross) return;

  var SEA_DECK_URL   = overlay.dataset.seaDeckUrl;
  var SEA_SAVE_URL   = overlay.dataset.seaSaveUrl;
  var SEA_DELETE_URL = overlay.dataset.seaDeleteUrl;

  var _levityPile = [], _gravityPile = [];
  var _filled = 0;
  var _activeStack = null;
  var _locked = false;

  function _csrf() {
    var m = document.cookie.match(/(?:^|; )csrftoken=([^;]+)/);
    return m ? decodeURIComponent(m[1]) : '';
  }
  function _currentOrder() { return DRAW_ORDER[hidden.value] || DRAW_ORDER['waite-smith']; }

  function _fetchDeck() {
    return fetch(SEA_DECK_URL, { credentials: 'same-origin' })
      .then(function (r) { return r.json(); })
      .then(function (data) { _levityPile = data.levity || []; _gravityPile = data.gravity || []; })
      .catch(function () {});
  }

  function _hideOk() {
    if (_activeStack) { _activeStack.classList.remove('sea-deck-stack--active'); _activeStack = null; }
  }
  function _showOk(stack) { _hideOk(); _activeStack = stack; stack.classList.add('sea-deck-stack--active'); }

  function _lockSpread() {
    if (seaSelect) { seaSelect.classList.add('sea-select--locked'); seaSelect.setAttribute('aria-disabled', 'true'); }
  }

  // ── Confirm the chosen spread → shunt the options DOWN + reveal the cross.
  // Mirrors Sky Select's form→wheel: the felt page gets `sea-spread-chosen` → the
  // SCSS engages the scroll-snap (the cross takes page 1 via order:-1, the options
  // shunt to page 2); lock the combobox; ease the scroller up to the cross.
  // Idempotent. Triggered by OK and (defensively) by AUTO DRAW.
  var _spreadChosen = page.classList.contains('sea-spread-chosen');
  function _chooseSpread(slideIn) {
    if (!_spreadChosen) {
      _spreadChosen = true;
      page.classList.add('sea-spread-chosen');
      slideIn = true;   // the first reveal always slides in from below
    }
    // NB: the combobox is NOT locked here — the spread stays changeable (scroll
    // up) until the FIRST card is drawn, when _lockSpread() + _setHasDrawn(true)
    // disable the select + OK together (user-spec 2026-06-07).
    // `slideIn` (OK reveal) pins to the options (page 2) first so the cross
    // slides in from above. AUTO DRAW fired from a scrolled-down options page
    // skips the pin + just eases UP to the cross (so the user watches the draw).
    if (slideIn) {
      var opts = overlay.querySelector('.sea-options-col');
      if (opts) page.scrollTop = opts.offsetTop;
    }
    _scrollToCross();
  }
  function _scrollToCross() {
    // Ease the scroller UP to the cross (page 1, scrollTop 0) from wherever it is.
    if (page.scrollTop === 0) return;
    var start = page.scrollTop, t0 = null, DUR = 320;
    function step(now) {
      if (t0 === null) t0 = now;
      var t = Math.min(1, (now - t0) / DUR);
      var u = 1 - t, e = 1 - u * u * u;
      page.scrollTop = Math.max(0, start * (1 - e));
      if (t < 1) requestAnimationFrame(step);
    }
    requestAnimationFrame(step);
  }
  if (okBtn) okBtn.addEventListener('click', function () {
    if (okBtn.classList.contains('btn-disabled')) return;
    _chooseSpread(true);
  });

  // First card drawn → DEL un-disables ("DEL") + OK disables ("×"), simultaneous
  // with the combobox locking (`_lockSpread`). The two btns are inverse states.
  function _setHasDrawn(on) {
    if (delBtn) { delBtn.classList.toggle('btn-disabled', !on); delBtn.innerHTML = on ? 'DEL' : '×'; }
    if (okBtn)  { okBtn.classList.toggle('btn-disabled', on);  okBtn.innerHTML  = on ? '×' : 'OK'; }
  }
  function _setComplete(on, live) {
    _locked = on;
    overlay.querySelectorAll('.sea-deck-stack .sea-stack-flip').forEach(function (btn) {
      btn.classList.toggle('btn-disabled', on);
      btn.innerHTML = on ? '×' : 'FLIP';
    });
    if (actionBtn) {
      actionBtn.dataset.state = on ? 'complete' : 'auto-draw';
      actionBtn.classList.toggle('btn-disabled', on);
    }
    _hideOk();
    if (on && live) _startSeaCascade();
  }

  // ── Post-completion cascade (mirrors CAST SKY's _startSaveCascade) ──────────
  // 6 cards down → linger ~3s → the felt eases OUT (revealing the table-hex) →
  // DRAW SEA gives way to SEED MAP + the sea glow fires (burger → sea_btn) → +3s
  // → SEED MAP eases IN. Same shape as CAST SKY → sky-btn glow → DRAW SEA.
  var _SEA_CASCADE_LINGER = 3000, _SEA_FELT_FADE = 500, _SEED_DELAY = 3000;
  var _cascadeRun = false;
  function _startSeaCascade() {
    if (_cascadeRun) return;
    _cascadeRun = true;
    setTimeout(_cascadeFeltOut, _SEA_CASCADE_LINGER);
  }
  function _cascadeFeltOut() {
    page.classList.add('sea-page--cascade-out');
    setTimeout(function () {
      document.documentElement.classList.remove('sea-open');
      page.classList.remove('sea-page--cascade-out');
      _restorePhaseBtns();
      if (window.RoomViews && window.RoomViews.syncGear) window.RoomViews.syncGear();
      var seaPhaseBtn = document.getElementById('id_pick_sea_btn');
      if (seaPhaseBtn) seaPhaseBtn.classList.add('hex-phase-btn--out');
      // The sea btn becomes the reopen/review affordance (active only NOW — the
      // post-completion cue, like the sky btn) + the sea glow fires on the burger.
      var seaBtn = document.getElementById('id_sea_btn');
      if (seaBtn) seaBtn.classList.add('active');
      var burgerBtn = document.getElementById('id_burger_btn');
      if (burgerBtn) burgerBtn.classList.add('glow-handoff');
      setTimeout(_cascadeSeedMapIn, _SEED_DELAY);
    }, _SEA_FELT_FADE);
  }
  function _cascadeSeedMapIn() {
    var seedBtn = document.getElementById('id_seed_map_btn');
    if (seedBtn) seedBtn.classList.remove('hex-phase-btn--out');
  }

  function _collectHandFromDom() {
    var byPos = {};
    cross.querySelectorAll('.sea-card-slot.sea-card-slot--filled').forEach(function (slot) {
      var pos = slot.dataset.posKey || '';
      if (!pos) return;
      byPos[pos] = {
        position: pos,
        card_id: parseInt(slot.dataset.cardId, 10),
        reversed: /sea-card-slot--reversed\b/.test(slot.className),
        polarity: /sea-card-slot--levity\b/.test(slot.className) ? 'levity' : 'gravity',
      };
    });
    var hand = [];
    _currentOrder().forEach(function (pos) { if (byPos[pos]) hand.push(byPos[pos]); });
    return hand;
  }

  function _postLock(hand) {
    if (!hand.length) return Promise.resolve(null);
    return fetch(SEA_SAVE_URL, {
      method: 'POST',
      credentials: 'same-origin',
      headers: { 'Content-Type': 'application/json', 'X-CSRFToken': _csrf() },
      body: JSON.stringify({ spread: hidden.value, hand: hand }),
    }).then(function (r) { return r.ok ? r.json() : null; }).catch(function () { return null; });
  }

  // ── Deck-stack FLIP → deposit one card onto the felt cross.
  overlay.querySelectorAll('.sea-deck-stack').forEach(function (stack) {
    stack.addEventListener('click', function (e) {
      e.stopPropagation();
      if (_activeStack === stack) _hideOk(); else _showOk(stack);
    });
    var ok = stack.querySelector('.sea-stack-flip');
    if (ok) {
      ok.addEventListener('click', function (e) {
        e.stopPropagation();
        if (_locked) { _hideOk(); return; }
        var isLevity = stack.classList.contains('sea-deck-stack--levity');
        var pile = isLevity ? _levityPile : _gravityPile;
        if (!pile.length) { pile = isLevity ? _gravityPile : _levityPile; isLevity = !isLevity; }
        var card = pile.length ? pile.shift() : null;
        var order = _currentOrder();
        var posName = order[_filled];
        if (card && posName) {
          if (window.SeaDeal && window.SeaDeal.openStage) {
            SeaDeal.openStage(card, '.sea-pos-' + posName, isLevity);
          }
          _filled++;
          if (_filled === 1) { _lockSpread(); _setHasDrawn(true); }
          _postLock(_collectHandFromDom());
          if (_filled >= order.length) _setComplete(true, true);   // live → cascade
        }
        _hideOk();
      });
    }
  });
  overlay.addEventListener('click', _hideOk);

  // ── AUTO DRAW — confirm the spread (reveal the cross) then commit + animate.
  function _autoDraw() {
    // Reveal the cross if not yet, AND scroll back UP to it even when the user
    // already OK'd + scrolled down to the options page — so he watches the cards
    // land one-by-one (user-spec 2026-06-08). `_chooseSpread(false)` skips the
    // slide-in pin when already chosen, just easing up to the cross.
    _chooseSpread(false);
    var order = _currentOrder();
    var remaining = order.length - _filled;
    if (remaining <= 0) return;
    var autoEntries = [];
    for (var i = 0; i < remaining; i++) {
      var isLevity = false;
      var pile = _gravityPile;
      if (_levityPile.length && (!_gravityPile.length || Math.round(Math.random()))) { isLevity = true; pile = _levityPile; }
      if (!pile.length) { isLevity = !isLevity; pile = isLevity ? _levityPile : _gravityPile; }
      if (!pile.length) break;
      autoEntries.push({ card: pile.shift(), posName: order[_filled + i], isLevity: isLevity });
    }
    var fullHand = _collectHandFromDom();
    autoEntries.forEach(function (e) {
      fullHand.push({ position: e.posName, card_id: e.card.id, reversed: !!e.card.reversed, polarity: e.isLevity ? 'levity' : 'gravity' });
    });
    _postLock(fullHand).then(function (body) {
      if (!body || !body.ok) return;
      if (_filled === 0) _lockSpread();
      _setHasDrawn(true);
      var idx = 0;
      function placeNext() {
        if (idx >= autoEntries.length) { _setComplete(true, true); return; }   // live → cascade
        var e = autoEntries[idx++];
        var stack = overlay.querySelector('.sea-deck-stack--' + (e.isLevity ? 'levity' : 'gravity'));
        if (stack) _showOk(stack);
        setTimeout(function () {
          if (window.SeaDeal && window.SeaDeal.register) {
            SeaDeal.register(e.card, '.sea-pos-' + e.posName, e.isLevity);
          }
          var sl = cross.querySelector('.sea-pos-' + e.posName + ' .sea-card-slot');
          if (sl) sl.classList.add('sea-card-slot--visible');
          _filled++;
          _hideOk();
          setTimeout(placeNext, 250);
        }, 350);
      }
      placeNext();
    });
  }

  // ── DEL — guard → clear the seat's celtic_cross → reload.
  if (delBtn) {
    delBtn.addEventListener('click', function (e) {
      e.stopPropagation();
      if (delBtn.classList.contains('btn-disabled')) return;
      if (!window.showGuard) return;
      window.showGuard(delBtn, 'Are you sure?', function () {
        fetch(SEA_DELETE_URL, {
          method: 'POST', credentials: 'same-origin', headers: { 'X-CSRFToken': _csrf() },
        }).then(function (r) { if (r.ok) window.location.reload(); });
      });
    });
  }

  // ── AUTO DRAW btn → guard portal.
  if (actionBtn) {
    actionBtn.addEventListener('click', function (e) {
      e.preventDefault();
      if (actionBtn.dataset.state !== 'auto-draw') return;
      if (!window.showGuard) return;
      window.showGuard(actionBtn, 'Auto Draw cards?', _autoDraw);
    });
  }

  // ── Spread switch (pre-OK) → re-layout the felt cross + the preview + labels.
  function syncLabels(spread) {
    var labels = POSITION_LABELS[spread] || {};
    cross.querySelectorAll('.sea-pos-label').forEach(function (el) {
      el.textContent = labels[el.dataset.position] || '';
    });
  }
  function sync() {
    cross.setAttribute('data-spread', hidden.value);
    if (preview) preview.setAttribute('data-spread', hidden.value);
    syncLabels(hidden.value);
  }
  hidden.addEventListener('change', sync);

  // ── Open / close the felt (DRAW SEA ⇄ gear NVM nav). On open: disable ONLY the
  // burger Text sub-btn (its swipe machine would drive into a scroll-locked
  // reelhouse). The SKY sub-btn is left .active (lit) — symmetric with Sky Select,
  // which leaves the sea btn lit while the sky felt is up (user-spec 2026-06-08):
  // both completed phases stay one click apart. The sea btn itself is NOT
  // activated here — it's the post-completion reopen affordance (see the cascade
  // + the reopen binding). Clicking the lit sky btn from here SWAPS felts cleanly
  // (openSea/openSky close each other — see openSea below).
  var _disabledBtns = [];
  function _disablePhaseBtns() {
    _disabledBtns = [];
    ['id_text_btn'].forEach(function (id) {
      var b = document.getElementById(id);
      if (b && b.classList.contains('active')) { b.classList.remove('active'); _disabledBtns.push(b); }
    });
  }
  function _restorePhaseBtns() {
    _disabledBtns.forEach(function (b) { b.classList.add('active'); });
    _disabledBtns = [];
  }
  function openSea() {
    // Clean SWAP, not a double-open: if the sky felt is up (its lit sea btn was
    // just clicked) close it first — both felts are z-5 siblings that otherwise
    // stack (sea paints over sky), and neither open path drops the other's
    // open-class on its own. Mirrored by openSky closing the sea felt.
    if (document.documentElement.classList.contains('sky-open') && window.closeSkyFelt) {
      window.closeSkyFelt();
    }
    document.documentElement.classList.add('sea-open');
    document.documentElement.classList.add('sea-entered');
    _disablePhaseBtns();
    if (window.RoomViews && window.RoomViews.syncGear) window.RoomViews.syncGear();
  }
  function closeSea() {
    document.documentElement.classList.remove('sea-open');
    _restorePhaseBtns();
    if (window.RoomViews && window.RoomViews.syncGear) window.RoomViews.syncGear();
  }
  window.openSeaFelt = openSea;
  window.closeSeaFelt = closeSea;
  var pickSeaBtn = document.getElementById('id_pick_sea_btn');
  if (pickSeaBtn) pickSeaBtn.addEventListener('click', openSea);

  // ── Sea sub-btn = post-completion REOPEN (active only once the spread is
  // complete, like the sky btn). An ACTIVE click re-shows the felt to review the
  // saved spread (window.openSeaFelt); inactive clicks fall to burger-btn.js's
  // --priRd flash. DEFERRED to DOMContentLoaded: #id_sea_btn lives in
  // _burger.html, which room.html includes AFTER this overlay — a parse-time
  // getElementById returns null → the binding would silently no-op (sea btn
  // dead). Bind once the burger fan exists.
  function _bindSeaReopen() {
    var seaSubBtn = document.getElementById('id_sea_btn');
    if (!seaSubBtn) return;
    seaSubBtn.addEventListener('click', function () {
      if (!seaSubBtn.classList.contains('active')) return;
      openSea();
    });
  }
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', _bindSeaReopen);
  } else {
    _bindSeaReopen();
  }

  // Re-seed SeaDeal's `_seaHand` from the server-rendered saved slots so they
  // stay clickable to RE-OPEN the stage after a refresh.
  function _seedSavedHand() {
    if (!window.SeaDeal || !window.SeaDeal.seedHand) return;
    var byId = {};
    _levityPile.concat(_gravityPile).forEach(function (c) { byId[c.id] = c; });
    var seed = {};
    cross.querySelectorAll('.sea-card-slot.sea-card-slot--filled').forEach(function (slot) {
      var posName = slot.dataset.posKey;
      var card = byId[parseInt(slot.dataset.cardId, 10)];
      if (!posName || !card) return;
      var slotCard = {};
      for (var k in card) if (Object.prototype.hasOwnProperty.call(card, k)) slotCard[k] = card[k];
      slotCard.reversed = slot.classList.contains('sea-card-slot--reversed');
      seed[posName] = { card: slotCard, isLevity: slot.classList.contains('sea-card-slot--levity') };
    });
    SeaDeal.seedHand(seed);
  }

  // ── Init — bind SeaDeal, seed the deck, then re-seed the saved hand.
  if (window.SeaDeal && window.SeaDeal.reinit) SeaDeal.reinit();
  _fetchDeck().then(_seedSavedHand);
  _filled = cross.querySelectorAll('.sea-card-slot.sea-card-slot--filled').length;
  if (_filled > 0) document.documentElement.classList.add('sea-entered');
  if (_filled >= _currentOrder().length) { _setComplete(true); _lockSpread(); _setHasDrawn(true); }
  else if (_filled > 0) { _lockSpread(); _setHasDrawn(true); }
  syncLabels(hidden.value);
}());
</script>

{# ── Sea glow handoff — the SEA glow-machine does NOT fire while drawing. The  #}
{# post-completion CASCADE (in the picker IIFE above) STARTS it on the burger   #}
{# as the felt eases out (DRAW SEA → SEED MAP), mirroring CAST SKY's burger →   #}
{# sky-btn cue. This IIFE only carries the handoff: burger → sea_btn →          #}
{# .sea-select → end, so the user is led to reopen + review their sea.          #}
<script>
(function () {
  // DEFERRED to DOMContentLoaded: #id_burger_btn + #id_sea_btn live in
  // _burger.html, which room.html includes AFTER this overlay — capturing them at
  // parse time yields null and the early-return below would skip every listener
  // (burger never sheds .glow-handoff → stuck --priId; the chain never advances).
  // Bind once the burger fan exists.
  function _bindGlowHandoff() {
    var burgerBtn = document.getElementById('id_burger_btn');
    var seaBtn    = document.getElementById('id_sea_btn');
    var seaSelect = document.querySelector('#id_sea_overlay .sea-select');
    if (!burgerBtn || !seaBtn || !seaSelect) return;

    var glowDone = false;
    function endGlow() {
      glowDone = true;
      burgerBtn.classList.remove('glow-handoff');
      seaBtn.classList.remove('glow-handoff');
      seaSelect.classList.remove('glow-handoff');
    }

    burgerBtn.addEventListener('click', function () {
      if (glowDone || !burgerBtn.classList.contains('glow-handoff')) return;
      burgerBtn.classList.remove('glow-handoff');
      seaBtn.classList.add('glow-handoff');
    });
    seaBtn.addEventListener('click', function () {
      if (glowDone || !seaBtn.classList.contains('glow-handoff')) return;
      seaBtn.classList.remove('glow-handoff');
      seaSelect.classList.add('glow-handoff');
    });
    seaSelect.addEventListener('click', function () {
      if (glowDone) return;
      endGlow();
    });
  }
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', _bindGlowHandoff);
  } else {
    _bindGlowHandoff();
  }
}());
</script>
