PICK SEA slot interaction: polarity card bg/border, cross-slot opacity fix, two-step tap; _hideOk ReferenceError removed from sea.js; Jasmine spec updated for two-step; migration 0012 PENTACLES cleanup — TDD
Some checks failed
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline failed

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-04-29 02:30:59 -04:00
parent 08aa4dc819
commit e084bcc2d5
9 changed files with 186 additions and 52 deletions

View File

@@ -0,0 +1,27 @@
"""Delete 4 stray PENTACLES court cards from the Earthman deck.
These survived the migration collapse; the Earthman deck uses
BRANDS/GRAILS/BLADES/CROWNS only.
"""
from django.db import migrations
def delete_pentacles(apps, schema_editor):
TarotCard = apps.get_model("epic", "TarotCard")
DeckVariant = apps.get_model("epic", "DeckVariant")
try:
earthman = DeckVariant.objects.get(slug="earthman")
except DeckVariant.DoesNotExist:
return
TarotCard.objects.filter(deck_variant=earthman, suit="PENTACLES").delete()
class Migration(migrations.Migration):
dependencies = [
("epic", "0011_nomad_schizo_icons"),
]
operations = [
migrations.RunPython(delete_pentacles, reverse_code=migrations.RunPython.noop),
]

View File

@@ -63,7 +63,7 @@ var SeaDeal = (function () {
stageCard.querySelector('.fan-card-reversal-name').textContent = title;
} else {
stageCard.querySelector('.fan-card-reversal-qualifier').textContent = qualifier;
stageCard.querySelector('.fan-card-reversal-name').textContent = '';
stageCard.querySelector('.fan-card-reversal-name').textContent = title;
}
// Keywords
@@ -109,7 +109,7 @@ var SeaDeal = (function () {
function _openInfo() {
_infoOpen = true;
_renderInfo();
if (fyiPanel) fyiPanel.style.display = '';
if (fyiPanel) fyiPanel.style.display = 'flex';
if (spinBtn) { spinBtn.classList.add('btn-disabled'); spinBtn.textContent = '×'; }
if (fyiBtn) { fyiBtn.classList.add('btn-disabled'); fyiBtn.textContent = '×'; }
stage.classList.add('sea-info-open');
@@ -142,12 +142,22 @@ var SeaDeal = (function () {
// ── Show / hide stage ─────────────────────────────────────────────────────
function _showStage() {
function _showStage(isLevity) {
stage.style.display = '';
stage.classList.toggle('sea-stage--levity', !!isLevity);
stage.classList.toggle('sea-stage--gravity', !isLevity);
stageCard.classList.add('sea-stage-card--shown');
}
function _hideStage() {
// Reveal the deposited card in its slot (opacity 0 → 0.6 transition)
if (_viewingPos) {
var cell = overlay.querySelector(_viewingPos);
if (cell) {
var slot = cell.querySelector('.sea-card-slot--filled');
if (slot) slot.classList.add('sea-card-slot--visible');
}
}
stage.style.display = 'none';
stageCard.classList.remove('sea-stage-card--shown');
_viewingPos = null;
@@ -161,7 +171,7 @@ var SeaDeal = (function () {
_seaHand[posSelector] = { card: card, isLevity: isLevity };
_populate(card, isLevity);
_fillSlot(posSelector, card, isLevity);
_showStage();
_showStage(isLevity);
}
// ── Init ──────────────────────────────────────────────────────────────────
@@ -197,6 +207,9 @@ var SeaDeal = (function () {
spinBtn.addEventListener('click', function () {
if (spinBtn.classList.contains('btn-disabled')) return;
statBlock.classList.toggle('is-reversed');
// Remove animation fill, force reflow so the transition has a start state
stageCard.classList.remove('sea-stage-card--shown');
stageCard.getBoundingClientRect(); // flush layout
stageCard.classList.toggle('stage-card--reversed');
});
}
@@ -209,6 +222,18 @@ var SeaDeal = (function () {
});
}
// Clicking the FYI panel itself dismisses it (same as sig-select caution)
if (fyiPanel) {
fyiPanel.addEventListener('click', function (e) {
if (!e.target.closest('.sea-fyi-prev') && !e.target.closest('.sea-fyi-next')) {
_closeInfo();
}
});
}
// Clicking the FYI panel closes it (same pattern as sig-select)
if (fyiPanel) fyiPanel.addEventListener('click', _closeInfo);
// FYI nav
if (fyiPrev) {
fyiPrev.addEventListener('click', function () {
@@ -228,16 +253,34 @@ var SeaDeal = (function () {
bdrop.addEventListener('click', _hideStage);
}
// Click on deposited slot → re-open
// Overlay click — handle slot focus/open two-step tap pattern
// (deck-stack _hideOk is registered separately from the inline template script)
overlay.addEventListener('click', function (e) {
var slot = e.target.closest('.sea-card-slot--filled');
if (!slot) return;
if (!slot) {
// Clicked outside any filled slot — unfocus all
overlay.querySelectorAll('.sea-card-slot--focused').forEach(function (s) {
s.classList.remove('sea-card-slot--focused');
});
return;
}
var pos = slot.dataset.posKey;
if (!pos || !_seaHand[pos]) return;
var h = _seaHand[pos];
_viewingPos = pos;
_populate(h.card, h.isLevity);
_showStage();
if (slot.classList.contains('sea-card-slot--focused')) {
// Second tap/click — open modal
var h = _seaHand[pos];
_viewingPos = pos;
_populate(h.card, h.isLevity);
_showStage(h.isLevity);
} else {
// First tap/click — focus (persist opacity 1)
overlay.querySelectorAll('.sea-card-slot--focused').forEach(function (s) {
s.classList.remove('sea-card-slot--focused');
});
slot.classList.add('sea-card-slot--focused');
}
});
}
@@ -256,6 +299,7 @@ var SeaDeal = (function () {
return {
openStage: openStage,
resetHand: resetHand,
reinit: init, // call after overlay is injected into the DOM
_testInit: function () {
overlay = null; stage = null; stageCard = null; statBlock = null;
spinBtn = null; fyiBtn = null; bdrop = null;

View File

@@ -157,7 +157,7 @@ var SigSelect = (function () {
stageCard.querySelector('.fan-card-reversal-name').textContent = title;
} else {
stageCard.querySelector('.fan-card-reversal-qualifier').textContent = qualifier;
stageCard.querySelector('.fan-card-reversal-name').textContent = '';
stageCard.querySelector('.fan-card-reversal-name').textContent = title;
}
// Populate stat block keyword faces and reset to upright