Files
python-tdd/src/static_src/scss/_wallet-tokens.scss
Disco DeDisco f6093136f1 fix: shop tooltip price flex-pinned right (cross-file #id_tooltip_portal .tt-title { display: block } was clobbering the flex h4) + My Sign page collapses to read-only card+stat-block when sig is saved + My Sign applet card gets proper 5:8 shell + Game Kit row space-evenly. Five visual polish items batched.
(1) **Shop tooltip price right-align — root-cause fix.** Earlier today's `feat: shop tooltip price moves to the title row` (commit e90f10f) left `.tt-price` visually adjacent to the name instead of pinned right despite `<h4 class="tt-title">` carrying flex+space-between in `_tooltips.scss:38-46`'s `.token-tooltip, .tt { h4 { ... } }` block. **The bug was in a totally unrelated file**: `_palette-picker.scss:88-95` opens `#id_tooltip_portal { .tt-title, .tt-description, .tt-date, .tt-lock { display: block; } }` for the palette swatch tooltip — `#id_tooltip_portal .tt-title` has specificity **1,1,0** which beats `.token-tooltip h4`'s **0,1,1**, ID wins regardless of source order. The palette tooltip's h4 only carries a text node (no flex children) so `block` vs `flex` looked identical for that surface + the rule sat there as quiet defensive scaffolding for months. The wallet Shop's two-`<span>` h4 finally exercised it. Fix: drop `.tt-title` from the palette override list (left `.tt-description`/`.tt-date`/`.tt-lock` alone — those are `<p>` siblings, already block, redundant but harmless). Also keeps `margin-left: auto !important` on `.tt-price` (today's earlier failed-first-attempt fix) — now redundant w. the flex parent's space-between but documents intent + survives any future flex-direction tweak. Generalizable trap: an ID-scoped child rule in any consumer's SCSS file can silently override shared base rules for every consumer of that portal.

(2) **Game Kit row space-evenly.** `#id_game_kit` in `_gameboard.scss:61-72` was `justify-content: center` + `gap: 0.75rem` so 7 trinket icons clumped left-of-center. Switched to `justify-content: space-evenly` (no gap) — matches the established convention in `.token-row` (`_wallet-tokens.scss:46`) + `.shop-grid` (`_wallet-tokens.scss:92`) which both space-evenly the wallet's parallel rows. Items now spread across the applet width same as the wallet's tokens row + shop row.

(3) **My Sign page collapses to read-only when sig is committed.** Per user spec — once a sig is saved, the SCAN SIGN btn + table hex + chair are meaningless (you can't draw a new sig until you DEL the current one) so the landing renders only the saved-sig preview on the stage + the DEL btn pinned bottom-right. `my_sign.html:91-110` wraps the `.room-shell > .room-table > ... > #id_scan_sign_btn + .table-seat` chain in `{% if not current_significator %}`. `.my-sign-clear-form` stays unconditional (its own `{% if current_significator %}` block) — its `position: absolute; bottom: 0.75rem; right: 1rem` against the now-empty `.my-sign-landing` (which keeps `position: relative` from `_card-deck.scss:671`) lands the DEL in the same bottom-right corner whether the hex is present or not.

(4) **Stat block reveals next to saved-sig preview on landing.** `_populateStage(savedCardEl)` on init was filling the stage card data but `.sig-stat-block` stayed `display: none` because only `.sig-stage--frozen` (added by JS on OK-confirm in picker phase) reveals it via `_card-deck.scss:609`'s `&.sig-stage--frozen .sig-stat-block { display: block; }`. Added `stage.classList.add('sig-stage--frozen');` after the saved-sig `_populateStage` call at `my_sign.html:386`. Stat block now sits flex-row-adjacent to the stage card (stage's `flex-direction: row` + `gap: 0.75rem` from `_card-deck.scss:505-508` does the layout work) — emanation keywords + SPIN + FYI all visible alongside the saved card.

(5) **My Sign applet card — proper 5:8 card shell.** The applet's `<div class="my-sign-applet-card">` markup (corner-rank top-left + name) was rendering bg-less + collapsed to the applet's top-left corner because **no SCSS rule existed** for `.my-sign-applet-card` / `.my-sign-applet-body` / `.my-sign-applet-empty`. Added `#id_applet_my_sign` block at `_billboard.scss:434+` — scaled-down clone of `.sig-stage-card`'s shape language: `--applet-card-w: 5rem` knob drives all child sizing via the same calc-fractions used by `.sig-stage-card`'s `--sig-card-w`, 5:8 aspect-ratio, `--priUser` bg, `--secUser` border, corner-rank absolute top-left, `.fan-card-name` flex-centered, `&.stage-card--reversed { transform: rotate(180deg); }` for the reversed-sig case. `.my-sign-applet-body` flex-centers the card in the 4×6 applet aperture; `.my-sign-applet-empty` flex-centers the 'No sign chosen yet.' empty state. Layered visually consistent w. the room sig-select card + Shop tiles.

