/* site/app/screens/book.css — the Open play and Courts tabs.
 * Depends on tokens.css, ui.css, shell.css. Reuses .card .list .row .btn .tag .price
 * .avatar .empty .sheet-panel; everything here is the furniture those do not cover.
 *
 * ⚠ NO RAW HEX IN THIS FILE. A colour written here does not follow the palette into dark
 *   mode, and this screen is used courtside at night more than it is used in daylight.
 *
 * Two calendars live here and they are deliberately close relatives:
 *   COURTS   a month of DAYS, where the tint marks what is still OPEN.
 *   PLAY     a month of WEEKS in the News tab's language, one week highlighted.
 * They share the weekday header and the cell metrics so the app has one calendar, drawn
 * twice, rather than two calendars that happen to sit in the same product.
 */

/* ═══ 1 · SHELL ════════════════════════════════════════════════════════════ */

/* ⚠ THE SCREEN IS ITS OWN SIZE CONTAINER, SO THE LAYOUT MEASURES THE FRAME AND NOT THE
   BROWSER WINDOW. The app is drawn inside a phone-width frame; a `@media (min-width: 520px)`
   in here asks the WINDOW how wide it is, so on a tablet the hour grid went to four columns
   inside a 390px frame and every cell came out too narrow to read. A container query asks
   the thing the grid is actually drawn in. Named, so it cannot be captured by a container
   some other file adds later. */
.bk{ container: bk-screen / inline-size; }

.bk .bk-body{ padding-top: 2px; }

/* Every inline SVG sits in one of these. Grid rather than inline-block so the glyph is
   optically centred against the text beside it instead of riding the baseline. */
.bk .bk-glyph, .bk .bk-paid-i{ display: grid; place-items: center; }

/* The mode swap. .enter (tokens.css §8) supplies the entrance; this only owns the box. */
.bk .bk-mode{ display: block; }

/* ⚠⚠ `.sec-note` MOVED TO shell.css AND IS NO LONGER SCOPED TO `.bk`. It lived here from the
   day it was written, and event.js has been rendering the same class name in five section
   headers ever since — every one of them completely unstyled: 16px inherited body type where
   12px uppercase tertiary was intended. Exactly the shape of the `.btn-navy` bug found one
   rule below this one, and found the same way: by asking which screens render a class and
   whether the selector that styles it can reach them. `.sec-note` is a part of `.sec-head`,
   and `.sec`/`.sec-head` are already global. */


.bk .bk-foot{
  margin: 2px 20px 0; padding-bottom: var(--s-4);
  font: 400 12.5px/1.5 var(--font-ui); color: var(--ink-tertiary);
}

/* ⚠⚠ `.btn-navy` MOVED TO ui.css AND IS NO LONGER SCOPED TO `.bk`. It lived here, under this
   screen, from the day it was written — and the day event.js reused the class name for its
   "New match" and "Scan a player" buttons, those two got NO STYLING AT ALL. On Chrome that is
   the UA's grey button and it passes for a quiet variant; on Safari it is a grey button with
   BLUE TEXT, which is the only reason anybody noticed. A screen-scoped rule and an
   app-generic class name is a trap: the name says "use me anywhere" and the selector says
   otherwise, silently. */

.bk .btn.is-off{
  background: var(--bg-sunken); color: var(--ink-tertiary); cursor: default;
}

/* ═══ 2 · THE SHARED CALENDAR FURNITURE ════════════════════════════════════
 * ⚠ THE WEEKDAY HEADER MUST SHARE THE GRID OF THE THING BELOW IT, TO THE PIXEL. Both are
 *   `repeat(7, 1fr)` with the same side padding; letting either one drift by a few pixels
 *   puts every date one column off its letter, which reads as a broken calendar long before
 *   anyone works out why.
 */
.bk .bk-cal-head{
  display: grid; grid-template-columns: repeat(7, 1fr);
  margin: 0 16px 6px;
}
.bk .bk-cal-dow{
  text-align: center;
  font: 600 9px/1 var(--font-ui); letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-tertiary);
}

/* ═══ 3 · COURTS — THE MONTH ═══════════════════════════════════════════════ */

/* The two months on sale. Each carries its own remaining stock as a word, which is the
   fastest answer on the screen: a player who reads "Fully booked" here never opens it. */
