fan-card title symmetry; pips → Minor; tray Sig card

- title slot: <h3> → <p>; font-size 0.1 → 0.087 (deck) / 0.093 → 0.08 (sig/sea); text-wrap: balance — kills upright/reversal asymmetry & all per-card squeeze hacks
- trump 8 hyphen → U+2011, trump 9 space → U+00A0 (mig 0021) so titles wrap as intended
- pips (Earthman 1–10) → MINOR arcana (mig 0022); StageCard._arcanaDisplay() picks the right label
- PICK SEA: re-clicking a deposited slot now restores the server-rolled reversed state (sea.js _populate toggle)
- tray Sig card: render same .sig-stage-card.sea-sig-card (rank + icon, -5deg) as Sea center; --sig-card-w sized off --tray-cell-size
- title_squeeze_class kept as no-op for template compat
- 0020 (Self-Unimportance rename) included from prior turn

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-05-01 02:06:55 -04:00
parent c264b6e3ee
commit 3410f073f0
13 changed files with 233 additions and 48 deletions

View File

@@ -33,14 +33,14 @@ function initGameKitTooltips() {
if (portal.classList.contains('active') && activeToken) {
const tokenRect = activeToken.getBoundingClientRect();
const portalRect = portal.getBoundingClientRect();
// Expand left to cover button overflow outside portal edge
const expandedPortalRect = {
left: portalRect.left - 24,
top: portalRect.top,
right: portalRect.right,
bottom: portalRect.bottom,
};
const rects = [tokenRect, expandedPortalRect];
const rects = [tokenRect, portalRect];
// Include the DON/DOFF button group's actual bounding rect so the
// portions of those buttons that hang past the portal's left edge
// (and above its top edge) stay inside the hover-tolerance region.
// Was previously a hardcoded 24px left expansion which didn't
// cover top overhang and underestimated wider button labels.
const equipBtns = portal.querySelector('.tt-equip-btns');
if (equipBtns) rects.push(equipBtns.getBoundingClientRect());
if (miniPortal.classList.contains('active')) rects.push(miniPortal.getBoundingClientRect());
const left = Math.min(...rects.map(r => r.left));
const top = Math.min(...rects.map(r => r.top));
@@ -244,7 +244,19 @@ function initGameKitTooltips() {
const tokenRect = token.getBoundingClientRect();
const halfW = portal.offsetWidth / 2;
const rawLeft = tokenRect.left + tokenRect.width / 2;
const clampedLeft = Math.max(halfW + 8, Math.min(rawLeft, window.innerWidth - halfW - 8));
// Extra left clearance — the DON/DOFF button group is absolute-
// positioned with `left: -1rem` inside the portal and spills further
// left by its own width. Measure the actual overhang so the clamp
// keeps the buttons inside the viewport rather than just the portal.
let leftOverhang = 0;
const equipBtns = portal.querySelector('.tt-equip-btns');
if (equipBtns) {
const portalRect = portal.getBoundingClientRect();
const btnsRect = equipBtns.getBoundingClientRect();
leftOverhang = Math.max(0, portalRect.left - btnsRect.left);
}
const minLeft = halfW + 8 + leftOverhang;
const clampedLeft = Math.max(minLeft, Math.min(rawLeft, window.innerWidth - halfW - 8));
portal.style.left = Math.round(clampedLeft) + 'px';
// Show above when token is in lower viewport half; below when in upper half