diff --git a/src/apps/epic/static/apps/epic/sea.js b/src/apps/epic/static/apps/epic/sea.js
index 75e59b4..c38b72c 100644
--- a/src/apps/epic/static/apps/epic/sea.js
+++ b/src/apps/epic/static/apps/epic/sea.js
@@ -227,6 +227,31 @@ var SeaDeal = (function () {
});
}
+ // Polish-6 — FLIP btn (rotateY 0→90→0 over 500ms, toggle
+ // `.is-flipped-to-back` at midpoint). Renders unconditionally per
+ // user-spec "allow the FLIP btn everywhere"; no-ops when the card
+ // has no `.sig-stage-card-back-img` sibling (back-img only renders
+ // server-side for non-polarized image-equipped decks; text-mode +
+ // polarized image decks render no back-img + the FLIP is inert).
+ // Mirrors `_flipToBackAnimated` shape from my_sign.html / applet.
+ var flipBtn = stage.querySelector('.sea-stage-flip-btn');
+ if (flipBtn) {
+ flipBtn.addEventListener('click', function () {
+ if (stageCard.dataset.flipping) return;
+ if (!stageCard.querySelector('.sig-stage-card-back-img')) return;
+ stageCard.dataset.flipping = '1';
+ stageCard.animate([
+ { transform: 'rotateY(0deg)' },
+ { transform: 'rotateY(90deg)', offset: 0.5 },
+ { transform: 'rotateY(0deg)' },
+ ], { duration: 500, easing: 'ease' });
+ setTimeout(function () {
+ stageCard.classList.toggle('is-flipped-to-back');
+ }, 250);
+ setTimeout(function () { delete stageCard.dataset.flipping; }, 500);
+ });
+ }
+
// Clicking the FYI panel itself dismisses it (same as sig-select caution)
if (fyiPanel) {
fyiPanel.addEventListener('click', function (e) {
diff --git a/src/static_src/scss/_card-deck.scss b/src/static_src/scss/_card-deck.scss
index 117b219..3ee411d 100644
--- a/src/static_src/scss/_card-deck.scss
+++ b/src/static_src/scss/_card-deck.scss
@@ -989,12 +989,15 @@ html:has(.sig-backdrop) {
background: rgba(var(--duoUser), 1);
}
-// Polish-5: my_sign main + applet FLIP btns share one positioning rule.
-// Both live INSIDE their card (`.sig-stage-card` / `.my-sign-applet-card`,
-// both `position: relative`) so `bottom: 0.6rem; left: 0.6rem` anchors
-// universally to card-bottom-left w/o needing surface-specific calc().
+// Polish-5: my_sign main + applet + sea_stage FLIP btns share one positioning
+// rule. All live INSIDE their card (`.sig-stage-card` / `.my-sign-applet-card`
+// / `.sig-stage-card.sea-stage-card`, all `position: relative`) so `bottom:
+// 0.6rem; left: 0.6rem` anchors universally to card-bottom-left w/o needing
+// surface-specific calc(). Polish-6 added sea-stage-flip-btn for the sea_stage
+// modal per user-spec "allow the FLIP btn everywhere".
.my-sign-flip-btn,
-.my-sign-applet-flip-btn {
+.my-sign-applet-flip-btn,
+.sea-stage-flip-btn {
@include flip-btn-base;
z-index: 25;
bottom: 0.6rem;
@@ -1012,19 +1015,22 @@ html:has(.sig-backdrop) {
.my-sign-stage.sig-stage--frozen .sig-stage-card:hover .my-sign-flip-btn,
.my-sign-stage.sig-stage--frozen .sig-stage-card:has(.my-sign-flip-btn:hover) .my-sign-flip-btn,
.my-sign-applet-card:hover .my-sign-applet-flip-btn,
-.my-sign-applet-card:has(.my-sign-applet-flip-btn:hover) .my-sign-applet-flip-btn {
+.my-sign-applet-card:has(.my-sign-applet-flip-btn:hover) .my-sign-applet-flip-btn,
+.sea-stage-card:hover .sea-stage-flip-btn,
+.sea-stage-card:has(.sea-stage-flip-btn:hover) .sea-stage-flip-btn {
@extend %flip-btn-revealed;
}
-// Unified mid-flip-hide across all 3 surfaces. `[data-flipping]="1"` is set on
+// Unified mid-flip-hide across all 4 surfaces. `[data-flipping]="1"` is set on
// the card by each surface's FLIP handler for the 500ms rotation duration;
// `%flip-btn-mid-flip`'s `display: none` makes the btn vanish INSTANTLY (per
// user spec — no ease-out logic competing w. the click). Selector chains
// differ per surface because the btn-to-card DOM relationship varies (btn is
-// INSIDE the card on my_sign + applet post-polish-5; sibling under .tarot-
-// fan-wrap for the fan).
+// INSIDE the card on my_sign + applet + sea_stage; sibling under .tarot-fan-
+// wrap for the fan carousel).
.sig-stage-card[data-flipping] .my-sign-flip-btn,
.my-sign-applet-card[data-flipping] .my-sign-applet-flip-btn,
+.sea-stage-card[data-flipping] .sea-stage-flip-btn,
.tarot-fan-wrap:has(.fan-card[data-flipping]) .fan-flip-btn {
@extend %flip-btn-mid-flip;
}
diff --git a/src/templates/apps/billboard/_partials/_applet-my-sign.html b/src/templates/apps/billboard/_partials/_applet-my-sign.html
index d7f98ad..b978104 100644
--- a/src/templates/apps/billboard/_partials/_applet-my-sign.html
+++ b/src/templates/apps/billboard/_partials/_applet-my-sign.html
@@ -18,23 +18,26 @@
data-card-id="{{ card.id }}"
data-arcana-key="{{ card.arcana }}">
{% if card.deck_variant.has_card_images %}
- {# Sprint A.6 — image-mode render mirrors my_sign.html's #}
- {# .sig-stage-card--image treatment. Shares the SCSS rule #}
- {# (comma-list selector) so the contour stroke + tray-card #}
- {# silhouette black depth shadow + arcana stroke-color #}
- {# come for free. #}
+ {% comment %}
+ Sprint A.6 — image-mode render mirrors my_sign.html's
+ .sig-stage-card--image treatment. Shares the SCSS rule
+ (comma-list selector) so the contour stroke + tray-card
+ silhouette black depth shadow + arcana stroke-color
+ come for free.
+ {% endcomment %}
{% if not card.deck_variant.is_polarized %}
- {# Non-polarized image deck: FLIP btn shows the deck back #}
- {# image (same behavior as my_sign.html main page). Both #}
- {# the back-img + flip-btn nest INSIDE the card so the #}
- {# absolute-positioned FLIP btn anchors to the card's #}
- {# bounds (card is position: relative in --image mode). #}
+ {% comment %}
+ Non-polarized image deck: back-img element renders the
+ deck-back PNG that FLIP toggles to. Back-img stays gated
+ (back-img is meaningless for polarized decks or text-mode);
+ the FLIP btn itself moved OUT of this gate in polish-6 so
+ it renders for every card (per user-spec "allow the FLIP
+ btn everywhere"). The JS click handler is a no-op when no
+ back-img sibling exists.
+ {% endcomment %}
-
{% endif %}
{% else %}
{{ face.qualifier }}
@@ -67,6 +72,16 @@ {% if card.suit_icon %}{% endif %}No sign chosen yet.
diff --git a/src/templates/apps/gameboard/_partials/_sea_stage.html b/src/templates/apps/gameboard/_partials/_sea_stage.html index 56b3093..001ac69 100644 --- a/src/templates/apps/gameboard/_partials/_sea_stage.html +++ b/src/templates/apps/gameboard/_partials/_sea_stage.html @@ -41,6 +41,24 @@ + {% comment %} + Polish-6 — back-img + FLIP btn. The back-img mirrors the + my_sign.html / _applet-my-sign.html pattern: only renders + for non-polarized image-equipped decks (since back-img is + meaningless otherwise; src derives from user's equipped + deck). FLIP btn renders UNCONDITIONALLY per user-spec "allow + the FLIP btn everywhere"; sea.js's click handler no-ops + when no back-img sibling exists. Multi-user gameroom is a + known limitation here — the back-img src is the room + viewer's deck-back, not the drawing gamer's, which is wrong + when different gamers' decks have different backs. Parked + for a future multi-user polish pass. + {% endcomment %} + {% if request.user.is_authenticated and request.user.equipped_deck.has_card_images and not request.user.equipped_deck.is_polarized %} +