diff --git a/src/apps/epic/tests/integrated/test_views.py b/src/apps/epic/tests/integrated/test_views.py
index 8c80f35..d3db315 100644
--- a/src/apps/epic/tests/integrated/test_views.py
+++ b/src/apps/epic/tests/integrated/test_views.py
@@ -4211,6 +4211,33 @@ class PickSeaUnifiedFeltTest(TestCase):
self.assertNotIn("sea-deck-stack--single", content)
self.assertNotIn("sea-stacks--single", content)
+ def test_seed_map_btn_out_until_hand_complete(self):
+ """SEED MAP joins the hex phase stack (the post-completion cascade eases
+ it IN, mirroring CAST SKY → DRAW SEA). Pre-completion it renders --out
+ while DRAW SEA is in (user-spec 2026-06-07)."""
+ import lxml.html
+ parsed = lxml.html.fromstring(self.client.get(self.url).content)
+ [seed] = parsed.cssselect("#id_seed_map_btn")
+ self.assertIn("hex-phase-btn--out", seed.get("class", ""))
+ [sea] = parsed.cssselect("#id_pick_sea_btn")
+ self.assertNotIn("hex-phase-btn--out", sea.get("class", ""))
+
+ def test_seed_map_in_and_draw_sea_out_when_hand_complete(self):
+ """A reload of an already-complete sea lands on SEED MAP server-side:
+ SEED MAP in, DRAW SEA --out (the cascade's end-state, no animation)."""
+ card_id = TarotCard.objects.filter(deck_variant=self.earthman).first().id
+ char = Character.objects.get(seat=self.pc_seat, confirmed_at__isnull=False)
+ char.celtic_cross = {"spread": "waite-smith", "hand": [
+ {"position": p, "card_id": card_id, "reversed": False, "polarity": "gravity"}
+ for p in ["cover", "cross", "crown", "lay", "loom", "leave"]]}
+ char.save(update_fields=["celtic_cross"])
+ import lxml.html
+ parsed = lxml.html.fromstring(self.client.get(self.url).content)
+ [seed] = parsed.cssselect("#id_seed_map_btn")
+ self.assertNotIn("hex-phase-btn--out", seed.get("class", ""))
+ [sea] = parsed.cssselect("#id_pick_sea_btn")
+ self.assertIn("hex-phase-btn--out", sea.get("class", ""))
+
class CarteSeatSwitchSkySeaTest(TestCase):
"""A CARTE owner (one gamer owns all 6 seats) must drive EACH seat through
diff --git a/src/static_src/scss/_sky.scss b/src/static_src/scss/_sky.scss
index 238cf5b..833883d 100644
--- a/src/static_src/scss/_sky.scss
+++ b/src/static_src/scss/_sky.scss
@@ -103,6 +103,15 @@ html.sea-open .position-strip {
visibility: hidden;
}
+// Post-completion cascade ease-out — once the 6-card spread is complete the felt
+// fades to transparent over ~0.5s (the JS _SEA_FELT_FADE timer) BEFORE sea-open
+// is removed, revealing the table-hex with a soft dissolve (mirrors the CAST SKY
+// post-save cascade's .sky-page--cascade-out).
+.sea-page.sea-page--cascade-out {
+ opacity: 0;
+ transition: opacity 0.5s ease;
+}
+
// ── Backdrop ──────────────────────────────────────────────────────────────────
.sky-backdrop {
diff --git a/src/templates/apps/gameboard/_partials/_room_hex_center.html b/src/templates/apps/gameboard/_partials/_room_hex_center.html
index 86a1f7f..e437823 100644
--- a/src/templates/apps/gameboard/_partials/_room_hex_center.html
+++ b/src/templates/apps/gameboard/_partials/_room_hex_center.html
@@ -29,14 +29,17 @@ sky_confirmed, polarity_done, user_polarity, current_slot, …).
onclick="window.location.href='{% url 'epic:room_gate' room.id %}{% if current_slot %}?seat={{ current_slot }}{% endif %}'">GATE
VIEW
{% else %}
{% if room.table_status == "SKY_SELECT" %}
- {# Both phase btns render so the post-save cascade can cross-fade CAST #}
- {# SKY → DRAW SEA in place (no reload). The server sets --out on the #}
- {# inactive one; sky-select.js's cascade swaps them. On a confirmed #}
- {# reload the server lands DRAW SEA visible + CAST SKY out, same as the #}
- {# cascade end. #}
+ {# All three phase btns render so the cascades can cross-fade in place #}
+ {# (no reload): CAST SKY → DRAW SEA on sky-save, then DRAW SEA → SEED MAP #}
+ {# on the 6-card spread completing. The server sets --out on the inactive #}
+ {# ones; the sky/sea cascades swap them. On a reload the server lands the #}
+ {# right one visible (DRAW SEA once sky_confirmed; SEED MAP once the sea #}
+ {# hand is complete), same as each cascade's end. SEED MAP → the Voronoi #}
+ {# map (roadmap step 21) is a stub for now — it only needs to APPEAR here. #}