Yes / No

Level 1, and the PAIR is the control. Two halves that state one market's two sides and cannot exist apart: there is no such thing as a YES in this product without the NO beside it. 116 pairs and 232 halves on 14 painted screens, plus 44 trader picks on 10. Measured 2026-08-08 in a browser, at 390 and 1280.

116 pairs 232 halves 4 faces 44 tall, unconditionally 0 disabled

What this page is for

The level and the reason for it stay on the atoms page. What needs the room here is that this atom has two families of face, not two faces: a SPECTATOR's pair that states a market, and a TRADER's chooser that states a choice. They never appear together, they are drawn from opposite ends of the palette, and the shelf can only show one of them.

And like chip, a single specimen misleads here: half a pair is not a small version of the control, it is the half that carries no information.

The spectator's pair: it states the market

full, 64 placements, on a card and in the hero

Vault, darkDaylight, light

compact, 42 placements, in a card's option row

Vault, darkDaylight, light

Same two colours, 11px instead of 12, and it is a <span> because it stands inline in a row of text. Nothing else changes, including the height.

the outcome list, 10 placements, and here it is a CHOICE

Vault, darkDaylight, light
JD Vance41%
Donald Trump22%
Nikki Haley9%
JD Vance41%
Donald Trump22%
Nikki Haley9%

Same class, different ground: on a multi-outcome market the pair rests on the quiet control colour and the chosen side goes solid, so the state is the whole difference between the two. It rested on a SOFT outcome tint until 2026-08-16, which meant chosen and unchosen differed only in how much of the same colour was showing, and that is the weakest signal a state can be given. Forty-two of the 52 compact pairs are the first kind and ten are this one, and the difference is not a modifier: it is the list around them, because in a list of candidates a pair is something you answer rather than something you read.

A side is a POSITION IN THE PAIR, and the day it was a fact about a link

Look at the two markups. On a card the halves are wrapped: <a><button>YES</button></a>, because the whole card links to the event. In an outcome list they are bare <button>s, because there is nowhere to go.

Every colour rule used to hang off > a. So a pair whose buttons are not inside an anchor got no color from anywhere and fell back to the User Agent's buttontext: near black on a graphite card, 1.42:1, on four screens. Same shape as the 992 links that rendered in the browser's blue, and the same sentence covers both: A MISSING COLOUR IS A COLOUR. A component has to say what it is whatever markup it stands in.

Every selector is written twice now, > a:first-of-type button and > button:first-of-type, and the pair of them is what the sentence in the heading means.

The trader's chooser: it states the choice

Vault, darkDaylight, light

the same chooser with NO taken, and until 2026-08-15 no screen in this repository had ever drawn it

Vault, darkDaylight, light

Five rules in yesno.css draw a chosen NO and not one of them could fire. Read in the DOM across all three trees on 2026-08-15, .sel and .no had never once stood on the same element: 127 chosen sides in the paint, 24 in the grey and 39 on this stand, and every one of them YES. The pair is symmetric and half of it had never been rendered, so half of it had never been measured either, which is this repository's whole method turned off for one control.

It was the SCREENS and not the stylesheet, and the proof is that the grey tree agreed with the paint. A colour layer that had lost a state would show the state in grey and not in colour; both trees showed only YES, so the tree depicted one path. The fix was one screen in both trees, event-detail-bet-processing.html, chosen because its panel is mid-submit and carries no payout to keep in step: the pick moves in the panel and in the sticky dock, the dock's figure goes from $13.16 to $8.06 because $5 at 62 per cent pays that, and the YES picture inside the how-it-works sheet stays YES because it is a picture and not this person's bet. The route already existed: backlog 143 gave every card ?side=yes and ?side=no, 212 anchors each, so the product had been promising an arrival the tree never drew.

And rendering it for the first time is what let it be measured. The chosen NO is --text-on-no on --outcome-no at 4.64:1, against the chosen YES at 6.42:1. Both clear AA for body text; the NO side is the tighter of the two and now has a number.

It rests on the system's quiet ground and not in green and red, and components/tokens.css wrote the reason beside the token it is not using: the tinted fill is "the tinted YES button (spectator, not trader)". A side pressed in green would be inventing a colour the control does not have and telling a person the side is chosen before it is.

Two faces, and they never coexist: .yesno-pick in the panel and the sheet, .yesno-pick-bar in the sticky dock below 760. Measured, each is absent where the other stands: 16 picks read 0x0 at 390 and 16 bars read 0x0 at 1280. Four more are <span>s rather than buttons, on the two loading screens, where the shape of the control stands in for the control.

facewornat 390at 1280
.yesno-pick, in the sheet8166x71256x71
.yesno-pick, in the desktop panel160x0140x71
.yesno-pick-bar, in the dock1690x51 and 174x510x0

