/* =========================================================================
 * BREAK ROOM — THE THEME'S BRIDGE OVER THE MOCKUP SHEET
 *
 * Lifted out of style.css unchanged. It is here rather than there so the
 * admin Current Break screen can load THESE rules without loading the
 * whole site stylesheet: that screen shows the same board (spec 33 R3d),
 * and the only way to give it the bridge used to be to enqueue all 7,067
 * lines of style.css into wp-admin. 973 of that file's selector parts
 * carry no scope — a bare `body, button, input, textarea{font-family}`,
 * a bare `h1..h6` — and they win on load order against core, so the admin
 * menu and footer came out in the theme's face.
 *
 * LOADED, NOT COPIED, by both pages. The two boards cannot drift, which
 * is the whole reason the admin screen was reaching for the theme's file
 * in the first place.
 *
 * ORDER MATTERS: this must come AFTER css/redesign/break-room.css. That
 * sheet is the mockup scoped by tools/scope-mockup-css.py; this is the
 * bridge over it, and several rules here exist only to outrank it or the
 * legacy breaks.css. Both enqueues name it as a dependency.
 *
 * It is also listed in csb_perf_critical_sources() — the critical blocks
 * are built from these files, and a source the build cannot see goes
 * stale silently, which switches the whole perf phase off.
 * ========================================================================= */

/* =========================================================================
 * BREAK ROOM — specs/redesign/03-break-room.md
 *
 * THE PAGE'S OWN STYLESHEET IS css/redesign/break-room.css — the mockup's
 * pages/css/break-room.css, scoped to .csb-rm. Nothing here restyles it.
 * What is left is the bridge: the frame the theme puts the page in, two
 * class names the theme already owned, and the join between the mockup's
 * board grid and the tiles cardsmiths-breaks.js appends into it.
 * ========================================================================= */

/* THE SAME 1440px BOX AS EVERY OTHER PAGE (Todd, Oct 25: "the break room
 * isn't doing the same width everything else is. It needs to respect the
 * 1440px width everything else does").
 *
 * THIS REVERSES spec 36 L1's point (2), which set 1200 here. Sam's
 * complaint that day was that the room ran out to the window's edge while
 * every other page stopped short of it — it had no cap at all — and the
 * fix capped it at the break pages' inner 1200 rather than at the number
 * the house actually uses. Counted today, #content .col-full is 1440 on
 * the cart and checkout (style.css:5128), the breaks list (5629), My
 * Account (6013) and the break pages (5628). 1200 was the room on its own.
 *
 * A break page caps TWICE — .col-full at 1440 and its own .csb-bp .wrap at
 * 1200 (style.css:5718) — which is why 1200 looked like the house number
 * from inside that page. The room has no second wrapper: the
 * `.csb-rm .wrap{max-width:none}` rule three lines down takes its cap off
 * so .stage can own the full row, so whatever .col-full says IS the room.
 *
 * THE PLAYER FOLLOWS ON ITS OWN. Its height is
 * `calc((100cqw - 340px) * 9 / 16)` — the container's width minus Twitch's
 * chat column, in sixteen-nines — so a 1404px content box gives it 598px
 * where 1164 gave 464. Nothing to retune; that is what a wider frame means
 * for a 16:9 embed. */
body.csb-rm-page #content .col-full{max-width:1440px;width:auto;
 padding-left:18px;padding-right:18px;box-sizing:border-box;margin:0 auto}
body.csb-rm-page .site-main,
body.csb-rm-page #primary.content-area{padding-left:0;padding-right:0;width:100%;float:none}
body.csb-rm-page .csb-rm .page{padding-left:0;padding-right:0}
body.csb-rm-page .csb-rm .wrap{max-width:none}

/* THE THEME ALREADY OWNED .page — and on this template specifically:
 * `.page-template-template-livestream-php .page{width:55%;margin:0 auto}`
 * has been there since long before the redesign, for the post content
 * below. .page is also what the mockup calls its own wrapper, so the
 * Break Room came out 55% wide and centred. The legacy rule is left
 * alone and undone inside .csb-rm, which is the only place the mockup's
 * version applies. (Second collision of this kind; .coupon on the cart
 * was the first.) */
body.csb-rm-page .csb-rm .page{width:auto;margin:0}

/* THE BOARD IS THE GRID; THE TIER CONTAINERS ARE NOT.
 * cardsmiths-breaks.js appends tiles into #all-teams-1..3, so without
 * this the board is three stacked blocks instead of one grid. The tier
 * labels span the full row. */
body.csb-rm-page .csb-rm .board .tier{display:contents}
body.csb-rm-page .csb-rm .board .teamtitle{grid-column:1/-1;margin:0;
 color:var(--mut);font-size:11px;font-weight:800;letter-spacing:.1em;text-transform:uppercase}
body.csb-rm-page .csb-rm .board .teamtitle:empty{display:none}
/* THE LEGACY BOARD CONTAINER AND NAME PILL, undone in scope.
 * breaks.css paints `#all-teams{background:black;padding:5px;min-height:
 * 125px}` and sizes the nickname with `#all-teams p{width:85%;height:24px;
 * border:1px solid white}`. Both are keyed on ids, so both outranked the
 * mockup's .board and .pn. Same treatment as the tile floats below:
 * leave the legacy rules for the admin board, undo them here. */
body.csb-rm-page #all-teams{background:var(--s1);width:auto;padding:18px 12px;
 margin-top:0;min-height:0;overflow:visible;float:none}
body.csb-rm-page #all-teams p,
body.csb-rm-page #all-teams-1 p,
body.csb-rm-page #all-teams-2 p,
body.csb-rm-page #all-teams-3 p{width:100%;max-width:150px;height:auto;
 margin:0;padding:5px 4px;font-size:15px;border:1.5px solid #cfd6da;border-radius:9px}

/* THE LEGACY BOARD SIZED TILES BY FLOAT.
 * css/breaks.css has `#all-teams-1 .team-multi{width:12%;height:148px;
 * float:left}` — a 12%-wide float in a plain block, which is how the board
 * was laid out before there was a grid. Against the mockup's grid that
 * collapsed every tile to a 16px sliver. The legacy rule is left alone
 * (the admin board still uses it) and undone inside .csb-rm. Third
 * collision of this kind, after .coupon and .page.
 *
 * The selector carries the ids because the legacy one does: an id beats
 * any number of classes, so `.csb-rm .board .team-multi` lost to
 * `#all-teams-1 .team-multi` and the tiles stayed 12% floats. */
body.csb-rm-page #all-teams .team,
body.csb-rm-page #all-teams .team-multi,
body.csb-rm-page #all-teams-1 .team-multi,
body.csb-rm-page #all-teams-2 .team-multi,
body.csb-rm-page #all-teams-3 .team-multi{width:auto;height:auto;float:none;
 overflow:visible;margin-bottom:0}
/* The tile is a cloned template: its <a> is the whole tile's surface, and
 * the icon stack keeps the square the mockup's logo sits in. */
body.csb-rm-page .csb-rm .board .tl .link{display:flex;flex-direction:column;
 align-items:center;gap:7px;text-decoration:none;width:100%;min-width:0}
/* .pn is white-space:nowrap with an ellipsis, so its MIN-content width is
 * the whole nickname. Without min-width:0 that becomes the flex item's
 * floor and a long name pushes the tile past its grid cell — "Stew
 * Pidasso" overhung its neighbour at 390. */
body.csb-rm-page .csb-rm .board .tl .pn{min-width:0;max-width:100%}
/* The icon stack holds absolutely-positioned quadrant images, so it needs
 * a height of its own — aspect-ratio, never height:auto, which collapses
 * it to nothing. It also has to fit its grid cell: at 390 the board is
 * four columns of 81px and a fixed 96px square overhung its neighbours. */
body.csb-rm-page .csb-rm .board .tl .team-icon-multi{position:relative;
 width:100%;max-width:96px;aspect-ratio:1/1;height:auto;flex:0 0 auto;overflow:hidden}
body.csb-rm-page .csb-rm .board .tl .team-icon-multi img{max-width:100%;max-height:100%}
/* SPEC 36 L16 — AND THE SAME DROP ON SPEC 03's BOARD. A random-PLAYER
 * board gets a real two-line name for the first time below (nameTiles()
 * now adopts the name the other script wrote instead of leaving it as a
 * 25px band), so every tile grows a line; over 60 tiles the logo pays
 * for it.
 *
 * !important on background-size ONLY: cardsmiths-breaks.js writes
 * .css('background-size','96px 96px') INLINE on .team-icon, and an inline
 * style is the one thing a stylesheet cannot outrank any other way — the
 * same justification as the display:none!important above. The count class
 * is written by csb-break-room.js (boardDensity).
 *
 * On the Admin Current Break screen admin-break-room.css:126-128 keys
 * `#all-teams .team-icon` on an id, so it beats this there. Deliberate:
 * the admin board is not a customer screen. */
body.csb-rm-page .csb-rm .board.many .tl .team-icon-multi{max-width:44px}
body.csb-rm-page .csb-rm .board.many .tl .team-icon{width:44px;height:44px;
 background-size:44px 44px!important}
body.csb-rm-page .csb-rm .board .tl .rk:empty,
body.csb-rm-page .csb-rm .board .tl .tn:empty{display:none}
/* SPEC 03's unrevealed draft tile: "dashed '?' for unrevealed".
 *
 * The generated sheet draws this as `.tl.hid .mv`, but .mv is the
 * mockup's own 150x88 art box and the real board's container is
 * .team-icon-multi, which carries a tuned 96px square above — giving it
 * .mv as well would fight that and overhang the four-column phone board.
 * So the dashed treatment lands on the tile the room actually renders.
 *
 * The movie stays visible: on this board a tile IS the movie, and what is
 * unknown until the pick lands is the buyer. */
