"Split between" on Quick Split was two controls for one value stacked on each other: chips 2 3 4 5, and under them a bar reading "2 ways" with a − and a +. The count was written down three times at once — the lit chip, the bar, and "Each of 2 players gets" in the panel above — and two of the three were controls. 134px with its label, against 74px for "Smallest chip in play" right below it, which offers five choices in one row. The bar was never meant to be a bar. `.waysStepper` asked for a 150px min-width inside a wrapping flex row, so on a phone it always wrapped to a line of its own, and `flex: 1 1 auto` then gave it all 358px of that line: 252px of empty readout with the − and + pushed 304px apart, on a screen 390px wide. Now it is 136px with its ends 121px apart, and it only exists once you are through the door — a fifth chip reading "6+", behind which the stepper is where the count is written. Under six ways, which is every chop a home game will run, the field is one row and 74px. Two more things went with it: Neither stepper ever disabled an end, so − at the floor and + at the ceiling looked live and swallowed the tap. NN/G's stepper guidance asks for the opposite. Both ends of both steppers now grey out. The per-pot chop capped its + with `Math.max(contenderCount, MAX_WAYS)`, which is always 12 — a side pot only P1 and P2 were eligible for would happily chop ten ways at $12 each. It is `chopCeiling()` now, and a two-contender pot is offered no stepper at all, that being the common shape. The sweep went straight to the all-in mode and audited only that, so the mode the screen opens in had never been looked at in fourteen rounds, which is how a 358px bar lasted this long. It audits both now — 428 audits, clean — and the first run of it found the step buttons had been 40px wide rather than 44 since they were written. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgb
657 lines
15 KiB
CSS
657 lines
15 KiB
CSS
/* Quick Split is phone-first: sized for one thumb at the table, then allowed to
|
||
breathe on a laptop. Palette matches the dealer table so the two read as one tool. */
|
||
|
||
/* And matches it in the half a stylesheet does not paint, for the same reason: this
|
||
page is #0a0a0a and had never told the browser so, which leaves the scrollbars, the
|
||
caret, the selection and the autofill wash drawn for a light page. It has no
|
||
checkboxes to go white, but a dealer who opens it from the felt should not find a
|
||
light scrollbar down the side of the darker of the two pages. */
|
||
:root {
|
||
color-scheme: dark;
|
||
}
|
||
|
||
body {
|
||
background: radial-gradient(ellipse at 50% -10%, #1c1c1c 0%, #101010 55%, #0a0a0a 100%);
|
||
min-height: 100vh;
|
||
margin: 0;
|
||
color: #e6e6e6;
|
||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||
}
|
||
|
||
/* Same touch handling as the dealer table — see the note there. This page is the one
|
||
a dealer opens mid-hand to chop a pot, so the ~300ms the browser spends deciding
|
||
whether a tap was a double-tap-to-zoom is the last thing it needs. */
|
||
button,
|
||
[role="button"],
|
||
input,
|
||
select,
|
||
textarea,
|
||
a {
|
||
touch-action: manipulation;
|
||
}
|
||
|
||
button,
|
||
[role="button"],
|
||
input,
|
||
select,
|
||
textarea,
|
||
a {
|
||
-webkit-tap-highlight-color: transparent;
|
||
}
|
||
|
||
/* Not on the fields — a dealer typing a pot amount still needs to select it. */
|
||
button,
|
||
[role="button"] {
|
||
-webkit-user-select: none;
|
||
user-select: none;
|
||
}
|
||
|
||
.clearPotBtn:active:not(:disabled),
|
||
.choiceChip:active:not(:disabled),
|
||
.stepBtn:active:not(:disabled),
|
||
.splitBtn:active:not(:disabled),
|
||
.splitBtnGhost:active:not(:disabled),
|
||
.unevenFoldBtn:active:not(:disabled),
|
||
.unevenRemoveBtn:active:not(:disabled) {
|
||
transform: translateY(1px);
|
||
filter: brightness(1.25);
|
||
transition-duration: 0.04s;
|
||
}
|
||
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.clearPotBtn:active:not(:disabled),
|
||
.choiceChip:active:not(:disabled),
|
||
.stepBtn:active:not(:disabled),
|
||
.splitBtn:active:not(:disabled),
|
||
.splitBtnGhost:active:not(:disabled),
|
||
.unevenFoldBtn:active:not(:disabled),
|
||
.unevenRemoveBtn:active:not(:disabled) {
|
||
transform: none;
|
||
}
|
||
}
|
||
|
||
#splitApp {
|
||
max-width: 480px;
|
||
margin: 0 auto;
|
||
padding: 1.25rem 1rem 3rem;
|
||
}
|
||
|
||
/* ---------- Header ---------- */
|
||
|
||
#splitHeader h1 {
|
||
margin: 0;
|
||
font-size: 1.5rem;
|
||
font-weight: 300;
|
||
letter-spacing: 0.04em;
|
||
color: #f5f5f5;
|
||
position: relative;
|
||
display: inline-block;
|
||
padding-bottom: 0.35rem;
|
||
}
|
||
|
||
#splitHeader h1::after {
|
||
content: "";
|
||
position: absolute;
|
||
left: 0;
|
||
bottom: 0;
|
||
width: 36px;
|
||
height: 3px;
|
||
border-radius: 2px;
|
||
background: linear-gradient(90deg, #d8b46a, #a9782f);
|
||
}
|
||
|
||
.splitSubtitle {
|
||
margin: 0.35rem 0 1.25rem;
|
||
color: #8f8f8f;
|
||
font-size: 0.85rem;
|
||
}
|
||
|
||
/* ---------- Mode toggle ---------- */
|
||
|
||
#modeToggle {
|
||
margin-bottom: 1.1rem;
|
||
}
|
||
|
||
/* ---------- Uneven amounts ---------- */
|
||
|
||
#unevenRows {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 0.45rem;
|
||
margin-bottom: 0.6rem;
|
||
}
|
||
|
||
.unevenRow {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.45rem;
|
||
}
|
||
|
||
.unevenRowLabel {
|
||
flex: none;
|
||
width: 2rem;
|
||
color: #8f8f8f;
|
||
font-size: 0.8rem;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.unevenAmountWrap {
|
||
flex: 1;
|
||
min-width: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.3rem;
|
||
background: #141414;
|
||
border: 1px solid #3a3a3a;
|
||
border-radius: 10px;
|
||
padding: 0 0.6rem;
|
||
}
|
||
|
||
.unevenAmountWrap:focus-within {
|
||
border-color: #d8b46a;
|
||
}
|
||
|
||
.unevenCurrency {
|
||
/* Was #777 — 4.11:1 on this background, under the 4.5:1 small text needs. It sits
|
||
against every amount a dealer types, so it is read constantly. */
|
||
color: #8f8f8f;
|
||
}
|
||
|
||
/* 37px tall, on the field a dealer types every amount into. The touch rule has been
|
||
44px everywhere else since the round that set it; this page never got measured for
|
||
it, because the audit only ran the target check when asked and nothing asked. */
|
||
.unevenAmount {
|
||
flex: 1;
|
||
min-width: 0;
|
||
min-height: 46px;
|
||
background: none;
|
||
border: none;
|
||
outline: none;
|
||
color: #f2f2f2;
|
||
font-family: inherit;
|
||
font-size: 16px;
|
||
font-variant-numeric: tabular-nums;
|
||
padding: 0.6rem 0;
|
||
}
|
||
|
||
.unevenFoldBtn {
|
||
flex: none;
|
||
min-height: 44px;
|
||
padding: 0 0.6rem;
|
||
border-radius: 9px;
|
||
border: 1px solid #3a3a3a;
|
||
background: #232323;
|
||
color: #8f8f8f;
|
||
font-family: inherit;
|
||
font-size: 0.72rem;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.unevenFoldBtn.selected {
|
||
background: linear-gradient(180deg, #3d1f1f, #2c1515);
|
||
border-color: #5b2626;
|
||
color: #ffd6d6;
|
||
}
|
||
|
||
/* 30px across, and it deletes a player's entry — the one control on the row where a
|
||
near miss costs something. The amount field beside it gives up the 16px. */
|
||
.unevenRemoveBtn {
|
||
flex: none;
|
||
width: 46px;
|
||
height: 46px;
|
||
border: none;
|
||
background: none;
|
||
/* Was #6a6a6a — 3.66:1, the worst on the page, on a control that deletes a
|
||
player's entry. A destructive action should not be the faintest thing in view. */
|
||
color: #9a9a9a;
|
||
font-size: 0.85rem;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.unevenRemoveBtn:disabled {
|
||
opacity: 0.3;
|
||
cursor: not-allowed;
|
||
}
|
||
|
||
#unevenResult {
|
||
background: linear-gradient(160deg, #1f2a21, #161c17);
|
||
border: 1px solid #2c3a2f;
|
||
border-radius: 14px;
|
||
padding: 0.9rem 1rem;
|
||
margin-bottom: 1.5rem;
|
||
}
|
||
|
||
#unevenResult[hidden] {
|
||
display: none;
|
||
}
|
||
|
||
.unevenPot {
|
||
display: flex;
|
||
align-items: baseline;
|
||
/* Wraps so a chop opens underneath its own pot rather than squeezing in beside the
|
||
eligible-players list and pushing it off the row. */
|
||
flex-wrap: wrap;
|
||
gap: 0.6rem;
|
||
padding: 0.3rem 0;
|
||
font-size: 0.85rem;
|
||
}
|
||
|
||
.unevenChopToggle {
|
||
flex: none;
|
||
order: 3;
|
||
/* 44px on touch: it moves money, like everything else that does. */
|
||
min-height: 32px;
|
||
padding: 0.2rem 0.6rem;
|
||
border: 1px solid rgba(216, 180, 106, 0.45);
|
||
border-radius: 999px;
|
||
background: rgba(216, 180, 106, 0.1);
|
||
color: #e3c887;
|
||
font: inherit;
|
||
font-size: 0.74rem;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.unevenChopToggle:hover {
|
||
background: rgba(216, 180, 106, 0.18);
|
||
}
|
||
|
||
.unevenChopToggle:focus-visible {
|
||
outline: 2px solid #d8b46a;
|
||
outline-offset: 2px;
|
||
}
|
||
|
||
.unevenChopDetail {
|
||
order: 4;
|
||
flex: 0 0 100%;
|
||
/* Or the padding is added on top of the 100% basis and the panel sits wider than
|
||
the row it belongs to — measured 328px inside a 309px row on a phone. */
|
||
box-sizing: border-box;
|
||
margin: 0.15rem 0 0.2rem;
|
||
padding: 0.45rem 0.6rem;
|
||
border-radius: 8px;
|
||
background: rgba(255, 255, 255, 0.04);
|
||
}
|
||
|
||
.unevenChopWays {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.45rem;
|
||
margin-bottom: 0.3rem;
|
||
}
|
||
|
||
.unevenChopWaysLabel {
|
||
color: #cfcfcf;
|
||
font-size: 0.78rem;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
|
||
.unevenChopEach {
|
||
margin: 0;
|
||
color: #f2f2f2;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.unevenChopNote {
|
||
margin: 0.2rem 0 0;
|
||
color: #9a9a9a;
|
||
font-size: 0.76rem;
|
||
}
|
||
|
||
.unevenChopDust {
|
||
color: #e0b169;
|
||
}
|
||
|
||
@media (max-width: 700px), (pointer: coarse) {
|
||
.unevenChopToggle {
|
||
min-height: 44px;
|
||
padding: 0.4rem 0.9rem;
|
||
}
|
||
}
|
||
|
||
.unevenPot + .unevenPot {
|
||
border-top: 1px solid rgba(255, 255, 255, 0.06);
|
||
}
|
||
|
||
.unevenPotLabel {
|
||
flex: none;
|
||
color: #d8b46a;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.unevenPotAmount {
|
||
flex: none;
|
||
color: #f2f2f2;
|
||
font-weight: 600;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
|
||
.unevenPotWho {
|
||
flex: 1;
|
||
min-width: 0;
|
||
text-align: right;
|
||
color: #9a9a9a;
|
||
font-size: 0.78rem;
|
||
}
|
||
|
||
.unevenPotReturn .unevenPotLabel,
|
||
.unevenPotReturn .unevenPotAmount {
|
||
color: #9a9a9a;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.unevenPotTotal {
|
||
margin-top: 0.15rem;
|
||
border-top: 1px solid rgba(255, 255, 255, 0.14) !important;
|
||
}
|
||
|
||
.unevenPotTotal .unevenPotLabel {
|
||
color: #8f9d92;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.unevenEmpty {
|
||
margin: 0;
|
||
color: #8f9d92;
|
||
font-size: 0.82rem;
|
||
line-height: 1.45;
|
||
}
|
||
|
||
/* ---------- The answer ---------- */
|
||
|
||
#splitResult {
|
||
background: linear-gradient(160deg, #1f2a21, #161c17);
|
||
border: 1px solid #2c3a2f;
|
||
border-radius: 14px;
|
||
padding: 1.4rem 1.1rem;
|
||
text-align: center;
|
||
margin-bottom: 1.5rem;
|
||
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
||
}
|
||
|
||
#splitResult.hasAmount {
|
||
border-color: #3c6b46;
|
||
box-shadow: 0 0 0 1px rgba(78, 201, 122, 0.08), 0 6px 20px rgba(0, 0, 0, 0.35);
|
||
}
|
||
|
||
#splitResultLabel {
|
||
color: #8f9d92;
|
||
font-size: 0.78rem;
|
||
letter-spacing: 0.06em;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
#splitResultAmount {
|
||
margin-top: 0.35rem;
|
||
font-size: clamp(2.6rem, 14vw, 3.4rem);
|
||
font-weight: 600;
|
||
line-height: 1.05;
|
||
color: #f2f2f2;
|
||
font-variant-numeric: tabular-nums;
|
||
letter-spacing: -0.01em;
|
||
}
|
||
|
||
#splitResult.hasAmount #splitResultAmount {
|
||
color: #7ee2a0;
|
||
}
|
||
|
||
#splitOddNote {
|
||
margin-top: 0.7rem;
|
||
color: #d8b46a;
|
||
font-size: 0.85rem;
|
||
line-height: 1.45;
|
||
}
|
||
|
||
#splitDustNote {
|
||
margin-top: 0.5rem;
|
||
color: #e0a1a1;
|
||
font-size: 0.8rem;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
/* ---------- Inputs ---------- */
|
||
|
||
.splitField {
|
||
display: block;
|
||
margin-bottom: 1.35rem;
|
||
}
|
||
|
||
/* A `display` declaration outranks the browser's own [hidden] rule, so anything
|
||
given one has to opt back out explicitly or toggling `hidden` does nothing. */
|
||
[hidden] {
|
||
display: none !important;
|
||
}
|
||
|
||
.splitLabel {
|
||
display: block;
|
||
margin-bottom: 0.5rem;
|
||
color: #9a9a9a;
|
||
font-size: 0.75rem;
|
||
letter-spacing: 0.06em;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
.potInputWrap {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.4rem;
|
||
background: #141414;
|
||
border: 1px solid #3a3a3a;
|
||
border-radius: 12px;
|
||
padding: 0.2rem 0.75rem;
|
||
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
||
}
|
||
|
||
.potInputWrap:focus-within {
|
||
border-color: #d8b46a;
|
||
box-shadow: 0 0 0 3px rgba(216, 180, 106, 0.12);
|
||
}
|
||
|
||
.potCurrency {
|
||
color: #777;
|
||
font-size: 1.6rem;
|
||
font-weight: 300;
|
||
}
|
||
|
||
#potInput {
|
||
flex: 1;
|
||
min-width: 0;
|
||
background: none;
|
||
border: none;
|
||
outline: none;
|
||
color: #f2f2f2;
|
||
font-size: 2rem;
|
||
font-weight: 500;
|
||
font-variant-numeric: tabular-nums;
|
||
padding: 0.55rem 0;
|
||
font-family: inherit;
|
||
}
|
||
|
||
#potInput::placeholder {
|
||
color: #4a4a4a;
|
||
}
|
||
|
||
.clearPotBtn {
|
||
flex: none;
|
||
width: 34px;
|
||
height: 34px;
|
||
border-radius: 50%;
|
||
border: none;
|
||
background: #262626;
|
||
color: #999;
|
||
font-size: 0.85rem;
|
||
cursor: pointer;
|
||
}
|
||
|
||
@media (hover: hover) {
|
||
.clearPotBtn:hover {
|
||
background: #333;
|
||
color: #ddd;
|
||
}
|
||
}
|
||
|
||
/* ---------- Tap targets ---------- */
|
||
|
||
.chipRow {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 0.5rem;
|
||
}
|
||
|
||
.choiceChip {
|
||
flex: 1 1 auto;
|
||
min-width: 58px;
|
||
min-height: 52px;
|
||
padding: 0.5rem 0.7rem;
|
||
background: linear-gradient(180deg, #2e2e2e, #232323);
|
||
border: 1px solid #3a3a3a;
|
||
border-radius: 11px;
|
||
color: #ddd;
|
||
font-size: 1rem;
|
||
font-family: inherit;
|
||
cursor: pointer;
|
||
transition: all 0.15s ease;
|
||
}
|
||
|
||
@media (hover: hover) {
|
||
.choiceChip:hover {
|
||
border-color: #4a4a4a;
|
||
background: linear-gradient(180deg, #383838, #2a2a2a);
|
||
}
|
||
}
|
||
|
||
.choiceChip.selected {
|
||
background: linear-gradient(180deg, #3a2f18, #241d0f);
|
||
border-color: #d8b46a;
|
||
color: #f0d9a8;
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* As wide as the three things in it, and no wider.
|
||
This sits in the same wrapping flex row as the chips, where it has never once fitted
|
||
on the first line of a phone. `flex: 1 1 auto` then handed it the whole of the second
|
||
line: measured on an iPhone, a 358px bar with 252px of nothing in the middle and the
|
||
− and + pushed 304px apart — the two ends of a control a thumb is meant to work with
|
||
one hand. 136px now, its two ends 121px apart. */
|
||
.waysStepper {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.35rem;
|
||
flex: 0 0 auto;
|
||
background: #191919;
|
||
border: 1px solid #333;
|
||
border-radius: 11px;
|
||
padding: 0.2rem 0.4rem;
|
||
}
|
||
|
||
/* 44 both ways, not 40x44. It had been 40px wide since the steppers were written, and
|
||
the sweep never said so because the only two steppers on the site are on this screen
|
||
and this screen was only ever audited in its all-in mode, where neither is on display
|
||
until a side pot has more than two contenders. The first sweep that opened the even
|
||
mode reported `hittable 39x43` on both ends, on every touch viewport. */
|
||
.stepBtn {
|
||
width: 44px;
|
||
height: 44px;
|
||
border: none;
|
||
border-radius: 8px;
|
||
background: #262626;
|
||
color: #ddd;
|
||
font-size: 1.25rem;
|
||
line-height: 1;
|
||
font-family: inherit;
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* The floor and the ceiling look like the floor and the ceiling. */
|
||
.stepBtn:disabled {
|
||
opacity: 0.32;
|
||
cursor: default;
|
||
}
|
||
|
||
@media (hover: hover) {
|
||
.stepBtn:not(:disabled):hover {
|
||
background: #333;
|
||
}
|
||
}
|
||
|
||
/* The count itself, now that no chip beside it is also holding one — so it is painted
|
||
the way a selected chip is painted, because that is what it is standing in for. */
|
||
.waysReadout {
|
||
min-width: 2.5ch;
|
||
text-align: center;
|
||
color: #f0d9a8;
|
||
font-size: 1rem;
|
||
font-weight: 600;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
|
||
/* ---------- Footer actions ---------- */
|
||
|
||
#splitActions {
|
||
display: flex;
|
||
gap: 0.6rem;
|
||
margin-top: 1.75rem;
|
||
}
|
||
|
||
.splitBtn {
|
||
flex: 1;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-height: 48px;
|
||
padding: 0.6rem 0.9rem;
|
||
border-radius: 10px;
|
||
border: 1px solid #3a3a3a;
|
||
background: linear-gradient(180deg, #2e2e2e, #232323);
|
||
color: #ddd;
|
||
font-size: 0.9rem;
|
||
font-family: inherit;
|
||
text-decoration: none;
|
||
cursor: pointer;
|
||
transition: all 0.15s ease;
|
||
}
|
||
|
||
@media (hover: hover) {
|
||
.splitBtn:hover {
|
||
border-color: #4a4a4a;
|
||
background: linear-gradient(180deg, #383838, #2a2a2a);
|
||
}
|
||
}
|
||
|
||
.splitBtnGhost {
|
||
background: transparent;
|
||
}
|
||
|
||
.splitFootnote {
|
||
margin-top: 1.5rem;
|
||
/* Was #6f6f6f — 3.94:1. It carries the instruction for what to do with the pot
|
||
list, which is not a decorative line. */
|
||
color: #8d8d8d;
|
||
font-size: 0.78rem;
|
||
line-height: 1.5;
|
||
text-align: center;
|
||
}
|
||
|
||
/* This footnote names a control the dealer is being told to reach for, so the name
|
||
itself has to be readable — it was 3.39:1 at its worst, inheriting the muted grey
|
||
the surrounding sentence is deliberately set in. Emphasised text carrying the
|
||
instruction gets its own colour rather than the aside's. */
|
||
.splitFootnote strong {
|
||
color: #a8a8a8;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.splitFootnote a {
|
||
color: #a9782f;
|
||
}
|
||
|
||
/* Roomier once there's a real screen to work with. */
|
||
@media (min-width: 700px) {
|
||
#splitApp {
|
||
padding-top: 2.5rem;
|
||
}
|
||
|
||
#splitHeader h1 {
|
||
font-size: 1.8rem;
|
||
}
|
||
}
|