Compare commits

...
Author SHA1 Message Date
jheaps e8797b8dc2 Merge branch 'master' into feature/casino-holdem-undo-toasts 2026-08-31 18:41:13 -06:00
jheaps 48bd3682f2 Merge pull request 'Make the four seat states readable across the table' (#18) from feature/casino-holdem-seat-legibility into feature/casino-holdem-undo-toasts
Reviewed-on: #18
2026-08-31 18:39:58 -06:00
jheapsandClaude Sonnet 5 1e1bdcccce Make the four seat states readable across the table
A seat could be live in the hand, folded, sitting out, or empty, and three of
those looked nearly the same: a plain dark puck, or a dimmed one. An unclaimed
chair was indistinguishable from a nameless player, and nothing positively said
"this player is in" — the dealer had to infer it from whether a dollar badge
happened to be showing.

Each state now has one look. Live gets a green edge. Folded gets a red edge and
a struck-through name, so it reads as out rather than merely faint. An empty
chair is the only dashed outline and says so. Sitting out just fades — and
fades less than it used to, since that player is still someone the dealer may
need to deal back in, and at 0.4 the name was nearly gone.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgb
2026-08-31 18:36:54 -06:00
jheaps aee172a5cd Merge pull request 'Quick Split: chop a pot from your phone without setting up a table' (#15) from feature/casino-holdem-quick-split into master
Build and Deploy / build-deploy (push) Successful in 1m14s
Reviewed-on: #15
2026-08-31 18:33:05 -06:00
jheaps d206758729 Merge branch 'master' into feature/casino-holdem-quick-split 2026-08-31 18:32:56 -06:00
jheaps 4afc3649cc Merge pull request 'Make the dealer table usable on a phone' (#16) from feature/casino-holdem-mobile-table into feature/casino-holdem-quick-split
Reviewed-on: #16
2026-08-31 18:31:52 -06:00
jheaps 71b33f8623 Merge pull request 'Give the Hold'em dealer a session record: hand history, CSV export and standings' (#14) from feature/casino-holdem-hand-history into master
Build and Deploy / build-deploy (push) Successful in 1m13s
Reviewed-on: #14
2026-08-31 18:31:19 -06:00
2 changed files with 57 additions and 4 deletions
+39 -2
View File
@@ -250,13 +250,50 @@ body {
outline-offset: 2px;
}
/* Four states a dealer needs to tell apart from across the table, without
reading anything: live in this hand, folded, sitting out, and nobody there.
Live gets a green edge, folded gets a red one and a struck-through name,
sitting-out just fades, and an empty chair is the only dashed outline. */
.seat.seatLive {
border-color: rgba(78, 201, 122, 0.45);
box-shadow:
0 0 0 1px rgba(78, 201, 122, 0.18),
0 3px 10px rgba(0, 0, 0, 0.5),
inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
/* Sitting out, not gone: still a person the dealer may need to deal back in, so
the name has to stay readable rather than fading almost to the felt. */
.seat.seatInactive {
opacity: 0.4;
opacity: 0.58;
}
.seat.seatFolded {
border-color: rgba(224, 123, 123, 0.4);
opacity: 0.5;
}
.seat.seatFolded .seatPuckName {
text-decoration: line-through;
text-decoration-color: rgba(224, 123, 123, 0.75);
}
.seat.seatEmpty {
background: rgba(255, 255, 255, 0.02);
border-style: dashed;
opacity: 0.55;
border-color: rgba(255, 255, 255, 0.13);
box-shadow: none;
/* Deliberately louder than seatInactive: an open seat is information a
dealer wants, not something to squint at. */
opacity: 0.7;
}
.seatEmptyLabel {
color: #6d6d6d;
font-size: 0.6rem;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.seat.seatSelected {
@@ -124,8 +124,22 @@ const Render = {
return /[HD]$/i.test(card || "");
},
// A chair nobody has claimed: no name typed, not dealt in, nothing in the pot.
// Worth calling out, because at a short-handed table the open seats are what
// the dealer is looking for.
isEmptySeat(player) {
const named = !!(player.name && player.name.trim());
const contributing =
HoldemState.computeContribution(player, this.state.chipLegend, this.state.basePotAmount) > 0;
return !named && !player.inHand && !contributing;
},
updatePuckContent(node, player, index) {
node.querySelector(".seatPuckName").textContent = player.name && player.name.trim() ? player.name.trim() : "";
const empty = this.isEmptySeat(player);
const nameEl = node.querySelector(".seatPuckName");
nameEl.textContent = empty ? "Empty" : (player.name || "").trim();
nameEl.classList.toggle("seatEmptyLabel", empty);
const cardsEl = node.querySelector(".seatPuckCards");
cardsEl.innerHTML = "";
(player.cards || []).filter(Boolean).forEach((card, i) => {
@@ -137,8 +151,10 @@ const Render = {
});
const total = HoldemState.computeContribution(player, this.state.chipLegend, this.state.basePotAmount);
node.querySelector(".seatPuckTotal").textContent = total > 0 ? Money.format(total) : "";
node.classList.toggle("seatInactive", !player.inHand);
node.classList.toggle("seatEmpty", empty);
node.classList.toggle("seatInactive", !player.inHand && !empty);
node.classList.toggle("seatFolded", player.folded);
node.classList.toggle("seatLive", player.inHand && !player.folded);
},
// Cheaper than a full renderSeats() — used after edits so the seat editor's inputs