/* Bet Better /odds scene engine (Round 9). Built ONLY from the terminal's tokens and classes. © Bet Better. */
#obtStage .obt-bento.r9-grid{display:grid;grid-auto-flow:row dense;grid-template-columns:repeat(3,minmax(0,1fr));grid-template-rows:none!important;grid-auto-rows:auto!important;gap:8px;align-content:start!important;height:auto!important;max-height:none!important;overflow:visible!important}
#obtStage .obt-bento.r9-grid .bc{grid-column:auto!important;grid-row:auto!important;height:auto!important;max-height:none!important;min-height:0!important;overflow:visible!important;margin:0}
#obtStage .obt-bento.r9-grid .bc.span2{grid-column:span 2!important}
#obtStage .obt-bento.r9-grid .bc.span3{grid-column:1/-1!important}
#obtStage .obt-bento.r9-grid .bc .bb{flex:none!important;overflow:visible!important;max-height:none!important;height:auto!important}
#obtStage .obt-bento.r9-grid .bc.base .bb{overflow:auto!important;max-height:420px!important}
.r9-grid .bh .lab.r9-sig{color:var(--ink-faint);margin-left:auto;letter-spacing:.1em}
/* [design law 2026-09-13] the sig chip is always the faint ink: no green / gold / red tags in the console (the classes stay for meaning) */
.r9-grid .bh .lab.r9-sig.g,.r9-grid .bh .lab.r9-sig.w,.r9-grid .bh .lab.r9-sig.r{color:var(--ink-faint)}
/* [live walk 2026-09-13] in a quarter-width helper the label and the sig chip crowded each other: let the header wrap, sig under the label */
.r9-grid .bc:not(.r9-leadcell):not(.span2):not(.span3) .bh{flex-wrap:wrap;row-gap:2px}
.r9-grid .bc:not(.r9-leadcell):not(.span2):not(.span3) .bh .lab.r9-sig{margin-left:0;flex-basis:100%;letter-spacing:.06em}
.r9-lead{font-family:var(--ui);font-size:.86rem;color:var(--ink);line-height:1.45;margin:0 0 7px}
.r9-lead b{color:var(--ink)}
.r9-grid .obt-chart{height:auto!important;width:100%;border:none;background:transparent;display:block}
.r9-grid .obt-chart.r9-field{height:auto;max-height:260px;aspect-ratio:auto}.r9-grid .obt-chart.r9-tl{height:80px}.r9-grid .obt-chart.r9-mirror{height:auto}
.r9-two{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.r9-rows{display:flex;flex-direction:column;gap:5px;margin-top:6px}
.r9-row{display:grid;grid-template-columns:8em 1fr auto;gap:8px;align-items:center;font-family:var(--mono);font-size:.62rem;color:var(--ink-dim)}
.r9-row .bar{height:6px;background:rgba(128,150,180,.14);position:relative}
.r9-row .bar i{position:absolute;left:0;top:0;bottom:0;background:var(--action-hi)}
.r9-row .bar i.g{background:var(--model)}.r9-row .bar i.o{background:var(--gold)}.r9-row .bar i.r{background:#E07070}
.r9-row .v{color:var(--ink);white-space:nowrap}.r9-row .v.g{color:var(--model)}
.r9-ticks{display:flex;gap:3px;flex-wrap:wrap;margin:6px 0 4px}
.r9-ticks i{width:15px;height:15px;display:grid;place-items:center;font-family:var(--mono);font-size:.56rem;font-weight:700;font-style:normal;color:var(--ink-faint);background:rgba(128,150,180,.12)}
.r9-ticks i.w{background:var(--model);color:#06251A}.r9-ticks i.u{background:var(--action-hi);color:#06131F}
.r9-heat{display:grid;gap:3px;margin-top:4px;font-family:var(--mono);font-size:.62rem;color:var(--ink-dim);align-items:center}
.r9-heat .h{font-size:.52rem;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-faint);text-align:center}
.r9-heat .c{height:22px;display:grid;place-items:center;color:var(--ink);background:rgba(128,150,180,.08)}
.r9-heat .c.g1{background:rgba(52,211,153,.32)}.r9-heat .c.g2{background:rgba(52,211,153,.16)}.r9-heat .c.r1{background:rgba(224,112,112,.32)}.r9-heat .c.r2{background:rgba(224,112,112,.16)}
.r9-list{display:flex;flex-direction:column;gap:5px;margin-top:4px;font-family:var(--ui);font-size:.76rem;color:var(--ink-dim)}
.r9-list div{display:flex;justify-content:space-between;gap:8px;align-items:center}
.r9-list .st{font-family:var(--mono);font-size:.58rem;letter-spacing:.06em;text-transform:uppercase;padding:1px 6px;white-space:normal;text-align:right;max-width:58%;border:1px solid var(--line);color:var(--ink-faint)}
.r9-list .st.out{color:#E07070;border-color:rgba(224,112,112,.5)}.r9-list .st.q{color:var(--gold);border-color:rgba(245,179,1,.5)}.r9-list .st.in{color:var(--model);border-color:rgba(52,211,153,.5)}
.r9-legend{display:flex;gap:12px;font-family:var(--mono);font-size:.62rem;letter-spacing:.06em;color:var(--ink-faint);margin-top:6px;flex-wrap:wrap}
.r9-legend i{display:inline-block;width:10px;height:3px;background:var(--action-hi);vertical-align:middle;margin-right:5px}
.r9-legend i.g{background:var(--model)}.r9-legend i.o{background:var(--gold)}.r9-legend i.d{background:var(--ink-faint)}
.r9-chips{margin:8px 0 0}
.r9-chips .obt-chip{cursor:pointer;background:transparent}
.r9-chips .obt-chip.on{color:var(--ink);border-color:var(--action-hi)}
.r9-gauges{display:grid;grid-template-columns:1fr 1fr;gap:6px 14px}
.r9-gauge svg{width:100%;height:auto;display:block}
.r9-condrow{display:grid;grid-template-columns:120px 1fr;gap:12px;align-items:start}
.r9-wind svg{width:120px;height:120px;display:block}
.r9-lc{border:1px solid var(--line);padding:6px 8px}
.r9-lch{font-family:var(--mono);font-size:.6rem;letter-spacing:.1em;text-transform:uppercase;color:var(--model);margin-bottom:5px;display:flex;justify-content:space-between}
.r9-lch i{font-style:normal;color:var(--ink-faint)}
.r9-lcr{display:flex;gap:4px;flex-wrap:wrap;justify-content:center;margin:3px 0}
.r9-lcp{font-family:var(--ui);font-size:.68rem;color:var(--ink);background:rgba(128,150,180,.1);padding:3px 7px;display:inline-flex;gap:5px;align-items:baseline;white-space:nowrap}
.r9-lcp b{font-family:var(--mono);font-size:.54rem;color:var(--ink-faint);letter-spacing:.06em}
.r9-lcp small{font-family:var(--mono);font-size:.52rem;color:var(--ink-faint)}
.r9-lcp.out{text-decoration:line-through;opacity:.55}.r9-lcp.new{box-shadow:inset 0 0 0 1px var(--model)}.r9-lcp.hi{box-shadow:inset 0 0 0 1px var(--action-hi)}
.r9-depth{display:flex;flex-direction:column;gap:4px;font-family:var(--ui);font-size:.72rem}
.r9-dg{display:flex;gap:6px;align-items:baseline;flex-wrap:wrap}
.r9-dg b{font-family:var(--mono);font-size:.56rem;letter-spacing:.1em;color:var(--ink-faint);min-width:2.6em}
.r9-dg span{color:var(--ink-dim)}.r9-dg span:first-of-type{color:var(--ink)}.r9-dg span.out{text-decoration:line-through;color:#E07070}.r9-dg span.q{color:var(--gold)}
.r9-pair{display:flex;gap:10px;align-items:flex-end;margin-top:6px}
.obt-facts .fact{font-family:var(--ui);font-size:.8rem;color:var(--ink)}
.r9-skel{min-height:120px;background:linear-gradient(90deg,rgba(128,150,180,.06),rgba(128,150,180,.12),rgba(128,150,180,.06));background-size:200% 100%;animation:r9sk 1.2s linear infinite}
@keyframes r9sk{to{background-position:-200% 0}}
@media (prefers-reduced-motion:reduce){.r9-skel{animation:none}}
/* right column */
#obtTiles.r9-pbi{display:flex!important;flex-direction:column;gap:0;padding:0;flex:1 1 auto!important;height:auto!important;max-height:none!important;overflow-y:auto}
#obtTiles.r9-pbi ~ #obtRailFoot{display:none!important}
#obtTiles.r9-pbi > *{flex:none}
.r9-head{display:flex;align-items:center;gap:8px;padding:9px 10px;border-bottom:1px solid var(--line)}
.r9-head .av{width:24px;height:24px;border-radius:50%;background:var(--action);display:grid;place-items:center;font-family:var(--mono);font-size:.6rem;font-weight:700;color:#fff;flex:none}
.r9-head .who{font-family:var(--ui);font-weight:700;font-size:.8rem;color:var(--ink);line-height:1.1}
.r9-head .me{font-family:var(--mono);font-size:.54rem;color:var(--ink-faint);letter-spacing:.06em}
.r9-head .pro{margin-left:auto;font-family:var(--mono);font-size:.54rem;letter-spacing:.12em;color:var(--gold);border:1px solid rgba(245,179,1,.5);padding:2px 6px}
.r9-head .pro.lock{color:var(--ink-faint);border-color:var(--line)}
#obtTiles.r9-pbi .obt-tile.r9t{display:flex;flex-direction:column;align-items:stretch;min-height:0;border-left:3px solid var(--line);border-bottom:1px solid var(--line);border-top:none;border-right:none;background:transparent;padding:8px 10px;gap:3px;cursor:default;transform:none;box-shadow:none}
#obtTiles.r9-pbi .obt-tile.r9t .tl{display:block;flex:none;white-space:normal;font-size:.56rem;letter-spacing:.1em}
#obtTiles.r9-pbi .obt-tile.r9t .hl{display:block;flex:none;white-space:normal;overflow:visible;text-overflow:clip;max-width:none;font-size:.9rem;line-height:1.25}
#obtTiles.r9-pbi .obt-tile.r9t .sb{display:block;flex:none;white-space:normal;overflow:visible;font-size:.72rem;line-height:1.4;color:var(--ink-dim);-webkit-line-clamp:unset}
#obtTiles.r9-pbi .obt-tile.r9t .hl .g{color:var(--model)}
#obtTiles.r9-pbi .obt-tile.r9t.lead{background:rgba(52,211,153,.06);border-left-color:var(--model)}
#obtTiles.r9-pbi .obt-tile.r9t.lead .hl{color:var(--model);font-size:1rem}
#obtTiles.r9-pbi .obt-tile.r9t.wait .hl{color:var(--gold)}
.r9-mirror{display:flex;gap:3px;align-items:flex-end;height:22px;margin:4px 0 2px}
.r9-mirror i{width:12px;height:9px;background:rgba(128,150,180,.14)}.r9-mirror i.w{background:var(--model);height:22px}
.r9-lim{display:flex;gap:6px;align-items:center;font-family:var(--mono);font-size:.6rem;color:var(--ink-dim);margin-top:4px}
.r9-lim .track{flex:1;height:5px;background:rgba(128,150,180,.14);position:relative}.r9-lim .track i{position:absolute;left:0;top:0;bottom:0;background:var(--action-hi)}
.r9-btn{font-family:var(--mono);font-size:.56rem;letter-spacing:.08em;text-transform:uppercase;padding:4px 8px;border:1px solid var(--line);color:var(--ink);background:transparent;white-space:nowrap;cursor:pointer}
.r9-btn.p{background:var(--action);border-color:var(--action);color:#fff;font-weight:700}.r9-btn.g{color:var(--model);border-color:rgba(52,211,153,.5)}
.r9-btn:focus-visible{outline:2px solid var(--action-hi);outline-offset:1px}
.r9-tr{display:flex;justify-content:space-between;align-items:center;gap:8px}.r9-tr.wrap{flex-wrap:wrap}
.r9-ask .q{font-family:var(--ui);font-size:.7rem;color:var(--ink-faint);padding:4px 0}
.r9-ask .a{font-family:var(--ui);font-size:.72rem;color:var(--ink-dim);border-left:2px solid var(--action-hi);padding:3px 8px;line-height:1.4;margin-top:4px}
.r9-ask .a small{display:block;font-family:var(--mono);font-size:.52rem;color:var(--ink-faint);margin-top:4px;letter-spacing:.04em}
.r9-ask .in{display:flex;gap:5px;margin-top:6px}
.r9-ask input{flex:1;min-width:0;background:var(--panel);border:1px solid var(--line);color:var(--ink);font-family:var(--ui);font-size:.7rem;padding:5px 7px}
.r9-rg{padding:7px 10px;font-family:var(--ui);font-size:.54rem;color:var(--ink-faint);border-top:1px solid var(--line);display:flex;justify-content:space-between;gap:6px;flex-wrap:wrap;margin-top:auto}   /* [2026-09-14 integration] one-typeface law: the helpline was the last mono on every tab */
.r9-rg b{color:var(--ink-dim)}
.r9-gate{margin:8px;border:1px solid var(--card-edge);background:var(--panel);padding:10px}
.r9-gate p{font-family:var(--ui);font-size:.76rem;color:var(--ink-dim);margin:0 0 8px;line-height:1.45}.r9-gate p b{color:var(--ink)}
.r9-lockwrap{filter:blur(3px);opacity:.5;pointer-events:none;user-select:none}
/* mobile: single column organs; the column becomes the "You" module */
@media (max-width:899px){#obtStage .obt-bento.r9-grid{grid-template-columns:1fr}#obtStage .obt-bento.r9-grid .bc.span2,#obtStage .obt-bento.r9-grid .bc.span3{grid-column:auto!important}.r9-two{grid-template-columns:1fr}.r9-condrow{grid-template-columns:1fr}.r9-row{grid-template-columns:6.5em 1fr auto}}

.r9-coach{display:flex;flex-direction:column;gap:2px;font-family:var(--ui);font-size:.74rem;color:var(--ink-dim)}
.r9-coach b{font-size:.9rem;color:var(--ink)}

.r9-in{width:6.5em;background:var(--panel);border:1px solid var(--line);color:var(--ink);font-family:var(--mono);font-size:.7rem;padding:4px 6px}
.obt-tile.t-you{--acc:var(--gold)}
#obtStage .obt-bento.r9-grid.r9-you{grid-template-columns:1fr;padding:0}
.r9-pbi-mobile{display:flex!important;flex-direction:column;grid-template-columns:none!important;padding:0!important;gap:0!important}
.r9-pbi-mobile .obt-tile.r9t{border-left:3px solid var(--line);border-bottom:1px solid var(--line);background:transparent;padding:10px 12px;gap:4px;display:flex;flex-direction:column;align-items:stretch;min-height:0}
.r9-pbi-mobile .obt-tile.r9t .tl{display:block;font-size:.58rem;letter-spacing:.1em}
.r9-pbi-mobile .obt-tile.r9t .hl{display:block;white-space:normal;font-size:1rem;max-width:none;overflow:visible}
.r9-pbi-mobile .obt-tile.r9t .sb{display:block;white-space:normal;font-size:.78rem;-webkit-line-clamp:unset;overflow:visible}
.r9-pbi-mobile .obt-tile.r9t.lead .hl{color:var(--model)}
.r9-pbi-mobile .obt-tile.r9t.wait .hl{color:var(--gold)}

@media (max-width:899px){
  #obtStage .obt-wsid.v39 .hr1{flex-wrap:wrap;row-gap:6px}
  #obtStage .obt-wsid.v39 .obt-build.v38{flex-wrap:wrap;max-width:100%;row-gap:6px}
  #obtStage .obt-wsid.v39 .obt-build.v38 select{max-width:100%;min-width:0}
  #obtStage .obt-wsid.v39 .hr2{white-space:normal;flex-wrap:wrap;row-gap:4px}
  #obtStage .obt-bento.r9-grid{gap:10px}
}
/* mobile guards (additive): the page must never scroll sideways; the top bar and game head shrink instead of overflowing */
@media (max-width:899px){
  html,body,.obt-page,.obt-app,.obt-deck{max-width:100vw;overflow-x:hidden}
  .obt-top{overflow:hidden;min-width:0}
  .obt-top .obt-stamp{min-width:0;max-width:34vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .obt-top input.obt-ctl{min-width:0;flex:1 1 auto;width:auto}
  .obt-gamehead{min-width:0;overflow:hidden}
  .obt-gamehead .obt-crumb{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1 1 auto}
  .obt-glens{flex-wrap:wrap;row-gap:6px}
  .obt-tiles{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .obt-tile{min-width:0}
  .obt-mboss{min-width:0;overflow:hidden}
  #obtStage,.obt-stage{max-width:100vw;overflow-x:hidden}
  #obtStage .obt-bento.r9-grid .bc{min-width:0;overflow:hidden!important}
}

/* ---- review round (09-10 evening): sticky game head inside the scrolling console ---- */
#obtStage{padding-top:0!important}
#obtStage .obt-wsid.v39{position:sticky;top:0;z-index:6;background:var(--panel);box-shadow:0 10px 16px -10px rgba(0,0,0,.65)}
#obtStage .obt-bento.r9-grid{padding-top:10px}
/* ---- PBI discoverability ---- */
.r9-pbi-title{display:flex;align-items:center;gap:8px;padding:8px 10px 6px;font-family:var(--mono);font-size:.6rem;letter-spacing:.14em;text-transform:uppercase;color:var(--gold);border-bottom:1px solid var(--line)}
.r9-pbi-title em{font-style:normal;font-size:.52rem;letter-spacing:.12em;padding:1px 5px;border:1px solid rgba(245,179,1,.55);color:var(--gold)}
.r9-gate-ul{margin:0 0 10px;padding:0 0 0 1.1em;font-family:var(--ui);font-size:.74rem;line-height:1.45;color:var(--ink-dim)}
.r9-gate-ul li{margin:0 0 3px}
.r9-guide{margin-top:10px;padding-top:8px;border-top:1px solid var(--line);font-family:var(--ui);font-size:.74rem;color:var(--ink-dim);line-height:1.45}
.r9-guide b{color:var(--ink)}.r9-guide ol{margin:6px 0 0;padding-left:1.2em}.r9-guide li{margin:0 0 4px}
.r9-gate .r9-btn{margin-bottom:4px}
#obtTiles.r9-spot{animation:r9spot 1.4s ease-in-out 3;outline:2px solid var(--gold);outline-offset:-2px}
@keyframes r9spot{0%,100%{box-shadow:inset 0 0 0 0 rgba(245,179,1,0)}50%{box-shadow:inset 0 0 0 3px rgba(245,179,1,.55),0 0 24px rgba(245,179,1,.35)}}
@media (prefers-reduced-motion:reduce){#obtTiles.r9-spot{animation:none}}
#obtBar .u-you i{color:var(--gold)}

/* ---- Personal Betting Intelligence (09-11 rebuild): typographic, hairlines, one accent ---- */
.r9-pbi-title{color:var(--ink-faint);font-size:.56rem;letter-spacing:.16em;padding:9px 12px 7px}
.r9-pbi-title em{color:var(--ink-faint);border-color:var(--line)}
.r9-head{padding:10px 12px}
.r9x{padding:10px 12px 12px;border-bottom:1px solid var(--line)}
.r9x-cap{display:flex;justify-content:space-between;gap:8px;align-items:baseline;font-family:var(--mono);font-size:.56rem;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-faint);margin:0 0 8px}
.r9x-cap span:last-child{letter-spacing:.06em;text-transform:none;text-align:right;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.r9x-read p{font-family:var(--ui);font-size:.82rem;line-height:1.5;color:var(--ink-dim);margin:0 0 7px}.r9x-read p:last-child{margin-bottom:0}.r9x-read b{color:var(--ink);font-weight:600}
.r9x-read .v{font-weight:700}.r9x-read .v.g{color:var(--model)}.r9x-read .v.y{color:var(--gold)}.r9x-read .v.r{color:#E07070}
.r9x-tabs{display:flex;flex-wrap:wrap;gap:0 12px;margin:0 0 6px;border-bottom:1px solid var(--line)}
.r9x-tab{background:none;border:none;border-bottom:2px solid transparent;margin-bottom:-1px;padding:3px 0 6px;font-family:var(--mono);font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-faint);cursor:pointer}
.r9x-tab.on{color:var(--ink);border-bottom-color:var(--gold)}.r9x-tab:focus-visible{outline:2px solid var(--action-hi);outline-offset:1px}
.r9x-table{display:grid;grid-template-columns:minmax(0,1fr) auto auto auto;gap:0 8px;font-variant-numeric:tabular-nums}
.r9x-row{display:contents}
.r9x-row > span{padding:5px 0;border-bottom:1px solid rgba(128,150,180,.10);font-family:var(--ui);font-size:.76rem;color:var(--ink-dim);min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.r9x-row .l{position:relative;padding-left:10px}.r9x-row .l small{font-family:var(--mono);font-size:.52rem;color:var(--ink-faint);margin-left:4px}
.r9x-row.me .l{color:var(--ink)}.r9x-row.me .l:before{content:'';position:absolute;left:0;top:11px;width:5px;height:5px;border-radius:50%;background:var(--gold)}
.r9x-row .n{font-family:var(--mono);font-size:.7rem;color:var(--ink);text-align:right}.r9x-row .n small{font-size:.52rem;color:var(--ink-faint)}
.r9x-row .m{font-family:var(--mono);font-size:.7rem;text-align:right}.r9x-row .m.g{color:var(--model)}.r9x-row .m.r{color:#E07070}
.r9x-row .tag{font-family:var(--mono);font-size:.5rem;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-faint);text-align:right}.r9x-row .tag.keep{color:var(--model)}.r9x-row .tag.leak{color:#E07070}
.r9x-foot{font-family:var(--mono);font-size:.52rem;letter-spacing:.06em;color:var(--ink-faint);margin-top:6px}.r9x-foot:before{content:'';display:inline-block;width:5px;height:5px;border-radius:50%;background:var(--gold);margin-right:5px;vertical-align:middle}
.r9x-lines{margin-top:10px}.r9x-lines p{font-family:var(--ui);font-size:.76rem;line-height:1.45;color:var(--ink-dim);margin:0 0 4px}.r9x-lines b{color:var(--ink);font-weight:600}
.r9x-quiet{font-family:var(--ui);font-size:.74rem;line-height:1.45;color:var(--ink-faint);margin:0}
.r9x-note{display:flex;gap:8px;align-items:flex-start;font-family:var(--ui);font-size:.78rem;line-height:1.45;color:var(--ink);margin:0 0 6px}
.r9x-note i{flex:none;width:6px;height:6px;border-radius:50%;background:var(--gold);margin-top:7px}.r9x-note.tilt i{background:#E07070}.r9x-note.debrief i{background:var(--action-hi)}.r9x-note.pace i{background:var(--gold)}
.r9x-tr{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-top:8px}.r9x-tr .r9x-quiet{flex:1 1 auto}.r9x-tr .r9-btn{flex:none}
.r9x-thread{display:flex;flex-direction:column;gap:6px;margin-bottom:6px}
.r9x-msg{font-family:var(--ui);font-size:.76rem;line-height:1.45}.r9x-msg.q{color:var(--ink-faint);padding-left:10px;border-left:2px solid var(--line)}.r9x-msg.a{color:var(--ink-dim);padding-left:10px;border-left:2px solid var(--gold)}
.r9x-msg small{display:block;font-family:var(--mono);font-size:.5rem;letter-spacing:.06em;color:var(--ink-faint);margin-top:3px}
.r9x-chips{display:flex;flex-wrap:wrap;gap:5px;margin:0 0 8px}
.r9x-chip{background:none;border:1px solid var(--line);color:var(--ink-dim);font-family:var(--ui);font-size:.68rem;padding:3px 8px;cursor:pointer}.r9x-chip:hover{color:var(--ink);border-color:var(--ink-faint)}
.r9x-in{display:flex;gap:5px}.r9x-in input{flex:1;min-width:0;background:var(--panel);border:1px solid var(--line);color:var(--ink);font-family:var(--ui);font-size:.74rem;padding:6px 8px}.r9x-in.tight input{width:5.5em;flex:none}
.r9x-week{font-family:var(--mono);font-size:.7rem;color:var(--ink-dim);display:grid;grid-template-columns:1fr auto;gap:6px 8px;align-items:center}.r9x-week .track{grid-column:1/-1}.r9x-week b{color:var(--ink)}.r9x-week .track{height:4px;background:rgba(128,150,180,.14);position:relative}.r9x-week .track i{position:absolute;left:0;top:0;bottom:0;background:var(--gold)}.r9x-week .left{font-size:.6rem;color:var(--ink-faint)}
.r9x-adds{margin:0 0 10px;padding-left:1.1em;font-family:var(--ui);font-size:.76rem;line-height:1.45;color:var(--ink-dim)}.r9x-adds li{margin:0 0 4px}
.r9x-btns{display:flex;flex-wrap:wrap;gap:6px}
.r9x.gate p{font-family:var(--ui);font-size:.78rem;line-height:1.45;color:var(--ink-dim);margin:0 0 8px}.r9x.gate p b{color:var(--ink)}
.r9-pbi-mobile .r9x{padding:12px 14px}

/* PBI column width: the intelligence column earns 280px on wide screens (the console keeps 3 organ columns) */
@media (min-width:1400px){.obt-app .obt-deck{grid-template-columns:60px 116px 240px minmax(0,1fr) 280px!important}}
@media (min-width:1700px){.obt-app .obt-deck{grid-template-columns:60px 116px 240px minmax(0,1fr) 320px!important}}

/* ---- direction One (09-11): one typeface, two colours, hairlines; the column is the whole right side ---- */
#obtTiles.r9-pbi{padding:0!important}
.r9o{display:flex;flex-direction:column;height:100%;min-height:0;font-family:var(--ui);font-size:13px;line-height:1.5;color:var(--ink);font-variant-numeric:tabular-nums}
#obtTiles.r9-pbi .r9o{flex:1 1 auto}
.r9o-tabs{display:flex;align-items:center;gap:18px;padding:14px 16px 10px;border-bottom:1px solid var(--line);flex:none}
.r9o-tabs button{background:none;border:none;padding:0;font:inherit;font-size:13px;color:var(--ink-faint);cursor:pointer}
.r9o-tabs button.on{color:var(--ink);font-weight:500}
.r9o-tabs button:focus-visible,.r9o button:focus-visible{outline:1px solid var(--ink-dim);outline-offset:3px}
.r9o-tabs .me{margin-left:auto;display:flex;align-items:center;gap:7px;font-size:11px;color:var(--ink-faint);min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.r9o-tabs .av{width:20px;height:20px;border-radius:50%;overflow:hidden;background:rgba(255,255,255,.06);display:grid;place-items:center;flex:none;padding:0}
.r9o-tabs .av img{width:20px;height:20px;display:block;object-fit:cover}.r9o-tabs .av i{font-style:normal;font-size:8px;color:var(--ink-dim);letter-spacing:.04em}
.r9o-body{flex:1 1 auto;min-height:0;overflow-y:auto;padding:14px 16px;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.12) transparent}
.r9o-body p{margin:0 0 10px}.r9o-body p:last-child{margin-bottom:0}
.r9o-body b{font-weight:500;color:var(--ink)}
.r9o-body .h{color:var(--ink-faint);font-size:11px;margin:0 0 6px}.r9o-body .h+.h{margin-top:-2px}
.r9o-body .q{color:var(--ink-faint);margin:14px 0 10px}
.r9o-body .a{color:var(--ink)}
.r9o-body .src,.r9o-body .dim{font-size:11px;color:var(--ink-faint)}.r9o-body .src{margin:-4px 0 14px}
.r9o-body .cur{display:inline-block;width:6px;height:12px;background:var(--ink-dim);vertical-align:-2px;margin-left:2px;animation:r9cur 1s steps(2) infinite}
@keyframes r9cur{to{opacity:0}}
@media (prefers-reduced-motion:reduce){.r9o-body .cur{animation:none}}
.r9o-body .qr{margin:4px 0 14px}.r9o-body .qr button,.r9o-body .links button,.r9o-body .vote button,.r9o-body .tog,.r9o-body .dims button{display:block;background:none;border:none;padding:2px 0;font:inherit;font-size:12px;color:var(--ink-faint);cursor:pointer;text-align:left}
.r9o-body .qr button:hover,.r9o-body .links button:hover,.r9o-body .vote button:hover,.r9o-body .dims button:hover{color:var(--ink)}
.r9o-body .links{display:flex;gap:16px;margin-top:6px}.r9o-body .links button{display:inline;text-decoration:underline;text-underline-offset:3px;color:var(--ink)}
.r9o-body .vote{display:flex;gap:14px;margin:-6px 0 12px}.r9o-body .vote button{display:inline}.r9o-body .vote button.on{color:var(--ink);text-decoration:underline;text-underline-offset:3px}
.r9o-body .dims{display:flex;flex-wrap:wrap;gap:0 12px;margin:0 0 8px}.r9o-body .dims button{display:inline;font-size:12px}.r9o-body .dims button.on{color:var(--ink)}
.r9o-body .tbl{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:0 14px;margin:0 0 16px}
.r9o-body .tbl>span{padding:5px 0;border-bottom:1px solid var(--line);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;color:var(--ink-dim);font-size:12.5px}
.r9o-body .tbl .me{color:var(--ink)}.r9o-body .tbl .n,.r9o-body .tbl .m{text-align:right}
/* ---- [WP-P7 2026-09-14] THE YOU TAB'S OWN THREE MARKS (src/03_pbi.js; spec PBI_TOPTIER_SPEC.md S8 + section 9) ----
   .lead  the dollars-first headline. One step up in size, the same typeface and the same ink as everything else:
          it leads by being first and by being the only number on its line, not by shouting.
   .hit   a count of the reader's own bets that landed; .be the break-even the prices they took set. The pair is the
          ICP law made visible, so they are drawn as a pair - the count in the reading ink, the break-even one step
          back, because the count is the news and the break-even is the ruler beside it.
   .cnt   a count that is not a claim (a month's bets, legs still running): plain body ink, no emphasis at all.
   In the table the break-even rides UNDER the count in the same cell, which is why .n becomes a two-line stack: a
   fourth column would have taken 60px out of a 280px rail and pushed the label into an ellipsis. */
.r9o-body .lead{font-size:16px;line-height:1.35;color:var(--ink);margin:0 0 10px}
.r9o-body .hit{font-weight:500;color:var(--ink)}
.r9o-body .be{font-weight:400;color:var(--ink-dim)}
.r9o-body .cnt{color:inherit}
.r9o-body .tbl .n{display:flex;flex-direction:column;align-items:flex-end;justify-content:center;gap:0;line-height:1.25}
.r9o-body .tbl .n small{display:block;font-size:11px;line-height:1.2;color:var(--ink-faint);white-space:nowrap}
.r9o-body .tbl .n .be{color:var(--ink-faint)}
.r9o-body .rows{margin:0 0 16px}.r9o-body .rows div{display:flex;justify-content:space-between;gap:12px;padding:5px 0;border-bottom:1px solid var(--line);color:var(--ink-dim);font-size:12.5px}.r9o-body .rows span:last-child{white-space:nowrap;color:var(--ink)}
.r9o-body .rows small{display:block;font-size:11px;color:var(--ink-faint)}
.r9o-body .tog{display:inline;text-decoration:underline;text-underline-offset:3px}.r9o-body .tog.on{color:var(--ink)}
.r9o-body .setl .in{display:inline-flex;gap:8px;align-items:center;margin-left:6px}.r9o-body .setl input{width:5.5em;background:none;border:none;border-bottom:1px solid var(--line-2,rgba(255,255,255,.14));color:var(--ink);font:inherit;font-size:12px;padding:1px 0}.r9o-body .setl button{background:none;border:none;padding:0;font:inherit;font-size:12px;color:var(--ink);text-decoration:underline;text-underline-offset:3px;cursor:pointer}
.r9o-body .avs{display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin:0 0 12px}.r9o-body .avs button{background:none;border:1px solid transparent;padding:2px;cursor:pointer;border-radius:50%}.r9o-body .avs button.on{border-color:var(--ink)}.r9o-body .avs img{display:block;width:100%;height:auto;border-radius:50%}
.r9o-in{display:flex;padding:10px 16px 14px;border-top:1px solid var(--line);flex:none}
.r9o-in input{flex:1;min-width:0;background:none;border:none;color:var(--ink);font:inherit;font-size:13px;padding:0}
.r9o-in input::placeholder{color:var(--ink-faint)}
.r9o-foot{padding:8px 16px 12px;font-size:11px;color:var(--ink-faint);border-top:1px solid var(--line);flex:none}
#obtTiles.r9-pbi ~ #obtRailFoot{display:none!important}
.r9-pbi-mobile .r9o{height:auto}.r9-pbi-mobile .r9o-body{overflow:visible;padding:14px 16px}

/* ---- chat laid out like a chat app ---- */
.r9o .msg{display:flex;flex-direction:column;gap:4px;margin:0 0 16px}
.r9o .msg .who{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--ink);font-weight:500}
.r9o .msg .who small{font-weight:400;color:var(--ink-faint);font-size:11px;margin-left:2px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.r9o .mk{width:20px;height:20px;border-radius:50%;overflow:hidden;display:grid;place-items:center;background:rgba(255,255,255,.06);flex:none}
.r9o .mk img{width:20px;height:20px;display:block;object-fit:cover}.r9o .mk.bb img{width:14px;height:14px}.r9o .mk i{font-style:normal;font-size:8px;color:var(--ink-dim)}
.r9o .msg .txt{padding-left:28px}.r9o .msg .txt p{margin:0 0 8px}.r9o .msg .txt p:last-child{margin-bottom:0}
.r9o .msg.me .txt p{color:var(--ink-dim)}
.r9o .msg .txt .src{margin:4px 0 0}
.r9o .msg .txt .vote{margin:6px 0 0}
.r9o-in{flex-direction:column;gap:6px;padding:10px 12px 12px}
.r9o-in .box{display:flex;align-items:center;gap:6px;border:1px solid rgba(255,255,255,.14);border-radius:18px;padding:6px 6px 6px 14px;background:var(--panel)}
.r9o-in .box input{flex:1;min-width:0;background:none;border:none;color:var(--ink);font:inherit;font-size:13px;padding:0}
.r9o-in .box button{width:26px;height:26px;border-radius:50%;border:none;background:var(--ink);color:var(--panel);display:grid;place-items:center;cursor:pointer;flex:none;padding:0}
.r9o-in .box button:hover{opacity:.85}
.r9o-in .left{margin:0;font-size:11px;color:var(--ink-faint);padding-left:4px}
/* ---- [WP-C4 2026-09-14] THE CHAT CLIENT, PROTOCOL 2 (src/03_pbi.js + src/04_engine.js; spec 6.2/6.3/6.5/6.7) ----
   Four marks, no new furniture: the status line is the body face in italic one ink back, the "- " rows reuse the
   column's existing hairline row (.rows), the answer's actions sit in the row the thumbs already had, and the
   composer footer becomes a two-item row so "Start again" can share the line with the budget without a second one.
   Nothing here introduces a card, a pill, a second typeface or a colour. */
.r9o-body .st{font-style:italic;color:var(--ink-faint);margin:0 0 8px}
.r9o-body .draft{margin:0}
.r9o-body .rows.md{margin:6px 0 10px}
.r9o-body .rows.md div:last-child{border-bottom:0}
.r9o .msg .txt .a p:last-child{margin-bottom:0}
.r9o .msg .txt .acts{display:flex;gap:14px;margin:6px 0 0;flex-wrap:wrap}
.r9o-in .row{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin:0;padding-left:4px}
.r9o-in .row .left{padding-left:0}
.r9o-in .again{background:none;border:none;padding:0;font:inherit;font-size:11px;color:var(--ink-faint);cursor:pointer;text-decoration:underline;text-underline-offset:3px;margin-left:auto;flex:none}
.r9o-in .again:hover{color:var(--ink)}
.r9o-in .rest{margin:0;padding-left:4px}
/* ---- the games list slides in once a game is open, and back out on hover (more room for the console) ---- */
@supports selector(:has(a)){
  @media (min-width:1100px){
    .obt-app.r9-game .obt-deck{transition:grid-template-columns .22s ease}
    .obt-app.r9-game .obt-deck{grid-template-columns:60px 116px 18px minmax(0,1fr) 280px!important}
    .obt-app.r9-game .obt-deck:has(.obt-gamescol:hover){grid-template-columns:60px 116px 240px minmax(0,1fr) 280px!important}
    .obt-app.r9-game .obt-gamescol{position:relative;overflow:hidden}
    .obt-app.r9-game .obt-gamescol:before{content:'games';position:absolute;left:0;top:0;bottom:0;width:18px;display:flex;align-items:center;justify-content:center;writing-mode:vertical-rl;transform:rotate(180deg);font-family:var(--mono);font-size:9px;letter-spacing:.2em;text-transform:uppercase;color:var(--ink-faint);background:var(--panel);border-right:1px solid var(--line);z-index:3;cursor:pointer}
    .obt-app.r9-game .obt-deck:has(.obt-gamescol:hover) .obt-gamescol:before{display:none}
    .obt-app.r9-game .obt-gamescol > *{opacity:0;transition:opacity .15s}
    .obt-app.r9-game .obt-deck:has(.obt-gamescol:hover) .obt-gamescol > *{opacity:1}
  }
}
/* ---------- [stage 1] THE FIVE TABS: one typeface, two text colours, hairlines. No gradients, pills, gold, coloured tags. ---------- */
#obtStage .obt-bento.r9-grid.r9-five{display:block!important;overflow:auto!important;padding:12px 26px 16px;font-family:var(--ui);color:var(--ink);font-variant-numeric:tabular-nums}
.r9-five .r9-tabs{display:flex;gap:22px;align-items:baseline;font-size:13px;color:var(--ink-faint);border-bottom:1px solid var(--line);padding-bottom:10px;margin-bottom:12px}
.r9-five .r9-tabs button{background:none;border:0;padding:0 0 10px;margin-bottom:-11px;font:inherit;color:inherit;cursor:pointer;border-bottom:1px solid transparent}
.r9-five .r9-tabs button.on{color:var(--ink);border-bottom-color:var(--ink)}
.r9-five .r9-tabs .r{margin-left:auto;font-size:12px}
.r9-five .r9-rule{font-size:21px;line-height:1.25;font-weight:600;letter-spacing:-.01em;margin:0 0 3px;color:var(--ink)}
.r9-five .r9-rule b{font-weight:600}
.r9-five .r9-pay{font-size:14px;color:var(--ink-faint);margin:0 0 10px}
.r9-five .r9-pay b{color:var(--ink);font-weight:500}
.r9-five .r9-counts{border:1px solid var(--line);padding:8px 12px;margin:0 0 10px;font-size:13px;line-height:1.5;max-width:760px;color:var(--ink)}
.r9-five .r9-counts b{font-weight:600}
.r9-five .bc{border:0!important;background:transparent!important;box-shadow:none!important;border-radius:0!important;padding:0!important;margin:0!important;grid-column:auto!important}
.r9-five .bc .bh{padding:0;margin:0 0 4px;border:0;background:transparent;display:flex;gap:10px;align-items:baseline}
.r9-five .bc .bh .lab{font-family:var(--ui);font-size:13px;font-weight:600;letter-spacing:0;text-transform:none;color:var(--ink)}
.r9-five .bc .bh .lab.r9-sig{font-weight:400;color:var(--ink-faint);margin-left:0;letter-spacing:0;text-transform:none}
.r9-five .bc .bh .lab.r9-sig.g,.r9-five .bc .bh .lab.r9-sig.w,.r9-five .bc .bh .lab.r9-sig.r{color:var(--ink-faint)}
.r9-five .bc .bb{padding:0!important}
.r9-five .r9-leadcell{border-top:1px solid var(--line)!important;padding:10px 0 8px!important}
.r9-five .r9-leadcell .bh .lab{font-size:15px}
.r9-five .r9-leadcell .r9-lead{font-size:15px;line-height:1.5}
.r9-five .r9-helpers{display:grid;grid-template-columns:repeat(4,1fr);border-top:1px solid var(--line);margin-top:10px}
.r9-five .r9-helpers.c1{grid-template-columns:1fr}.r9-five .r9-helpers.c2{grid-template-columns:repeat(2,1fr)}.r9-five .r9-helpers.c3{grid-template-columns:repeat(3,1fr)}
.r9-five .r9-helpers>.bc{padding:10px 18px 10px 0!important;border-right:1px solid var(--line)!important;margin-right:18px!important;min-width:0}
.r9-five .r9-helpers>.bc:last-child{border-right:0!important;margin-right:0!important}
.r9-five .r9-helpers .r9-lead{font-size:14px;line-height:1.42}
.r9-five .r9-lose{border-top:1px solid var(--line);margin:10px 0 0;padding-top:10px;font-size:14px;line-height:1.5;color:var(--ink)}
.r9-five .r9-lose b{font-weight:600}
.r9-five .r9-door{border-top:1px solid var(--line);margin-top:12px;padding-top:9px;font-size:13px;color:var(--ink-faint)}
.r9-five .r9-door summary{cursor:pointer;list-style:none}
.r9-five .r9-door summary::-webkit-details-marker{display:none}
.r9-five .r9-door summary b{color:var(--ink);font-weight:500;border-bottom:1px solid var(--ink)}
.r9-five .r9-deeper{display:grid;grid-template-columns:repeat(3,1fr);gap:0;margin-top:12px;border-top:1px solid var(--line)}
.r9-five .r9-deeper>.bc{padding:10px 18px 10px 0!important;border-right:1px solid var(--line)!important;border-bottom:1px solid var(--line)!important;margin-right:18px!important;min-width:0}
.r9-five .r9-deeper>.bc:nth-child(3n){border-right:0!important;margin-right:0!important}
.r9-five .r9-deeper>.bc.span2{grid-column:span 2!important}
.r9-five .r9-rg{font-size:12px;color:var(--ink-faint);margin:10px 0 0;padding-top:8px;border-top:1px solid var(--line)}
.r9-five .r9-loading{font-size:14px;color:var(--ink-faint);margin:0}
.r9-five .obt-cap{color:var(--ink-faint);font-family:var(--ui);font-size:13px}
.r9-five .r9-legend,.r9-five .r9-row,.r9-five .r9-heat,.r9-five .r9-list{font-family:var(--ui)}
@media (max-width:1100px){.r9-five .r9-helpers,.r9-five .r9-deeper{grid-template-columns:1fr!important}.r9-five .r9-helpers>.bc,.r9-five .r9-deeper>.bc{border-right:0!important;margin-right:0!important;border-bottom:1px solid var(--line)!important}#obtStage .obt-bento.r9-grid.r9-five{padding:10px 14px 14px}.r9-five .r9-rule{font-size:18px}.r9-five .r9-tabs{gap:14px;overflow-x:auto}}
/* ---------- [stage 1] direction-One kit: faces, ticks, face-off, organ tabs, modals, columns, surfaces ---------- */
.r9-face{display:inline-grid;place-items:center;border-radius:50%;overflow:hidden;background:var(--line);vertical-align:middle;flex:none}
.r9-face img{width:100%;height:100%;object-fit:cover;display:block}
/* [W15B 2026-09-18] .r9-face.ini IS GONE FROM THIS FILE. It styled the initials disc - "two letters in a round box" -
   and the owner's law bans that object outright (NO AVATARS EVER: real faces or initials). W14B retired the thing
   itself: src/00b_kit2.js:150 draws the crest, and when the image fails its onerror swaps in K.swatch (a rounded
   club-colour square with no letters in it), never initials. Nothing in src/ has emitted the class since. Leaving a
   rule that dresses a banned shape is an invitation to re-add it, and the vet now measures the AVATAR BY ITS SHAPE
   (1-3 letters in a round box under 44px, tools/vet_lenses.py out.avatars), so a new name for it would trip anyway.
   The two .r9-face rules above stay: they are the crest image itself. */
.r9-crest{vertical-align:middle;width:22px;height:22px;object-fit:contain}
.r9-ticks2{display:flex;gap:6px;margin:6px 0 2px;flex-wrap:wrap}
.r9-ticks2 i{display:block;width:30px;height:30px;border:1px solid var(--line);box-sizing:border-box}
.r9-ticks2 i.y{background:var(--ink)}
.r9-ticks2.s i{width:16px;height:16px}
.r9-ticks2.h i{border-style:dashed}.r9-ticks2.h i.y{background:transparent;border:1px solid var(--ink)}
/* [live walk 2026-09-13] the opponent codes under the squares (NMFC, RICH, GEEL) overflowed their 30px column: one column per
   square, 10px, centred, clipped to the square's width so four letters never run into the next */
.r9-tl2{display:flex;gap:6px;flex-wrap:wrap;margin:0 0 4px;font-family:var(--ui);font-size:10px;line-height:1.2;color:var(--ink-faint)}
.r9-tl2 span{display:block;width:30px;text-align:center;overflow:hidden;white-space:nowrap;letter-spacing:0}
.r9-tl2.s span{width:16px;font-size:9px}
/* [W15B 2026-09-18] THE DUPLICATE .r9-tl2 BLOCK THAT USED TO SIT HERE IS GONE, AND IT WAS NOT DEAD - IT WAS WINNING.
   Two blocks declared the same two selectors, four lines apart. The SECOND one had no `flex-wrap`, no `margin`, no
   `line-height` and a font-size of 11px, so the later block re-set font-size and, by omitting flex-wrap, left the row
   at the `nowrap` default - quietly undoing the wrap the 2026-09-13 live walk added three lines above it to stop the
   opponent codes (NMFC, RICH, GEEL) running off their 30px column. Deleting it restores the fix that was already
   written and paid for. Nothing else referenced it: every other .r9-tl2 rule in this file is scoped (.r9-five, or a
   media query) and still applies. */
.r9-faceoff{display:grid;grid-template-columns:1fr 250px 1fr;align-items:center;gap:20px;padding:4px 0 2px;font-family:var(--ui)}
.r9-faceoff .p{text-align:center}
.r9-faceoff .p b{display:block;font-size:17px;font-weight:600;margin-top:6px;color:var(--ink)}
.r9-faceoff .p span{color:var(--ink-faint);font-size:13px}
.r9-faceoff .tape div{display:grid;grid-template-columns:1fr 110px 1fr;font-size:14px;padding:3px 0;border-bottom:1px solid var(--line);color:var(--ink)}
.r9-faceoff .tape div span:first-child{text-align:right}
.r9-faceoff .tape div span:nth-child(2){text-align:center;color:var(--ink-faint);font-size:12px}
/* [W29A 2026-09-22] ONE TAB GRAMMAR ON THE WHOLE CONSOLE. K.tabs2 draws the WINDOW rows (Last 5 / Last 10 / This
   season / By quarter / the two starters) and K.tabrow draws the SPLIT rows; they were two different-looking
   controls doing one job - an 18px-gap text row with a 1px mark, beside a row of bordered chips. The owner asked
   for "tab controls beautifully in each card": that is ONE control, and this is it. Same hairline under the row,
   same 2px active bar in the club colour where the card sets --tc, same 8px top radii, same sideways scroll with
   the next tab half-shown as the cue, same focus ring. The desktop row is kept compact (30px, was about 20) so no
   tile that fitted yesterday stops fitting today; the phone row takes the 44px thumb in the phone block below. */
.r9-otabs{display:flex;gap:2px 4px;font-size:13px;color:var(--ink-faint);margin:4px 0 10px;font-family:var(--ui);
  flex-wrap:wrap}
.r9-otabs button{flex:0 0 auto;background:none;border:0;border-bottom:2px solid transparent;border-radius:8px 8px 0 0;
  padding:6px 9px;min-height:30px;font:inherit;font-weight:500;color:inherit;cursor:pointer;white-space:nowrap}
.r9-otabs button:hover{color:var(--ink-dim)}
.r9-otabs button:focus-visible{outline:2px solid var(--ink);outline-offset:-2px}
.r9-otabs button.on{color:var(--ink);font-weight:600;border-bottom-color:var(--tc,var(--ink))}
/* [W37E 2026-09-25] the tab row's native stand-in where the labels would wrap (K.tabs2): the tab's own clothes - the
   UI face at 13 px, a hairline, 8 px corners, the ink - one line tall so the drawing under it keeps its room. */
.r9-otabs-sel{-webkit-appearance:none;appearance:none;display:block;max-width:100%;height:34px;box-sizing:border-box;margin:4px 0 10px;padding:0 28px 0 10px;
  background:transparent url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%23888' stroke-width='1.5'/></svg>") no-repeat right 10px center;
  border:1px solid var(--line);border-radius:8px;font-family:var(--ui);font-size:13px;font-weight:600;color:var(--ink);cursor:pointer;text-overflow:ellipsis;overflow:hidden}
.r9-otabs-sel:hover{border-color:var(--ink-faint)}
.r9-otabs-sel:focus-visible{outline:1px solid var(--ink);outline-offset:2px}
.r9-morelink{background:none;border:0;padding:0;font:inherit;font-size:13px;color:var(--ink);cursor:pointer;border-bottom:1px solid var(--ink);font-family:var(--ui)}
.r9-modal{position:fixed;inset:0;z-index:9000;display:grid;place-items:center;background:rgba(0,0,0,.55)}
.r9-modal .box{background:var(--panel,#0e1117);color:var(--ink);border:1px solid var(--line);max-width:min(920px,92vw);max-height:86vh;overflow:auto;padding:18px 22px 20px;font-family:var(--ui)}
.r9-modal .box h3{font-size:16px;font-weight:600;margin:0 0 10px;display:flex;justify-content:space-between;align-items:baseline;gap:20px}
.r9-modal .box h3 button{background:none;border:0;font:inherit;color:var(--ink-faint);cursor:pointer}
.r9-three{display:grid;grid-template-columns:repeat(3,1fr);margin-top:8px;border-top:1px solid var(--line);font-family:var(--ui)}
.r9-three div{padding:8px 18px 6px 0;border-right:1px solid var(--line);margin-right:18px}
.r9-three div:last-child{border-right:0}
.r9-three b{display:block;font-size:22px;font-weight:600;letter-spacing:-.01em;color:var(--ink)}
.r9-three span{font-size:13px;color:var(--ink-faint)}
.r9-cols{display:grid;grid-template-columns:repeat(4,1fr);border-top:1px solid var(--line);margin-top:10px;font-family:var(--ui)}
.r9-cols.c1{grid-template-columns:1fr}.r9-cols.c2{grid-template-columns:repeat(2,1fr)}.r9-cols.c3{grid-template-columns:repeat(3,1fr)}
.r9-cols>div{padding:10px 18px 10px 0;border-right:1px solid var(--line);margin-right:18px;min-width:0}
.r9-cols>div:last-child{border-right:0;margin-right:0}
.r9-cols h4{font-size:13px;font-weight:600;margin:0 0 6px;color:var(--ink)}
.r9-cols p{font-size:14px;line-height:1.42;margin:0;color:var(--ink)}.r9-cols p+p{margin-top:4px}.r9-cols p.f{color:var(--ink-faint)}
.r9-table{border-collapse:collapse;width:100%;font-size:13px;font-family:var(--ui);color:var(--ink)}
.r9-table th{text-align:left;font-weight:500;color:var(--ink-faint);padding:4px 10px 4px 0;border-bottom:1px solid var(--line)}
.r9-table td{padding:4px 10px 4px 0;border-bottom:1px solid var(--line);vertical-align:top}
.r9-table td.n,.r9-table th.n{text-align:right}.r9-table tr.me td{font-weight:600}.r9-table tr.f td{color:var(--ink-faint)}
.r9-one svg{max-width:100%;height:auto;display:block}
.r9-five .r9-leadcell .r9-one svg{max-width:1128px}
.r9-five .r9-leadcell .obt-chartwrap:not(.r9-one) svg{max-width:640px}
.r9-five .r9-helpers .obt-chartwrap svg,.r9-five .r9-deeper .obt-chartwrap svg{max-width:100%}
.r9-spark{vertical-align:middle;margin-right:8px}
#obtStage:has(.r9-five){overflow-y:auto!important}
.r9-five .r9-ticks i{background:transparent;border:1px solid var(--line);color:transparent;width:16px;height:16px}
.r9-five .r9-ticks i.w,.r9-five .r9-ticks i.u{background:var(--ink);color:transparent}
.r9-five .r9-row .bar{background:transparent;border:1px solid var(--line)}.r9-five .r9-row .bar i{background:var(--ink)}.r9-five .r9-row .bar i.g,.r9-five .r9-row .bar i.o,.r9-five .r9-row .bar i.r{background:var(--ink)}
.r9-five .r9-row{font-family:var(--ui);font-size:13px;color:var(--ink)}.r9-five .r9-row .v,.r9-five .r9-row .v.g{color:var(--ink)}
.r9-five .r9-heat .c{background:transparent;border:1px solid var(--line)}.r9-five .r9-heat .c.g1,.r9-five .r9-heat .c.g2,.r9-five .r9-heat .c.r1,.r9-five .r9-heat .c.r2{background:transparent}
.r9-five .r9-list .st,.r9-five .r9-list .st.out,.r9-five .r9-list .st.q,.r9-five .r9-list .st.in{color:var(--ink-faint);border:0;text-transform:none;letter-spacing:0;font-family:var(--ui);font-size:13px}
.r9-five .r9-legend i,.r9-five .r9-legend i.g,.r9-five .r9-legend i.o,.r9-five .r9-legend i.d{background:var(--ink)}
.r9-five .r9-lch{font-family:var(--ui);text-transform:none;letter-spacing:0;color:var(--ink);font-size:13px;font-weight:600}
.r9-five .r9-lcp{background:transparent;border:1px solid var(--line);font-size:13px}.r9-five .r9-lcp b,.r9-five .r9-lcp small{font-family:var(--ui)}
.r9-five .r9-dg b{font-family:var(--ui);letter-spacing:0}
.r9-five .obt-chips .obt-chip{border:1px solid var(--line);background:transparent;color:var(--ink-faint);font-family:var(--ui);text-transform:none;letter-spacing:0}.r9-five .obt-chips .obt-chip.on{color:var(--ink);border-color:var(--ink)}
.r9-morerow{font-size:13px;margin:8px 0 0;font-family:var(--ui)}
.r9-foot{font-size:12px;color:var(--ink-faint);margin:6px 0 0;font-family:var(--ui)}
/* [W16B 2026-09-18] THE TAIL OF A LEAD THAT WAS TOO LONG. cell() cuts every tile's lead to one sentence (the ICP
   law, and tile_test T4) and prints the rest here, under the drawing, which is where the organs that already cut
   their own lead put theirs. It is the body's own size and ink - 13 px, never under the phone floor - because it is
   the same sentence it always was, one row lower. */
.r9-foot2{font-size:13px;line-height:1.45;color:var(--ink-dim);margin:7px 0 0;font-family:var(--ui)}
.r9-foot2 b{color:var(--ink);font-weight:600}
/* ---------- [stage 7 · de-AI, redone 2026-09-13 — owner: "the bottom navbar could be way better"] THE BAR = one ruled strip in the
   house style (mock A, on the real bench, dark + light): the five stops as plain text tabs, the one you are on underlined in ink;
   the utility cluster (run 100×, coach, compare, alerts, You, more) as plain text with hairline separators; "+ Slip it" a hairline
   box in ink. No gradients, no scan-lines, no glow, no coloured proc edges, no circles, no hotkey badges. Mock B (= A + each tab's
   one-line value) and C (= A + the 1-5 digit) are the two commented switches at the end. ---------- */
.r9-game #obtBar{background:var(--panel)!important;border-top:1px solid var(--line-strong,rgba(255,255,255,.3))!important;padding:0 8px!important;gap:0!important;align-items:stretch!important;transform:none!important;height:52px!important;min-height:0!important;box-shadow:none!important}
.r9-game #obtBar::before,.r9-game #obtBar::after,.r9-game #obtBar .jstage::before,.r9-game #obtBar .jstage::after,.r9-game #obtBar.sweep::after{display:none!important;content:none!important}
.r9-game #obtBar .jstage{flex:0 1 auto!important;min-width:0!important;padding:0 18px!important;margin:0!important;background:transparent!important;border:0!important;border-bottom:2px solid transparent!important;box-shadow:none!important;transform:none!important;color:var(--ink-faint)!important;display:flex!important;flex-direction:column!important;justify-content:center!important;align-items:flex-start!important;gap:1px!important;animation:none!important}
.r9-game #obtBar .jstage b{font-family:var(--ui)!important;font-weight:500!important;font-size:13px!important;letter-spacing:0!important;text-transform:none!important;color:inherit!important;overflow:visible!important}
.r9-game #obtBar .jstage.on{color:var(--ink)!important;border-bottom-color:var(--ink)!important;background:transparent!important}
.r9-game #obtBar .jstage.on b{font-weight:600!important}
.r9-game #obtBar .jstage.seen,.r9-game #obtBar .jstage.proc-red,.r9-game #obtBar .jstage.proc-green,.r9-game #obtBar .jstage.proc-blue,.r9-game #obtBar .jstage.proc-gold,.r9-game #obtBar .jstage.pinned,.r9-game #obtBar .jstage.cast{color:var(--ink-faint)!important;border-color:transparent!important;box-shadow:none!important;animation:none!important}
.r9-game #obtBar .jstage.on.seen{color:var(--ink)!important;border-bottom-color:var(--ink)!important}
.r9-game #obtBar .jstage:hover{color:var(--ink)!important;background:transparent!important}
.r9-game #obtBar .jstage .jg,.r9-game #obtBar .jstage .jc,.r9-game #obtBar .jstage .jq,.r9-game #obtBar .jstage .jn{display:none!important}
.r9-game #obtBar .baru{margin-left:auto!important;border-left:0!important;gap:0!important;background:transparent!important}
.r9-game #obtBar .ub{background:transparent!important;border:0!important;border-left:1px solid var(--line)!important;color:var(--ink-faint)!important;font-family:var(--ui)!important;font-size:12px!important;padding:0 14px!important;min-width:0!important;box-shadow:none!important;animation:none!important;flex-direction:row!important;gap:6px!important;align-items:center!important;text-transform:none!important;letter-spacing:0!important;transform:none!important}
.r9-game #obtBar .ub span{font-family:var(--ui)!important;font-size:12px!important;letter-spacing:0!important;text-transform:none!important;color:inherit!important}
.r9-game #obtBar .ub svg,.r9-game #obtBar .ub .rg,.r9-game #obtBar .ub i{display:none!important}
.r9-game #obtBar .ub:hover{color:var(--ink)!important;background:transparent!important}
.r9-game #obtBar .ub.pw,.r9-game #obtBar .ub.pw.proc,.r9-game #obtBar .ub.go{background:transparent!important;color:var(--ink-faint)!important;animation:none!important}
.r9-game #obtBar .ub.u-slip{border:1px solid var(--ink)!important;color:var(--ink)!important;margin:10px 0 10px 12px!important;padding:0 14px!important;border-radius:0!important;background:transparent!important}
.r9-game #obtBar .slot{display:none!important}
/* [2026-09-13 15:40 — mock D shipped, on top of the rules above] the v7b GLYPH tiles the owner liked, cleaned: glyph + label + the
   stop's one-line value, hairline separators, ink top rule on the active stop, utilities as glyph + word, a solid ink Slip button.
   No glow, no digit badges, no coloured seen-tick. (Mock E = this + a faint active panel: add
   .r9-game #obtBar .jstage.on{background:rgba(128,150,180,.08)!important}.) */
.r9-game #obtBar{height:60px!important;padding:0 6px!important}
.r9-game #obtBar .jstage{flex:1 1 0!important;padding:0 14px 0 46px!important;flex-direction:column!important;align-items:flex-start!important;justify-content:center!important;gap:2px!important;border-bottom:0!important;border-top:2px solid transparent!important;border-right:1px solid var(--line)!important;position:relative!important;min-width:0!important}
.r9-game #obtBar .jstage:last-of-type{border-right:0!important}
.r9-game #obtBar .jstage .jg{display:block!important;position:absolute!important;left:14px!important;top:50%!important;transform:translateY(-50%)!important;width:22px!important;height:22px!important;color:inherit!important;opacity:1!important}
.r9-game #obtBar .jstage .jg svg{width:22px!important;height:22px!important;display:block!important}
.r9-game #obtBar .jstage .jq{display:block!important;position:static!important;transform:none!important;font-family:var(--ui)!important;font-size:11.5px!important;letter-spacing:0!important;text-transform:none!important;color:var(--ink-faint)!important;max-width:100%!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;opacity:1!important}
.r9-game #obtBar .jstage.on{border-top-color:var(--ink)!important;color:var(--ink)!important}
.r9-game #obtBar .jstage.on .jq{color:var(--ink-faint)!important}
.r9-game #obtBar .jstage .jn,.r9-game #obtBar .jstage .jc{display:none!important}
.r9-game #obtBar .baru{margin-left:0!important;flex:0 0 auto!important}
.r9-game #obtBar .ub{flex-direction:column!important;gap:3px!important;padding:0 12px!important;min-width:56px!important;font-size:10.5px!important;justify-content:center!important;border-left:1px solid var(--line)!important}
.r9-game #obtBar .ub svg{display:block!important;width:18px!important;height:18px!important}
.r9-game #obtBar .ub .rg{display:block!important;background:transparent!important;border:0!important;box-shadow:none!important;width:auto!important;height:auto!important;padding:0!important;margin:0!important;color:inherit!important}
.r9-game #obtBar .ub .rg svg{width:18px!important;height:18px!important}
.r9-game #obtBar .ub span{font-size:10.5px!important}
.r9-game #obtBar .ub.u-slip{flex-direction:row!important;background:var(--ink)!important;color:var(--panel,#15171f)!important;border:0!important;margin:12px 2px 12px 10px!important;padding:0 16px!important;font-size:12px!important;font-weight:600!important;min-width:0!important}
.r9-game #obtBar .ub.u-slip svg,.r9-game #obtBar .ub.u-slip .rg{display:none!important}
html[data-theme="light"] .r9-game #obtBar .ub.u-slip{color:#fff!important}
.r9-game #obtBar .jstage b{font-family:var(--ui)!important;font-weight:500!important;font-size:13px!important;color:inherit!important;letter-spacing:0!important;text-transform:none!important}
.r9-game #obtBar .jstage.on b{font-weight:600!important}
.r9-game #obtBar .jstage:hover{color:var(--ink)!important}
.r9-game .obt-callline,.r9-game .obt-callrow{font-family:var(--ui)!important;color:var(--ink)!important}
.r9-game .obt-callline .st{display:none!important}
.r9-game .obt-callline .pr,.r9-game .obt-callpay{color:var(--ink)!important;font-family:var(--ui)!important}
.r9-game .obt-callchip{background:transparent!important;border:1px solid var(--line)!important;color:var(--ink)!important;font-family:var(--ui)!important;text-transform:none!important;letter-spacing:0!important}
.r9-game .obt-callline .pips span.on{background:var(--ink)!important}.r9-game .obt-callline .pips span{background:var(--line)!important}
.r9-five .r9-first{font-size:13px;color:var(--ink-faint);margin:-4px 0 10px;font-family:var(--ui)}
.r9-five .r9-tabs .r button{background:none;border:0;padding:0;font:inherit;color:var(--ink);cursor:pointer;border-bottom:1px solid var(--ink);margin-left:14px}
/* [integration 2026-09-13] the few host base cells that still ride behind the door (more numbers, price landscape, shop the
   price, price radar, pitching edge, defence v position, pace, phases, player prices) wore the old look: green pills, mono
   caps labels, coloured boxes. The house rules apply to them too: one typeface, two text colours, hairlines. SVG is left alone. */
.r9-grid .bc.base :not(svg):not(svg *){font-family:var(--ui)!important;text-transform:none!important;letter-spacing:0!important;background:transparent!important;border-color:var(--line)!important;box-shadow:none!important;border-radius:0!important}
.r9-grid .bc.base :not(svg):not(svg *):not(.bh):not(.lab){color:var(--ink)!important}
.r9-grid .bc.base .wt,.r9-grid .bc.base small,.r9-grid .bc.base .cap,.r9-grid .bc.base i{color:var(--ink-faint)!important}
.r9-grid .bc.base .r9-backed-inline{margin:0}
.r9-five .r9-backed-inline{margin:6px 0 12px;padding:8px 0 10px;border-bottom:1px solid var(--line)}
/* [owner 2026-09-13 "colours are sometimes very hard to see"] MEASURED on the bench with the real surface colours: body ink was
   15:1 (dark) / 16.7:1 (light) but the faint ink (pay line, foots, sig chips, RG line, tick + chart labels) was 3.29:1 in BOTH
   themes — under the 4.5:1 floor. Inside the console the faint tokens are re-pinned to >= 5:1 and the hairline to a visible
   grey; nothing else changes (still two text colours + hairlines). Measured after: faint 5.2:1 dark, 5.0:1 light. */
/* CORRECTION, same day: the real cause was the SLAB. The host's bento panel paints a 7% white wash (dark) / an 18% blue wash (light)
   under the console; the owner-approved mock (round9/shots/console_mocks2) has NO slab — the console sits straight on the page
   surface, ink on near-black / ink on white — and on that surface the host's own faint ink measures 5.4:1. So: kill the slab, keep the
   host tokens exactly as the mock used them, no re-pinned greys. */
.r9-five,#obtStage .obt-bento.r9-grid,#obtStage .obt-bento.r9-five{background:transparent!important;box-shadow:none!important;border:0!important;backdrop-filter:none!important}
html[data-theme="light"] .r9-five,html[data-theme="light"] #obtStage .obt-bento.r9-grid{background:transparent!important}
.r9-five,.r9-grid,.r9-game #obtBar{--line-strong:rgba(128,150,180,.35)}
/* …and one honest number on top of the mock: the host's faint ink is 3.3:1 on the page in BOTH themes (under the 4.5:1 floor for
   small text — the "hard to see" the owner sees). Same blue-grey hue as the mock, one step stronger: 4.9:1 dark, 5.0:1 light. */
/* [design law 2026-09-13] the legacy kit (00_kit.js: K.pair / K.bars / K.mirror / K.wind) still paints green, cyan and gold fills —
   the "Half by half" bars were green on the NFL proof tab. Inside the console every such fill and stroke becomes ink; the
   contrasting series stays the faint grey the kit already uses. */
.r9-five svg [fill="var(--model)"],.r9-five svg [fill="var(--action-hi)"],.r9-five svg [fill="var(--gold)"],.r9-five svg [fill="#E07070"],.r9-five svg [fill="#B48CFF"],.r9-five svg [fill="#5DD3E8"],.r9-five svg [fill="#F2A65A"]{fill:var(--ink)!important}
.r9-five svg [stroke="var(--model)"],.r9-five svg [stroke="var(--action-hi)"],.r9-five svg [stroke="var(--gold)"],.r9-five svg [stroke="#E07070"]{stroke:var(--ink)!important}
.r9-five svg [fill="rgba(128,150,180,.6)"],.r9-five svg [fill="rgba(128,150,180,.35)"],.r9-five svg [fill="rgba(128,150,180,.45)"]{fill:var(--line-strong)!important}
.r9-five .r9-legend i,.r9-five [class*="leg"] i.g,.r9-five [class*="leg"] i.a{background:var(--ink)!important}
.r9-five,.r9-grid,.r9-game #obtBar{--ink-faint:#78879e}
html[data-theme="light"] .r9-five,html[data-theme="light"] .r9-grid,html[data-theme="light"] .r9-game #obtBar{--ink-faint:#4F5B6E}
/* mobile: the tab row scrolls sideways, never wraps; the right label hides */
@media (max-width:800px){.r9-five .r9-tabs{flex-wrap:nowrap;overflow-x:auto;gap:16px;-webkit-overflow-scrolling:touch}.r9-five .r9-tabs button{white-space:nowrap;flex:none}.r9-five .r9-tabs .r{display:none}.r9-five .r9-three{grid-template-columns:1fr}.r9-five .r9-three div{border-right:0;border-bottom:1px solid var(--line)}.r9-faceoff{grid-template-columns:1fr;gap:8px}.r9-faceoff .tape div{grid-template-columns:1fr 90px 1fr}}
/* ---------- [a11y pass 2026-09-13 · round-9 item 42] THE NARROW + ZOOMED + GREYSCALE PASS. Measured on the bench with
   tools/bench_a11y.py (afl, nfl, mlb, soccer/epl, nrl x five tabs, 140 organ cells): 59 console-side clips at 320px wide,
   4 at 1600px, 0 at 200% text zoom. Nothing is added here but wrapping, shrinking and hairlines - no colour, no new size
   except the 10px tick label the live walk asked for. ---------- */
/* 1. THE CELL HEAD. The label and its sig sat on one no-wrap flex line and cut each other off in any narrow column:
      "How often they win" / "Atlanta Braves 4 of 10" (mlb), "The injury report" / "7 out - one touches this bet" (nfl),
      "If you put this in a multi" / "$151 on three legs" (deal, every league). The head wraps now: the sig drops under
      the label when the cell is a quarter column, and both print in full. */
.r9-five .bc{min-width:0}
.r9-five .bc .bh{flex-wrap:wrap;row-gap:1px}
.r9-five .bc .bh .lab,.r9-five .bc .bh .lab.r9-sig{min-width:0;max-width:100%;overflow:visible;text-overflow:clip;white-space:normal;overflow-wrap:break-word}
/* 2. K.cols / K.three. Three or four FIXED columns inside a quarter-width helper left 26-46px per column, so the words
      ran straight out of their box ("matrixturf", "Turnovers", "Dockers get 54.", "That is the team's record") - at 1600px
      as well as at 320px. The columns now fit themselves to the box they are handed: four across a lead cell, two in a
      helper, one on a phone, at every width. */
.r9-five .r9-cols,.r9-five .r9-cols.c1,.r9-five .r9-cols.c2,.r9-five .r9-cols.c3{grid-template-columns:repeat(auto-fit,minmax(124px,1fr))}
.r9-five .r9-cols>div{min-width:0;overflow-wrap:break-word}
.r9-five .r9-cols h4,.r9-five .r9-cols p{overflow-wrap:break-word}
.r9-five .r9-three{grid-template-columns:repeat(auto-fit,minmax(104px,1fr))}
.r9-five .r9-three div{min-width:0;overflow-wrap:break-word}
/* 3. THE WIDE CELLS. The inning-by-inning line, both batting orders, the league table and tonight's list cannot shrink
      below their own columns, so at 320px the cell cut them off with no way to reach the rest. Under 820px each cell's
      body scrolls sideways inside itself instead - the page itself still never scrolls sideways (checked on all five tabs
      at 320px: documentElement.scrollWidth == innerWidth). */
@media (max-width:820px){
  /* the console's own "overflow:visible!important" on every cell body (written to stop the host clipping tall organs)
     has to be answered at the same weight, or the phone keeps the cut instead of the sideways reach */
  #obtStage .obt-bento.r9-grid.r9-five .bc .bb{overflow-x:auto!important;overflow-y:visible!important}
  /* and on a phone each K.cols column gets the whole width rather than half of 254px, hairline-ruled between */
  .r9-five .r9-cols,.r9-five .r9-cols.c1,.r9-five .r9-cols.c2,.r9-five .r9-cols.c3{grid-template-columns:1fr}
  .r9-five .r9-cols>div{border-right:0;margin-right:0;padding-right:0;border-bottom:1px solid var(--line)}
  .r9-five .r9-cols>div:last-child{border-bottom:0}
  /* a three-column table (app, price, what $10 gets) should try to FIT the phone before it asks to be scrolled */
  .r9-five .r9-table{min-width:0}
  .r9-five .r9-table th,.r9-five .r9-table td{white-space:normal;padding-right:8px;overflow-wrap:break-word}
  #obtStage .obt-bento.r9-grid.r9-five{padding:10px 12px 14px}
  .r9-five .r9-faceoff .tape div{grid-template-columns:1fr 78px 1fr}
}
/* 4. THE TICK ROW (the live walk's own finding): four-letter opponent codes - NMFC, GEEL, RICH - under a 30px square.
      The 10px rule written for them was overridden two lines later by an 11px duplicate. 10px wins now. */
.r9-five .r9-tl2{font-size:10px;line-height:1.2}
.r9-five .r9-tl2 span{overflow:hidden;text-overflow:clip}
.r9-five .r9-tl2.s span{font-size:9px}
/* 5. 200% TEXT ZOOM (a 1600px window at Ctrl-plus = an 800px layout viewport): the console already reflows to its
      one-column helper grid there and measured 0 clips. Nothing to add - this comment is the record that it was tested. */
/* 6. GREYSCALE / COLOUR-VISION: the console paints in ink, faint ink and hairlines only, so a greyscale render is
      identical to the colour one. A hit is SOLID ink, a miss is a hairline box, an under-8 sample is a DASHED box -
      shape, never colour - and every count is written out in words beside it. The scan over all five tabs of all five
      leagues found no element inside the console painted in a meaning colour. The two host tokens kept below are the
      blue-grey ink itself, not a meaning. The tick rules above (.r9-ticks2) already carry all of that; nothing is
      restated here, because re-stating .r9-ticks2.h i at a higher weight would have flattened the hollow HIT (solid ink
      hairline) into the hollow MISS (dashed hairline) and lost the one distinction the greyscale pass exists to protect. */

/* ---------- [contrast audit 2026-09-13 · round-9 item 16, WP-CONTRAST] WCAG 2.2 AA, MEASURED. ----------
   Tool: tools/bench_contrast.py. Five leagues (afl, nfl, mlb, soccer/epl, nrl) x five tabs x two widths (1600 and the
   owner's 390px phone) x both themes. Every visible text node gets its real foreground composited over the first OPAQUE
   background above it, and the WCAG ratio against 4.5:1 (normal text) / 3:1 (large text and non-text marks).
   Raw text nodes measured: 5,437 at 1600px, 9,552 at 390px, per theme.

   WHAT THE 14:20 RESPIN ALREADY FIXED, and this run confirms: every WORD inside the console passes in both themes at
   both widths. The tightest text in the whole console is the faint ink itself - #78879e on the dark cell ground = 4.90:1,
   #606c80 on the light one = 5.00:1, both over the 4.5 floor, at 1600px and at 390px. 0 text failures out of 478 console
   rows. The owner's "hard to see" is therefore NOT the console's words any more. It is two other things:
     (a) the HOST chrome still runs the un-lifted site faint ink - #5A6B82 dark / #7C8AA0 light - at 3.09:1 to 3.50:1:
         the game head band (kick-off line, "our call:", the venue sentence) and the left rail's day headings and book
         names; plus the bottom bar's tile glyphs at 2.18:1 dark / 2.00:1 light, and the light theme's green price and
         gold "TAKE IT" at 3.14-3.86:1. Those live in assets/bb-oddst.css + assets/bb-core-rest.css, which this package
         does not own - handed over as integration asks with the measured ratio each one fixes.
     (b) the MARKS in 1-3 below and the "You" column in 4, which ARE painted by this file, and which are the real
         "I can't see it" on a phone.

   1. THE MISS BOX - the worst thing on the page. A tick row says "a filled block is a win", so a MISS is carried by a
      1px box drawn in var(--line): rgba(255,255,255,.07) dark, rgba(16,24,40,.08) light. Against the cell ground that
      measures 1.20:1 dark and 1.17:1 light - SC 1.4.11 asks 3:1 for a mark that carries meaning, and at 1.2:1 a loss is
      not a box, it is a hole. On the 390px capture the losses simply vanish and a 6-from-10 row reads as six blocks
      floating in white. 315 tick boxes were live on the tabs walked (organs form, threeway, socladder and every hit row).
      The box stays a 1px hairline - only its colour moves, and only to the ink token that is already in the file. */
.r9-five .r9-ticks2 i{border-color:var(--ink-faint)}
/*    the under-8 sample keeps its own law: DASHED = miss, SOLID = hit, so the greyscale distinction the a11y pass
      protects survives (fill vs no fill in a solid row; dash vs solid in a hollow row - shape, never colour). The .y
      line has to come after, or the rule above would repaint the hollow HIT outline and flatten the pair. */
.r9-five .r9-ticks2.h i{border-color:var(--ink-faint)}
.r9-five .r9-ticks2.h i.y{border-color:var(--ink)}
/* 2. THE BAR TRACK. Same hairline, same 1.20:1 / 1.17:1: the empty part of a bar IS the scale the fill is read against,
      so if the reader cannot see where the box ends the fill says nothing. Hairline kept, colour moved to faint ink. */
.r9-five .r9-row .bar{border-color:var(--ink-faint)}
/* 3. THE MIRROR BLOCKS. The empty block was a 14% blue-grey wash at 1.22:1 dark / 1.13:1 light, and the WIN block was
      still painted var(--model) GREEN - the last meaning colour left inside the console, which the greyscale pass never
      caught because no mirror row was on screen during that walk (live use 0 of 5 leagues). Both are brought onto the
      tick law: empty = hairline box, win = solid ink. */
.r9-five .r9-mirror i{background:transparent;border:1px solid var(--ink-faint);box-sizing:border-box}
.r9-five .r9-mirror i.w{background:var(--ink);border-color:var(--ink)}
/* 4. THE RIGHT "YOU" COLUMN - the second half of the owner's "hard to see", and it turns out to be OURS, not the host's.
      Every line in that column is painted by rules IN THIS FILE (.r9o-tabs button, .r9o-body .src, .r9o-body .rows small,
      .r9o-foot, .r9o-in .left, and the tile label .tl) and every one of them says color:var(--ink-faint) - but the 14:20
      respin only re-pinned that token on .r9-five / .r9-grid / .r9-game #obtBar, so inside #obtTiles the token was still
      the un-lifted SITE value: #5A6B82 dark, #7C8AA0 light. Measured there: 3.73:1 dark on #02060c, 3.23:1 light on
      #f2f6fc, and 2.98:1 on the phone's tile ground - all under the 4.5 floor, across 6 selectors x 5 leagues x 5 tabs.
      The chat answers, the RG line at the foot ("Set a limit - Take a break - Gambling Help 1800 858 858"), the "About 41
      questions left this month" and the "Sydney Swans to win - $2.45" under each answer are all in that band. Same token,
      same blue-grey, the scope simply reaches the column this file paints. One difference from the console's own value:
      the phone's tiles put that text on a TINTED ground (#192031, the lead tile's wash) where the console's #78879e
      measures 4.46:1 - four hundredths short - so the column runs one step further at #7b8aa1: 4.64:1 on the tinted
      tile, 5.10:1 on the plain one, 5.80:1 on the chat ground. Light is unchanged at #606c80 (4.90-5.31:1 there). */
#obtTiles{--ink-faint:#7b8aa1}
html[data-theme="light"] #obtTiles{--ink-faint:#4F5B6E}
/* 5. NOT CHANGED, on purpose: the plain DIVIDER hairlines (cell rules, .r9-five line, the tab underline) measure
      1.13:1 dark / 1.12:1 light (the chip and tab outlines 1.18:1 / 1.17:1, and each of those carries its own word
      inside it, so the outline is never the only thing telling the reader it is there). SC 1.4.11 exempts a divider
      that carries no meaning, the house style is built on them,
      and the design law says hairlines stay hairlines - so they are measured, printed in the audit, and left alone.
      Nothing else moves: one typeface, two ink colours, no new colour anywhere in this block.
      Full audit, per surface, per theme, with the failing host selectors: .claude/odds-terminal-work/CONTRAST_AUDIT_2026-09-13.md */

/* [2026-09-13 17:45, integrator] PHONE TICK ROWS: at 390px the console column is ~342px and a ten-square row (10 x 30 + 9 x 6 =
   354px) wrapped its tenth square onto a second line with its label under it (seen in the 390 proof capture; the 320 pass did not
   catch it because .s rows are 16px there). Below 520px a tick row never wraps: the squares and their labels share the width
   equally, capped at their desktop size, so ten squares paint at ~29px and twenty at ~14px. Same ink, same hairlines. */
@media (max-width:520px){
  .r9-five .r9-ticks2{flex-wrap:nowrap;gap:4px}
  .r9-five .r9-ticks2 i{flex:1 1 0;min-width:0;width:auto;max-width:30px;height:auto;aspect-ratio:1/1}
  .r9-five .r9-ticks2.s i{max-width:16px}
  .r9-five .r9-tl2{flex-wrap:nowrap;gap:4px}
  .r9-five .r9-tl2 span{flex:1 1 0;min-width:0;width:auto;max-width:30px;font-size:9px}
  .r9-five .r9-tl2.s span{max-width:16px;font-size:8px}
}

/* [WP-CONSOLE 2026-09-13, owner "ONE VERB, ONE PLACE"] THE CALL BLOCK. The call carried a second button ("I backed this
   for $10") while the bottom bar carried its own — two verbs for one act. The button is gone from the call: what stays is
   the MONEY (the $5 / $10 / $20 / Other chips, which set the one stake every line and the bar's Back it button read back)
   and one plain sentence that says where the button is and what happens after. Same words on a phone; only the chips wrap,
   and each chip grows to a 44px tap target there. Two inks, one hairline, no pills, no colour. */
.r9-five .r9-back{margin:6px 0 12px;padding:0 0 10px;border-bottom:1px solid var(--line)}
.r9-five .r9-back .r9-stakelab{margin:0 0 6px;font-family:var(--ui);font-size:13px;color:var(--ink-faint)}
.r9-five .r9-back .r9d-chips{margin:0 0 8px;flex-wrap:wrap}
.r9-five .r9-back .r9-backnote{margin:0 0 6px;font-family:var(--ui);font-size:13px;line-height:1.5;color:var(--ink-faint);max-width:70ch}
@media (max-width:700px){
  .r9-five .r9-back .r9d-chips .r9d-chip{min-height:44px;padding:0 16px;display:inline-flex;align-items:center}
}

/* ================================================================================================================
   [W16B 2026-09-18] THE PICK CARD'S TWO SENTENCES, ITS VERB AND ITS DOOR.
   The approved prototype's card is: the word, the picture, what has to happen, ONE why, ONE why-it-could-lose, the
   button and what it pays. These are those rows. One typeface (var(--ui) is inherited), two inks, one hairline; the
   only filled object is .r9cta, which is the one the design law names. Nothing here is a pill, a gauge or a glow.
   THE PHONE FLOOR is 13 px and the taps are 44 px, so the sentences are set at 14 and the button at 44 high on both
   devices - a desktop tile is narrow, not small, and the card is the one thing on the screen nobody should squint at.
   ================================================================================================================ */
/* ⛔ THE RULE SENTENCE IS 15 px INSIDE THE CARD, NOT 21. MOCKUP_DIFF row A7 says it in those words, and the reason is
   arithmetic: the card now carries the confidence word, the tug bar, the rule, a why, a why-it-could-lose, the button
   and the chips, and a 21 px sentence over four lines is 96 px of a tile that is about 300 px tall. At 15 px it is two
   lines. It is still the largest ink in the body and still the first thing read after the word and the picture; only
   the pick's own card is touched, so the rule above every other stop's pane is the size it always was. */
.r9-five .r9-callcard .r9-rule{font-size:15px;line-height:1.4;margin:0 0 7px}
@media (max-width:1100px){.r9-five .r9-callcard .r9-rule{font-size:15px}}
.r9-five .r9-back .r9-why,.r9-five .r9-back .r9-lose{margin:0 0 6px;font-family:var(--ui);font-size:14px;line-height:1.45;color:var(--ink);max-width:68ch}
.r9-five .r9-back .r9-why b,.r9-five .r9-back .r9-lose b{font-weight:600}
/* ⛔ the v1 rule gave .r9-lose a top hairline and 10 px of space above it because it used to be the LAST thing on
   the stop, under everything else. Inside the card it is the line straight after the why, so the rule is undone
   here rather than edited above - the v1 selector is still what a stop that is not the pick would use. */
.r9-five .r9-back .r9-lose{border-top:0;padding-top:0}
/* THE CARD IS A COLUMN: the word at the top, the sentences in a box that may run short, the verb and the door pinned
   under them. See the note at callBlock's return for the measurement that made this necessary. */
.r9-five .r9-callcard>.bb{display:flex;flex-direction:column;min-height:0}
.r9-five .r9-callcard>.bb>.r9-back{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;margin-bottom:0;border-bottom:0}
/* ⛔ flex-basis 0, NOT auto. With auto the box is sized from its content and then shrunk, and MEASURED at 1440 it
   shrank to exactly 0 px - the rule, the why and the why-it-could-lose all gone, with no sign that they were ever
   there. With basis 0 it simply takes whatever the pinned rows leave, which is what "the prose is what clips" means. */
.r9-five .r9-callprose{flex:1 1 0;min-height:0;overflow:hidden}
/* [W36F 2026-09-25] A SLIVER IS NOT A SENTENCE, MEASURED. At 1150 the card body is short enough that the pinned rows
   (Track it 84 px + margins, the door 30 + 5) leave the prose box 11 px, so the first line of "Why it could lose"
   showed as a half-cut strip behind the button (scratch w36f_probe: .r9-callprose 323-334, p.r9-lose 329-364,
   .r9cta 340-384; the pay line wraps under the button at that width, which is what took the room). The prose box
   is a size container on a desktop (its basis is 0 already, so containment changes no layout), and when the box
   is under one line (19 px) its words step aside whole instead of showing a strip; every word is still behind
   "Read it all", where the open tile un-pins the prose and lets it flow. A phone never contains: its rows are as
   tall as their words (the rule at the foot of this block). */
@media (min-width:900px){
  .r9-five .r9-callcard:not(.r9-open) .r9-callprose{container-type:size}
  @container (max-height:19px){ .r9-callprose>*{display:none} }
  .r9-five .r9-callcard.r9-open .r9-callprose{flex:none;overflow:visible}
}
.r9-five .r9-trackrow,.r9-five .r9-trackdone,.r9-five .r9-calldoor{flex:0 0 auto}
/* every pixel in these two rows is a pixel the two sentences above them do not get, so the padding is the minimum
   that still clears the 44 px tap law and the 12 px desktop ink floor. MEASURED: this pair went 103 px -> 83. */
/* ⛔ NOT nowrap. Tried and MEASURED: with nowrap the pay column shrinks to its min-width and the row goes to 123 px,
   worse than the 68 it was. It wraps under the button, and the words themselves are what got shorter instead. */
.r9-five .r9-trackrow{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin:6px 0 4px}
/* ⛔⛔ THE CARD'S VERB IS THE PROTOTYPE'S BUTTON, NOT THE SUBSCRIBE PILL.
   `.r9cta` is the ONE filled object the design law allows, so the class stays - but 08_cta.css describes it as "THE
   PILL ... used where the door IS the thing on screen (the locked column)", and it is a full-width blue GRADIENT
   with a GLOW. LOOKED AT on shots/w16b/after/nfl_call_1440.png: it filled the card edge to edge and out-shouted
   the confidence word, the bet and the two sentences - and a glowing gradient pill is the exact "AI-looking" object
   the owner has already rejected once (feedback-design-never-ai-looking). The approved prototype's own Track it is
   a small SOLID button in the page's ink: `background:var(--ink);color:var(--page);padding:9px 16px;radius:8px`.
   So the sanctioned class keeps its name and takes the prototype's look inside this row, and only inside it: the
   locked column's pill is untouched. No gradient, no glow, no sheen, sized to its own words. */
.r9-five .r9-trackrow .r9cta{min-height:44px;display:inline-flex;align-items:center;justify-content:center;
  padding:0 18px;flex:0 0 auto;width:auto;max-width:none;align-self:flex-start;
  background:var(--ink);background-image:none;color:var(--bg,#0F1118);border:0;border-radius:8px;
  box-shadow:none;filter:none;text-shadow:none;font-size:14px;font-weight:600;letter-spacing:0}
.r9-five .r9-trackrow .r9cta::before,.r9-five .r9-trackrow .r9cta::after{display:none}
.r9-five .r9-trackpay{font-family:var(--ui);font-size:13px;line-height:1.28;color:var(--ink-dim);flex:1 1 120px;min-width:0}
.r9-five .r9-trackpay b{color:var(--ink);font-weight:600}
.r9-five .r9-trackdone{margin:10px 0 8px;font-family:var(--ui);font-size:13px;line-height:1.45;color:var(--ink-dim)}
/* the door: the four sentences a reader needs AFTER he has decided. A summary row, not a modal and not a scroll. */
.r9-five .r9-calldoor{margin:5px 0 0;border-top:1px solid var(--line);padding-top:5px}
.r9-five .r9-calldoor>summary{font-family:var(--ui);font-size:13px;color:var(--ink-dim);cursor:pointer;min-height:24px;
  display:flex;align-items:center;list-style:none}
.r9-five .r9-calldoor>summary::-webkit-details-marker{display:none}
.r9-five .r9-calldoor>summary::after{content:'';width:6px;height:6px;margin-left:8px;border-right:1px solid currentColor;
  border-bottom:1px solid currentColor;transform:rotate(45deg) translateY(-2px)}
.r9-five .r9-calldoor[open]>summary::after{transform:rotate(-135deg) translateY(1px)}
.r9-five .r9-calldoor .r9-counts{border:0;padding:8px 0 0;margin:0 0 6px;font-size:13px;line-height:1.5;color:var(--ink-dim)}
@media (max-width:700px){
  /* ⛔ THE PIN IS A DESKTOP ANSWER TO A DESKTOP PROBLEM. A phone SCROLLS: there is no clip to protect the verb from,
     and `flex:1 1 0` in a column whose height is not constrained gives the prose box ZERO - LOOKED AT on
     shots/w16b/after2/nfl_call_390.png, the rule sentence and "Why it could lose" were both simply gone from the
     card. On a phone the card is a plain block again and every sentence is in it, which is what the prototype's
     phone section is. */
  .r9-five .r9-callcard>.bb,.r9-five .r9-callcard>.bb>.r9-back{display:block}
  .r9-five .r9-callprose{flex:none;overflow:visible}
  .r9-five .r9-calldoor>summary{min-height:44px}
  .r9-five .r9-trackrow .r9cta{flex:0 0 auto}   /* a phone still sizes it to its words, never edge to edge */
}

/* ================================================================================================================
   [WP-M4 · 2026-09-14] THE CONTENT FIT ON A PHONE  (MOBILE_OVERHAUL_SPEC.md §8 WP-M4, defects D6 and D11)

   THE LAW THIS BLOCK OBEYS: every rule below sits inside @media (max-width:899px) — the one phone token (D13) —
   so the desktop console's bytes do not move. Proved with a 1600px before/after capture pair.

   WHAT IT FIXES, in the order the reader meets it:
     1. THE RG LINE FLOATED IN A HOLE. On a short tab (ufc "What could stop it?" is 509px of content in a 796px
        stage) the helpline ended mid-screen with ~290px of empty panel under it. The tab is now a flex column
        with min-height 100%, and the RG line takes margin-top:auto, so it sits on the bottom edge of every tab
        and the reading never ends in a hole. gap is pinned to 0 because the host's phone rule sets a 10px grid
        gap that a block box ignored and a flex box would not.
     2. WIDE TABLES CUT THEMSELVES UP INSTEAD OF SCROLLING. The injury table (Player · Side · Thu · Fri · Sat ·
        What it means for this line) folded six columns into 342px: "Jack Driscoll, OT" over three lines and the
        meaning column over six. A table of FOUR OR MORE columns now takes its own width, scrolls sideways inside
        its own cell body, and pins its first column so the reader can always see who a row is about. Three-column
        tables (app · price · what $10 gets) still fit themselves to the phone, as the 820px block intended.
     3. THE THREE-UP STAT BLOCK. `.r9-three` was left at auto-fit/104px, which is three columns at 342px: "60 of
        100" broke across two lines and its sentence ran nine lines deep. One stat per row on a phone, hairline
        between, same as K.cols already does.
     4. TEXT UNDER THE 10px FLOOR (D11). The HTML half of it: the chart legend (9.9px), the tick-row opponent
        codes (9/8px), the base cells' mono-caps headings (9.9px) and their side labels (9.3px), and the 7px
        initials inside a league table. The SVG half is fixed in the kit (src/00_kit.js, K._ps).
     5. THE GO DEEPER DOOR AND THE MODALS. The door was a 13px line with no tap target; it is 44px now. A modal
        was centred with its heading — and its Close — scrolling away above the content; on a phone it is a
        full-width sheet on the bottom edge with a pinned heading, a 44px Close, 88vh, and its own scroll.
     6. THE STAGE'S BOTTOM PADDING follows the bar instead of a hard-coded 124px, through --bb-barh (set by the
        bar block, WP-M3). The fallback is today's number, so nothing moves until that block lands.
   ================================================================================================================ */
@media (max-width:899px){

  /* --- 1. the tab is a column and the RG line sits on its bottom edge ------------------------------------- */
  /* the base rule up the file pins this box to display:block!important, so the column has to answer at the same weight.
     The tab is as tall as the stage MINUS the head that shares the stage with it (--bb-headh, published by the head
     block; the fallback is the head's own spec budget of 112px) — a plain 100% would push the helpline the height of
     the head below the fold and make the reader scroll a short tab to find it, which is worse than the hole it fixes. */
  #obtStage .obt-bento.r9-grid.r9-five{display:flex!important;flex-direction:column;gap:0;box-sizing:border-box;
    min-height:calc(100% - var(--bb-headh,112px))}
  #obtStage .obt-bento.r9-grid.r9-five>.r9-rg{margin-top:auto}
  /* the stage's own bottom room tracks the bar through --bb-barh. The bar block (WP-M3, host_css/30_phone.css)
     publishes the var AND owns the padding rule (`.obt-app .obt-stage{padding-bottom:calc(var(--bb-barh,101px)+14px)}`),
     so this sheet must NOT restate it: an id selector here would beat that class rule and silently eat its +14px. */

  /* --- 2. wide tables: their own width, sideways inside the cell, first column pinned ---------------------- */
  #obtStage .obt-bento.r9-grid.r9-five .bc .bb{overflow-x:auto;overflow-y:visible;-webkit-overflow-scrolling:touch}
  #obtStage .r9-five .r9-table:is(:has(th:nth-child(4)),:has(td:nth-child(4))){width:max-content;min-width:100%}
  #obtStage .r9-five .r9-table:is(:has(th:nth-child(4)),:has(td:nth-child(4))) th,
  #obtStage .r9-five .r9-table:is(:has(th:nth-child(4)),:has(td:nth-child(4))) td{white-space:nowrap;padding-right:14px}
  /* the last column is the one that carries a sentence ("A hole in the Steelers line") — it keeps wrapping */
  #obtStage .r9-five .r9-table:is(:has(th:nth-child(4)),:has(td:nth-child(4))) th:last-child,
  #obtStage .r9-five .r9-table:is(:has(th:nth-child(4)),:has(td:nth-child(4))) td:last-child{white-space:normal;min-width:150px;max-width:230px;padding-right:0}
  #obtStage .r9-five .r9-table:is(:has(th:nth-child(4)),:has(td:nth-child(4))) th:first-child,
  #obtStage .r9-five .r9-table:is(:has(th:nth-child(4)),:has(td:nth-child(4))) td:first-child{position:sticky;left:0;z-index:1;background:var(--panel-2);box-shadow:1px 0 0 var(--line);max-width:132px;white-space:normal}
  #obtStage .r9-five .r9-table:is(:has(th:nth-child(4)),:has(td:nth-child(4))) th:first-child{z-index:2}

  /* --- 3. one stat per row — the number beside its sentence, not above it ---------------------------------- */
  /* Three columns at 342px gave "60 of 100" a line break inside the number itself. One stat per row fixes that but
     stacking the number over its sentence spent ~75px on "4 / draws"; the number sits BESIDE the sentence instead,
     left-aligned on a fixed 96px so the three numbers line up, and a row costs ~46px. */
  #obtStage .r9-five .r9-three{grid-template-columns:1fr}
  #obtStage .r9-five .r9-three div{border-right:0;margin-right:0;padding:7px 0;border-bottom:1px solid var(--line);
    display:flex;align-items:baseline;gap:12px}
  #obtStage .r9-five .r9-three div:last-child{border-bottom:0}
  #obtStage .r9-five .r9-three b{flex:0 0 auto;min-width:96px;font-size:19px;white-space:nowrap}
  #obtStage .r9-five .r9-three span{flex:1 1 auto;min-width:0}
  #obtStage .r9-five .r9-faceoff .tape div{grid-template-columns:1fr 84px 1fr;font-size:13px}

  /* --- 4. nothing in the reading paints under 10px --------------------------------------------------------- */
  /* [W13C 2026-09-17, second pass] A LEGEND IS READ TEXT. This row carries the two CLUB NAMES under the play-call
     and drive drawings ("Steelers", "Falcons"), and at 11px it was the last thing on the nfl / ncaaf / nrl matchup
     tab under the 13px phone floor (console vet L7, "4 text under the floors"; desk_law_test nfl 390 matchup 2).
     Two short names at 13px fit a 322px cell with the row's own wrap to catch a long one. */
  #obtStage .r9-five .r9-legend{font-size:13px;letter-spacing:.02em;gap:10px}
  /* THE STREAK ROW. The 2026-09-13 rule shrank the squares and their opponent codes until a ten-square row fitted:
     at 320px that is 21.8px a square, and a four-letter club code (NMFC, MELB, SUNS) printed at the 10px floor needs
     24 - so the codes ran into each other. The squares and the codes keep the size the kit drew them at, and the CELL
     carries the row sideways when it will not fit, the same answer the wide tables and the wide drawings get. Both
     rows sit in the same scroller (the cell body), so a square and its code can never slide apart. */
  #obtStage .r9-five .r9-ticks2,#obtStage .r9-five .r9-tl2{flex-wrap:nowrap;gap:6px}
  #obtStage .r9-five .r9-ticks2 i{flex:0 0 auto;width:30px;height:30px;max-width:none;aspect-ratio:auto}
  #obtStage .r9-five .r9-ticks2.s i{width:16px;height:16px}
  #obtStage .r9-five .r9-tl2 span{flex:0 0 auto;width:30px;max-width:none;font-size:10px;overflow:hidden}
  #obtStage .r9-five .r9-tl2.s span{width:16px;font-size:10px}
  #obtStage .r9-five .r9-ticks i{font-size:10px}
  /* the base cells the host still paints inside the console: one typeface, sentence case, over the floor */
  #obtStage .r9-five .gcmh{font-family:var(--ui);font-size:11px;letter-spacing:0;text-transform:none}
  #obtStage .r9-five .obt-splab{font-family:var(--ui);font-size:11px;letter-spacing:0;text-transform:none;min-width:0}
  /* [W13C 2026-09-17] 12px WAS UNDER THE PHONE FLOOR. The design law is 13px on a phone and 12px on a desktop, and
     console_vet measured these captions at 12.0 on the epl and nrl matchup tabs (L7, "4 text under the floors").
     The base rule up this file is already 13; this phone override was pulling it back DOWN, which is the one
     direction a floor may never move. The caption is where the honest count and the sample note live - it is read,
     not decoration. The RG line below keeps its own size: that line is untouched by law. */
  #obtStage .r9-five .obt-cap{font-size:13px}
  #obtStage .r9-five .r9-foot,#obtStage .r9-five .r9o-rlab,#obtStage .r9-five .r9h-sub{font-size:13px}
  /* the helpline was the last thing on the phone still set in the mono face (.r9-rg, up this file) — one typeface,
     and it is now the line the reader's eye lands on at the bottom of every tab. The desktop half of that rule is
     handed to the lane lead as an integration ask, because this package may not move a desktop byte. */
  #obtStage .r9-five .r9-rg{font-family:var(--ui);letter-spacing:0;font-size:12px}
  /* [W15B 2026-09-18] the 10px floor-lift for the initials badge is gone with the badge. The comment that stood here
     said the badges "are handed to the lane lead as an integration ask, because deleting them is an organ change":
     W14B made that organ change (K.swatch / K.shield, no letters), so this rule has had nothing to select since. */

  /* --- 5. the door and the modals are things a thumb can use ----------------------------------------------- */
  #obtStage .r9-five .r9-door>summary{min-height:44px;display:flex;align-items:center;padding:4px 0;line-height:1.35}
  .r9-modal{align-items:end;justify-items:stretch;place-items:end stretch}
  .r9-modal .box{width:100%;max-width:100%;max-height:88vh;display:flex;flex-direction:column;
    padding:0 14px calc(18px + env(safe-area-inset-bottom));border-left:0;border-right:0;border-bottom:0}
  .r9-modal .box h3{position:sticky;top:0;z-index:2;background:var(--panel,#0e1117);margin:0 -14px 10px;
    padding:12px 14px 10px;border-bottom:1px solid var(--line);align-items:center}
  .r9-modal .box h3 button{min-width:44px;min-height:44px;display:inline-flex;align-items:center;justify-content:flex-end}
}

/* ======================================================================================================================
   [WP-C5 2026-09-14] CITATIONS AND CHIPS  (src/03_pbi.js; CHAT_TOPTIER_SPEC.md sections 6.1 + 6.4)
   Four things, and no new furniture in the column:
     1. THE FROM ROW (.src.cites) keeps the faint ink it has always had; only the NAMES inside it become taps, drawn
        exactly like the door links already in this column (.r9o-body .links button, up this file): the reading ink and
        an underline, nothing else. No pill, no chevron, no colour - the underline is the whole affordance.
     2. THE CHIP (.qr button.qc) is now two lines: the question, then the tab it opens one step back. The question keeps
        the chip ink it has always had and lifts to the reading ink under a pointer; the door line stays faint, because
        the question is the thing the reader is choosing and the door is the promise attached to it.
     3. THE LANDING MARK (.bc.r9-citelit) is a hairline around the organ the citation opened, for 2.6 seconds. A reader
        who taps "The ladder" and is put 900px down a stage needs to see WHICH cell answered him. It is an outline, not
        a background, so it never repaints an organ's own drawing, and it is not animated.
     4. THE BOARD CITE (.obt-deck.r9-citeopen) re-opens the games column for four seconds on a desktop, where the list
        collapses to a hairline once a game is open. The numbers are the hover rule's own, three rules up - the same
        column width, arrived at by a tap instead of a mouse.
   Design law: one typeface, the two inks, hairlines, no pills, no colour, no faces. Phone rules are inside the one
   @media (max-width:899px) at the bottom of this block and only buy the 44px target the a11y pass requires.
   ====================================================================================================================== */
.r9o-body .src.cites{color:var(--ink-faint)}
/* every property the host's own `.cb` / mono-caps chrome could reach in is written out here, because this button sits
   inside the host's stylesheet as well as ours: one typeface, sentence case, no letter-spacing, no box. */
.r9o-body .src.cites button.r9-cite{display:inline;background:none;border:none;padding:0;margin:0;font:inherit;
  font-family:var(--ui);font-size:11px;text-transform:none;letter-spacing:0;color:var(--ink);
  text-decoration:underline;text-underline-offset:3px;cursor:pointer;text-align:left}
.r9o-body .src.cites button.r9-cite:hover{text-decoration-thickness:2px}
.r9o-body .qr button.qc{padding:4px 0;text-transform:none;letter-spacing:0}
.r9o-body .qr button.qc .r9-chipq{display:block;margin:0;color:inherit}
.r9o-body .qr button.qc small{display:block;font-size:11px;line-height:1.35;color:var(--ink-faint);margin-top:1px;
  font-family:var(--ui);text-transform:none;letter-spacing:0}
.r9o-body .qr.qr-more{margin-top:-6px}
.bc.r9-citelit{outline:1px solid var(--ink-faint);outline-offset:2px}
.bc[tabindex="-1"]:focus{outline:none}
.bc[tabindex="-1"]:focus-visible{outline:1px solid var(--ink-faint);outline-offset:2px}
@media (min-width:1100px){
  .obt-app.r9-game .obt-deck.r9-citeopen{grid-template-columns:60px 116px 240px minmax(0,1fr) 280px!important}
}
@media (max-width:899px){
  /* the 44px floor, bought the way every other control in this column buys it: a taller box around the same words,
     never bigger words. The chip is already a full-width 44px row (07_you.css); it only has to stop being a
     single-line flex row now that it carries the door underneath. */
  #obtStage .r9o-ph .r9o-body .qr button.qc{flex-direction:column;align-items:flex-start;justify-content:center;
    padding:6px 0;line-height:1.35}
  #obtStage .r9o-ph .r9o-body .qr button.qc small{font-size:11.5px}
}

/* ==================================================================================================================
   [W15B 2026-09-18] THE VET'S RANKED BACKLOG, ITEM 8: 44 px TAPS, AND ITEM 6: THE BAR ANSWER THAT CLIPS AT 1150.
   round10w/CONSOLE_VET_V2_2026-09-18.md section 4 rows 14-16, 20, 23, 24, 38, 39 (taps) and row 7 (clipped text).
   ==================================================================================================================
   WHY A FLOOR AND NOT NINE MORE SELECTORS. The vet's tap rule is not a list of classes: it measures EVERY visible
   button, link and [role="tab"] inside #obtStage, #obtBar and #obtTiles on a phone and fails any box under 43.5 px
   tall (tools/vet_lenses.py out.taps). L7 was the lowest lens on the whole walk - 128 of 385 - and the named
   offenders came from six different files, four of which this package does not own ("Show me" is the HOST's phone
   head .phh-show, 59x24; "Go deeper" is the door's own summary, 62x22; "all 13 apps" is 01i_deal.js, 65x22; "All
   games, 6 of 7" is this wave's own situation chip, 123x37). Nine more class rules would leave the tenth control
   under the floor the day someone adds it. A floor, scoped to the phone and to the console's own furniture, is the
   rule the law actually states.
   THE TEXT DOES NOT MOVE. This buys the height with padding and a min-height on the BOX, never with bigger type -
   the design law's floors (13 px phone) are a minimum, not a target, and the prototype's chips are small words in a
   big hit area. Nothing here paints, so no pill, no gauge and no new colour enters the design.
   THE ONE EXEMPTION, AND WHY IT IS HONEST. A button that sits INSIDE a sentence ("... <button>See the teams</button>
   ...") is a word, not a control: giving it a 44 px box would open a hole in the middle of the paragraph it is part
   of. Those are excluded by their position (a direct child of a <p>), and they are the only exclusion. */
@media (max-width:899px){
  #obtStage button,
  #obtStage a[href],
  #obtStage [role="tab"],
  #obtBar button,
  #obtTiles button{min-height:44px}
  /* ⛔ [W15B 2026-09-18, MEASURED AND REVERSED] THE "WORD IN A SENTENCE" EXEMPTION IS GONE, BECAUSE IT MADE THINGS
     WORSE. The first cut of this block exempted a button that is a direct child of a <p> on the argument that a
     control inside a sentence is a word and not a slab. The vet then read "Show me" at 59x17 where it had been
     59x24: the host's phone head draws it inside <p class="phh-c"> ("Our call here is LEAN. [Show me]"), so the
     exemption did not spare it - it STRIPPED the padding it already had and shrank it seven pixels.
     A rule whose only measured effect is to take height off the control it was written to protect is not a nuance,
     it is a bug, and the law it was hedging against has no exemption in it. Every button in the console's furniture
     gets the 44 px box; where that opens up a line of prose, the fix is to stop writing controls into the middle of
     sentences - which is what the approved prototype does. The captures at 390 are in shots/w15b/. */
  /* ⛔ THE HIT AREA GROWS, THE HEAD DOES NOT - MEASURED, AND THE FIRST CUT BROKE A GATE THAT HAD BEEN GREEN.
     Giving "Show me" a plain 44 px box took the phone head from 112 px to 117 px, and tools/phone_metrics.py H1
     failed it on soccer_epl at 390 in both themes on all five stops (plus B5, the chrome total, as the
     consequence) - a gate W14B had at 0 failures. That head is sticky and it is the D1 defect this lane already
     paid for once: every pixel it gains is a pixel of the bet sentence hidden underneath it.
     The negative block margins are the whole point. The BUTTON's own rect is 44 px tall, which is what the tap law
     is about and what the vet measures; the LINE BOX it sits in is unchanged, because the extra height is pulled
     back out of the paragraph's own leading on both sides. A hit area that overlaps the whitespace above and below
     it is the standard way to buy a touch target inside running text, and there is nothing tappable in that
     whitespace for it to steal from. */
  /* ⛔ AND IT STOPS AT 360, WHICH IS A CONFESSION AND NOT A TUNING. MEASURED, three ways:
     the phone head is 97 px at 390 and 107 px at 320 with this rule, 97 / 97 without it; the button's own rect is
     75x44 either way; and the paragraph it sits in goes 24 -> 34 no matter what the negative margins are set to,
     because `.phh-c` lays its child out as a flex item and a flex item's line box is its border box, which
     negative margins do not shrink. At 320 that 10 px puts tools/phone_metrics.py's B5 total 2 px over
     (top 48 + head 107 + bar 105 = 260 of 258) - and that budget exists because this head is STICKY and every
     pixel it gains is a pixel of the bet sentence hidden under it, which is defect D1 this lane already paid for.
     So the floor applies from 360 up, which covers every width the console is measured at (390, 1150, 1440) and
     every phone in the ICP's hand bar the very smallest, and at 320 the control stays exactly as it was rather
     than eating the sentence above it.
     ⛔ THIS IS NOT THE RIGHT FIX AND IT IS IN THE ASKS AS SUCH. The right fix is one line in the HOST: "Show me"
     is written INSIDE a sentence (`<p class="phh-c">Our call here is LEAN. <button class="phh-show">Show me
     </button></p>`), and a control in the middle of a paragraph can never have a 44 px box without opening a hole
     in the paragraph. On its own row it costs the head nothing at any width. That is a host change this package
     may not make. */
  /* the rule itself is NOT here: a nested @media inside this one did not survive the build (the head measured
     117 px at 320, worse than the 107 the nesting was written to avoid), so it is written flat below this block. */
  /* [W29A 2026-09-22] THE SPLIT CONTROL IS A TAB ROW ON THE PHONE TOO - the owner's "same for mobile". It keeps
     the wrap (desk_law_test counts a sideways scroller's cut last word as clipped text at 390 as well as at 1600),
     and every tab keeps the 44px thumb. What has gone is the NUMBER on the button: the row is short words now, so
     a wrapped row is two lines of labels instead of three lines of counts. */
  #obtStage .bbs-sit .bbs-sb,#obtStage .bbtab .bbtab-t{min-height:44px;display:inline-flex;align-items:center;
    padding-top:4px;padding-bottom:4px}
  #obtStage .bbtab-say,#obtStage .bbs-say{min-height:38px}
  /* the window rows are the same control, so they take the same thumb */
  #obtStage .r9-otabs button{min-height:44px;display:inline-flex;align-items:center}
  /* ⛔ THE SELECTOR CARRIES `.r9-v2` ON PURPOSE - MEASURED. tools/host_css/89_stops.css:217 sets
     `#obtStage .r9-v2 .r9-morechip { min-height: 30px; font-size: 12px }`, which out-specifies a bare
     `#obtStage .r9-morechip`, so the first cut of this rule lost the cascade in silence and the vet read the player
     chips at 262x30 and 320x30 with their price text at 12.0px - under the floor AND under the tap law, on the one
     control this wave added. Matching the host's own specificity, later in the cascade, is what actually wins.
     13 px is the phone floor, not a preference: the chip says "$10 gets $38.00" and that is the number the reader
     came for. */
  #obtStage .r9-morechip,#obtStage .r9-pbet{min-height:44px;display:inline-flex;align-items:center}
  /* ⛔ SECOND CORRECTION, AND THE LESSON IS THE CASCADE AND NOT THE NUMBER. `#obtStage .r9-v2 .r9-morechip`
     MATCHED 89_stops.css's specificity and still lost - this stylesheet is not guaranteed to come after the host
     chain, so a tie goes to whoever is later in the document and that is not us. The vet read the player chips at
     245x32 / 307x32 with 12.0px text through BOTH earlier attempts. Two classes on the same element
     (`.r9-pbet.r9-morechip`) out-specifies it outright, which does not depend on load order at all. Measured, not
     reasoned: the chips are the control this wave added, and 12 px on "$10 gets $38.00" is the number the reader
     came for, written under the floor. */
  /* `gap` is not decoration here. LOOKED AT (shots/w15b/after/afl_stop_390.png): flex layout drops the whitespace
     text node between a chip's words and its <b>, so every chip read "Karl Worner 18+ disposals$10 gets $18.50"
     with the price welded to the stat. The markup has the space; inline-flex ate it. */
  #obtStage .r9-v2 .r9-pbet.r9-morechip,#obtStage .r9-pbet.r9-morechip{min-height:44px;display:inline-flex;
    align-items:center;gap:6px;flex-wrap:wrap;font-size:13px;line-height:1.25;padding-top:6px;padding-bottom:6px}
  #obtStage .r9-v2 .r9-pbet.r9-morechip b,#obtStage .r9-pbet.r9-morechip b{font-size:13px}
  #obtStage .r9-v2 .r9-morerow2 .r9-morechip{min-height:44px;display:inline-flex;align-items:center;font-size:13px}
  /* the door: the summary is the tap, so the height goes on the summary and not on the <details> around it */
  #obtStage .r9-door>summary{min-height:44px;display:flex;align-items:center}
}

/* ---- item 6: THE BAR'S ANSWER LINE, CLIPPED AT 1150 AND NOWHERE ELSE ---------------------------------------------
   MEASURED, not guessed. The vet read the same five clipped texts on EVERY stop of eleven leagues, and every one of
   them was at 1150 px and none at 1440: ".jq \"$24.50 for $10\"", ".jq \"the pattern\"", ".jq \"led QT 6 of 10\"",
   ".jq \"23 v 23 named\"". They are not organ text at all - .jq is the bottom bar's per-stop answer line, written by
   the host and dressed 300 lines above by this file with `overflow:hidden; text-overflow:ellipsis; white-space:nowrap`.
   At 1440 the five tiles have room for one line of 11.5 px; at 1150 they do not, so each answer ends in an ellipsis
   that no door can open - which is exactly what "clipped text in a tile with no door" is there to catch.
   THE FIX IS ROOM, NOT SILENCE. The phone hides this line (tools/host_css/89_stops.css) because five labels plus a
   second row of type is unreadable at 320. A 1150 desktop is not that case: the tile is 60 px tall and carries a
   13 px label, which leaves room for two lines of 10.5 px underneath. So between 900 and 1279 the answer WRAPS
   instead of being cut off. Nothing is hidden and nothing is shortened. */
@media (min-width:900px) and (max-width:1279px){
  .r9-game #obtBar .jstage .jq{white-space:normal!important;overflow:visible!important;text-overflow:clip!important;
    font-size:10.5px!important;line-height:1.15!important}
  .r9-game #obtBar .jstage{padding-left:40px!important;padding-right:10px!important}
  .r9-game #obtBar .jstage .jg{left:10px!important}
}

/* [W15B 2026-09-18] THE PHONE HEAD'S ONE CONTROL, AT 360 AND UP ONLY - see the note in the 899px block above for
   the three measurements and for why this is a confession rather than a tuning. Flat, not nested: build_r9.py's
   css step does not keep a @media inside a @media. */
@media (min-width:360px) and (max-width:899px){
  #obtStage .phh-show,#obtStage .phh-c button{min-height:44px;display:inline-flex;align-items:center;
    line-height:16px;padding:14px 10px;margin-top:-14px;margin-bottom:-14px;vertical-align:middle}
}
/* ⛔ AND THE BLANKET FLOOR IS TAKEN BACK OFF THIS ONE BUTTON BELOW 360, WHICH IS THE HALF THE FIRST GATE MISSED.
   MEASURED: with only the rule above gated, the head was still 117 px at 320 - because the 44 px floor in the
   899px block catches EVERY `#obtStage button`, and "Show me" is one, so it kept the height and lost the negative
   margins that were paying for it. Both halves have to stop at the same width or the smallest screen gets the
   cost of the rule without its compensation. */
@media (max-width:359px){
  /* ⛔ min-height AND NOTHING ELSE, MEASURED TWICE. This block only has to UNDO the floor the 899px block adds;
     it must not restyle the host's own button. The cut before this one also set padding, margin, line-height and
     display:inline on every control in the head, and tools/phone_metrics.py went the wrong way - mlb's collapsed
     head 82 -> 92 px against an 80 px budget - because zeroing the host's own padding and forcing a flex button
     back to inline re-laid the head out rather than leaving it alone. The rule the console adds is the only rule
     the console may take away. */
  #obtStage .phh-show,#obtStage .phh-c button,#obtStage .phh button,#obtStage .obt-wsid button{min-height:0}
}

/* [integrator 2026-09-18, W16B tile shell] the mockup's tile icon: 18px stroke, ink-dim, before every tile title */
.bc .bh .lab svg.r9-oi{width:18px;height:18px;stroke:var(--ink-dim);fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;vertical-align:-4px;margin-right:7px;flex:0 0 auto}
.bc .bh .lab{display:inline-flex;align-items:center}

/* ==================================================================================================================
   [W17B 2026-09-18] A TILE HAS AN INSIDE.   ⛔ THE ONE LINE THAT MADE EVERY v2 TILE LOOK WRONG IS IN THIS FILE.
   ------------------------------------------------------------------------------------------------------------------
   MEASURED, not guessed (tools/_w17b_probe.py, 2026-09-18, nfl + afl at 1440): the computed `padding-left` of every
   tile on every stop read **0**. The prototype's own tile is `padding:12px 14px` (round10w/proto/odds-console-
   prototype.html:77) and its phone section is `12px 16px 14px` (:84). So on the bench every tile's first letter sat
   ON its own 1px border, and "won by enough 2 of 6" and "$10 gets $21.50" ran into the right edge - which is exactly
   what the integrator's side-by-side saw at 18:45 and called "the tiles have no inner padding".
   WHY IT WAS ZERO, AND WHY THE FIX BELONGS HERE AND NOT IN THE HOST. The host's v2 tile rules (tools/host_css/
   89_stops.css:128-146) never set padding at all - they were written expecting the card's own. This file's line 312,
   `.r9-five .bc{...padding:0!important...}`, is what zeroes it: it is a v1 rule (v1's `.bc` was a run of text with no
   edge, and the zero is right there), and `!important` beats the host's un-!important shorthand no matter how much
   more specific the host selector is. The host file is W17A's; this line is W17B's; so the correction is made where
   the zero is made, with one selector that is more specific AND !important, and v1 keeps its zero untouched.
   THE DOOR GETS ITS MARGIN BACK TO ZERO for the same reason: 89_stops.css:167 gives `.r9-tiledoor` `margin:0 12px 8px`
   because it was sitting in an unpadded box. With the box padded, 14 + 12 = 26px of inset would put the door out of
   line with every sentence above it, so inside a padded tile the door carries the tile's padding and nothing more.
   ================================================================================================================== */
#obtStage .obt-bento.r9-grid.r9-v2 .r9-pane>.bc,
#obtStage .obt-bento.r9-grid.r9-v2 .r9-pane>.bc.span2,
#obtStage .obt-bento.r9-grid.r9-v2 .r9-pane>.bc.span3{padding:12px 14px!important}
#obtStage .obt-bento.r9-grid.r9-v2 .r9-pane>.bc>.r9-tiledoor{margin:2px 0 0!important}
@media (max-width:899px){
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-helpers.r9-sections>.bc,
  #obtStage .obt-bento.r9-grid.r9-v2>.bc.r9-leadcell,
  #obtStage .obt-bento.r9-grid.r9-v2>.bc.r9-callcard{padding:12px 16px 14px!important}
  /* ⛔ AND THE READINGS BEHIND "GO DEEPER" ARE TILES TOO. MEASURED at 390 (out/w17b_probe_mid3.json): the first six
     sections read padding-left 16 and the seventh onwards read 0 - they are not in .r9-sections at all, they are
     inside the phone's own `<details class="r9-door"><div class="r9-deeper">` (src/04_engine.js:774), where
     scenes.css:334 gives them `padding:10px 18px 10px 0`. On nfl's Matchup that is TEN of sixteen sections with
     their text on the left border. A reader who opens the door gets the same object he had above it. */
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-deeper>.bc{padding:12px 16px 14px!important;
    border:1px solid var(--line)!important;border-radius:8px!important;margin:0 0 10px!important;
    background:rgba(255,255,255,.012)!important}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-helpers.r9-sections>.bc>.r9-tiledoor,
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-deeper>.bc>.r9-tiledoor,
  #obtStage .obt-bento.r9-grid.r9-v2>.bc.r9-leadcell>.r9-tiledoor,
  #obtStage .obt-bento.r9-grid.r9-v2>.bc.r9-callcard>.r9-tiledoor{margin:2px 0 0!important}
}

/* [integrator 2026-09-19] an empty caption or sub line takes no room (the how-to sentences are gone, the mockup has none) */
.r9-five .bbs-cap:empty,.r9-five .r9r-sub:empty{display:none}
/* [integrator 2026-09-19] drawing_fit at 320: three K.cols columns with 18+18 px gutters held 322 px in 239 (nfl "The ground").
   On a phone the columns stack; a long stadium name wraps in its own column at every width. */
.r9-cols{grid-template-columns:repeat(4,minmax(0,1fr))}.r9-cols.c2{grid-template-columns:repeat(2,minmax(0,1fr))}.r9-cols.c3{grid-template-columns:repeat(3,minmax(0,1fr))}
.r9-cols p,.r9-cols h4{overflow-wrap:anywhere}
@media (max-width:560px){.r9-cols,.r9-cols.c2,.r9-cols.c3{grid-template-columns:minmax(0,1fr)}.r9-cols>div{border-right:0;margin-right:0;padding-right:0;border-bottom:1px solid var(--line)}.r9-cols>div:last-child{border-bottom:0}}

/* =====================================================================================================================
   [W23B 2026-09-20] LIGHT THEME, MADE CORRECT - AND WHY IT WAS BROKEN FOR A READER WHO NEVER TOUCHED THE TOGGLE.
   ---------------------------------------------------------------------------------------------------------------------
   PROD, 19 Sep (remaining list item 34, the owner's own screen): "nav words invisible, Track it verbs black blobs,
   r9pd-blur not blurred". The console did not look like that for anyone who PRESSED the light switch - it looked like
   that for a guest whose OPERATING SYSTEM is light and who pressed nothing. That is a different selector entirely:
   pressing the switch stamps html[data-theme="light"], and every light rule on this console was written against that
   stamp, so a reader sitting at `:root` with no attribute at all and `prefers-color-scheme: light` got the site's
   light page tokens underneath a console drawn for a dark one. Dark ink on a dark wash is a black blob.
   THE RULE FROM HERE: every light rule is written TWICE - once for the stamp, once for the system default with no
   stamp - and the dark stamp always wins over the system. That is the three-state contract, and tools/light_theme_test.py
   walks it: contrast >= 4.5:1 for text and >= 3:1 for marks, on every stop, at 1440 and 390, guest and subscriber.
   NOTHING IS REMOVED. Dark stays the pinned default; light stops being a trap.
   ===================================================================================================================== */
html[data-theme="light"] #obtStage,
:root:not([data-theme="dark"]):not([data-theme="light"]) #obtStage{
  /* the console's OWN inks, so a scene surface never depends on what the page chrome happens to be handing down */
  --ink:#10131A;--ink-dim:#3C4657;--ink-faint:#4F5B6E;--line:#D9DEE8;--panel:#FFFFFF;--page:#F6F7FA;
  --model:#0B7A52;--gold:#8A6A00;--action-hi:#1D4FD8;
}
@media (prefers-color-scheme:light){
  :root:not([data-theme="dark"]) #obtStage{
    --ink:#10131A;--ink-dim:#3C4657;--ink-faint:#4F5B6E;--line:#D9DEE8;--panel:#FFFFFF;--page:#F6F7FA;
    --model:#0B7A52;--gold:#8A6A00;--action-hi:#1D4FD8;
  }
}
/* the washes. Every one of these is rgba(128,150,180,a) - a mid slate that reads as a lift on dark and a shade on
   light - EXCEPT where a rule hard-codes a white film, which on a white panel is invisible. Those are the tiles. */
html[data-theme="light"] #obtStage .obt-bento.r9-grid.r9-v2 .r9-deeper>.bc,
html[data-theme="light"] #obtStage .obt-bento.r9-grid.r9-v2>.bc{background:#FFF}
@media (prefers-color-scheme:light){
  :root:not([data-theme="dark"]) #obtStage .obt-bento.r9-grid.r9-v2 .r9-deeper>.bc,
  :root:not([data-theme="dark"]) #obtStage .obt-bento.r9-grid.r9-v2>.bc{background:#FFF}
}
/* THE BLUR. filter:blur() paints the element's own ink; on light the locked block was dark text at .48 opacity over
   white, which reads as grey WORDS, not as a locked block - the reader could still read our verdict through it. The
   opacity floor goes up and the blur with it, so the shape survives and the sentence does not. */
html[data-theme="light"] #obtStage .r9pd-blur,
:root:not([data-theme="dark"]):not([data-theme="light"]) #obtStage .r9pd-blur{filter:blur(5px);opacity:.34}
@media (prefers-color-scheme:light){:root:not([data-theme="dark"]) #obtStage .r9pd-blur{filter:blur(5px);opacity:.34}}
/* THE SCRIM behind the reading sheet: rgba(6,8,12,.74) is right on a dark page and a hole punched in a light one. */
html[data-theme="light"] .r9-modal,
:root:not([data-theme="dark"]):not([data-theme="light"]) .r9-modal{background:rgba(24,28,36,.48)}
@media (prefers-color-scheme:light){:root:not([data-theme="dark"]) .r9-modal{background:rgba(24,28,36,.48)}}
/* THE DARK-INK BUTTON (line 697): background:var(--ink) with color:var(--bg,#0F1118). On light --ink is near-black
   and --bg is unset, so it fell back to near-black ON near-black - the owner's "black blobs". The label is the page. */
html[data-theme="light"] #obtStage .r9-verb,
html[data-theme="light"] #obtStage .r9-btn.p,
:root:not([data-theme="dark"]):not([data-theme="light"]) #obtStage .r9-verb,
:root:not([data-theme="dark"]):not([data-theme="light"]) #obtStage .r9-btn.p{color:#FFF}
@media (prefers-color-scheme:light){
  :root:not([data-theme="dark"]) #obtStage .r9-verb,
  :root:not([data-theme="dark"]) #obtStage .r9-btn.p{color:#FFF}
}

/* [W23B 2026-09-20] THE RESULT LETTER INSIDE A TABLE. The W / L / D law (owner, 19 Sep: "use W and Ls") reached every
   strip and every tick, and then a sheet's own table printed a bare letter with no mark. These are the strip's own
   colours, scoped to the table so nothing else moves, and the LETTER is always there - colour is the second reading,
   never the only one (the design law: W/L colour lives only inside proof strips, and a sheet's table is one). */
.r9-table .wn,.r9-table .ls,.r9-table .dr{font-weight:700;font-style:normal}
.r9-table .wn{color:var(--model)}.r9-table .ls{color:#C2453F}.r9-table .dr{color:var(--ink-faint)}
html[data-theme="light"] .r9-table .ls,:root:not([data-theme="dark"]):not([data-theme="light"]) .r9-table .ls{color:#A32B26}
@media (prefers-color-scheme:light){:root:not([data-theme="dark"]) .r9-table .ls{color:#A32B26}}

/* [W23B 2026-09-20] 320 PX. The walk (item 5) at 320 wide, guest and subscriber, every stop on nfl / mlb / afl /
   soccer_epl. Three things were measured sideways-scrolling a 320 px phone and every one of them is a table or a grid
   that cannot be narrower than its own columns: the sheet's own tables, the ladder, and the four-column conditions
   row. A table gets its OWN scroller (the law allows exactly that - tables, diagrams and code blocks, each inside its
   own overflow-x:auto container) so the PAGE never moves sideways; the grids stack. Nothing drops below 12 px. */
@media (max-width:360px){
  /* [integrator 2026-09-20] phone_metrics F2 (30 failures on mint #10): a table made into a sideways scroller is a STRAY scroller -
     only the house strips may drag. At 320 a table FITS instead: fixed layout, the words wrap inside their own column. */
  #obtStage .r9-table{table-layout:fixed;width:100%;max-width:100%}
  #obtStage .r9-table th,#obtStage .r9-table td{white-space:normal;overflow-wrap:anywhere;font-size:12px;padding-left:2px;padding-right:2px}
  #obtStage .r9h-lad{grid-template-columns:minmax(0,1fr)}
  #obtStage .r9-cols,#obtStage .r9-cols.c2,#obtStage .r9-cols.c3{grid-template-columns:minmax(0,1fr)}
  #obtStage .r9-row{grid-template-columns:5.6em 1fr auto;font-size:12px}
  #obtStage .bc,#obtStage .r9-five .bc{min-width:0;overflow-wrap:anywhere}
  #obtStage [data-r9="tiledoor"],#obtStage [data-r9="organmodal"],#obtStage .bbs-sb,#obtStage .bbtab-t,#obtStage .obt-chip{min-height:44px}
}


/* ================================================================================================================
   [W25B 2026-09-20, item 7a] THE LIGHT THEME'S FAINT INK WAS NOT DARK ENOUGH TO SIT ON THE LIGHT THEME'S OWN TINTS.
   MEASURED (round9/out/gates20.log, light_theme L1, afl at 390, guest and subscriber, the STAMPED light state):
     'Dockers'  rgb(96,108,128) on rgb(217,222,232) = 3.94:1
   rgb(96,108,128) was --ink-faint (#606c80) and rgb(217,222,232) is the raised tint a tick or a square is drawn
   on, so the token cleared 4.5:1 against the PAGE and failed against the surfaces the page actually puts it on.
   #4F5B6E reads 5.0:1 on that tint and 6.2:1 on the page, and is the same hue: nothing else about the theme moves.
   Dark is untouched by a byte - every rule changed above is inside an html[data-theme="light"] selector or the
   light :root block, and light_theme_test asserts both halves.
   ⛔ THE HOST STYLESHEET HOLDS A SECOND COPY of this token (tools/host_css/103_w23b.css, which this package may
   not edit). It is handed to the integrator as an exact edit rather than shadowed here, because two truths about
   one token is how a theme drifts. */
html[data-theme="light"] .r9-five,html[data-theme="light"] .r9-grid,
html[data-theme="light"] #obtTiles,html[data-theme="light"] .r9-modal{--ink-faint:#4F5B6E}

/* TEXT ON A CLUB COLOUR TAKES --tcg, WHICH IS NOW BLACK OR WHITE BY THAT COLOUR'S OWN LUMINANCE (K.tcg).
   A CLUB-COLOURED NUMBER ON THE PAGE TAKES --tct, WHICH EXISTS ONLY WHERE THE COLOUR CAN BE READ THERE (K.tct).
   Both fall back to exactly what they printed before, so a league with no colour table is byte-for-byte itself. */
#obtStage .r9-sp .n,.r9-modal .r9-sp .n{color:var(--tct,var(--ink))}
#obtStage .r9h-ar,.r9-modal .r9h-ar{color:var(--tct,var(--ink))}
#obtStage .bbs-rk span.ls,.r9-modal .bbs-rk span.ls{color:var(--tct,var(--bbs-l))}
#obtStage .bbs-mk i.no,.r9-modal .bbs-mk i.no{color:var(--tct,var(--bbs-l))}
#obtStage .r9pd-tug .a,.r9-modal .r9pd-tug .a{color:var(--tcg,var(--bg,#0F1118))}

/* ================================================================================================================
   [W26B 2026-09-20, item 1] THE ZONE WORDS A PHONE CANNOT FIT INSIDE THE BOX.
   SEEN ON PROD at 375 px (afl Matchup and Player, "Where the ball goes"): the three headings printed on top of
   each other ("their b..." over "the middle") and the three numbers ran through one another ("let in 12.3" into
   "148 contested"). On a phone the kit now paints the NUMBER inside the zone and hands the WORDS to this list -
   one zone to a line, in the order they sit on the field, with the zone's own tint beside it so the line and the
   box pair up. One typeface, inks and hairlines only; no pill, no gradient; 13 px is the phone floor.
   It is emitted only on a phone (K.zones pushes nothing off one), so every desktop drawing is untouched. */
#obtStage .r9-zcap,.r9-modal .r9-zcap{list-style:none;margin:8px 0 0;padding:0;display:grid;gap:4px}
#obtStage .r9-zcap li,.r9-modal .r9-zcap li{display:flex;align-items:center;gap:8px;font:400 13px/1.35 var(--ui);color:var(--ink);min-width:0}
#obtStage .r9-zcap li i,.r9-modal .r9-zcap li i{flex:0 0 auto;width:10px;height:10px;border-radius:2px;background:var(--ink);display:block}

/* [W26B 2026-09-20, item 2] A ROW THE TILE CANNOT SHOW WHOLE IS NOT SHOWN AT ALL.
   The tile body is a fixed-height box in the bento grid, so a max-height cap on it does nothing (measured: a 90 px
   cap left clientHeight at 158). The first row that the clip would cut through, and every row after it, is taken
   off the screen instead - by VISIBILITY, so the body still measures as clipped and the "Read it all" door it
   earns stays. Half a row of letters above a door reads as a rendering fault; a clean edge reads as a door. */
#obtStage .r9-cutrow{visibility:hidden}

/* ================================================================================================================
   [W27B 2026-09-21] A TABLE SCROLLS SIDEWAYS. THE TILE NEVER DOES.
   MEASURED (`tools/drawing_fit_test.py --list`, nfl Matchup, the two DRAG failures the hand-over names): "The
   weather" held a 289 px table in a 239 px tile body at 320 and a 322 px table in a 309 px one at 390, so the tile
   BODY became the sideways scroller - and the gridiron drawing above the table was dragged out of the cell with it.
   The design law allows a table (and only a table, a diagram or a code block) its own overflow-x:auto container.
   K.table now writes one. The wrapper is the cell's own width, so the body has nothing left to scroll.
   AND IT SAYS SO: `data-more="1"` is set by the pass at the foot of src/01k_integ.js on any wrapper that really
   does hold more than it shows, and the right edge of that wrapper fades - the reader can see the row runs on.
   Nothing is hidden and nothing is cut; a scroller that announces itself is the honest answer, an invisible one
   is not. At 320 nothing drags at all: the table is made to FIT, the words wrapping inside their own column. */
.r9-tw{max-width:100%}
@media (max-width:560px){
  #obtStage .r9-five .r9-tw{overflow-x:auto;-webkit-overflow-scrolling:touch;position:relative}
  #obtStage .r9-five .r9-tw[data-more="1"]{
    -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 26px),rgba(0,0,0,.25));
            mask-image:linear-gradient(to right,#000 calc(100% - 26px),rgba(0,0,0,.25))}
}
@media (max-width:360px){
  /* this has to beat the four-column rule in the phone block above, which is why the selector is as long as it is */
  #obtStage .r9-five .r9-table:is(:has(th:nth-child(4)),:has(td:nth-child(4))){width:100%;max-width:100%;table-layout:fixed}
  #obtStage .r9-five .r9-table:is(:has(th:nth-child(4)),:has(td:nth-child(4))) th,
  #obtStage .r9-five .r9-table:is(:has(th:nth-child(4)),:has(td:nth-child(4))) td{white-space:normal;overflow-wrap:break-word;padding-right:6px}
  #obtStage .r9-five .r9-table:is(:has(th:nth-child(4)),:has(td:nth-child(4))) th:first-child,
  #obtStage .r9-five .r9-table:is(:has(th:nth-child(4)),:has(td:nth-child(4))) td:first-child{position:static;box-shadow:none;max-width:none}
  #obtStage .r9-five .r9-tw{overflow-x:visible}
}

/* [W27B 2026-09-21] the fighter's corner swatch on a legend - the octagon's own mark, never an invented club
   colour (src/00e_colours.js BBCol.corner). It takes --tc like every other club-coloured mark in this console. */
.r9-legend i.tcm,.r9-five .r9-legend i.tcm{background:var(--tc,var(--ink-faint))}

/* [W27B 2026-09-21] the corner mark on a fighter's card: a hairline rule in his corner's ink above his name.
   Not a pill, not a glow, not a swatch pretending to be a club badge - the same 2 px rule the console uses
   everywhere a side is marked, wearing the octagon's own red or blue (src/00e_colours.js BBCol.corner). */
.r9-faceoff .p{position:relative}
.r9-faceoff .p>i.r9-cnr{display:block;width:26px;height:2px;background:var(--tc,var(--ink-faint));margin:0 auto 6px;border-radius:1px}


/* ======================================================================================================================
   [W40A 2026-09-25] THE V4 CARD ANATOMY - the bench copy of tools/host_css/119_represent.css, rule for rule.
   Owner, 25 Sep: "what we have is elite, it just needs to be presented better design/ux/ui wise ... minimal copy
   unless its a breakdown" / "how do we ensure we lose none of the incredible info we have". The words are not lost:
   the face keeps ONE number (or the organ's own picture), ONE line and a Breakdown row, and every other sentence is
   behind that row, in E.organModal. tools/noloss_test.py is the arithmetic.
   ⛔ KEEP THESE TWO FILES THE SAME. The bench reads src/scenes.css; prod reads the host css chain, which must never
   edit a minted file - so the identical rules ship as a NEW numbered host css and the chain line is an ask.
   ====================================================================================================================== */
/* ---- the title row: name left, three grey words right -------------------------------------------------------- */
#obtStage .r9-five .bc.r9-v4 .bh{display:flex;align-items:baseline;gap:8px;flex-wrap:nowrap}
/* ⛔ THE NAME AND ITS CONTEXT WRAP, THEY NEVER CLIP. MEASURED by tools/desk_law_test.py on the bench at 1600 and
   390: a nowrap title cut "What matters here" and a nowrap context cut "63 in 100 - price needs 47" - the one
   number on the pick card. scenes.css:539 has said `white-space:normal` for a card's label since W17B and this
   rule was over-riding it. Two lines of a 13 px name cost the card 17 px; a cut number costs it the reader. */
#obtStage .r9-five .bc.r9-v4 .bh .lab.r9m-open{font-family:var(--ui);font-size:13px;font-weight:700;line-height:1.25;
  letter-spacing:0;text-transform:none;min-width:0;white-space:normal;overflow:visible;text-overflow:clip;
  overflow-wrap:break-word;text-align:left}
#obtStage .r9-five .bc.r9-v4 .bh .lab.r9-sig.r9-ctx,
/* 12 px, not the brief's 11: the DESIGN LAW's floor is 12 px on a desktop and 13 px on a phone, and a law
   outranks a type scale. desk_law_test counted 21 elements under the floor on the first cut. */
#obtStage .r9-five .bc.r9-v4:not(.r9-leadcell) .bh .lab.r9-sig.r9-ctx{font-family:var(--ui);font-size:12px;
  font-weight:400;letter-spacing:0;text-transform:none;color:var(--ink-faint);margin-left:auto;flex:0 1 auto;
  min-width:0;max-width:64%;white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:break-word;
  text-align:right}

/* ---- the body is a column: hero, one line, then the Breakdown row pinned to the floor ------------------------- */
#obtStage .r9-five .bc.r9-v4>.bb{display:flex;flex-direction:column;gap:6px;min-height:0}
#obtStage .r9-five .bc.r9-v4>.bb>.r9-hero{min-width:0;max-width:100%}
#obtStage .r9-five .bc.r9-v4>.bb>.r9-hero>*{margin-top:0}

/* ---- rule 1: THE NUMBER ---------------------------------------------------------------------------------------
   One typeface, tabular figures, no letterform tricks. 44 px is the number; 32 px is a word or an "N of M", which
   is longer and would otherwise crash into the card's own edge. */
/* ⛔ AND THE HERO NEVER CLIPS EITHER. A number the card is built around, cut off by its own card, is the worst
   defect this package could ship; desk_law_test found nine of them at 1600 on the first cut. It wraps instead. */
#obtStage .r9-five .bc.r9-v4 .r9-hnum{font-family:var(--ui);font-size:44px;font-weight:800;line-height:1.02;
  letter-spacing:-.02em;color:var(--ink);padding:2px 0 0;white-space:normal;overflow:visible;
  overflow-wrap:break-word;font-variant-numeric:tabular-nums;text-transform:none}
#obtStage .r9-five .bc.r9-v4 .r9-hnum.r9-hmid{font-size:32px}
#obtStage .r9-five .bc.r9-v4 .r9-hnum.r9-callword{color:var(--tc,var(--ink))}

/* ---- rule 2: ONE LINE ------------------------------------------------------------------------------------------
   The full sentence is in the Breakdown; this is its first line and it never becomes two. */
#obtStage .r9-five .bc.r9-v4 .r9-oneline{font-size:13px;line-height:1.35;margin:0;color:var(--ink-dim);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
#obtStage .r9-five .bc.r9-v4 .r9-oneline b{color:var(--ink);font-weight:600}

/* ---- rule 3: THE BREAKDOWN ROW --------------------------------------------------------------------------------
   Context on the left (the organ's own segment tabs when it draws them, else the first phrase of its foot), the
   door on the right. A hairline above it, 12 px ink, 44 px of tap. */
#obtStage .r9-five .bc.r9-v4 .r9-bd{margin-top:auto;display:flex;align-items:center;justify-content:space-between;
  gap:10px;padding-top:6px;border-top:1px solid var(--line);font-size:12px;min-height:34px}
#obtStage .r9-five .bc.r9-v4 .r9-bdctx{color:var(--ink-faint);font-size:12px;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
/* the age in words for a live card - it sits where the context sits and it is never clamped away */
#obtStage .r9-five .bc.r9-v4 .r9-bdage{color:var(--ink-faint);font-size:12px;white-space:nowrap;flex:0 0 auto}
#obtStage .r9-five .bc.r9-v4 .r9-bdctx .r9-chips,#obtStage .r9-five .bc.r9-v4 .r9-bdctx .r9-seg,
#obtStage .r9-five .bc.r9-v4 .r9-bdctx .bbtab{margin:0;display:flex;gap:4px;flex-wrap:nowrap;border:0;padding:0}
#obtStage .r9-five .bc.r9-v4 .r9-bdctx .bbtab .bbtab-t{font-size:12px;padding:6px 6px;min-height:34px;
  display:inline-flex;align-items:center;white-space:nowrap}
#obtStage .r9-five .bc.r9-v4 .r9-bdbtn{font-family:var(--ui);font-size:12px;font-weight:600;color:var(--ink-dim);
  background:none;border:0;padding:6px 0 6px 10px;cursor:pointer;white-space:nowrap;min-height:34px;
  display:inline-flex;align-items:center}
#obtStage .r9-five .bc.r9-v4 .r9-bdbtn:hover{color:var(--ink)}
#obtStage .r9-five .bc.r9-v4 .r9-bdsrc{display:none!important}

/* ---- the pick card: the word is the hero, the money is the context, ONE Track it on the screen (the head's) ---- */
#obtStage .r9-five .r9-callcard .r9-hero.r9-herocall{padding:2px 0 0}
#obtStage .r9-five .r9-callcard .r9-hero.r9-herocall .r9-callgate{display:flex;flex-direction:column;gap:8px;
  align-items:flex-start}
#obtStage .r9-five .r9-callcard .r9-trackrow{display:none}
#obtStage .r9-five .r9-callcard>.bb>.r9-back{display:contents}

/* ---- rule 4: ONE THING PER SCREEN -----------------------------------------------------------------------------
   "More on this" stops being a row of chips and becomes one grey line, the way the brief draws it:
   More - a - b - c. The buttons keep their markup, their tap size and their handler; only the ink changes. */
#obtStage .r9-five .r9-morerow2{display:flex;align-items:center;gap:0;flex-wrap:wrap;font-size:12px;
  color:var(--ink-faint);border:0;padding:6px 0 0;background:none}
#obtStage .r9-five .r9-morerow2 .r9-morelab{font-size:12px;color:var(--ink-faint);letter-spacing:0;
  text-transform:none;margin-right:2px}
#obtStage .r9-five .r9-morerow2 .r9-morechip,#obtStage .r9-v2 .r9-morerow2 .r9-morechip{border:0!important;
  background:none!important;padding:6px 8px!important;color:var(--ink-dim)!important;font-size:12px!important;
  font-weight:400!important;border-radius:8px!important;min-height:34px}  /* [integrator 25 Sep 22:50] 8 px radius law (stops S8) */
#obtStage .r9-five .r9-morerow2 .r9-morechip:hover{color:var(--ink)!important;text-decoration:underline}
#obtStage .r9-five .r9-morerow2 .r9-morechip+.r9-morechip::before{content:"\00b7";color:var(--ink-faint);
  margin-right:8px;text-decoration:none;display:inline-block}

/* ---- the intro sentence above the grid: one compact grey line, not a two-line banner ------------------------- */
/* ⛔ COMPACT, NOT CLIPPED. MEASURED by tools/console_vet.py lens L7, 24 times across six leagues: a one-line clamp
   here reads as "1 clipped text in a tile with no door to read the rest" - and it is right, this sentence sits
   ABOVE the pane and has no door of its own. It is the bet's own condition ("Steelers need to win. If it ends
   level, your money comes back.") and the reader must be able to read all of it. So it comes down from 21 px bold
   to 13 px and WRAPS; two lines of 13 px is still less than one line of 21 px was. */
#obtStage .r9-five>.r9-rule{font-size:13px;line-height:1.35;font-weight:600;letter-spacing:0;color:var(--ink-dim);
  margin:0 0 2px;white-space:normal;overflow:visible;text-overflow:clip}
#obtStage .r9-five>.r9-pay{font-size:12px;color:var(--ink-faint);margin:0 0 8px;white-space:normal;overflow:visible;
  text-overflow:clip}

/* ---- the card room shrinks with the terminal: at 1150 the hero steps down (container query, as W36F) ---------- */
@supports (container-type:inline-size){
  #obtStage .r9-five .r9-pane6{container-type:inline-size;container-name:r9pane}
  @container r9pane (max-width:820px){
    #obtStage .r9-five .bc.r9-v4 .r9-hnum{font-size:32px}
    #obtStage .r9-five .bc.r9-v4 .r9-hnum.r9-hmid{font-size:26px}
  }
}

/* ---- phone: the same anatomy, 13 px floor, 44 px taps -------------------------------------------------------- */
@media (max-width:899px){
  #obtStage .r9-five .bc.r9-v4 .r9-oneline{font-size:13px}
  #obtStage .r9-five .bc.r9-v4 .r9-bd{font-size:13px;min-height:44px}
  #obtStage .r9-five .bc.r9-v4 .r9-bdctx,#obtStage .r9-five .bc.r9-v4 .r9-bdage{font-size:13px}
  #obtStage .r9-five .bc.r9-v4 .r9-bdbtn{font-size:13px;min-height:44px}
  #obtStage .r9-five .bc.r9-v4 .bh .lab.r9-sig.r9-ctx{font-size:13px;max-width:46%}
  #obtStage .r9-five .bc.r9-v4 .r9-bdctx .bbtab .bbtab-t{font-size:13px;min-height:44px}
  #obtStage .r9-five .bc.r9-v4 .bh .lab.r9m-open{font-size:15px}
  #obtStage .r9-five .r9-morerow2 .r9-morechip{font-size:13px!important;min-height:44px}
  #obtStage .r9-five>.r9-rule{font-size:14px}
  #obtStage .r9-five>.r9-pay{font-size:13px}
}

/* [integrator 2026-09-25 19:55 BB_REPRESENT_CSS_V175] dead space: the hero fills the card room between the title row and the floor; a picture card with its number above it steps the number to 28 px */
#obtStage .r9-five .bc.r9-v4>.bb>.r9-hero{flex:1 0 auto;min-height:0;display:flex;flex-direction:column;justify-content:center;gap:8px}
#obtStage .r9-five .bc.r9-v4 .r9-hnum.r9-hpic{font-size:28px;line-height:1.05}
#obtStage .r9-five .bc.r9-v4 .r9-hnum .r9-hsub{display:inline;font-size:13px;font-weight:600;color:var(--ink-faint);margin-left:8px;vertical-align:6px;letter-spacing:0}
/* [integrator 2026-09-25 21:36, light_theme L1 afl LEAN 4.16:1] on a LIGHT stamp the confidence word takes the ink, not the club colour - a club red on a white ground does not clear 4.5:1 */
:root[data-theme="light"] #obtStage .r9-five .bc.r9-v4 .r9-hnum.r9-callword{color:var(--ink)}
/* [integrator 2026-09-25 21:45, stops S8 "a More chip corner is 0px and must be 8px" x30] the More row is one grey line of links, and a link is still a control under the 8 px radius law */
#obtStage .r9-five .r9-morerow2 .r9-morechip{border-radius:8px}
/* [integrator 2026-09-25 22:58, LOOKED AT after_nfl_390_call.png] the phone call card carries the bet condition line above the word; it is a caption, not a headline */
#obtStage .r9-five .r9-callcard.r9-v4>.bb>.r9-rule{font-size:13px;font-weight:400;color:var(--ink-faint);line-height:1.3;margin:0 0 2px}
/* [integrator 2026-09-25 23:00, LOOKED AT after_nfl_1440_call.png] the pick stop rule line above the pane is a caption like the other stops, never a headline */
#obtStage .r9-five>.r9-rule{font-size:13px!important;font-weight:400!important;color:var(--ink-faint)!important;line-height:1.3;margin:0 0 6px}
/* BB_SELECTSCHEME_CSS_V176 [lane lead 2026-09-26 08:18, OWNER on prod #35: "the dropdown has font color you cant read"]
   MEASURED on prod as a guest at 1440: every native <select> on the page (the bet picker obt-msel / obt-ssel, the board's
   obtRegion / obtBook / obtSort) computes color rgb(232,237,245) with color-scheme: normal - so Windows paints the OPEN list
   on a white sheet and the light ink is unreadable on it. The picker stays native (DESIGN law); the browser is told the
   control is dark, so the open list takes the dark sheet and the same ink, and every option says so itself as well. */
.obt-page select, #obtStage select, #obtBar select, .obt-app select, select.obt-sel, #obt-msel, #obt-ssel, #obt-lsel,
#obtRegion, #obtBook, #obtSort { color-scheme: dark; }
.obt-page select option, #obtStage select option, .obt-app select option, #obt-msel option, #obt-ssel option, #obt-lsel option,
#obtRegion option, #obtBook option, #obtSort option { color: #e8edf5; background-color: #15171f; }

/* ================================================================================================================
   [W41 2026-09-26] THE CARD SIDE OF "CLUB COLOURS LEAD" - the same rules for the bench and for prod.
   The owner picked variant 2 of round10w/proto/odds-console-variations.html ("club colors led is cool i like that
   ... just make sure font colors work"), and in it every reading card carries a 3px rule across its top in the
   chosen side's colour and a 14px corner ("i dont like square things. i like border radius").
   THE COLOUR IS --tc AND NOTHING ELSE: the bet side's club colour, already measured by BBCol.pick against the real
   ground behind the console, and simply absent when that club has no colour we can honestly draw - in which case
   these rules fall back to the hairline the card has today. A 3px rule is not text, so it carries no reading
   contrast of its own; the CALL WORD above it keeps the ink rule it already had (line 1303, and the light-theme
   guard at 1390), and the chips, the Track it and the head - the surfaces that do carry words on a colour - are
   host css 121_clublead.css, where the ink is picked by measurement.
   ================================================================================================================ */
#obtStage .obt-bento.r9-grid.r9-v2 .bc,
#obtStage .obt-bento.r9-grid.r9-v2 > .bc,
#obtStage .obt-bento.r9-grid.r9-v2 .r9-pane > .bc{
  border-top:3px solid var(--tc,var(--line))!important;
  border-radius:14px!important;
}

/* Part 0c css — LE-4, 2026-09-16. ONE sentence: the honest state of the live bundle while it is in flight, or the
   honest state when it will not come. House style only: one typeface var(--ui), the quiet ink var(--ink-faint), one
   hairline var(--line). No spinner, no pill, no colour, no icon — a reader who is told the truth in a sentence does
   not need a machine noise, and a spinner that never ends is the exact defect this file exists to avoid.
   It lives in the MAIN bundle (not the live one) because it has to be paintable before the live css exists. */

.r9-liveload {
  font-family: var(--ui);
  font-size: 13px;
  line-height: 1.45;
  color: var(--ink-faint);
  margin: 0 0 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
}

/* the failed sentence is the one a reader must actually finish reading, so it takes the full ink — still no colour */
.r9-liveload[data-state="failed"] { color: var(--ink-dim); }

@media (max-width: 899px) {
  .r9-liveload { font-size: 12.5px; padding: 7px 0; margin: 0 0 8px; }
}

/* Part 0d (css): the scene-side pieces of the hero package — [W10A 2026-09-16].
   ================================================================================================================
   The hero BAND's own type and layout live in tools/host_css/83_hero.css, because the band is host markup and has
   to be dressed in the first paint, before this bundle is fetched. What is left here is the one thing the SCENE
   engine draws for this package: the cover map's no-side state (src/01a_cover.js, critique D4) — the two clubs
   named in their own colours where a broken dashed box used to be.

   Design law: one typeface, inks, hairlines. The club colour is a 3px mark beside the name, not a fill behind it:
   a filled chip at this size is the pill the owner rejected on 09-15.
   ================================================================================================================ */

.bbcv{display:flex;flex-wrap:wrap;align-items:center;gap:14px;margin:8px 0 2px}
.bbcv .bbcv-tm{display:inline-flex;align-items:center;gap:7px;font-family:var(--ui);font-size:.9rem;
  font-weight:600;color:var(--ink);line-height:1.25;min-width:0}
.bbcv .bbcv-tm i{display:block;width:3px;height:15px;flex:0 0 auto;background:var(--tc,var(--ink-dim))}

@media (max-width:899px){
  .bbcv{gap:12px}
  .bbcv .bbcv-tm{font-size:.86rem}
}

/* WP-P5 — "your record, in the console". House style only: one typeface var(--ui), two text colours
   var(--ink) / var(--ink-faint), hairlines var(--line). No pills, no status colours, no badges, no avatars.
   A reader's own record is stated in plain rows; a losing row looks exactly like a winning one. */

/* 1. THE CALL TAB LINE — directly under .r9-pay, printed by 04_engine.js callBlock(). Same size as the pay line, so
      the head reads rule (21px) -> pay (14px) -> your record (14px) and nothing shouts. */
.r9-five .r9-mine { font-family: var(--ui); font-size: 14px; line-height: 1.45; color: var(--ink-faint); margin: -4px 0 10px; }
.r9-five .r9-mine b { color: var(--ink); font-weight: 600; }

/* 2. THE ORGAN TABLE — three hairline rows, label and numbers on one baseline. The label is allowed to WRAP: nothing
      in this lane may be sliced sideways (phone gate F1), so there is no ellipsis and no overflow:hidden anywhere. */
.r9-minetbl { margin: 2px 0 0; }
.r9-minetbl .r9mn-row { display: grid; grid-template-columns: minmax(0, 12em) minmax(0, 1fr); gap: 0 14px; align-items: baseline; padding: 7px 0; border-bottom: 1px solid var(--line); }
.r9-minetbl .r9mn-row:last-of-type { border-bottom: 0; }
.r9-minetbl .l { margin: 0; font-family: var(--ui); font-size: 13px; line-height: 1.4; color: var(--ink-faint); min-width: 0; overflow-wrap: anywhere; }
.r9-minetbl .v { margin: 0; font-family: var(--ui); font-size: 13px; line-height: 1.4; color: var(--ink-faint); min-width: 0; overflow-wrap: anywhere; }
.r9-minetbl .v b { color: var(--ink); font-weight: 600; }

/* 3. THE OPEN LEGS ON THIS GAME — one sentence, never a card. */
.r9-five .r9-mineopen { font-family: var(--ui); font-size: 13px; line-height: 1.45; color: var(--ink-faint); margin: 8px 0 0; }
.r9-five .r9-mineopen b { color: var(--ink); font-weight: 600; }

/* 4. PHONE (the one breakpoint this lane uses: max-width 899px). The two columns stack, because a 12em label column
      on a 320px screen leaves the numbers nowhere to go. Nothing here paints under 12px (phone gate F4). */
@media (max-width: 899px) {
  .r9-minetbl .r9mn-row { grid-template-columns: minmax(0, 1fr); gap: 2px; padding: 8px 0; }
  .r9-five .r9-mine { font-size: 13.5px; margin: -2px 0 10px; }
}

/* 01ab_situation.css - WHAT MATTERS HERE (W40B, 2026-09-25).
   Three rows, each a label, a count and the hit organ's own tick strip. No new colour, no new typeface, no pill and
   no gauge: var(--ui), the two inks and the one hairline the rest of the console is built from.
   FLOORS. 13 px on both the label and the count, so the phone floor (13) and the desktop floor (12) are both clear
   with the same rule - drawing_fit_test and desk_law_test read every one of these.
   THE STRIP IS A ROW, NEVER A WALL. .r9-ticks2.s is 16 px square and wraps; inside this card it is 10 px, it does
   not wrap, and it is capped at eight games by the organ, so a row is one line at a 300 px tile (1440, three
   columns) and at 358 px (390 phone). */
.r9sit{display:flex;flex-direction:column;gap:7px;margin:2px 0 0}
/* [integrator 2026-09-25 22:05, desk_law clipped 1: afl 390 call, the label "At home" cut at 38 px] the label WRAPS
   before it is ever cut: at 390 the count and the eight-game strip take the room and the label takes what is left. */
/* [lane lead 2026-09-26 15:40, LOOKED at afl Form 1150 after the break-word cut: 'At home' still ran A / t / h] the label keeps a
   7ch floor and the row WRAPS, so when the count and the eight-game strip take the room the strip drops under the label instead
   of the label being squeezed to a column of letters. At 390 and 1440 nothing moves (the row had room there). */
.r9sit-r{display:flex;flex-wrap:wrap;align-items:flex-start;gap:4px 8px;min-height:20px}
/* [lane lead 2026-09-26 14:30, LOOKED at afl Form 1150: 'At home' printed as A / t / h down the column] overflow-wrap:anywhere
   breaks INSIDE a word even when the word fits on the next line; break-word only breaks a word that cannot fit a line by
   itself, so the label wraps at the space first and a short word is never spelt down the column. */
.r9sit-r > .l{font:600 13px/1.2 var(--ui);color:var(--ink-dim);flex:1 1 auto;min-width:7ch;white-space:normal;overflow-wrap:break-word}
.r9sit-r > .n{font:700 13px/1.2 var(--ui);color:var(--ink);flex:0 0 auto;font-variant-numeric:tabular-nums;white-space:nowrap}
.r9sit-r .r9-ticks2{margin:0;gap:3px;flex:0 0 auto;flex-wrap:nowrap}
.r9sit-r .r9-ticks2 i{width:10px;height:10px}
/* the live row is the one the reader is standing in, so its label is full ink and nothing else changes */
.r9sit-r.live > .l{color:var(--ink)}
/* the Breakdown: every situation the payload has, all games first */
.r9sit-tbl{width:100%;border-collapse:collapse;font:400 13px/1.35 var(--ui);margin:2px 0 6px}
.r9sit-tbl td{padding:5px 0;border-bottom:1px solid var(--line);color:var(--ink-dim)}
.r9sit-tbl td.r{text-align:right;font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums;white-space:nowrap}
.r9sit-tbl tr.a td{font-weight:700;color:var(--ink)}

/* 01c_hit.css - WP-HIT. House style only: one typeface (var(--ui)), two text colours, hairlines. No colour, no pills. */
.r9-five .r9h-cap{font-family:var(--ui);font-size:15px;line-height:1.5;margin:6px 0 0;color:var(--ink)}
.r9-five .r9h-cap b{font-weight:600}
.r9-five .r9h-sub{font-family:var(--ui);font-size:13px;line-height:1.5;color:var(--ink-faint);margin:3px 0 0}
.r9-five .r9h-lbl{font-family:var(--ui);font-size:12px;color:var(--ink-faint);margin:6px 0 2px}
.r9-five .r9-helpers .r9h-cap{font-size:14px;line-height:1.42}
.r9-modal .r9h-cap{font-family:var(--ui);font-size:14px;line-height:1.5;margin:6px 0 0;color:var(--ink)}
.r9-modal .r9h-sub{font-family:var(--ui);font-size:13px;line-height:1.5;color:var(--ink-faint);margin:6px 0 0}

/* ⛔ [W24B 2026-09-20] .r9h-sph HAD NO RULE ANYWHERE IN THE ESTATE.
   The ladder's reading sheet has printed <h4 class="r9h-sph"> since W23B and every one of them rendered as a
   BROWSER-DEFAULT h4: the user agent's own bold face (not var(--ui)), its own size, and 1.33em of margin above and
   below - inside a sheet whose whole design law is one typeface and hairlines. Grepped: `.r9h-sph` appears in no
   .css file on the tree, while the rates file's near-twin `.r9r-sph` is fully styled. It is a typo that has been
   shipping as a design defect. This is that rule, matched to .r9r-sph so the two sheets read as one system, and it
   is scoped nowhere in particular because a reading sheet is the only place these heads appear. */
.r9h-sph{font-family:var(--ui);font-size:13px;font-weight:600;letter-spacing:0;text-transform:none;
  color:var(--ink);margin:16px 0 0;padding-top:10px;border-top:1px solid var(--line)}
.r9-modal .r9h-sph{margin-top:14px}
.r9-modal .r9h-sph:first-child{margin-top:0;padding-top:0;border-top:0}
@media (max-width:820px){.r9h-sph{font-size:12.5px;margin-top:14px}}

/* the ladder: one rung per number, the one you are on marked with a rule above it */
.r9h-lad{display:flex;gap:0;margin:6px 0 0;border-top:1px solid var(--line);font-family:var(--ui);flex-wrap:wrap}
.r9h-lad>*{flex:1 1 140px;min-width:120px;padding:8px 10px 8px 0;font-size:13px;border-right:1px solid var(--line);margin-right:10px;
  background:none;border-top:0;border-bottom:0;border-left:0;text-align:left;color:var(--ink-faint);font-family:inherit;cursor:pointer}
.r9h-lad>*:last-child{border-right:0;margin-right:0}
.r9h-lad>*.on{border-top:2px solid var(--ink);margin-top:-1px}
.r9h-lad b{display:block;font-size:15px;font-weight:600;color:var(--ink)}
.r9h-lad span{display:block;color:var(--ink-faint)}
.r9h-lad button:hover b{border-bottom:1px solid var(--ink)}
.r9h-lad button:focus-visible{outline:1px solid var(--ink);outline-offset:2px}
@media (max-width:1100px){.r9h-lad>*{flex:1 1 100%;border-right:0;margin-right:0;border-bottom:1px solid var(--line)}}

/* [W14B 2026-09-17] WHAT DRIVES THE CALL (brief addition 3). The arrow sits in its own column so three drivers
   read as a ranked list and not as three paragraphs; it takes the bet side's club colour where the card has one
   and the plain ink where it does not, and it is never the only carrier of meaning (the words say it too). */
.r9h-drv{display:grid;grid-template-columns:16px 1fr;gap:8px;align-items:start}
.r9h-ar{color:var(--tct,var(--ink));font-size:15px;line-height:1.45;font-weight:600}

/* [W21B 2026-09-19] THE DRIVER SPLIT, DRAWN. Two bars per driver: the half the sentence leads with, then the
   other. Hairlines and one club colour (--tc, from BBCol.pick); no gradient, no glow, no pill, 8 px radii, and
   every number at or above the 13 px phone / 12 px desktop floor. The bar is a <i> inside a track so the width
   is the only thing that moves - no transform, no repaint of the row. */
.r9h-dblk{margin:0 0 10px}
.r9h-dblk:last-child{margin-bottom:0}
.r9h-dsp{display:grid;gap:3px;margin:0 0 4px}
.r9h-dr{display:grid;grid-template-columns:86px 1fr auto;gap:8px;align-items:center}
.r9h-dl{font:400 12px/1.3 var(--ui);color:var(--ink-faint);white-space:nowrap}
.r9h-db{display:block;height:10px;border-radius:2px;background:rgba(128,150,180,.14);overflow:hidden}
.r9h-db>i{display:block;height:100%;border-radius:2px;background:rgba(128,150,180,.45)}
.r9h-dr.on .r9h-db>i{background:var(--tc,var(--ink-dim))}
.r9h-dr.on .r9h-dl,.r9h-dr.on .r9h-dn{color:var(--ink)}
.r9h-dn{font:600 13px/1.2 var(--ui);color:var(--ink-dim);font-variant-numeric:tabular-nums;white-space:nowrap}
@media (max-width:899px){
  .r9h-dl{font-size:13px}
  .r9h-dr{grid-template-columns:92px 1fr auto}
}

/* [W21B] the tick row when it stands in for the spread bands: the same object, just the picture the card opens on */
.r9h-upticks{margin:0 0 8px}

/* 01d_aus.css — [WP-AUS] the AFL + NRL organs. House style only: one typeface, two text colours, hairlines.
   No colour, no pills, no badges. Every rule here is namespaced r9-aus-* except the two shared blocks it reuses. */

/* the jumper number in front of a named player */
.r9-aus-num { display: inline-block; min-width: 1.6em; color: var(--ink-faint); font-variant-numeric: tabular-nums; }

/* the running total beside a goals.behinds cell on the scoreboard */
.r9-aus-f { color: var(--ink-faint); font-variant-numeric: tabular-nums; }

/* the three biggest try scorers, with real faces (or initials) */
.r9-aus-faces { display: flex; gap: 26px; flex-wrap: wrap; margin-top: 10px; padding-top: 12px; border-top: 1px solid var(--line); }
.r9-aus-faces .p { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 4px; min-width: 110px; }
.r9-aus-faces .p b { font-size: 13px; color: var(--ink); font-weight: 600; }
.r9-aus-faces .p span { font-size: 12px; color: var(--ink-faint); line-height: 1.3; }

@media (max-width: 900px) {
  .r9-aus-faces { gap: 16px; }
  .r9-aus-faces .p { min-width: 92px; }
  /* [W13C 2026-09-17] 13px IS THE PHONE FLOOR. "winger" and "13 tries in 14 games" are the two lines that say who
     the man is and what he does - read text, not decoration - and at 12px they were the last sub-floor words on the
     nrl and afl matchup tabs (console vet L7, "4 text under the floors"). The column wraps rather than clips, so a
     longer line costs a second row and never a cut word. A desktop keeps 12px, which is its own floor. */
  .r9-aus-faces .p span { font-size: 13px; }
}

/* 01e_gridiron.css — WP-NFL (NFL + NCAAF). House style only: hairlines, two text colours, one typeface.
   Nothing here introduces a colour, a gradient, a pill or a badge; it only lays the drive boards out. */

/* the two drive boards, side by side on a wide lead cell, stacked on anything narrower */
.r9-drives { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; margin: 12px 0 2px; }
.r9-drives > .r9-gd { min-width: 0; }
.r9-gd .r9-gdh { display: block; font-family: var(--ui, Geist, system-ui, sans-serif); font-size: 13px; color: var(--ink-faint); margin: 0 0 4px; }
.r9-gd .obt-chartwrap { margin: 0; }
.r9-gd svg { max-width: 100%; height: auto; display: block; }
@media (max-width: 1100px) { .r9-drives { grid-template-columns: 1fr; } }

/* the drive board inside the deeper door gets the full width of the cell */
.r9-five .r9-deeper .r9-drives { grid-template-columns: 1fr; }

/* the injury report is a wide table: let the last column breathe and never scroll the page sideways */
.bc[data-organ="injrep"] .r9-table { table-layout: auto; }
.bc[data-organ="injrep"] .r9-table td:last-child, .bc[data-organ="injrep"] .r9-table th:last-child { width: 46%; }
.bc[data-organ="injrep"] .r9-table td:nth-child(n+3):nth-child(-n+5) { white-space: nowrap; color: var(--ink-faint); }
.bc[data-organ="injrep"] .r9-table tr.me td:nth-child(n+3):nth-child(-n+5) { color: var(--ink); }

/* every wide gridiron table scrolls inside its own cell rather than pushing the grid out */
.bc[data-organ="injrep"] .r9-table, .bc[data-organ="gstyle"] .r9-table, .bc[data-organ="alts"] .r9-table,
.bc[data-organ="gdepth"] .r9-table, .bc[data-organ="gdvp"] .r9-table { display: table; width: 100%; }
.bc[data-organ="gstyle"] .r9-table th:first-child, .bc[data-organ="qbeff"] .r9-table th:first-child { width: 58%; }
.bc[data-organ="qbeff"] .r9-table tr:first-child th { border-bottom: 0; padding: 0; }

/* the rung table's "take this one" control is a plain hairline link, like every other control in the console */
.bc[data-organ="alts"] .r9-morelink { font-size: 13px; }

/* Part 1f CSS: MLB (WP-MLB). Nothing new is invented here - the lineup card, the linescore and the pitcher box all
   reuse the kit's shapes (.r9-table, .r9-faceoff, .r9-cols, the hairline surfaces). These rules only tighten the two
   places baseball needs it: a batting order reads as a card, and a linescore reads as a linescore. */

/* the lineup card and the linescore: tabular figures, a narrow slot column, the man in focus in solid ink */
.bc[data-organ="lineupcard"] .r9-table,
.bc[data-organ="linescore"] .r9-table { font-variant-numeric: tabular-nums; }
.bc[data-organ="lineupcard"] .r9-table th:first-child,
.bc[data-organ="lineupcard"] .r9-table td:first-child { width: 2.2em; color: var(--ink-faint); }
.bc[data-organ="lineupcard"] .r9-table tr.me td:first-child { color: var(--ink); }
.bc[data-organ="lineupcard"] .r9-table td:nth-child(3) { color: var(--ink-faint); }
.bc[data-organ="lineupcard"] .r9-table tr.me td { font-weight: 600; }

/* the linescore: every inning column the same width, the run column set apart by a hairline */
.bc[data-organ="linescore"] .r9-table th,
.bc[data-organ="linescore"] .r9-table td { padding-right: 6px; }
.bc[data-organ="linescore"] .r9-table th:first-child,
.bc[data-organ="linescore"] .r9-table td:first-child { text-align: left; padding-right: 14px; white-space: nowrap; }
.bc[data-organ="linescore"] .r9-table th:last-child,
.bc[data-organ="linescore"] .r9-table td:last-child { border-left: 1px solid var(--line); padding-left: 8px; }

/* a batting order is a card, not a full-width table: hold it to a card's width even in the lead cell */
.bc[data-organ="lineupcard"] .r9-table { max-width: 620px; }
/* both orders side by side (a team, line or total bet): each card takes its own half of the lead cell */
.bc[data-organ="lineupcard"] .r9-cols .r9-table { max-width: none; }
.bc[data-organ="lineupcard"] .r9-cols h4 { margin-bottom: 2px; }

/* The two drawings that carry real marks - the diamond and the strike zone - take two helper columns through the
   house class span2 (scenes.css pins every .bc to grid-column:auto!important, so only span2/span3 can widen one).
   Below 899px scenes.css drops the span, which is right: one column, one drawing. */

/* neither drawing ever stretches past the size it was drawn at */
.bc[data-organ="park"] .r9-one svg { max-width: 340px; }
.bc[data-organ="spray"] .r9-one svg { max-width: 360px; }

/* the strike zone, in HTML so its counts never scale: an SVG in a 250px helper column shrinks its own text under the
   11px floor. Hairline cells, the busiest one underlined in ink, the dashed frame = everything outside the zone. */
/* every class is namespaced: the host stylesheet owns bare names like .cap (8.96px mono) and .grid, and inheriting one
   by accident drops a caption under the 11px floor. */
.mlb-zone { margin: 8px 0 0; max-width: 330px; font-family: var(--ui); }
.mlb-zone .mlb-grid { display: grid; grid-template-columns: repeat(3, 1fr); border: 1px dashed var(--line); padding: 7px; gap: 0; }
.mlb-zone .mlb-z { border: 1px solid var(--line); padding: 7px 4px 6px; text-align: center; min-width: 0; }
.mlb-zone .mlb-z b { display: block; font-size: 17px; font-weight: 500; color: var(--ink); line-height: 1.1; font-variant-numeric: tabular-nums; }
.mlb-zone .mlb-z i { display: block; font-style: normal; font-size: 11px; color: var(--ink-faint); margin-top: 2px; }
.mlb-zone .mlb-z.on { box-shadow: inset 0 -4px 0 var(--ink); }
.mlb-zone .mlb-z.on b { font-weight: 600; }
.mlb-zone .mlb-cap { font-family: var(--ui); font-size: 12px; line-height: 1.35; letter-spacing: 0; text-transform: none; color: var(--ink-faint); margin: 0 0 5px; }
.mlb-zone .mlb-grid + .mlb-cap { margin: 5px 0 0; }

/* the three field shares under the spray diamond: the kit's column shape, one line each, never inside the plot */
.bc[data-organ="spray"] .mlb-wedges { margin-top: 6px; }
.bc[data-organ="spray"] .mlb-wedges > div { padding: 6px 10px 6px 0; margin-right: 10px; }
.bc[data-organ="spray"] .mlb-wedges h4 { font-size: 12px; font-weight: 400; color: var(--ink-faint); margin-bottom: 1px; }
.bc[data-organ="spray"] .mlb-wedges p { font-size: 13px; }

/* Part 1g CSS: SOCCER organs (WP-SOCCER). House style only — one typeface var(--ui), two text colours
   var(--ink) / var(--ink-faint), hairlines var(--line). No gradients, pills, colour tags or rounded card stacks.
   Everything here is a layout helper; every shape inside is one of the five allowed shapes. */

/* A pitch or a bar chart cannot be read in a quarter of the helper row. ⛔ scenes.css pins every .bc to
   grid-column:auto with an ID-qualified !important, so the WIDTH itself has to come from the house classes span3
   (the whole row) and span2 (two of the four columns) — this package's organs set "span3 r9soc-wide" /
   "span2 r9soc-half" and these rules only clean up the hairline and the padding beside them. */
#obtStage .r9-five .r9-helpers > .bc.r9soc-wide, #obtStage .r9-five .r9-deeper > .bc.r9soc-wide { border-right: 0 !important; margin-right: 0 !important; padding-right: 0 !important; }
#obtStage .r9-five .r9-helpers > .bc.r9soc-wide + .bc, #obtStage .r9-five .r9-deeper > .bc.r9soc-wide + .bc { border-top: 1px solid var(--line); padding-top: 10px; }

/* two sides of the same fact, side by side (both teams named, both set-piece lists) */
.r9soc-two { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; align-items: start; }
.r9soc-two > div { min-width: 0; }
@media (max-width: 720px) { .r9soc-two { grid-template-columns: 1fr; gap: 14px; } }

.r9soc-h4 { font-family: var(--ui); font-size: 13px; font-weight: 600; color: var(--ink); margin: 2px 0 6px; padding-bottom: 4px; border-bottom: 1px solid var(--line); }

/* set-piece takers: a face (or initials), the name, what he takes */
.r9soc-spg { min-width: 0; }
.r9soc-sp { display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto auto; column-gap: 10px; align-items: center; padding: 6px 0; border-bottom: 1px solid var(--line); }
.r9soc-sp:last-child { border-bottom: 0; }
.r9soc-sp > span:first-child { grid-row: 1 / span 2; display: inline-flex; }
.r9soc-sp b { font-family: var(--ui); font-size: 14px; font-weight: 600; color: var(--ink); line-height: 1.2; }
/* [W13C 2026-09-17] 13px IS THE PHONE FLOOR. This line says what the man actually does ("takes the corners",
   "takes the penalties") - the reading, not decoration - and at 12px it was under the floor on every soccer
   matchup tab (console vet L7, "text under the floors", epl). A desktop's floor is 12, so only the phone moves. */
.r9soc-sp > span:last-child { font-family: var(--ui); font-size: 12px; color: var(--ink-faint); }
@media (max-width: 900px) { .r9soc-sp > span:last-child { font-size: 13px; } }

/* Part 1h CSS: WP-OTHER (NBA / WNBA / NCAAB / NHL / UFC / cricket / tennis).
   House style only: one typeface var(--ui), two text colours var(--ink) / var(--ink-faint), hairlines var(--line).
   No gradients, no pills, no gold, no coloured tags, no rounded card stacks. Prefixed r9o- so nothing collides. */

/* two blocks side by side (the two fighters, the two teams, the two boards) */
/* [W36D 2026-09-25] TWO-UP ONLY WHEN THERE IS ROOM FOR TWO, MEASURED. `1fr 1fr` is minmax(auto, 1fr) twice, so in a
   161 px body (cricket, 1150, the half-width toss card) the table's own min-content took the row and the drawing was
   painted into 40 px: its labels came out at 3.4 px (vet L7 'svg text 3.4px painted', 4 views; scratch w36d_probe:
   .r9o-two 161 > .r9c 40 > svg 40x19). 150 is K.roomTwo's own floor for one half, so a column is never narrower
   than the drawing was authored for, and below two of them the halves stack - which is what the phone rule below
   already does for every width under 900. */
.r9o-two { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 22px; align-items: start; font-family: var(--ui); }
.r9o-two > div > h4 { font-size: 13px; font-weight: 600; color: var(--ink); margin: 0 0 6px; }
.r9o-two p { font-size: 13px; line-height: 1.45; color: var(--ink-faint); margin: 6px 0 0; }
.r9o-two p b { color: var(--ink); font-weight: 600; }
@media (max-width: 900px) { .r9o-two { grid-template-columns: 1fr; gap: 14px; } }

/* the tale of the tape: the two men across the width, the octagon held to one column so its labels stay at
   reading size instead of being blown up to the width of the card */
.r9o-tape { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 18px; align-items: center; }
.r9o-tape > .obt-chartwrap { max-width: 320px; margin: 0; }
@media (max-width: 900px) { .r9o-tape { grid-template-columns: 1fr; } .r9o-tape > .obt-chartwrap { max-width: 360px; } }

/* the five round blocks under the tale of the tape */
.r9o-rounds { display: flex; gap: 6px; justify-content: center; margin: 8px 0 0; }
.r9o-rounds i { width: 34px; height: 12px; border: 1px solid var(--line); display: block; box-sizing: border-box; }
.r9o-rounds i.y { background: var(--ink); }
.r9o-rlab { text-align: center; font-size: 12px; color: var(--ink-faint); margin: 6px 0 0; font-family: var(--ui); }
.r9o-two .r9o-rounds { justify-content: flex-start; }
.r9o-two .r9o-rlab { text-align: left; }

/* the NHL lines board: four lines then three pairs, hairline columns */
.r9o-board { font-family: var(--ui); }
.r9o-board > h4 { font-size: 13px; font-weight: 600; color: var(--ink); margin: 0 0 6px; }
.r9o-units { display: grid; grid-template-columns: repeat(4, 1fr); border-top: 1px solid var(--line); }
.r9o-units + .r9o-units { grid-template-columns: repeat(3, 1fr); margin-top: 8px; }
.r9o-unit { padding: 6px 10px 8px 0; border-right: 1px solid var(--line); }
.r9o-unit:last-child { border-right: 0; }
.r9o-unit h5 { font-size: 11px; font-weight: 400; color: var(--ink-faint); margin: 0 0 4px; }
.r9o-unit div { display: flex; justify-content: space-between; gap: 8px; font-size: 12.5px; color: var(--ink); padding: 1px 0; white-space: nowrap; }
.r9o-unit div span:first-child { overflow: hidden; text-overflow: ellipsis; }
.r9o-unit div span:last-child { color: var(--ink-faint); font-variant-numeric: tabular-nums; flex: 0 0 auto; }
.r9o-unit div.me { font-weight: 600; }
.r9o-unit div.me span:last-child { color: var(--ink); }
@media (max-width: 900px) { .r9o-units, .r9o-units + .r9o-units { grid-template-columns: repeat(2, 1fr); } }

/* the tennis set-score line under the face-off.
   ⛔ scenes.css styles EVERY div inside .r9-faceoff .tape as a three-column row, so these rules have to out-specify it
   (three classes + the type) or the set scores get laid out across that grid three at a time. */
.r9o-setline { border-top: 1px solid var(--line); margin-top: 8px; font-family: var(--ui); }
.r9-faceoff .tape .r9o-setline { display: block; border-bottom: 0; padding: 0; }
.r9o-setline div,
.r9-faceoff .tape .r9o-setline div { display: grid; grid-template-columns: 92px 1fr 104px; font-size: 13px; padding: 3px 0; border-bottom: 1px solid var(--line); color: var(--ink-faint); }
.r9o-setline div b,
.r9-faceoff .tape .r9o-setline div b { text-align: center; color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.r9o-setline div span:last-child,
.r9-faceoff .tape .r9o-setline div span:last-child { text-align: right; }
.r9-faceoff .tape .r9o-setline div span:first-child { text-align: left; }

/* [W25B 2026-09-20] each fighter's last five under the tale of the tape (item 5). Two strips, hairline-separated,
   the same record object the rest of the console uses - no new colours, no new shapes. */
#obtStage .r9o-l5,.r9-modal .r9o-l5{margin:10px 0 0;padding-top:8px;border-top:1px solid var(--line)}
#obtStage .r9o-l5 .bbs-rec,.r9-modal .r9o-l5 .bbs-rec{margin:4px 0 0}
#obtStage .r9o-l5 .bbs-cap,.r9-modal .r9o-l5 .bbs-cap{font-size:12px}
@media (max-width:760px){#obtStage .r9o-l5 .bbs-cap,.r9-modal .r9o-l5 .bbs-cap{font-size:13px}}

/* [integrator 2026-09-20, seen on the list #21 bench at 1440] THE UFC TAPE IN A TILE. .r9o-tape is a two-column grid whose second
   column is a fixed 320 px and .r9-faceoff carries a fixed 250 px middle - both written for a full-width lead seat. In the v2 frame
   every desktop tile is ~265 px wide, so the octagon painted across both men's names and the right-hand name was cut to 'Willia'.
   Inside a TILE the tape is one column, the face-off shares the width it has, and the octagon is left to the reading sheet (the
   sheet lives outside #obtStage, so nothing here touches it). */
#obtStage .bc .r9o-tape { grid-template-columns: minmax(0, 1fr); gap: 8px; }
#obtStage .bc .r9o-tape > .obt-chartwrap { display: none; }
#obtStage .bc .r9o-tape .r9-faceoff { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 6px 12px; align-items: start; }
#obtStage .bc .r9o-tape .r9-faceoff > .tape { grid-column: 1 / -1; order: 3; min-width: 0; }
#obtStage .bc .r9o-tape .r9-faceoff > .p:last-of-type { text-align: right; }

/* WP-DEAL — Where to put it, the browse layer and the honest multi. Direction One only: one typeface (var(--ui)),
   two text colours (var(--ink) / var(--ink-faint)), hairlines (var(--line)). No pills, no gradients, no colour tags.
   Every shape here is one of the approved ones: the price row, the tick row, the plain table. */
.r9d-apps{font-family:var(--ui);margin-top:4px}
.r9d-apps>div{display:grid;grid-template-columns:minmax(120px,180px) 70px 90px 1fr;padding:6px 0;border-bottom:1px solid var(--line);font-size:14px;align-items:baseline;color:var(--ink)}
.r9d-apps>div.h{color:var(--ink-faint);font-size:13px}
.r9d-apps>div.me{font-weight:600}
.r9d-apps>div span:last-child{color:var(--ink-faint);font-size:13px}

/* the ladder's own styles are WP-HIT's (.r9h-lad in 01c_hit.css): one home per organ, one set of styles with it. */

.r9d-note{font-size:13px;color:var(--ink-faint);margin:6px 0 0;line-height:1.5;font-family:var(--ui)}
.r9d-inline{font-size:14px;color:var(--ink);font-family:var(--ui);vertical-align:middle}
.r9d-btn{font-family:var(--ui);font-size:14px;color:var(--ink);background:none;border:1px solid var(--line);padding:6px 14px;cursor:pointer}
.r9d-btn:hover,.r9d-btn:focus-visible{border-color:var(--ink)}
.r9d-btn.g{border-color:var(--ink);font-weight:600}
.r9d-btn[disabled]{opacity:.5;cursor:default}
.r9d-chips{display:flex;gap:8px;margin:6px 0 8px;font-size:13px;font-family:var(--ui)}
.r9d-chips .r9d-chip{border:1px solid var(--line);padding:4px 12px;background:none;color:var(--ink-faint);font-family:inherit;font-size:13px;cursor:pointer}
.r9d-chips .r9d-chip.on{border-color:var(--ink);color:var(--ink);font-weight:600}

.r9d-tn{font-family:var(--ui);margin-top:4px}
.r9d-tn>div.h,.r9d-tn>button{display:grid;grid-template-columns:46px minmax(130px,1.5fr) minmax(80px,1fr) 58px 96px 148px 84px;gap:10px;font-size:14px;padding:5px 0;border-bottom:1px solid var(--line);align-items:baseline;text-align:left;width:100%;min-width:0}
.r9d-tn>div.h span,.r9d-tn>button span{min-width:0;overflow:hidden;text-overflow:ellipsis}
.r9d-tn>button span.f{white-space:nowrap}
.r9d-tn>div.h{color:var(--ink-faint);font-size:13px}
.r9d-tn>button{background:none;border:0;border-bottom:1px solid var(--line);color:var(--ink);font-family:inherit;cursor:pointer}
.r9d-tn>button:hover,.r9d-tn>button:focus-visible{background:rgba(128,150,180,.07)}
.r9d-tn>button.me{font-weight:600}
.r9d-tn>button.me span:last-child{color:var(--ink)}
.r9d-tn .f{color:var(--ink-faint)}
.r9d-tn .t{display:inline-flex;gap:2px;vertical-align:middle}
.r9d-tn .t i{width:7px;height:12px;border:1px solid var(--line);display:block;box-sizing:border-box}
.r9d-tn .t i.y{background:var(--ink)}
.r9d-tn .t.h i{border-style:dashed}
.r9d-tn .t.h i.y{background:transparent;border:1px solid var(--ink)}
@media (max-width:1100px){
  .r9d-tn>div.h,.r9d-tn>button{grid-template-columns:minmax(140px,1fr) 64px 110px;gap:8px}
  .r9d-tn>div.h span:nth-child(1),.r9d-tn>button span:nth-child(1),
  .r9d-tn>div.h span:nth-child(3),.r9d-tn>button span:nth-child(3),
  .r9d-tn>div.h span:nth-child(5),.r9d-tn>button span:nth-child(5),
  .r9d-tn>div.h span:nth-child(7),.r9d-tn>button span:nth-child(7){display:none}
  .r9d-apps>div{grid-template-columns:1fr 64px 80px}
  .r9d-apps>div span:last-child{display:none}
}

/* [W17B 2026-09-18] THE PRICE IS THE BIG NUMBER IN THE ROW. The prototype's "Best price" tile is app / BIG
   condensed price / "$10 gets", and the price is the thing the reader's eye goes to - ours was the same size as
   the app's name. Tabular figures so a column of prices lines up on the decimal point. */
.r9d-apps>div:not(.h) span:nth-child(2){font-size:17px;font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums;letter-spacing:-.01em}

/* [W17B 2026-09-18] THE PRICE TABLE INSIDE A v2 PANE TILE. MEASURED (tools/desk_law_test.py, nfl at 1600): the
   four-column grid (minmax(120,180) 70 90 1fr) needs more than the 294px a pane column gives, and .bb reported a
   10px sideways overflow on The pick and on Track it - a clip, which the desk law counts as a defect. The phone
   already drops the note column at 820px for the same reason; a pane tile is as narrow as a phone and gets the
   same three columns. */
@media (min-width:900px){
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .r9d-apps>div{grid-template-columns:1fr 58px 76px}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .r9d-apps>div span:last-child{display:none}
}

/* WP-STOP — "What could stop it?" House style only: one typeface var(--ui), two text colours, hairlines.
   No pills, no status colours, no badges. A missing player is a sentence, not a red tag. */
.r9-outrow { display: grid; grid-template-columns: 30px 1fr; gap: 10px; align-items: start; padding: 8px 0; border-bottom: 1px solid var(--line); font-family: var(--ui); }
.r9-outrow:last-of-type { border-bottom: 0; }
.r9-outrow .n { margin: 0; font-size: 14px; line-height: 1.45; color: var(--ink); }
.r9-outrow .s { margin: 3px 0 0; font-size: 13px; line-height: 1.45; color: var(--ink-faint); }
.r9-outrow .s b { color: var(--ink); font-weight: 600; }
.r9-outrow.top .n { font-size: 15px; }
.r9-five .r9-outrow .r9-face { margin-top: 2px; }

.r9-mh { font-family: var(--ui); font-size: 13px; font-weight: 600; color: var(--ink); margin: 0 0 6px; }
.r9-windwrap { flex: none; }
.r9-windwrap svg { display: block; }
.r9-condrow2 { display: flex; gap: 14px; align-items: center; margin-top: 6px; }
.r9-condrow2 > div { min-width: 0; }
.r9-condrow2 .obt-cap { margin: 0; }

.r9-five span.f, .r9-modal span.f { color: var(--ink-faint); }
.r9-five .r9-table td .f, .r9-modal .r9-table td .f { color: var(--ink-faint); }
.r9-modal .r9-mh { margin-top: 14px; }
.r9-modal .r9-mh:first-child { margin-top: 0; }

@media (max-width: 1100px) {
  .r9-condrow2 { flex-direction: column; align-items: flex-start; }
}

/* the caption under a WP-STOP organ is house type, never the legacy mono */
.r9-five .bb .obt-cap, .r9-modal .obt-cap { font-family: var(--ui); font-size: 13px; line-height: 1.45; color: var(--ink-faint); letter-spacing: 0; text-transform: none; margin: 6px 0 0; }
.r9-five .r9-helpers .bb .obt-cap { font-size: 12px; }

/* ================================================================================================================
   [W16B 2026-09-18] THE CONDITIONS ROW - the approved prototype's `.cond` object.
   A row of columns, each a 24 px stroke glyph over a short label, drawn BEFORE the sentences. It is the picture
   this card never had (tile_test T3/T4, organs_v2_test V1 on afl and nrl). One typeface, one ink, hairline box,
   8 px radii; no pill, no gauge, no glow, no colour of its own - the weather is not the bet's side.
   THE LABEL IS 13 px ON A PHONE AND 12 ON A DESKTOP, which are the two floors; it never shrinks to fit, it wraps.
   ================================================================================================================ */
/* ⛔ [W24B 2026-09-20] THE READING SHEET LIVES OUTSIDE #obtStage.
   LOOKED AT, shots/w22a/w24b_nfl_spine_modal_1440.png: a K.sprows block inside the "Read it all" sheet had
   collapsed into one run-on line of prose because its grid is written at #obtStage and the modal is appended
   to the page OUTSIDE that id. Every organ-body shape in this file had the same hole - the sheet is where a
   reader goes for MORE, so a drawing that only exists on the tile is the wrong way round. The selectors below
   carry a .r9-modal twin; the declarations are written ONCE so the tile and the sheet can never drift.
   (#obtStage is still needed on the tile: the host floor sheets carry #obtStage rules that a plain class
   selector loses to. Inside .r9-modal nothing competes, so a plain twin is enough there.) */
#obtStage .r9-cdrow,.r9-modal .r9-cdrow{display:flex;gap:6px;flex-wrap:wrap;margin:0 0 8px}
#obtStage .r9-cdrow>div,.r9-modal .r9-cdrow>div{flex:1 1 0;min-width:74px;display:flex;flex-direction:column;align-items:center;gap:5px;
  padding:9px 6px;border:1px solid var(--line);border-radius:8px;text-align:center}
#obtStage .r9-cdrow span,.r9-modal .r9-cdrow span{font-family:var(--ui);font-size:12px;line-height:1.25;color:var(--ink-dim)}
#obtStage .r9-cdi,.r9-modal .r9-cdi{width:24px;height:24px;stroke:var(--ink);fill:none;stroke-width:1.6;stroke-linecap:round;
  stroke-linejoin:round;flex:0 0 auto}
@media (max-width:760px){#obtStage .r9-cdrow span,.r9-modal .r9-cdrow span{font-size:13px}#obtStage .r9-cdrow>div,.r9-modal .r9-cdrow>div{min-width:82px}}

/* [W19B 2026-09-19, REMAINING_LIST item 13] CONDITIONS AS FOUR ICON-OVER-LABEL COLUMNS.
   .r9-condcols rides on the existing .r9-cdrow (which already gives the column its icon, its gap and its 13px
   phone floor) and adds the three things the mockup's row has and the old one did not: exactly four seats of
   equal width at every width, the NUMBER above the word instead of inside a sentence, and a 44px tap height so
   the column is a real target on a phone. Two by two under 560px - four 88px columns on a 390px screen would put
   "temperature" under the 12px floor, which is the squish this wave is clearing. */
#obtStage .r9-cdrow.r9-condcols,.r9-modal .r9-cdrow.r9-condcols{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;flex-wrap:nowrap}
#obtStage .r9-condcols>div,.r9-modal .r9-condcols>div{min-height:44px;min-width:0;justify-content:flex-start;text-align:center;gap:3px}
#obtStage .r9-condcols .cdi,.r9-modal .r9-condcols .cdi{display:block;line-height:1}
#obtStage .r9-condcols .cdv,.r9-modal .r9-condcols .cdv{font-family:var(--ui);font-weight:600;font-size:17px;line-height:1.15;color:var(--ink);
  font-variant-numeric:tabular-nums;white-space:nowrap}
#obtStage .r9-condcols .cdl,.r9-modal .r9-condcols .cdl{font-family:var(--ui);font-size:12px;line-height:1.25;color:var(--ink-faint)}
@media (max-width:560px){#obtStage .r9-cdrow.r9-condcols,.r9-modal .r9-cdrow.r9-condcols{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
  #obtStage .r9-condcols .cdl,.r9-modal .r9-condcols .cdl{font-size:13px}#obtStage .r9-condcols .cdv,.r9-modal .r9-condcols .cdv{font-size:18px}}
/* [integrator 2026-09-19] drawing_fit at 320 (nrl): a long value ("not known", "18 km/h SE") held 245 px in 238. The words wrap inside their column; nothing drags. */
#obtStage .r9-condcols>div,.r9-modal .r9-condcols>div{overflow:hidden}
#obtStage .r9-condcols .cdv,.r9-modal .r9-condcols .cdv,#obtStage .r9-condcols .cdl{white-space:normal;overflow-wrap:anywhere;max-width:100%}

/* ================================================================================================================
   [W25B 2026-09-20] `pnames` - THE MEN IN THIS GAME (the Player stop of a team, line or total bet).
   A LIST OF MEN, NOT A TABLE OF NUMBERS: each row is a name, where he plays, his club, and his own record strip
   in his club's colour. The strip object is the console's ONE record strip (.bbs .bbs-rec, 01v_strips.css) so
   nothing new is invented and the W / L letters keep the one meaning they have everywhere else; this file only
   gives the rows around it their shape. The .r9-modal twin is written on the same line as the tile selector so
   the reading sheet and the tile can never drift apart (the rule the rest of this file already follows).
   ⛔ FLOORS: 13 px on a phone, 12 px on a desktop (design law), and the name itself never goes under 14 px - it
   is the thing the reader came to read. Nothing here is a pill: the rows are separated by hairlines. */
#obtStage .r9pn,.r9-modal .r9pn{margin:10px 0 0}
#obtStage .r9pn-r,.r9-modal .r9pn-r{padding:9px 0;border-top:1px solid var(--line)}
#obtStage .r9pn-r:first-child,.r9-modal .r9pn-r:first-child{border-top:0;padding-top:2px}
#obtStage .r9pn-h,.r9-modal .r9pn-h{display:flex;align-items:baseline;flex-wrap:wrap;gap:6px;margin:0 0 4px}
#obtStage .r9pn-n,.r9-modal .r9pn-n{font-family:var(--ui);font-weight:600;font-size:15px;line-height:1.2;color:var(--ink)}
#obtStage .r9pn-p,.r9-modal .r9pn-p{font-family:var(--ui);font-size:12px;line-height:1.2;color:var(--ink-faint);
  text-transform:none}
/* the club sits behind a hairline tick in ITS OWN colour - the one place the row wears the colour as a block,
   and it is a 3 px rule beside the name, never a filled chip. */
#obtStage .r9pn-t,.r9-modal .r9pn-t{font-family:var(--ui);font-size:12px;line-height:1.2;color:var(--ink-dim);
  padding-left:7px;border-left:3px solid var(--tc,var(--ink-faint))}
#obtStage .r9pn .bbs-rec,.r9-modal .r9pn .bbs-rec{margin:0}
#obtStage .r9pn .bbs-cap,.r9-modal .r9pn .bbs-cap{font-size:12px;margin:3px 0 0}
@media (max-width:760px){
  #obtStage .r9pn-n,.r9-modal .r9pn-n{font-size:16px}
  #obtStage .r9pn-p,.r9-modal .r9pn-p,#obtStage .r9pn-t,.r9-modal .r9pn-t{font-size:13px}
  #obtStage .r9pn .bbs-cap,.r9-modal .r9pn .bbs-cap{font-size:13px}
  #obtStage .r9pn-r,.r9-modal .r9pn-r{padding:10px 0}
}

/* 01p_rates.css — WP-M2, the numbers area (organ `rates`). House style only: one typeface var(--ui), two inks,
   hairlines. No colour of its own, no pill, no gauge, no gradient: every value here is a token, so the card is
   correct in light and in dark without a second rule. */

/* the sentences under the numbers (same two voices every organ uses: the reading, then the caveat) */
.r9-five .r9r-cap{font-family:var(--ui);font-size:15px;line-height:1.5;margin:8px 0 0;color:var(--ink)}
.r9-five .r9r-cap b{font-weight:600}
.r9-five .r9r-sub{font-family:var(--ui);font-size:13px;line-height:1.5;color:var(--ink-faint);margin:4px 0 0}
.r9-five .r9-helpers .r9r-cap{font-size:14px;line-height:1.42}
.r9-modal .r9r-cap{font-family:var(--ui);font-size:14px;line-height:1.5;margin:6px 0 0;color:var(--ink)}
.r9-modal .r9r-sub{font-family:var(--ui);font-size:13px;line-height:1.5;color:var(--ink-faint);margin:6px 0 0}

/* THE NUMBERS AREA. The three tiles are the kit's own (.r9-three); this only gives the middle one — what the price
   needs — a hairline of its own weight, so the reader's eye lands on the comparison and not on the big count alone. */
.r9-five [data-organ="rates"] .r9-three{margin-top:10px}
.r9-five [data-organ="rates"] .r9-three div:nth-child(2) b{color:var(--ink-faint)}
.r9-five [data-organ="rates"] .r9-three div:nth-child(2) span{color:var(--ink-faint)}

/* THE CUTS TABLE. Three columns, and the break-even rides under the count in the same cell (a fourth column pushed
   the average out of a 390px card and behind a sideways scroll). The count carries the weight; what the price needed
   and the average stay quiet under and beside it. */
.r9-five [data-organ="rates"] .r9-table{margin-top:10px}
.r9-five [data-organ="rates"] .r9-table td:nth-child(3){color:var(--ink-faint)}
.r9-five [data-organ="rates"] .r9-table td:first-child{padding-right:14px}
.r9r-be{display:block;font-family:var(--ui);font-size:12px;font-weight:400;color:var(--ink-faint);white-space:nowrap}
.r9-modal .r9r-be{font-size:12px}

/* WHERE IT CHANGES — the situational splits. Same table, same inks: what separates it from the cuts above is a
   hairline and a heading, not a new colour, a badge or a box. The first cell is a button because tapping it
   re-filters the whole card, so it has to look like the plain text it replaced and behave like a control. */
.r9r-sph{font-family:var(--ui);font-size:13px;font-weight:600;letter-spacing:0;text-transform:none;
  color:var(--ink);margin:16px 0 0;padding-top:10px;border-top:1px solid var(--line)}
.r9-five [data-organ="rates"] .r9r-sph + .r9-table{margin-top:6px}
.r9r-spb{font-family:var(--ui);font-size:inherit;line-height:inherit;color:var(--ink);background:none;border:0;
  padding:0;margin:0;text-align:left;cursor:pointer;border-bottom:1px solid var(--line)}
.r9r-spb:hover{border-bottom-color:var(--ink)}
.r9r-spb:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
/* "tonight" — the mark that says THIS is the situation the game in front of you is being played in. A word, not a
   pill: the pill system in 08_cta.css is the owner's CTA language and borrowing it here would say "buy something". */
.r9r-spnow{font-family:var(--ui);font-size:11.5px;color:var(--ink-faint);margin-left:7px;white-space:nowrap}
.r9-modal .r9r-sph{margin-top:14px}
.r9-modal .r9r-sph:first-child{margin-top:0;padding-top:0;border-top:0}

/* a phone: the cut name takes the width it needs and the two numbers keep their column, no sideways scroll */
@media (max-width:820px){
  .r9-five [data-organ="rates"] .r9-table th,
  .r9-five [data-organ="rates"] .r9-table td{padding-right:6px;font-size:12.5px}
  .r9-five [data-organ="rates"] .r9-table td:first-child{padding-right:8px}
  .r9-five [data-organ="rates"] .r9r-be{font-size:11.5px}
  .r9r-sph{font-size:12.5px;margin-top:14px}
  .r9r-spnow{font-size:11px;margin-left:5px}
}

/* ==================================================================================================================
   [W17B 2026-09-18] THE CARD'S PICTURE AND ITS ONE SENTENCE.
   The ticks are 01v_strips.css's object, so nothing about the square, the letter or the club colour is restated
   here - only the two things this card adds: a thin row when there are fewer than eight games behind it (the
   honest-sample rule, brief addition 7), and the single line under the chips.
   ================================================================================================================== */
.bbs-rates{margin:2px 0 0}
.bbs-rates.thin .bbs-t i{border-style:dashed}
.bbs-rates.thin .bbs-t.wn i{background:none;color:var(--tc)}
.r9r-one{font-size:13px;line-height:1.45;color:var(--ink-dim);margin:8px 0 0}
.r9r-one b{color:var(--ink);font-weight:600}

/* 01q_fp.css - WP-W5B, the fingerprint exec summary (organ `fpsum`).
   House style only: one typeface var(--ui), the three inks, hairlines. No gauge, no bar, no pill, no gradient and no
   colour of its own - every value is a token, so the card is right in light and in dark with one set of rules.

   THE SHAPE. A ranked list, and it LOOKS ranked: the count sits in its own narrow column in the ink the rest of the
   console uses for a quiet number, with a hairline between rows. That is the whole design - the reading is the
   sentence, and nothing is drawn that would make a reader work out what a shape means before they can read it. */

/* the counter STARTS AT TWO on the card: the lead sentence above the list is the number-one angle, so a list that
   began at 1 would show the same rank twice. Inside the "rest of this game" door the whole list is printed, lead
   included, and the counter starts at one there. */
.r9fp-ol{list-style:none;margin:8px 0 0;padding:0;counter-reset:r9fp 1}
.r9-modal .r9fp-ol{counter-reset:r9fp 0}
.r9fp-ol li{counter-increment:r9fp;display:grid;grid-template-columns:18px 1fr;gap:0 10px;align-items:baseline;
  padding:8px 0 0;margin:8px 0 0;border-top:1px solid var(--line)}
.r9fp-ol li:first-child{border-top:0;margin-top:4px;padding-top:0}
.r9fp-ol li::before{content:counter(r9fp);grid-row:1/3;font-family:var(--ui);font-size:13px;font-variant-numeric:tabular-nums;
  font-weight:600;color:var(--ink-faint);line-height:1.5}
.r9fp-ol li b{font-family:var(--ui);font-size:14px;font-weight:600;color:var(--ink);line-height:1.45}
.r9fp-ol li span{grid-column:2;font-family:var(--ui);font-size:14px;font-weight:400;color:var(--ink-dim);line-height:1.5;
  display:block;margin-top:2px}

/* the helper column runs narrower than the lead cell, so the same list sets one step down there */
.r9-five .r9-helpers .r9fp-ol li b,
.r9-five .r9-helpers .r9fp-ol li span{font-size:13px;line-height:1.42}

/* the door: the full list, then one line per other subject the model wrote something down for */
.r9fp-mp{font-family:var(--ui);font-size:14px;line-height:1.5;color:var(--ink-dim);margin:8px 0 0}
.r9fp-mp b{font-weight:600;color:var(--ink)}
.r9fp-mh{color:var(--ink-faint);margin-top:14px;padding-top:10px;border-top:1px solid var(--line)}
.r9-modal .r9fp-ol li b,.r9-modal .r9fp-ol li span{font-size:14px}

/* a phone: the number column tightens, nothing wraps under the rule */
@media (max-width:820px){
  .r9fp-ol li{grid-template-columns:15px 1fr;gap:0 8px}
  .r9fp-ol li b,.r9fp-ol li span{font-size:13.5px}
  .r9fp-ol li::before{font-size:12px}
  .r9fp-mp{font-size:13.5px}
}

/* 01r_gaps.css - WP-W5D, the price-gap organ (`gaps`). House style only: one typeface var(--ui), the two inks,
   hairlines. No colour of its own, no pill, no gauge, no gradient - the CTA inside the locked card is the owner's
   own .r9cta from 08_cta.css and brings its own rules. Every value is a token, so the card is right in both themes. */

/* the reading voice, then the caveat voice - the same two every organ uses */
.r9-five .r9g-say{font-family:var(--ui);font-size:15px;line-height:1.5;margin:8px 0 0;color:var(--ink)}
.r9-five .r9g-say b{font-weight:600}
.r9-five .r9g-sub{font-family:var(--ui);font-size:13px;line-height:1.5;color:var(--ink-faint);margin:6px 0 0}
.r9-five .r9-helpers .r9g-say{font-size:14px;line-height:1.42}
.r9-modal .r9g-say{font-family:var(--ui);font-size:14px;line-height:1.5;margin:8px 0 0;color:var(--ink)}
.r9-modal .r9g-sub{font-family:var(--ui);font-size:13px;line-height:1.5;color:var(--ink-faint);margin:8px 0 0}

/* THE PAIR TABLE. Three columns: what to put on, the app, the price. The money carries the weight; the app name
   and the price stay level with it and the price sits right so two rows compare down the column. */
.r9-five [data-organ="gaps"] .r9-table,
.r9-modal .r9g-say + .r9-table{margin-top:8px}
.r9-five [data-organ="gaps"] .r9-table td:first-child{padding-right:14px}
.r9-five [data-organ="gaps"] .r9-table td:nth-child(2){color:var(--ink-dim)}

/* an exchange leg says so on the row, quietly, and the card says what it means underneath */
.r9g-ex{font-style:normal;font-family:var(--ui);font-size:11.5px;color:var(--ink-faint);white-space:nowrap}

/* THE DOOR IN A WIDE CARD. 08_cta.css composes the pill and the quiet account line to sit on one line, which is
   right in the narrow column it was built for; in a full-width organ cell the account line lands hard against the
   pill's right edge. Scoped to this organ: the pill keeps a readable width and the account line takes its own line. */
.r9-five [data-organ="gaps"] .r9cta-wrap .r9cta{max-width:420px}
.r9-five [data-organ="gaps"] .r9cta-wrap .r9cta-quiet{display:flex;margin-top:2px}

/* the other games tonight: a plain text button, underlined on hover, never a pill */
.r9g-go{background:none;border:0;padding:0;margin:0;font:inherit;color:var(--ink);cursor:pointer;text-align:left}
.r9g-go:hover,.r9g-go:focus-visible{text-decoration:underline}

@media (max-width:820px){
  .r9-five [data-organ="gaps"] .r9-table th,
  .r9-five [data-organ="gaps"] .r9-table td{padding-right:6px;font-size:12.5px}
  .r9-five [data-organ="gaps"] .r9-table td:first-child{padding-right:8px}
  .r9g-ex{display:block;font-size:11px}
}

/* 01s_pred.css - [WP-W6E 2026-09-15] "Our prediction" (organ `pred`).
   House rules only: one typeface (var(--ui) is already on the cell), the three inks, hairlines, no gauge, no pill of
   its own, no colour of its own, no gradient, no glow. The only filled thing this card can draw is the owner's .r9cta
   pill, which comes from 08_cta.css. Correct in light and dark because every value is a token. */

#obtStage .bc[data-organ="pred"] .r9pd-l {
  margin: 0 0 7px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-dim);
}
#obtStage .bc[data-organ="pred"] .r9pd-l:last-child { margin-bottom: 0; }
#obtStage .bc[data-organ="pred"] .r9pd-l b { color: var(--ink); font-weight: 600; }

/* "Why this could lose" sits under a hairline: it is the last word on the card, not a footnote squeezed in. */
#obtStage .bc[data-organ="pred"] .r9pd-lose {
  border-top: 1px solid var(--line);
  padding-top: 7px;
  margin-top: 9px;
  color: var(--ink-faint);
}
#obtStage .bc[data-organ="pred"] .r9pd-lose b { color: var(--ink-dim); font-weight: 600; }

/* ---- THE TEASE ----------------------------------------------------------------------------------------------
   The blur covers a placeholder that has no number in it (BbOddsPred.Placeholder: "##" is the only thing standing
   where a number would be, and .r9pd-bar is what "##" becomes). Removing the blur in devtools reveals grey bars,
   which is the point - a blur over real numbers is devtools-removable and this one has nothing to remove. */
#obtStage .bc[data-organ="pred"] .r9pd-blur {
  filter: blur(3.5px);
  opacity: .48;
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
}
#obtStage .bc[data-organ="pred"] .r9pd-blur .r9pd-l { color: var(--ink-dim); }
#obtStage .bc[data-organ="pred"] .r9pd-sig { display: inline-block; }

/* the grey bar that stands where a number would be */
#obtStage .bc[data-organ="pred"] .r9pd-bar {
  display: inline-block;
  width: 22px;
  height: .72em;
  margin: 0 1px -1px;
  border-radius: 2px;
  background: var(--ink-faint);
  opacity: .5;
}

/* the honest line under the blur. It is NOT blurred and must never be. */
#obtStage .bc[data-organ="pred"] .r9pd-hid {
  margin: 9px 0 10px;
  padding-top: 8px;
  border-top: 1px solid var(--line);
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--ink-faint);
}

/* 08_cta.css composes the pill and the quiet account line onto one row, which is right in the narrow column it was
   built for and lands the account line against the pill's edge in a full-width organ cell. Two lines, this organ only
   (the same scoped fix 01r_gaps.css makes for the same reason). */
#obtStage .bc[data-organ="pred"] .r9cta-wrap { display: block; }
#obtStage .bc[data-organ="pred"] .r9cta-wrap .r9cta { margin-bottom: 6px; }
#obtStage .bc[data-organ="pred"] .r9cta-quiet { display: block; margin-top: 2px; }

@media (max-width: 820px) {
  #obtStage .bc[data-organ="pred"] .r9pd-l { font-size: 13px; }
  #obtStage .bc[data-organ="pred"] .r9pd-bar { width: 20px; }
}

/* ================================================================================================================
   IN 100 GAMES - [W14B 2026-09-17], CONSOLE_V2_BRIEF addition 4. A tug bar: our chance in club colour, the rest in
   hairline, and a plain ink mark where the price sits. No gauge, no gradient, no glow (DESIGN LAW). 8 px radii per
   DESIGN LAW v2. The numbers are printed IN the bar at the body size, so nothing here can fall under a text floor.
   ================================================================================================================ */
.r9pd-tug{position:relative;display:flex;height:30px;border:1px solid var(--line);border-radius:8px;overflow:hidden;
  font-family:var(--ui);font-size:13px;font-variant-numeric:tabular-nums;margin:2px 0 6px}
.r9pd-tug .a{background:var(--tc,var(--ink-faint));color:var(--tcg,var(--bg,#0F1118));display:flex;align-items:center;
  padding:0 8px;font-weight:600;min-width:26px;box-sizing:border-box}
.r9pd-tug .b{flex:1 1 auto;display:flex;align-items:center;justify-content:flex-end;padding:0 8px;color:var(--ink-faint)}
.r9pd-tug i{position:absolute;top:0;bottom:0;width:2px;margin-left:-1px;background:var(--ink)}
.r9pd-tugw{font-family:var(--ui);font-size:13px;line-height:1.45;color:var(--ink-dim);margin:0 0 8px}
.r9pd-tugw b{color:var(--ink);font-weight:600}
@media (min-width:900px){.r9pd-tugw{font-size:13px}}

/* [integrator 2026-09-19] THE SAME TEASE ON EVERY LOCKED SHELL. MEASURED ON PROD: the guest gate (04_engine.js
   guestGate) draws this shell on organs other than `pred`, and the rule above is scoped to pred - so a guest read a
   crisp "## of ## - about ## in 100". One rule for the class wherever it is drawn, plus the pick card's gate row. */
#obtStage .r9pd-blur { filter: blur(3.5px); opacity: .48; pointer-events: none; user-select: none; -webkit-user-select: none; }
#obtStage .r9pd-blur .r9pd-l { color: var(--ink-dim); }
#obtStage .r9-callgate { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin: 0 0 8px; }
#obtStage .r9-callgate .r9pd-blur { font-size: 20px; font-weight: 700; letter-spacing: .02em; }

/* 01t_spine.css - WP-W6X, the stat-spine organ (`spine`, "What the numbers say").
   House style only: one typeface var(--ui), the three inks, hairlines. No gauge, no bar, no pill, no gradient, no
   colour of its own - every value is a token, so the card is right in light and in dark with one set of rules.

   THE SHAPE. Sentences, and nothing else. The body of this card is a QUOTED SOURCE - BetBetter's own stats engine
   wrote every word of it and the guide forbids changing them - so the design's whole job is to make six quoted
   sentences readable: one a row, hairline between, the same reading size as the rest of the console. Nothing is
   drawn that a reader would have to decode before they could read. */

.r9sp-ul{list-style:none;margin:8px 0 0;padding:0}
.r9sp-ul li{font-family:var(--ui);font-size:14px;font-weight:400;color:var(--ink-dim);line-height:1.5;
  padding:8px 0 0;margin:8px 0 0;border-top:1px solid var(--line)}
.r9sp-ul li:first-child{border-top:0;margin-top:4px;padding-top:0}

/* the freshness tag. It only appears on a sentence the spine itself called dated or stale - those sentences already
   open with their own date, so this is the plain-English warning beside it, never a second date. */
.r9sp-old{font-family:var(--ui);font-size:12px;font-weight:400;color:var(--ink-faint);line-height:1.5;
  display:inline-block;margin-left:8px;white-space:nowrap}
.r9sp-old::before{content:"\2022";margin-right:6px;color:var(--line)}

/* the helper column runs narrower than the lead cell, so the same list sets one step down there */
.r9-five .r9-helpers .r9sp-ul li{font-size:13px;line-height:1.42}

/* the door: a heading per subject, then that subject's sentences */
.r9sp-dh{font-family:var(--ui);font-size:13px;font-weight:600;color:var(--ink);margin:14px 0 0;
  padding-top:10px;border-top:1px solid var(--line)}
.r9sp-dh:first-child{margin-top:8px;padding-top:0;border-top:0}
.r9-modal .r9sp-ul li{font-size:14px}

/* a phone: nothing wraps under a rule, the tag drops to its own line rather than pushing the sentence around */
@media (max-width:820px){
  .r9sp-ul li{font-size:13.5px}
  .r9sp-old{margin-left:0;display:block}
  .r9sp-old::before{display:none}
  .r9sp-dh{font-size:12.5px}
}

/* Part 1v (css): THE STRIPS - [W11A 2026-09-17]. Dress for src/01v_strips.js.
   ================================================================================================================
   STATUS: complete on disk.

   THE RULES THIS FILE KEEPS
     one typeface        every word is var(--ui); there is no second face and no mono anywhere in here.
     inks + hairlines    --ink / --ink-dim / --ink-faint for text, 1px var(--line) for every edge. No gradients,
                         no glow, no shadow, no rounded pill. The only radius in the file is 0.
     team colour         the ONE allowed accent (critique L4). It arrives as --tc, already contrast-checked
                         against the real ground by src/00e_colours.js; when there is no colour we can stand
                         behind, --tc falls back to var(--ink-dim) and the strip is honest greyscale.
     W/L colour          --bbs-w / --bbs-l are used in exactly two places: the tick or cross under a hit-strip bar
                         and the squares of the record strip. Both are proof strips, which is the one exemption
                         the design law grants. Measured against the console's two grounds with the same routine
                         src/00e_colours.js uses: 5.7:1 and 4.6:1 on #0F1118, 5.5:1 and 6.1:1 on white - every one
                         of them over the 3:1 floor for a non-text mark, and tools/strips_test.py re-measures them
                         in the browser rather than trusting this comment.
     shape, not colour   colour is never the only carrier. A win is FILLED and a loss is an OUTLINE in every strip,
                         so the greyscale and colour-blind pass (round-9 item 42) survives untouched.
     size floor          13px on a phone, 12px on desktop (tools/desk_law_test.py). Nothing here is smaller, which
                         is why no label is drawn inside an SVG.
     44px taps           only the form strip's squares are tappable. Each is a 44px column; below 340px of room
                         the row scrolls sideways rather than shrinking the target.
   ================================================================================================================ */

.bbs{--tc:var(--ink-dim);--bbs-w:#35A06A;--bbs-l:#D2564E;font-family:var(--ui);margin:6px 0 2px}
html[data-theme="light"] .bbs{--bbs-w:#1B7A4E;--bbs-l:#B23A32}
.bbs p{margin:0}
.bbs .bbs-one{font-size:13px;line-height:1.45;color:var(--ink-dim);margin:4px 0 0}
.bbs .bbs-one b{color:var(--ink);font-weight:600}
.bbs .bbs-nm{font-size:14px;font-weight:600;color:var(--ink);line-height:1.3;display:flex;align-items:center;gap:7px}
.bbs .bbs-nm:before{content:'';display:block;width:3px;height:14px;flex:0 0 auto;background:var(--tc)}
.bbs .bbs-nm em{font-style:normal;font-weight:400;font-size:13px;color:var(--ink-faint)}
/* [W21B 2026-09-19] AN EMPTY CAPTION TAKES NO ROOM, ANYWHERE. The integrator emptied the how-to sentence on
   19-Sep (the approved mockup has none) and hid the empty node only inside .r9-five (scenes.css:1055), so every
   strip OUTSIDE a five-up tile - the pick card, a borrowed strip, a thin-tail tile, an opened door - reserved
   19 px of blank under it. The rule belongs with the object, not with one of the places it is drawn. It comes
   back the moment a tick writes into it, which is what src/01v_strips.js wire() does on tap, hover and focus. */
.bbs .bbs-cap{font-size:13px;line-height:1.45;color:var(--ink-faint);margin:6px 0 0;min-height:19px}
.bbs .bbs-cap:empty{display:none}
.bbs .bbs-cap[data-on]{color:var(--ink)}

/* ---------- the form strip ---------- */
.bbs-form .bbs-r{padding:8px 0;border-top:1px solid var(--line)}
.bbs-form .bbs-r:first-child{border-top:0;padding-top:2px}
/* [W13B 2026-09-17, vet L7] THE TICKS WRAP, THEY NO LONGER SCROLL SIDEWAYS. The sideways scroll was the right
   trade at 390 (seven 44px squares need ~330px and nothing was hidden), but a helper column at 1600 is 225px
   wide: measured there, the row was 360px of content in a 225px box with three results sitting past the right
   edge and only a drag to reach them - a record the reader cannot see is not a record. Wrapping keeps every
   square at the 44px tap floor and hides nothing at any width. The foot says "newest last", not "on the right",
   because on a narrow column the newest square is on the second line. */
.bbs-tk{display:flex;flex-wrap:wrap;gap:4px;margin:6px 0 0;overflow-x:visible;padding-bottom:2px}
.bbs-t{flex:0 0 auto;width:44px;min-height:44px;display:flex;flex-direction:column;align-items:center;gap:3px;
  padding:2px 0 0;background:none;border:0;cursor:pointer;font-family:var(--ui);color:var(--ink-faint)}
/* [W17B 2026-09-18] THE LETTER IN THE SQUARE (MOCKUP_DIFF B5). The square was a fill with no word in it, so a
   reader had to learn a legend before he could read his own form line; the prototype puts W / L / D inside it.
   A WON square is a block of club colour, so its letter is the GROUND the colour was contrast-checked against
   (--tcg, set beside --tc by 01v_strips.js tcVar) and not a hard-coded near-black that would only be right in
   the dark theme. A lost square is an outline, so its letter is the colour itself. */
.bbs-t i{display:flex;align-items:center;justify-content:center;width:24px;height:24px;box-sizing:border-box;
  border:1px solid var(--tc);position:relative;font-size:12px;line-height:1;font-weight:600;color:var(--tc);font-style:normal}
.bbs-t.wn i{background:var(--tc);color:var(--tcg,#0F1118)}
/* [integrator 2026-09-19] the half-fill sat OVER the letter, so a draw read ')' instead of 'D' (seen in the reading sheet). A draw is a
   thick club-colour underline under a plain D: still neither a win (filled) nor a loss (outline only). */
.bbs-t.dr i:before{content:'';position:absolute;left:0;right:0;bottom:0;height:4px;background:var(--tc)}
.bbs-t.dr i{color:var(--ink)}
.bbs-t span{font-size:13px;line-height:15px;max-width:44px;overflow:hidden;white-space:nowrap}
/* "scored 41, 30, 24, 17, 27" - the prototype's own line under the ticks, faint, one row, never wrapped twice */
/* ⛔ 13px, NOT 12. MEASURED (tools/desk_law_test.py, 2026-09-18): at 12px this line broke the PHONE floor on
   sixteen views - afl, nfl and mlb, three stops each, both clubs' rows. The design law's floors are 13px on a
   phone and 12px on a desktop, so the line is 13px everywhere and drops to the desktop floor only inside a v2
   pane tile, where the column is 237px wide and the row is one line. */
.bbs .bbs-sc{font-size:13px;line-height:1.35;color:var(--ink-faint);margin:3px 0 0;font-variant-numeric:tabular-nums;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media (min-width:900px){#obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .bbs .bbs-sc{font-size:12px}}
/* the head-to-head chips inside the form tile, on the pick (01v_strips.js h2hMini). One hairline, a quiet label,
   then the same .bbs-ch chip the head-to-head organ draws - one object, one stylesheet. */
.bbs .bbs-h2m{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:8px 0 0;padding-top:8px;border-top:1px solid var(--line)}
.bbs .bbs-h2l{font-size:13px;color:var(--ink-faint);flex:0 0 auto}
.bbs .bbs-h2m .bbs-ch{min-height:32px;padding:4px 9px}
.bbs .bbs-h2m .bbs-ch i{height:16px}
.bbs .bbs-h2m .bbs-ch b{font-size:13px}
.bbs .bbs-h2m .bbs-ch span{font-size:13px}
@media (min-width:900px){
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .bbs .bbs-h2l,
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .bbs .bbs-h2m .bbs-ch span{font-size:12px}
}
.bbs-t:focus-visible{outline:2px solid var(--ink);outline-offset:-1px}
.bbs-t:hover i,.bbs-t:focus i{border-width:2px}

/* ---------- the head-to-head strip ---------- */
.bbs-h2h{display:flex;flex-wrap:wrap;gap:8px}
.bbs-ch{display:flex;align-items:center;gap:8px;border:1px solid var(--line);padding:7px 10px;min-height:44px;box-sizing:border-box}
/* [W22B 2026-09-19] THE LETTER IN THE CHIP. The 3px club-colour rule became a 22px lettered box: the colour still
   says which club won the meeting, the letter says what it means to the bet the reader is holding. A W is the club
   colour filled with the ground it was contrast-checked against; an L is the same colour as an outline; a D is
   half-filled, exactly as the form strip's drawn square already is, so the two objects read the same. */
.bbs-ch i{display:flex;align-items:center;justify-content:center;width:22px;height:22px;flex:0 0 auto;box-sizing:border-box;
  border:1px solid var(--tc);background:none;font-size:12px;line-height:1;font-weight:600;font-style:normal;color:var(--tc);position:relative}
.bbs-ch.lW i{background:var(--tc);color:var(--tcg,#0F1118)}
.bbs-ch.lD i{color:var(--ink)}
.bbs-ch.lD i:before{content:'';position:absolute;left:0;top:0;bottom:0;width:50%;background:var(--tc)}
.bbs-ch b{font-size:15px;font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
.bbs-ch span{font-size:13px;color:var(--ink-faint);line-height:1.3}

/* ---------- the hit strip ---------- */
/* the track has NO padding on purpose: the bars' bottom/height percentages and the line's bottom percentage both
   resolve against this one box, so a 62% line sits exactly where a 62% bar ends. The number the line stands for
   is named on its own row ABOVE the track (.bbs-key) rather than written on the rule, because a label drawn on
   the rule is covered by any bar tall enough to reach it - measured on MLB, first run. */
.bbs-hit{margin-top:8px}
.bbs-key{display:flex;align-items:center;gap:7px;font-size:13px;line-height:1.3;color:var(--ink-dim);margin:0 0 5px}
.bbs-key i{display:block;width:24px;height:0;flex:0 0 auto;border-top:1px dashed var(--ink)}
.bbs-key b{color:var(--ink);font-weight:600}
.bbs-tk2{position:relative;display:flex;gap:4px;align-items:flex-end;height:104px;
  border-bottom:1px solid var(--line)}
.bbs-tk2 .bbs-c{position:relative;flex:1 1 0;min-width:0;height:100%}
/* [W22B 2026-09-19] the bars are the bet side's club colour where the colour table knows the league, the ink it
   always was where it does not. A bar that cleared the number is solid; one that did not is the same bar as an
   outline - the strength of the ink carries it, never a second hue. */
.bbs-tk2 .bbs-bar{position:absolute;left:0;right:0;background:var(--tc,var(--ink))}
.bbs-tk2 .bbs-bar.f{background:none;border:1px solid var(--tc,var(--ink-faint));opacity:.6}
.bbs-tk2 .bbs-ln{position:absolute;left:0;right:0;bottom:var(--lp);border-top:1px dashed var(--ink);pointer-events:none}
/* [W22B 2026-09-19] ⛔ THE LETTER LAW + ⛔ COLOUR IS NEVER THE ONLY SIGNAL. These marks were a 10px filled or
   hollow square - the reader had to learn a legend. Each now carries its letter (W cleared the number, L missed
   it, P landed exactly on it) and takes THE BET SIDE'S CLUB COLOUR through --tc, which src/01v_strips.js sets on
   the strip from K.tc. --bbs-w / --bbs-l survive only as the FALLBACK for a league the colour table does not
   know, and neither is ever the only thing carrying the meaning. */
.bbs-mk{display:flex;gap:4px;margin-top:6px}
.bbs-mk i{flex:1 1 0;min-width:0;height:18px;display:flex;align-items:center;justify-content:center;position:relative;
  font-style:normal;font-size:12px;line-height:1;font-weight:600;color:var(--ink-faint);overflow:hidden}
.bbs-mk i:before{content:'';position:absolute;left:50%;top:0;width:18px;height:18px;margin-left:-9px;box-sizing:border-box}
.bbs-mk i.ok{color:var(--tcg,#0F1118)}
.bbs-mk i.ok:before{background:var(--tc,var(--bbs-w))}
.bbs-mk i.no{color:var(--tct,var(--bbs-l))}
.bbs-mk i.no:before{border:1px solid var(--tc,var(--bbs-l))}
.bbs-mk i.pu{color:var(--ink-faint)}
.bbs-mk i.pu:before{border:1px dashed var(--ink-faint)}
/* the letter is painted over its own box, never under it */
.bbs-mk i{z-index:0}
.bbs-mk i:before{z-index:-1}
.bbs-lb{display:flex;gap:4px;margin-top:4px}
.bbs-lb em{flex:1 1 0;min-width:0;font-style:normal;font-size:13px;line-height:1.3;color:var(--ink-faint);
  text-align:center;overflow:hidden;white-space:nowrap}

/* ---------- the record strip ---------- */
/* [W22B 2026-09-19] ⛔ THE LETTER LAW, on the last bare mark in the console. K.rec (src/00b_kit2.js) and the
   recstrip organ both drew a 16px square with `aria-hidden` and nothing in it: invisible to a screen reader,
   unreadable to everyone else without a legend. Every square now holds its letter - W, L, D (or P on a strip
   about a bet) - in the bet side's club colour, and is focusable when it carries a line to write into the
   caption beneath it. */
.bbs-rk{display:flex;flex-wrap:wrap;gap:5px;margin-top:2px}
.bbs-rk span{display:flex;align-items:center;justify-content:center;width:22px;height:22px;box-sizing:border-box;
  font-size:12px;line-height:1;font-weight:600;font-family:var(--ui);position:relative}
.bbs-rk span.wn{background:var(--tc,var(--bbs-w));color:var(--tcg,#0F1118);border:1px solid var(--tc,var(--bbs-w))}
.bbs-rk span.ls{border:1px solid var(--tc,var(--bbs-l));color:var(--tct,var(--bbs-l))}
.bbs-rk span.dr{border:1px solid var(--ink-faint);color:var(--ink)}
.bbs-rk span.dr:before{content:'';position:absolute;left:0;top:0;bottom:0;width:50%;background:var(--tc,var(--ink-faint));z-index:-1}
.bbs-rk span[data-bbsc]{cursor:pointer}
.bbs-rk span:focus-visible{outline:2px solid var(--ink);outline-offset:2px}

/* ---------- the cover map's scoring bands ---------- */
.bbs-bands .bbs-bd{padding:8px 0;border-top:1px solid var(--line)}
.bbs-bands .bbs-bd:first-child{border-top:0}
.bbs-bt{position:relative;height:14px;margin:7px 0 0;border-bottom:1px solid var(--line)}
.bbs-bt .bbs-sp{position:absolute;top:3px;height:8px;background:var(--tc)}
.bbs-bt i{position:absolute;top:0;width:2px;height:14px;background:var(--ink);margin-left:-1px}

/* ---------- the pending skeleton's title ----------
   04_engine.js prints TITLES[key] || key while a card waits for the deep payload, and its TITLES map is a closure
   the scene engine cannot reach. Until the integrator adds the four entries (handed verbatim in this package's
   asks) a reader would see the raw key "hitstrip" for a second on a cold open. This is the belt: while the cell is
   a skeleton, the key is replaced with the words. It costs nothing once the ask lands - the rule only ever fires
   on a cell that is still loading, and a rendered card carries its own title from render(). */
.bc[data-organ="hitstrip"]:has(.r9-loading) .bh .lab:first-child,
.bc[data-organ="formstrip"]:has(.r9-loading) .bh .lab:first-child,
.bc[data-organ="h2hstrip"]:has(.r9-loading) .bh .lab:first-child,
.bc[data-organ="recstrip"]:has(.r9-loading) .bh .lab:first-child{font-size:0}
.bc[data-organ="hitstrip"]:has(.r9-loading) .bh .lab:first-child:after{content:'How often it lands, by situation';font-size:14px}
.bc[data-organ="formstrip"]:has(.r9-loading) .bh .lab:first-child:after{content:'Their last seven';font-size:14px}
.bc[data-organ="h2hstrip"]:has(.r9-loading) .bh .lab:first-child:after{content:'When they last met';font-size:14px}
.bc[data-organ="recstrip"]:has(.r9-loading) .bh .lab:first-child:after{content:'Our record on calls like this';font-size:14px}

@media (min-width:900px){
  .bbs .bbs-one,.bbs .bbs-cap,.bbs-ch span,.bbs-lb em,.bbs-t span{font-size:13px}
  .bbs-t{width:48px}
  .bbs-t i{width:28px;height:28px}
  .bbs-tk2{height:132px}
  .bbs-rk span{width:24px;height:24px}
}


/* ================================================================================================================
   THE SITUATION CHIPS - [W14B 2026-09-17], CONSOLE_V2_BRIEF addition 1.
   One row of chips under the picture. Each is a real button (the console's own data-r9="otab" verb), 8 px radii
   per DESIGN LAW v2, wrapping rather than scrolling sideways (the same ruling the tick row took on 09-17), a
   36 px box so a thumb can hit it, and 13 px text so it clears the phone floor. The ACTIVE chip takes the bet
   side's club colour through --tc, which the strip's own wrapper already sets; a chip under six games is DASHED
   and dimmed, which is the honest floor said in a shape a reader does not have to read.
   No pill: the chip is a hairline box with a square-ish 8 px radius, not a lozenge. No glow, no gradient.
   ================================================================================================================ */
/* [W29A 2026-09-22] THE CHIPS ARE TABS NOW - one grammar, drawn here, emitted by K.tabrow (src/00b_kit2.js).
   The owner read "All games, 5 of 7" and "Last 5, only 4" as noise, and he was right: a control is not a place to
   put a rate. The label is the whole tab; the count is the sentence under the row (.bbtab-say). The row is a tab
   strip - hairline under it, the active tab marked by a 2px club-colour bar it sits ON, not a box - which is the
   same mark the stop strip above it uses, so the reader learns ONE control for the whole console.
   The old class names stay on the same elements (.bbs-sit / .bbs-sb), so every gate that presses a split - the
   integrator's repaint_test, reload_probe, every_control_test, organs_v2_test, strips_test's radius exemption -
   keeps its hook and there is only one set of declarations to read. */
/* ⛔ THE ROW WRAPS; IT DOES NOT SCROLL SIDEWAYS - MEASURED, AND THE FIRST CUT HAD IT WRONG. A nowrap row with
   overflow-x:auto and a half-shown next tab is the usual answer, and tools/desk_law_test.py refused it: 28 clips
   across 30 tab views (24 of them the form strip's row, 4 the rates card's), at 1600 AND at 390, because a control
   whose last word is cut is clipped text wherever it lives - "the desktop page never scrolls" is not a desktop-only
   rule in that gate, and it is right. Labels alone are short enough that a wrapped row is two tidy lines of words,
   not the old wall of "All games, 3 of 6 / Home games, only 5". So: wrap, and the hairline goes ON EACH TAB rather
   than under the row, because a row rule under a wrapped row draws a line under the last line only. */
/* the control and its sentence are ONE object to the tile's clip (see K.tabrow) - this is that object. */
/* ⛔ THE PAIR'S HEIGHT IS MEASURED, NOT CHOSEN. On mlb Proof / Matchup at 1440 the strip is the tile's
   one big first object, which src/01k_integ.js's cut pass steps over by design ("the door owns it"), so
   nothing hides the sentence there - it is simply cut by the tile's edge, and it was cut by 9px. The pair
   gives back 10: 4px off the tab box, 2 off the sentence's lead-in, 4 off the row's own top margin. */
.bbtabw{margin:2px 0 0}
.bbs-sit,.bbtab{display:flex;flex-wrap:wrap;gap:2px 4px;margin:0;padding:0}
.bbs-sb,.bbtab-t{flex:0 0 auto;font-family:var(--ui);font-size:13px;line-height:1.2;font-weight:500;
  color:var(--ink-faint);background:none;border:0;border-bottom:2px solid transparent;border-radius:8px 8px 0 0;
  padding:5px 10px;min-height:28px;box-sizing:border-box;cursor:pointer;
  white-space:nowrap;text-align:left}
.bbs-sb:hover,.bbtab-t:hover{color:var(--ink-dim)}
.bbs-sb:focus-visible,.bbtab-t:focus-visible{outline:2px solid var(--ink);outline-offset:-2px}
/* ⛔ NO box-shadow ON A TAB. tools/strips_test.py S7 counts any shadow inside a strip as a glow, and it is right
   to: an inset bar drawn with a shadow is a glow as far as a stylesheet can tell. The active tab says so with its
   own bottom border in the club colour instead - the same mark, one fewer property, and the gate stays sharp. */
.bbs-sb.on,.bbtab-t.on{color:var(--ink);font-weight:600;border-bottom-color:var(--tc,var(--ink))}
/* A SPLIT UNDER THE FLOOR KEEPS ITS HONEST DASHED STATE - it is offered, and the sentence says why it is thin.
   ⛔ the dash is drawn in var(--ink-faint), not var(--line): LOOKED AT on shots/w29a/zoom_rates_light.png, a 2px
   dash in the hairline colour sitting on the row's own hairline read as a broken line, not as a mark. */
/* ⛔ AND THE DASH IS QUIET UNTIL THE READER IS STANDING ON IT. LOOKED AT (shots/w29a/FIN_390_light.png): three
   thin splits side by side drew three heavy dashed rules across the card and the eye went to them instead of to
   the words. An inactive tab is not making a claim - it is an offer - so it says "thin" in a 1px hairline dash;
   the tab in focus, which IS the claim, keeps the full 2px dash in the club colour, and the sentence under the
   row says it in words ("Only 4 games behind it, too few to lean on."). */
.bbs-sb.thin,.bbtab-t.thin{border-bottom-style:dashed;border-bottom-width:1px;border-bottom-color:var(--line);color:var(--ink-faint)}
.bbs-sb.thin.on,.bbtab-t.thin.on{border-bottom-width:2px;border-bottom-color:var(--tc,var(--ink-faint));color:var(--ink-dim)}
/* THE SENTENCE UNDER THE ROW. It carries the count, the verdict and the name of the filter, and it keeps a box
   whether or not there are words in it, so swapping tabs never moves the card under the reader's thumb.
   ⛔ THE RESERVE IS ONE LINE ON THE DESKTOP, TWO ON THE PHONE - MEASURED (tools/_w29a_say.py nfl 1440). A desktop
   tile's body is a FIXED 185px box with overflow:hidden, and src/01k_integ.js takes any row that hangs past it
   off the screen outright: with a two-line (36px) reserve the rates card's sentence came out `visibility:hidden`,
   4px past the clip - the count would have vanished from the console altogether, because the count lives in this
   sentence now. A fixed box cannot jump, so it does not need the reserve; the phone column can, and keeps it. */
.bbs-say,.bbtab-say{font-family:var(--ui);font-size:13px;line-height:1.35;color:var(--ink-dim);
  margin:2px 0 0;min-height:18px}
.bbs-say b,.bbtab-say b{color:var(--ink);font-weight:600}

/* SAMPLE HONESTY (addition 7): under eight games every mark is hollow, win or loss. The colour is kept as the
   outline so a reader who knows the code still reads which way it went, and nobody reads a thin sample as solid. */
.bbs-hit.thin .bbs-mk i.ok:before{background:none;border:1px solid var(--tc,var(--bbs-w))}
.bbs-hit.thin .bbs-mk i.ok{color:var(--tc,var(--bbs-w))}
.bbs-hit.thin .bbs-bar{opacity:.72}


/* ================================================================================================================
   THE VERSION-TWO PRIMITIVES - [W14B 2026-09-17]. The stylesheet for K.sprows / K.spread (src/00b_kit2.js) and
   for the wrap the tick row lost. These three classes are what the brief's additions 2, 4 and 11 are DRAWN with,
   so they live once, beside the kit that emits them, rather than in each sport file.

   ⛔ THE TICK ROW'S LOST WRAP, MEASURED. src/scenes.css:353 gives .r9-tl2 `flex-wrap:wrap`; :356 re-declares the
   same selector three lines later WITHOUT it (a leftover of an older pass - the two blocks are otherwise the same
   rule). Equal specificity, later wins, so the LABELS under a tick row never wrapped while the TICKS above them
   did. That is the whole of the vet's "the drawing is 779 px wide in a 322 px box - 6 of its labels start off the
   right edge" on afl, nrl and epl (CONSOLE_VET_2026-09-17 section 3, findings 11, 12 and 14). src/*.css is
   concatenated AFTER scenes.css, so restoring it here wins without touching the file W14A is finishing in. The
   tick and its label are both 30 px wide with a 6 px gap, so both rows break at the same count and a label stays
   under the mark it names.
   ================================================================================================================ */
.r9-tl2{flex-wrap:wrap}

/* THE NUMBERS BEHIND IT (addition 2): label, the number in the bet side's club colour, what it means.
   ⛔ MEASURED: the host's own floor sheets carry `#obtStage ... b { font-size:12px }` at an id's specificity, so a
   plain `.r9-sp .n{font-size:17px}` lost and the number painted at 12 px - the same size as its label, which is
   the one thing the prototype's tile does NOT do (the number is the thing the eye lands on). Every rule here is
   written at #obtStage so the grid wins, and the floors are respected by being ABOVE them, never under. */
#obtStage .r9-sp{display:grid;grid-template-columns:1fr auto auto;gap:6px 12px;align-items:baseline;
  font-family:var(--ui);font-size:13px;line-height:1.3;margin:2px 0 8px}
#obtStage .r9-sp .l{color:var(--ink-dim);font-size:13px}
#obtStage .r9-sp .n{font-size:17px;font-weight:700;color:var(--tct,var(--ink));font-variant-numeric:tabular-nums;white-space:nowrap}
#obtStage .r9-sp .d{color:var(--ink-faint);text-align:right;font-size:12px}
@media (max-width:760px){#obtStage .r9-sp{grid-template-columns:1fr auto}#obtStage .r9-sp .d{grid-column:1/3;text-align:left;margin:-4px 0 4px;font-size:13px}}

/* ⛔⛔ [W24B 2026-09-20] AND THE READING SHEET IS NOT INSIDE #obtStage.
   LOOKED AT, shots/w22a/w24b_nfl_spine_modal_1440.png: the top of the "Read it all" sheet on the NFL proof stop
   read, as one unbroken line of text,
       "Margin, average-2.3won 3 of 6Points a game17.8their best was 28Points let in20let in 20 or fewer in 3 of 6"
   - the three-column grid above is scoped to #obtStage and the modal is appended OUTSIDE it, so every K.sprows
   block lost its display:grid and collapsed into run-on prose the moment a reader opened the sheet. That is not a
   spine defect: it hits EVERY organ that draws these rows (spine, coach, and anything that reaches for the same
   object), on the one surface the owner asked for by name ("make sure read it all pops up a modal ... make sure
   its elite on phone and desktop"). The rules are repeated here under .r9-modal at the same specificity weight,
   with the same numbers, so the sheet and the tile read as ONE object. The 760 px rule is repeated too: a phone
   sheet is the narrowest place these rows are ever read. */
.r9-modal .r9-sp{display:grid;grid-template-columns:1fr auto auto;gap:6px 12px;align-items:baseline;
  font-family:var(--ui);font-size:13px;line-height:1.3;margin:2px 0 10px}
.r9-modal .r9-sp .l{color:var(--ink-dim);font-size:13px}
.r9-modal .r9-sp .n{font-size:17px;font-weight:700;color:var(--tct,var(--ink));font-variant-numeric:tabular-nums;white-space:nowrap}
.r9-modal .r9-sp .d{color:var(--ink-faint);text-align:right;font-size:12px}
@media (max-width:760px){.r9-modal .r9-sp{grid-template-columns:1fr auto}.r9-modal .r9-sp .d{grid-column:1/3;text-align:left;margin:-4px 0 4px;font-size:13px}}

/* IN 100 GAMES (addition 4): a band spread. The bands that LAND THE BET take the club colour; the rest are the
   hairline ink. 8 px radii on the bar tops per DESIGN LAW v2. Hollow under the eight-game floor. */
/* ⛔ [W24B 2026-09-20] THE READING SHEET LIVES OUTSIDE #obtStage.
   LOOKED AT, shots/w22a/w24b_nfl_spine_modal_1440.png: a K.sprows block inside the "Read it all" sheet had
   collapsed into one run-on line of prose because its grid is written at #obtStage and the modal is appended
   to the page OUTSIDE that id. Every organ-body shape in this file had the same hole - the sheet is where a
   reader goes for MORE, so a drawing that only exists on the tile is the wrong way round. The selectors below
   carry a .r9-modal twin; the declarations are written ONCE so the tile and the sheet can never drift.
   (#obtStage is still needed on the tile: the host floor sheets carry #obtStage rules that a plain class
   selector loses to. Inside .r9-modal nothing competes, so a plain twin is enough there.) */
#obtStage .r9-spr,.r9-modal .r9-spr{display:flex;align-items:flex-end;gap:4px;height:78px;margin:4px 0 26px;position:relative}
/* ⛔ 3 px ON THE BAR TOPS, NOT 8. The approved prototype's own spread is `border-radius:3px 3px 0 0` (.dist div),
   and tools/desk_law_test.py counted 16 of these 8 px bars as PILLS - it is a v1 rule but it is reading the same
   shape the prototype deliberately did not draw. The 8 px radius law is about tiles, chips, ticks and sheets. */
#obtStage .r9-spr span,.r9-modal .r9-spr span{flex:1 1 0;min-width:0;background:var(--line);border-radius:3px 3px 0 0;position:relative}
#obtStage .r9-spr span.o,.r9-modal .r9-spr span.o{background:var(--tc,var(--ink))}
/* ⛔⛔ [W16B 2026-09-18] NEVER DOTTED BOXES. The owner, on prod with list #12 (18 Sep 08:00): "that does not fully
   look like your mockup". MOCKUP_DIFF row B3, LOOKED AT on shots/w16b/base/nfl_call_1440.png: a six-game sample
   drew four EMPTY DASHED OUTLINES where the prototype draws bars, and read as a broken chart, not as honesty.
   The honesty is real and it stays - a thin sample must not look like a finding - but it is carried by the SIZE OF
   THE INK, not by taking the ink away: a thin band is the same bar at just over half strength, and the card's own
   sentence still says how many games it is counted over. The prototype has no dashed rectangle anywhere.
   tools/tile_test.py T6 fails any spread drawn with a dashed border, so this cannot come back by accident. */
   ⛔ AND NOT `opacity` EITHER. The band's end label is an <i> INSIDE the span, and a child can never be more opaque
   than its parent's opacity group - fading the bar to .62 fades the two words that orient the reader with it, under
   the ink floor. The strength is carried on the BACKGROUND only, so the labels stay at full ink. The plain colour is
   declared first and a browser without color-mix simply gets the solid bar. */
#obtStage .r9-spr.h span,.r9-modal .r9-spr.h span{background:var(--line);border:0;border-radius:3px 3px 0 0}
#obtStage .r9-spr span.z,.r9-modal .r9-spr span.z{border-radius:0;opacity:.55}
#obtStage .r9-spr.h span.o,.r9-modal .r9-spr.h span.o{background:var(--tc,var(--ink));background:color-mix(in srgb,var(--tc,var(--ink)) 62%,transparent)}
#obtStage .r9-spr i,.r9-modal .r9-spr i{position:absolute;top:100%;left:0;margin-top:5px;font-style:normal;font-family:var(--ui);
  font-size:12px;line-height:1.1;color:var(--ink-faint);white-space:nowrap}
#obtStage .r9-spr span:last-child i,.r9-modal .r9-spr span:last-child i{left:auto;right:0}
@media (max-width:760px){#obtStage .r9-spr,.r9-modal .r9-spr{height:70px;margin-bottom:28px}#obtStage .r9-spr i,.r9-modal .r9-spr i{font-size:13px}}

/* ================================================================================================================
   THE TEXT FLOORS INSIDE THE DRAWING KIT - [W14B 2026-09-17].
   console_vet measured 59 texts under the floor on the MLB Matchup stop at 1600 and 38 at 390, and desk_law_test
   counted 101 across the console (W14A_STATUS "the 169 under the floor are ORGAN INTERNALS, 165 of them MLB").
   Every one of them is a kit class sized in rem fractions written for v1's denser card: .r9-lcp b at .54rem is
   8.6 px, .r9-lcp small at .52rem is 8.3 px, .r9-dg b at .56rem is 9 px, .r9-dg span at .72rem is 11.5 px, and
   src/scenes.css:402's v2 override lifts the CHIP to 13 px while leaving the two children where they were.
   v2 puts lineupcard / starters / depth on the Matchup stop, where the brief puts them - above the door, not
   behind it - so these sizes are now on the reader's screen and they go to the floor: 12 px desktop, 13 px phone.
   ================================================================================================================ */
#obtStage .r9-lcp b,#obtStage .r9-lcp small,#obtStage .r9-dg b,#obtStage .r9-dg span,
#obtStage .r9-lch,#obtStage .r9-depth,#obtStage .r9-lcp{font-size:12px;letter-spacing:0}
#obtStage .r9-lch{font-family:var(--ui);text-transform:none}
@media (max-width:760px){
  #obtStage .r9-lcp b,#obtStage .r9-lcp small,#obtStage .r9-dg b,#obtStage .r9-dg span,
  #obtStage .r9-lch,#obtStage .r9-depth,#obtStage .r9-lcp{font-size:13px}
}


/* THE LEGEND'S WORDS ARE WORDS - [W14B 2026-09-17]. src/scenes.css sizes .r9-legend span at .62rem = 9.9 px, and
   desk_law_test read four of them on the NFL console ("Steelers scored", "Falcons" under `periods` and `playcall`).
   A legend is the key to the drawing above it; it is the last thing that should be unreadable. 12 / 13 px. */
#obtStage .r9-legend span,#obtStage .r9-legend{font-size:12px}
@media (max-width:760px){#obtStage .r9-legend span,#obtStage .r9-legend{font-size:13px}}

/* ================================================================================================================
   THE TICK ROW WRAPS ON A PHONE - [W14B 2026-09-17]. THE MEASUREMENT: on afl/call at 390 the tick row reported
   width 322 and scrollWidth 714, and its label row 322 / 779. console_vet read exactly that and called it what a
   reader would: "the drawing is 779 px wide in a 322 px box - 6 of its labels (GEEL, RICH, STK) start off the
   right edge and only a sideways scroll reaches them" (CONSOLE_VET findings 12, 13, 15 - afl, nrl, epl).
   It is not a bug, it is a v1 DECISION: src/scenes.css:713 says "the CELL carries the row sideways when it will
   not fit, the same answer the wide tables get", and src/scenes.css:613 keeps a 20-square row on one line by
   shrinking the squares. Version two does not have that cell: the desktop pane is a fixed 3 x 2 that clips, and
   the phone section is a card in a stack. A row a thumb has to drag is a row half the reader never sees.
   So both rows WRAP, on the same 32 px + 6 px grid, which is how a code stays under the square it names - and the
   codes come off 10 px to the 13 px phone floor while they are there. Nothing is dropped and nothing shrinks.
   ================================================================================================================ */
@media (max-width:820px){
  #obtStage .r9-five .r9-ticks2,#obtStage .r9-five .r9-tl2{flex-wrap:wrap;gap:6px}
  #obtStage .r9-five .r9-ticks2 i{flex:0 0 auto;width:32px;height:32px;max-width:none;aspect-ratio:auto}
  #obtStage .r9-five .r9-ticks2.s i{width:20px;height:20px}
  #obtStage .r9-five .r9-tl2 span{flex:0 0 auto;width:32px;max-width:none;font-size:13px;letter-spacing:-.02em;overflow:hidden}
  #obtStage .r9-five .r9-tl2.s span{width:20px;font-size:13px}
}

/* ==================================================================================================================
   [W17B 2026-09-18] A TICK IN A v2 DESKTOP TILE IS SMALLER THAN A TICK ON A PHONE, AND THAT IS A MEASUREMENT.
   A v2 pane tile at 1440 is about 237px of inner width (265px column less the 14px padding each side this package
   put back). At the 44px tap floor five squares fill it and a sixth wraps, so a five-game form strip drew 4 + 1 and
   a twelve-game numbers strip drew three rows - most of it under the tile's clip. The 44px floor is a TOUCH rule
   (tools/phone_metrics.py measures it at 320 and 390, where these rules do not apply); a mouse pointer does not
   need it, and the prototype's own desktop tick is 22px. So the floor is kept exactly where it is enforced and the
   desktop tile gets the prototype's size. The numbers card drops the opponent code with it - the code is the FORM
   strip's job and the caption under the ticks still names the game when one is tapped.
   ================================================================================================================== */
@media (min-width:900px){
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .bbs-form .bbs-t{width:38px;min-height:40px}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .bbs-form .bbs-t i{width:22px;height:22px;font-size:12px}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .bbs-rates .bbs-t{width:26px;min-height:26px;gap:0}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .bbs-rates .bbs-t span{display:none}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .bbs-rates .bbs-t i{width:22px;height:22px;font-size:12px}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .bbs-tk{gap:4px}
}

/* Part 1w css: THE SURFACES - [W11B 2026-09-17] the four named rows + the gwx layout fix.
   ================================================================================================================
   STATUS: complete on disk. Built into the scene stylesheet by build_r9.py (src/0*.css, sort order).

   DESIGN LAW. One typeface (inherited - nothing here sets a family), the three inks, hairlines. No pill, no gauge,
   no glow, no gradient, no rounded chip, no upper-casing (84_desklaw.css would strip it anyway). The ONE accent is
   the club's own colour, arriving as an inline --c from src/00e_colours.js after a 3:1 contrast check against the
   real ground; every rule falls back to var(--ink-dim) when no colour was written, so a team we have no colour for
   is never given somebody else's.

   THE FLOOR. Nothing here is under 13px. 84_desklaw.css section 7 declares --bbfloor (12px desktop / 13px phone)
   and lifts anything below it; these rules sit at or above the phone floor at both widths so the floor never has
   to fire on them, and tools/desk_law_test.py measures it.

   TAPS. Nothing in these four organs is tappable, so there is no 44px target to hold. The rows are read, not
   pressed - the taps on these tabs belong to the picker, the door and the bottom bar.
   ================================================================================================================ */

/* ---- the club colour mark: a 3px bar, never a disc, never initials (owner law 2026-09-12) ------------------- */
/* [W13B 2026-09-17] --tc, not --c: one spelling for the club accent across the whole engine (muTwo, cover, the
   strips and the hero band all write --tc). The paint is unchanged; what changes is that the estate's own colour
   count can now see it. --c is still honoured so an older minted scene bundle paints the same. */
.r9s-tm { display: inline-block; width: 3px; height: 14px; flex: 0 0 3px; border-radius: 0;
  background: var(--tc, var(--c, var(--ink-dim))); }

/* ---- 1. WHO IS OUT ------------------------------------------------------------------------------------------ */
.r9s-out { display: flex; flex-direction: column; margin-top: 8px; }
/* [W11B fix 2026-09-17] NAMES WRAP, THEY NEVER CLIP. The row used nowrap + ellipsis on the name and the side, so
   at 320px the phone gate caught twelve cuts ("Harry Cunningha...", "Sydney Swa..."). A half-printed player name
   is worse than useless to a bettor deciding on a bet, and it is defect D5. The row wraps to a second line at
   the widths that need it; the club mark stays on the first line beside the name. */
.r9s-o { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; padding: 7px 0;
  border-top: 1px solid var(--line); font-size: 14px; line-height: 1.35; min-width: 0; }
.r9s-o:first-child { border-top: 0; }
.r9s-nm { color: var(--ink); font-weight: 600; white-space: normal; overflow-wrap: anywhere; }
.r9s-sd { color: var(--ink-dim); font-size: 13px; white-space: normal; overflow-wrap: anywhere; }
.r9s-imp { margin-left: auto; color: var(--ink-dim); font-size: 13px; white-space: normal; }
.r9s-more { margin: 6px 0 0; color: var(--ink-faint); font-size: 13px; }

/* ---- 2. THE CONDITIONS ROW ---------------------------------------------------------------------------------- */
/* one row across the read; it wraps on a phone instead of scrolling sideways, and each cell keeps its glyph and
   its words together. The hairline between cells is a border, not a pill edge. */
/* [W13B 2026-09-17] the cell is a div (a repeated row shape the estate's own count can see) laid out as a flex
   item; the glyph is 18px. Nothing about the way the row reads changes. */
.r9s-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0 18px; margin: 2px 0 10px; }
.r9s-it { display: flex; align-items: center; gap: 7px; padding: 7px 0; font-size: 14px;
  line-height: 1.3; color: var(--ink); white-space: nowrap; }
.r9s-gl { flex: 0 0 18px; color: var(--ink-dim); }
/* [W13B 2026-09-17] .r9s-say is gone with the say() helper that wrote it: the three sentences ride the organs'
   own `lead` now, which 04_engine.js paints as .r9-lead and scenes.css already styles. */

/* ---- 3. THE PRICE STORY ------------------------------------------------------------------------------------- */
.r9s-sp { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 2px 0 10px; }
.r9s-sp .r9-spark { flex: 0 0 auto; color: var(--ink); }
.r9s-spw { font-size: 14px; color: var(--ink-dim); white-space: nowrap; }

/* ---- 4. PUBLIC v US ----------------------------------------------------------------------------------------- */
.r9s-two { display: flex; flex-direction: column; gap: 8px; margin: 2px 0 10px; }
/* [W11B fix 2026-09-17] the name column was a fixed em cap (11/8.5/7.5) with an ellipsis, so our own side - the
   one row carrying the " . our call" suffix - read "Sydney Swan..." at 390, and in a narrow helper column at
   1600 as well. A clipped team name is exactly defect D5, which this wave exists to kill. The name column now
   takes what it needs and the BAR gives way (the bar is the decoration; the name and the count are the read),
   and where even that is not enough the name WRAPS instead of clipping. Two short lines beat half a name.
   tools/surfaces_test.py S5b measures scrollWidth against clientWidth on every bar label at both widths. */
.r9s-b { display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto; align-items: center;
  gap: 10px; font-size: 14px; line-height: 1.3; }
.r9s-bn { color: var(--ink-dim); white-space: normal; overflow-wrap: anywhere; }
.r9s-b.us .r9s-bn { color: var(--ink); font-weight: 600; }
.r9s-bt { display: block; height: 10px; background: transparent; border-bottom: 1px solid var(--line); }
.r9s-bt > i { display: block; height: 10px; background: var(--c, var(--ink-dim)); }
.r9s-bv { color: var(--ink); font-size: 14px; white-space: nowrap; }

/* ---- 5. THE GWX LAYOUT FIX (the hand-over from W10B) --------------------------------------------------------- */
/* `gwx` draws the wind as ONE arrow across a 520-unit field plus an hour-by-hour table. On a 1600px desktop it was
   landing in a 221px helper column with the arrow cut in half and the caption clipped mid-word. It is spliced to
   the END of the stop order by src/01w_surfaces.js (the headline conditions are `scond`'s job now) and it takes a
   full-width row wherever it lands, so the drawing is read at the size it was drawn at. */
/* THE ID QUALIFIER IS NOT DECORATION. scenes.css:3 pins every cell with
   `#obtStage .obt-bento.r9-grid .bc { grid-column: auto !important }` - an ID-qualified !important, which is why
   the house span classes exist at all. A plain `.r9-five .r9-deeper > .bc[data-organ="gwx"]` parses, matches the
   element and still loses the cascade (measured: computed grid-column-start stayed `auto`). Matching the ID and
   going one class deeper is what actually wins. */
#obtStage .obt-bento.r9-grid .r9-helpers > .bc[data-organ="gwx"],
#obtStage .obt-bento.r9-grid .r9-deeper > .bc[data-organ="gwx"] {
  grid-column: 1 / -1 !important; border-right: 0 !important; margin-right: 0 !important;
}
/* the drawing itself needs no rule: K.surface paints it at the cell's width once the cell is wide enough, and on a
   phone it keeps its own size inside its own overflow-x wrapper, which is the house answer for wide content. */
.bc[data-organ="gwx"] .r9-table { width: 100%; }

/* ---- 5b. THE READER'S OWN APPS, MARKED (J9) ------------------------------------------------------------------
   The apps table's last column ("yours") is HIDDEN under 900px by src/01i_deal.css - which is exactly where the
   reader needs to know which row is his. A 6px dot in the house accent beside the name says it at every width.
   It is a dot, not a pill: no border, no padding, no text inside. */
.r9d-apps > div.me > span:first-child { display: flex; align-items: center; gap: 7px; }
.r9d-dot { display: inline-block; width: 6px; height: 6px; flex: 0 0 6px; border-radius: 50%;
  background: var(--acc, var(--gold, var(--ink))); }

/* ---- 6. NARROW ---------------------------------------------------------------------------------------------- */
@media (max-width: 899px) {
  .r9s-row { gap: 0 14px; }
  .r9s-b { gap: 8px; }
  .r9s-imp { margin-left: auto; }
}
@media (max-width: 400px) {
  .r9s-sd { font-size: 13px; }
}

/* Part 1x (css): THE LIVE BAND + THE MATCHUP FOLD - [W12A 2026-09-17]. Dress for src/01x_liveband.js and for the
   folded `matchup` organ in src/01_organs.js.
   ================================================================================================================
   THE RULES THIS FILE KEEPS
     one typeface      every word is var(--ui). No second face, no mono anywhere.
     inks + hairlines  --ink / --ink-dim / --ink-faint for text, 1px var(--line) for every edge. No gradient, no
                       glow, no shadow, no radius, no pill.
     team colour       the one allowed accent. It arrives as --bbh-a / --bbh-h, written onto the head by
                       src/00d_hero.js ONLY when the club's colour clears 3:1 against the real ground behind the
                       band; every rule here falls back to var(--ink), so a club we have no colour for is honest
                       plain ink rather than an invented maroon.
     W/L colour        none. The live state word (on track / line ball / behind / home / gone) is ink: green and
                       red belong to the proof strips and nowhere else.
     size floor        13px on a phone, 12px on desktop (tools/desk_law_test.py). Nothing here is smaller.
     44px taps         nothing in this file is tappable, so nothing here needs a target.
   ================================================================================================================ */

/* ---------- THE BAND STAYS ONE ROW ----------
   MEASURED at 390px on the NFL bench recording: with the clock in it ("1st quarter, 10:00 left") the band wrapped
   onto three rows and the sticky head went from ~104px to 192px - which eats the fold AND trips block 89_hero.py's
   "the reader is parked under the sticky head, take him to the top" guard on the next repaint. The clock never
   wraps; the two club NAMES give way instead, exactly as they already do at 320px, because a reader beside two
   crests can read a shortened club name and cannot read a clock that is not there. */
#obtStage .obt-wsid .bbh{flex-wrap:nowrap}
#obtStage .obt-wsid .bbh .bbh-when{white-space:nowrap;flex:0 0 auto;max-width:58%;overflow:hidden;text-overflow:ellipsis}
#obtStage .obt-wsid .bbh .bbh-tm{min-width:0}
#obtStage .obt-wsid .bbh .bbh-tm b{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ---------- the score in the hero band (phone) ---------- */
#obtStage .bbh-sc[data-bbh-sc]{display:flex;align-items:baseline;gap:3px}
#obtStage .bbh-sc[data-bbh-sc] b{font-family:var(--ui);font-size:1.05rem;font-weight:700;line-height:1;
  font-variant-numeric:tabular-nums;color:var(--ink)}
#obtStage .bbh-sc[data-bbh-sc] b.sa{color:var(--bbh-a,var(--ink))}
#obtStage .bbh-sc[data-bbh-sc] b.sh{color:var(--bbh-h,var(--ink))}
#obtStage .bbh-sc[data-bbh-sc] i{font-style:normal;font-size:.8rem;color:var(--ink-faint);line-height:1}
/* past the freshness budget there is no score to show, and we say so in the clock words instead of showing one */
#obtStage .bbh-sc[data-bblb-off="1"]{display:none}

/* ---------- the score in the hero band (desktop) ---------- */
#obtStage .obt-wsid .mid.live-mid .bigsc{font-variant-numeric:tabular-nums}
#obtStage .obt-wsid .mid.live-mid .bigsc .sa{color:var(--bbh-a,var(--ink))}
#obtStage .obt-wsid .mid.live-mid .bigsc .sh{color:var(--bbh-h,var(--ink))}
#obtStage .obt-wsid .mid.live-mid .bigsc i{font-style:normal;color:var(--ink-faint);font-weight:400}

/* ---------- the bet's one state word, beside the price ---------- */
#obtStage .bblb-st{font-style:normal;font-weight:600;font-size:13px;color:var(--ink);white-space:nowrap}
#obtStage .phh-line .bblb-st:before{content:"\00b7";font-weight:400;color:var(--ink-faint);margin:0 5px}

/* ---------- where you stand: one sentence under the band, in play only ---------- */
#obtStage .bblb-ws{margin:5px 0 0;padding:5px 0 0;border-top:1px solid var(--line);
  font-family:var(--ui);font-size:13px;line-height:1.4;color:var(--ink-dim);
  display:flex;align-items:baseline;gap:7px;min-width:0}
#obtStage .bblb-ws b{color:var(--ink);font-weight:600;flex:0 0 auto}
#obtStage .bblb-ws span{min-width:0;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
@media (min-width:900px){#obtStage .bblb-ws{font-size:12px}}

/* ---------- the matchup fold: the two numbers side by side, in club colour ----------
   src/01_organs.js `matchup` used to open with a full mirror chart and a legend - 1,004px tall on a 390px phone,
   which pushed "Who is out" 1.7 screens down the matchup tab. The first paint is now these two numbers and one
   sentence; the chart is one tap away behind the organ's own "Go deeper" link. */
/* ⛔ [W24B 2026-09-20] THE READING SHEET LIVES OUTSIDE #obtStage.
   LOOKED AT, shots/w22a/w24b_nfl_spine_modal_1440.png: a K.sprows block inside the "Read it all" sheet had
   collapsed into one run-on line of prose because its grid is written at #obtStage and the modal is appended
   to the page OUTSIDE that id. Every organ-body shape in this file had the same hole - the sheet is where a
   reader goes for MORE, so a drawing that only exists on the tile is the wrong way round. The selectors below
   carry a .r9-modal twin; the declarations are written ONCE so the tile and the sheet can never drift.
   (#obtStage is still needed on the tile: the host floor sheets carry #obtStage rules that a plain class
   selector loses to. Inside .r9-modal nothing competes, so a plain twin is enough there.) */
#obtStage .r9mu2,.r9-modal .r9mu2{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:8px 0 2px}
#obtStage .r9mu2 .s,.r9-modal .r9mu2 .s{min-width:0;border-top:2px solid var(--tc,var(--ink-dim));padding:7px 0 0}
#obtStage .r9mu2 .s b,.r9-modal .r9mu2 .s b{display:block;font-family:var(--ui);font-size:1.6rem;font-weight:700;line-height:1.05;
  color:var(--ink);font-variant-numeric:tabular-nums}
#obtStage .r9mu2 .s em,.r9-modal .r9mu2 .s em{display:block;font-style:normal;font-size:13px;line-height:1.35;color:var(--ink);
  font-weight:600;margin:4px 0 0}
#obtStage .r9mu2 .s i,.r9-modal .r9mu2 .s i{display:block;font-style:normal;font-size:13px;line-height:1.35;color:var(--ink-faint);margin:1px 0 0}
@media (min-width:900px){#obtStage .r9mu2 .s em,.r9-modal .r9mu2 .s em,#obtStage .r9mu2 .s i{font-size:12px}}

/* 01y_officials.css - [W18C 2026-09-19] one rule, and here is why it is only one.
   ------------------------------------------------------------------------------------------------------------------
   src/01y_officials.js draws its pictures with objects the console already owns - K.rows (the bars: his games against
   the league's), K.rec (the ten-tick proof strip, which is the one place the design law allows W/L colour) and
   K.sprows (the club rows). Giving the same three shapes a second look would put two officials cards in one console
   that can drift apart, so nothing here restyles them.
   THE ONE THING THAT DID NEED A RULE: the officials card stacks TWO different objects - the bars (what his games run
   against the league's) and then the club rows (what they did with him on it). Butted together they read as one
   eight-row table and the reader cannot see where the subject changes. A hairline and the house gap separate them,
   and that is the whole file.
   DESIGN LAW: inks and hairlines only - no pill, no gauge, no glow, no gradient, no second typeface. Nothing here is
   tappable, so no 44 px target is owed. */
.r9of-clubs { margin-top: 11px; padding-top: 10px; border-top: 1px solid var(--line); }
.r9of-clubs .r9-sp { margin-top: 0; }

/* Part 1z stylesheet: THE DIRECT MATCHUP (organ `pvo`, src/01z_pvo.js). Owned by W22B, 2026-09-19.
   ---------------------------------------------------------------------------------------------------------------
   THREE COLUMNS AT 1440 AND ONE AT 390, and at 390 the two men sit SIDE BY SIDE with the tape under them - a
   face-off read top to bottom is two portraits, not a matchup. One typeface (var(--ui)), inks, hairlines, 8px
   radii, no pill, no glow, no gradient. The club colour arrives as --tc on each plate (K.tc, via 01z_pvo.js) and
   is used for the plate's own rule and the tape's bars - never as the only signal, because every number on this
   card is written as a number and every result mark beside it carries a letter. */
.pvo{display:grid;grid-template-columns:1fr minmax(0,1.25fr) 1fr;gap:12px;align-items:start;margin:6px 0 0}
.pvo-p{display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px;min-width:0;
  padding:10px 6px 12px;border:1px solid var(--line);border-radius:8px;position:relative;overflow:hidden}
/* the club's own colour as a rule along the top of the plate - a hairline, not a fill, so a bright club colour
   can never become the ground a 13px name is read on. */
.pvo-p:before{content:'';position:absolute;left:0;right:0;top:0;height:3px;background:var(--tc,var(--line))}
.pvo-p b{font-size:14px;line-height:1.25;font-weight:600;color:var(--ink);max-width:100%;overflow-wrap:anywhere}
.pvo-p span{font-size:13px;line-height:1.3;color:var(--ink-faint);max-width:100%;overflow-wrap:anywhere}
.pvo-p .r9-face{border-radius:8px;overflow:hidden;flex:none}
.pvo-p .r9-face img{width:100%;height:100%;object-fit:cover;display:block}
.pvo-p .pvo-cr{display:flex;align-items:center;justify-content:center;width:68px;height:68px;flex:none}
.pvo-p .pvo-cr img,.pvo-p .pvo-cr svg{width:58px;height:58px;object-fit:contain}
.pvo-mid{min-width:0;align-self:center}
/* the tape: his number, what it is, what they allow. Tabular numerals so the two columns line up on the decimal,
   which is the only reason a reader can compare them without reading. */
.pvo-t{display:flex;flex-direction:column;gap:0}
.pvo-t > div{display:grid;grid-template-columns:1fr auto 1fr;align-items:baseline;gap:8px;
  padding:8px 0;border-top:1px solid var(--line)}
.pvo-t > div:first-child{border-top:0;padding-top:2px}
.pvo-t .a,.pvo-t .b{font-size:17px;line-height:1.2;font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
.pvo-t .a{text-align:right}
.pvo-t .b{text-align:left;color:var(--ink-dim);font-weight:400;font-size:14px}
.pvo-t .l{font-size:13px;line-height:1.3;color:var(--ink-faint);text-align:center;white-space:nowrap}
@media (max-width:899px){
  .pvo{grid-template-columns:1fr 1fr;gap:10px}
  .pvo-mid{grid-column:1 / -1;order:2}
  .pvo-t .a{font-size:18px}
  .pvo-t .l{white-space:normal}
}
/* ⛔ INSIDE A v2 PANE TILE, THREE COLUMNS IS TWO TOO MANY. MEASURED on shots/w22b/after4/nfl_player_stop_1440.png:
   the pane cell is ~237-340px wide, and the three-column layout put the tape between the two plates with about
   90px for it - "51.9 his rushing yards a ga..." ran under the opponent's crest and the third row fell off the
   card. A card whose numbers are covered by its own pictures is worse than no card.
   So a tile uses the PHONE layout: the two men side by side across the top, the tape full width beneath them.
   That is the approved prototype's own shape for a two-man card at any narrow width, it needs no new object, and
   every number is then read at its own size with the whole cell to sit in. The face comes down to 44px because a
   68px plate over a 110px column leaves no room for the name under it. */
@media (min-width:900px){
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .pvo{grid-template-columns:1fr 1fr;gap:10px}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .pvo-mid{grid-column:1 / -1;order:2}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .pvo-p{padding:8px 4px 10px}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .pvo-p .r9-face,
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .pvo-p .pvo-cr{width:44px;height:44px}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .pvo-p .pvo-cr img,
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .pvo-p .pvo-cr svg{width:38px;height:38px}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .pvo-p span,
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .pvo-t .l{font-size:12px}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .pvo-t .l{white-space:normal}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .pvo-t .a{font-size:15px}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .pvo-t .b{font-size:13px}
}
/* the tape's own guard at every width: the middle label may wrap, and neither number column may be squeezed
   under the width of the number it holds. */
.pvo-t .a,.pvo-t .b{min-width:0;overflow-wrap:anywhere}
.pvo-t .l{min-width:0}
/* ⛔ A THREE-ACROSS ROW DOES NOT FIT A 237px CELL EITHER. MEASURED on the same capture: "61 allowed" broke to
   three lines and ran off the bottom of the tile. In a narrow box the row stacks - his number and what it is on
   the first line, what the opponent allows on the second, right-aligned under it - which is how a versus strip
   is read on a phone anyway. */
@media (max-width:899px){
  .pvo-t > div{grid-template-columns:auto 1fr}
  .pvo-t .a{grid-column:1;text-align:left}
  .pvo-t .l{grid-column:2;text-align:left}
  .pvo-t .b{grid-column:1 / -1;text-align:left;margin-top:2px}
}
@media (min-width:900px){
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .pvo-t > div{grid-template-columns:auto 1fr}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .pvo-t .a{grid-column:1;text-align:left}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .pvo-t .l{grid-column:2;text-align:left}
  #obtStage .obt-bento.r9-grid.r9-v2 .r9-pane .pvo-t .b{grid-column:1 / -1;text-align:left;margin-top:2px}
}
/* a plate with no picture keeps its rule and its name and takes no portrait-sized hole */
.pvo-p.nop{justify-content:center;min-height:0;padding-top:14px}

/* ====================================================================================================================
   04m_modal.css - [W22A 2026-09-19] THE READING SHEET. "Read it all" (and a tile's own name) opens the organ at full
   size in a layer: a centred sheet on a desktop, a bottom sheet on a phone.

   Owner, 19 Sep 13:00: "make sure read it all pops up a modal. make sure its elite on phone and desktop."

   THE RULES THIS FILE HOLDS, and the reason each one is a rule:
     * THE PAGE BEHIND NEVER SCROLLS. `html.r9-noscroll` is set while the sheet is up. The desktop terminal has never
       scrolled; a phone does, and a sheet that lets the page scroll under it loses the reader's place the moment
       they close it.
     * THE SHEET'S BODY SCROLLS, NOT THE SHEET. The head is sticky and the body is the only scrolling box, so the
       name of the reading and the way out are on the screen at every scroll position - on a 620 px table as much as
       on a two-line note.
     * ONE TYPEFACE (var(--ui)), inks, hairlines, 8 px radii, 44 px taps on a phone. No pill, no glow, no gradient.
     * THE BET SIDE'S CLUB COLOUR comes in on `--tc` (set inline by E.openModal) so a reading's ticks and bars paint
       in the sheet exactly as they paint in the tile.
   The base .r9-modal geometry is src/scenes.css:380; this file loads after it and upgrades it for every modal,
   including the glossary and the key card - both of which get the same sticky head and the same way out.
   ==================================================================================================================== */
html.r9-noscroll, html.r9-noscroll body { overflow: hidden !important; }

/* the scrim. scenes.css:380 sets rgba(0,0,0,.55); LOOKED AT on shots/w22a/AFTER_nfl_proof_1440_modal.png the rail
   and the Ask column behind it were still fully legible and competed with the reading in front. */
.r9-modal { padding: 24px; background: rgba(6, 8, 12, .74); }
.r9-modal .box {
  width: min(920px, 94vw); max-width: min(920px, 94vw); max-height: 86vh;
  display: flex; flex-direction: column; overflow: hidden;
  border-radius: 8px; padding: 0; font-family: var(--ui);
}
.r9-modal .box h3 {
  flex: 0 0 auto; position: sticky; top: 0; z-index: 2;
  margin: 0; padding: 14px 18px; gap: 14px;
  background: var(--panel, #0e1117); border-bottom: 1px solid var(--line);
  align-items: center; font-size: 16px; line-height: 1.25;
}
.r9-modal .box .r9m-body { flex: 1 1 auto; overflow: auto; padding: 16px 18px 20px; -webkit-overflow-scrolling: touch; }

/* the head: icon + the reading's name, and under it the bet every number in the sheet is about */
.r9m-t { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
.r9m-t .r9-oi { width: 18px; height: 18px; flex: 0 0 auto; fill: currentColor; opacity: .85; }
.r9m-sub { flex: 0 0 100%; font-size: 12px; font-weight: 400; color: var(--ink-faint, #8a93a5); letter-spacing: 0; }
.r9m-nav { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; margin-left: auto; }
.r9-modal .box h3 .r9m-nav button {
  background: none; border: 1px solid transparent; border-radius: 8px; font: inherit; font-size: 13px;
  color: var(--ink-faint, #8a93a5); cursor: pointer; padding: 6px 10px; min-height: 32px;
}
.r9-modal .box h3 .r9m-nav button:hover { color: var(--ink); border-color: var(--line); }
.r9m-arw { font-size: 15px !important; min-width: 32px; }

/* the sheet's own content. The organ's body is printed exactly as the tile printed it; what follows is the depth the
   tile had no room for - r.full, then each r.more block under its own name. */
.r9m-lead { margin: 10px 0 0; }
.r9m-full { margin: 14px 0 0; }
.r9m-sec { margin: 16px 0 0; padding: 14px 0 0; border-top: 1px solid var(--line); }
.r9m-sec h4 { margin: 0 0 8px; font: 600 13px/1.3 var(--ui); color: var(--ink); }
.r9-omodal .r9m-body table { width: 100%; }
.r9-omodal .r9m-body p { font-size: 13px; }
/* nothing inside the sheet is clipped - that is the whole point of it */
.r9-omodal .r9m-body .bb, .r9-omodal .r9m-body .bc { max-height: none; overflow: visible; }
.r9-omodal .r9m-body svg { max-width: 100%; height: auto; }

/* the guest's door, once and large (E.guestGate shells the organ and returns ONE door; never a second under it) */
.r9-omodal .r9m-body .r9cta { display: block; width: 100%; margin-top: 14px; padding: 14px 18px; font-size: 15px; }
.r9-omodal .r9m-body .r9pd-blur { margin-bottom: 10px; }

/* a tile's name is its door (cell(), src/04_engine.js): a button that looks exactly like the label it replaced */
.bh .lab.r9m-open {
  background: none; border: 0; padding: 0; margin: 0; font: inherit; color: inherit;
  text-align: left; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;
}
.bh .lab.r9m-open:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }

/* ---------------------------------------------------------------------------------------------------------------
   THE PHONE: a bottom sheet. 44 px on the close and on both arrows (the design law's tap floor), the head sticky,
   the body the only thing that moves. scenes.css:828 already puts the sheet at the bottom of the screen; this
   sizes it for a thumb. (The Back gesture is the HOST's - see src/04_engine.js openModal and W22A ask 1.)
   --------------------------------------------------------------------------------------------------------------- */
@media (max-width: 899px) {
  .r9-modal { padding: 0; }
  .r9-modal .box {
    /* the sheet takes the room the READING needs, between half the screen and nearly all of it. LOOKED AT on
       shots/w22a/AFTER_nfl_proof_390_modal.png at a fixed 94vh: a five-game strip left 280 px of empty panel under
       it, which reads as a page that failed to load rather than as a short reading. */
    width: 100%; max-width: 100%; height: auto; min-height: 52vh; max-height: 94vh;
    border-radius: 12px 12px 0 0; border-bottom: 0;
  }
  .r9-modal .box h3 { margin: 0; padding: 12px 14px; font-size: 15px; }
  .r9-modal .box .r9m-body { padding: 14px 14px 28px; }
  .r9-modal .box h3 .r9m-nav button { min-width: 44px; min-height: 44px; padding: 6px 8px; justify-content: center; }
  .r9m-sub { font-size: 12px; }
  .r9-omodal .r9m-body p { font-size: 13px; }
}

/* [integrator 2026-09-20] SEEN in shots/w22a/L19_mlb_park_modal.png: a drawing authored for a 341 px tile becomes a 450 px tall
   diamond in a 920 px sheet and pushes every number under the fold. A drawing in the sheet is capped at 44% of the viewport height
   (never under 220 px); the viewBox keeps its shape, so nothing is squashed - it is simply not allowed to be the whole sheet. */
/* [W24A 2026-09-20] THE CAP IS RIGHT IN KIND AND WAS TOO GENEROUS AT A DESK. MEASURED in the open sheet
   (tools/_w24a_probe-style measurement, mlb "The park" at 1440): viewBox 340x190, rendered 882 x 493 - a diamond
   taking 55% of an 86vh sheet, with "The ground" printed across it and every number it exists to explain pushed
   under the fold (LOOKED AT, shots/w24a/SHEET_mlb_park_1440.png). 44vh of a 900 px window is 396 px, which is still
   most of the sheet. A drawing in the sheet is an ILLUSTRATION of the numbers beside it, not the sheet itself.
   A first cut of this fix gave wide drawings the full width instead, and made the park WORSE (493 px, measured) -
   it is written up in round10w/W24A_STATUS.md and was thrown away. One cap, tighter at a desk where the sheet is
   920 px wide and the reader has a mouse, unchanged on a phone where a drawing has earned half the screen.
   `width:auto` stays: it is what keeps a 6:1 drive chart from being letterboxed inside a box it cannot fill. */
.r9-omodal .r9m-body svg{max-height:min(40vh,360px);width:auto;max-width:100%;display:block;margin-left:auto;margin-right:auto}
@media (max-width:760px){
  .r9-omodal .r9m-body svg{max-height:max(220px,44vh)}
}
.r9-omodal .r9m-body .r9-table svg,.r9-omodal .r9m-body button svg,.r9-omodal .r9m-body .bbs svg{max-height:none;width:revert;margin:0;display:revert}

/* ====================================================================================================================
   [W24A 2026-09-20] A REPAINT IS NOT AN ARRIVAL.  (It lives in this file because the scene bundle is the only
   stylesheet this package owns, and the rule needs no host wiring at all - `.obt-bento.r9-re .bc` is specificity
   0-3-0 and beats the host's `.bc{animation:obtIn .26s ease both}` from any stylesheet, in any order.)

   MEASURED with the live shim ticking at 390 (tools/_w24a_focuswalk.py nfl 390 live): 37 of 45 controls in the pane
   returned checkVisibility() false and could not take the keyboard AT ALL, because a live frame rebuilds the deck and
   every new tile goes back into the opacity-0 phase of the host's entry animation - and an element in that phase is
   not a rendered box. Off the shim the same walk reads 38 of 42 focusable. That is bench_tap_test's S4 at 390: the
   control the check picked could never hold focus in the first place, so there was never a keyboard for a frame to
   steal. It is also the flash the owner reported on prod, six tiles re-entering under him on every tick.

   The fade-up is right the first time a reading appears and wrong every rebuild after it, so it is spent per pane:
   src/04_engine.js stamps `r9-re` on the bento when the same game + same bet + same stop is rendered again.
   ==================================================================================================================== */
.obt-bento.r9-re .bc{animation:none;opacity:1;transform:none}

/* ====================================================================================================================
   [W24A 2026-09-20] THE LIGHT THEME'S BLACK BLOB. (In this file for the same reason as the rule above: the scene
   bundle is the only stylesheet this package owns, and `:root[data-theme="light"] .r9cta` is specificity 0-2-0, so
   it beats the host's own `.r9cta` colour from any stylesheet, in any order, with no host wiring and no mint.)

   Owner, 19 Sep, off his own machine: "LIGHT THEME BROKEN ... Track it verbs black blobs".
   MEASURED (tools/light_theme_test.py, the STAMPED light state, nfl + mlb + afl + soccer_epl x 1440, 390 x guest,
   sub - 21 of the 95 failures): the verb reads rgb(15,17,24) on rgb(16,19,26). 1.01:1. Black on black.

   The FILL is a host surface that stays dark in the light theme on purpose - a dark primary action on a light page
   is the console's own look and is what the approved prototype draws - and it is left alone. What did not follow it
   is the LABEL, which takes the light theme's near-black ink and vanishes into the button it is printed on. Only the
   label moves. After: white on rgb(16,19,26) = 18.9:1.
   ==================================================================================================================== */
:root[data-theme="light"] .r9cta,
:root[data-theme="light"] .obt-verb,
:root[data-theme="light"] .r9-verb,
:root[data-theme="light"] .ub.u-slip,
:root[data-theme="light"] .r9-btn.p{color:#fff}

/* ======================================================================================================================
   04n_dive.css - [W42A 2026-09-26] THE MARKET DIVE: three table cards on the pick stop, and the rule bar above them.
   OWNER, 26 Sep 20:20, choosing mockup B: "B for sure. put it in."
   ACCEPTANCE: round9/shots/mkt/dive_B_1440.png and dive_B_390.png, captured inside this console by tools/_mkt_dive.js.

   EVERYTHING HERE IS THE CONSOLE'S OWN LANGUAGE. One typeface (var(--ui)), hairlines (var(--line)), ink tokens, the
   club colour only through --tc, 8-14 px radii, no pills, no gauges, no glow, no gradient, no mono-caps. The tables
   are .r9-tw > table.r9-table (scenes.css:413), the tab rows are .r9-otabs (scenes.css:383) - the SAME control every
   other organ's tab row uses, so a press is the same press - and the chips are .obt-chips .r9-chips .obt-chip
   (scenes.css:433). Nothing new is invented; what is here is geometry, and the one thing geometry has to do is keep
   1440 x 900 from scrolling.

   ⛔ WHY THE PANE RULE CARRIES !important AND AN EXTRA CLASS. tools/host_css/89_stops.css:99 writes the 3 x 2 grid
   with `!important` on every line (it has to: src/scenes.css sets the bento's geometry with !important of its own).
   A plain rule here would lose to it whatever the order of the two stylesheets, so the dive's one row of three is
   said with the same weight AND one class more specific (.r9-pane.r9-pane3), which wins on specificity alone and
   therefore cannot depend on which file the browser saw last.
   ====================================================================================================================== */

/* ---------------------------------------------------------------- 1. THE PANE: THREE CARDS, ONE ROW -------------- */
#obtStage .obt-bento.r9-grid.r9-v2 .r9-pane.r9-pane3 {
  grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
  grid-template-rows: minmax(0, 1fr) !important;
  grid-auto-rows: minmax(0, 1fr) !important;
}

/* ------------------------------------------- 2. THE RULE BAR: "Our call" as ONE ROW, above the three tables ------ */
/* mockup B keeps the pick's dollars sentence on the line above the pane and gives the pane to the tables. The card
   is the same .bc with the same Breakdown button it has always had - only its shape changes, so every gate that
   reads .r9-callcard, .r9-rule or the Breakdown door keeps reading exactly what it read before. */
#obtStage .r9-five .r9-diverow {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin: 0 0 10px;
}
#obtStage .r9-five .r9-diverow > .r9-rule {
  flex: 1 1 260px;
  min-width: 0;
  margin: 0;
  font-size: 13px;
  line-height: 1.35;
  color: var(--ink-dim);
}
/* ⛔ EVERY DECLARATION IN THIS BLOCK IS !important AND CARRIES ONE CLASS MORE THAN THE RULES IT HAS TO BEAT.
   MEASURED (shots/w42a/after_nfl_1440.png, the first cut): the bar came out 160 px tall with the confidence word at
   44 px, because `#obtStage .r9-five .bc.r9-v4 .r9-hnum{font-size:44px}` is written TWICE - src/scenes.css:1299 and
   tools/host_css/119_represent.css:39 - at exactly the specificity a plain rule here can only tie with, and the host
   chain is a separate stylesheet whose order this package does not control. 160 px off the top of a pane that must
   not scroll is 160 px taken off the three tables, and it cut a ten-game log to one row. */
#obtStage .r9-five .bc.r9-v4.r9-diverule {
  flex: 0 1 auto !important;
  display: flex !important;
  flex-direction: row !important;
  align-items: center !important;
  gap: 12px !important;
  min-width: 0 !important;
  margin: 0 !important;
  padding: 5px 12px !important;
  border: 1px solid var(--line) !important;
  border-left: 3px solid var(--tc, var(--line)) !important;
  border-radius: 10px !important;
  background: rgba(255, 255, 255, .012) !important;
}
#obtStage .r9-five .bc.r9-v4.r9-diverule > .bh {
  flex: 0 0 auto !important;
  display: flex !important;
  align-items: baseline !important;
  gap: 8px !important;
  margin: 0 !important;
  border: 0 !important;
  padding: 0 !important;
  min-height: 0 !important;
}
#obtStage .r9-five .bc.r9-v4.r9-diverule > .bb {
  flex: 1 1 auto !important;
  display: flex !important;
  flex-direction: row !important;
  align-items: center !important;
  gap: 12px !important;
  min-width: 0 !important;
  padding: 0 !important;
}
#obtStage .r9-five .bc.r9-v4.r9-diverule .r9-hero,
#obtStage .r9-five .bc.r9-v4.r9-diverule .r9-herocall {
  flex: 0 0 auto !important; min-height: 0 !important; margin: 0 !important; padding: 0 !important; display: block !important;
}
#obtStage .r9-five .bc.r9-v4.r9-diverule .r9-hnum,
#obtStage .r9-five .bc.r9-v4.r9-diverule .r9-hnum.r9-callword {
  font-size: 19px !important; line-height: 1.15 !important; margin: 0 !important; letter-spacing: 0 !important;
}
#obtStage .r9-five .bc.r9-v4.r9-diverule .r9-ctx { white-space: nowrap; }
#obtStage .r9-five .bc.r9-v4.r9-diverule .r9-oneline {
  flex: 1 1 auto !important;
  min-width: 0 !important;
  margin: 0 !important;
  font-size: 13px !important;
  line-height: 1.3 !important;
  color: var(--ink-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#obtStage .r9-five .bc.r9-v4.r9-diverule .r9-bd {
  flex: 0 0 auto !important;
  margin: 0 !important;
  padding: 0 !important;
  border-top: 0 !important;
  min-height: 0 !important;
}
/* ⛔ DESKTOP ONLY, AND THE PHONE IS THE REASON. The desktop prints the bet's own sentence on its own line ABOVE the
   bar (the .r9-diverow), so a second copy inside the bar would be the same words twice. The PHONE has printed that
   sentence INSIDE the call card since W40A (04_engine's `(mobile && ruleHtml)` branch, because a bet change redraws
   the card by node and a line above the pane went stale) - hiding it there took the one sentence that names the bet
   off the phone altogether. MEASURED by this package's own gate: "no .r9-rule sentence above the pane", 390, twice. */
@media (min-width: 900px) {
  #obtStage .r9-five .bc.r9-v4.r9-diverule .r9-rule,
  #obtStage .r9-five .bc.r9-v4.r9-diverule .r9-callprose,
  #obtStage .r9-five .bc.r9-v4.r9-diverule .r9-calldeep { display: none !important; }
}
/* a guest's shelled call is a bar's width of shell, not a card's: the door stays, the bars come down to one line */
#obtStage .r9-five .bc.r9-diverule .r9-callgate { display: flex; align-items: center; gap: 10px; }

/* ------------------------------------------------------- 3. THE CARD: head, one control row, the table, the door - */
/* ⛔ THE CARD'S HEAD IS LEFT EXACTLY AS THE v4 HEAD ALREADY IS, AND THAT IS A RULING, NOT AN OVERSIGHT.
   The first cut here clipped the name to one line with an ellipsis and dropped the context words to 11 px, and both
   are things this console has already MEASURED and refused: src/scenes.css:1274 records that a nowrap title cut
   "What matters here" and a nowrap context cut "63 in 100 - price needs 47" (desk_law_test, 1600 and 390), and the
   DESIGN LAW's floor is 12 px on a desktop. Two lines of a 13 px name cost the card 17 px; a cut name costs it the
   reader. What IS reclaimed is the SECOND wrapped line the toggle was causing - it moves into the tab row below
   (see .r9-dtogs), which is a row the card was paying for anyway. */
#obtStage .r9-five .bc.r9-dcard > .bb {
  display: flex !important;
  flex-direction: column;
  min-height: 0;
  gap: 0;
}
/* the door row is pinned to the bottom of the card, which is what makes E.diveFit's measurement stable: the limit
   it cuts rows against does not move as rows come off. */
/* ⛔ THE DOOR NEVER LOSES ITS ROW TO THE FOOT. LOOKED AT (shots/w42a/after_nfl_1440_sheet.png, a 1424 x 805 window):
   "every game: 21 of 25 - avg 5..." took the whole row and "+3 more" had nowhere to go, on the one card that was
   hiding seven rows. The count is what truncates; the way to the rows it is counting never does. */
#obtStage .r9-five .bc.r9-dcard .r9-bd {
  margin-top: auto;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}
#obtStage .r9-five .bc.r9-dcard .r9-bd .r9-bdctx {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#obtStage .r9-five .bc.r9-dcard .r9-bd .r9-bdbtn { flex: 0 0 auto; white-space: nowrap; }
#obtStage .r9-five .bc.r9-dcard .r9-tw { min-height: 0; overflow-x: auto; overflow-y: hidden; }

/* the tab row inside a dive card: the console's own .r9-otabs, one line, sideways with a cue when it does not fit */
#obtStage .r9-five .bc.r9-dcard .r9-dtabs {
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  margin: 2px 0 8px;
}
#obtStage .r9-five .bc.r9-dcard .r9-dtabs::-webkit-scrollbar { display: none; }
#obtStage .r9-five .bc.r9-dcard .r9-dtabs button { white-space: nowrap; }
#obtStage .r9-five .bc.r9-dcard .r9-dchips { margin: 0 0 8px; display: flex; flex-wrap: wrap; gap: 6px; }
#obtStage .r9-five .bc.r9-dcard .r9-dchips .obt-chip { font-size: 12px; padding: 3px 9px; border-radius: 8px; }

/* the toggle sits at the right end of the tab row (mockup B: "over 2.5 · home | away"), and in the context slot
   only on a card that has no tabs to hang it on */
/* ⛔ AND IT IS STICKY, because the row it sits in scrolls sideways. MEASURED at 1440: with three tabs and three
   toggle words the row is wider than a 341 px card, so "Home | Away" scrolled off the right edge and the reader had
   a control he could not see. Sticky to the right edge with the card's own ground behind it, the toggle is always
   there and the TABS are what scroll under it - which is the right way round, because the reader is standing on
   one tab and choosing among many. */
#obtStage .r9-five .bc.r9-dcard .r9-dtogs {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex: 0 0 auto;
  padding-left: 10px;
  position: sticky;
  right: 0;
  /* a flat ground, never a fade: the DESIGN LAW has no gradients in it */
  background: var(--panel-2);
  box-shadow: -8px 0 0 var(--panel-2);
}
#obtStage .r9-five .bc.r9-dcard .r9-dtog {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-family: var(--ui);
  color: var(--ink-faint);
  cursor: pointer;
  border-bottom: 1px solid transparent;
}
#obtStage .r9-five .bc.r9-dcard .r9-dtog:hover { color: var(--ink-dim); }
#obtStage .r9-five .bc.r9-dcard .r9-dtog.on { color: var(--ink); border-bottom-color: var(--tc, var(--ink)); }
#obtStage .r9-five .bc.r9-dcard .r9-dtog:focus-visible { outline: 1px solid var(--ink); outline-offset: 2px; }
#obtStage .r9-five .bc.r9-dcard .r9-dsep { color: var(--ink-faint); font-style: normal; opacity: .6; }

/* a sortable column header is a button, so the keyboard and the reader-out get it for nothing */
#obtStage .r9-five .bc.r9-dcard .r9-dsort {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 3px;
}
#obtStage .r9-five .bc.r9-dcard th.n .r9-dsort { flex-direction: row-reverse; }
#obtStage .r9-five .bc.r9-dcard .r9-dsort:hover { color: var(--ink-dim); }
#obtStage .r9-five .bc.r9-dcard .r9-dsort.on { color: var(--ink); }
#obtStage .r9-five .bc.r9-dcard .r9-dsort:focus-visible { outline: 1px solid var(--ink); outline-offset: 2px; }
#obtStage .r9-five .bc.r9-dcard .r9-dcar { width: 9px; height: 9px; opacity: 0; flex: 0 0 auto; }
#obtStage .r9-five .bc.r9-dcard .r9-dsort.on .r9-dcar { opacity: 1; }

/* the table itself, at the desktop floor (12 px) with hairline rows - the console's own .r9-table, tightened by
   two pixels a row so a card holds the rows the brief asks it to hold. */
#obtStage .r9-five .bc.r9-dcard .r9-table { font-size: 12px; }
#obtStage .r9-five .bc.r9-dcard .r9-table th { padding: 3px 8px 3px 0; white-space: nowrap; }
#obtStage .r9-five .bc.r9-dcard .r9-table td { padding: 4px 8px 4px 0; white-space: nowrap; vertical-align: middle; }
#obtStage .r9-five .bc.r9-dcard .r9-table th:last-child,
#obtStage .r9-five .bc.r9-dcard .r9-table td:last-child { padding-right: 0; }
#obtStage .r9-five .bc.r9-dcard .r9-table tr.me td { font-weight: 600; color: var(--ink); }
#obtStage .r9-five .bc.r9-dcard .r9-table tr:last-child td { border-bottom: 0; }

/* ⛔ THE ROWS THAT DO NOT FIT. `data-dspill` is the brief's cap (7 / 6 / 6), written at build time; `data-dhid` is
   what E.diveFit took off after the browser measured the card. Both are on the door's count and both are in the
   Breakdown, so a row is never lost - only moved one press away. The phone shows every row (section 5). */
#obtStage .r9-five .bc.r9-dcard .r9-table tr[data-dspill],
#obtStage .r9-five .bc.r9-dcard .r9-table tr[data-dhid] { display: none; }

/* ------------------------------------------------------------------------------ 4. THE PHONE: three stacked cards */
@media (max-width: 899px) {
  /* every row is drawn - the phone scrolls, so nothing has to be cut */
  #obtStage .r9-five .bc.r9-dcard .r9-table tr[data-dspill],
  #obtStage .r9-five .bc.r9-dcard .r9-table tr[data-dhid] { display: table-row; }
  /* the phone floor is 13 px */
  #obtStage .r9-five .bc.r9-dcard .r9-table { font-size: 13px; }
  #obtStage .r9-five .bc.r9-dcard .r9-table th { padding: 5px 10px 5px 0; }
  #obtStage .r9-five .bc.r9-dcard .r9-table td { padding: 7px 10px 7px 0; }
  /* 44 px taps */
  #obtStage .r9-five .bc.r9-dcard .r9-dtabs button,
  #obtStage .r9-five .bc.r9-dcard .r9-dchips .obt-chip {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    font-size: 13px;
  }
  #obtStage .r9-five .bc.r9-dcard .r9-dchips .obt-chip { padding: 0 12px; }
  #obtStage .r9-five .bc.r9-dcard .r9-dtog { min-height: 44px; display: inline-flex; align-items: center; font-size: 13px; }
  #obtStage .r9-five .bc.r9-dcard .r9-dsort { min-height: 44px; }
  /* the rule bar stacks: the sentence, then the word and the door */
  #obtStage .r9-five .r9-diverow { display: block; margin: 0 0 8px; }
  #obtStage .r9-five .r9-diverow > .r9-rule { margin: 0 0 6px; }
  /* ⛔ ON THE PHONE THE BAR IS A CARD AGAIN, NOT A ROW. MEASURED (shots/w42a/after_nfl_390.png, first cut): the
     desktop's one-row flex squeezed the confidence word into a 40 px column and printed it as "HIG / H", and the
     bet's own sentence and the watch line were pushed out of the box altogether. 390 px has no room for four
     things side by side, so the same four things stack - which is what the phone did before the dive existed. */
  #obtStage .r9-five .bc.r9-v4.r9-diverule {
    display: flex !important;
    flex-direction: column !important;
    align-items: stretch !important;
    width: 100%;
    box-sizing: border-box;
    gap: 4px !important;
    padding: 8px 12px !important;
  }
  #obtStage .r9-five .bc.r9-v4.r9-diverule > .bb {
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 4px !important;
  }
  #obtStage .r9-five .bc.r9-v4.r9-diverule .r9-oneline { white-space: normal !important; }
  #obtStage .r9-five .bc.r9-v4.r9-diverule .r9-rule { font-size: 13px !important; margin: 0 !important; }
  #obtStage .r9-five .bc.r9-v4.r9-diverule .r9-hnum,
  #obtStage .r9-five .bc.r9-v4.r9-diverule .r9-hnum.r9-callword { font-size: 28px !important; }
}

/* ---------------------------------------------------- 5. THE BREAKDOWN SHEET: the same tables, every row, no cut - */
.r9m .r9m-dive .r9m-sec { margin: 0 0 14px; }
.r9m .r9m-dive .r9-table tr[data-dspill],
.r9m .r9m-dive .r9-table tr[data-dhid] { display: table-row; }
.r9m .r9m-dive .r9-dsort { pointer-events: none; }

/* [lane lead 2026-09-27, W42C's ask - LOOKED AT shots/w42c/after_nfl_line_1440.png: the Both-teams head's third column
   ('Falcons') was cut at the card's right edge inside the card's own sideways scroller] the label column gives up room first, so
   two value columns always fit a 250 px tile; a long label wraps instead of pushing a number off the edge. */
/* LOOKED AGAIN (w22a/w42_nfl_player_1440.png): on the six-column games table the same rule spelt Opp and ATL down a column - the
   label rule belongs to the two- and three-column WHY tables only (the card carries data-dive=3), and it breaks between words. */
#obtStage .r9-five .bc.r9-dcard[data-dive="3"] .r9-table td:first-child, #obtStage .r9-five .bc.r9-dcard[data-dive="3"] .r9-table th:first-child { max-width: 46%; white-space: normal; overflow-wrap: break-word; }
#obtStage .r9-five .bc.r9-dcard .r9-table td.n, #obtStage .r9-five .bc.r9-dcard .r9-table th.n { white-space: nowrap; }

/* ---- [W44 2026-09-27] THE CELLS, THE CHART AND THE STRIPS THE WAY THE BOOKS DRAW THEM (Outlier / bet365 / Sportsbet), in our
   language: green = landed, red = missed, gold only for the chosen thing; a crest per opponent; terminal density. ---- */
:root { --r9-hit: #22c55e; --r9-miss: #ef4444; }
#obtStage .r9-five .bc.r9-dcard .r9-table td, #obtStage .r9-five .bc.r9-leadcell .r9-table td { padding-top: 0; padding-bottom: 0; height: 32px; line-height: 32px; white-space: nowrap; font-variant-numeric: tabular-nums; }
#obtStage .r9-table .r9-ok, #obtStage .r9-table .r9-no { display: inline-flex; width: 18px; height: 18px; border-radius: 50%; align-items: center; justify-content: center; font-size: 11px; line-height: 18px; vertical-align: middle; }
#obtStage .r9-table .r9-ok { background: rgba(34,197,94,.22); color: var(--r9-hit); }
#obtStage .r9-table .r9-no { background: rgba(239,68,68,.22); color: var(--r9-miss); }
#obtStage .r9-table .r9-pos { color: var(--r9-hit); font-weight: 700; }
#obtStage .r9-table .r9-neg { color: var(--r9-miss); font-weight: 700; }
#obtStage .r9-table img.r9-oc { width: 18px; height: 18px; vertical-align: middle; margin-right: 6px; border-radius: 50%; background: rgba(0,0,0,.35); }
#obtStage .r9-seg { display: inline-flex; gap: 2px; margin-left: 8px; vertical-align: middle; }
#obtStage .r9-seg i { display: block; width: 4px; height: 10px; border-radius: 1.5px; background: var(--line, #2a2e36); }
#obtStage .r9-seg i.lit { background: var(--r9-hit); }
#obtStage .r9-seg i.dim { background: var(--r9-miss); }
#obtStage .r9-strip { display: inline-flex; gap: 2px; margin-right: 6px; vertical-align: middle; }
#obtStage .r9-chart .r9-ch span b { color: var(--ink, #fff); margin-right: 4px; }
#obtStage .r9-strip i { display: block; width: 8px; height: 8px; border-radius: 2px; background: var(--line, #2a2e36); }
#obtStage .r9-strip i.lit { background: var(--r9-hit); }
#obtStage .r9-strip i.dim { background: var(--r9-miss); }
#obtStage .r9-chart { padding: 2px 0 6px; margin-bottom: 4px; border-bottom: 1px solid var(--line, rgba(255,255,255,.08)); }
#obtStage .r9-chart .r9-ch { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px 8px; margin-bottom: 2px; }
#obtStage .r9-chart .r9-ch span { margin-left: auto; white-space: nowrap; }
#obtStage .r9-chart .r9-ch b { font-size: 13px; color: var(--ink, #fff); }
#obtStage .r9-chart .r9-ch span { font-size: 12px; color: var(--ink-dim, #9aa0ab); }
#obtStage .r9-bars { display: block; padding-right: 30px; }
#obtStage .r9-plot { position: relative; display: flex; align-items: flex-end; gap: 4px; height: 92px; padding: 16px 0 16px; box-sizing: border-box; }
#obtStage .r9-col { position: relative; flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; }
#obtStage .r9-col .r9-bar { display: block; width: 62%; max-width: 22px; min-height: 3px; border-radius: 3px 3px 2px 2px; background: var(--ink-dim, #5b6270); opacity: .85; }
#obtStage .r9-col.last .r9-bar { opacity: 1; }
#obtStage .r9-col .r9-bar.ok { background: var(--r9-hit); }
#obtStage .r9-col .r9-bar.no { background: var(--r9-miss); }
#obtStage .r9-col .r9-cv { font-size: 12px; line-height: 14px; color: var(--ink, #fff); font-weight: 700; margin-bottom: 2px; font-style: normal; }
#obtStage .r9-col .r9-cl { position: absolute; bottom: -16px; left: 0; right: 0; text-align: center; font-size: 12px; line-height: 14px; color: var(--ink-dim, #9aa0ab); font-style: normal; white-space: nowrap; overflow: hidden; }
#obtStage .r9-cln { position: absolute; left: 0; right: 0; height: 0; border-top: 1.5px dashed var(--gold, #f0b323); pointer-events: none; }
#obtStage .r9-cln u { position: absolute; right: -30px; top: -8px; font-size: 12px; line-height: 14px; color: var(--gold, #f0b323); font-weight: 700; text-decoration: none; }
@media (max-width: 899px) {
  #obtStage .r9-plot { height: 118px; }
  /* the 13 px phone floor, and a code never clipped: it may touch its neighbour, it is never cut (desk_law_test clip / small) */
  #obtStage .r9-col .r9-cl, #obtStage .r9-col .r9-cv { font-size: 13px; overflow: visible; }
}
/* the desktop never scrolls: under the chart the games table scrolls inside its card */
@media (min-width: 900px) {
  #obtStage .r9-five .bc .r9-chart + .r9-tw { max-height: 196px; overflow-y: auto; }
  /* a 250 px card holds ten 25 px columns: the opponent codes under the bars would touch, so on the desktop the bars carry their
     values only and the table under them names every opponent (the phone, wider per bar, shows both) */
  #obtStage .r9-five .r9-pane3 .r9-col .r9-cl { display: none; }
  #obtStage .r9-five .r9-pane3 .r9-plot { padding-bottom: 4px; height: 80px; }
}
#obtStage .r9-table td:first-child { padding-right: 8px !important; }


/* Part 6 CSS: THE BET PICKER ROW.  Owned by W9B (2026-09-16).  Pair: src/06_sheet.js.

   STATUS: complete on disk.

   EVERY RULE FOR THE BOTTOM SHEET IS GONE - .r9-sheet, .r9sh-scrim, .r9sh-box, .r9sh-head, .r9sh-body, .r9sh-sec,
   .r9sh-lab, .r9sh-rows, .r9sh-row, .r9sh-t/.r9sh-v/.r9sh-n/.r9sh-s, .r9sh-gh, .r9sh-back, .r9sh-find, .r9sh-door,
   .r9sh-close, .r9sh-foot and body.r9sh-lock. There is no modal on this page (owner, 2026-09-16 17:25).

   WHAT IS HERE. The picker is the game head's own three <select>s (.obt-msel / .obt-ssel / .obt-lsel inside
   .obt-ddw), and their INK look belongs to host_css/82_drawer.css section 8 (W9E). This file adds only the two
   things that css cannot own, because they are about where the row SITS:

     1. THE PHONE. The head used to be one 48px "Change >" button that opened the sheet. It is now a bet line the
        reader can read, and the same three dropdowns sit in `.obt-pickrow` immediately BELOW the head - stacked
        full width so a thumb can hit any of them, each row at least 44px, each a plain ink line with a hairline
        under it and the label in faint ink at the left, exactly like the desktop strip.
        WHY BELOW THE HEAD AND NOT IN IT: the head is sticky and has a 112px ceiling (phone_metrics H1), and the
        chrome budget is 258px unscrolled / 236px scrolled (B5) with 560px of reading area owed to the reader (G1).
        Three 44px controls inside it measured 165px (MLB), 172px (AFL) and 241px (NFL) and broke all of them, and
        a picker pinned over a fifth of the screen for the whole read is not what a bookmaker app does either: the
        market selector sits at the top of the scrolling view. So the row is a sibling of the head (host block
        87_pickerui.py hunk 6) - first thing the reader sees, and it scrolls away with the read.
     2. A LABEL FOR EACH DROPDOWN, on both widths. Without it the row is three unexplained boxes; with it, it reads
        "Market | Selection | Line" the way a bookmaker's slip does. `.obt-ddw > i` is the element W9E's css already
        expects, so the two files agree on one DOM.

   Design law: one typeface var(--ui), inks --ink/--ink-dim/--ink-faint, hairlines var(--line). No pill, no chip, no
   glow, no gradient, no mono caps, no rounded corners, nothing that looks generated.
   A11y: native <select>s, so the phone shows the OS wheel; every control is at least 44px tall on a phone and keeps
   a visible focus ring from 82_drawer.css. */

/* ------------------------------------------------------------------ the label on every dropdown, both widths ----
   The minted host css already carries a `.obt-ddw>i` rule from an earlier round - var(--mono), .52rem, .13em of
   letter-spacing, UPPERCASE - which is the mono-caps the design law bans and which nothing emitted until this row
   did. host_css/82_drawer.css (W9E) fixes it for good at the next host-css mint; this rule makes the label right
   NOW, whichever of the two stylesheets loads last, by carrying one more class. */
.obt-build .obt-ddw > i {
  font-style: normal;
  font-family: var(--ui);
  font-size: .64rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-faint);
  line-height: 1.1;
  white-space: nowrap;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ------------------------------------------------------------------ the phone -------------------------------- */
@media (max-width: 899px) {
  /* the bet the reader is on, in one line, above the controls that change it. Not a button any more: there is
     nothing to open, so nothing pretends to be tappable. */
  .obt-stage .phh-line {
    display: block;
    width: 100%;
    min-height: 34px;
    padding: 4px 0 2px;
    margin: 0;
    font-family: var(--ui);
    font-size: .86rem;
    font-weight: 400;
    color: var(--ink-faint);
    line-height: 1.28;
  }
  .obt-stage .phh-line b { font-weight: 600; color: var(--ink); }
  .obt-stage .phh-line i { font-style: normal; color: var(--ink-faint); white-space: nowrap; }

  /* THE ROW ITSELF, directly under the head. It is ordinary stage content, so it carries the stage's own side
     gutter and nothing else - no card, no panel, no border box around it. */
  .obt-stage .obt-pickrow {
    display: block;
    padding: 2px 14px 8px;
    margin: 0;
    background: none;
    border: 0;
  }

  /* the three dropdowns, stacked, full width, thumb sized */
  .obt-stage .obt-pickrow .obt-build {
    display: block;
    padding: 0 0 4px;
    margin: 0;
    border: 0;
    background: none;
  }
  .obt-stage .obt-pickrow .obt-build .strip {
    display: flex;
    flex-direction: column;
    gap: 0;
    min-width: 0;
  }
  /* one line per control: the label in a fixed column on the left, the value filling the rest, a hairline under
     the whole row and the chevron at the right - a bet slip's own shape, and nothing overlaps at any text size. */
  /* flex-direction MUST be declared here. The base `.obt-ddw{display:inline-flex;flex-direction:column}` (w29.css)
     is put back into a row by `.obt-wsid.v39 .obt-ddw{flex-direction:row}` - a rule that only reaches the controls
     while they are INSIDE the head. Out in .obt-pickrow they fell back to a column, and the label sat centred above
     a full-width select with a chevron floating off to the right (capture pickrow_mlb_390_1open.png, before). */
  .obt-stage .obt-pickrow .obt-ddw {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 10px;
    width: 100%;
    min-width: 0;
    position: relative;
    padding: 0;
    border-bottom: 1px solid var(--line);
  }
  .obt-stage .obt-pickrow .obt-ddw > i {
    flex: 0 0 74px;
    max-width: 74px;
    font-size: .74rem;
    color: var(--ink-faint);
    pointer-events: none;
  }
  .obt-stage .obt-pickrow .obt-ddw select,
  .obt-stage .obt-pickrow .obt-ddw .obt-lsel {
    -webkit-appearance: none;
    appearance: none;
    flex: 1 1 auto;
    display: block;
    width: auto;
    min-width: 0;
    min-height: 44px;
    max-width: none;
    padding: 6px 22px 6px 0;
    font-family: var(--ui);
    font-size: .88rem;
    font-weight: 500;
    text-align: left;
    background: none;
    border: 0;
    border-radius: 0;
    color: var(--ink);
    text-overflow: ellipsis;
  }
  /* the chevron. The phone rule above takes the select's own background off (it is a cyan SVG baked into the minted
     css), so the row draws its own in ink. This is the SAME ::after that host_css/82_drawer.css section 8 uses, so
     when that file is minted the two merge into one chevron - there is never a second one. */
  .obt-stage .obt-pickrow .obt-ddw::after {
    content: "";
    position: absolute;
    right: 3px;
    top: 50%;
    margin-top: -5px;
    width: 6px;
    height: 6px;
    border-right: 1.5px solid var(--ink-faint);
    border-bottom: 1.5px solid var(--ink-faint);
    transform: rotate(45deg);
    pointer-events: none;
  }
  .obt-stage .obt-pickrow .obt-build .obt-one {
    display: block;
    width: 100%;
    min-height: 44px;
    padding: 12px 0;
    font-family: var(--ui);
    font-size: .88rem;
    color: var(--ink);
    border-bottom: 1px solid var(--line);
  }
}

/* ------------------------------------------------------------------ the desktop strip -------------------------
   THE THREE MUST READ AS ONE ROW. Measured on the bench at 1600 (tools/picker_layout_probe.py, MLB, a player market
   in focus): `.obt-build.v38` AND `.strip` are both `display: contents`, so the three `.obt-ddw` labels are direct
   flex items of `.hr1` - the same wrapping row that carries the crests and the score. With a player market in focus
   they measure 290 + 189 + 212 px, the score takes the left of a 1075px row, and the LINE control alone wrapped to
   a second line at the far left (x=219, y=110) while Market and Player stayed at the right (x=805 / x=1105). Three
   dropdowns split across two lines and two alignments is not "as simple as dropdowns".
   One property fixes it: the strip stops being `contents`, so it is ONE flex item that wraps as a whole and the
   three always sit together, in order, left aligned - the shape of a bookmaker's slip. Nothing about their ink is
   set here; that is host_css/82_drawer.css section 8 (W9E). */
@media (min-width: 900px) {
  /* the selector has to out-weigh the host's own `.obt-wsid.v39 .hr1 .obt-build.v38 .strip{display:contents}`
     (w29.css:1677, six classes), so it carries all six and one more. */
  .obt-stage .obt-wsid.v39 .hr1 .obt-build.v38 .strip {
    display: flex;
    flex-wrap: nowrap;
    align-items: flex-end;
    gap: 14px;
    min-width: 0;
    max-width: 100%;
  }
  .obt-stage .obt-wsid.v39 .hr1 .obt-build.v38 .strip > .obt-ddw { min-width: 0; }
  .obt-build.v38 .obt-ddw select,
  .obt-build.v38 .obt-ddw .obt-lsel { min-height: 34px; }
}

/* ======================================================================================================================
   07_you.css — [WP-M5 · 2026-09-14] THE YOU SCREEN ON A PHONE  (MOBILE_OVERHAUL_SPEC.md §3.4, §3.6, §6; defect D6)

   The right-hand column and the phone's whole You screen are the same DOM (src/03_pbi.js P.column, wrapped by
   src/04_engine.js E.stage's 'you' branch in .r9-pbi-mobile). On a 1600px desktop it is a 280-320px rail beside the
   console; on a 390px phone it IS the screen — and until this file it was a rail's composition dropped on a phone:
   20px tab words a thumb misses, a body that stopped ~250px above the bar with the RG helpline floating in the hole,
   a dimension row that wrapped into three lines of 12px words, and, for a subscriber, a composer that scrolled away
   under the on-screen keyboard the moment they tapped it.

   ⛔ EVERY rule in this file sits inside @media (max-width:899px) — the one phone token (spec D13). The desktop
   column must be byte-identical after this file: proved with a 1600px capture pair (md5), not asserted.
   ⛔ Every selector is scoped to #obtStage (the phone screen) or .r9o-ph (the class 03_pbi.js only adds below 900px),
   so the desktop column in #obtTiles is out of reach even if a rule ever escaped the query.

   Design law: one typeface var(--ui), two inks var(--ink) / var(--ink-faint), hairlines var(--line). No pills, no
   gold, no gradients, no mono caps, no cards. The reader's own mark stays where it is — the tab row's .me — and no
   organ on this screen paints a face.
   ====================================================================================================================== */

@media (max-width:899px){

  /* --- 1. THE COLUMN IS THE SCREEN: one flex column, and the helpline sits on its bottom edge (D6) -----------------
     The You stage is `.obt-bento.r9-grid.r9-you > .obt-tiles.r9-pbi-mobile > .r9o`. The grid rule up in scenes.css
     pins the box to display:grid, so the column has to answer at the same weight. Its height is the stage MINUS the
     phone head that shares the stage with it (--bb-headh when the head block publishes it, otherwise the head's own
     spec budget of 112px) — a plain 100% would push the helpline a head's height below the fold and make the reader
     scroll a short screen to find it, which is worse than the hole it fixes. Same formula as .r9-five (WP-M4), on
     purpose: the two phone screens must end on the same line. */
  #obtStage .obt-bento.r9-grid.r9-you{display:flex!important;flex-direction:column;gap:0;box-sizing:border-box;
    min-height:calc(100% - var(--bb-headh,112px))}
  /* ⛔ overflow MATTERS here, and it cost an hour: .obt-tiles carries overflow:auto from the host sheet (it is the
     desktop rail's own scroller), so on the phone it was a scroll container that never scrolled - and a scroll
     container is a SCROLLPORT, which is what position:sticky measures against. The composer was therefore "sticky"
     against a box the size of its own content and never moved: measured at bottom 1812 in an 844px window. With the
     overflow gone the nearest scrollport is #obtStage, which is the box the reader actually scrolls. */
  #obtStage .r9-you>.obt-tiles.r9-pbi-mobile{flex:1 1 auto;min-height:0;overflow:visible}
  /* no percentage heights anywhere in the chain: each box is a flex item that grows, so the column measures right
     whether the stage's own height is definite or not. */
  #obtStage .r9-you .r9o{flex:1 1 auto;height:auto;min-height:0;display:flex;flex-direction:column}
  #obtStage .r9-you .r9o-body{flex:1 1 auto;min-height:0}
  #obtStage .r9-you .r9o-foot{flex:none}

  /* --- 2. THE THREE TABS ARE THINGS A THUMB CAN HIT ------------------------------------------------------------------
     Chat / You / Tonight were 13px words in a 20px line: a 30px-wide, 18px-tall target against the 44px floor
     (WCAG 2.5.5 / Apple HIG 44pt / Material 48dp). They keep their look — plain words, active one brighter, no pills,
     no underline bar — and gain the box around them. The row's own padding drops from 14/10 to 4/2 so the taller
     buttons cost the read 8px, not 30. min-width is what makes "You" (30px of word) a 44px target; the extra reaches
     right, into the gap, never into the next tab (gap 22 > the 14px of overhang). */
  #obtStage .r9o-ph .r9o-tabs{padding:4px 16px 2px;gap:22px;align-items:stretch}
  #obtStage .r9o-ph .r9o-tabs button{min-height:44px;min-width:44px;display:inline-flex;align-items:center;
    font-size:14px;line-height:1.2}
  /* the reader's own name, stake and mark stay on the right of the row, vertically centred against the taller tabs.
     The mark opens the 30-mark picker, so it is a control and it takes the same 44px floor - but as a 44px BOX around
     a 26px mark, not a 44px mark: growing the circle itself would make the reader's own face bigger than anything the
     read prints, and the design law keeps faces out of the organs entirely. */
  #obtStage .r9o-ph .r9o-tabs .me{align-self:center;font-size:12px}
  /* [W29B 2026-09-22] THE GUEST'S HALF OF THAT SLOT. Owner, 22 Sep: "wheres the login if you have an account?"
     MEASURED on the bench before this rule existed: at 390 and at 320, on the board AND inside a game, every
     "log in" in the whole document read inview=false - this row carried "You . $10" for a guest and no control at
     all. 03_pbi.js P.column now prints a real Sign in button here (.me-in), and it takes the same 44px floor the
     three tabs beside it take, centred against them exactly as the reader's own mark is. Nothing about the
     signed-in row changes: that branch is byte-for-byte what it was, and this selector cannot reach it. */
  #obtStage .r9o-ph .r9o-tabs .me-in{align-self:center}
  #obtStage .r9o-ph .r9o-tabs .me-in .r9-wayb-head{min-height:44px;padding:0 12px;font-size:13px}
  #obtStage .r9o-ph .r9o-tabs .av{width:44px;height:44px;background:none;border-radius:0;padding:0}
  #obtStage .r9o-ph .r9o-tabs .av img{width:26px;height:26px;border-radius:50%}
  #obtStage .r9o-ph .r9o-tabs .av i{font-size:10px}

  /* --- 3. THE DIMENSION ROW SCROLLS SIDEWAYS INSTEAD OF WRAPPING (spec WP-M5) ----------------------------------------
     Market · Bet type · Price · Team · Player · Time · League is 300px of words in a 342px body: it wrapped to two or
     three 12px lines that read as a paragraph, not as a control, and every one of them was an 18px tap target. One
     line now, carried sideways inside its own scroller, full-bleed to the panel edges so a half-visible word tells the
     reader there is more. It is marked data-bbscroll (03_pbi.js) because the phone gate fails any sideways scroller
     that is not a declared house scroller.
     ⛔ [WP-P7 2026-09-14] THE LINE BELOW USED TO CLOSE THIS COMMENT EARLY. A stray comment terminator sat at the end
     of the sentence above, which left the next three lines of prose loose in the sheet; CSS read all of it as the
     start of a selector and swallowed the `.dims` rule that follows it, so the sideways dimension row was DEAD on the
     phone from the moment WP-M5 shipped it - the words wrapped to two lines exactly as before. One comment
     terminator, one whole feature. ⛔ never write a comment terminator inside a CSS comment, not even in quotes:
     that is the same bug a second time, and it is how this one was re-introduced once while being fixed.
     ...and the 44px floor is bought with padding, not with a min-width: "Time" is 29px of word, and a 44px min-width
     would have left it 15px of dead target reaching into the gap after it while "Bet type" had none - the spacing
     between the words would have read as random. 12px each side gives every word the same box and the same gutter. */
  #obtStage .r9o-ph .r9o-body .dims{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;gap:0;
    margin:0 -16px 6px;padding:0 4px;-webkit-overflow-scrolling:touch;scrollbar-width:none}
  #obtStage .r9o-ph .r9o-body .dims::-webkit-scrollbar{display:none}
  #obtStage .r9o-ph .r9o-body .dims button{flex:0 0 auto;min-height:44px;padding:0 12px;display:inline-flex;
    align-items:center;white-space:nowrap;font-size:13px}

  /* --- 4. EVERY OTHER WORD-BUTTON IN THE COLUMN GETS THE SAME FLOOR -------------------------------------------------- */
  /* the door: "Log in" is 36px of word, so the same padding trick buys it a 60px box and both doors an even gutter */
  #obtStage .r9o-ph .r9o-body .links{gap:0;flex-wrap:wrap;margin:8px -12px 0}
  #obtStage .r9o-ph .r9o-body .links button{padding:0 12px}
  #obtStage .r9o-ph .r9o-body .links button,
  #obtStage .r9o-ph .r9o-body .qr button,
  #obtStage .r9o-ph .r9o-body .vote button,
  #obtStage .r9o-ph .r9o-body .setl button,
  #obtStage .r9o-ph .r9o-body .tog{min-height:44px;display:inline-flex;align-items:center;font-size:13px}
  #obtStage .r9o-ph .r9o-body .qr button{width:100%;justify-content:flex-start;border-bottom:1px solid var(--line)}
  #obtStage .r9o-ph .r9o-body .qr button:last-child{border-bottom:0}
  #obtStage .r9o-ph .r9o-body .avs{grid-template-columns:repeat(5,1fr);gap:10px}

  /* --- 5. A LOCKED READER'S DEAD SPACE BECOMES THE ONE HONEST THING THEY CAN ACT ON (D6) -------------------------------
     A guest Chat tab was the read, one grey sentence and two links — about 300px of a 586px screen, and the rest was
     empty panel with the helpline floating in the middle of it. Three plain rows now say what a subscription is, in
     the reader's own words, above the same door. No card, no border box, one hairline to separate it from the read. */
  #obtStage .r9o-ph .r9o-gets{margin:16px 0 0;padding-top:12px;border-top:1px solid var(--line)}
  #obtStage .r9o-ph .r9o-gets p{margin:0 0 10px;font-size:13px;line-height:1.5;color:var(--ink-faint)}
  #obtStage .r9o-ph .r9o-gets p.h{margin:0 0 8px;font-size:13px;color:var(--ink)}

  /* --- 6. THE PAID COMPOSER RIDES ABOVE THE BAR, AND ABOVE THE KEYBOARD (spec §6) ---------------------------------------
     #obtStage is the scroller on a phone, so position:sticky is measured against it - and, the trap that cost the most
     time here, against its CONTENT edge, not the window. The stage already carries a padding-bottom the width of the
     bottom bar (the bar block publishes it), so `bottom:0` lands the composer exactly on the line where the read ends,
     just above the bar, with no constant in this file that could drift when the bar changes shape.
     THE KEYBOARD. iOS does not shrink the layout viewport when the keyboard opens, so that same line ends up behind the
     keys. 03_pbi.js measures the overlap with visualViewport, works out the lift against the real stage, and writes it
     as --bb-kbfit with data-bb-kb="1" on <html>. Nothing here fires when there is no keyboard.
     margin-top:auto keeps the box on the bottom edge of a SHORT thread too, so it never floats mid-panel.
     ⛔ the composer must NOT be position:fixed: the phone gate fails any fixed element whose rect lands on the read. */
  #obtStage .r9o-ph .r9o-in{position:sticky;bottom:0;z-index:4;margin-top:auto;
    background:var(--panel);border-top:1px solid var(--line);
    padding:10px 16px calc(10px + env(safe-area-inset-bottom))}
  html[data-bb-kb="1"] #obtStage .r9o-ph .r9o-in{bottom:var(--bb-kbfit,0px)}
  /* the box itself: a 44px row, so the input and the send arrow are both real targets */
  /* the box's border is a white-alpha rule in the base sheet (invisible on the light theme's white panel, where the
     composer is now a bar the reader has to find). One hairline token, both themes. */
  #obtStage .r9o-ph .r9o-in .box{min-height:44px;padding:4px 4px 4px 14px;border-color:var(--line)}
  #obtStage .r9o-ph .r9o-in .box input{font-size:16px}   /* under 16px iOS zooms the whole page on focus */
  /* the send arrow: a 44px target around a 32px mark. Growing the filled disc to 44px would put the biggest, boldest
     shape on the whole screen next to an empty text box; the disc is drawn by the pseudo-element and the tap area is
     the button around it. */
  #obtStage .r9o-ph .r9o-in .box button{width:44px;height:44px;background:none;color:var(--panel);position:relative}
  #obtStage .r9o-ph .r9o-in .box button::before{content:"";position:absolute;inset:6px;border-radius:50%;background:var(--ink)}
  #obtStage .r9o-ph .r9o-in .box button svg{position:relative}
  #obtStage .r9o-ph .r9o-in .left{font-size:11.5px}
  /* --- [WP-C4 2026-09-14] the protocol-2 chat on a phone (src/03_pbi.js; spec 6.2/6.5/6.7) ---------------------------
     Two new controls reach the phone with the framed chat: "Start again" beside the budget footer and "Copy" on every
     answer. Both are text, both are in the column's 44px tap list (phone_metrics Y5), and the footer row has to be
     allowed to wrap - at 320px "About 12 questions left this month." and "Start again" do not share one line. */
  #obtStage .r9o-ph .r9o-in .row{flex-wrap:wrap;row-gap:0}
  #obtStage .r9o-ph .r9o-in .again{font-size:12px;min-height:44px;display:inline-flex;align-items:center}
  #obtStage .r9o-ph .r9o-in .rest{font-size:12px}
  #obtStage .r9o-ph .r9o-body .st{font-size:13px}
  /* the last message must be reachable above the sticky box when the thread is long */
  #obtStage .r9o-ph .r9o-body{scroll-padding-bottom:96px}

  /* --- 7. THE HELPLINE, LAST LINE ON THE SCREEN ------------------------------------------------------------------------
     One typeface with everything else on the phone (the desktop half of that rule belongs to the lane lead), and a
     hairline above it so it reads as the foot of the screen rather than as another sentence in the read. */
  /* [W25A 2026-09-20] 13px, not 12: the vet's L7 read ".r9o-foot 12.0px" on the You column of THIRTEEN leagues,
     for a subscriber and a guest. The helpline is the one line on the screen a reader in trouble has to be able to
     read, so it is the last line that may sit under the floor. */
  #obtStage .r9o-ph .r9o-foot{font-family:var(--ui);letter-spacing:0;font-size:13px;
    padding:10px 16px calc(12px + env(safe-area-inset-bottom))}

  /* --- 8. THE READING ITSELF: a rail's type sizes are too small held at arm's length ------------------------------------
     13px/12.5px in a 280px rail is 15px-equivalent at reading distance; on a phone it is just small. Nothing here goes
     under the 10px floor the gate enforces, and the numbers stay tabular so the record's columns line up. */
  #obtStage .r9o-ph{font-size:14px}
  #obtStage .r9o-ph .r9o-body p{margin:0 0 11px}
  #obtStage .r9o-ph .r9o-body .h{font-size:12px}
  /* [W25A 2026-09-20] the 13px floor. Measured by the vet on 13 leagues (".src 12.0px") and by desk_law_test.
     The source line under an answer and the dim line under a count are readings, not fine print. */
  #obtStage .r9o-ph .r9o-body .src,#obtStage .r9o-ph .r9o-body .dim{font-size:13px}
  /* [WP-P7] the You tab's own three marks on a phone. The headline is the one line that must read from a pocket at
     arm's length, so it takes the biggest step; the break-even under each count stays a clear step back but never
     goes near the 10px floor the gate enforces. */
  #obtStage .r9o-ph .r9o-body .lead{font-size:18px;line-height:1.3;margin:0 0 12px}
  #obtStage .r9o-ph .r9o-body .tbl .n small{font-size:12px}
  #obtStage .r9o-ph .r9o-body .tbl>span{font-size:13.5px;padding:8px 0}
  #obtStage .r9o-ph .r9o-body .rows div{font-size:13.5px;padding:8px 0}
  #obtStage .r9o-ph .r9o-body .rows small{font-size:12px}
  /* "Bet Better" broke over two lines at 390px: the name had no shrink guard and the bet name beside it took the room.
     The name is one line; the bet name is the only thing allowed to give way, and it already ellipsises. */
  #obtStage .r9o-ph .msg .who{font-size:13px}
  #obtStage .r9o-ph .msg .who>span{flex:0 0 auto;white-space:nowrap}
  #obtStage .r9o-ph .msg .who small{font-size:12px;flex:0 1 auto}
  #obtStage .r9o-ph .r9o-body .setl input,#obtStage .r9o-ph .r9o-body .setl button{font-size:13px}
  #obtStage .r9o-ph .r9o-body .setl input{min-height:44px}

  /* --- 9. [W28A 2026-09-21] THE ASK SHEET IS A COLUMN, NOT A PAGE ----------------------------------------------------
     THE SHEET IS THE PHONE'S CHAT. Every rule above is scoped to #obtStage, and the sheet is a BODY-LEVEL modal
     (E.askSheet -> E.openModal appends to document.body), so none of them has ever reached it. MEASURED on the bench,
     ufc 390x844, subscriber, with the sheet open:
        .r9m-body     overflow auto   70-844
        .r9-askwrap   overflow auto   70-844
        .r9o-body     overflow auto   115-708   min-height 160px
        .r9o-in       position STATIC  708-807
     THREE nested scrollports one inside the other, and a composer with no position at all.
       * THREE SCROLLERS is not a column. A drag that starts on the thread can move .r9-askwrap or .r9m-body instead,
         which carries the whole composer up out of the sheet and slides the question list out from under it - the
         "a suggestion half hidden behind the box, another below it" the owner is looking at. A column has ONE
         scroller and it is the thread.
       * min-height:160px on the body means the thread refuses to shrink. On a short phone, and on ANY phone once the
         keyboard has taken half the window, that 160px pushes the composer past the bottom edge of the sheet.
       * position:static means the sticky rule in section 6 and its --bb-kbfit companion could not apply even if the
         selector had reached: the box cannot lift over the keys.
     WHAT IT IS NOW: one flex column - tabs, the thread (the one scroller), the message box on its own opaque
     var(--panel) ground with a hairline above it, then the helpline. The box is a flex sibling of the thread rather
     than a sticky child of it, so it is pinned by the layout itself and there is no scrollport for it to drift
     against. The last message stays reachable (scroll-padding-bottom).
     THE KEYBOARD. 03_pbi.js P.kb now writes --bb-kbraw, the raw overlap, because this sheet is fixed to the WINDOW's
     bottom edge and the stage's padding is no part of its geometry. Giving the sheet back that many pixels lifts the
     box AND the helpline clear of the keys in one move, with nothing inside the column having to know.
     ⛔ NO !important ANYWHERE HERE, AND THE SPECIFICITY IS MEASURED, NOT GUESSED. The first draft of this block was
     written at (0,2,0) - ".r9-askmodal .r9o-in" - and LOST. tools/_w28a_rules.py asked the browser which rule
     actually wins, and printed the answers:
        position  on .r9o-in    winner ".r9-modal.r9-askmodal .r9o-in {position:static}"   (0,3,0), in two sheets
        overflow  on .r9m-body  winner ".r9-modal .box .r9m-body {overflow:auto}"          (0,3,0)
     Both beat a two-class selector on SPECIFICITY, so no amount of cascade order would have helped and !important
     would only have hidden that. Every selector below therefore carries four classes and wins outright. */
  .r9-modal.r9-askmodal>.box{overflow:hidden}
  .r9-modal.r9-askmodal .box .r9m-body,
  .r9-modal.r9-askmodal .box .r9-askwrap{overflow:hidden;min-height:0}
  .r9-modal.r9-askmodal .box .r9-askwrap{flex:1 1 auto;display:flex;flex-direction:column}
  .r9-modal.r9-askmodal .box .r9o{min-height:0}
  .r9-modal.r9-askmodal .box .r9o-tabs{flex:0 0 auto}
  .r9-modal.r9-askmodal .box .r9o-body{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;
    -webkit-overflow-scrolling:touch;scroll-padding-bottom:96px}
  .r9-modal.r9-askmodal .box .r9o-in{flex:0 0 auto;position:relative;z-index:4;margin-top:0;
    background:var(--panel);border-top:1px solid var(--line);
    padding:10px 16px calc(10px + env(safe-area-inset-bottom))}
  .r9-modal.r9-askmodal .box .r9o-in .box{min-height:48px;padding:5px 5px 5px 14px}
  .r9-modal.r9-askmodal .box .r9o-in textarea{font-size:16px}   /* under 16px iOS zooms the page on focus */
  .r9-modal.r9-askmodal .box .r9o-foot{flex:0 0 auto;background:var(--panel);font-family:var(--ui);
    letter-spacing:0;font-size:13px}
  /* ⛔ THE LIFT GOES ON THE SCRIM, NOT ON THE BOX, AND THE FIRST TRY PROVED WHY. A max-height on the box looked
     right and did nothing useful: .r9-modal is a fixed grid with align-items:end, so the box is anchored to the
     BOTTOM - shrinking it moved its TOP down (measured: box 0-844 became 336-844) and left the composer at 711-804,
     still under a keyboard covering 508-844. Padding the scrim moves the anchor itself, so the whole column - the
     message box AND the helpline under it - comes up with it. The 8 px is the same breathing room P.kb gives the
     stage: a box flush against the top of the keys reads as trapped. */
  html[data-bb-kb="1"] .r9-modal.r9-askmodal{padding-bottom:calc(var(--bb-kbraw,0px) + 8px)}
}

/* =====================================================================================================================
   [WP-M1 2026-09-15] THE CTA SYSTEM — every door and every upsell in the /odds terminal, in one sheet.
   =====================================================================================================================
   OWNER RULING TODAY (the one exception to the terminal's design law): "make sure the ctas and upselling is done to
   elite levels... can use this cta styling from default.aspx... light and dark theme obviously". So THE SITE'S OWN CTA
   LANGUAGE is allowed here and nowhere else: the filled accent pill (var(--accent-grad), white 700, the accent glow).
   Everything that is NOT a call to action keeps the terminal's law — one typeface var(--ui), two inks var(--ink) /
   var(--ink-faint), hairlines var(--line), no gradients, no gauges, no avatars.

   TWO WEIGHTS, AND THE RULE FOR PICKING ONE (spec: "the pill where it is THE action, a quieter underline where a pill
   would shout over reading"):
       .r9cta         THE PILL. Used where the door IS the thing on screen: the locked column (Chat / You / Tonight),
                      the live strip while a game a free reader can see is running, the chat's out-of-questions row.
       .r9cta-quiet   THE UNDERLINE. Used inside a reading path where a filled pill would out-shout the sentence the
                      reader came for: the call stop's back-note, the second (account) action under a pill.

   THE FLAGSHIP COMPOSITION (owner): LABEL left · a thin translucent divider · PRICE right. The price half is ALWAYS
   `<span class="r9cta-pr bb-price-copy">` carrying the canonical `$29 a week` token, so the master modal's localiser
   (assets/bb-master-modal.*.js — it rewrites $29/$89/$399 inside .bb-price-copy) and 03_pbi.js's own P.priceWeek()
   both land the reader's real currency. ⛔ PRICE-COPY LAW: never hard-code a price into a new CTA.

   WHY THE TOKENS CARRY FALLBACKS. --accent-grad / --accent-glow live in assets/bb-core-rest.*.css, which Site.Master
   loads ASYNC (media="print" onload). For the first frames of a cold load they do not exist, and a CTA with no
   background would be white-on-white. The fallbacks below are the same literals bb-core-rest ships, per theme, so the
   pill is correct before, during and after that stylesheet lands.

   THEMES. The terminal switches on html[data-theme="light"] (scenes.css, host_css/10_topbar.css); the site also honours
   the OS through prefers-color-scheme when no attribute is set. Both are covered.
   ===================================================================================================================== */

/* ---- 1. THE TOKENS ---------------------------------------------------------------------------------------------- */
:root {
  --r9cta-grad: var(--accent-grad, linear-gradient(180deg, #5AA0FF, #2F6FE6));
  --r9cta-glow: var(--accent-glow, rgba(70, 140, 255, .55));
  --r9cta-on: #fff;
  --r9cta-div: rgba(255, 255, 255, .34);
  --r9cta-sheen: rgba(255, 255, 255, .38);
}
html[data-theme="light"] {
  --r9cta-grad: var(--accent-grad, linear-gradient(180deg, #3B82F6, #2563EB));
  --r9cta-glow: var(--accent-glow, rgba(47, 111, 224, .28));
}
@media (prefers-color-scheme: light) {
  html:not([data-theme="dark"]):not([data-theme="light"]) {
    --r9cta-grad: var(--accent-grad, linear-gradient(180deg, #3B82F6, #2563EB));
    --r9cta-glow: var(--accent-glow, rgba(47, 111, 224, .28));
  }
}

/* ---- 2. THE BLOCK: one reason, one action, one small line ------------------------------------------------------- */
/* .r9cta-wrap sits on the same element that still carries `links`, so the phone gate's tap-target scanner
   (tools/phone_metrics.py: ".r9o-body .links button") keeps measuring these buttons. It only has to undo the old
   `.links` flex row. */
.r9o-body .links.r9cta-wrap,
.r9cta-wrap { display: block; margin: 14px 0 0; }
.r9cta-wrap + .r9cta-wrap { margin-top: 10px; }

/* THE REASON. One sentence, in the reading ink, directly above the action - never a list, never a wall. */
.r9cta-why { margin: 0 0 10px; font-family: var(--ui); font-size: 14px; line-height: 1.5; color: var(--ink); }
.r9cta-why b { font-weight: 600; color: var(--ink); }

/* THE SMALL LINE under the action: the reassurance, in the faint ink. Never a price, never a countdown. */
.r9cta-note { margin: 8px 0 0; font-family: var(--ui); font-size: 12.5px; line-height: 1.45; color: var(--ink-faint); }

/* ---- 3. THE PILL ------------------------------------------------------------------------------------------------ */
.r9cta,
.r9o-body .links button.r9cta,
.r9-livestrip .r9lv-door button {
  display: inline-flex; align-items: center; justify-content: center; gap: 12px;
  box-sizing: border-box; width: 100%; max-width: 420px; min-height: 46px; padding: 9px 18px;
  font-family: var(--ui); font-size: 14px; font-weight: 700; line-height: 1.25; letter-spacing: 0;
  text-align: left; text-decoration: none; text-transform: none;
  color: var(--r9cta-on); background: var(--r9cta-grad); border: 0; border-radius: 99px;
  box-shadow: inset 0 1px 0 var(--r9cta-sheen), 0 10px 28px -6px var(--r9cta-glow);
  cursor: pointer; transition: transform .16s ease, box-shadow .16s ease;
}
/* the inline card CTA (owner: "10-11px for inline card CTAs") - used where the CTA sits inside a written block
   rather than closing a screen: the chat answer's row and the live strip's door sentence. */
.r9cta.r9cta-card,
.r9-livestrip .r9lv-door button { border-radius: 11px; }

.r9cta:hover,
.r9-livestrip .r9lv-door button:hover { transform: translateY(-1px); box-shadow: inset 0 1px 0 var(--r9cta-sheen), 0 14px 34px -8px var(--r9cta-glow); color: var(--r9cta-on); }
.r9cta:active,
.r9-livestrip .r9lv-door button:active { transform: translateY(0); box-shadow: inset 0 1px 0 var(--r9cta-sheen), 0 6px 18px -6px var(--r9cta-glow); }
.r9cta:focus-visible,
.r9-livestrip .r9lv-door button:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) {
  .r9cta, .r9-livestrip .r9lv-door button { transition: none; }
  .r9cta:hover, .r9-livestrip .r9lv-door button:hover { transform: none; }
}

/* THE SPLIT: label left, a hairline of white, price right. `justify-content:space-between` and the divider are the
   whole composition - at 320px the two halves still sit on one line because the label is allowed to shrink. */
.r9cta.r9cta-split { justify-content: space-between; gap: 0; padding-left: 16px; padding-right: 14px; }
.r9cta .r9cta-lab { min-width: 0; flex: 0 1 auto; text-wrap: balance; }
.r9cta .r9cta-pr {
  flex: 0 0 auto; margin-left: 12px; padding-left: 12px; border-left: 1px solid var(--r9cta-div);
  font-weight: 600; font-size: .88em; white-space: nowrap; opacity: .96;
}
/* THE DESKTOP RAIL is a ~235px column: at 14px the label broke to three lines against the price half, which reads as
   a mistake rather than a composition. Half a point smaller buys the two-line balance the shots were signed off on. */
#obtTiles .r9cta { font-size: 13.5px; }
/* the arrow on a single-label pill. A CTA with nothing on its right edge reads as a label, not as a door. */
.r9cta.r9cta-go .r9cta-lab::after { content: ' \2192'; font-weight: 600; opacity: .8; }

/* ---- 4. THE QUIET ONE ------------------------------------------------------------------------------------------- */
/* Reading ink, underlined, a real 44px target, no fill: it must read as a sentence that happens to be tappable. */
.r9cta-quiet,
.r9o-body .links button.r9cta-quiet,
.r9-backnote button.r9cta-quiet {
  display: inline-flex; align-items: center; min-height: 44px; margin: 6px 0 0; padding: 0;
  background: none; border: 0; font: inherit; font-family: var(--ui); font-size: 13.5px; font-weight: 500;
  line-height: 1.5; color: var(--ink); text-align: left; text-decoration: underline;
  text-underline-offset: 3px; text-decoration-thickness: 1px; cursor: pointer;
}
.r9cta-quiet:hover { color: var(--ink); text-decoration-thickness: 2px; }
.r9cta-quiet:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 4px; }
/* inside a written paragraph (the call stop's back-note) the quiet CTA is part of the sentence flow */
.r9-backnote .r9cta-quiet { margin-top: 2px; }

/* ---- 5. THE SURFACES -------------------------------------------------------------------------------------------- */
/* 5a. THE COLUMN (Chat / You / Tonight). The block is the last thing on a locked screen, so it gets air above it and
       a hairline only where the reading actually ends. */
.r9o-body .r9cta-wrap { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); }
.r9o-body .r9cta-wrap .r9cta { max-width: none; }
/* the "What you get" rows already carry their own rule on the phone (07_you.css section 5); when they are printed the
   door follows them directly and a second hairline would box the reader in. */
.r9o-body .r9o-gets + .r9cta-wrap { margin-top: 12px; padding-top: 0; border-top: 0; }

/* 5b. THE CHAT ANSWER's upsell row: it belongs to the answer, so it is a card-radius pill on its own line - no
       hairline above it, because the answer bubble is already its own block. */
.r9o-body .r9cta-wrap.r9cta-ask { margin: 10px 0 0; padding-top: 0; border-top: 0; }
.r9o-body .r9cta-wrap.r9cta-ask .r9cta { max-width: 320px; }

/* 5c. THE LIVE STRIP. The door is one sentence written by src/01m_livestate.js, so the pill carries the sentence
       instead of a split - it is the only place in the lane where the words come from the live payload (L.door).
       Left-aligned, card radius, and capped so it never becomes a banner across a 1600px strip. */
.r9-livestrip .r9lv-door { margin-top: 8px; }
.r9-livestrip .r9lv-door button {
  justify-content: flex-start; max-width: 430px; font-size: 13.5px; font-weight: 700;
  padding: 10px 16px; min-height: 46px; text-align: left; text-underline-offset: 0; text-decoration: none;
}
.r9-livestrip .r9lv-door button::after { content: ' \2192'; margin-left: auto; padding-left: 14px; font-weight: 600; opacity: .85; }

/* 5d. THE CALL STOP. The sentence keeps its own paragraph; the action gets a row of its own so the 44px target never
       lands on top of the reading, and so a phone thumb cannot hit it while scrolling the sentence. */
.r9-backcta { margin: 2px 0 0 !important; }
.r9-backcta .r9cta-quiet { display: inline-flex; margin-top: 0; }

/* 5e. THE BACK-IT TOAST (host chrome; the button is raised by tools/host_blocks/77_cta.py through the host's own
       toast(msg, actLabel, actFn)). The host sheet gives #obtToast button a 34px mono link - under the tap floor and
       in a typeface the CTA system does not use. This is the moment a guest has just chosen a bet, so it gets the
       real pill, small. The scene stylesheet is injected after the host's, so an id-plus-id beats it either way. */
#obtToast #obtToastAct {
  display: inline-flex; align-items: center; justify-content: center; min-height: 44px; margin-left: 12px;
  padding: 0 16px; font-family: var(--ui); font-size: 13px; font-weight: 700; letter-spacing: 0; white-space: nowrap;
  color: var(--r9cta-on); background: var(--r9cta-grad); border: 0; border-radius: 99px;
  box-shadow: inset 0 1px 0 var(--r9cta-sheen), 0 8px 22px -8px var(--r9cta-glow); cursor: pointer;
}
#obtToast #obtToastAct:hover { color: var(--r9cta-on); box-shadow: inset 0 1px 0 var(--r9cta-sheen), 0 12px 28px -8px var(--r9cta-glow); }
#obtToast #obtToastAct:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
/* THE ROW HAS TO BE GIVEN A WIDTH. The host's toast is `display:flex` with `max-width:92%` and a nowrap button, and
   the sentence is the only thing in it that can shrink - drop a real pill in and the words collapse to one per line
   (measured at 390px before this rule). So the toast is given a real width and the pill is told never to shrink.
   ⛔ the host sheet is concatenated AFTER this one on the page, so a bare `#obtToast` here loses the tie on equal
   specificity: every layout rule below carries `html` in front of it. (The `#obtToast #obtToastAct` rules above are
   two ids and win on their own.) */
html #obtToast { width: min(92vw, 680px); max-width: 92vw; }
html #obtToast > span { flex: 1 1 auto; min-width: 0; }
#obtToast #obtToastAct { flex: 0 0 auto; }
@media (max-width: 899px) {
  html #obtToast { width: min(92vw, 430px); }
  #obtToast #obtToastAct { margin-left: 10px; padding: 0 14px; font-size: 12.5px; }
}

/* ---- 6. PHONE (320 / 390) --------------------------------------------------------------------------------------- */
/* The one breakpoint this lane uses. Nothing shrinks below the 44px floor and nothing overflows at 320: the pill is
   full width, the label is allowed to shrink against the price, and the price never wraps. */
@media (max-width: 899px) {
  .r9cta,
  .r9o-body .links button.r9cta,
  .r9-livestrip .r9lv-door button { max-width: none; font-size: 13.5px; min-height: 48px; }
  .r9cta.r9cta-split { padding-left: 16px; padding-right: 14px; }
  .r9cta .r9cta-pr { margin-left: 10px; padding-left: 10px; font-size: .9em; }
  .r9o-body .r9cta-ask .r9cta { max-width: none; }
  .r9cta-why { font-size: 13.5px; }
  .r9cta-note { font-size: 12px; }
  /* 07_you.css pulls .links out to the panel edge for the old underline row; the pill has its own box, so it comes
     back inside the gutter. */
  #obtStage .r9o-ph .r9o-body .links.r9cta-wrap { margin-left: 0; margin-right: 0; gap: 0; }
  #obtStage .r9o-ph .r9o-body .links.r9cta-wrap button { padding: 9px 16px; }
  #obtStage .r9o-ph .r9o-body .links.r9cta-wrap button.r9cta-quiet { padding: 0; }
}
@media (max-width: 359px) {
  .r9cta, .r9-livestrip .r9lv-door button { font-size: 13px; padding-left: 14px; padding-right: 12px; }
  .r9cta .r9cta-pr { margin-left: 8px; padding-left: 8px; }
}

/* =====================================================================================================================
   [WP-W5A 2026-09-16] THE CHAT SURFACE.  (round10w/CHAT_TOPTIER_SPEC.md section 6 + the owner's 15:00 ruling:
   "chat UI = ChatGPT/Gemini-level look in our brand tokens + that area upsold well".)
   =====================================================================================================================
   WHAT THIS SHEET IS FOR. The Chat tab was drawn with the You tab's furniture - a paragraph, a hairline row, an
   underlined word - because that is all the column had. A conversation needs its own rhythm: room between turns, the
   reader's words set apart from ours, a step line saying what is being read, a composer that behaves like a composer,
   sources that look like sources. That is this file and nothing else.
   THE LAW IT WORKS INSIDE. One typeface var(--ui); three inks var(--ink) / var(--ink-dim) / var(--ink-faint);
   hairlines var(--line). No gauge, glow, gradient, mono-caps eyebrow or face - the reader's own chosen mark is the
   only picture in the column and it was already here. THE ONE EXCEPTION is the owner's CTA pill (08_cta.css .r9cta):
   every upsell on this screen is that pill, and nothing here paints a button that could compete with it.
   THE ONE TINT is rgba(128,150,180,.10), the terminal's own neutral for a filled cell (scenes.css .r9-heat .c).
   ORDER: concatenated AFTER scenes.css, 07_you.css and 08_cta.css (build_r9.py globs src/0*.css in sort order), so it
   is the last word on anything it names, and it re-states only what it changes.
   ===================================================================================================================== */

/* ---- 1. THE SHELL -- a containing block for anything this sheet floats over the thread. ------------------------ */
.r9o { position: relative; }

/* ---- 2. THE RHYTHM OF A TURN -- a conversation is read in turns, so the space BETWEEN two turns must beat the space
   inside one: 20px against 6px. ---------------------------------------------------------------------------------- */
.r9o .msg { gap: 6px; margin: 0 0 20px; }
.r9o .msg:last-child { margin-bottom: 0; }
.r9o .msg .who { font-size: 12px; font-weight: 600; letter-spacing: 0; color: var(--ink); }
.r9o .msg .who small { font-size: 11.5px; }
.r9o .msg .txt { padding-left: 28px; font-size: 13.5px; line-height: 1.58; }
.r9o .msg .txt p { margin: 0 0 10px; }
.r9o .msg .txt .a p:last-child { margin-bottom: 0; }

/* THE READER'S OWN TURN. Their words in the house tint so the eye finds where they asked - no colour, no bubble tail,
   no second typeface. It hugs the text: a full-width panel round eight words reads as an error message. */
.r9o .msg.me .txt { padding-left: 28px; }
.r9o .msg.me .txt p {
  display: inline-block; max-width: 100%; margin: 0;
  background: rgba(128, 150, 180, .10); border-radius: 10px;
  padding: 7px 11px; color: var(--ink); font-size: 13.5px; line-height: 1.5;
}

/* ---- 3. THE STEP LINE -- "Reading the price story." lands inside 800 ms (04_engine.js E.askStatus; the server's own
   replaces it when a tool really runs) and then STAYS, ticked, while the answer writes under it. The dot is the work,
   the tick is the work finished - both DRAWN, so no glyph can be missing from the host's subset. ----------------- */
.r9o-body .st {
  display: flex; align-items: baseline; gap: 8px;
  font-style: normal; font-size: 12.5px; line-height: 1.45; color: var(--ink-faint); margin: 0 0 10px;
}
.r9o-body .st .stk { flex: none; width: 8px; height: 8px; position: relative; top: -1px; }
.r9o-body .st .stk::before {
  content: ""; position: absolute; left: 0; top: 0; width: 8px; height: 8px; border-radius: 50%;
  background: var(--ink-faint); opacity: .9; animation: r9stp 1.1s ease-in-out infinite;
}
@keyframes r9stp { 0%, 100% { transform: scale(.6); opacity: .45; } 50% { transform: scale(1); opacity: .95; } }
/* read, not reading: the dot becomes a tick and the animation stops. */
.r9o-body .st.done .stk::before {
  animation: none; border-radius: 0; background: none; opacity: 1;
  width: 7px; height: 4px; top: 1px;
  border-left: 1.5px solid var(--ink-faint); border-bottom: 1.5px solid var(--ink-faint);
  transform: rotate(-45deg);
}
@media (prefers-reduced-motion: reduce) { .r9o-body .st .stk::before { animation: none; } }

/* THE CURSOR -- narrower and softer than the old block: writing, not a terminal prompt. */
.r9o-body .cur { width: 2px; height: 14px; vertical-align: -2px; margin-left: 3px; background: var(--ink-dim); border-radius: 1px; }
.r9o-body .draft { min-height: 20px; }

/* ---- 4. THE SOURCES, AS CARDS -- the From line was underlined words: you had to tap one to learn whether it was
   worth tapping. Now a card per source - real name, one plain line - and the whole card is the tap. ------------- */
.r9o-body .src.cites { display: block; margin: 12px 0 0; padding: 0; }
.r9o-body .src.cites .srch {
  display: block; font-size: 11px; line-height: 1.4; color: var(--ink-faint); margin: 0 0 6px;
}
.r9o-body .src.cites button.r9-cite,
.r9o-body .src.cites .r9-cite {
  display: block; width: 100%; text-align: left; margin: 0 0 6px;
  background: none; border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px;
  font: inherit; color: var(--ink); text-decoration: none; cursor: pointer;
}
.r9o-body .src.cites .r9-cite:last-child { margin-bottom: 0; }
.r9o-body .src.cites .r9-cite .cn { display: block; font-size: 12.5px; line-height: 1.35; color: var(--ink); font-weight: 500; }
/* [W25A 2026-09-20] 13px, not 11.5: the vet's L7 read ".cl 12.0px" twice on the You column of FOUR leagues for a
   guest, after the rest of this file's floor was lifted (the phone rule below had already gone to 12 and that is
   still under the floor). This is the one line of a citation a reader actually reads - what the reading behind the
   chip will tell him - so it is the last place to save a pixel. Size only: colour, weight, family and spacing are
   untouched, and the block below keeps the phone at the same floor. */
.r9o-body .src.cites .r9-cite .cl { display: block; font-size: 13px; line-height: 1.4; color: var(--ink-faint); margin-top: 2px; }
.r9o-body .src.cites button.r9-cite:hover { border-color: var(--ink-dim); text-decoration: none; }
.r9o-body .src.cites button.r9-cite:hover .cn { text-decoration: underline; text-underline-offset: 3px; }
.r9o-body .src.cites button.r9-cite:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
/* the example cards in the guest block are spans, not buttons: nothing to tap, nothing to hover. */
.r9o-body .src.cites .r9-cite.eg { cursor: default; opacity: .8; }

/* ---- 5. THE STARTER QUESTIONS -- four real questions about the bet in front of the reader. Cards, not links: a card
   says "you can do this" at a glance, in the source cards' own hairline vocabulary. ------------------------------ */
.r9o-body .qr { display: block; margin: 4px 0 4px; }
.r9o-body .qr button.qc {
  display: block; width: 100%; text-align: left; margin: 0 0 6px; padding: 9px 11px;
  border: 1px solid var(--line); border-radius: 8px; background: none; color: var(--ink);
  font: inherit; font-size: 13px; line-height: 1.4; cursor: pointer;
}
.r9o-body .qr button.qc:last-child { margin-bottom: 0; }
.r9o-body .qr button.qc:hover { border-color: var(--ink-dim); color: var(--ink); }
.r9o-body .qr button.qc:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.r9o-body .qr button.qc .r9-chipq { font-size: 13px; color: var(--ink); }
.r9o-body .qr button.qc small { font-size: 11px; color: var(--ink-faint); margin-top: 2px; }
.r9o-body .qr.qr-more { margin-top: 10px; }

/* ---- 6. WHAT YOU CAN DO WITH AN ANSWER -- copy and the two votes: furniture, a step back from the words. ------- */
.r9o .msg .txt .acts { margin: 10px 0 0; gap: 16px; }
.r9o-body .vote button { font-size: 11.5px; color: var(--ink-faint); }
.r9o-body .vote button:hover { color: var(--ink); }
/* the reader pulled the brake: the partial answer stays, and says so. */
.r9o-body .r9c-stopped { margin: 8px 0 0; font-size: 12px; color: var(--ink-faint); }

/* ---- 7. THE COMPOSER -- a textarea that grows to four lines (03_pbi.js P.grow), Enter sends, Shift+Enter is a new
   line, and one round button that is SEND until an answer is writing and STOP while it is. --------------------- */
.r9o-in { padding: 10px 14px 12px; gap: 7px; position: relative; }
.r9o-in .box {
  align-items: flex-end; gap: 8px; padding: 7px 7px 7px 13px; border-radius: 20px;
  border: 1px solid var(--line); background: var(--panel);
}
.r9o-in .box:focus-within { border-color: var(--ink-dim); }
.r9o-in .box textarea {
  flex: 1 1 auto; min-width: 0; width: 100%; height: 22px; max-height: 88px;
  background: none; border: none; resize: none; overflow-y: hidden;
  color: var(--ink); font: inherit; font-family: var(--ui); font-size: 13px; line-height: 1.45;
  padding: 3px 0; margin: 0;
}
.r9o-in .box textarea:focus { outline: none; }
.r9o-in .box textarea::placeholder { color: var(--ink-faint); }
.r9o-in .box textarea:disabled { color: var(--ink-faint); -webkit-text-fill-color: var(--ink-faint); opacity: 1; }
.r9o-in .box button.snd {
  width: 30px; height: 30px; border-radius: 50%; border: none; flex: none; padding: 0;
  background: var(--ink); color: var(--panel); display: grid; place-items: center; cursor: pointer;
}
.r9o-in .box button.snd:hover { opacity: .85; }
.r9o-in .box button.snd:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.r9o-in .row { padding-left: 6px; }
.r9o-in .left { font-size: 11px; color: var(--ink-faint); }
.r9o-in .again { font-size: 11.5px; }

/* ---- 8. JUMP TO THE LATEST -- shown only while the reader has scrolled away from the bottom of a thread taller than
   the screen (03_pbi.js P.downTick). The only floating thing in this column. ------------------------------------ */
.r9o-in .r9c-down {
  position: absolute; right: 14px; top: -44px; z-index: 5;
  width: 34px; height: 34px; border-radius: 50%; padding: 0;
  border: 1px solid var(--line); background: var(--panel); color: var(--ink);
  display: grid; place-items: center; cursor: pointer;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .28);
}
.r9o-in .r9c-down:hover { border-color: var(--ink-dim); }
.r9o-in .r9c-down:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ---- 9. THE UPSELL INSIDE THE CHAT AREA ---------------------------------------------------------------------------
   NEVER (sub-only law): nothing here is a number, a count or a price about tonight's game. It is the SHAPE of an
   answer, labelled as an example, so a reader who pays on the strength of it gets what they were shown. The action
   under it is the owner's CTA pill and nothing here may out-shout it: a faint label, one hairline, no border. */
.r9o-body .r9c-eg { margin: 18px 0 2px; padding: 0 0 0 12px; border-left: 2px solid var(--line); }
.r9o-body .r9c-eglab { margin: 0 0 12px; font-size: 11.5px; line-height: 1.45; color: var(--ink-faint); }
.r9o-body .r9c-eg .msg:last-child { margin-bottom: 0; }
.r9o-body .r9c-eg .msg .txt { font-size: 13px; }
.r9o-body .r9c-eg .src.cites { margin-top: 10px; }

/* ---- 10. THE PHONE (< 900px) --------------------------------------------------------------------------------------
   The same column IS the whole You screen here. Three rules: every touchable control >= 44px on its short side
   (phone_metrics Y5), nothing readable under 10px (Y6), and no text box under 16px or iOS zooms the page on focus. */
@media (max-width: 899px) {
  #obtStage .r9o-ph .r9o-body .msg .txt { font-size: 14px; line-height: 1.55; }
  #obtStage .r9o-ph .r9o-body .msg.me .txt p { font-size: 14px; }
  #obtStage .r9o-ph .r9o-body .st { font-size: 13px; }
  /* [W25A 2026-09-20] 13px floor - the vet read ".srch 11.5px" on the You column of 12 leagues for a guest.
     A cite's heading is what tells the reader where an answer came from; it is never fine print. */
  #obtStage .r9o-ph .r9o-body .src.cites .srch { font-size: 13px; }
  /* the pre-card rule in scenes.css (shared) makes each cite an inline-flex ROW, which put the name and its line side
     by side and squashed both. Same specificity, later in the cascade, so the card wins. */
  #obtStage .r9o-ph .r9o-body .src.cites button.r9-cite,
  #obtStage .r9o-ph .r9o-body .src.cites span.r9-cite {
    display: block; width: 100%; padding: 10px 12px; min-height: 44px; font-size: 13px;
  }
  #obtStage .r9o-ph .r9o-body .src.cites .r9-cite .cn { display: block; font-size: 13px; }
  #obtStage .r9o-ph .r9o-body .src.cites .r9-cite .cl { display: block; font-size: 13px; }   /* [W25A] 13px floor */
  /* the 07_you.css phone rule turns every .qr button into a full-width row with a bottom hairline and no border of
     its own; this restores the card so the phone and the rail read the same, at a 44px floor. */
  #obtStage .r9o-ph .r9o-body .qr button.qc { min-height: 44px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px; }
  #obtStage .r9o-ph .r9o-body .qr button.qc:last-child { border-bottom: 1px solid var(--line); }
  #obtStage .r9o-ph .r9o-body .qr button.qc .r9-chipq { font-size: 13.5px; }
  #obtStage .r9o-ph .r9o-body .qr button.qc small { font-size: 11.5px; }
  #obtStage .r9o-ph .r9o-body .vote button { font-size: 12.5px; }
  #obtStage .r9o-ph .r9o-body .r9c-stopped { font-size: 12.5px; }
  #obtStage .r9o-ph .r9o-body .r9c-eglab { font-size: 12px; }
  /* the composer. 07_you.css already makes it sticky and lifts it over the keyboard (--bb-kbfit): that is untouched. */
  #obtStage .r9o-ph .r9o-in .box { min-height: 48px; padding: 5px 5px 5px 14px; align-items: flex-end; }
  #obtStage .r9o-ph .r9o-in .box textarea { font-size: 16px; line-height: 1.4; height: 24px; max-height: 92px; padding: 6px 0; }
  #obtStage .r9o-ph .r9o-in .box button.snd { width: 44px; height: 44px; background: none; color: var(--panel); position: relative; }
  #obtStage .r9o-ph .r9o-in .box button.snd::before { content: ""; position: absolute; inset: 6px; border-radius: 50%; background: var(--ink); }
  #obtStage .r9o-ph .r9o-in .box button.snd svg { position: relative; }
  #obtStage .r9o-ph .r9o-in .r9c-down { width: 44px; height: 44px; right: 12px; top: -52px; }
}

/* ---- 11. LIGHT -- the tint and the hairlines carry both themes; only the reader's own turn needs more weight on a
   white panel, where a 10% grey reads as nothing at all. --------------------------------------------------------- */
/* and the BB mark, which is a WHITE png: on a white panel it was an invisible name with a hole beside it. */
html[data-theme="light"] .r9o .msg.me .txt p { background: rgba(40, 60, 90, .07); }
html[data-theme="light"] .r9o .mk.bb { background: var(--ink); }
@media (prefers-color-scheme: light) {
  html:not([data-theme="dark"]):not([data-theme="light"]) .r9o .msg.me .txt p { background: rgba(40, 60, 90, .07); }
  html:not([data-theme="dark"]):not([data-theme="light"]) .r9o .mk.bb { background: var(--ink); }
}
