My Sign picker iteration 3 — SCAN SIGN landing hex + OK/NVM thumbnail two-step + duoUser picker bg — Sprint 4a-cont — TDD
Two-phase picker. Landing phase renders the DRY 1-chair table hex w. a central SCAN SIGN .btn-primary; clicking it swaps the page to picker phase (hex hides, sig-card grid + always-present stage frame + SAVE SIGN visible). Stage frame previews the saved sig on landing if User.significator is set ; sig-card selection lifts the room's two-step OK/NVM-on-thumbnail pattern via `.sig-card-actions` w. `.sig-ok-btn`/`.sig-nvm-btn`: click thumb → `.sig-focused` (CSS reveals OK badge, stage previews card, no lock); click OK → `.sig-reserved--own` (CSS swaps OK→NVM badge, `.sig-stage--frozen` reveals stat block + FLIP, SAVE SIGN enables); click NVM → unlock + clear focus + disable SAVE SIGN ; SAVE SIGN form pinned `position:absolute; bottom:0.75rem; right:1rem` to .my-sign-stage so it stops shifting across the stage row when the stat block reveals on lock (was getting shoved left as a flex item alongside the stat-block reveal) ; .my-sign-page mirrors .room-page's `flex:1; min-height:0; display:flex; flex-direction:column` so the DRY hex container chain propagates real height down into #id_game_table for room.js's scaleTable() to compute against (was reading 0 + leaving the hex unscaled at 200×231 in a 360×320 scene) ; stage min-height gated to picker phase (`.my-sign-page[data-phase="picker"] .my-sign-stage`) — landing-phase stage is natural-sized so the hex centers in the bigger available area instead of being bottom-anchored by a 376px stage reservation ; picker-phase bg uses `rgba(var(--duoUser), 1)` so the transition from "hex face" → "card pile on felt" reads as a continuous surface rather than a context swap ; room sig-select media queries re-scoped to `.sig-overlay .sig-deck-grid` so they don't bleed into my-sign — my-sign gets its own breakpoint cascade: 6×3rem (portrait) → 9×3rem (≥900px landscape) → 18×3rem (≥1600px) → 18×5rem (≥2200px); thresholds bumped from sig-select's 1400/1800px so 18×col + sidebar/footer margins clear the viewport at fluid-rem ceiling (rem=22 → 18×3rem=1188px + 220px margins=1408, safe with 1600px floor) ; default `repeat(6, 1fr)` collapsed to 0-width when paired w. `align-self:center` (no parent width for `fr` to resolve against, hence the dotted-line miniscule cards in portrait); fixed `repeat(6, 3rem)` at portrait default fixes it ; SCAN SIGN font-size 0.75rem (vs .btn-primary's default 0.875rem) so the 2-line "SCAN/SIGN" label fits inside the 4rem circle without crowding the border — treated as a smaller variant via `#id_scan_sign_btn` rule scoped under .my-sign-landing ; room.js's scaleTable() runs on DOMContentLoaded before flex layout flushes (#id_game_table.clientWidth/Height read 0 at that moment) — added `requestAnimationFrame → dispatchEvent('resize')` tick at the end of the inline IIFE so scaleTable re-fires once layout settles ; tests — 6 FTs in test_bill_my_sign.py rewritten for the new flow: test_landing_renders_dry_hex_with_scan_sign_button pins the 1-chair hex + central SCAN SIGN + hidden picker grid; test_scan_sign_click_transitions_to_picker_phase pins the phase swap (hex hides, grid shows); test_click_thumbnail_shows_OK_btn_without_locking pins step 1 (focus + OK appears, no lock yet); test_OK_click_locks_thumbnail_and_enables_save_sign pins step 2 (lock + NVM appears + SAVE SIGN enables + persists to /billboard/ applet); test_NVM_click_deselects_and_disables_save_sign pins NVM unlock cycle; test_landing_previews_saved_sig_on_stage pins the on-load saved-sig preview behavior — all green visually verified across portrait + landscape
Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -616,13 +616,81 @@ html:has(.sig-backdrop) {
|
||||
}
|
||||
|
||||
// ─── My Sign picker — sizing + state-gated reveal ────────────────────────────
|
||||
// Bigger preview card than the room (no shared overlay width budget) — clamp
|
||||
// scales w. viewport for portrait/landscape both. FLIP btn + stat block hidden
|
||||
// at rest; revealed by `.sig-stage--frozen` (added by JS on click, cleared by
|
||||
// NVM). SPIN (orientation 180°) stays in `.sig-stat-block`; FLIP toggles
|
||||
// polarity (data-polarity attr on .my-sign-page).
|
||||
// Two-phase layout: landing (DRY 1-chair hex w. SCAN SIGN center) → picker
|
||||
// (sig-card grid below an always-present stage frame). SAVE SIGN rides
|
||||
// inside .my-sign-stage to its right, sig-select-style. FLIP btn + stat
|
||||
// block hidden at rest; revealed by `.sig-stage--frozen` (added by JS on
|
||||
// OK confirm, cleared by NVM). SPIN (orientation 180°) stays in
|
||||
// `.sig-stat-block`; FLIP toggles polarity (data-polarity on .my-sign-page).
|
||||
// .my-sign-page mirrors .room-page's flex-column-fill-aperture pattern so
|
||||
// the DRY hex inside .my-sign-landing gets a non-zero #id_game_table size
|
||||
// for room.js's scaleTable() to compute against. Without flex:1 + min-height:0
|
||||
// the container chain collapses + the hex renders unscaled (200×231 inside
|
||||
// a 360×320 scene, looking elongated/portrait).
|
||||
.my-sign-page {
|
||||
--sig-card-w: clamp(140px, 36vw, 220px);
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
// Stage frame — fixed slice in picker phase, natural-sized on landing.
|
||||
// The picker min-height reserves real estate so hover-preview cards don't
|
||||
// shift adjacent layout; on landing the stage shrinks to its actual content
|
||||
// (empty or saved-sig preview) so the DRY hex below gets fair vertical
|
||||
// space. SAVE SIGN form is absolutely positioned (see below) so it stays
|
||||
// pinned when the stat block reveals on OK confirm.
|
||||
.my-sign-stage {
|
||||
flex: 0 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.my-sign-page[data-phase="picker"] .my-sign-stage {
|
||||
min-height: calc(var(--sig-card-w, 140px) * 8 / 5 + 1.5rem);
|
||||
}
|
||||
|
||||
// SAVE SIGN form — pinned to the bottom-right of the stage so it stays in
|
||||
// place across hover/lock states (the stat block reveal would otherwise
|
||||
// shove a flex-positioned btn around the stage row).
|
||||
#id_save_sign_form {
|
||||
position: absolute;
|
||||
bottom: 0.75rem;
|
||||
right: 1rem;
|
||||
margin: 0;
|
||||
z-index: 6;
|
||||
}
|
||||
|
||||
// Landing phase — DRY hex container. flex:1 + min-height:0 propagates the
|
||||
// available vertical space into .room-shell → #id_game_table → scaleTable().
|
||||
.my-sign-landing {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
|
||||
// SCAN SIGN btn — centered in the hex. Default .btn-primary text
|
||||
// (0.875rem) scales tighter than the room's PICK SIGS btn font; this
|
||||
// bumps it down a notch so the 2-line "SCAN/SIGN" label sits cleanly
|
||||
// inside the 4rem circle without crowding the border.
|
||||
#id_scan_sign_btn {
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.1;
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide SAVE SIGN on landing — the form only makes sense once the user
|
||||
// has entered the picker. Saved-sig preview on landing is read-only.
|
||||
.my-sign-page[data-phase="landing"] #id_save_sign_form {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Picker phase — bg matches the table hex's interior (--duoUser) so the
|
||||
// transition from "hex face" → "card pile on felt" reads as a continuous
|
||||
// surface rather than a context swap. Landing phase keeps the body bg.
|
||||
.my-sign-page[data-phase="picker"] {
|
||||
background: rgba(var(--duoUser), 1);
|
||||
}
|
||||
|
||||
.my-sign-flip-btn {
|
||||
@@ -637,7 +705,7 @@ html:has(.sig-backdrop) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// FLIP btn appears only when the stage is frozen (post-click). Hover-only
|
||||
// FLIP btn appears only when the stage is frozen (post-OK confirm). Hover-only
|
||||
// previews don't reveal the polarity toggle — the user hasn't committed yet.
|
||||
.my-sign-stage.sig-stage--frozen .my-sign-flip-btn {
|
||||
display: inline-flex;
|
||||
@@ -938,10 +1006,13 @@ html:has(.sig-backdrop) {
|
||||
margin-left: 4rem;
|
||||
margin-right: 3rem;
|
||||
}
|
||||
.sig-stage {
|
||||
.sig-overlay .sig-stage {
|
||||
min-width: 0; // allow shrinking in row layout; align-items:flex-end already set
|
||||
}
|
||||
.sig-deck-grid {
|
||||
// Scoped to .sig-overlay — the room sig-select modal has its own width
|
||||
// budget. .my-sign-page gets its own breakpoints below (different col
|
||||
// counts + thresholds tuned for the full content area).
|
||||
.sig-overlay .sig-deck-grid {
|
||||
grid-template-columns: repeat(6, 2.5rem);
|
||||
margin: 0;
|
||||
align-self: flex-end; // sit at the bottom of the modal row
|
||||
@@ -954,12 +1025,12 @@ html:has(.sig-backdrop) {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
.sig-stage {
|
||||
.sig-overlay .sig-stage {
|
||||
min-width: auto;
|
||||
align-self: stretch; // fill full modal width so JS sizeSigCard() gets correct stageWidth
|
||||
margin-left: 3rem;
|
||||
}
|
||||
.sig-deck-grid {
|
||||
.sig-overlay .sig-deck-grid {
|
||||
grid-template-columns: repeat(9, 3rem);
|
||||
align-self: center;
|
||||
}
|
||||
@@ -968,7 +1039,7 @@ html:has(.sig-backdrop) {
|
||||
@media (orientation: landscape) and (min-width: 1400px) {
|
||||
// Wide landscape: 18-card single-row grid. 18×3rem + ~7rem modal margins
|
||||
// clears the viewport here even at the fluid-rem ceiling (rem=22 → ~1376px).
|
||||
.sig-deck-grid {
|
||||
.sig-overlay .sig-deck-grid {
|
||||
grid-template-columns: repeat(18, 3rem);
|
||||
}
|
||||
}
|
||||
@@ -976,11 +1047,11 @@ html:has(.sig-backdrop) {
|
||||
@media (orientation: landscape) and (min-width: 1800px) {
|
||||
// Sig overlay: clear doubled sidebars (8rem each instead of 4rem/6rem)
|
||||
.sig-overlay { padding-left: 8rem; padding-right: 8rem; }
|
||||
.sig-stage {
|
||||
.sig-overlay .sig-stage {
|
||||
align-self: stretch; // fill full modal width so JS sizeSigCard() gets correct stageWidth
|
||||
margin-left: 3rem;
|
||||
}
|
||||
.sig-deck-grid {
|
||||
.sig-overlay .sig-deck-grid {
|
||||
grid-template-columns: repeat(18, 5rem);
|
||||
align-self: center;
|
||||
}
|
||||
@@ -990,6 +1061,46 @@ html:has(.sig-backdrop) {
|
||||
#id_room_menu { right: 2.5rem; }
|
||||
}
|
||||
|
||||
// ─── My Sign picker grid ────────────────────────────────────────────────────
|
||||
// align-self:center horizontally centers the shrink-to-content grid in
|
||||
// .my-sign-page's flex column; overflow:visible avoids the modal's hidden
|
||||
// clip. Col counts ramp up at wider viewports — sig-select's breakpoints
|
||||
// are tuned for the modal's width budget so we use our own thresholds that
|
||||
// account for the navbar/footer sidebars (~5rem each) eating viewport width.
|
||||
// Portrait: fixed rem cols (default repeat(6, 1fr) collapses to 0 width
|
||||
// w. align-self:center because 1fr has no defined parent to fr against).
|
||||
.my-sign-deck-grid {
|
||||
align-self: center;
|
||||
margin: 1rem auto;
|
||||
overflow: visible;
|
||||
grid-template-columns: repeat(6, 3rem);
|
||||
}
|
||||
|
||||
@media (orientation: landscape) and (min-width: 900px) {
|
||||
// Middling landscape: 9-card row × 2 (mirrors sig-select's middling step).
|
||||
.my-sign-deck-grid {
|
||||
grid-template-columns: repeat(9, 3rem);
|
||||
}
|
||||
}
|
||||
|
||||
@media (orientation: landscape) and (min-width: 1600px) {
|
||||
// Wide landscape: 18-card single row. Bumped from sig-select's 1400px so
|
||||
// 18×3rem + the doubled-sidebar margins (~10rem) still clears the viewport
|
||||
// at the fluid-rem ceiling (rem=22 → 18×3rem=1188px + 220px margins = 1408,
|
||||
// safe with 1600px floor).
|
||||
.my-sign-deck-grid {
|
||||
grid-template-columns: repeat(18, 3rem);
|
||||
}
|
||||
}
|
||||
|
||||
@media (orientation: landscape) and (min-width: 2200px) {
|
||||
// XL landscape: 18×5rem. Bumped from sig-select's 1800px — 18×5rem=1980px
|
||||
// at rem=22 needs ~2200px viewport after sidebar/footer clearance.
|
||||
.my-sign-deck-grid {
|
||||
grid-template-columns: repeat(18, 5rem);
|
||||
}
|
||||
}
|
||||
|
||||
// ── DRAW SEA overlay ─────────────────────────────────────────────────────────
|
||||
// Mirrors .sky-* structure but with columns reversed:
|
||||
// left = transparent (Celtic Cross card positions)
|
||||
|
||||
Reference in New Issue
Block a user