The chosen side is ONE answer at both widths, and it was two until 2026-08-06. The panel and the option list filled it solid; the dock bar used a strong fill with a lit ink. Both cleared the contrast floor and no file said why the same control should differ at two widths when the bar IS the panel below 760. Two of the three placements were solid, and the third is now: a person choosing a side on a phone and a person choosing it on a desktop are choosing the same thing.

Three press mechanisms, and this control needed the third one invented

The system's neutral press settles a control onto --bg-pressed. On a filled outcome side that would lie: hold a green YES down, the outcome colour leaves under the finger, and it reads as "it let go", which is the opposite of what holding YES means.

surfacehow it goes down
a quiet controlsettles onto --bg-pressed, one step deeper in both themes
a brass gradientreverses its own angle
a filled colourgoes down by DEPTH: an inset shade at the top edge, and the ink keeps the exact ground it was measured on

The third one exists because of a number with 0.14 of room in it. --text-on-no over --outcome-no is 4.64:1, which is the 4.5 floor with 0.14 to spare. Pressing it by stepping the ground down through its own darker role spends more than that at every strength a person could see: 92 per cent is already 4.48:1, 82 per cent is 4.29:1, and a mix small enough to pass is a mix nobody notices. The YES side had the room and was deliberately NOT shipped alone, because a YES that darkens beside a NO that does not reads as a broken NO.

The unfilled sides take the ordinary press, and both are restated rather than left to the hover, because a touch screen never hovers: on a phone the pressed side would otherwise keep its rest edge.

The boxes, and the one axis that is short

facehalvesat 390at 1280
full128130x44, and 147x44 in the hero148x44 and 207x44
compact8446x44 and 43x4446x44 and 43x44
outcome list2046x44 and 43x4446x44 and 43x44

44 tall everywhere, with a mouse and with a finger, at both widths, and none of it comes from the touch floor in base.css: .yesno button writes min-height:var(--control-44) unconditionally. A media block used to restate that inside a 640px query, which read as the target is a mobile concern. It is not, and the block was deleted rather than corrected.

The 43 is the word NO. It measures 42.7 wide, so it stands 44 tall and under 44 across, and it is one of the 212 targets in that shape across the product. A word's box comes from the word, and widening every one of them is a layout decision about six components rather than a floor. docs/backlog.md 50.

What has no rule, and why that is the honest answer

No disabled state. 241 pairs across all three trees and not one of them is disabled: there is no closed-market screen that greys the pair. A rule for it would be a guess about a screen that does not exist, and it would be written in the one place nobody would think to check when the screen is drawn.

No focus rule either, and this one is a positive reading rather than a gap. base.css draws the ring once and outline-offset puts it 2px OUTSIDE the button, so even on the filled green and the filled red the ring stands on the row behind the control. The ground it has to survive is the card, which it already does.

What it does with width

One query, at DESK, and it is the half of the wrap that says what the pair does with the second line. options.css decides the row wraps; below the rung this file gives .opt-row .yesno.compact a whole line of its own and lets its two halves share it, so the pair goes from 46 and 42.7px side by side with the name to 268 apiece under it.

It stays on the WINDOW, and that was measured rather than assumed, backlog 145. Forced into the inline layout at every width from 320 to 1600: the two halves measure 46 and 42.7px at every container width from 251 to 628, because they are content-sized and the name absorbs the rest. So the container cannot answer the question this rule asks. What the container does decide is whether the NAME clips, which happens below about 260, and keying the wrap there would put the cramped pair on every phone in the product, with one of the two halves under the 44px floor this project set itself. A non-separable rule is what it looks like when the window carries information the container does not have.

The rule

The pair is the control. Not two buttons that happen to sit together: one thing with two sides, which is why every selector here is positional and why nothing on this page shows one half by itself.

Green and red are the OUTCOME and never an opinion. A spectator's pair states which side the market is on. A trader's chooser states which side YOU are on, and until you have chosen it has no outcome colour at all.

A press is paid for out of whatever the surface has left. Where the contrast is spent, the depth pays.

The anti-rule

Never hang a colour off the markup around the control. Every colour here once hung off > a, and the pairs that are not wrapped in a link rendered at 1.42:1 on four screens.

Never fill a trader's side before it is chosen. It tells a person they have committed to something they have not.

Never ship half a pair's state. The YES side had the contrast for a darkening press and the NO side did not, and a YES that darkens beside a NO that does not reads as a broken NO.

Never write a target inside a width query. A finger is not a mobile concern, and the deleted block said it was.

Where the rest of it is

The level and its reason: the atoms page. The stylesheet and the argument for every value: components/yesno.css. The panel, the sheet and the dock that hold the trader's face, plus the odds figure inside each side: components/betpanel.css. The colour decision, once for both families: DESIGN.md.