room Sig Select: unify with the my_sign card-stage apparatus (DRY stat-block, per-card stage image, --duoUser felt)

The in-room SIG_SELECT stage diverged from the polished GAME SIGN page:
a fixed dark-Gaussian modal over the hex, a stale label-only stat-block,
and no card imagery. This brings it in line with my_sign / my_sea.

A — Stat-block DRY: _sig_select_overlay.html now renders the shared
core/_partials/_stat_face.html (rank-chip + title + arcana + keywords)
instead of a reduced label-only copy; sig-select.js's updateStage() now
calls StageCard.populateStatExtras (the missing call that left those
fields blank). data-arcana-key added per card for title color-keying.

B — Per-card stage image: the stage card gains a .sig-stage-card-img
slot + data-image-url per thumbnail, so an image-equipped seat deck
(RWS / Minchiate) shows real card art on the preview. Thumbnails stay
glyph-only (rank + suit) at every deck — only the stage shows the image.
Keyed off each card's OWN deck_variant, so it auto-upgrades to mixed art
when the dubbodeck assembly lands. No backend change (cards already
carry a deck_variant via _room_deck_variant).

C — Felt-in-aperture: the stage renders INSIDE .room-hex-pane on edge-to-
edge green --duoUser felt (my_sea-style), replacing the hex content; the
old .sig-backdrop blur is gone. .sig-overlay absolute-fills the pane
(.room-hex-pane.has-sig-stage = positioning context); dismissing it
reveals the hex + waiting message behind. Scroll-down still reaches the
reelhouse carousel (untouched scroll pane).

Polishes:
- Image-mode bg escape: the levity 0,3,0 polarity rule
  (.sig-overlay/.my-sign-page[data-polarity="levity"] .sig-stage-card)
  hard-set a --secUser background that re-clothed image cards behind the
  transparent PNG. Added the &.sig-stage-card--image { background:
  transparent; border:0; overflow:visible } escape (parity w. the base +
  my-sea rules). Latent my_sign bug too. Monodeck-era assumption.
- FLIP .btn-reveal: non-polarized image decks get a FLIP that turns the
  preview to the deck card-back (my_sign parity) — back-img + reused
  .my-sign-flip-btn (shared positioning/hide/counter-position rules
  already cover .sig-stage-card) + a frozen-gated reveal scoped to
  .sig-overlay + sig-select.js _flipToBack (500ms Y-rotate, midpoint
  swap). SPIN now sets data-spinning so the btn hides mid-rotate.
- Reserved thumbs-up / hover cursors portal to a body-root fixed
  container, so they hung over the reelhouse on scroll. sig-select.js now
  toggles .cursors-hidden off the aperture scrollTop: instant hide the
  moment the scroll leaves the hex, 0.5s opacity ease-in on the full
  return. Tray intentionally kept.

TDD: SigSelectUnifiedStageTest (6 ITs) — DRY stat-face present, per-card
data-image-url + data-arcana-key, .sig-stage-card-img slot, image deck
non-empty face URL / text deck empty, has-sig-stage felt + overlay inside
the hex pane. 319 epic test_views ITs green; user-verified live on an RWS
room (no rect, FLIP works, thumb timing). Jasmine for the JS wiring +
the dubbodeck cross-deck assembly (per-seat segment cards, CARTE-solo
both-polarity case, per-card backs) are the tracked follow-on.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-06-03 02:37:13 -04:00
parent 148fcac7af
commit 71c00699a1
5 changed files with 231 additions and 38 deletions

View File

