Hold'em: every seat on the ring is the same seat, and the ring is measured before it is believed #122
@@ -90,6 +90,32 @@
|
||||
--gold-deep: #a9782f;
|
||||
--gold-tint: #3a2f18;
|
||||
--gold-shade: #241d0f;
|
||||
|
||||
/* The page is #141414 and never said so.
|
||||
|
||||
Everything above is a colour this stylesheet paints. `color-scheme` is the half
|
||||
the stylesheet cannot paint: the browser draws the checkboxes, the dropdown a
|
||||
<select> opens, the scrollbars, the caret, the spellcheck underline and the
|
||||
autofill wash itself, and with no scheme declared it draws all of them for a
|
||||
light page. Measured before this line: `color-scheme: normal`, three checkboxes
|
||||
rendering as bright white squares in the Table Setup panel — the loudest objects
|
||||
on a near-black screen, brighter than the gold — and a <select> whose menu opens
|
||||
white over the felt.
|
||||
|
||||
One declaration moves every one of them, and it moves them *natively*, which is
|
||||
the part worth having: a control the browser draws still answers Windows High
|
||||
Contrast Mode, still matches the platform a dealer already knows, and cannot
|
||||
lose its tick to a stylesheet. See .potWizardChoice input for what painting one
|
||||
by hand costs, and what it has to pay back.
|
||||
|
||||
--accent-on is the checked colour, and it is the green this tool already uses for
|
||||
yes: the same #1e8449 the pot wizard's hand-drawn box fills with, so the one
|
||||
painted checkbox and the six native ones agree. Chrome picks the tick's own
|
||||
colour from it, and against a green this dark that is white. */
|
||||
--accent-on: #1e8449;
|
||||
|
||||
color-scheme: dark;
|
||||
accent-color: var(--accent-on);
|
||||
}
|
||||
|
||||
/* Every number that changes while the dealer is looking at it — the pot, the stacks,
|
||||
@@ -1974,8 +2000,13 @@ button,
|
||||
|
||||
/* A bare checkbox ships at 13x13, which misses the 24px minimum with a mouse as well
|
||||
as with a thumb. The row around it is the real target on touch, but the box itself
|
||||
should be findable on any device. */
|
||||
#dedicatedDealerToggle {
|
||||
should be findable on any device.
|
||||
|
||||
This said `#dedicatedDealerToggle` and fixed one box of six. The other five were
|
||||
still 13x13 — measured — including the two in the seat sheet that a dealer uses far
|
||||
more often than any setting. Said about checkboxes instead, since that is what the
|
||||
sentence above is about. */
|
||||
input[type="checkbox"] {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
@@ -2888,7 +2919,13 @@ button,
|
||||
gap: var(--sp-2);
|
||||
}
|
||||
|
||||
/* `flex: none` here for the same reason the coarse-pointer block already says it: a
|
||||
stated width is only a suggestion to a flex item, and this one sits in a crowded row.
|
||||
It was declared 32px wide and measured 22 with a mouse — under the 24px floor the
|
||||
checkbox rule near the top of this file is written to clear, and squeezed by exactly
|
||||
the mechanism that block had already been bitten by once. */
|
||||
.chipColorInput {
|
||||
flex: none;
|
||||
width: 32px;
|
||||
height: 28px;
|
||||
background: none;
|
||||
@@ -4554,17 +4591,23 @@ body.hasActionBar #toastHost {
|
||||
}
|
||||
}
|
||||
|
||||
/* The last raw browser control in the tool.
|
||||
`accent-color` only paints the tick; the box around it stayed the platform's own —
|
||||
a bright white square, which on this near-black dialog was the loudest thing on
|
||||
screen and read as unfinished next to controls that had all been drawn. Painted to
|
||||
match the rest, on the same surface ramp and the same corner radius. */
|
||||
/* The one checkbox in the tool that is drawn rather than asked for.
|
||||
The comment here called it "the last raw browser control", which was not true when
|
||||
it was written — six more were still the platform's, and they were white because the
|
||||
page had never declared `color-scheme`. That is fixed at the top of this file, and
|
||||
fixing it there is what makes this one the exception rather than the rule.
|
||||
|
||||
It stays painted because it is not a setting: it is the control a dealer ticks to
|
||||
move money, with players watching, and it wants a fill and a tick that read across a
|
||||
table rather than the platform's 24px square. What painting costs is the browser's
|
||||
own answer to forced-colors mode, which is bought back below.
|
||||
|
||||
It takes its size from the checkbox rule near the top rather than restating it, so
|
||||
there is one number for how big a checkbox is here. */
|
||||
.potWizardChoice input {
|
||||
flex: none;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border: 2px solid var(--line-strong);
|
||||
border-radius: var(--r-sm);
|
||||
background: var(--surface-2);
|
||||
@@ -4602,6 +4645,34 @@ body.hasActionBar #toastHost {
|
||||
}
|
||||
}
|
||||
|
||||
/* What the paint job owes back.
|
||||
In forced-colors mode the OS replaces every colour on the page with its own palette,
|
||||
and a tick drawn as a `background` on a pseudo-element is not a colour it knows how
|
||||
to replace — it is simply gone. So this box, alone among the tool's checkboxes, had
|
||||
no visible checked state at all in Windows High Contrast Mode, on the dialog that
|
||||
pays the table. The system keywords are the fix: they are the only colours
|
||||
guaranteed to survive, because they *are* the palette. */
|
||||
@media (forced-colors: active) {
|
||||
.potWizardChoice input {
|
||||
border-color: ButtonBorder;
|
||||
background: Canvas;
|
||||
}
|
||||
|
||||
.potWizardChoice input::before {
|
||||
background: CanvasText;
|
||||
}
|
||||
|
||||
.potWizardChoice input:checked {
|
||||
border-color: Highlight;
|
||||
background: Canvas;
|
||||
}
|
||||
|
||||
/* The row's own chosen state is a background gradient, which goes the same way. */
|
||||
.potWizardChoice.chosen {
|
||||
outline: 2px solid Highlight;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 {
|
||||
@@ -5213,12 +5284,6 @@ body.hasActionBar #toastHost {
|
||||
min-height: 44px;
|
||||
}
|
||||
|
||||
/* A bare checkbox with no label box around it to grow. */
|
||||
#dedicatedDealerToggle {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
/* An underlined word is a 14px-tall target; give it room without making it look
|
||||
like a button. */
|
||||
.linkBtn {
|
||||
@@ -6047,11 +6112,6 @@ textarea:focus-visible {
|
||||
min-height: 44px;
|
||||
}
|
||||
|
||||
#dedicatedDealerToggle {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
/* An underlined word is a 14px-tall target; give it room without making it look
|
||||
like a button. */
|
||||
.linkBtn {
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
/* 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;
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
// The half of the interface the stylesheet does not draw.
|
||||
//
|
||||
// The browser draws the checkboxes, the menu a <select> opens, the scrollbars, the
|
||||
// caret, the spellcheck underline and the autofill wash, and it draws all of them for a
|
||||
// light page unless the page says otherwise. This one never did: measured,
|
||||
// `color-scheme: normal` on a #141414 ground, with three checkboxes in the Table Setup
|
||||
// panel rendering as bright white squares — the loudest objects on the screen, brighter
|
||||
// than the gold — and two more in the seat sheet doing the same over the felt.
|
||||
//
|
||||
// The comment on the pot wizard's hand-painted checkbox called it "the last raw browser
|
||||
// control in the tool". Six others were still the platform's, and three of those were
|
||||
// still 13x13 against a 24px floor this stylesheet had already written down once and
|
||||
// applied to exactly one box.
|
||||
//
|
||||
// Painting is the expensive way to fix that, and the pot wizard's box shows the bill:
|
||||
// a tick drawn as a `background` on a pseudo-element is not a colour forced-colors mode
|
||||
// knows how to replace, so it simply disappears — no visible checked state at all, on
|
||||
// the dialog that pays the table. Declaring the scheme fixes six controls natively and
|
||||
// costs nothing; the seventh stays painted on purpose and pays its own way.
|
||||
const test = require("node:test");
|
||||
const { describe } = require("node:test");
|
||||
const assert = require("node:assert");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const CSS = fs.readFileSync(
|
||||
path.join(__dirname, "..", "..", "JoshHeaps.Net", "wwwroot", "css", "casino", "holdem.css"), "utf8");
|
||||
|
||||
const ruleFor = selector => {
|
||||
const at = CSS.indexOf(`\n${selector} {`);
|
||||
assert.ok(at >= 0, `there is no \`${selector}\` rule`);
|
||||
return CSS.slice(at, CSS.indexOf("}", at));
|
||||
};
|
||||
|
||||
// The body of a whole at-rule block, braces balanced.
|
||||
const atRule = query => {
|
||||
const at = CSS.indexOf(`@media ${query} {`);
|
||||
assert.ok(at >= 0, `there is no \`@media ${query}\` block`);
|
||||
let depth = 0;
|
||||
for (let i = CSS.indexOf("{", at); i < CSS.length; i++) {
|
||||
if (CSS[i] === "{") depth++;
|
||||
else if (CSS[i] === "}" && --depth === 0) return CSS.slice(at, i + 1);
|
||||
}
|
||||
assert.fail(`\`@media ${query}\` never closes`);
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe("the page says what colour it is", () => {
|
||||
const root = ruleFor(":root");
|
||||
|
||||
test("dark, to the browser and not only to the eye", () => {
|
||||
assert.match(root, /color-scheme:\s*dark/);
|
||||
});
|
||||
|
||||
// The checked colour is the green this tool already uses for yes, so the one
|
||||
// painted checkbox and the six native ones agree rather than nearly agree.
|
||||
test("and the checked colour is the tool's own green, not the platform's blue", () => {
|
||||
assert.match(root, /--accent-on:\s*#1e8449/);
|
||||
assert.match(root, /accent-color:\s*var\(--accent-on\)/);
|
||||
assert.match(ruleFor(".potWizardChoice input:checked"), /background:\s*#1e8449/);
|
||||
});
|
||||
});
|
||||
|
||||
describe("a checkbox is one size", () => {
|
||||
test("every one of them, not the one that was noticed", () => {
|
||||
assert.match(ruleFor('input[type="checkbox"]'), /width:\s*24px/);
|
||||
assert.match(ruleFor('input[type="checkbox"]'), /height:\s*24px/);
|
||||
});
|
||||
|
||||
test("and no box carries a size of its own any more", () => {
|
||||
assert.ok(!/#dedicatedDealerToggle\s*\{/.test(CSS),
|
||||
"one checkbox is still sized by id, which is how five got left behind");
|
||||
assert.ok(!/width:\s*22px/.test(ruleFor(".potWizardChoice input")),
|
||||
"the painted box restates its size instead of taking the one above");
|
||||
});
|
||||
|
||||
// A stated width is only a suggestion to a flex item. The coarse-pointer block had
|
||||
// already been bitten by this and said so; the mouse case had not.
|
||||
test("a swatch in a crowded row keeps the width it was given", () => {
|
||||
assert.match(ruleFor(".chipColorInput"), /flex:\s*none/);
|
||||
});
|
||||
});
|
||||
|
||||
describe("what painting a control costs, and who pays it", () => {
|
||||
// If a future round paints another one, this is the bill it has to settle too.
|
||||
test("nothing gives up the platform's drawing without answering forced colours", () => {
|
||||
const forced = atRule("(forced-colors: active)");
|
||||
const painted = [...CSS.matchAll(/\n([^\n{}]+)\s*\{[^}]*appearance:\s*none/g)]
|
||||
.map(m => m[1].trim());
|
||||
assert.ok(painted.length > 0, "nothing is painted, so this test is measuring nothing");
|
||||
painted.forEach(selector => {
|
||||
assert.ok(forced.includes(selector),
|
||||
`\`${selector}\` drops the platform's control but has no forced-colors answer`);
|
||||
});
|
||||
});
|
||||
|
||||
// A tick drawn as a background is gone in forced-colors mode; a system keyword is
|
||||
// the only colour guaranteed to survive, because it *is* the palette.
|
||||
test("the tick that is drawn rather than typed survives the OS repainting it", () => {
|
||||
const forced = atRule("(forced-colors: active)");
|
||||
assert.match(forced, /\.potWizardChoice input::before\s*\{[^}]*background:\s*CanvasText/);
|
||||
});
|
||||
|
||||
test("and so does the row's own chosen state, which is a gradient", () => {
|
||||
const forced = atRule("(forced-colors: active)");
|
||||
assert.match(forced, /\.potWizardChoice\.chosen\s*\{[^}]*outline:\s*2px solid Highlight/);
|
||||
});
|
||||
});
|
||||
|
||||
describe("the other page of the same tool", () => {
|
||||
const QUICKSPLIT = fs.readFileSync(
|
||||
path.join(__dirname, "..", "..", "JoshHeaps.Net", "wwwroot", "css", "casino", "quicksplit.css"), "utf8");
|
||||
|
||||
// It is the darker of the two pages and is opened from the felt mid-hand. It has no
|
||||
// checkboxes to go white, but scrollbars, caret and selection were still drawn for
|
||||
// a light page.
|
||||
test("Quick Split says what colour it is too", () => {
|
||||
assert.match(QUICKSPLIT, /:root\s*\{[^}]*color-scheme:\s*dark/);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user