Sea Select: keep the sky btn lit on a revisited felt (+ clean felt-swap); slow the glow-handoff ease-out — TDD
Symmetry (user-spec): Sky Select leaves the burger sea btn lit while the sky felt is up; Sea Select now mirrors it — openSea disables ONLY id_text_btn, no longer id_sky_btn, so a revisited Sea Select keeps the completed sky one click away. An adversarial pass flagged that the two felts are equal-z (z-index:5) siblings and neither open path drops the other's open-class, so leaving the sky btn lit and clicking it from inside the sea felt would DOUBLE-OPEN (sea paints over sky → confusing no-op) — the same latent stack already reachable in the sky->sea direction on a both-complete reload. Fixed in BOTH directions: openSea now closes the sky felt first + openSky closes the sea felt first (each exposes its close on window: closeSeaFelt / closeSkyFelt), so clicking the other phase's lit btn performs a clean SWAP. The text-btn disable/restore chain stays correct across the swap (closeSky restores text, openSea re-disables + recaches it). Glow: the glow-handoff pulse ease-OUT now runs ~2.8s (was ~1.4s) — moved the cycle to 3.2s with the bright peak at 12.5%, keeping the ease-IN swell at ~0.4s (user asked for a longer linger). [[feedback-felt-aperture-fill-covers-felt]] [[feedback-inline-partial-script-defer-for-later-partial]] Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4270,6 +4270,25 @@ class PickSeaUnifiedFeltTest(TestCase):
|
||||
[sea] = parsed.cssselect("#id_pick_sea_btn")
|
||||
self.assertIn("hex-phase-btn--out", sea.get("class", ""))
|
||||
|
||||
def test_sea_felt_leaves_sky_btn_lit_and_swaps_cleanly(self):
|
||||
"""Symmetric with Sky Select (which leaves the sea btn lit while the sky
|
||||
felt is up): opening the Sea Select felt must NOT grey the burger Sky
|
||||
sub-btn — it stays .active so a revisited Sea Select keeps the completed
|
||||
sky one click away (user-spec 2026-06-08). openSea therefore disables
|
||||
ONLY id_text_btn (not id_sky_btn). And because both felts are z-5 siblings
|
||||
that otherwise STACK (sea paints over sky; neither open path drops the
|
||||
other's open-class), clicking the lit sky btn must SWAP felts: openSea
|
||||
closes the sky felt + openSky closes the sea felt (both expose their close
|
||||
on window). Regression guard for the symmetry + clean-swap fix."""
|
||||
content = self.client.get(self.url).content.decode()
|
||||
# openSea disables only the Text btn now — the old 2-btn list is gone.
|
||||
self.assertIn("['id_text_btn']", content)
|
||||
self.assertNotIn("'id_text_btn', 'id_sky_btn'", content)
|
||||
# Clean felt-swap wiring both ways (sea exposes + sky calls it; sky
|
||||
# exposes + sea calls it).
|
||||
self.assertIn("window.closeSeaFelt", content)
|
||||
self.assertIn("window.closeSkyFelt", content)
|
||||
|
||||
def test_sea_btn_and_glow_bindings_defer_past_parse_time(self):
|
||||
"""room.html includes _sea_overlay.html (~line 77) BEFORE _burger.html
|
||||
(~line 167, which holds #id_burger_btn + #id_sea_btn). So the overlay's
|
||||
|
||||
@@ -191,13 +191,14 @@
|
||||
#id_sea_btn.glow-handoff {
|
||||
color: rgba(var(--priId), 1);
|
||||
border-color: rgba(var(--priId), 1);
|
||||
animation: glow-handoff-pulse 1.8s infinite;
|
||||
animation: glow-handoff-pulse 3.2s infinite;
|
||||
}
|
||||
|
||||
// Quick ease-IN to the bright peak over the first ~22% of the cycle, then a slow
|
||||
// ease-OUT fade back to the dim trough across the remaining ~78%. The per-segment
|
||||
// timing fns set the in/out asymmetry; the lopsided keystop split makes the swell
|
||||
// feel snappy and the decay linger.
|
||||
// Quick ease-IN to the bright peak over the first ~12.5% of the cycle (~0.4s),
|
||||
// then a slow ease-OUT fade back to the dim trough across the remaining ~87.5%
|
||||
// (~2.8s — roughly twice the earlier decay; user asked for a longer linger). The
|
||||
// per-segment timing fns set the in/out asymmetry; the lopsided keystop split
|
||||
// keeps the swell snappy while the fade lingers.
|
||||
@keyframes glow-handoff-pulse {
|
||||
0% {
|
||||
box-shadow:
|
||||
@@ -205,7 +206,7 @@
|
||||
0 0 0.7rem 0.1rem rgba(var(--ninUser), 0.12);
|
||||
animation-timing-function: ease-in;
|
||||
}
|
||||
22% {
|
||||
12% {
|
||||
box-shadow:
|
||||
0 0 0.6rem 0.15rem rgba(var(--ninUser), 0.95),
|
||||
0 0 1.4rem 0.4rem rgba(var(--ninUser), 0.55);
|
||||
|
||||
@@ -449,13 +449,18 @@ via epic:sea_save. `?seat` threads the CARTE-selected seat onto the action URLs.
|
||||
}
|
||||
hidden.addEventListener('change', sync);
|
||||
|
||||
// ── Open / close the felt (DRAW SEA ⇄ gear NVM nav). On open: disable the
|
||||
// burger Text + Sky sub-btns. The sea btn is NOT activated here — it's the
|
||||
// post-completion reopen affordance (see the cascade + the reopen binding).
|
||||
// ── 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', 'id_sky_btn'].forEach(function (id) {
|
||||
['id_text_btn'].forEach(function (id) {
|
||||
var b = document.getElementById(id);
|
||||
if (b && b.classList.contains('active')) { b.classList.remove('active'); _disabledBtns.push(b); }
|
||||
});
|
||||
@@ -465,6 +470,13 @@ via epic:sea_save. `?seat` threads the CARTE-selected seat onto the action URLs.
|
||||
_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();
|
||||
@@ -476,6 +488,7 @@ via epic:sea_save. `?seat` threads the CARTE-selected seat onto the action URLs.
|
||||
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);
|
||||
|
||||
|
||||
@@ -184,6 +184,13 @@
|
||||
}
|
||||
|
||||
function openSky() {
|
||||
// Clean SWAP, not a double-open: if the sea felt is up (its lit sky btn was
|
||||
// just clicked) close it first. Both felts are z-5 siblings that otherwise
|
||||
// stack; neither open path drops the other's open-class on its own. Mirrored
|
||||
// by openSea closing the sky felt (user-spec 2026-06-08).
|
||||
if (document.documentElement.classList.contains('sea-open') && window.closeSeaFelt) {
|
||||
window.closeSeaFelt();
|
||||
}
|
||||
document.documentElement.classList.add('sky-open');
|
||||
_disableTextBtn();
|
||||
// Re-sync the room gear to the sky NVM pane (room-views.js owns the gear
|
||||
@@ -624,6 +631,9 @@
|
||||
// Exposed so the burger fan's #id_sky_btn (active once the sky is saved) can
|
||||
// reopen the saved wheel. burger-btn.js calls window.openSkyFelt().
|
||||
window.openSkyFelt = openSky;
|
||||
// Exposed so openSea can close the sky felt for a clean felt-swap when a user
|
||||
// clicks the lit sky btn from inside the sea felt (user-spec 2026-06-08).
|
||||
window.closeSkyFelt = closeSky;
|
||||
|
||||
// ── Restore persisted form data + prime a saved (confirmed) wheel ───────────
|
||||
// Pre-save the wheel draw is deferred to openSky (form shows alone). Once the
|
||||
|
||||
Reference in New Issue
Block a user