Lane C R33 (v7.0-beta wave 2): ☆ WANT IT on the pull card

The wantlist grows from the card, not a search box the 90s didn't have: you pulled it, it's
dear, you'll hunt one cheaper. ☆ WANT IT → ★ ON THE WANTLIST (a stamp once wanted, not a
button). Construction-gated on opts.onWant/isWanted — ?game=0 / classic cards carry ZERO
wantlist DOM, the classic-pure pattern.
This commit is contained in:
type-two 2026-07-20 19:01:40 +10:00
parent 9aae167d64
commit ce71908bb5

View File

@ -116,6 +116,7 @@ export function createDig(THREE, renderer) {
let recs = [], cursor = 0, vel = 0, active = false, pulled = null, lastFloor = -1;
let crate = null, offers = [], onCloseCb = null, onBuyCb = null, getCashCb = null;
let onWantCb = null, isWantedCb = null; // [R33] the wantlist seams — absent (?game=0/classic) ⇒ no WANT DOM at all
let emitters = null; // [R28] room.audio.emitters, per open — where the till sounds from. Optional.
// shared across opens (persistent): sleeves are all the same box; sides + crate timber never vary
const sleeveGeo = trackGeo(new THREE.BoxGeometry(SLEEVE[0], SLEEVE[1], SLEEVE[2]));
@ -141,6 +142,9 @@ export function createDig(THREE, renderer) {
.pcdg-panel button{margin-top:13px;width:100%;padding:9px;border:1px solid #8a7f66;background:#e7dcc2;color:#241f18;font:700 13px "Courier New",monospace;letter-spacing:.06em;cursor:pointer}
.pcdg-panel button:hover:not(:disabled){background:#241f18;color:#f4e11a;border-color:#241f18}
.pcdg-panel button:disabled{color:#9a917c;border-color:#c3b99f;cursor:default}
.pcdg-panel .want{margin-top:7px;text-align:center;font:700 11px "Courier New",monospace;letter-spacing:.08em;color:#8a7f66;cursor:pointer;user-select:none}
.pcdg-panel .want:hover{color:#241f18}
.pcdg-panel .want.on{color:#b3121f;cursor:default}
.pcdg-panel .x{position:absolute;top:4px;left:8px;cursor:pointer;color:#a89e86;font-size:13px}
.pcdg-out{position:fixed;left:16px;top:16px;background:#1d1d2b;border:1px solid #666;color:#d8d8e0;padding:8px 14px;font:13px "Courier New",monospace;cursor:pointer;display:none;z-index:60}
.pcdg-out:hover{border-color:#3dff8b;color:#3dff8b}
@ -268,14 +272,25 @@ export function createDig(THREE, renderer) {
// the sticker; whether it's under the guide is for the PLAYER to notice — the card never says gem.
const guide = guideText('record', o.band);
if (guide) stamps.push(`<span class="tag">${esc(guide)}</span>`);
// [R33] the WANT line — only when the game layer wired the seams (construction-gated DOM: a
// ?game=0 / classic card carries no wantlist trace). Already-wanted reads as a stamp, not a button.
const wanted = isWantedCb ? !!isWantedCb(o) : false;
const wantLine = onWantCb
? `<div class="want${wanted ? ' on' : ''}">${wanted ? '★ ON THE WANTLIST' : '☆ WANT IT — hunt one cheaper'}</div>`
: '';
panel.innerHTML = `<div class="x">✕</div>`
+ `<div class="sticker">$${esc(o.price)}</div>`
+ `<h3>${esc(o.a)}</h3>`
+ (o.t ? `<div class="ttl">“${esc(o.t)}”</div>` : '')
+ (stamps.length ? `<div class="stamps">${stamps.join('')}</div>` : '')
+ `<button ${o.price > cash ? 'disabled' : ''}>${o.price > cash ? 'NOT ENOUGH CASH' : 'BUY IT'}</button>`;
+ `<button ${o.price > cash ? 'disabled' : ''}>${o.price > cash ? 'NOT ENOUGH CASH' : 'BUY IT'}</button>`
+ wantLine;
panel.style.display = 'block';
panel.querySelector('.x').onclick = unpull;
const wantEl = panel.querySelector('.want');
if (wantEl && !wanted) wantEl.onclick = () => {
if (onWantCb(o) !== false) { wantEl.classList.add('on'); wantEl.textContent = '★ ON THE WANTLIST'; wantEl.onclick = null; }
};
const b = panel.querySelector('button');
if (b && !b.disabled) b.onclick = () => {
// STUB economy (round 6+): onBuy may veto; default is a toast + remove-from-bin.
@ -395,6 +410,7 @@ export function createDig(THREE, renderer) {
function open(opts = {}) {
active = true;
onCloseCb = opts.onClose || null; onBuyCb = opts.onBuy || null; getCashCb = opts.getCash || null;
onWantCb = opts.onWant || null; isWantedCb = opts.isWanted || null; // [R33] wantlist seams
emitters = opts.emitters || null;
const count = opts.count || 16;
const gone = opts.gone instanceof Set && opts.gone.size ? opts.gone : null;