From 38488f2978bac81658bc6f7a09158b4e98601c80 Mon Sep 17 00:00:00 2001 From: JoshHeaps Date: Tue, 1 Sep 2026 00:22:14 -0600 Subject: [PATCH] Give the pot wizard the same tap targets as everything else MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Measured the screen where the money actually gets decided and found the smallest targets in the tool: 37px winner rows, 13px checkboxes, a 36px confirm. Every other surface has been held to 44px and up for several rounds — the one place a mis-tap pays the wrong player was the one place that hadn't been. Winner rows are now 56px and up, with a 22px box and a green fill when chosen, because a dealer confirms this with players watching and a small checkbox is easy to misread across a table. The row already was the tap target; now it looks like one. Each row also splits into name, what they can win, and their cards as separate pieces rather than one run-on sentence, so the hand can be read at a glance. The confirm takes the full width, and on a phone the summary's buttons stack with the one that ends the hand furthest from a stray thumb. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgb --- JoshHeaps.Net/wwwroot/css/casino/holdem.css | 94 ++++++++++++++++++- .../wwwroot/js/casino/holdem/potWizard.js | 45 ++++++++- 2 files changed, 133 insertions(+), 6 deletions(-) diff --git a/JoshHeaps.Net/wwwroot/css/casino/holdem.css b/JoshHeaps.Net/wwwroot/css/casino/holdem.css index 8d9ca2e..ea14ea5 100644 --- a/JoshHeaps.Net/wwwroot/css/casino/holdem.css +++ b/JoshHeaps.Net/wwwroot/css/casino/holdem.css @@ -1962,20 +1962,75 @@ body.hasActionBar #toastHost { margin-bottom: 0.6rem; } +/* This is the screen where the money gets decided, so it holds the same 44px+ + targets as the rest of the tool rather than the smallest ones in it. Picking the + wrong winner is the one mistake here that costs somebody real money. */ .potWizardChoice { display: flex; align-items: center; - gap: 0.5rem; + gap: 0.7rem; + min-height: 56px; background: #141414; border: 1px solid #333; - border-radius: 6px; - padding: 0.5rem 0.7rem; + border-radius: 10px; + padding: 0.6rem 0.8rem; cursor: pointer; - font-size: 0.85rem; + font-size: 0.95rem; + transition: border-color 0.12s ease, background 0.12s ease; } .potWizardChoice:hover { border-color: #555; + background: #191919; +} + +.potWizardChoice input { + flex: none; + width: 22px; + height: 22px; + accent-color: #1e8449; +} + +/* Selected has to be obvious at a glance — a dealer confirms this with players + watching, and a checkbox alone is easy to misread across a table. */ +.potWizardChoice.chosen { + border-color: #1e8449; + background: linear-gradient(180deg, #16301f, #12241a); +} + +.potWizardChoice.chosen .potWizardChoiceName { + color: #d6ffe0; +} + +.potWizardChoiceText { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + gap: 0.1rem; +} + +.potWizardChoiceName { + color: #f0f0f0; + font-weight: 600; +} + +.potWizardChoiceUpTo { + color: #9a9a9a; + font-size: 0.76rem; + font-variant-numeric: tabular-nums; +} + +.potWizardChoiceCards { + flex: none; + font-family: var(--font-mono, monospace); + font-size: 1rem; + font-weight: 700; + color: #ddd; +} + +.potWizardChoiceCards .cardRed { + color: #ff6b6b; } .potWizardSummary ul { @@ -1996,6 +2051,37 @@ body.hasActionBar #toastHost { gap: 0.6rem; } +/* Every button in this modal is one a dealer presses with players waiting. */ +#potWizardBody .holdemBtn { + min-height: 48px; + justify-content: center; +} + +/* The confirm is the whole point of the step, so it gets the whole width rather + than being sized to the length of its own label. */ +.potWizardRound > .holdemBtn { + width: 100%; +} + +.potWizardActions .holdemBtn { + flex: 1; +} + +.potWizardSummary li { + font-variant-numeric: tabular-nums; +} + +@media (max-width: 700px) { + /* Stacked, with the action that ends the hand furthest from a stray thumb. */ + .potWizardActions { + flex-direction: column-reverse; + } + + .potWizardChoice { + min-height: 60px; + } +} + @media (max-width: 900px) { #holdemLayout { grid-template-columns: 1fr; diff --git a/JoshHeaps.Net/wwwroot/js/casino/holdem/potWizard.js b/JoshHeaps.Net/wwwroot/js/casino/holdem/potWizard.js index ab36c9a..16918d3 100644 --- a/JoshHeaps.Net/wwwroot/js/casino/holdem/potWizard.js +++ b/JoshHeaps.Net/wwwroot/js/casino/holdem/potWizard.js @@ -18,6 +18,14 @@ const PotWizard = { this.playerLabelById = new Map( players.map(p => [p.id, this.labelFor(p, state.seats.indexOf(p))]) ); + // The label carries name and cards together for the log and the payout lines; + // the choice rows want them separately so each can be styled and read on its own. + this.nameById = new Map( + players.map(p => [p.id, HoldemState.displayName(p, state.seats.indexOf(p))]) + ); + this.cardsById = new Map( + players.map(p => [p.id, (p.cards || []).filter(Boolean)]) + ); const contributions = players.map(p => ({ id: p.id, contribution: HoldemState.computeContribution(p, state.chipLegend, state.basePotAmount), @@ -105,13 +113,46 @@ const PotWizard = { contenders.forEach(c => { const label = document.createElement("label"); label.className = "potWizardChoice"; + const checkbox = document.createElement("input"); checkbox.type = "checkbox"; checkbox.value = c.id; - const text = document.createElement("span"); - text.textContent = `${this.playerLabelById.get(c.id)} — up to ${Money.format(c.remaining)}`; + // The row is the target, not the box — so the row has to look chosen too. + checkbox.addEventListener("change", () => { + label.classList.toggle("chosen", checkbox.checked); + }); label.appendChild(checkbox); + + const text = document.createElement("span"); + text.className = "potWizardChoiceText"; + + const name = document.createElement("span"); + name.className = "potWizardChoiceName"; + name.textContent = this.nameById.get(c.id); + text.appendChild(name); + + const upTo = document.createElement("span"); + upTo.className = "potWizardChoiceUpTo"; + upTo.textContent = `up to ${Money.format(c.remaining)}`; + text.appendChild(upTo); label.appendChild(text); + + // Cards sit apart from the name rather than inside it, so a dealer reading + // a row across the table sees the hand, not a sentence. + const cards = this.cardsById.get(c.id) || []; + if (cards.length > 0) { + const cardsEl = document.createElement("span"); + cardsEl.className = "potWizardChoiceCards"; + cards.forEach((card, i) => { + if (i > 0) cardsEl.appendChild(document.createTextNode(" ")); + const span = document.createElement("span"); + if (/[HD]$/i.test(card)) span.className = "cardRed"; + span.textContent = Render.formatCard(card); + cardsEl.appendChild(span); + }); + label.appendChild(cardsEl); + } + choices.appendChild(label); }); round.appendChild(choices);