diff --git a/HANDOFF.md b/HANDOFF.md
index a903f0a..c8ea542 100644
--- a/HANDOFF.md
+++ b/HANDOFF.md
@@ -442,6 +442,15 @@ the countdown panel ('CHANGEOVER · RESUMING IN n'). He kept the burst-arm weapo
praise words. **A bottom/above-rack message slot was proposed and REJECTED**: that is thumb
territory — covered by the hand mid-pull and outside where the eyes are.
+**Fourth batch, same day — the card went HORIZONTAL, and nothing draws under a modal.** The
+stacked icon card ran 102 px tall and its lower third hung over live court; the icon sits LEFT of
+the text now (boxed to 58×52 so a wide tin cannot reach the type — and it draws BIGGER than the
+stacked layout gave it), so every card is a flat `CARD_H` 62 px at fixed `CARD_TOP` 96, fully over
+the crowd. `bandTop()` is gone with it. And a modal owns the whole screen now: the flash and the
+card are neither DRAWN under its dim nor TICKED behind the freeze (the card tick moved below the
+modal early-return, next to the flash's) — a card raised in the same beat as a popup used to burn
+its whole life dimmed-out underneath it, and now it holds and plays after the dismissal.
+
**Second batch, same day — THE MESSAGE BAND.** Oliver: transient messages need "a definite space
… over the crowd". `AD_TOP()`/`bandTop(h)` in render.js pin the whole family there — below the
scoreboard block, above the ad strip, never on the court:
diff --git a/gameplay.js b/gameplay.js
index 779ec5a..21f7085 100644
--- a/gameplay.js
+++ b/gameplay.js
@@ -1326,12 +1326,6 @@ export function update(dt) {
updateZombies(dt);
return;
}
- // A card can wait before it shows. The chapter card used to land on the same frame as the boss
- // died, so the biggest gore burst in the game happened underneath it and nobody ever saw it.
- if (G.card) {
- if (G.card.wait > 0) G.card.wait -= dt;
- else { G.card.t -= dt; if (G.card.t <= 0) G.card = null; }
- }
if (G.shake && (G.shake.t -= dt) <= 0) G.shake = null;
if (G.netRipple && (G.netRipple.t -= dt) <= 0) G.netRipple = null; // the tape settles
if (G.zoom && (G.zoom.t += dt) >= G.zoom.T) G.zoom = null; // scripted punch-in (render applies it)
@@ -1351,6 +1345,14 @@ export function update(dt) {
// late in a run — the weapon modal is first-sight-only, so once you have seen a tin the label
// flash IS the announcement, and the trainer's popup was eating it every time you were wounded.
if (G.flash) { G.flash.t -= dt; if (G.flash.t <= 0) G.flash = null; }
+ // A card can wait before it shows. The chapter card used to land on the same frame as the boss
+ // died, so the biggest gore burst in the game happened underneath it and nobody ever saw it.
+ // BELOW the modal return, like the flash: a card raised in the same beat as a popup used to
+ // burn its whole life dimmed-out underneath it — now it holds and plays AFTER the dismissal.
+ if (G.card) {
+ if (G.card.wait > 0) G.card.wait -= dt;
+ else { G.card.t -= dt; if (G.card.t <= 0) G.card = null; }
+ }
for (let i = pops.length - 1; i >= 0; i--) if ((pops[i].t -= dt) <= 0) pops.splice(i, 1); // reaction pops decay
crowd.cheer = Math.max(0, crowd.cheer - dt);
G.idleT += dt;
diff --git a/index.html b/index.html
index 7df0e1b..388343c 100644
--- a/index.html
+++ b/index.html
@@ -359,6 +359,6 @@
-
+