body.csb-rm-page .csb-rm .board .tl.hid .team-icon-multi,
body.csb-rm-page .csb-rm .board .tl.hid .team-icon{
 border:1px dashed #3a434c;border-radius:12px;background:var(--s2,#181c21);opacity:.45}
body.csb-rm-page .csb-rm .board .tl.hid .nickname{
 color:var(--dim,#7d8a92);font-weight:900;letter-spacing:.04em}
/* no rank chip on a pick that has not landed */
body.csb-rm-page .csb-rm .board .tl.hid .rk{display:none}

/* THE LEGACY .mine FLOAT, UNDONE IN SCOPE — the fifth collision of this
 * kind, after .coupon, .page, the floated tiles and .add_to_cart_button.
 *
 * css/breaks.css:127 carries an unscoped `.mine{width:100px;float:left}`
 * from the old board. My Account got its undo (body.csb-ma-page below);
 * the Break Room never did, and the mockup's own .mine declares neither
 * width nor float, so nothing outranked it. Measured logged out, the
 * "Log in to see the board" strip was a 100x379 sliver reading one or two
 * words per line with its yellow button broken over two — and because it
 * FLOATS, the app module, the board and both break lists were pushed to
 * x=116 and lost 100px of width with it. At 390 that is 258px of content
 * inside a 358px wrap: 28% of the page given to the sliver.
 *
 * SCOPED TO #mine ON PURPOSE. The board's own tiles carry `mine` too —
 * that is the mockup's YOURS class (.tl.mine) — so an unscoped undo here
 * would reach into the board grid. The id keeps it to the two panels. */
body.csb-rm-page .csb-rm #mine .mine{width:auto;float:none}
/* AND THE BAND INSIDE IT. Undoing the float uncovered two more legacy
 * rules on the tile row, which was a 94px column nobody could read until
 * the panel went full width:
 *   breaks.css:294  #my-teams{background:black;padding:5px;overflow:hidden}
 *   bootstrap 3.3.7 .row{margin-left:-15px;margin-right:-15px}
 * The first is an id, so the mockup's `.csb-rm .mine .row` never stood a
 * chance; the second matches because the template gives the row
 * class="row", and Bootstrap is hard-coded into this template AFTER every
 * other sheet. Together they painted a solid black bar across the yellow
 * gradient panel and hung it 15px outside the panel's own padding.
 * The id here is what beats the id there. */
body.csb-rm-page .csb-rm #mine #my-teams{background:none;padding:0;overflow:visible;
 margin-left:0;margin-right:0;
 /* A GRID, LIKE THE BOARD — not the flex row the class name asks for.
  *
  * Todd, Oct 24, from production: "the Your teams section isn't right,
  * each team is taking the whole width."
  *
  * The tile is `class="team tl"`, and break-room.css gives `.csb-rm .tl`
  * `width:100%`. On #all-teams that is harmless: the tile is a GRID
  * item, so 100% is 100% of its ~122px track. #my-teams carries
  * class="row", which the mockup styles `display:flex` — and in a flex
  * row 100% is the whole container. Measured on a break with 18 of
  * them: container 1372px, every tile 1372px, eighteen stacked rows.
  *
  * Same grid the board uses, so a tile here is the size a tile is
  * there and `width:100%` resolves against a track either way.
  *
  * !important BECAUSE jQUERY WRITES AN INLINE display:block. The legacy
  * board script calls `$('#my-teams').show()` in six places; jQuery, on
  * an element whose computed display is none, forces the tag default —
  * `display:block` in the style attribute, which beats any stylesheet
  * rule that is not !important. First paint was a grid and the row went
  * back to full-width tiles the moment anything hid and re-showed it.
  * Same answer #all-teams already needed, for the same reason. */
 /* SPEC 36 L34 — A LEFT-PACKED WRAP ROW, NOT A GRID (Todd, Oct 25: the
  * first tile sat in the second column, the Mets about 200px in).
  *
  * A grid hands EVERY child a cell, including one that draws nothing. The
  * board script appends to #my-teams in four places and leaves a non-tile
  * child behind it, so the real tiles started one track over. Hiding that
  * child is the rule below; this is the other half, because a flex row
  * only gives a box a slot if it has width, so the same thing cannot
  * happen again from a child nobody has noticed yet.
  *
  * THE FIXED BASIS IS NOT DECORATION. The tile is `class="team tl"` and
  * break-room.css gives `.csb-rm .tl` width:100% — which is what made
  * every tile full-width on Oct 24 and is why this was a grid in the
  * first place. `flex:0 0 122px` plus an explicit width overrides it at
  * the one place it matters, and 122px is the track the grid was using,
  * so the strip keeps the board's own rhythm.
  *
  * !important stays for the reason above it: jQuery writes an inline
  * display:block every time it shows this element. */
 display:flex!important;flex-wrap:wrap;justify-content:flex-start;
 gap:12px 10px}
/* NOTHING THAT IS NOT A TILE TAKES A SLOT. The script's own leftovers —
 * a stray .nickname, the placeholder breaks.css:294-302 draws — are the
 * reason the strip was offset; they are not ours to stop appending, so
 * they are ours to stop showing. */
body.csb-rm-page .csb-rm #mine #my-teams > :not(.team){display:none}
/* AND THE TWO NOBODY CAN SELECT. #my-teams carries class="row", and
 * Bootstrap 3.3.7 gives .row a clearfix — `.row:before,.row:after
 * {content:" ";display:table}`. In a flex container those pseudos become
 * flex ITEMS: zero width, but each one still takes a slot and the column
 * gap beside it, which is why the strip was still inset 10px after the
 * child above was hidden. In the grid this replaced they took a whole
 * 122px track each, which is the "first tile in the second column" the
 * row is about — measured here, not reasoned about. `> :not(.team)`
 * cannot reach a pseudo-element, so they are named. */
body.csb-rm-page .csb-rm #mine #my-teams:before,
body.csb-rm-page .csb-rm #mine #my-teams:after{display:none}
body.csb-rm-page .csb-rm #mine #my-teams .tl{flex:0 0 122px;width:122px}
/* Four across on a phone, the same as the board there. */
@media (max-width:860px){
 body.csb-rm-page .csb-rm #mine #my-teams .tl{flex-basis:calc(25% - 8px);width:auto}
}

/* "You're In It!" is appended by the board script, not by us. */
body.csb-rm-page .csb-rm .purchased-alert{display:block;background:var(--teal);color:#04241c;
 font-weight:800;font-size:11px;border-radius:7px;padding:2px 6px;margin-top:4px}

/* THE MOCKUP'S ART PANELS, GIVEN REAL IMAGES — SPEC 36 L3.
 *
 * .q-art and .bart are grey panels in the mockup; its JS set
 * `background:#0e1216 url(...) center/contain no-repeat` on them at
 * runtime, and this sheet used to say the same fit for an inline URL.
 *
 * A BACKGROUND CANNOT CARRY A SRCSET, which is the whole of L3: the
 * rails handed these boxes woocommerce_thumbnail (324px) into a ~377px
 * tile — 754 device px on a 2x phone — and the browser had no better
 * file to pick. They now render wp_get_attachment_image( id,
 * 'csb-square' ): 512 base, with 100w through 2048w in the srcset. So
 * .im only has to kill the mockup's grey radial placeholder, and the
 * <img> does the fitting, in the same three declarations the homepage
 * card uses (style.css:4287).
 *
 * The box keeps its own square: break-room.css:146/159 put
 * aspect-ratio:1/1 on .q-art and .bcard .bart, and :145 already makes
 * both centring flex containers, so nothing about the layout moves.
 * overflow:hidden is new on .q-art — .bcard already clips (:158), but
 * .q-art carries its own 10px radius with nothing clipping it, so a
 * wide box-art scan would have squared its corners.
 *
 * The `background` shorthand, not background-color, is what resets the
 * radial-gradient from `.csb-rm .q-art,.csb-rm .bart` at (0,1,1). */
body.csb-rm-page .csb-rm .q-art.im,
body.csb-rm-page .csb-rm .bart.im{background:#0e1216;overflow:hidden}
body.csb-rm-page .csb-rm .q-art img,
body.csb-rm-page .csb-rm .bart img{width:100%;height:100%;object-fit:contain;display:block}

/* THE LEGACY .add_to_cart_button LOOK, UNDONE IN SCOPE (rule 7.2 / 7.9).
 *
 * Woo's ajax handler binds on `.add_to_cart_button`, so a "Still open"
 * card that adds a spot without leaving the page HAS to carry that class
 * — and style.css has painted it since long before the redesign: 12px
 * uppercase with 1px tracking, #FFC82E and `margin-bottom:10px
 * !important`. Measured in the grid: "ADD 1 SPOT · $59" in a different
 * yellow beside "Buy teams · $25-265", and its row sitting 25px off the
 * card bottom where every other button sits at 15px — 7.9 asks for one
 * line. The !important is only reachable with another one.
 *
 * Fourth collision of this kind after .coupon, .page and the floated
 * tiles: the legacy rule is left alone for the shop loops and undone
 * here. The font size, weight and radius already come from the mockup's
 * own `.csb-rm .bcard .btn`, which outranks a bare class. */
body.csb-rm-page .csb-rm .qrow .btn.add_to_cart_button{text-transform:none;
 letter-spacing:0;margin:0!important;background-color:var(--yel)!important;color:#111!important}

/* ONE STAGE, FULL WIDTH (Todd, 18 Oct).
 *
 * The mockup draws the player and a chat column side by side. The real
 * Twitch embed is "video-with-chat" — its own default above 700px — so a
 * second column beside it showed the same conversation twice. .stage.solo
 * is one column and the embed brings its own chat.
 *
 * That also changes the shape of the box: 16/9 is right for a video, but
 * with Twitch's ~340px chat column beside it a 16/9 box letterboxes the
 * video badly. A height instead, clamped so it is neither a letterbox
 * slot on a laptop nor the whole screen on a big monitor. (This block
 * once said Twitch drops chat below 900px and 16/9 is right again there.
 * It does not — it stacks chat UNDER the video; see the @media's own
 * measurement below.) */
body.csb-rm-page .csb-rm .stage.solo{grid-template-columns:1fr;container-type:inline-size}
/* SPEC 36 L1 (5) — THE BOX IS THE SIZE OF THE VIDEO, not 16:9 of the row.
 *
 * Sam, Oct 25: "black bars above and below the stream". The clamp above
 * was a slot the embed sat inside rather than a box it filled. The embed
 * is video-with-chat and draws its own ~340px chat column INSIDE this
 * box, so the video only ever gets (row - 340). In the 1200 frame that is
 * 824px, a 463px-tall video in a 640px box: 177px of black.
 *
 * .stage.solo is the query container — it is .player's direct parent
 * (template-livestream.php:376-377) — so 100cqw is the row width and the
 * height is the video's own.
 *
 * TWO height declarations on purpose. The clamp is the fallback for a
 * browser without container queries: cqw makes the second declaration
 * invalid at parse time and it is dropped, leaving today's behaviour.
 * min-height is the floor for the narrow end of the desktop range, where
 * (row - 340) is small but Twitch has not yet switched layouts. The
 * @media below keeps a height of its own, and it has to: at <=900px
 * Twitch STACKS chat under the video instead of dropping it, so the box
 * has to get TALLER there, not shorter — the measurement in that block's
 * own comment. That is why the seam here is 900px and not the 701px the
 * row asked for.
 *
 * The 340px is the row's number, not a measurement — it needs a live
 * stream to take. The mockup's own chat column was 330px
 * (css/redesign/break-room.css:57). Worth one check with Sam on air. */
body.csb-rm-page .csb-rm .stage.solo .player{aspect-ratio:auto;
 height:clamp(420px,64vh,760px);
 height:calc((100cqw - 340px) * 9 / 16);min-height:380px}
@media (max-width:900px){
 /* Twitch stacks video over chat on a narrow screen rather than dropping
  * it, so a 16/9 box clipped the chat clean off — the iframe asked for
  * 625px inside a 201px slot. It gets a height here too. */
 body.csb-rm-page .csb-rm .stage.solo .player{aspect-ratio:auto;
  height:clamp(420px,78vh,660px)}
}
/* OFFLINE, THERE IS NO EMBED TO SIZE FOR.
 *
 * The heights above exist because the Twitch embed carries its own chat
 * column and letterboxes badly in a 16/9 box. The offline card is a
 * five-line message, and until the live state started answering honestly
 * it was almost never on screen — measured at 1280x1000 it was 215x125 of
 * content inside a 1248x640 panel. The embed's height does not apply to
 * it, so it goes back to something proportionate. .l--off is the mockup's
 * own class and sits on .page, which is why this is a descendant of it
 * rather than a second modifier on .player. */
body.csb-rm-page .csb-rm .l--off .stage.solo .player{height:clamp(260px,34vh,420px)}
@media (max-width:900px){
 body.csb-rm-page .csb-rm .l--off .stage.solo .player{height:clamp(240px,32vh,360px)}
}
/* ...AND THE VIDEO'S min-height IS NOT THE MESSAGE CARD'S FLOOR.
 *
 * The two rules above only name `height`. min-height is a separate
 * property, so the 380px floor the live box got for its container query
 * (spec 36 L1) went on applying here and the offline card could not go
 * below it — 380px instead of the 272px a 34vh clamp asks for on an
 * 800px-tall window, and instead of 360px at the narrow end, where its
 * own rule asks for less than the floor. The floor is the embed's; this
 * card has no embed. */
body.csb-rm-page .csb-rm .l--off .stage.solo .player{min-height:0}
body.csb-rm-page .csb-rm .player .on{width:100%;height:100%}
body.csb-rm-page .csb-rm .player .on iframe,
body.csb-rm-page .csb-rm .player .on #twitch-embed,
body.csb-rm-page .csb-rm .player .on .livevideo{width:100%!important;height:100%!important;border:0;display:block}

/* Storefront furniture the mockup assumes is not there. */
body.csb-rm-page .entry-header,
body.csb-rm-page .storefront-breadcrumb{display:none}


/* THE RANDOM.ORG VERIFY BUTTON, DRESSED AS THE LINK IT SITS BESIDE.
 *
 * #break-verify is filled by cardsmiths-breaks.js with markup stored on
 * the break — a <form action="https://api.random.org/verify"> wrapping a
 * bare <input type="submit" value="Validate Random">. It is a SIGNED POST
 * and must not be rebuilt as a link, so this is the only way to style it.
 *
 * Left alone it was Storefront's default button: #999 on #333, square,
 * 8px/19px padding — a light grey slab in the middle of the dark current
 * break strip, between two teal text links. The form was display:block
 * with a 21.8px bottom margin too, so it also pushed the flex row around.
 *
 * A YELLOW PILL, NOT A LINK (Todd, 20 Oct). The mockup draws this item as
 * `<a class="v">Verified by RANDOM.ORG ↗</a>`, a muted link among links,
 * and it was built that way first — but a pill is the call, so it takes
 * the room's own small-button treatment from `.mine.out a.b`: var(--yel)
 * on #111, 800, 9px radius, 7px/14px.
 *
 * THE FORM IS THE PILL AND THE INPUT IS THE LABEL. Doing it the other way
 * round leaves the ↗ stranded outside the pill, because ::after does
 * nothing on a replaced element and the input is one. Painting the form
 * instead puts the arrow inside, where it belongs, and the input goes
 * transparent and inherits.
 *
 * align-items keeps the two text links beside it centred rather than
 * stretched to the pill's height.
 *
 * And :empty, because there are TWO of these containers (the second is
 * the Blue Box single draw) and a .links row with gap:16px was paying
 * 32px for them on every break that has neither. */
body.csb-rm-page .csb-rm .links{align-items:center}
body.csb-rm-page .csb-rm .links #break-verify:empty,
body.csb-rm-page .csb-rm .links #break-verify-single:empty{display:none}
body.csb-rm-page .csb-rm .links form{display:inline-block;margin:0;
 background:var(--yel);color:#111;border-radius:9px;padding:7px 14px;
 font-size:13.5px;font-weight:800;line-height:1.2}
body.csb-rm-page .csb-rm .links form::after{content:'\00a0\2197'}
body.csb-rm-page .csb-rm .links form:hover{background:#ffd438}
body.csb-rm-page .csb-rm .links input[type="submit"]{width:auto;background:none;border:0;
 border-radius:0;padding:0;margin:0;box-shadow:none;color:inherit;font:inherit;
 letter-spacing:normal;text-transform:none;cursor:pointer}
body.csb-rm-page .csb-rm .links input[type="submit"]:hover,
body.csb-rm-page .csb-rm .links input[type="submit"]:focus{background:none;color:inherit}

/* [hidden] IS INERT ON THESE TWO. The generated sheet declares
 * `.csb-rm .links{display:flex}` and `.csb-rm .rounds{display:flex}`, and a
 * class rule beats the user-agent's `[hidden]{display:none}` — so the
 * "See how the order was drawn →" row and the empty eight-step rounds bar
 * were ON SCREEN on every visit, logged out, with nothing in them. The JS
 * sets .hidden expecting it to mean something. */
body.csb-rm-page .csb-rm .links[hidden],
body.csb-rm-page .csb-rm .rounds[hidden]{display:none}

/* THE "YOURS" BADGE NEEDS A POSITIONED TILE. The generated sheet draws it
 * with `.tl.mine::before{position:absolute}` but gives `.csb-rm .tl` no
 * position, so the badge would anchor to the board instead of the tile.
 * The class itself is the mockup's — csb-break-room.js toggles `mine`. */
body.csb-rm-page .csb-rm .tl{position:relative}
body.csb-rm-page .csb-rm .tl.mine{border-color:var(--yel,#f5c518);
 box-shadow:0 0 0 1px var(--yel,#f5c518)}

/* =========================================================================
 * SPEC 33 R3a — THE PICKED BOARD (pick your team / mixer teams / pick your
 * player / letters). Mockup: specs/mockups/break-room-board/.
 *
 * HERE RATHER THAN IN THE GENERATED SHEET for the same reason as the type
 * pill below: css/redesign/break-room.css is the ROOM mockup scoped, and
 * this board is in a newer mockup of its own. When the two are merged
 * upstream these rules can go and the generated sheet will carry them.
 *
 * The values are that mockup's, with one change made on purpose: it tints
 * from a local --wash, and the real page already has the product colour on
 * --washrgb (CardSmiths_Product_Color::print_break_vars, body.w--on). R3a
 * says "the board container and tiles carry the break's --washrgb tint ...
 * exactly like the checklist header card", so they read the real variable
 * and fall back to the room's own surface where no colour was set.
 * ========================================================================= */
body.csb-rm-page .csb-rm .pboard{display:grid;
 grid-template-columns:repeat(auto-fill,minmax(126px,1fr));gap:12px 10px;
 border:1px solid rgba(var(--washrgb,39,45,52),.45);border-radius:14px;
 background:linear-gradient(180deg,rgba(var(--washrgb,17,20,24),.16),
  rgba(var(--washrgb,17,20,24),.04) 40%,transparent);padding:16px 12px}
/* A player board runs to a few hundred tiles; the mockup gives it a denser
 * grid rather than a page of scrolling. */
body.csb-rm-page .csb-rm .pboard.dense{
 grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:10px 8px}
body.csb-rm-page .csb-rm .pboard[hidden]{display:none}
/* EXACTLY ONE BOARD ON SCREEN. cardsmiths-breaks.js calls
 * $('#all-teams').show() on every pass, which writes an inline display,
 * so only !important can put the old board away for the picked types.
 * Overriding another script's inline style is what it is for. */
body.csb-rm-page .csb-rm.csb-picked #all-teams{display:none!important}
/* AND THE GRID HAS TO COME BACK THE SAME WAY.
 *
 * jQuery's .show() does not simply clear the inline display — once an
 * element has been hidden it restores a REMEMBERED one, and for a div
 * that is `block`. So the moment the picked/spot board handed the
 * screen back, $('#all-teams').show() wrote display:block inline and
 * the 153-tile final board came back as a single column. The hide above
 * still wins: it carries one more class at the same id. */
body.csb-rm-page .csb-rm #all-teams{display:grid!important}
/* The checklist popup's wrapper exists only to put break-pages.css in
 * scope; .csb-bp's own base rule is `margin:0;background:#000`, which
 * would paint an empty black band across the room. display:contents
 * removes the wrapper's box and keeps both the scope and the custom
 * properties the overlay reads. */
body.csb-rm-page .csb-rm .csb-rm-ovwrap{display:contents}
/* BOOTSTRAP OWNS .modal, AND IT IS ON THIS PAGE — the seventh collision
 * of this kind, after .coupon, .page, the floated tiles, .mine,
 * .add_to_cart_button and .next.
 *
 * `.modal{position:fixed;inset:0;z-index:1050}` comes from a plugin's
 * Bootstrap, and .csb-bp .modal declares NONE of those three, so there
 * was nothing for the scoped rule to outrank: the overlay's panel was
 * pulled out of its flex centring and pinned to the top-left corner,
 * full height, with the board showing beside it.
 *
 * Undone in scope rather than anywhere else — the break page's own
 * overlay is not this page's business, and Bootstrap's .modal is not
 * ours to change. */
body.csb-rm-page .csb-rm .csb-bp .modal{position:static;inset:auto;z-index:auto}
/* .pn IS THE BOARD TILE'S NAME PILL — AND THE CHECKLIST TABLE'S PLAYER
 * CELL. The eighth collision of this kind, after .coupon, .page, the
 * floated tiles, .mine, .add_to_cart_button, .next and .modal.
 *
 * break-room.css draws `.csb-rm .pn{width:100%;max-width:150px;border:
 * 1.5px solid #cfd6da;text-align:center;white-space:nowrap}` for the
 * tile's name. The popup's rows are `<td class="pn">`, and the overlay
 * lives inside .csb-rm so the room's rule reached every one of them.
 *
 * Both symptoms came from this single rule. The visible one was a pale
 * rounded box drawn round each player cell. The other was stranger: the
 * tables are `table-layout:fixed` with five <col>s, two of them auto,
 * and `width:100%` on one cell took the whole remainder — collapsing
 * its neighbour to ZERO, so the card name wrapped one character per line
 * and a six-row table stood 1,400px tall. Forcing auto layout hid that,
 * which is how it was found; this removes the cause instead.
 *
 * Undone in scope, never on the room's own tiles, which still want it. */
body.csb-rm-page .csb-rm .csb-bp .pn{width:auto;max-width:none;min-width:0;
 border:0;border-radius:0;padding:7px 8px;text-align:left;white-space:normal;
 font-size:inherit;font-weight:inherit;color:inherit;overflow:visible}

body.csb-rm-page .csb-rm .pboard .t{position:relative;display:flex;
 flex-direction:column;align-items:center;text-align:center;gap:6px;
 padding:12px 6px 10px;border-radius:12px;min-width:0;
 background:linear-gradient(180deg,rgba(var(--washrgb,28,33,38),.22),
  rgba(var(--washrgb,28,33,38),.08));
 border:1px solid rgba(var(--washrgb,39,45,52),.35)}
/* The whole tile face is the checklist link — logo and name both — and Add
 * to cart is a sibling, so a tap on the tile never buys (R3a). */
body.csb-rm-page .csb-rm .pboard .t > a.ck{display:flex;flex-direction:column;
 align-items:center;gap:6px;width:100%;min-width:0;text-decoration:none;
 color:inherit;cursor:pointer}
/* SPEC 36 L17 — NO LOGO IS CLIPPED TO A CIRCLE.
 *
 * css/redesign/break-room.css draws `.csb-rm .lg{border-radius:50%}` for
 * the no-image fallback (the coloured initials) and resets it again on
 * `.lg.im`, and the tile csb-break-room.js builds carries the art WITHOUT
 * .im — so a square-ish logo lost its corners. Sam, Oct 25: the serifs of
 * the "H" on the WWE Universe letters board (break 881511).
 *
 * The radius is undone HERE rather than on `.csb-rm .lg`, because that
 * sheet is generated from specs/ and because the circle is right where it
 * means it: .ini below and .lg.q on the reveal board both declare their
 * own 50% and keep it. So the rule is effectively inverted — art is
 * square, the two fallbacks are round — without touching a generated file.
 *
 * No overflow on the box either: the picture is background-size:contain
 * inside the span, so there is nothing here to clip. */
body.csb-rm-page .csb-rm .pboard .t .lg{width:64px;height:64px;border-radius:0;
 background:center/contain no-repeat;
 filter:drop-shadow(0 2px 6px rgba(0,0,0,.45));flex:0 0 auto}
body.csb-rm-page .csb-rm .pboard.dense .t .lg{width:50px;height:50px}
body.csb-rm-page .csb-rm .pboard .t .ini{width:58px;height:58px;border-radius:50%;
 background:rgba(var(--washrgb,28,33,38),.35);display:flex;align-items:center;
 justify-content:center;font-weight:800;font-size:18px;color:var(--ink);
 border:1px solid var(--line);flex:0 0 auto}
body.csb-rm-page .csb-rm .pboard.dense .t .ini{width:46px;height:46px;font-size:15px}
/* SPEC 36 L16 — OVER 60 TILES THE LOGO DROPS, so the second line of name
 * below costs the tile nothing. A 232-entry player board (break 874681,
 * Bowman Chrome Hobby Dual Case #4) is twenty-odd rows; the clamp adds
 * 15px to each of them and 64 -> 44 gives back 20. Measured on the live
 * board: tile height 194px -> 174px with the clamp on.
 *
 * AFTER the .dense rules on purpose: a player board carries both classes
 * and these selectors have the same weight, so the later one wins. It
 * also outranks the (max-width:860px) block further down, which is fine —
 * 44 is smaller than the 48 that block asks for, which is the direction
 * this rule is already going. */
body.csb-rm-page .csb-rm .pboard.many .t .lg{width:44px;height:44px}
body.csb-rm-page .csb-rm .pboard.many .t .ini{width:44px;height:44px;font-size:14px}
body.csb-rm-page .csb-rm .sboard.many .t.pick .lgs .lg,
body.csb-rm-page .csb-rm .sboard.many .t.pick .lg{width:44px;height:44px}
/* The dashed "?" comes down with them. `.sboard .t.pick .lg.q` is one
 * class more specific than the rule above and declares its own 52px, so
 * without this line a 92-pick draft showed 44px squares beside 52px
 * circles in the same grid — measured. It is the same tile not yet
 * turned over, so it is the same size. */
body.csb-rm-page .csb-rm .sboard.many .t.pick .lg.q{width:44px;height:44px;
 font-size:17px}
/* SPEC 36 L16 — A NAME IS NEVER ONE LINE WITH AN ELLIPSIS.
 *
 * "Ronald Acuña…", "Other Los An…", "Keaton Antho…", "Pete
 * Crow-Ar…" (Sam, Oct 25) — measured on the live room this rule was
 * white-space:nowrap with text-overflow:ellipsis and the box was 15px
 * tall, so every name longer than its tile lost its end.
 *
 * The phone block below has had exactly this clamp since R3a. The
 * truncation was never a phone problem, so the clamp comes out of the
 * query and the phone block keeps only its smaller font.
 *
 * min-height in EM is right HERE and wrong on .player-name.csb-named:
 * nothing inside this rule changes the font size, so 2.4em is always two
 * of its own lines. (.csb-named has a smaller .csb-combo variant, which
 * is why that one is pinned in px and a test asserts the px.)
 *
 * -webkit-line-clamp brings its own ellipsis, so text-overflow goes. */
body.csb-rm-page .csb-rm .pboard .t .nm{font-weight:700;font-size:12.5px;
 line-height:1.2;width:100%;overflow:hidden;white-space:normal;
 display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
 min-height:2.4em}
body.csb-rm-page .csb-rm .pboard .t:hover .nm{color:var(--teal);
 text-decoration:underline;text-underline-offset:3px}
body.csb-rm-page .csb-rm .pboard .t .who{font-size:11.5px;color:var(--mut);
 width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* THE BUYER IS YELLOW ON EVERY BOARD IN THE ROOM (Todd, Oct 26: "the
 * customer name should be yellow on ALL BREAK TYPES IN THE BREAKROOM").
 *
 * The room draws three boards and the buyer's name is a different element
 * on each, which is why fixing the legacy one did not carry:
 *
 *   #all-teams   p.nickname      random and drafted teams — done further
 *                                down, on that rule's own colour
 *   .pboard      .t .who b       pick-your-team / player — was --ink
 *   .sboard      .t .who b       the spot board while a random or draft
 *                                fills, AND the draft reveal board — had
 *                                no colour of its own at all, so it took
 *                                whatever .who's --mut passed down
 *
 * pTile() writes the first, spotBoard() and revealBoard() both write into
 * .sboard, so the one selector covers both of those. The surrounding
 * .who stays --mut: it is the quiet label, and only the name inside it is
 * the person. */
body.csb-rm-page .csb-rm .pboard .t .who b,
body.csb-rm-page .csb-rm .sboard .t .who b{color:var(--yel);font-weight:700}

/* AVAILABLE IS THE FULL-COLOUR TILE; TAKEN GOES QUIET — the mockup's
 * v30 sync inverts what the first cut did, and the comment it arrives
 * with says why: "available = the normal, full-colour tile with a price
 * and a button; taken = quiet. No tag, no mint wash."
 *
 * What a buyer is looking at a filling board FOR is what they can still
 * have, so the ones they can have keep the product colour and a solid
 * teal edge, and the ones already gone fade back. It only applies while
 * the board is SELLING: once it is full every tile is equal again and
 * the board is a record rather than a shop. */
body.csb-rm-page .csb-rm .pboard .t.open{border-color:rgba(21,204,173,.45);
 border-style:solid}
body.csb-rm-page .csb-rm .pboard .t.open .lg,
body.csb-rm-page .csb-rm .pboard .t.open .ini{opacity:1;filter:none}
body.csb-rm-page .csb-rm .pboard.selling .t:not(.open):not(.yours) .lg,
body.csb-rm-page .csb-rm .pboard.selling .t:not(.open):not(.yours) .ini{
 opacity:.45;filter:grayscale(.8) drop-shadow(0 2px 6px rgba(0,0,0,.45))}
body.csb-rm-page .csb-rm .pboard.selling .t:not(.open):not(.yours) .nm{color:var(--mut)}
body.csb-rm-page .csb-rm .pboard.selling .t:not(.open):not(.yours){
 background:rgba(255,255,255,.02);border-color:var(--line)}
body.csb-rm-page .csb-rm .pboard .t .pr{font-size:13px;font-weight:800;color:var(--ink)}
body.csb-rm-page .csb-rm .pboard .t .add{margin-top:4px;padding:4px 10px;
 border-radius:999px;border:0;background:var(--yel);color:#111;font-weight:800;
 font-size:11px;white-space:nowrap;text-decoration:none;cursor:pointer;
 display:inline-block;line-height:1.5}
body.csb-rm-page .csb-rm .pboard .t .add:hover{filter:brightness(1.08)}
/* The theme's own .add_to_cart_button is a full-width storefront button;
 * the sixth collision of this kind, after .coupon, .page, the floated
 * tiles, .mine and .add_to_cart_button on the break pages. */
body.csb-rm-page .csb-rm .pboard .t .add.add_to_cart_button{width:auto;
 float:none;margin-left:0;margin-right:0;min-height:0;height:auto}
body.csb-rm-page .csb-rm .pboard .t .add.added{display:none}
body.csb-rm-page .csb-rm .pboard .t .added_to_cart{margin-top:4px;
 font-size:11px;font-weight:800;color:var(--teal);text-decoration:none}

/* YOURS, highlighted in place — "not pulled to the front". */
body.csb-rm-page .csb-rm .pboard .t.yours{background:rgba(245,197,24,.10);
 border-color:var(--yel);border-style:solid}
body.csb-rm-page .csb-rm .pboard .t.yours:before{content:"YOURS";position:absolute;
 top:-8px;left:50%;transform:translateX(-50%);background:var(--yel);color:#111;
 font-size:9.5px;font-weight:800;letter-spacing:.08em;padding:2px 7px;
 border-radius:999px;z-index:2}

/* The help row's legend and the footer counts. */
body.csb-rm-page .csb-rm .bhelp .legend{margin-left:auto;display:flex;gap:12px;
 font-size:12px;color:var(--mut)}
body.csb-rm-page .csb-rm .bhelp .legend[hidden]{display:none}
body.csb-rm-page .csb-rm .bhelp .legend i{display:inline-block;width:10px;height:10px;
 border-radius:3px;margin-right:5px;vertical-align:-1px;border:1px solid var(--line)}
body.csb-rm-page .csb-rm .bhelp .legend .so i{background:var(--s3)}
body.csb-rm-page .csb-rm .bhelp .legend .op i{background:transparent;
 border-style:dashed;border-color:var(--teal)}
body.csb-rm-page .csb-rm .bhelp .legend .yo i{background:rgba(245,197,24,.3);
 border-color:var(--yel)}
body.csb-rm-page .csb-rm .foot{display:flex;justify-content:space-between;gap:10px;
 flex-wrap:wrap;color:var(--mut);font-size:12.5px;margin-top:8px}
body.csb-rm-page .csb-rm .foot b{color:var(--ink)}
body.csb-rm-page .csb-rm .foot[hidden]{display:none}

/* PHONE: three columns, and a smaller name.
 *
 * This block used to carry the two-line clamp as well, which is where
 * R3a put it; spec 36 L16 moved that up to the unscoped rule, because a
 * name losing its end was never a phone problem. All that is left here
 * is the font size. */
@media (max-width:860px){
 body.csb-rm-page .csb-rm .pboard,
 body.csb-rm-page .csb-rm .pboard.dense{grid-template-columns:repeat(3,minmax(0,1fr));
  gap:10px 6px;padding:12px 6px}
 body.csb-rm-page .csb-rm .pboard .t .lg,
 body.csb-rm-page .csb-rm .pboard .t .ini{width:48px;height:48px}
 body.csb-rm-page .csb-rm .pboard .t .who{font-size:10.5px}
 body.csb-rm-page .csb-rm .pboard .t .nm{font-size:11.5px}
 body.csb-rm-page .csb-rm .pboard .t .add{padding:5px 12px;font-size:12px}
 body.csb-rm-page .csb-rm .bhelp .legend{margin-left:0}
}

/* SPEC 33 R3b — THE SPOT BOARD. Same grid and the same tile shell as
 * R3a's picked board — it IS .pboard, with .sboard only to mark which
 * one it is — because a spot board and a picked board are the same board
 * showing different things. A spot tile is a NUMBER and a name: no
 * picture, no price and no button, "because you can't buy a number". */
/* v30's spot tile is Todd-style: the number large and white on the
 * wash, with the # small and faded in front of it. No logo — there is
 * no team on a spot yet — and no open tiles at all (see the note in
 * spotBoard). */
body.csb-rm-page .csb-rm .sboard .t.spot{gap:4px;padding:14px 6px 12px;
 justify-content:center;min-height:92px}
body.csb-rm-page .csb-rm .sboard .t .num{font-weight:800;font-size:30px;
 line-height:1;color:#fff;letter-spacing:-.02em;padding:14px 0 6px;
 text-shadow:0 2px 8px rgba(0,0,0,.5);display:block;width:auto;height:auto;
 background:none;border:0;border-radius:0}
body.csb-rm-page .csb-rm .sboard .t .num small{font-size:20px;
 color:rgba(255,255,255,.55);margin-right:1px;letter-spacing:0}
/* yours keeps R3a's yellow, and the number goes with it */
body.csb-rm-page .csb-rm .sboard .t.yours .num{color:var(--yel)}
body.csb-rm-page .csb-rm .sboard .t.yours .num small{color:rgba(245,197,24,.6)}

/* SPEC 36 L30 — THE UNSOLD CELLS, drawn from the first paint so the
 * board is its final height before a single spot sells. Sam asked for
 * this on the admin screen, where a board growing a row mid-break pushes
 * the section below it into camera; it comes to the room on his own note
 * that "those changes could apply to the Break Room" — a customer
 * watching the board jump is not better off either.
 *
 * BLANK IS THE POINT. The note above says there were no open tiles at
 * all, because "you can't buy a number" and a dashed "open #19" invites
 * somebody to try. A dim cell with nothing in it says how big the break
 * is without offering anything: no number, no name, the same border.
 *
 * .spots, not .sboard — spotBoard() adds it, and revealBoard() takes it
 * off again, so a draft reveal keeps its own grid. Eight across matches
 * the admin screen and stops auto-fill changing the row count with the
 * window.
 *
 * FOUR ON A PHONE, which is L30's own number ("ceil(total/4) rows") and
 * one more than the picked board gets. A spot cell is a number, not a
 * logo and a name, so it does not need a team tile's width — and the
 * picked board keeps its three, untouched. */
body.csb-rm-page .csb-rm .sboard .t.spot.empty{opacity:.35}
body.csb-rm-page .csb-rm .sboard.spots{grid-template-columns:repeat(8,minmax(0,1fr))}
@media (max-width:860px){
 body.csb-rm-page .csb-rm .sboard.spots{grid-template-columns:repeat(4,minmax(0,1fr))}
}

/* The stepper, where R3a's "Buy teams →" link sits on a picked break.
 * csb_room_spot_buy() prints the Still open rail's own markup, so this
 * only has to place it — the rail's rules come from break-room.css. */
body.csb-rm-page .csb-rm .status .spotbuy{margin-left:auto;display:flex;
 align-items:center;gap:8px;flex-wrap:wrap}
body.csb-rm-page .csb-rm .status .spotbuy[hidden]{display:none}
/* CENTRE, DO NOT STRETCH (Todd, Oct 24: "button text isn't vertically
 * centered and seems to be the wrong size").
 *
 * .qrow is a flex row and its default align-items is `stretch`, so the
 * button was pulled to the stepper's full height — 51px — while its
 * own text stayed on the first line. Measured: a 34px button in a 51px
 * box, text ~8px above centre. */
body.csb-rm-page .csb-rm .status .spotbuy .qrow{margin:0;gap:8px;align-items:center}
/* v30 line 70: `.status .buy{border-radius:10px;padding:8px 14px;
 * font-weight:800;font-size:13px}`. The size was already right; the
 * WEIGHT was the miss — without it Bootstrap's `.btn{font-weight:400}`
 * won and the bar's button came out light where the rail's is 900.
 * display:flex so the label is centred in whatever height the row
 * settles at, rather than sitting on its own baseline. */
body.csb-rm-page .csb-rm .status .spotbuy .btn.add{margin:0;padding:8px 14px;
 font-size:13px;font-weight:800;line-height:1.2;border-radius:10px;
 display:inline-flex;align-items:center;justify-content:center;
 white-space:nowrap}
/* AND THE STEPPER COMES DOWN TO MEET IT. break-room.css sizes .qty for
 * the Still open CARD, where the control is the whole bottom of a tile;
 * in the bar it is one item in a row of text. v30's is 36px tall
 * (line 69: `.stp button{width:34px;height:36px}`). */
body.csb-rm-page .csb-rm .status .spotbuy .qrow .qty{height:36px;align-items:center}
body.csb-rm-page .csb-rm .status .spotbuy .qrow .qty button{width:30px;height:34px;
 font-size:16px;line-height:1;padding:0}
body.csb-rm-page .csb-rm .status .spotbuy .qrow .qty b{min-width:24px;font-size:14px}

/* THE RANDOMIZING AND FINAL BOARD IS STILL THE ROOM'S BOARD.
 *
 * R3b says the randomizing board is "exactly what show_teams() in
 * cardsmiths-breaks.js does today" — which is about the MECHANISM, the
 * tiles keyed by slug with the name rewritten each round, not about the
 * paint. Read as "leave that board alone" it left the two states a
 * break night actually spends its time in — randomizing and final —
 * with bare tiles on a flat panel while every other board in the room
 * carried the product colour. Todd, Oct 24: "still seeing a lot of
 * missing colors".
 *
 * The tile is #all-teams' own .team / .team-multi, so this gives those
 * the same surface the mockup's .t has. The ids are here because the
 * legacy sheet keys on them and an id beats any number of classes. */
body.csb-rm-page .csb-rm #all-teams .team,
body.csb-rm-page .csb-rm #all-teams .team-multi{
 background:linear-gradient(180deg,rgba(var(--washrgb,28,33,38),.22),
  rgba(var(--washrgb,28,33,38),.08));
 border:1px solid rgba(var(--washrgb,39,45,52),.35);border-radius:12px;
 padding:12px 6px 10px;align-items:center;text-align:center;
 /* the corner number anchors to this */
 position:relative}

/* THE BAR'S BUY CONTROL GETS THE CARD'S "ADDED" STATE.
 * css/redesign/break-room.css keys those rules on `.spotcard.done` —
 * right for the Still open rail, which is where the mockup had the only
 * stepper. The Current Break bar's control is a bare `.spotbuy` span, so
 * it needs the same three rules said about it. The sheet is generated
 * from the mockup and not hand-edited, so they live here. */
body.csb-rm-page .csb-rm .spotbuy.done .qrow,
body.csb-rm-page .csb-rm .spotbuy.done .btn{display:none!important}
body.csb-rm-page .csb-rm .spotbuy.done .added{display:block}
/* inline in a status row, not stacked inside a card — and the SAME
 * height as the button it replaces, or the whole row jumps 8px the
 * moment a spot goes in the cart. */
body.csb-rm-page .csb-rm .spotbuy .added{margin:0;padding:8px 14px;font-size:13px;
 font-weight:800;line-height:1.2;border-radius:10px;white-space:nowrap}

/* YOUR BREAKS TONIGHT — v30 index.html lines 82-86.
 *
 * The third block of mockup rules the generated sheets never carried:
 * grep `.night` across css/redesign/*.css finds nothing. Same story as
 * `.status .big em` and the chips — these are the rules for markup the
 * room had not built yet, so nothing noticed they were missing.
 *
 * Copied as the mockup has them, with --wash spelled the way the rest
 * of this bridge spells it. */
/* SPEC 36 L35 — AN EQUAL-WIDTH CARD GRID (Todd, Oct 25: four breaks and
 * "the label sits inline beside a wrapping row of unequal-width chips, so
 * row one is short, row two wide, label stranded").
 *
 * The mockup's own rules, which is what was here, are a flex line of
 * inline chips capped at 300px: fine for the two breaks it was drawn
 * with and incoherent at four, because every chip is as wide as its own
 * title and the label is just the first item on the line.
 *
 * THE GRID IS .night ITSELF and the label spans it. A wrapper around the
 * cards would have been the obvious move and is one element more than
 * this needs — `grid-column:1/-1` puts the label on its own line and
 * leaves the markup almost where it was. auto-fill at a 240px minimum is
 * the same shape the queue uses, so the two read as one page.
 *
 * EQUAL HEIGHT COMES FREE. Grid items stretch to their row, so a card
 * with a two-word title is as tall as one with a long one — which is the
 * thing that looked broken. */
body.csb-rm-page .csb-rm .night{margin-top:8px;display:grid;
 grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:8px;font-size:12.5px}
body.csb-rm-page .csb-rm .night .lbl{grid-column:1/-1;font-size:11px;font-weight:800;
 letter-spacing:.1em;color:var(--mut);text-transform:uppercase;margin:0 0 2px}
/* min-width:0 is what lets the title below actually ellipsise: a grid item's
 * default min-width is auto, which is wide enough for its longest word. */
body.csb-rm-page .csb-rm .night .nb{display:flex;flex-direction:column;gap:3px;
 border:1px solid var(--line);border-radius:10px;padding:8px 11px;
 background:var(--s1);color:var(--ink);text-decoration:none;min-width:0}
/* NOW · UP NEXT · 3RD — the ordinal this row has always carried, as a pill
 * instead of a middot-joined prefix on the holdings line. */
body.csb-rm-page .csb-rm .night .nb em{font-style:normal;font-size:10px;font-weight:800;
 letter-spacing:.08em;text-transform:uppercase;color:var(--mut);align-self:flex-start}
body.csb-rm-page .csb-rm .night .nb b{font-size:12.5px;white-space:nowrap;
 overflow:hidden;text-overflow:ellipsis;min-width:0}
body.csb-rm-page .csb-rm .night .nb span{color:var(--mut);font-size:11.5px;
 white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
/* the one that is on now wears the room's yellow, like every other
 * "this is the live one" on the page */
body.csb-rm-page .csb-rm .night .nb.now{border-color:var(--yel)}
body.csb-rm-page .csb-rm .night .nb.now em{color:var(--yel)}
body.csb-rm-page .csb-rm .night .nb:hover{border-color:var(--teal)}
/* One column on a phone: 240px of card and a 390px screen is one card and
 * a gap, so auto-fill would do this anyway — said out loud because the row
 * asks for it and because a future minimum must not quietly change it. */
@media (max-width:700px){
 body.csb-rm-page .csb-rm .night{grid-template-columns:1fr}
}

/* THE "YOUR SPOTS" CHIPS — v30 index.html lines 75-78.
 *
 * Those four rules are in the mockup and in NEITHER generated sheet:
 * grep `.chip` across css/redesign/*.css finds nothing, so the strip
 * had no styling to fall back on and rendered as run-together text,
 * "#1Spot 1#2Spot 2". `.mine` is one of the class names that collides
 * with the theme's own, which is the likely reason the scoping tool
 * never carried this block over.
 *
 * Copied as the mockup has them, with --wash spelled the way the rest
 * of this bridge spells it. */
body.csb-rm-page .csb-rm .mine .chips{display:flex;gap:8px;flex-wrap:wrap}
/* AND THE TILE ROW REALLY GOES WHEN THE CHIPS ARE UP. `.row{display:flex}`
 * outranks the plain `[hidden]` rule, so hiding #my-teams by attribute
 * left all five board tiles on screen with the chips underneath them. */
/* TWO IDS, to match the grid rule above — a one-id selector loses to it
 * and the row would never hide. */
body.csb-rm-page .csb-rm #mine #my-teams[hidden]{display:none!important}
body.csb-rm-page .csb-rm .mine .chip{display:inline-flex;align-items:center;
 gap:7px;border:1px solid var(--line);background:var(--s1);
 border-radius:999px;padding:4px 10px 4px 4px;font-size:13px;font-weight:700}
body.csb-rm-page .csb-rm .mine .chip img,
body.csb-rm-page .csb-rm .mine .chip .ini{width:26px;height:26px;
 border-radius:50%;object-fit:contain}
body.csb-rm-page .csb-rm .mine .chip .ini{
 background:rgba(var(--washrgb,39,45,52),.35);color:var(--ink);
 display:inline-flex;align-items:center;justify-content:center;
 font-size:11px;font-weight:800}

/* THE STATUS LINE'S SECOND TONE.
 *
 * v30 line 65: `.status .big em{font-style:normal;color:var(--mut);
 * font-weight:600;font-size:14px;margin-left:4px}` — the muted clause
 * after the bold head, in every state. The generated sheet never
 * carried it (grep `.status .big` in css/redesign/break-room.css finds
 * the two size rules and no em), and BIG() returned one flat string
 * written with textContent, so there was nothing to style anyway.
 * Both halves exist now. */
body.csb-rm-page .csb-rm .status .big em{font-style:normal;color:var(--mut);
 font-weight:600;font-size:14px;margin-left:6px}

/* WHICH ROUND IS RUNNING. v30 line 135 paints a finished round teal and
 * the live one yellow; the generated sheet paints BOTH yellow, so the
 * bar could not show where the draw had got to — eight identical
 * lozenges, one of them pulsing. Teal is also the colour the meter
 * beside it already uses for "done". */
body.csb-rm-page .csb-rm .rounds i.done{background:var(--teal)}

/* AND IT LOOKS TAPPABLE. v30 line 105: `.t .lg,.t .nm{cursor:pointer}`
 * with `.t:hover .nm{color:var(--teal);text-decoration:underline;
 * text-underline-offset:3px}`. Neither reached this board — a grep for
 * a cursor declaration inside the .csb-rm scope finds nothing — so even
 * once the anchor worked there was no sign it would. Only on a tile
 * that really has a checklist behind it. */
body.csb-rm-page .csb-rm #all-teams a.checklistlink,
body.csb-rm-page .csb-rm #all-teams a.checklistlink .player-name,
body.csb-rm-page .csb-rm #all-teams a.checklistlink .team-icon,
body.csb-rm-page .csb-rm #all-teams a.checklistlink .team-icon-multi{cursor:pointer}
body.csb-rm-page .csb-rm #all-teams a.checklistlink:hover .player-name{
 color:var(--teal);text-decoration:underline;text-underline-offset:3px}

/* THE SPOT NUMBER IN THE CORNER — the mockup's `.t .tag` (index.html
 * line 128), which says which spot this team landed on.
 *
 * Muted and small on purpose: it is the quiet fact on the tile. The
 * logo, the team and the buyer are what a room full of people is
 * reading; the number is for the one person checking their spot. It is
 * only ever drawn when the draw actually recorded a spot. */
body.csb-rm-page .csb-rm #all-teams .csb-tag{
 position:absolute;top:6px;left:8px;z-index:2;
 font-size:10.5px;font-weight:800;letter-spacing:.04em;
 line-height:1;color:var(--mut);pointer-events:none}
/* on your own tile it reads against the yellow, like everything else */
body.csb-rm-page .csb-rm #all-teams .team.mine .csb-tag,
body.csb-rm-page .csb-rm #all-teams .team-multi.mine .csb-tag{color:#111}
/* THE NAME SITS UNDER THE LOGO, not across it.
 * breaks.css draws .player-name as an absolutely-positioned black band
 * over the top of .team-icon-multi — right for a random-PLAYER board,
 * where it labels the team logo with the player. The name this script
 * adds for a TEAM board is the tile's own name, so it reads where the
 * mockup puts it: under the picture, above the buyer. */
/* TWO LINES, ALWAYS — reserved whether the name needs them or not.
 *
 * Todd, Oct 24: "team names in the results need to assume and clip at 2
 * lines so that the customer names don't keep floating up and down in
 * relation to each other."
 *
 * A one-line name was 14px tall and a wrapped one 29px, so inside a
 * single row of the board the buyer under a short name sat 15px higher
 * than the buyer beside it. Measured on break 867297: three rows, each
 * with its nicknames at two different tops.
 *
 * The mockup already answers this — index.html line 188 has exactly
 * this clamp — but only inside its (max-width:860px) block, where it
 * was reached for as a phone fix. The jitter is not a phone problem:
 * it happens at any width the moment one name in a row wraps. So the
 * rule comes out of the media query and applies everywhere.
 *
 * -webkit-line-clamp brings its own ellipsis, so text-overflow goes. */
body.csb-rm-page .csb-rm #all-teams .player-name.csb-named{
 position:static;background:none;color:var(--ink);font-weight:700;
 font-size:12.5px;line-height:1.2;width:100%;max-width:150px;
 padding:0;margin:0;white-space:normal;overflow:hidden;
 display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
 height:auto;min-height:30px;
 text-shadow:none;z-index:auto;order:2}
/* the icon before it, the buyer after it */
body.csb-rm-page .csb-rm #all-teams .team-multi .link,
body.csb-rm-page .csb-rm #all-teams .team .link{display:flex;flex-direction:column;
 align-items:center;gap:5px}
body.csb-rm-page .csb-rm #all-teams .team-icon,
body.csb-rm-page .csb-rm #all-teams .team-icon-multi{order:1}


/* THE BUYER'S NAME IS YELLOW IN EVERY STATE (Todd, Oct 26: "the customer
 * name isn't showing yellow on the final board although it is during the
 * random. User name should stay yellow the whole time").
 *
 * It used to be yellow ONLY under .csb-s-randomizing, where v30 meant it
 * as a signal: while the random is still running the names are
 * provisional and move every round until the eighth, so the yellow said
 * "this will change" in the one place a buyer is looking. The moment the
 * board settled the name dropped back to --ink and the colour a buyer had
 * been tracking for eight rounds went away at the exact instant it became
 * the answer.
 *
 * So the yellow stops being a state signal and becomes what the buyer
 * line is. The icons keep their dimming below — THAT is now the only
 * thing saying a round is still provisional, which is the right place for
 * it: the tile is what is changing, not the person who bought it.
 *
 * The colour is set on the base rule further down rather than here, so
 * there is one declaration for it instead of two fighting on specificity.
 * This block keeps only the icon dimming. */
body.csb-rm-page .csb-rm.csb-s-randomizing #all-teams .team-icon,
body.csb-rm-page .csb-rm.csb-s-randomizing #all-teams .team-icon-multi{opacity:.85}
/* THE BUYER'S LINE IS TEXT, NOT A PILL (Todd, Oct 24: "and customer
 * name borders").
 *
 * Both tile templates carry `class="nickname pn"`, and
 * css/redesign/break-room.css draws `.pn` as a bordered pill: 15px
 * white inside a 1.5px #cfd6da outline with its own padding and a
 * radius. THAT CLASS IS NOT IN THE v30 MOCKUP ANYWHERE — it is left
 * over from the older board that sheet was generated from. v30 draws
 * the buyer as plain text under the name (index.html line 106):
 *
 *     .t .who{font-size:11.5px;color:var(--mut);…}
 *     .t .who b{color:var(--ink);font-weight:700}
 *
 * so the box, the outline and the white all go. `.nickname` holds the
 * name itself rather than wrapping it in a <b>, so the whole line
 * takes what the mockup gives the <b>.
 *
 * The ids are here because breaks.css keys on them and an id beats any
 * number of classes — the same reason every other rule in this block
 * carries one. Killing the background also undoes break-room.css's
 * `body.u--in .csb-rm .tl.mine .pn{background:var(--yel)}`, which is
 * what made a buyer's own name white-on-yellow: on a .mine tile the
 * YELLOW TINT IS THE TILE'S, exactly as v30's .t.yours has it, and the
 * name just stays readable on top of it. */
body.csb-rm-page .csb-rm #all-teams p.nickname{
 border:0;border-radius:0;background:none;box-shadow:none;
 padding:0;margin:4px 0 0;min-height:0;
 font-size:11.5px;font-weight:700;line-height:1.25;
 /* --yel in every state, not just while the random runs — see the note
  * on the .csb-s-randomizing block above. On a .mine tile this reads
  * against rgba(245,197,24,.10) over --s1, which is a 10% tint on a dark
  * surface, not a yellow fill: the name stays legible and the tile's own
  * tint is still what marks it as yours. */
 color:var(--yel);width:100%;max-width:150px;
 white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
 /* picture, name, buyer — the buyer last */
 order:3}
/* A COMBO IS "Texas Rangers + Washington Nationals" — the long case the
 * two-line box above is sized for, and the class the script now puts on
 * only when the tile really carries two teams. It must NOT change the
 * line box: a different line-height here is a different tile height,
 * which is why min-height above is a px value, not an em: the smaller
 * font below still has to produce the same box. Left as a hook for the
 * wash and for anything that wants to find a combo in the DOM. */
body.csb-rm-page .csb-rm #all-teams .player-name.csb-named.csb-combo{
 white-space:normal;font-size:11.5px;line-height:1.3}

/* yours keeps the yellow it already had, over the wash */
body.csb-rm-page .csb-rm #all-teams .team.mine,
body.csb-rm-page .csb-rm #all-teams .team-multi.mine{
 background:rgba(245,197,24,.10)}

/* SPEC 33 R3c — THE DRAFT REVEAL BOARD. One tile per PICK, so a spot
 * that picks twice is two tiles and never one. Pick number on top, then
 * the team, then who got it; unrevealed is a dashed "?" with no name. */
body.csb-rm-page .csb-rm .sboard .t.pick{gap:5px;padding:10px 6px}
body.csb-rm-page .csb-rm .sboard .t.pick .pk{font-size:11px;font-weight:800;
 letter-spacing:.08em;text-transform:uppercase;color:var(--mut)}
body.csb-rm-page .csb-rm .sboard .t.pick .pk b{color:var(--ink);font-size:13px}
/* .lgs so a combo pick is two logos side by side, not one picture that
 * has to be both teams */
body.csb-rm-page .csb-rm .sboard .t.pick .lgs{display:flex;gap:4px;
 justify-content:center}
/* L17 again: the reveal board's logos are square too, and this is the
 * board Sam's "H" was on. `.lg.q` below is the dashed "?" and declares
 * its own border-radius:50% after this rule, so the placeholder stays a
 * circle on purpose — see the note down there. */
body.csb-rm-page .csb-rm .sboard .t.pick .lgs .lg,
body.csb-rm-page .csb-rm .sboard .t.pick .lg{width:52px;height:52px;border-radius:0;
 background:center/contain no-repeat;filter:drop-shadow(0 2px 6px rgba(0,0,0,.45))}
body.csb-rm-page .csb-rm .sboard .t.pick.combo .nm{white-space:normal;line-height:1.15}
/* SPEC 36 L33 — THE LOGO AND THE NAME ARE LINKS NOW, and nothing about
 * the tile may look different for it. break-room.css:24 paints every
 * anchor in the room teal, which on a pick tile would make the team name
 * the one coloured thing on a board of white ones.
 *
 * The hover IS the affordance, and it is the picked board's own —
 * `.pboard .t:hover .nm` has read as a link on hover since R3a, so a
 * draft tile now behaves like the team tile beside it.
 *
 * No display to set: .lgs is flex and .t is a flex column, so an <a> in
 * either is blockified and the sizes above still land on it. */
body.csb-rm-page .csb-rm .sboard .t.pick a.ck{color:inherit;text-decoration:none;cursor:pointer}
body.csb-rm-page .csb-rm .sboard .t.pick a.ck.nm:hover{color:var(--teal);
 text-decoration:underline;text-underline-offset:3px}
/* "your #3 choice" on its own line, under the buyer */
body.csb-rm-page .csb-rm .sboard .t.pick .ch{font-size:11px;color:var(--yel);
 font-weight:700}

/* NOT REVEALED YET — dashed, dimmed, a "?" where the logo goes. */
body.csb-rm-page .csb-rm .sboard .t.pick.unrev{opacity:.75;border-style:dashed;
 border-color:#3a434c;background:var(--s2)}
body.csb-rm-page .csb-rm .sboard .t.pick.unrev .pk{color:var(--dim)}
/* A DASHED CIRCLE IN THE PRODUCT'S OWN WASH, not a grey square.
 *
 * v30 line 143: `.t .q{width:52px;height:52px;border-radius:50%;
 * border:2px dashed rgba(var(--wash),.7);…font:800 20px var(--display);
 * color:var(--mut)}`. Ours was a 10px-radius box with a 1px hardcoded
 * grey edge at 24px/900 — a different shape, a different weight, and
 * the one colour on the tile that did not follow the break's wash.
 *
 * The circle matters more than it sounds: every revealed tile beside
 * it is a round logo, so a square placeholder reads as a different
 * KIND of thing rather than as the same thing not yet turned over. */
body.csb-rm-page .csb-rm .sboard .t.pick .lg.q{display:flex;align-items:center;
 justify-content:center;width:52px;height:52px;
 font-size:20px;font-weight:800;color:var(--mut);
 background:none;filter:none;
 border:2px dashed rgba(var(--washrgb,58,67,76),.7);border-radius:50%}
/* THE BEAT IN BETWEEN: the buyer has landed and their team has not.
 * Full opacity and a yellow edge, because this is the one moment of a
 * draft with any suspense in it and the board should point at it. */
body.csb-rm-page .csb-rm .sboard .t.pick.naming{opacity:1;border-color:var(--yel);
 border-style:solid}
body.csb-rm-page .csb-rm .sboard .t.pick.naming .lg.q{border-color:var(--yel);
 color:var(--yel)}
body.csb-rm-page .csb-rm .sboard .t.pick.naming .pk{color:var(--yel)}

/* SPEC 33 R3a — THE REST OF THE CURRENT BREAK BAR: the when line, the
 * box pill, and the status row's meter, price range and Buy button.
 * Values from specs/mockups/break-room-board/, which is the mockup for
 * this bar; break-room.css already draws .cur, .status and .big. */
body.csb-rm-page .csb-rm .cur .when{font-size:14px;color:var(--ink);font-weight:700;
 margin-top:4px}
body.csb-rm-page .csb-rm .cur .when small{color:var(--mut);font-weight:400;
 margin-left:8px;font-size:13px}
body.csb-rm-page .csb-rm .cur .pill.grey{background:var(--s3);color:#c8d2d7}
/* The meter is the one thing in the row that should take the slack, so
 * the Buy button stays hard right whatever the line beside it says. */
body.csb-rm-page .csb-rm .status .meter{flex:1;min-width:160px;height:8px;
 border-radius:99px;background:var(--s3);overflow:hidden}
body.csb-rm-page .csb-rm .status .meter > i{display:block;height:100%;
 background:var(--teal);border-radius:99px}
body.csb-rm-page .csb-rm .status .meter[hidden]{display:none}
body.csb-rm-page .csb-rm .status .range{color:var(--mut);font-size:13px;white-space:nowrap}
body.csb-rm-page .csb-rm .status .range:empty{display:none}
body.csb-rm-page .csb-rm .status .buy{margin-left:auto;background:var(--yel);
 color:#111;border-radius:10px;padding:8px 14px;font-weight:800;font-size:13px;
 border:0;text-decoration:none;white-space:nowrap}
body.csb-rm-page .csb-rm .status .buy:hover{filter:brightness(1.08);color:#111}
body.csb-rm-page .csb-rm .status .buy[hidden]{display:none}

/* SPEC 33 R1 — THE TYPE PILL IN THE CURRENT BREAK BAR.
 *
 * Sam, Oct 23: the room "has no idea what kind of break it's displaying".
 * The pill is the break page's own string; this is only its box.
 *
 * NOT IN THE GENERATED SHEET, which is why it is here. css/redesign/
 * break-room.css is pages/css/break-room.css scoped, and that mockup's
 * bar has no pill — the one that does is Sam's newer
 * specs/mockups/break-room-board/, which is the mockup for THIS bar. The
 * values below are its .pill / .pill.type, so when the room mockup picks
 * the pill up these can go and the generated sheet will carry them.
 *
 * THE SOLID TEAL IS THAT MOCKUP'S, and it differs from the break page's
 * own pill (.csb-bp .pill.type is --tealdk behind --teal text). R1 says
 * "same words", not same paint, and the room's bar is a darker, denser
 * strip than the break page hero. Worth knowing they are deliberately
 * two looks rather than a drift.
 *
 * .lbl becomes the mockup's .eyebrow row: the label and the pill on one
 * line, wrapping on a phone rather than squeezing the pill. */
body.csb-rm-page .csb-rm .cur .lbl{display:flex;align-items:center;gap:10px;
 flex-wrap:wrap}
body.csb-rm-page .csb-rm .cur .pill{display:inline-block;border-radius:999px;
 padding:3px 9px;font-size:11px;font-weight:800;letter-spacing:.08em;
 text-transform:uppercase;white-space:nowrap}
body.csb-rm-page .csb-rm .cur .pill.type{background:var(--teal,#15ccad);color:#07211b}
/* The script hides it when a break has no pill; [hidden] has to beat the
 * inline-block above, the same lesson as .links[hidden] further up. */
body.csb-rm-page .csb-rm .cur .pill[hidden]{display:none}

/* =========================================================================
 * SPEC 36 L1 — THE TITLE ROW, AND THE WASH THAT WAS A SQUARE SLAB.
 *
 * Sam, Oct 25: "Break Room is so close to the border... why is that box
 * square on the top left corner and everything else rounded?"
 *
 * The box was `body.w--on .csb-rm .page` (css/redesign/break-room.css:74):
 * a 1400x760 radial wash painted on the page wrapper, which is a plain div
 * with no border-radius, so the product colour arrived as a hard-cornered
 * slab with the h1 sitting on its edge. The wash moves INTO the rounded
 * cards — the same treatment the break page gives its hero card — and the
 * page surface goes back to the site's black (.csb-rm{background:#000}
 * sits under it, so transparent here is black, not white; the only pixel
 * delta is #0b0d10 to #000).
 *
 * The h1 was the theme's grey. style.css:1968 paints bare headings
 * `.dark-mode h1..h6{color:#999}` with no media query around it, and the
 * mockup sheet gives .csb-rm .titlerow h1 no colour of its own, so #999
 * beat the inherited --ink. Naming the colour at (0,3,1) settles it from
 * here rather than touching that shared rule.
 *
 * These are the As Built fix sheet's rules
 * (specs/mockups/as-built-oct25/fix/break-room.css) apart from the added
 * body.csb-rm-page scope, so Sam's preview and the shipped page cannot
 * drift. The two rules in that file this does NOT copy are the frame and
 * the player height: both had to be edited into the rules above instead,
 * because a media query adds no specificity and the fix sheet's (0,2,1)
 * selectors lose to the (0,4,1) bridge rules that are already there.
 *
 * Load order is the whole argument for the three (0,3,1) rules below:
 * this file is enqueued with css/redesign/break-room.css as a dependency
 * (template-livestream.php:187-198), so an equal-specificity rule here
 * wins, and these go at the end of the file so they are its last word.
 * ========================================================================= */
body.csb-rm-page .csb-rm .titlerow{margin:22px 0 14px}
body.csb-rm-page .csb-rm .titlerow h1{color:#fff}
/* The tagline span is deleted from the template — site copy states facts,
 * and "every break, as it runs" is a slogan. This is the belt and braces:
 * break-room.css is generated from the mockup and only hides .was below
 * 600px, so a regenerate cannot put it back on screen. */
body.csb-rm-page .csb-rm .titlerow .was{display:none}
/* NO SLAB, IN EITHER STATE — the second half of the selector list ties
 * break-room.css:74 and wins on order, the first ties :46. */
.csb-rm .page,body.w--on .csb-rm .page{background:transparent}
/* The wash, inside the cards' own 12px radius. The player rule also
 * outranks `.csb-rm .l--off .player`'s grey gradient (break-room.css:63,
 * equal specificity, earlier file), so the OFFLINE card is where this is
 * actually visible: when the stream is up the Twitch iframe is forced
 * width/height:100%!important over the whole box. */
body.w--on .csb-rm .player{background:radial-gradient(900px 420px at 50% 30%,rgba(var(--washrgb,43,93,143),.45),var(--s1) 75%);border-color:rgba(var(--washrgb,43,93,143),.6)}
body.w--on .csb-rm .cur{background:linear-gradient(180deg,rgba(var(--washrgb,43,93,143),.28),var(--s1) 85%);border-color:rgba(var(--washrgb,43,93,143),.55)}

/* =========================================================================
 * SPEC 36 L2 — THE CURRENT BREAK IS IN "STILL OPEN" TOO, AND SAYS SO.
 *
 * The rail used to be handed the current break as $skip, so the one open
 * break Sam had selected was the one open break the room would not sell.
 * It is now pinned first by csb_room_breaks()'s $first and carries the
 * Current Break bar's own label, from csb_room_current_tag().
 *
 * The pill copies that bar's label typography verbatim — break-room.css:79
 * `.csb-rm .cur .lbl` is 11px/800 with .14em tracking — but in the yellow
 * of the bar's own 5px left border (:74) rather than --mut, because here
 * it has to carry the "this is the one on screen" job on its own. The
 * card's border takes the same yellow, the minimum that makes the pin
 * legible as a pin rather than a sort accident.
 *
 * No !important needed: break-room.css styles .bcard .nm / .ty / .spots
 * and has no .curtag or .iscur rule at all, and this sheet is enqueued
 * with csb-break-room as its dependency so it loads after.
 * ========================================================================= */
body.csb-rm-page .csb-rm .bcard .curtag{font-size:11px;font-weight:800;
 letter-spacing:.14em;color:var(--yel);margin-bottom:2px}
body.csb-rm-page .csb-rm .bcard.iscur{border-color:var(--yel)}

/* =========================================================================
 * SPEC 36 L1 — THE OTHER BARE HEADINGS ON THIS PAGE
 *
 * L1 named the h1 and only the h1, and the rule above fixes that one. But
 * `.dark-mode h1..h6{color:#999}` (style.css:2043, no media query) paints
 * every bare heading, and the mockup sheet gives none of these a colour:
 * `.csb-rm .bhelp h2` is the board heading L18 renames to "The teams", and
 * `.csb-rm .sechd h2` is "Up next" and "Still open". So the page shipped a
 * white "Break Room" with three grey 21px headings under it — the same
 * defect L1 reports, on the elements it did not list.
 *
 * Measured on /break-room/ in headless Chrome over CDP, by deleting the
 * rule below at runtime and re-reading the computed colour: #bdh ("The
 * teams") and .sechd h2 ("Still open") both go to rgb(153,153,153) while
 * the h1 stays rgb(255,255,255). With the rule in place all three are white.
 *
 * Same (0,3,1) argument and same load order as the title rules above.
 * ========================================================================= */
body.csb-rm-page .csb-rm .bhelp h2,
body.csb-rm-page .csb-rm .sechd h2{color:#fff}

/* ═══ SPEC 36 L31 — THE QUEUE ═══════════════════════════════════════════
 *
 * The two card groups are gone. "Up next" was six tiles of huge box art
 * and "Still open" six cards below it; between them they were most of a
 * screen, they were capped at six, and on the admin Current Break they
 * pushed the board out of camera. One list of 44px rows takes about forty
 * breaks in the space the twelve cards took.
 *
 * ONE SHEET FOR BOTH SURFACES. The admin body carries csb-rm-page as well
 * as csb-rm-admin, so the row shape is written once here and the admin
 * sheet only tightens it. Nothing below is new vocabulary from a mockup —
 * these rows do not exist in one — so every class is .qr-*, which collides
 * with nothing in break-room.css.
 */
body.csb-rm-page .csb-rm .qlist{margin-bottom:28px}

/* GRID, NOT FLEX, and placed by name. The phone layout moves three cells
 * onto a second line and flex cannot say that; naming the areas also means
 * the DOM order is free, which is what lets .qr-meta sit in the markup
 * where it is useful and on screen where L31 wants it. */
body.csb-rm-page .csb-rm .qr{display:grid;align-items:center;
 grid-template-columns:44px minmax(0,1fr) 78px 164px 78px 110px auto;
 grid-template-areas:"art nm ty bar pr dt buy";
 gap:0 12px;padding:5px 10px;border-radius:10px;
 border:1px solid transparent;min-height:54px}
body.csb-rm-page .csb-rm .qr + .qr{border-top:1px solid var(--line,#272d34)}
body.csb-rm-page .csb-rm .qr:hover{background:rgba(255,255,255,.04)}

body.csb-rm-page .csb-rm .qr-art{grid-area:art;width:44px;height:44px;
 border-radius:8px;overflow:hidden;background:rgba(var(--washrgb,39,45,52),.5);
 display:block;flex:0 0 auto}
body.csb-rm-page .csb-rm .qr-art img{width:44px;height:44px;object-fit:cover;display:block}

/* ONE LINE, ELLIPSIS. A break title runs to ninety characters and the
 * row's whole promise is that it is 44px tall; the full title is in the
 * anchor's own title attribute. */
body.csb-rm-page .csb-rm .qr-nm{grid-area:nm;min-width:0;font-weight:700;
 font-size:14.5px;line-height:1.25;color:var(--ink);text-decoration:none;
 white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
body.csb-rm-page .csb-rm .qr-nm:hover{color:var(--teal);text-decoration:underline;
 text-underline-offset:3px}

/* THE LIVE DOT. The row it is on is also washed, because a dot alone is
 * eight pixels on a screen being read from across a room. */
body.csb-rm-page .csb-rm .qr-dot{display:inline-block;width:8px;height:8px;
 border-radius:50%;background:#e2342f;margin-right:7px;vertical-align:middle;
 box-shadow:0 0 0 3px rgba(226,52,47,.22)}
body.csb-rm-page .csb-rm .qr.is-live{background:rgba(226,52,47,.1);
 border-color:rgba(226,52,47,.38)}
/* The CURRENT row keeps the wash — that one IS the break on screen, and
 * matching its product colour is the whole job of --washrgb. */
body.csb-rm-page .csb-rm .qr.is-cur:not(.is-live){border-color:rgba(var(--washrgb,39,45,52),.9);
 background:rgba(var(--washrgb,39,45,52),.14)}

/* .yin is hidden for signed-out visitors by break-room.css; this is the
 * same rule for the same reason — it cannot be true of a guest. */
body.csb-rm-page .csb-rm .qr-yin{display:none;margin-left:8px;font-size:10.5px;
 font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--yel)}
body.u--in .csb-rm .qr-yin{display:inline}

body.csb-rm-page .csb-rm .qr-meta{display:contents}
body.csb-rm-page .csb-rm .qr-ty{grid-area:ty;font-size:11px;font-weight:800;
 letter-spacing:.06em;text-transform:uppercase;color:var(--mut);
 white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
body.csb-rm-page .csb-rm .qr-pr{grid-area:pr;font-size:13px;font-weight:700;
 color:var(--ink);white-space:nowrap;text-align:right}
body.csb-rm-page .csb-rm .qr-dt{grid-area:dt;font-size:12px;color:var(--mut);
 white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* THE FILL BAR IS THE COLUMN SAM READS. Width is sold/total, written as an
 * inline style by the renderer because it is a different number on every
 * row. The count sits beside it rather than under it, so the row stays one
 * line high. */
body.csb-rm-page .csb-rm .qr-bar{grid-area:bar;display:flex;align-items:center;
 gap:8px;min-width:0}
/* A TRACK AND A FILL, two elements. The first cut put the percentage on
 * the bar itself and gave it flex:1 — which grows it to the column and
 * throws the number away, so every break read as full. */
/* THE TRACK IS NEUTRAL, deliberately not --washrgb. The wash is the
 * current break's own product colour, and these breaks run red: the
 * unsold part of every bar came out red, so a half-sold break read as an
 * alert rather than as a break with spots left. A progress track is the
 * absence of progress, not a brand. */
body.csb-rm-page .csb-rm .qr-trk{flex:1 1 auto;min-width:40px;height:7px;
 border-radius:4px;overflow:hidden;background:rgba(255,255,255,.12);
 box-shadow:inset 0 0 0 1px rgba(255,255,255,.06)}
body.csb-rm-page .csb-rm .qr-trk>i{display:block;height:100%;border-radius:4px;
 background:var(--teal,#15ccad)}
body.csb-rm-page .csb-rm .qr-bar>b{font-size:12px;font-weight:800;
 color:var(--mut);white-space:nowrap;font-variant-numeric:tabular-nums}
body.csb-rm-page .csb-rm .qr-bar>em{font-style:normal;font-size:10px;
 font-weight:800;letter-spacing:.07em;color:#0b0d10;background:var(--teal,#15ccad);
 padding:2px 6px;border-radius:5px}
/* FULL is solid: the fill is already 100%, so this is only the colour
 * saying "nothing left" rather than "filling". */
body.csb-rm-page .csb-rm .qr.is-full .qr-trk>i{background:var(--teal,#15ccad)}

body.csb-rm-page .csb-rm .qr-buy{grid-area:buy;display:flex;align-items:center;
 gap:8px;justify-content:flex-end}
body.csb-rm-page .csb-rm .qr-buy:empty{display:none}
/* The stepper is csb_room_spot_buy()'s own markup, printed into the row
 * instead of a card — so this only has to lay it out. */
body.csb-rm-page .csb-rm .qr .qrow{display:flex;align-items:center;gap:8px;margin:0}
body.csb-rm-page .csb-rm .qr .btn,
body.csb-rm-page .csb-rm .qr .qrow .add{padding:7px 14px;font-size:13px;white-space:nowrap}
body.csb-rm-page .csb-rm .qr .added{font-size:12px;white-space:nowrap}

/* TWO LINES ON A PHONE (L31: "thumb + title + fill bar / price + date +
 * Add"). The thumb spans both, so the row still reads as one object. */
@media (max-width:860px){
 body.csb-rm-page .csb-rm .qr{grid-template-columns:44px minmax(0,1fr) auto;
  grid-template-areas:"art nm bar" "art meta buy";gap:6px 10px;min-height:0;
  padding:8px 8px}
 body.csb-rm-page .csb-rm .qr-art{align-self:start}
 body.csb-rm-page .csb-rm .qr-meta{grid-area:meta;display:flex;align-items:center;
  gap:10px;min-width:0}
 body.csb-rm-page .csb-rm .qr-bar{justify-self:end;gap:6px}
 /* THE FULL TAG WAS EATING THE SECOND LINE. Each row is its own grid, so
  * the bar column is sized per row — and a full row's extra tag took it
  * from 92px to 140px, which left the pill reading "DR…" and the date
  * "Fri 1…" while the open row beside it had room for both in full.
  * Measured at 390px: meta 117 on a full row against 165 on an open one. */
 body.csb-rm-page .csb-rm .qr-trk{min-width:44px;max-width:64px}
 body.csb-rm-page .csb-rm .qr-bar>b{font-size:11px}
 body.csb-rm-page .csb-rm .qr-bar>em{font-size:9px;padding:1px 4px}
 /* The pill and the price never shrink — they are three to seven
  * characters and they are what tells two breaks apart. The date takes
  * whatever squeeze is left, because "Wed 10/2…" still reads as a date
  * and "Ra…" does not read as anything. */
 body.csb-rm-page .csb-rm .qr-ty,
 body.csb-rm-page .csb-rm .qr-pr{flex:0 0 auto}
 body.csb-rm-page .csb-rm .qr-dt{flex:0 1 auto;min-width:0}
 body.csb-rm-page .csb-rm .qr-pr{text-align:left}
}