(6) **Misc visual cleanup bundled in.** `#id_scan_sign_btn` in `_card-deck.scss:677` lost its `font-size: 0.75rem` + `line-height: 1.1` overrides — the default `.btn-primary` sizing scales fine w. the 4rem circle now that the SCAN/SIGN wordmark fits cleanly w. just `white-space: normal`. `.tt-buy-btn` lost `line-height: 1.1` in `_wallet-tokens.scss:156` — Shop microbutton renders cleanly w. the default.

**TDD coverage**: `test_landing_previews_saved_sig_on_stage` in `test_bill_my_sign.py` rewritten to match the new contract (stage frozen → stat block visible, no SCAN SIGN btn, no `.table-hex` when sig is saved); other 28 my-sign FTs unaffected (they exercise the no-sig path which still renders the hex + SCAN SIGN). 3 traps caught + linked in memory: [[feedback-cross-file-id-scoped-override]] (this commit's #1), the pre-existing [[feedback-margin-auto-needs-flex-parent]] (correctly predicted today's bug — `!important` ladder was a tell to audit the parent's cascade), [[feedback-scss-import-order-specificity]] (related but different: same-specificity source order; this one was specificity-driven w. source order irrelevant).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 12:42:03 -04:00

176 lines
4.5 KiB
SCSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

.token {
position: relative;
display: inline-block;
cursor: help;
color: rgba(var(--terUser), 1);
.token-tooltip {
position: absolute;
bottom: 125%;
left: 50%;
transform: translateX(-50%);
}
&:hover .token-tooltip {
display: block; // legacy fallback; .tt is JS-portal-only (no CSS hover)
}
}
.token--empty {
cursor: help;
> i { opacity: 0.4; }
}
// Aperture foundation lives universally in _base.scss; nothing
// wallet-specific to override.
.wallet-page {
position: relative;
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
.wallet-tokens {
display: flex;
flex-direction: column;
overflow: visible;
.token-row {
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-evenly;
overflow: visible;
}
.token {
font-size: 1.5rem;
}
.token:hover .token-tooltip { display: none; }
}
#id_payment_methods {
overflow-y: auto;
}
@media (max-width: 768px) {
.token .token-tooltip {
width: 13rem;
max-width: 90vw;
left: 0;
transform: none;
}
.wallet-tokens .token-tooltip {
left: 50%;
transform: translateX(-50%);
}
}
// ── Wallet Shop applet ───────────────────────────────────────────────────────
// Mimics `.wallet-tokens` (horizontal row of tooltipped icons) but each tile
// carries an admin-defined catalog item + an optional `.shop-badge` (eg "×5"
// for the bundle) + a BUY-ITEM microbutton hosted in the tooltip portal.
// JS wiring lives in `apps/dashboard/static/apps/dashboard/wallet-shop.js`.
.wallet-shop {
display: flex;
flex-direction: column;
overflow: visible;
.shop-grid {
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-evenly;
gap: 1rem;
overflow: visible;
}
}
.shop-tile {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
color: rgba(var(--terUser), 1);
cursor: help;
}
// ×N quantity badge — top-right corner, --quaUser glyph on --quiUser bg.
// User-tweaked 2026-05-22: shrunk from 2rem → 1.5rem + nudged further up
// + right so most of the underlying tile icon stays visible.
.shop-badge {
position: absolute;
top: -0.8rem;
right: -1.2rem;
width: 1.5rem;
height: 1.5rem;
border-radius: 50%;
background: rgba(var(--secUser), 1);
color: rgba(var(--priUser), 1);
display: flex;
align-items: center;
justify-content: center;
font-size: 0.75rem;
font-weight: 900;
pointer-events: none;
}
// `.tt-micro` — sibling of `.tt` on each `.shop-tile`. Holds the BUY-ITEM
// btn (or × + 'Already owned' when capped). wallet.js's tooltip handler
// clones this into `#id_mini_tooltip_portal` on hover so the btn appears
// as a small floating bubble adjacent to the main tooltip card —
// mirroring Game Kit's Equipped/Unequipped/In-Use microtooltip pattern.
// Hidden in the source DOM; only the portal clone is visible.
.tt-micro {
display: none;
}
// Wallet-side mini portal — pinned to the bottom-right of the main
// portal by wallet.js (mirrors gameboard.js's gameKit positioning).
// Mostly mirrors gameboard's mini at `_gameboard.scss:140` but allows
// the BUY-ITEM btn label to wrap onto multiple lines (gameboard's
// mini holds short status text like "In-Use: X" which wants nowrap;
// our buy btn is round + needs the label to break onto 2 lines).
#id_mini_tooltip_portal {
position: fixed;
z-index: 9999;
width: fit-content;
text-align: center;
padding: 0.5rem 0.75rem;
display: none;
flex-direction: column;
align-items: center;
gap: 0.25rem;
.tt-buy-btn {
padding: 0.25rem 0.75rem;
white-space: normal;
word-break: normal;
}
// `.tt-already-owned` text — match Game Kit's "Equipped" / "In-Use: X"
// microtext styling (--secUser at full alpha, slightly bigger than
// 0.75rem) so the wallet shop's "Already owned" pill reads as the
// same widget as the gameboard's status pills.
.tt-already-owned {
font-size: 0.85rem;
margin: 0;
font-style: italic;
color: rgba(var(--secUser), 1);
white-space: nowrap;
}
&.active { display: flex; }
}