@@ -609,33 +609,33 @@
&--next { right: 1rem; }
}
// ─── Sig Select overlay (SIG_SELECT phase) ────────────────────────────────────
// ─── Sig Select stage (SIG_SELECT phase) ──────────────────────────────────────
//
// Two overlays (levity / gravity) run in parallel, one per polarity group.
// Layout mirrors the gatekeeper: dark Gaussian backdrop + centred modal.
// Inside the modal: upper stage (card preview) + lower mini card grid (no scroll).
// Two stages (levity / gravity) run in parallel, one per polarity group.
// Unified w. my_sign / my_sea 2026-06-03: renders INSIDE .room-hex-pane on
// edge-to-edge green --duoUser felt (no dark Gaussian backdrop), replacing the
// hex content my_sea-style. Inside the modal: upper stage (card preview) +
// lower mini card grid (no scroll).
html:has(.sig-backdrop) {
overflow: hidden;
}
.sig-backdrop {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.75);
backdrop-filter: blur(5px);
z-index: 100;
pointer-events: none;
// The hex pane becomes a positioning context only while the felt stage shows,
// so the absolute-filling overlay scopes to the pane (not the viewport) and
// the position-strip's root stacking stays untouched in every other phase.
.room-hex-pane.has-sig-stage {
position: relative;
}
.sig-overlay {
position: fixed;
position: absolute;
inset: 0;
display: flex;
align-items: stretch;
justify-content: center;
z-index: 120;
pointer-events: none;
z-index: 5;
// Edge-to-edge non-Gaussian green felt — an opaque surface that covers the
// hex/seats behind it; sig-select.js's _dismissSigOverlay removes the whole
// overlay (this gamer's sigs done) to reveal the hex + waiting message.
background: rgba(var(--duoUser), 1);
pointer-events: auto;
}
.sig-modal {
@@ -1077,6 +1077,15 @@ body.deck-family-english {
@extend %flip-btn-revealed;
}
// Room sig-select stage: same frozen-gated hover-reveal as my_sign, scoped to
// .sig-overlay (the FLIP btn renders only for non-polarized image seat decks).
// The FLIP appears once a card is OK-locked (.sig-stage--frozen), matching the
// my_sign-main rule above.
.sig-overlay .sig-stage--frozen .sig-stage-card:hover .my-sign-flip-btn,
.sig-overlay .sig-stage--frozen .sig-stage-card:has(.my-sign-flip-btn:hover) .my-sign-flip-btn {
@extend %flip-btn-revealed;
}
// 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
@@ -1232,8 +1241,26 @@ body.deck-family-english {
pointer-events: none;
z-index: 200; // above sig-overlay (120), below tray (310)
overflow: visible;
opacity: 1;
transition: opacity 0.25s ease; // eases the cursors back in on scroll-return
}
// sig-select.js toggles this off the aperture scrollTop. `transition: none`
// makes the hide at scroll-start INSTANT (user-spec); removing the class on the
// return falls back to the base 0.5s opacity ease above — fade in, snap out.
#id_sig_cursor_portal.cursors-hidden {
opacity: 0;
transition: none;
}
// The reserved-sig thumbs-up + hover hand-pointers portal to this body-root
// fixed container (escaping the deck-grid clip), so when the table-hex aperture
// scroll-snaps DOWN to the reelhouse they'd otherwise hang over that view at
// their stale coords. sig-select.js toggles their visibility off an
// IntersectionObserver on the scroll pane (threshold 0) — hidden the instant
// the reelhouse begins to enter, restored only once it has fully left. (The
// tray is intentionally NOT hidden — user wants to keep it.)
.sig-cursor-float {
position: absolute;
font-size: 1.5rem;
@@ -1324,6 +1351,16 @@ body.deck-family-english {
.fan-card-name-group{ color: rgba(var(--priUser), 1); }
.fan-card-name { color: rgba(var(--quiUser), 1); }
.fan-card-arcana { color: rgba(var(--priUser), 1); }
// Image-mode parity w. the base (`.sig-stage-card--image` ~L795) + the
// my-sea sea-sig-card override below: this 0,3,0 levity bg/border must
// NOT re-clothe an image card — its transparent shell + contour-stroke
// PNG has to show through (else a solid --secUser rect sits behind the
// card). Was the missing escape that left the rect on RWS/Minchiate.
&.sig-stage-card--image {
background: transparent;
border: 0;
overflow: visible;
}
}
// Polarity title + qualifier text: --quiUser for levity (paired w. gravity's --terUser).
// All five selectors prefixed w. .sig-stage-card to match (or beat) the 0,4,0 specificity