Bet panel

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.

3 faces, all 3 shown 0x0 at the other width capped to the window 3 press mechanisms

The panel, whole

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.

Vault, dark
Daylight, light

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.

And before a side is picked the block has no figures in it at all

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.

Vault, dark
Daylight, light

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 dock was two docks and is one, and the second was a phone with nowhere to put a state

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.

Vault, dark
Daylight, light

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.

Vault, dark
$5 to win$13.16 Confirm bet
Daylight, light
$5 to win$13.16 Confirm bet

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.

What this page is for

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.

Three faces, each absent where the others stand

facewornat 390at 1280
.bet-panel110x0, display:none322x273 to 322x558, pinned
.bet-dock8379x68, fixed at the foot0x0, display:none
.bet-sheet8379x529 and 379x623560x529 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.

Capped to the window, and this is the worst of the three

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 sheet, which is the panel again with a handle on it

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.

Vault, darkDaylight, light

Place your bet

YES selected
Your outcome
JD Vance 41%Change
Amount$92.00 cash
$
Fee (1.5% of your bet)$0.08
Total to pay$5.08
If YES wins, your side$12.20
If NO wins$0.00

$1 minimum, no maximum. The price you see is the price you get.

Place your bet

YES selected
Your outcome
JD Vance 41%Change
Amount$92.00 cash
$
Fee (1.5% of your bet)$0.08
Total to pay$5.08
If YES wins, your side$12.20
If NO wins$0.00

$1 minimum, no maximum. The price you see is the price you get.

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.

A hover alive in one theme only, and it was the second of two

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 sides left, and the argument travelled with them

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.

What it does with width

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.

A fourth line that is there only when the bet moved the price

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.

Vault, darkDaylight, light

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.

The rule

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.

The anti-rule

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.

Where the rest of it is

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.