Level 3, and the control a bet is actually placed with. Three faces that never coexist:
a pinned panel above 760, a fixed dock below it, and a sheet the dock opens. 12 panels, 9
docks and 9 sheets on 12 painted screens. It was 11, 8 and 8 until 2026-08-17, when the state
a bet is actually in - side chosen, nothing wrong, Confirm live - got a page of its own,
event-detail-bet-ready.html. The sheets were 4 until 2026-08-16, when the four
bet-state screens got one: the panel is display:none below 760, so
every state of the act this component exists for rendered on desktop only. Measured
2026-08-08 in a browser at 390 and 1280, re-counted 2026-08-16.
This section was a sheet wearing the panel's title, and it drew nothing at
all. A <dialog> with no open attribute is
display:none, so
both cells here were empty boxes at 390 and at 1280 from 2026-08-08 until 2026-08-09, while the
gap sweep that put this page at parity counted their 39 children and passed. An element count
reads a shut dialog exactly as it reads an open one.
What stands here now is .bet-panel itself, sliced whole out of
event-detail-multi.html, the richest of the eleven at 38 elements: the head
and its hint, the chosen outcome with its Change link, the pair, the amount row with the wallet
figure beside it, the four quick chips, the two lines, the outcome PAIR and the confirm.
Two things differ from the product, and the second one was a defect before
it was a difference. The panel is display:none below 760, so the cell declares
it visible in order to be a specimen at both widths, the same bargain the stand made for the
bottom bar. And the panel stands in .ed-layout, its own container, held in the
row direction: .bet-panel sizes itself with flex:0 0 322px, and a
flex basis is a width in a row and a height in a column. Dropped into the stand's column
cell it drew 353 x 322 with overflow:clip cutting the rest off, against 322 x
558 in the product. Its width here is the product's, untouched.
The panel used to print Potential payout $13.16 while both
sides read aria-pressed="false". That figure is 5 / 0.38, the YES price,
computed from a side the reader had not chosen, so a person who meant NO read a number that was
not theirs: NO at 62% pays $8.06. It was also the only coloured figure on the plate, in
--text-brass, which spent the accent on the upside and left the downside with no
ink anywhere. So there are two faces here and this is the first one: the instruction
stands at body scale where the numbers were, the two lines that are true whatever the reader
picks stay, and the Confirm is held. docs/backlog.md 180.
The held Confirm is the one disabled control in this system that changes
ROLE rather than strength, and it had to. Every other disabled control takes
--opacity-disabled, .45, which works because the control was already quiet. The
primary is a brass gradient, and 45 per cent of the one lit surface on the plate still reads as
the live action, so a reader who cannot yet act was looking at the thing that looked most
actionable. Here it drops the fill and takes the control ground with muted ink, measured at
5.49:1 against that ground and opacity:1, because a second dimming on top of
a role change reads as a rendering fault. It is a <button> and not a
link. The product carried <a href="event-detail-bet-processing.html"
aria-disabled="true"> until 2026-08-17. It did not actually navigate, because those
screens carry a script that calls preventDefault() on a click inside
[aria-disabled="true"]; the change stands because a control that is not a destination
should not be a link, and because safety should not rest on a script that four of the eight
surfaces happen to carry. aria-disabled stays rather than the property, for
the reason components/button.css gives, and aria-describedby points at
the instruction so the reason it is held is reachable and not only visible.
The argument was that a dock cannot stand on a page also read at 1280,
because it is display:none above 760. That is true of the panel above it in
exactly the same way and in the opposite direction, and the kit had already answered it once:
.tk-show-nav pins the bottom bar visible on the one page where the bar is not the
subject. Here all three faces ARE the subject, so both take the bargain and both say what
it costs.
Counted across the eight until 2026-08-16: four docks CHOSE and four
CONFIRMED, and this page argued they were two shapes rather than a long and a short form of
one. They were one shape and a symptom. The confirmer stood on the four bet-state screens,
and those four were the screens with no sheet: the panel is display:none below 760,
so on a phone the dock was the only thing that rendered and it had to carry the stake, the payout
and a Confirm by itself. What it could not carry was the state. "Registering your bet
on-chain" never appeared, nor did "Your bet did not register on-chain. No funds were taken", nor
the insufficient-balance guard while the same bar offered a $5 bet against a $3 balance, nor the
price reconcile that is the reason the whole payout model was chosen. The bar said
Confirm bet through all four.
All 8 docks are the chooser now, two sides carrying
data-open-sheet, and pressing either one is the only way a phone reaches the bet
panel at all. This section is kept at its full length on purpose: a page that recorded a
difference as a design decision, and was wrong about which of the two it was, is worth more than
a page that quietly agrees with today.
The chooser, from event-detail.html: 4 elements, on the
four plain detail screens. The multi-outcome pair names the outcome in the button, JD Vance
YES, because on that screen YES alone would not say which of five.
The confirmer, and it is worn by nothing since 2026-08-16. It stood on
the four bet-state screens and had 7 elements: the same bar, the same two sides, plus the stake,
its payout and a Confirm of its own. This is the second kind of zero, not the first: the
rules in betpanel.css are whole and the markup is what went, which is
.icon-btn-lift's case and not account.css's. It is drawn here rather
than deleted so that the zero is a thing a reader can see, next to the reason it is a
zero.
Two things differ here, not one: the dock is declared visible, as the
panel is, and it is pinned static, because position:fixed;bottom:var(--bottom-nav-h) is
a claim about a window and not about a cell. It read sticky;bottom:52px until
2026-08-16, and both halves of that were wrong: sticky gave up at the footer, and 52 was written
to clear a bottom nav measuring 56. Label muted, figure bright in the
.dock-meta, which is the same ranking the card's meta row uses, and the reason it is
stated in betpanel.css at all is that without it both halves inherit body text and
the two read as one sentence.
The level and its reason stay on the organisms page. What needs the room here is the worst of the three pinned-rail defects in this product, and a hover that was alive in one theme only.
| face | worn | at 390 | at 1280 |
|---|---|---|---|
.bet-panel | 11 | 0x0, display:none | 322x273 to 322x558, pinned |
.bet-dock | 8 | 379x68, fixed at the foot | 0x0, display:none |
.bet-sheet | 8 | 379x529 and 379x623 | 560x529 and 560x623 |
The panel and the dock are the same control at two widths and neither ever sees the other. A reading taken at one width reports the other as missing, which is what the skeleton page had to correct in the opposite direction: six marks read 0x0 at 390 because they stand inside this panel.
The sheet is a dialog, so it renders at both widths, and it is the phone's answer to the panel: the dock is a summary of the bet and a button, and tapping it opens the whole control.
The numbers in this table are the product's and the two specimens above are not measured by it, because both of them are declared visible by the stand in order to stand at all. What the table says is what the SCREENS do, which is the fact worth keeping: a person on a phone never sees the panel and a person at a desk never sees the dock.
Pinned at 120px and 555px tall on a multi-outcome event, this panel needs 676px of window. Below that, the Confirm button at the foot of it is off the bottom of the screen with nothing able to bring it back, because the page scrolls and a pinned box does not.
Three components in this product had the same defect on the same afternoon: the sub-category rail, the contents rail and this one. This is the worst of the three, because the part left out of reach is the ACTION. A rail hides two rows of navigation; this hides the button that places the bet.
The cap is written in small-viewport units with a viewport-unit line above it as a fallback, not as a second opinion: the tall viewport is the wrong one, because a browser that hides its chrome on scroll would put the foot of the panel back under the fold.
The specimen that stood here was not the product's sheet. It asked for "Your stake" against the product's "Amount", it printed one line called "If YES" against the product's three, it had three quick chips against four, and it carried a sentence about fees that appears on no screen. Six differences, and every one of them read as a plausible bet sheet, which is exactly why a specimen is copied and not composed.
What stands here now is the sheet from event-detail-multi.html,
39 elements, the richest of the four. Beside the panel above it the point is visible in
one look: the same control, plus a grab handle, minus nothing. The head, the outcome, the
pair, the amount, the chips, the three lines and the confirm are the same blocks in the same
order, which is why one file draws both.
The sheet has the same two shapes the card has, and for the same reason.
On the two binary screens it is 34 elements: no "Your outcome" label, no
.bp-selected row and no Change link, because with one question there is nothing to
choose between and nothing to go back to. Head, pair, amount, lines, confirm. The five elements
the multi sheet adds are that row, which is the same five the panel adds, which is the whole
difference between the two.
Two things differ from the product and this page has always said so: it
is open rather than showModal(), so there is no top layer and no
backdrop, and it is pinned into the flow. Everything inside is
components/betpanel.css untouched.
One difference here is the product's and not the stand's. The sheet
confirms with .btn-lg at 56 and the panel confirms with .btn-md at 48,
the same action twice at two sizes. On a phone that is defensible, since the sheet IS the phone's
face. It is written down rather than fixed because the two are never on screen together and
nothing in the system says which one a primary action should be.
The hover border read a role that is the LIT LIP of an emboss, which the light theme takes to a 70 per cent white so a lip has enough light on pale stone. As a hover BORDER on a chalk control that is a 70 per cent white line on a near-white ground: 1.02:1, so in daylight the only feedback left was the ink.
A lip role is not an edge role. The system already has the edge one, and the two look interchangeable in the dark and are not.
It is the second the same pass found. The first is on the hero, and it is worse.
The two sides are yes / no's now, as the trader's face of the outcome atom, neutral at rest because a chooser states the CHOICE and not the market. That argument was written in this file and it moved with the rules rather than staying here as a second copy.
What stayed is how two sides divide a row, and the odds figure inside each one: the percentage is the panel's DATUM rather than the control's face, the way an event photograph is the card's content. Whoever owns the odds owns how they are set.
Both press mechanisms travelled too, and both were measured rather than chosen: an unselected side is not an outcome control, so pressing it in green would invent a colour it does not have; a selected side has 0.14 of contrast to spend, so it goes down by depth instead.
Its own width query: 760 DETAIL. This is the component the DETAIL rung is named for. Below 760 the panel does not exist and the dock does; at 760 the panel becomes a flex:0 0 322px sticky column beside the content, with its own scroll and a height of the viewport less the header. 322px is a fixed basis in a row, which is why the specimen has to stand in a row: in a column that same basis is a HEIGHT, and the stand drew it 353 x 322 with the rest clipped off before that was understood.
The panel quotes the amount in the box, not an infinitesimal bet.
Filling a whole bet at the market's quote hands the buyer the slippage, and that give-away breaks
even at b = S(1-p)/(2fp), so it is unbounded as the quote nears either end and
unbounded at any b while the commission is 0, which is what the first release ships.
PRODUCT.md Liquidity and risk, docs/backlog.md 216.
The row is written by the script and removed by it, because a line
restating the number on the button three inches above it is a second answer to a question already
answered. At the product's $5 default it never appears: measured at b = 1000
against every price the shipped catalog carries, the size-adjusted quote rounds to the same whole
per cent as the market quote on 19 of 19. It first differs at $25, by one point, which is
the specimen above and the only screen in the product that draws it,
event-detail-bet-ready.html.
The figure shown is what the figures are computed from. The quote is rounded to the displayed whole per cent and the payout is the stake divided by THAT, so $25 at 39 is $64.10 and a reader doing the arithmetic by hand gets the number on the screen. The residual the rounding leaves is smaller than the fee at every size the product accepts. And the sentence that was read as forbidding this is the one that permits it: the shipped line ends "between the panel and the bet", which scopes the promise to an interval and not to size.
A pinned box is capped to the window. Especially this one, where what falls off the bottom is the action.
A role means what its name says. A lip is not an edge, and the two are indistinguishable in one theme.
An argument travels with the rules it justifies. Left behind, it becomes a second copy that can disagree with the file that now decides.
Never pin the control that places the bet without capping it. 676px of window, and below that Confirm is unreachable.
Never take a hover colour from a role built for depth. 1.02:1 in daylight, and it shipped.
Never colour a side before it is chosen. It tells a person they have committed to something they have not.
The level and its reason: the organisms
page. The stylesheet: components/betpanel.css. The two sides:
yes / no. The field: input. The chips beside
it: quick amounts. The sheet it opens as:
dialog. The other two capped rails:
category nav and contents.