Give the pot wizard the same tap targets as everything else

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 <[email protected]>
Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgb
This commit is contained in:
2026-09-01 00:22:14 -06:00
co-authored by Claude Sonnet 5
parent e8d6098d39
commit 38488f2978
2 changed files with 133 additions and 6 deletions
+90 -4
View File
@@ -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;
@@ -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);