.bk .bk-months{ display: flex; gap: 8px; margin: 0 16px 18px; }
.bk .bk-month{
  flex: 1; min-width: 0; cursor: pointer; text-align: left;
  display: flex; flex-direction: column; gap: 3px;
  padding: 11px 13px; border-radius: var(--r-lg);
  background: var(--bg-raised); border: 1px solid var(--rule); color: var(--ink);
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
[data-ready] .bk .bk-month{
  transition: background-color var(--t-press) var(--ease-out),
              border-color var(--t-press) var(--ease-out),
              color var(--t-press) var(--ease-out);
}
.bk .bk-month-n{
  font-family: var(--font-display); font-weight: 600; font-size: 17px; line-height: 1.1;
  letter-spacing: -.014em;
}
.bk .bk-month-s{
  font: 500 11.5px/1.2 var(--font-ui); color: var(--ink-tertiary);
  font-variant-numeric: tabular-nums;
}
/* ⚠ --ink / --bg-raised, NOT --navy / --cream. A selected chip painted raw navy is the same
   colour as the page at night, so the month you had chosen read as a hole and the one you
   had not looked chosen. --ink flips with the theme; the brand constants do not. */
.bk .bk-month[aria-selected="true"]{
  background: var(--ink); border-color: var(--ink); color: var(--bg-raised);
}
.bk .bk-month[aria-selected="true"] .bk-month-s{ color: var(--bg-raised); opacity: .78; }

/* ── The day grid ─────────────────────────────────────────────────────────
 * ⚠ THE OPEN DAYS ARE THE TINTED ONES. Every calendar reflexively marks what is unavailable;
 *   in a month that sells out in a day that paints twenty-six cells and leaves the four that
 *   matter as plain holes. --attn-bg / --attn-ink is the measured pair tokens.css ships for
 *   "a status that has to pull the eye and is not a button" (6.76 light · 8.80 dark), which
 *   is exactly what an opening is. Orange is not available for this: it means "press to pay".
 */
.bk .bk-cells{
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px;
  margin: 0 16px 12px;
}
.bk .bk-cell{
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  min-height: 52px; padding: 6px 2px;
  border-radius: var(--r-md); border: 1px solid transparent;
  background: transparent; color: var(--ink-tertiary);
}
.bk .bk-cell-n{
  font-family: var(--font-display); font-weight: 600; font-size: 16px; line-height: 1;
  letter-spacing: -.02em; font-variant-numeric: tabular-nums;
}
/* ⚠ EVERY CELL CARRIES A WORD, INCLUDING THE DEAD ONES. A hatched square with no word is a
   rendering fault to anyone who has not been told what the hatch means, and the legend
   underneath is read once and then never again. 8.5px is small; it is also uppercase,
   tracked, and only ever four or five characters. */
.bk .bk-cell-w{
  font: 600 8.5px/1 var(--font-ui); letter-spacing: .05em; text-transform: uppercase;
  white-space: nowrap;
}
/* The leading blanks before the 1st. Not a state, so no word and nothing to read. */
.bk .bk-cell.is-blank{ min-height: 52px; }

.bk button.bk-cell{ cursor: pointer; touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
[data-ready] .bk button.bk-cell{
  transition: background-color var(--t-press) var(--ease-out),
              border-color var(--t-press) var(--ease-out),
              color var(--t-press) var(--ease-out);
}

.bk .bk-cell.is-open{ background: var(--attn-bg); color: var(--attn-ink); }
.bk .bk-cell.is-open .bk-cell-n{ color: var(--attn-ink); }

/* ⚠ THE SELECTED DAY IS A FILLED SURFACE THAT FLIPS WITH THE THEME. --selected-bg is cream
   on a navy page and navy on a cream one; a raw brand colour here would vanish into one of
   the two themes, which is the bug tokens.css documents at length. */
.bk .bk-cell.is-on{
  background: var(--selected-bg); color: var(--selected-ink); border-color: var(--selected-edge);
}
.bk .bk-cell.is-on .bk-cell-n{ color: var(--selected-ink); }

/* ⚠ A FULL DAY IS GONE, NOT DISABLED — and in the DOM it is not a button at all. A greyed
   button still reads as a button, so people tap it, get nothing, and tap it harder. */
.bk .bk-cell.is-full{
  background:
    repeating-linear-gradient(135deg, transparent 0 5px, var(--steel-20) 5px 6px);
  color: var(--ink-tertiary);
}
.bk .bk-cell.is-full .bk-cell-n{
  text-decoration: line-through; text-decoration-thickness: 1.5px;
  color: var(--ink-tertiary);
}
/* Open play holds the courts that day. A different answer from "Full", so a different mark —
   but the SAME strike, because both mean there is no private court to be had. Without the
   strike the tint read as availability, and a tinted day you cannot book is the one mistake
   a month view must not make. */
.bk .bk-cell.is-past{ opacity: .45; }

.bk .bk-legend{ display: flex; flex-wrap: wrap; gap: 12px; padding: 0 20px; }
.bk .bk-key{
  display: inline-flex; align-items: center; gap: 6px;
  font: 500 11px/1 var(--font-ui); color: var(--ink-tertiary);
}
.bk .bk-key-sw{
  width: 13px; height: 13px; border-radius: 4px; flex: none;
  border: 1px solid transparent;
}
.bk .bk-key-sw.is-open{ background: var(--attn-bg); border-color: var(--attn-ink); }
.bk .bk-key-sw.is-full{
  background: repeating-linear-gradient(135deg, transparent 0 3px, var(--steel-20) 3px 4px);
  border-color: var(--rule);
}

/* ═══ 4 · COURTS — THE DAY'S HOURS ═════════════════════════════════════════ */

.bk .bk-dayhead{
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 8px; padding: 0 20px 10px;
}
.bk .bk-dayhead-t{
  font: 600 15px/1.2 var(--font-ui); letter-spacing: -.008em; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.bk .bk-daytags{ display: flex; flex-wrap: wrap; gap: 5px; }
.bk .bk-daytags .tag{ font-size: 10px; padding: 4px 7px; letter-spacing: .05em; }

/* ══ THE TIMETABLE ══════════════════════════════════════════════════════════
   Syd, 2026-09-03: "i want you to do the samething as this basically like you see a time
   table and the ability to book mulitple courts at the same time."

   ⚠ ONE CSS GRID, NOT A TABLE AND NOT EIGHT COLUMNS OF DIVS. `grid-auto-flow: row` with a
     fixed template means one pass of appends in book.js lays the whole thing out and nothing
     needs to know its own row or column — which is what keeps the JS a loop over hours inside
     a loop over courts rather than a layout engine.
   ⚠⚠ NOTHING SCROLLS SIDEWAYS. Syd, 2026-09-03: "for the courts i dont want to scroll, i want
     it all to be visible and selectable without needing to scroll at all horizontally." The
     first build made the grid `width: max-content` with 40px columns and let it scroll — 46 +
     8×40 + gaps is 402px against 343px of card at 375px wide. That is the wrong trade for this
     screen: the whole reason a timetable beats a list is that availability reads as a SHAPE in
     one glance, and half a shape behind a scroll edge is a list again, one that also hides
     which courts exist.
     So the columns are `1fr` and the grid fits BY CONSTRUCTION at any width. Every pixel spent
     elsewhere is a pixel off eight cells, which is why the gutter, the gaps and the side
     padding are all as small as they can be and still read:

         width     gutter  gap  padding   cell width
         320px       34     2      10       31.2px
         375px       34     2      10       38.1px
         390px       34     2      10       40.0px

   ⚠ THE CELLS ARE UNDER THE 44px FLOOR — the one place in the app that is true, and it is a
     deliberate trade rather than an oversight. The alternative is fewer courts on screen,
     which is the entire utility being asked for. It is mitigated the way a calendar mitigates
     it: cells are contiguous, so a miss lands on a neighbouring hour or court rather than on
     nothing, the row is 38px tall so the vertical axis stays comfortable, and the summary bar
     states what was picked before any money moves.
   ⚠ THE HOUR COLUMN IS NO LONGER STICKY, because there is nothing left to scroll under it.
     It was `position: sticky; left: 0` with an opaque background; left in place that is a
     paint layer and a stacking context for no reason at all. */
.bk .bk-tt-scroll{ padding: 0 10px 4px; }
.bk .bk-tt{
  display: grid; gap: 2px; width: 100%;
  grid-template-columns: 40px repeat(var(--tt-cols), minmax(0, 1fr));
}

/* ⚠ nowrap, AND THE TRACK IS 40px BECAUSE OF IT. At 34px "10 AM" and "12 PM" broke across two
   lines — and a wrapped label makes that ROW taller than its neighbours, so the grid came out
   with three deep rows in the middle of it and stopped reading as a grid at all. The label is
   the one thing here that must never wrap; six pixels of gutter is the cheapest possible fix
   and it comes out of slack rather than out of the cells. */
.bk .bk-tt-rh{
  display: flex; align-items: center; padding-right: 5px; white-space: nowrap;
  font: 600 10.5px/1 var(--font-ui); letter-spacing: -.01em;
  color: var(--ink-secondary); font-variant-numeric: tabular-nums;
}
.bk .bk-tt-ch{
  display: grid; place-items: center; gap: 1px; padding-bottom: 4px;
}
/* The axis label spans every court column. `grid-column: 2 / -1` rather than a hard number,
   so adding a ninth court is a data change and not a CSS one. */
.bk .bk-tt-axis{
  grid-column: 2 / -1; padding-bottom: 2px;
  font: 700 8.5px/1 var(--font-ui); letter-spacing: .13em; text-transform: uppercase;
  color: var(--ink-tertiary); text-align: center;
}
.bk .bk-tt-ch{ min-width: 0; }
.bk .bk-tt-ch-n{
  font-family: var(--font-display); font-weight: 600; font-size: 14px; line-height: 1;
  color: var(--ink);
}
/* ⚠ 8px, AND IT IS THE FIRST THING THAT WOULD GO. Courts are not all one price — 500 indoor,
   400 covered — so the column head is where that difference is visible without tapping. At a
   31px column "₱500" measures about 20px, which fits; if a ninth court is ever added and it
   stops fitting, drop this line rather than shrinking the cells. */
.bk .bk-tt-ch-p{
  font: 500 8px/1 var(--font-ui); letter-spacing: 0; color: var(--ink-tertiary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

.bk .bk-tt-c{
  display: grid; place-items: center; height: 38px; border-radius: var(--r-sm);
  border: 1px solid transparent; min-width: 0;
}
/* ⚠ THE OPEN CELL CARRIES THE TINT, NOT THE TAKEN ONE — the same inversion the month grid
   uses, and for the same reason: on a busy evening most cells are taken, and colouring those
   paints the whole grid and leaves the few that matter as holes. */
.bk .bk-tt-c.is-free{
  background: var(--attn-bg); border-color: var(--attn-ink); color: var(--attn-ink);
  cursor: pointer; touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
[data-ready] .bk .bk-tt-c.is-free{
  transition: background-color var(--t-press) var(--ease-out),
              border-color var(--t-press) var(--ease-out);
}
.bk .bk-tt-c.is-picked{
  background: var(--selected-bg); border-color: var(--selected-edge); color: var(--selected-ink);
}
.bk .bk-tt-c-i{ display: grid; place-items: center; }
/* Taken: hatched and inert, exactly like a full day in the month grid. Not a disabled button —
   a greyed-out button still reads as a button, so people tap it and tap it harder. */
.bk .bk-tt-c.is-taken{
  background: var(--bg-sunken);
  background-image: repeating-linear-gradient(45deg,
    transparent 0 3px, color-mix(in srgb, var(--ink) 9%, transparent) 3px 4px);
}
/* Open play is a different fact from "somebody booked it", and on this tab it is the one that
   is a reason to come rather than to look elsewhere. Chartreuse is ENERGY, never success. */
.bk .bk-tt-c.is-play{
  background: color-mix(in srgb, var(--live) 22%, transparent);
  border-color: color-mix(in srgb, var(--live) 55%, transparent);
}
.bk .bk-tt-c-w{
  font: 700 8px/1 var(--font-ui); letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-secondary);
}
/* In the legend the cell is a swatch, so it loses its height and its hit affordances. */
.bk .bk-key-sw.bk-tt-c{ width: 15px; height: 15px; border-radius: 5px; cursor: default; }

/* ── Court filter. A custom dropdown, never a native <select> (Syd's standing rule). ── */
.bk .bk-dd{ position: relative; margin: 0 16px 16px; }
.bk .bk-dd-trigger{
  width: 100%; display: flex; align-items: center; gap: 12px; cursor: pointer;
  padding: 13px 16px; border: 0; border-radius: var(--r-lg);
  background: var(--bg-raised); box-shadow: var(--shadow-1); color: var(--ink);
  text-align: left;
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
.bk .bk-dd-lab{ flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.bk .bk-dd-name{ font: 600 16px/1.2 var(--font-ui); letter-spacing: -.008em; color: var(--ink); }
.bk .bk-dd-note{ font: 400 12.5px/1.2 var(--font-ui); color: var(--ink-tertiary); }
.bk .bk-dd-price{ font: 500 13px/1 var(--font-ui); color: var(--ink-secondary); white-space: nowrap; }
.bk .bk-dd-chev{ display: grid; place-items: center; color: var(--ink-tertiary); }
[data-ready] .bk .bk-dd-chev{ transition: transform var(--t-menu) var(--ease-out); }
.bk .bk-dd-trigger[aria-expanded="true"] .bk-dd-chev{ transform: rotate(90deg); }

.bk .bk-dd-menu{
  position: absolute; z-index: 30; top: calc(100% + 6px); left: 0; right: 0;
  background: var(--bg-raised); border-radius: var(--r-lg);
  box-shadow: var(--shadow-3); overflow: hidden;
}
.bk .bk-dd-opt{
  width: 100%; display: flex; align-items: center; gap: 12px; cursor: pointer;
  padding: 12px 16px; border: 0; border-bottom: 1px solid var(--rule);
  background: transparent; color: var(--ink); text-align: left;
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
.bk .bk-dd-opt:last-child{ border-bottom: 0; }
.bk .bk-dd-opt-t{ flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.bk .bk-dd-opt-p{ font: 500 13px/1 var(--font-ui); color: var(--ink-tertiary); }
/* ⚠ THE CHOSEN COURT IS A STATE, NOT THE ACTION. Both of these were --action once, which put
   a second orange thing on a screen whose one orange thing is the pay button — and orange
   text at 13–16px on --bg-raised is the lowest-contrast text on the menu, so the option you
   had selected was the hardest one to read. */
.bk .bk-dd-opt-c{ display: grid; place-items: center; color: var(--ink); }
.bk .bk-dd-opt[aria-selected="true"] .bk-dd-name{ color: var(--ink); font-weight: 700; }

/* Exit is faster than enter, and along the path it entered. */
.bk .bk-dd-menu.is-out{
  opacity: 0; transform: scale(.97) translateY(-3px);
  transition: opacity var(--t-exit) var(--ease-out), transform var(--t-exit) var(--ease-out);
}
@media (hover: hover) and (pointer: fine){
  .bk .bk-dd-opt:hover{ background: var(--bg-sunken); }
  .bk .bk-month:hover, .bk button.bk-cell:hover,
  .bk .bk-tt-c.is-free:hover{ border-color: var(--ink); }
}

/* ── The commit bar. Sticky in the lower third, clear of the floating nav, because the one
 *    button that costs money should be under a thumb rather than at the top of a long page. */
.bk .bk-summary{
  /* Clearance comes from shell.css's --fnav-clear, not a number kept here. The 78px this
     used to say put the bar 2px UNDER the floating nav even before the nav grew — the pay
     button's top edge was behind the glass, on the one control in the app that takes money. */
  position: sticky; bottom: calc(var(--fnav-clear) + 4px); z-index: 20;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 18px 16px 0; padding: 12px 14px;
  border-radius: var(--r-lg);
  background: var(--chrome);
  backdrop-filter: var(--chrome-blur); -webkit-backdrop-filter: var(--chrome-blur);
  border: 1px solid var(--chrome-edge);
  box-shadow: var(--shadow-2);
}
.bk .bk-summary.is-empty{ justify-content: center; }
.bk .bk-summary-empty{
  margin: 0; text-align: center;
  font: 500 13px/1.4 var(--font-ui); color: var(--ink-tertiary);
}
.bk .bk-summary-info{ flex: 1; min-width: 130px; }
.bk .bk-summary-t{ font: 600 15px/1.2 var(--font-ui); letter-spacing: -.008em; color: var(--ink); }
.bk .bk-summary-s{ margin-top: 2px; font: 400 12px/1.3 var(--font-ui); color: var(--ink-tertiary); }
.bk .bk-summary-right{ display: flex; align-items: center; gap: 10px; }
.bk .bk-summary-p{
  font-family: var(--font-display); font-weight: 600; font-size: 20px; line-height: 1;
  letter-spacing: -.02em; color: var(--ink);
}
.bk .bk-summary-go{ padding: 11px 18px; font-size: 15px; }
.bk .bk-summary-max{
  flex-basis: 100%; margin: 0; font: 400 11.5px/1.3 var(--font-ui); color: var(--ink-tertiary);
}
@media (prefers-reduced-transparency: reduce){
  .bk .bk-summary{ background: var(--bg-raised); backdrop-filter: none; -webkit-backdrop-filter: none; }
}

/* ═══ 5 · OPEN PLAY — THE MONTH OF WEEKS ═══════════════════════════════════
 * Built to read as a sibling of news.css: the same sunken tray, the same sprung selection
 * block behind the content, Fraunces on the date, and one bar per session under it. The one
 * difference is the axis — News slides a thumb sideways across seven days, this slides a
 * band down the month, because a week is what gets selected here.
 */
.bk .bk-pcal-head{
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 0 16px 10px;
}
.bk .bk-pcal-t{
  font-family: var(--font-display); font-weight: 600; font-size: 20px; line-height: 1.1;
  letter-spacing: -.016em; color: var(--ink); margin: 0; text-transform: none;
}
/* ⚠ 34px PAINTED, 44px TAPPED — the .tap-min pattern from tokens.css, written out here
   because a month arrow drawn at 44px is a slab beside a 20px month name. */
.bk .bk-navbtn{
  position: relative;
  display: inline-grid; place-items: center; flex: none;
  width: 34px; height: 34px; padding: 0; cursor: pointer;
  border: 0; border-radius: var(--r-full);
  background: var(--bg-sunken); color: var(--ink);
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
.bk .bk-navbtn::after{
  content: ""; position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: var(--tap-min); height: var(--tap-min);
}

.bk .bk-weeks{
  position: relative;              /* the offsetParent the band is measured against */
  margin: 0 16px 4px; padding: 3px;
  background: var(--bg-sunken); border-radius: 14px;
}

/* The sliding selection block. Positioned by JS (a spring), so no transition here — a CSS
   transition on top of a spring fights it and produces two motions at once.
   ⚠ THE SOFT FILL NEEDS THE EDGE. tokens.css measures --selected-soft-bg at 1.27 against the
     page on its own, which is not a selection anyone can see on a sunlit court. */
.bk .bk-band{
  position: absolute; left: 3px; right: 3px; top: 0; height: 0;
  background: var(--selected-soft-bg); border-radius: 11px;
  box-shadow: inset 0 0 0 1.5px var(--selected-edge);
  z-index: 0; will-change: transform;
}

.bk .bk-week{
  position: relative; z-index: 1;
  display: grid; grid-template-columns: repeat(7, 1fr); width: 100%;
  border: 0; background: transparent; cursor: pointer;
  padding: 5px 0; border-radius: 11px;
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
.bk .bk-wcell{
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 3px 0; color: var(--ink-secondary);
}
/* Days belonging to the neighbouring month. Dimmed, never removed: a week row with three
   blank cells at a month boundary reads as a missing week, and the sessions on those days
   are in the list underneath. */
.bk .bk-wcell.is-out{ opacity: .34; }
.bk .bk-wnum{
  font-family: var(--font-display); font-weight: 600; font-size: 15px; line-height: 1;
  letter-spacing: -.02em; font-variant-numeric: tabular-nums;
}
/* Today keeps its own mark inside a selected week, so "this week" and "today" stay two
   different facts. A ring, not a fill — a fill would compete with the week band. */
.bk .bk-wcell.is-today .bk-wnum{
  color: var(--ink); font-weight: 700;
  box-shadow: 0 2px 0 -1px currentColor;
}
.bk .bk-week.is-on .bk-wcell{ color: var(--selected-soft-ink); }
.bk .bk-week.is-on .bk-wnum{ font-weight: 700; }
[data-ready] .bk .bk-wcell{ transition: color var(--t-press) var(--ease-out); }

.bk .bk-bars{ display: flex; gap: 2px; height: 3px; align-items: center; }
.bk .bk-bars i{
  width: 4px; height: 3px; border-radius: 2px;
  background: currentColor; opacity: .5;
}
/* Duos bars are the solid ones. Decoration only — the format is a word on every card below,
   because a player who reads the mark and not the word turns up to a duos night alone. */
.bk .bk-bars i.is-duos{ opacity: .95; }
/* A day with nothing on gets a rule, not an absent mark — an empty slot reads as a bug. */
.bk .bk-bars .bk-bar-none{ width: 8px; height: 1.5px; opacity: .28; }

/* ═══ 6 · SESSION CARDS ════════════════════════════════════════════════════ */

.bk .bk-ses{ padding: 0; overflow: hidden; }

/* ⚠⚠ A STACK, NOT A ROW — AND THE MEASUREMENTS ARE WHY.
 *
 * This was `display:flex` with the when-block beside the kind badge, and raising the day
 * and date to display weight inside that narrow column is what broke the card. Measured on
 * the deployed build, `.bk-day`'s box was 109px at 320px wide and 164px at 375px, because
 * the badge ("FIXED PAIRS" + glyph) takes ~130px off the row before anything else is drawn.
 * What has to fit in it:
 *
 *     "Wednesday 09/02/2026"   169px      → wrapped at BOTH 320 and 375
 *     "6:00 – 9:00 PM"         155px      → overflowed the 109px box by 46px at 320
 *     "11:00 AM – 2:00 PM"     201px      → over by 89px at 320, 34px at 375, 22px at 390
 *
 * so a card read as four stacked lines with the time broken across two of them. The card's
 * height varied 108–159px with nothing but the day name and the meridiem changing.
 *
 * ⚠ THE BADGE CANNOT SHARE A LINE WITH THE DATE AT ANY PHONE WIDTH. It is not a tuning
 *   problem: even shortening its label to "SOLO" leaves 161px beside it at 320px, and the
 *   day and date need 235px. So the badge takes its own line and the two display lines below
 *   it each get the card's full width — 252 / 307 / 322px at 320 / 375 / 390.
 *
 * ⚠ REJECTED, WITH NUMBERS: putting the date and the time together on one line under a
 *   day+badge row. It is one line shorter and it overflows — 274px into 252px at 320, and
 *   319px into 307px at 375 on a session that crosses noon. Measured, not guessed.
 *
 * ⚠ SINCE SUPERSEDED IN PART, AND THE NUMBERS ABOVE ARE WHY IT WORKED. `.bk-day` is gone:
 *   the when-block is now two columns (day over date, time right) and the time is printed
 *   without ":00", so the pair that needed 235px + 201px on separate lines needs about 110px
 *   + 125px on one. What survives unchanged is the finding this block exists to record — the
 *   BADGE still cannot share a line with any of it, at any phone width.
 *
 * The row-1 / row-2 split is the sticker's `.s-top` in ../Community Supply — the marker on
 * the left, the state chip flush right, one baseline — and the reason the time now spans the
 * whole card is the same bug that file records on `.tick-head`: a shared column track sizes
 * every row, including the rows with nothing beside them.
 */
.bk .bk-ses-top{
  display: block;
  width: 100%; text-align: left; cursor: pointer;
  border: 0; background: transparent; padding: 14px 18px 10px;
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}

/* The eyebrow: what kind of session it is, and what state it is in. Two ends of one line,
   so the badge sits above the price and the state tag above the spots-left tag in the foot
   — the card gets two aligned edges instead of four ragged ones. */
.bk .bk-ses-head{
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 10px;
}

/* ── THE WHEN BLOCK · two columns, split by what kind of fact each one is ─────────────────
   LEFT stacks the calendar answer — which day, then which date. RIGHT carries the clock
   answer, big, on the card's right edge directly under the status chip.

   ⚠ THIS IS A REVISION OF A REVISION, AND BOTH MOVES WERE SYD'S. First the date was pushed
     right to sit under the status chip, because the chip left a notch of dead card beneath it.
     Then: *"switch the position of the time and date, date under the day and time right
     aligned but big."* He is right, and the two arrangements are not equivalent: the card's
     right edge is the second thing the eye lands on, so it should hold the fact the card is
     scanned FOR — and between a date and a time, that is the time. "Tuesday / 6 – 9 PM" is
     the card read at a glance. The year is confirmation, not the question.

   ⚠ align-items: BASELINE, and the left column is itself a flex column — so the baseline the
     time shares is the DAY's, and the date hangs below that shared line instead of dragging it
     down. `center` would float the time against the middle of a two-line column and break the
     pairing that makes the row read as one fact. */
.bk .bk-when{
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; min-width: 0;
}
.bk .bk-when-l{ display: flex; flex-direction: column; gap: 2px; min-width: 0; }

/* ⚠⚠ TWO FACTS, TWO TREATMENTS — AND THE FIRST ATTEMPT AT THIS WAS THE BUG.
   Syd asked for the day and the date to be emphasised. They were both raised to the same 20px
   display face, differing only in ink colour, and he came straight back: *"the date and day
   being same font same line same look is super confusing, i want them to be both distinct and
   both visible."* He is right, and the reason is worth keeping written down: TWO ADJACENT
   THINGS IN IDENTICAL TYPE READ AS ONE THING. Emphasis is not the same as equality.

   So the pair splits across the two faces the app already owns, which is the distinction that
   needs no extra ink, weight or rule:
     · the DAY is a word — Fraunces, the display face, full size. It is what people scan for.
     · the DATE is a phrase — Inter, the UI face, smaller and quieter, on the line below.
   Both stay legible; neither is mistaken for the other. Stacking them rather than setting them
   side by side settles that argument for good: they are no longer competing for one line. */
.bk .bk-dow{
  font-family: var(--font-display); font-weight: 600; font-size: 20px; line-height: 1.15;
  letter-spacing: -.018em; color: var(--ink);
}
/* Spelled out, not 09/10/2026 — Syd, 2026-09-03. A heading is read, not scanned in a column,
   and this one now has a line of its own to be read on. `nowrap` because "September 10, 2026"
   broken after "September" reads as two facts. */
.bk .bk-date{
  white-space: nowrap;
  font: 500 14.5px/1.2 var(--font-ui); letter-spacing: .005em;
  color: var(--ink-secondary);
}

/* ⚠⚠ THE TIME ONLY FITS BECAUSE ":00" IS GONE — see rangeHeadline() in book.js.
   The previous layout gave this line the card's full width and the comment here recorded why:
   "11:00 AM – 2:00 PM" is the widest a session time gets and it needs 200px, against 252px of
   card at 320px wide. Sharing that line with a 110px "Wednesday" was therefore impossible at
   any size worth calling big — the time would have had to drop to about 14px, which is the
   opposite of what was asked for. Dropping the empty minutes takes the same string to 131px
   and the pair fits, at a LARGER size than the 22px this line used to be given alone.

   ⚠ 22px AND NOT 24, WHICH IS WHERE THIS FIRST SHIPPED. Measured on the deployed build, the
     worst pair — "Wednesday" beside a session that crosses noon — came to 266px against the
     252px the card has at 320px wide. It looked right on every fixture only because none of
     the fourteen falls on a Wednesday, which is the kind of luck that ships a defect. At
     20/22 with a 10px gap the same pair measures 249px. The numbers, per face:

         face      day 20px    "11 AM – 2 PM" 22px    + 10px gap    fits 252px
         Fraunces    107               131               248            yes
         Georgia*    107               133               250            yes
                                                          *at size-adjust 92% — see fonts.css
   ⚠ `nowrap` stays, and it is still the point. Left to wrap, the old string broke after
     "6:00 – 9:00" and stranded "PM" on a line by itself. */
.bk .bk-time{
  flex: none; text-align: right; white-space: nowrap;
  font-family: var(--font-display); font-weight: 600; font-size: 22px; line-height: 1.15;
  letter-spacing: -.02em; color: var(--ink); font-variant-numeric: tabular-nums;
}

/* ⚠ THE KIND BADGE. Solos and duos never mix, so this is the first thing the eye should
   land on after the time. Two distinct treatments, not two colours of the same shape —
   outlined for solos, filled for duos — plus the word and a glyph, so it survives being
   read in sunlight, by a colourblind player, and by a checker. */
/* ⚠ SMALLER, AND IT NO LONGER STRANDS THE CORNER. Syd, 2026-09-03: "now that the solo entry
   tag is at the top, its too much empty space on the top right of the card (WASTEFUL), make
   it fit, make the tag smaller."
   The tag was 12px/700 with .08em tracking and 12px of side padding — at "FIXED PAIRS" that
   is a 132px pill, so on a 343px card it claimed the entire right-hand column and left a
   band of dead space beneath itself that nothing could use. Dropped to 10.5px with tighter
   tracking and padding it lands near 96px, and .bk-ses-top now lets the text column reclaim
   the width instead of reserving it. The badge is still the loudest single element on the
   card — it is the one thing that makes a wasted trip — it just no longer costs a corner. */
.bk .bk-kind{
  flex: none; display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 9px 5px 7px; border-radius: var(--r-full);
  font: 700 10.5px/1 var(--font-ui); letter-spacing: .05em; text-transform: uppercase;
  align-self: flex-start;
}
.bk .bk-kind-i{ display: grid; place-items: center; }
.bk .bk-kind.is-solos{
  background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--ink);
}
.bk .bk-kind.is-duos{ background: var(--ink); color: var(--bg-raised); }

.bk .bk-meta{
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  padding: 0 18px; font: 400 13px/1.4 var(--font-ui); color: var(--ink-tertiary);
}
.bk .bk-dot{ opacity: .5; }

/* The partner requirement, stated on the card — not discovered at checkout. A LABEL now,
   not the sentence that started RULE ZERO. */
.bk .bk-req{
  display: flex; align-items: center; gap: 8px;
  margin: 10px 18px 0; padding: 8px 11px;
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--warn) 14%, transparent);
  color: var(--warn);
  font: 600 12.5px/1.35 var(--font-ui);
}
.bk .bk-req-i{ display: grid; place-items: center; flex: none; }

.bk .bk-ses-foot{
  display: flex; align-items: center; justify-content: space-between; gap: 8px 12px;
  padding: 12px 18px 16px;
  /* ⚠ THE ROW WRAPS AS A WHOLE OR THE TAG BREAKS IN HALF. "16 pairs left" beside a duos
     price ("₱250 each · ₱500 a pair") overflows a 390px card, and with nothing said here the
     TAG is what wrapped — two lines of half a pill, which reads as a rendering fault. Let the
     tag drop to its own line intact instead. */
  flex-wrap: wrap;
}
.bk .bk-ses-foot .tag{ white-space: nowrap; }
.bk .bk-price{ display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 7px; min-width: 0; }
.bk .bk-price .price{
  font-family: var(--font-display); font-weight: 600; font-size: 22px; line-height: 1;
  letter-spacing: -.02em; color: var(--ink);
}
.bk .bk-per{ font: 400 12px/1 var(--font-ui); color: var(--ink-tertiary); }

/* ⚠ THE QUIETEST OF THE THREE STATES, AND IT IS THE ONE THAT APPEARS MOST.
   "Upcoming" is true of nearly every card in the list, so giving it the filled pill that
   "Past" wears would set the same word in the same badge down the whole screen and add no way
   to tell one card from another — a badge that never varies is decoration, and it would also
   make the two OPPOSITE states look identical, which is the confusion this file already
   records once under the day and the date.
   So the three are ranked by how far each departs from the ordinary case:
     · TODAY    chartreuse, filled, a pulsing dot — the one you might act on right now
     · PAST     a filled grey pill — over, and worth saying so plainly
     · UPCOMING a hairline outline in the secondary ink — present, legible, and silent
   Under `prefers-contrast: more` the outline becomes --ink along with everything else, so the
   quiet version does not become the invisible one. */
.bk .tag.bk-tag-soon{
  background: transparent; color: var(--ink-secondary);
  box-shadow: inset 0 0 0 1px var(--rule);
}
.bk .tag.bk-tag-full{
  background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger);
}
/* Scarcity and the payment window: weight and a word, never the action colour. --warn is a
   different hue from --action in both themes, and a tag is a different shape from a button,
   so neither can be mistaken for the thing you press. */
.bk .tag.bk-tag-low{ color: var(--ink); font-weight: 700; }
.bk .tag.bk-tag-hold{
  background: color-mix(in srgb, var(--warn) 16%, transparent); color: var(--warn);
}
.bk .bk-ses.is-full .bk-time, .bk .bk-ses.is-full .bk-price .price{ color: var(--ink-secondary); }

/* ── The expansion ─────────────────────────────────────────────────────────
 * ⚠ 0fr → 1fr, NOT height. `height: auto` cannot be transitioned and a max-height guess is
 *   wrong at some text size or in some language — this animates to the content's real
 *   height, whatever it turns out to be. Same trick, same reason, as .fnav-lab in shell.css;
 *   it is the one place this project animates something other than transform and opacity,
 *   and it is deliberate rather than an oversight.
 * ⚠ The inner element needs min-height:0 and overflow:hidden or the row refuses to collapse.
 */
.bk .bk-more{ display: grid; grid-template-rows: 0fr; opacity: 0; }
.bk .bk-more-in{ min-height: 0; overflow: hidden; padding: 0 18px; }
.bk .bk-ses.is-open .bk-more{ grid-template-rows: 1fr; opacity: 1; }
.bk .bk-ses.is-open .bk-more-in{ padding-bottom: 18px; }

[data-ready] .bk .bk-more{
  transition: grid-template-rows 240ms var(--ease-out), opacity 160ms var(--ease-out);
}

.bk .bk-facts{ display: flex; gap: 8px; margin-bottom: 10px; }
.bk .bk-fact{
  flex: 1; min-width: 0; padding: 9px 10px;
  background: var(--bg-sunken); border-radius: var(--r-md);
  display: flex; flex-direction: column; gap: 3px;
}
.bk .bk-fact-k{
  font: 600 10px/1 var(--font-ui); letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-tertiary);
}
.bk .bk-fact-v{ font: 500 13px/1.25 var(--font-ui); color: var(--ink); }

.bk .bk-fine{
  margin: 10px 0 0; text-align: center;
  font: 400 12px/1.45 var(--font-ui); color: var(--ink-tertiary);
}

/* ═══ 7 · THE SHEET ════════════════════════════════════════════════════════ */

.bk .bk-sheet{ display: flex; flex-direction: column; max-height: 82%; }
.bk .bk-sheet-body{
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  padding-bottom: 4px;
}
.bk .bk-sheet-h{
  font-family: var(--font-display); font-weight: 600; font-size: 24px; line-height: 1.15;
  letter-spacing: -.018em; margin: 8px 0 0; color: var(--ink);
}
.bk .bk-sheet-p{
  margin: 7px 0 16px; font: 400 14.5px/1.5 var(--font-ui); color: var(--ink-secondary);
}
.bk .bk-sheet-foot{ padding-top: 14px; }
/* ⚠ THE ONLY WAY OUT OF A FLOW WITH A FIVE-MINUTE CLOCK RUNNING, AND IT WAS 39px TALL.
   12px padding either side of a 15px line is 39 — under the 44px floor tokens.css calls "the
   floor, not a target". A missed tap on Cancel is a player jabbing at a sheet while the hold
   timer counts down, which is the worst place in the app to lose a press. */
.bk .bk-cancel{
  display: flex; align-items: center; justify-content: center;
  width: 100%; margin-top: 4px; padding: 12px; cursor: pointer;
  min-height: var(--tap-min);
  border: 0; background: transparent; color: var(--ink-secondary);
  font: 600 15px/1 var(--font-ui); letter-spacing: -.008em;
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}

/* Banners. ⚠ Each carries a WORD as well as a colour — "Not reserved", "Not a ticket",
   "Duos · partner required" — because a coloured strip on its own tells a player nothing. */
.bk .bk-banner{
  display: flex; gap: 10px; align-items: flex-start;
  padding: 12px 13px; border-radius: var(--r-md); margin-bottom: 16px;
}
.bk .bk-banner-b{ display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.bk .bk-banner-w{
  font: 500 12.5px/1.4 var(--font-ui); color: var(--ink-secondary);
}
.bk .bk-banner-i{ flex: none; display: grid; place-items: center; margin-top: 1px; }
.bk .bk-banner.is-req{
  align-items: center;
  background: color-mix(in srgb, var(--warn) 14%, transparent); color: var(--warn);
}
.bk .bk-banner.is-req .bk-banner-w{ color: var(--warn); font-weight: 600; }
.bk .bk-banner.is-hold{ background: var(--bg-sunken); color: var(--ink-secondary); }
.bk .bk-banner.is-urgent{ background: color-mix(in srgb, var(--danger) 12%, transparent); }

.bk .bk-hold-state{ display: flex; align-items: center; gap: 9px; }
.bk .bk-hold-clock{
  font-family: var(--font-display); font-weight: 600; font-size: 19px; line-height: 1;
  letter-spacing: -.01em; color: var(--ink);
}
.bk .bk-banner.is-urgent .bk-hold-clock{ color: var(--danger); }

/* The order summary. Tabular figures so the total lines up under the lines above it. */
.bk .bk-order{
  background: var(--bg-sunken); border-radius: var(--r-md);
  padding: 4px 13px; margin: 16px 0;
}
.bk .bk-order-r{
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  padding: 10px 0; border-bottom: 1px solid var(--rule);
}
.bk .bk-order-r:last-child{ border-bottom: 0; }
.bk .bk-order-k{ font: 500 13.5px/1.35 var(--font-ui); color: var(--ink); }
.bk .bk-order-v{
  font: 400 13px/1.35 var(--font-ui); color: var(--ink-tertiary);
  text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums;
}
.bk .bk-order-r.is-total .bk-order-k{ font-weight: 700; }
.bk .bk-order-r.is-total .bk-order-v{
  font-family: var(--font-display); font-weight: 600; font-size: 20px;
  letter-spacing: -.02em; color: var(--ink);
}

/* Partner rows. The tick lives in the row and only appears when it is chosen — a radio
   circle on every row is six empty circles asking to be counted. */
.bk .bk-group{ margin: 0 0 16px; }
.bk .bk-prow{ cursor: pointer; border: 0; width: 100%; text-align: left; background: transparent; }
/* ⚠ ui.css's .title / .meta ARE SPANS HERE, AND SPANS DO NOT STACK. Every other list in the
   app builds these rows out of divs, so the handle and the name ran together on one line —
   "@jmreyesJM Reyes · Played together 08/31/2026" — which is unreadable and looks like a
   missing separator rather than a missing line break. They stay spans because .row is a
   <button> and a <div> inside a button is invalid; the display fix goes here instead. */
.bk .bk-prow .title, .bk .bk-prow .meta{ display: block; }
/* Ink, not --action: the chosen partner is a state, and the sheet's one orange thing is the
   button that takes the money. Orange here also failed contrast — a 13.5px orange name on
   --bg-sunken was the quietest line in the sheet, on the row the player had just chosen. */
.bk .bk-prow-c{ display: grid; place-items: center; color: var(--ink); opacity: 0; }
.bk .bk-prow[aria-checked="true"]{ background: var(--bg-sunken); }
.bk .bk-prow[aria-checked="true"] .bk-prow-c{ opacity: 1; }
.bk .bk-prow[aria-checked="true"] .title{ color: var(--ink); font-weight: 700; }
[data-ready] .bk .bk-prow-c{ transition: opacity var(--t-press) var(--ease-out); }

.bk .bk-invite{ display: flex; gap: 8px; align-items: stretch; }
.bk .bk-field{
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 2px;
  padding: 0 12px; border-radius: var(--r-md);
  background: var(--bg-sunken); border: 1px solid var(--rule);
}
.bk .bk-at{ font: 600 15px/1 var(--font-ui); color: var(--ink-tertiary); }
.bk .bk-input{
  flex: 1; min-width: 0; border: 0; background: transparent; color: var(--ink);
  font: 500 15px/1 var(--font-ui); letter-spacing: -.006em;
  padding: 13px 2px; outline: none;
}
.bk .bk-input::placeholder{ color: var(--ink-tertiary); }
.bk .bk-invite-go{ padding: 12px 18px; font-size: 15px; }

/* The paid state. The only celebratory moment on this screen, and it is a rare event —
   DESIGN.md §4.1 says delight is allowed here. It still enters from 0.96, never from 0. */
.bk .bk-paid{ text-align: center; padding-top: 10px; }
.bk .bk-paid-mark{
  width: 68px; height: 68px; margin: 6px auto 14px; border-radius: 50%;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--ok) 16%, transparent); color: var(--ok);
}
.bk .bk-paid .bk-sheet-h{ margin-top: 10px; }
.bk .bk-paid .bk-sheet-p{ max-width: 34ch; margin-left: auto; margin-right: auto; }

/* ═══ 8 · REDUCED MOTION ═══════════════════════════════════════════════════
 * Gentler, not absent. The expansion still opens and the dropdown still appears; what goes
 * is the movement — the row growing, the chevron rotating, the menu sliding out.
 * Named animations in this file: .bk-more (grid-template-rows), .bk-dd-chev (rotate),
 * .bk-dd-menu.is-out (scale + translate), .bk-month / .bk-cell / .bk-tt-c / .bk-wcell
 * (colour), .bk-prow-c (opacity), .bk-paid-mark (via .enter in tokens.css). The week band is
 * a JS spring — motion.js snaps it under reduced motion, so there is nothing to do here.
 */
@media (prefers-reduced-motion: reduce){
  [data-ready] .bk .bk-more{ transition-property: opacity; }
  .bk .bk-more{ grid-template-rows: 0fr; }
  .bk .bk-ses.is-open .bk-more{ grid-template-rows: 1fr; }
  [data-ready] .bk .bk-dd-chev{ transition: none; }
  .bk .bk-dd-trigger[aria-expanded="true"] .bk-dd-chev{ transform: none; }
  .bk .bk-dd-menu.is-out{ transform: none; transition-property: opacity; }
}

@media (prefers-contrast: more){
  .bk .bk-cell.is-open{ outline: 1px solid var(--attn-ink); outline-offset: -1px; }
  .bk .bk-cell.is-full{ background: none; outline: 1px dashed var(--ink); outline-offset: -1px; }
  .bk .bk-tt-c.is-free{ border-color: var(--ink); }
  .bk .bk-tt-c.is-taken{ background-image: none; background: var(--bg-sunken); border-color: var(--ink-tertiary); }
  .bk .bk-kind.is-solos{ box-shadow: inset 0 0 0 2px var(--ink); }
  .bk .bk-band{ box-shadow: inset 0 0 0 2px var(--ink); }
}

/* ── How it is paid ────────────────────────────────────────────────────────
   The method choice on the court checkout. ui.css owns `.segmented`; this is the three-up
   thumb width and the spacing inside a sheet.
   ⚠ (100% − 8px) / 3 is 2px of padding either side plus two 2px gaps. The same formula as the
     profile's appearance switch and the match filter — if a fourth method is ever added, this
     number changes with it or the thumb sits under the wrong word. */
.bk .bk-pay-h { margin-top: 18px; }
.bk .bk-pay-methods { margin: 10px 0 18px; }
.bk .bk-pay-methods .thumb { width: calc((100% - 8px) / 3); }

/* The code on the paid screen. ⚠ It is stated here as well as on the ticket because this is
   the one moment somebody might photograph the screen, and a receipt with no reference on it
   is a receipt nobody can quote at a desk. */
.bk .bk-paid-code {
  margin: 10px 0 0; font: 600 13px/1 var(--font-ui); letter-spacing: .12em;
  color: var(--ink-secondary);
}
