/* journey.css — boards 08-25 of "Bajaker Tarneeb Screens.dc.html", the
 * Tarneeb journey redrawn. Every value is the board's own; where a rule is
 * mine it says so. Prefix kj- (kufi journey) so nothing here collides with the
 * kn- templates in journey.html.
 *
 * The frame: a 384x832 canvas scaled as one piece (--kj-scale, set by
 * journey.js from the viewport, capped at 1.5), centred in a fixed layer that
 * paints the board's felt ground. Same trick as the Trix ladder. */

.kj-cer, .kj-frame {
  /* above the hub's tab bar and every table layer: it is the whole frame */
  position: fixed; inset: 0; z-index: 1300; overflow: hidden;
  background: radial-gradient(72% 40% at 50% 32%, var(--felt-1) 0%, var(--felt) 46%, var(--felt-2) 100%);
}
.kj-cer::before, .kj-frame::before {
  /* the mark, faint, high on the felt */
  content: ""; position: absolute; left: 50%; top: 18%; width: 170px; height: 170px;
  transform: translate(-50%, -50%); opacity: .09; pointer-events: none;
  background: url("brand/mark-256.webp") center / contain no-repeat;
}
.kj-cer::after, .kj-frame::after { content: ""; position: absolute; inset: 0; background: rgba(9,13,8,0.55); }
.kj-canvas {
  position: absolute; left: 50%; top: 50%; width: 384px; height: 832px; z-index: 1;
  transform: translate(-50%, -50%) scale(var(--kj-scale, 1)); transform-origin: center;
  text-align: left;
}

/* -- the felt half ------------------------------------------------------- */
.kj-cer-top {
  position: absolute; top: 78px; left: 0; right: 0;
  display: flex; flex-direction: column; align-items: center; gap: 12px;
}
.kj-cer-top[data-kind="cut"] { gap: 12px; }
.kj-cer-round { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--ink-2); }

/* board 08: three backs fanned, the middle one holding the gold pip */
.kj-fan { display: flex; align-items: flex-end; gap: 5px; height: 92px; }
.kj-fan-back {
  width: 62px; height: 86px; border-radius: 8px; position: relative; box-sizing: border-box;
  background: var(--felt); border: 1px solid var(--line-strong); box-shadow: 0 6px 16px rgba(0,0,0,0.5);
}
.kj-fan-back--l { transform: rotate(-4deg); }
.kj-fan-back--r { transform: rotate(4deg); }
.kj-fan-back--m {
  height: 88px; background: var(--chair); border-color: var(--chair-ring); box-shadow: 0 8px 20px rgba(0,0,0,0.55);
}
.kj-fan-inner {
  position: absolute; inset: 7px; border: 1px solid rgba(239,195,117,0.3); border-radius: 4px;
  display: flex; align-items: center; justify-content: center;
}
.kj-fan-back--m .kj-fan-inner { border-color: rgba(239,195,117,0.34); }
.kj-fan-inner i { display: block; width: 12px; height: 12px; transform: rotate(45deg); background: var(--gold); }

.kj-cer-pill {
  display: flex; align-items: center; gap: 8px;
  background: var(--surf2); border: 1px solid var(--line-strong); border-radius: 999px; padding: 6px 14px;
}
.kj-cer-av {
  width: 22px; height: 22px; border-radius: 50%; box-sizing: border-box;
  background: var(--teal); border: 1.5px solid var(--gold);
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 800; color: var(--ink);
}
.kj-cer-pill-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--gold); }
.kj-cer-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 12px; line-height: 1.4; color: var(--ink-3); }

.kj-cer-dots { position: absolute; top: 300px; left: 0; right: 0; display: flex; justify-content: center; gap: 8px; }
.kj-cer-dot {
  width: 26px; height: 26px; border-radius: 50%; box-sizing: border-box;
  background: var(--surface); border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 800; color: var(--ink-3);
}
.kj-cer-dot[data-actor="true"] { background: var(--teal); border-color: var(--gold); color: var(--ink); }

/* board 09: the deck split at the depth, and the slider that sets it */
.kj-cutdeck { width: 132px; height: 128px; position: relative; }
.kj-cut-top {
  position: absolute; left: 50%; top: 0; transform: translateX(-50%); width: 74px; height: 52px;
  border-radius: 8px 8px 4px 4px; background: var(--chair); border: 1px solid var(--chair-ring); box-sizing: border-box;
  box-shadow: 0 6px 16px rgba(0,0,0,0.5);
}
.kj-cut-line {
  position: absolute; left: 50%; top: 56px; transform: translateX(-50%); width: 100%; height: 2px;
  background: repeating-linear-gradient(90deg, var(--gold) 0 7px, transparent 7px 13px);
}
.kj-cut-bottom {
  position: absolute; left: 50%; top: 68px; transform: translateX(-50%); width: 74px; height: 58px;
  border-radius: 4px 4px 8px 8px; background: var(--felt); border: 1px solid var(--line-strong); box-sizing: border-box;
  box-shadow: 0 8px 18px rgba(0,0,0,0.5);
}
.kj-cut-depth {
  position: absolute; right: -8px; top: 46px;
  font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--gold);
}
.kj-slider { width: 232px; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.kj-slider-track { width: 100%; height: 4px; border-radius: 999px; background: var(--surf3); position: relative; }
.kj-slider-fill { position: absolute; left: 0; top: 0; bottom: 0; width: 50%; background: var(--gold-dim); border-radius: 999px; }
.kj-slider-thumb {
  position: absolute; left: 50%; top: -6px; width: 16px; height: 16px; margin-left: -8px; box-sizing: border-box;
  border-radius: 50%; background: var(--gold); border: 2px solid var(--ink-bg); pointer-events: none;
}
/* the real control sits invisibly over the drawn one (MINE: the board draws
   the slider, the browser has to move it) */
.kj-slider-input {
  position: absolute; left: -8px; right: -8px; top: -14px; height: 32px; width: calc(100% + 16px);
  margin: 0; opacity: 0; cursor: pointer; -webkit-appearance: none; appearance: none; background: transparent;
}
.kj-slider-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--ink-3); }

/* 70: the 9.5px "6s TO DECIDE" pill and its ring are gone - the countdown is
   a 56px ring in the sheet head now, and two clocks on one screen is the
   clutter this screen was reported for. */

/* -- the sheet ----------------------------------------------------------- */
.kj-sheet {
  position: absolute; bottom: 0; left: 0; right: 0; box-sizing: border-box;
  background: var(--surface-sheet); border-top: 1px solid var(--line-strong); border-radius: 22px 22px 0 0; padding: 20px 20px 30px;
}
.kj-sheet-grab { width: 40px; height: 4px; background: var(--line-strong); border-radius: 999px; margin: 0 auto 18px; }
.kj-sheet-head { display: flex; align-items: flex-end; justify-content: space-between; margin-bottom: 16px; }
.kj-sheet-titles { display: flex; flex-direction: column; gap: 5px; }
.kj-sheet-title { font-family: 'Archivo Black', sans-serif; font-size: 21px; line-height: 1; letter-spacing: -.02em; color: var(--ink); }
.kj-cer-top[data-kind="cut"] ~ .kj-sheet .kj-sheet-title { font-size: 22px; }
.kj-sheet-title-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 14px; line-height: 1.4; color: var(--gold-ar); }
.kj-sheet-meta { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }

/* board 08's three styles */
.kj-slist { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.kj-srow {
  display: flex; align-items: center; gap: 12px; width: 100%; box-sizing: border-box; text-align: left;
  background: var(--surface); border: 1px solid var(--surf4); border-radius: 12px; padding: 13px 15px;
  appearance: none; cursor: pointer; font-family: inherit;
}
.kj-srow[data-on="true"] { background: var(--surf2); border-color: var(--gold); box-shadow: inset 0 0 0 1px rgba(239,195,117,0.3); }
.kj-srow-body { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.kj-srow-name { font-size: 14.5px; font-weight: 800; color: var(--ink); }
.kj-srow-desc { font-size: 11.5px; color: var(--ink-3); }
.kj-srow-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 13px; line-height: 1.4; color: var(--ink-3); }
.kj-srow[data-on="true"] .kj-srow-name { color: var(--ink); }
.kj-srow[data-on="true"] .kj-srow-desc { color: var(--ink-2); }
.kj-srow[data-on="true"] .kj-srow-ar { color: var(--gold); }
body.theme-dark .kj-srow, body.theme-dark .kj-srow-name { color: var(--ink); }
/* the icons: riffle = two halves, overhand = three packets, wash = three spread */
.kj-sicon { width: 34px; height: 30px; flex: none; position: relative; display: flex; align-items: center; gap: 2px; }
.kj-sicon i { display: block; background: var(--line6); border-radius: 999px; }
.kj-sicon--riffle i { width: 15px; height: 30px; }
.kj-sicon--riffle[data-on="true"] i:first-child { background: var(--gold); }
.kj-sicon--riffle[data-on="true"] i:last-child { background: var(--gold-dim); }
.kj-sicon--overhand { flex-direction: column; align-items: flex-start; gap: 3px; }
.kj-sicon--overhand i { height: 8px; border-radius: 999px; }
.kj-sicon--overhand i:nth-child(1) { width: 34px; }
.kj-sicon--overhand i:nth-child(2) { width: 26px; }
.kj-sicon--overhand i:nth-child(3) { width: 30px; }
.kj-sicon--wash i { position: absolute; width: 16px; height: 11px; border-radius: 999px; }
.kj-sicon--wash i:nth-child(1) { left: 0; top: 4px; transform: rotate(-18deg); }
.kj-sicon--wash i:nth-child(2) { right: 0; top: 2px; transform: rotate(14deg); }
.kj-sicon--wash i:nth-child(3) { left: 6px; bottom: 1px; transform: rotate(8deg); }
.kj-sicon--overhand[data-on="true"] i, .kj-sicon--wash[data-on="true"] i { background: var(--gold); }   /* MINE: the board only draws Riffle chosen */

.kj-sheet-acts { display: flex; gap: 12px; }
.kj-btn-ghost {
  flex: 1; box-sizing: border-box; appearance: none; cursor: pointer; background: none; font-family: inherit;
  border: 1px solid var(--line5); color: var(--ink); font-size: 14px; font-weight: 600; padding: 13px 0; border-radius: 12px; text-align: center;
}
.kj-btn-gold {
  flex: 1.3; box-sizing: border-box; appearance: none; cursor: pointer; border: 0; font-family: inherit;
  background: var(--gold); color: var(--ink-bg); font-size: 15px; font-weight: 800; letter-spacing: .04em; padding: 15px 0; border-radius: 12px; text-align: center;
}
.kj-btn-gold--full { display: block; width: 100%; }
body.theme-dark .kj-btn-ghost { color: var(--ghost-ink); }
body.theme-dark .kj-btn-gold { color: var(--ink-bg); }

/* board 09's two cards */
.kj-cgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 14px; }
.kj-ccard {
  box-sizing: border-box; text-align: left; appearance: none; cursor: pointer; font-family: inherit;
  background: var(--surface); border: 1px solid var(--surf4); border-radius: 16px; padding: 16px 14px;
  display: flex; flex-direction: column; gap: 12px; min-height: 128px;
}
.kj-ccard[data-on="true"] { background: var(--surf2); border-color: var(--gold); box-shadow: inset 0 0 0 1px rgba(239,195,117,0.28); }
.kj-cicon { width: 30px; height: 34px; position: relative; display: block; }
.kj-cicon--cut i { position: absolute; left: 0; width: 30px; height: 15px; display: block; background: var(--line6); }
.kj-cicon--cut i:first-child { top: 0; border-radius: 4px 4px 4px 4px; }
.kj-cicon--cut i:last-child { bottom: 0; border-radius: 4px 4px 4px 4px; }
.kj-ccard[data-on="true"] .kj-cicon--cut i:first-child { background: var(--gold); }
.kj-ccard[data-on="true"] .kj-cicon--cut i:last-child { background: var(--gold-dim); }
.kj-cicon--knock { display: flex; align-items: center; justify-content: center; }
.kj-cicon--knock i { display: block; width: 26px; height: 26px; border-radius: 50%; border: 2px solid var(--line6); box-sizing: border-box; }
.kj-ccard[data-on="true"] .kj-cicon--knock i { border-color: var(--gold); }   /* MINE: the board only draws CUT chosen */
.kj-ccard-body { margin-top: auto; display: flex; flex-direction: column; gap: 3px; }
.kj-ccard-name { font-family: 'Archivo Black', sans-serif; font-size: 19px; line-height: 1; color: var(--ink); }
.kj-ccard-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 13px; line-height: 1.4; color: var(--ink-3); }
.kj-ccard-desc { font-size: 11px; line-height: 1.45; color: var(--ink-3); margin-top: 3px; }
.kj-ccard[data-on="true"] .kj-ccard-name { color: var(--gold); }
.kj-ccard[data-on="true"] .kj-ccard-ar { color: var(--gold-ar); }
.kj-ccard[data-on="true"] .kj-ccard-desc { color: var(--ink-2); }
body.theme-dark .kj-ccard { color: var(--ink); }

/* -- board 12: name the trump ------------------------------------------- */
.kj-trump::before { top: 16%; }
.kj-trump::after { background: rgba(9,13,8,0.5); }
.kj-trump-top { top: 74px; gap: 12px; }
.kj-trump-top .kj-cer-round { letter-spacing: .18em; }
.kj-recap { display: flex; align-items: flex-end; gap: 12px; }
.kj-recap-seat { display: flex; flex-direction: column; align-items: center; gap: 5px; }
.kj-recap-av {
  width: 38px; height: 38px; border-radius: 50%; box-sizing: border-box; opacity: .6;
  background: var(--line5); border: 2px solid var(--line-strong);
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 800; color: var(--ink);
}
.kj-recap-n { font-family: 'Archivo Black', sans-serif; font-size: 13px; line-height: 1; color: var(--ink-3); }
.kj-recap-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-recap-seat[data-won="true"] .kj-recap-av { width: 46px; height: 46px; opacity: 1; background: var(--teal); border-color: var(--gold); font-size: 16px; }
.kj-recap-seat[data-won="true"] .kj-recap-n { font-size: 17px; color: var(--gold); }
.kj-recap-seat[data-won="true"] .kj-recap-k { color: var(--gold); }
.kj-sheet-title--22 { font-size: 22px; }
.kj-must { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; }
.kj-must-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-must-n { font-family: 'Archivo Black', sans-serif; font-size: 20px; line-height: 1; color: var(--gold); }
.kj-tgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 14px; }
.kj-tcard {
  box-sizing: border-box; text-align: left; appearance: none; cursor: pointer; font-family: inherit;
  background: var(--surface); border: 1px solid var(--surf4); border-radius: 16px; padding: 14px;
  display: flex; align-items: center; gap: 12px;
}
.kj-tcard[data-on="true"] { background: var(--surf2); border-color: var(--gold); box-shadow: inset 0 0 0 1px rgba(239,195,117,0.28); }
.kj-tcard-glyph { font-size: 34px; line-height: 1; color: var(--ink-2); }
.kj-tcard[data-red="true"] .kj-tcard-glyph { color: var(--salmon); }
.kj-tcard[data-on="true"] .kj-tcard-glyph { color: var(--gold); }
.kj-tcard-body { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.kj-tcard-name { font-family: 'Archivo Black', sans-serif; font-size: 13px; line-height: 1; color: var(--ink); }
.kj-tcard-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 11px; line-height: 1.4; color: var(--ink-3); }
.kj-tcard-hold { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-tcard[data-on="true"] .kj-tcard-name { color: var(--gold); }
.kj-tcard[data-on="true"] .kj-tcard-ar { color: var(--gold-ar); }
.kj-tcard[data-on="true"] .kj-tcard-hold { color: var(--mint); }
body.theme-dark .kj-tcard { color: var(--ink); }

/* -- the joker ----------------------------------------------------------- */
.kj-joker { position: absolute; left: 14px; display: flex; align-items: flex-end; gap: 8px; max-width: 240px; }
.kj-joker img { width: 46px; display: block; flex: none; }
/* The joker SPEAKS, he does not act. A solid gold bubble is the same fill as
   the primary button, and on the lobby it was bigger than the button and
   higher on the screen - so the loudest thing on a screen whose whole job is
   "press START" was a wisecrack. Gold now means the thing you can press;
   the joker keeps it as the edge his voice comes from, and his face is still
   in full colour beside it. */
.kj-joker-bubble {
  background: var(--bubble); border-inline-start: 3px solid var(--bubble-edge);
  border-radius: 12px; border-start-start-radius: 3px; border-end-start-radius: 3px;
  padding: 8px 11px;
  display: flex; flex-direction: column; gap: 2px;
}
.kj-joker-en { font-size: 12px; font-weight: 800; line-height: 1.3; color: var(--bubble-ink); }
.kj-joker-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 10.5px; line-height: 1.5; color: var(--bubble-ink-2); }

/* ==========================================================================
   BOARDS 13a-c · 14 · 15 — the table in play. Lives under body.kj-table,
   which app.js sets while a Tarneeb hand is in TrickPlaying. Board: 384x832,
   app bar 53px at y=44, felt zone y=97..666 (569px), hand 646..806, one
   caption line 26px at the bottom. Every hex is the board's.
   ========================================================================== */

/* -- the app bar (replaces the HUD row while the skin is on) --------------- */
body.kj-table #ga-top {
  display: flex !important; align-items: center; padding: 0 !important;
  min-height: 53px; height: 53px; gap: 0;
  background: var(--ink-bg2) !important; border: 0 !important; border-bottom: 1px solid var(--surf3) !important;
  border-radius: 0 !important; box-shadow: none !important;
}
.kj-bar { display: flex; align-items: center; gap: 12px; padding: 0 16px; width: 100%; height: 53px; box-sizing: border-box; }
.kj-bar-back {
  font-family: 'IBM Plex Mono', monospace; font-size: 16px; color: var(--ink-2); background: none; border: 0;
  padding: 0; margin: 0; cursor: pointer; line-height: 1; min-width: 24px; min-height: 44px;
}
.kj-bar-mark { width: 26px; height: 26px; overflow: hidden; position: relative; flex: none; }
.kj-bar-mark img { position: absolute; left: 2px; top: -1px; width: 22px; display: block; }
.kj-bar-col { display: flex; flex-direction: column; gap: 0; }
.kj-bar-round { font-family: 'Archivo Black', sans-serif; font-size: 11px; letter-spacing: 0; color: var(--gold); line-height: 1.2; }
.kj-bar-trick { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); line-height: 1.2; }
.kj-bar-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.kj-bar-trump {
  display: flex; align-items: center; gap: 5px; background: var(--surf2); border: 1px solid var(--line);
  border-radius: 8px; padding: 4px 9px;
}
.kj-bar-trump-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-bar-trump-g { font-size: 14px; line-height: 1; color: var(--gold); }
.kj-bar-more {
  font-family: 'IBM Plex Mono', monospace; font-size: 14px; color: var(--ink-2); background: none; border: 0;
  padding: 0 4px; cursor: pointer; line-height: 1; min-width: 32px; min-height: 44px;
}

/* -- the felt zone --------------------------------------------------------- */
body.kj-table #view-room .felt-wrap { padding: 0; }
body.kj-table #view-room .felt {
  margin: 0; border: 0 !important; border-radius: 0 !important; min-height: 0;
  background: radial-gradient(72% 52% at 50% 46%, var(--felt-1) 0%, var(--felt) 46%, var(--felt-2) 100%) !important;
  box-shadow: none !important;
}
/* the board's inset ring replaces the arabesque tile and the corner glows */
body.kj-table #view-room .felt::before {
  background: none; animation: none; opacity: 1;
  inset: 14px; border: 1px solid rgba(239,195,117,0.16); border-radius: 50% / 22%;
}
body.kj-table #view-room .felt::after { display: none; }
body.kj-table #view-room .felt-logo {
  left: 50%; top: 50%; transform: translate(-50%, -50%); width: 116px; height: 116px;
  opacity: .1; font-size: 0; letter-spacing: 0; text-shadow: none;
}
body.kj-table #view-room .felt-logo img { width: 116px; height: 116px; display: block; }
body.kj-table .game-area { grid-template-rows: 53px minmax(0, 1fr) var(--handH) 0; }

/* -- the overlay: tiles, slot, tag, captions ------------------------------- */
.kj-tab { position: absolute; inset: 0; pointer-events: none; z-index: 5; text-align: left; }
.kj-seat {
  /* 58 amended: the column is explicit "so it can't grow even if a string I
     haven't anticipated appears". 92 was the widest thing that had happened to
     fit so far, which is not the same as a column. */
  position: absolute; transform: translate(-50%, -50%); width: 96px;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
}
.kj-av-box { position: relative; pointer-events: auto; }
.kj-av {
  width: var(--chair-felt); height: var(--chair-felt); border-radius: 50%; box-sizing: border-box;   /* 62: 44 felt seat, one body, one idle ring */
  background: var(--chair); border: 2px solid var(--chair-ring);
  display: flex; align-items: center; justify-content: center;
  font-size: 16px; font-weight: 800; color: var(--ink);
}
.kj-seat[data-active="1"] .kj-av { border-color: var(--gold); animation: knRing 1.6s ease-out infinite; }
.kj-seat-name { font-size: 10.5px; font-weight: 700; color: var(--ink-2); line-height: 1.2; max-width: 96px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kj-seat[data-active="1"] .kj-seat-name { color: var(--gold); }
/* 58: the status line reserves its height even when empty, so the avatar never moves when a chair falls silent (59b) */
.kj-seat-status { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); line-height: 1.2; min-height: 1.2em; white-space: nowrap; }
.kj-seat-status[data-tone="red"] { color: var(--salmon); }
.kj-seat-status[data-tone="gold"] { color: var(--gold); }
.kj-seat-status[data-tone="green"] { color: var(--mint); }
.kj-seat-status[data-tone="wait"] { color: var(--ink-4); }
.kj-seat-status[data-tone="follow"] { color: var(--gold); font-size: 9.5px; letter-spacing: .14em; }
/* UX Phase 1 item 1 (2026-09-08): the last three seconds of the armed chair's countdown.
 * Opacity only - the status line must not resize, or the frozen-frame test is right to fail. */
.kj-seat-status.kj-clock--urgent { color: var(--salmon); animation: kjClockPulse var(--t-ring) ease-in-out infinite; }
/* 58 amended: the clock is its own row and it is ALWAYS there, reading a
   transparent 0:00 when no deadline is running, so the block is the same
   height whether or not the table is waiting on this chair and nothing below
   it moves when a clock arrives. Appending it to the state word instead was
   what made the status line wrap in the first place. */
.kj-seat-clock {
  font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: .14em;
  line-height: 1.2; white-space: nowrap; color: transparent;
}
.kj-seat-clock[data-live="1"] { color: var(--gold); }
.kj-seat-clock.kj-clock--urgent { color: var(--salmon); animation: kjClockPulse var(--t-ring) ease-in-out infinite; }
body.kj-ar.kj-table .kj-seat-clock { letter-spacing: 0; }
@keyframes kjClockPulse { 0%, 100% { opacity: 1; } 50% { opacity: .5; } }

.kj-score {
  position: absolute; left: 12px; top: 12%; transform: translateY(-50%);
  background: rgba(9,13,8,0.72); border: 1px solid var(--line-strong); border-radius: 12px; padding: 7px 10px;
  display: flex; flex-direction: column; gap: 5px; min-width: 72px; box-sizing: border-box;
}
.kj-score-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-score-row { display: flex; align-items: baseline; gap: 5px; }
.kj-score-us { font-family: 'Archivo Black', sans-serif; font-size: 17px; line-height: 1; color: var(--gold); }
.kj-score-sl { font-family: 'IBM Plex Mono', monospace; font-size: 10px; color: var(--ink-3); }
.kj-score-them { font-family: 'Archivo Black', sans-serif; font-size: 17px; line-height: 1; color: var(--salmon); }
.kj-score-won { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--mint); white-space: nowrap; }

.kj-tomake {
  position: absolute; right: 12px; top: 12%; transform: translateY(-50%); width: 96px;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
}
.kj-tomake-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--ink-3); white-space: nowrap; }
.kj-tomake-row { display: flex; align-items: baseline; gap: 5px; }
.kj-tomake-n { font-family: 'Archivo Black', sans-serif; font-size: 23px; line-height: 1; color: var(--gold); }
.kj-tomake-more { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-tomake-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 9.5px; line-height: 1.4; color: var(--ink-3); }

/* the HIGH tag: sits just above the card currently taking the trick (13b/13c) */
.kj-high {
  position: absolute; margin-top: -58px; transform: translateX(-50%);
  background: rgba(239,195,117,0.95); border-radius: 8px; padding: 3px 7px; white-space: nowrap;
}
.kj-high span { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-bg); }

/* where your card lands: dashed and quiet (13a/b), lit and ringed when there is
   a card to beat (13c), three dots while somebody else is thinking (14) */
.kj-slot {
  position: absolute; transform: translate(-50%, -50%); width: 59px; height: 83px; box-sizing: border-box;
  border: 1.5px dashed rgba(239,195,117,0.4); border-radius: 8px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
}
.kj-slot-suit { font-size: 15px; line-height: 1; color: rgba(239,195,117,0.55); }
.kj-slot-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-slot--beat { border-color: var(--gold); animation: knRing 1.6s ease-out infinite; }
.kj-slot--beat .kj-slot-suit { color: var(--gold); }
.kj-slot--beat .kj-slot-k { color: var(--gold); letter-spacing: .14em; }
.kj-slot--thinking { border: 1.5px solid rgba(239,195,117,0.3); background: rgba(239,195,117,0.05); }
.kj-slot-dots { display: flex; gap: 3px; }
.kj-slot-dots i { width: 5px; height: 5px; border-radius: 50%; background: var(--gold); display: block; }
.kj-slot-dots i:nth-child(1) { opacity: .9; }
.kj-slot-dots i:nth-child(2) { opacity: .5; }
.kj-slot-dots i:nth-child(3) { opacity: .25; }

/* the caption under the trick (13a-c, 15) or the TO PLAY pill (14) */
.kj-cap {
  position: absolute; left: 50%; transform: translateX(-50%); width: 268px;
  display: flex; flex-direction: column; align-items: center; gap: 5px; text-align: center;
}
.kj-cap-en { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); white-space: nowrap; }
.kj-cap-en[data-tone="gold"] { color: var(--gold); }
.kj-cap-en[data-tone="warn"] { color: var(--salmon); letter-spacing: .14em; }
.kj-cap-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 10px; line-height: 1.4; color: var(--ink-3); }
.kj-cap-pill {
  display: flex; align-items: center; gap: 8px; background: rgba(9,13,8,0.7); border: 1px solid var(--line-strong);
  border-radius: 999px; padding: 5px 13px; margin-bottom: 2px;
}
.kj-cap-av {
  width: 20px; height: 20px; border-radius: 50%; background: var(--teal); display: flex; align-items: center;
  justify-content: center; font-size: 9.5px; font-weight: 800; color: var(--ink);
}
.kj-cap-pill-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-2); white-space: nowrap; }

/* board 14: the plan-ahead chip and the two reactions, in the felt's bottom corners */
.kj-plan {
  position: absolute; left: 14px; bottom: 14px; display: flex; align-items: center; gap: 8px;
  background: rgba(9,13,8,0.62); border: 1px solid var(--surf4); border-radius: 8px; padding: 6px 10px;
}
.kj-plan-g { font-size: 13px; line-height: 1; color: var(--ink-3); }
.kj-plan-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); white-space: nowrap; }
.kj-rx { position: absolute; right: 14px; bottom: 14px; display: flex; gap: 8px; pointer-events: auto; }
.kj-rx-btn {
  width: 34px; height: 34px; border-radius: 12px; background: rgba(9,13,8,0.62); border: 1px solid var(--surf4);
  display: flex; align-items: center; justify-content: center; font-size: 15px; color: var(--ink-2);
  padding: 0; margin: 0; cursor: pointer; font-family: inherit;
}

/* -- the played cards: 59x83, cream, corner index + one pip, tilted -------- */
body.kj-table #view-room .ga-felt .trick {
  position: absolute; inset: 0; width: auto; height: auto; max-width: none;
  background: none; border: 0; box-shadow: none; border-radius: 0; padding: 0; transform: none;
  --pc-w: clamp(44px, 15.4vw, 59px);
  --pc-h: calc(var(--pc-w) * 1.407);
}
body.kj-table #view-room .ga-felt .trick .played-card {
  position: absolute; width: var(--pc-w); height: var(--pc-h); box-sizing: border-box;
  left: 50%; top: 46%; right: auto; bottom: auto;
  margin: calc(var(--pc-h) / -2) 0 0 calc(var(--pc-w) / -2);
  background: var(--ink); border: 0; border-radius: 4px; box-shadow: 0 3px 10px rgba(0,0,0,0.45);
  /* UX Phase 1 item 6: board 13b's trick card is a CENTRED two-item face. It was pinned to the
     top by space-between, pushing against a legacy .corner.br that the hand already hides - and
     the audit measured the face 2px above its own padding because of it. */
  display: flex; flex-direction: column; justify-content: center; padding: 5px 6px;
  color: var(--card-ink); overflow: visible;
}
body.kj-table #view-room .ga-felt .trick .played-card.red { color: var(--card-red); }
body.kj-table #view-room .ga-felt .trick .played-card.west  { left: 31%; top: 46%; rotate: -7deg; }
body.kj-table #view-room .ga-felt .trick .played-card.north { left: 50%; top: 30%; rotate: 4deg; }
body.kj-table #view-room .ga-felt .trick .played-card.east  { left: 69%; top: 46%; rotate: 8deg; }
body.kj-table #view-room .ga-felt .trick .played-card.south { left: 50%; top: 62%; rotate: 0deg; }
body.kj-table #view-room .ga-felt .trick .played-card .corner {
  position: static; display: flex; align-items: baseline; gap: 0; margin: 0;
  font-family: 'IBM Plex Mono', monospace; font-size: 13px; font-weight: 500; line-height: 1; color: inherit;
}
body.kj-table #view-room .ga-felt .trick .played-card .corner .rank { font-size: 13px; letter-spacing: 0; color: inherit; }
body.kj-table #view-room .ga-felt .trick .played-card .corner .suit { font-size: 11px; margin: 0; color: inherit; }
body.kj-table #view-room .ga-felt .trick .played-card .corner.br { align-self: flex-end; transform: rotate(180deg); }
body.kj-table #view-room .ga-felt .trick .played-card .pip {
  position: static; font-size: 20px; line-height: 1; align-self: center; margin: 0; color: inherit; transform: none;
}
/* the card taking the trick is gold with dark ink (13b/13c/14) */
body.kj-table #view-room .ga-felt .trick .played-card.kj-high-card { background: var(--gold); color: var(--on-gold); }
body.kj-table #view-room .ga-felt .trick .played-card.kj-high-card.red { color: var(--on-gold); }

/* -- board 14: the hand at rest drops 14px and dims to 72% ------------------ */
body.kj-table.kj-idle #hand { transform: translateY(14px); opacity: .72; transition: transform .28s ease, opacity .28s ease; }
body.kj-table #hand { transition: transform .28s ease, opacity .28s ease; }

/* -- the caption line under the hand (26px, two languages, hairline) ------- */
body.kj-table .ga-hand .hand-hint-row {
  position: static !important; order: 3; height: 26px !important; min-height: 26px !important; max-height: 26px !important;
  margin: 0 !important; align-items: center; justify-content: center; inset: auto !important; transform: none !important;
}
body.kj-table .ga-hand { display: flex !important; flex-direction: column !important; }
body.kj-table .ga-hand .kj-sort { order: 1; flex: none; }
body.kj-table .ga-hand .hand-row { order: 2; }
body.kj-table .hand-hint { display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 14px; line-height: 14px; }   /* 58: the footer line is a fixed 14px box whatever glyphs it carries */
.kj-hint-en { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); white-space: nowrap; }
.kj-hint-en[data-tone="warn"] { color: var(--salmon); }
.kj-hint-sep { width: 1px; height: 9px; background: var(--line5); display: inline-block; }
.kj-hint-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 9.5px; line-height: 1.4; color: var(--ink-3); }
/* the boards carry your clock on the seat ring, not as a pill under the hand */

/* what the boards do not draw while the skin is on: the YOU · TEAM tab over
   the hand, the "Need X more · Y left" strip (the TO MAKE tile carries it),
   the narrator's italic line beside the caption */
/* The mark is a MEDALLION, not a backdrop. At 190px and 7% it filled the felt's
   whole middle, and since a phone's felt has nothing in that middle until the
   first card lands, the one thing there was a huge dim face cropped by the
   chair row - which reads as a smudge, and makes the empty middle look broken
   rather than deliberate. At 116px it sits inside the felt's own inset ring,
   centred with it, and a little darker so it reads as a mark instead of a
   stain. The middle is still empty during the auction, and it has to be: it is
   where the trick lands, and 58 says nothing there may move. */
body.kj-table #view-room .felt-logo {
  left: 50% !important; top: 50% !important; right: auto !important; bottom: auto !important;
  width: 116px !important; height: auto !important; margin: 0 !important;
  transform: translate(-50%, -50%) !important; animation: none !important; opacity: .1 !important;
}
body.kj-table #view-room .felt-logo img { width: 116px !important; height: auto !important; }
.kj-slot--waiting { width: 98px; height: 118px; border: 1.5px dashed rgba(239,195,117,0.2); border-radius: 12px; }
.kj-slot-wait { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--ink-3); }

/* -- board 17a: the last trick as an edge tab at 72% ----------------------- */
.kj-last {
  position: absolute; right: 0; top: 72%; transform: translateY(-50%); z-index: 6;
  background: rgba(9,13,8,0.82); border: 1px solid var(--line-strong); border-right: none; border-radius: 12px 0 0 12px;
  padding: 10px 10px 10px 12px; display: flex; align-items: center; gap: 8px; cursor: pointer;
  pointer-events: auto; font-family: inherit; color: inherit; text-align: left;
}
.kj-last-k { display: flex; flex-direction: column; gap: 3px; align-items: flex-end; }
.kj-last-en { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--ink-3); }
.kj-last-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 9.5px; line-height: 1.4; color: var(--ink-3); }
.kj-last-fan { display: flex; align-items: center; }
.kj-last-fan .kj-lcard + .kj-lcard { margin-inline-start: -19px; }
.kj-last-chev { font-family: 'IBM Plex Mono', monospace; font-size: 13px; color: var(--ink-2); }
.kj-lcard {
  width: 30px; height: 42px; border-radius: 4px; background: var(--ink); box-shadow: 0 2px 6px rgba(0,0,0,0.4);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; flex: none;
  color: var(--card-ink);
}
.kj-lcard[data-red="true"] { color: var(--oxblood); }
.kj-lcard--win { background: var(--gold); color: var(--ink-bg); }
.kj-lcard--win[data-red="true"] { color: var(--ink-bg); }
.kj-lcard-r { font-family: 'Archivo Black', sans-serif; font-size: 12px; line-height: 1; }
.kj-lcard-s { font-size: 12px; line-height: 1; }

/* -- board 17b: the last trick open ---------------------------------------- */
.kj-lsheet { position: absolute; inset: 0; z-index: 7; background: rgba(9,13,8,0.72); pointer-events: auto; cursor: pointer; }
.kj-lpanel {
  position: absolute; left: 18px; right: 18px; top: 50%; transform: translateY(-50%);
  background: var(--surface-sheet); border: 1px solid var(--line-strong); border-radius: 16px; overflow: hidden; cursor: default;
}
.kj-lhead { display: flex; align-items: center; gap: 12px; padding: 14px 16px; border-bottom: 1px solid var(--surf4); }
.kj-lhead-en { font-family: 'Archivo Black', sans-serif; font-size: 15px; letter-spacing: 0; color: var(--ink); }
.kj-lhead-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 12px; line-height: 1.4; color: var(--gold-ar); }
.kj-lhead-x { margin-left: auto; font-family: 'IBM Plex Mono', monospace; font-size: 13px; color: var(--ink-2); background: none; border: 0; padding: 4px; cursor: pointer; }
.kj-llist { padding: 14px 16px; display: flex; flex-direction: column; gap: 8px; }
.kj-lrow { display: flex; align-items: center; gap: 12px; background: var(--surface); border: 1px solid var(--surf4); border-radius: 12px; padding: 9px 12px; }
.kj-lrow--win { background: var(--surf2); border-color: var(--gold); }
.kj-lrow-av { width: 30px; height: 30px; border-radius: 50%; background: var(--teal); display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 800; color: var(--ink); flex: none; }
.kj-lrow-col { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.kj-lrow-name { font-size: 13px; font-weight: 700; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kj-lrow--win .kj-lrow-name { color: var(--gold); }
.kj-lrow-role { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-lrow--win .kj-lrow-role { color: var(--gold); }
.kj-ljoker { padding: 0 16px 16px; display: flex; align-items: center; gap: 8px; }
.kj-ljoker img { width: 42px; display: block; flex: none; }
.kj-ljoker-col { display: flex; flex-direction: column; gap: 1px; }
.kj-ljoker-en { font-size: 12px; font-weight: 800; line-height: 1.35; color: var(--gold); }
.kj-ljoker-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 10px; line-height: 1.4; color: var(--ink-3); }
.kj-lfoot { position: absolute; left: 0; right: 0; bottom: 8px; display: flex; align-items: center; justify-content: center; gap: 8px; }

/* -- board 16: trick won -------------------------------------------------- */
.kj-won { position: absolute; inset: 0; z-index: 6; pointer-events: none; }
.kj-won-burst {
  position: absolute; left: 50%; top: 46%; transform: translate(-50%, -50%); width: 210px; height: 210px;
  border-radius: 50%; background: radial-gradient(circle, rgba(239,195,117,0.16) 0%, rgba(239,195,117,0) 68%);
}
.kj-won-card {
  position: absolute; width: 59px; height: 83px; box-sizing: border-box; margin: -41.5px 0 0 -29.5px;
  background: var(--ink); border-radius: 4px; box-shadow: 0 3px 10px rgba(0,0,0,0.45);
  display: flex; flex-direction: column; justify-content: space-between; padding: 5px 6px; color: var(--card-ink);
}
.kj-won-card[data-red="true"] { color: var(--oxblood); }
.kj-won-card--win { background: var(--gold); color: var(--ink-bg); scale: 1.04; box-shadow: 0 12px 28px rgba(0,0,0,0.6), 0 0 0 3px rgba(239,195,117,0.28); z-index: 2; }
.kj-won-card--win[data-red="true"] { color: var(--ink-bg); }
.kj-won-corner { font-family: 'IBM Plex Mono', monospace; font-size: 13px; font-weight: 500; line-height: 1; display: flex; align-items: baseline; }
.kj-won-corner--br { align-self: flex-end; transform: rotate(180deg); }
.kj-won-suit { font-size: 11px; }
.kj-won-pip { font-size: 20px; line-height: 1; align-self: center; }
.kj-won-head {
  position: absolute; left: 50%; top: 26%; transform: translateX(-50%); width: 300px;
  display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center;
  animation: kjWonIn .32s ease-out both;
}
@keyframes kjWonIn { from { opacity: 0; transform: translateX(-50%) translateY(8px); } to { opacity: 1; transform: translateX(-50%); } }
.kj-won-title { font-family: 'Archivo Black', sans-serif; font-size: 30px; line-height: 1; letter-spacing: -.02em; color: var(--gold); white-space: nowrap; }
.kj-won-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 16px; line-height: 1.4; color: var(--gold-ar); }
.kj-won-tally { display: flex; align-items: center; gap: 5px; margin-top: 2px; white-space: nowrap; }
.kj-won-tally i { width: 14px; height: 20px; border-radius: 999px; background: transparent; border: 1px solid var(--line6); display: block; box-sizing: border-box; }
.kj-won-tally i[data-on="1"] { background: var(--gold); border-color: var(--gold); }
.kj-won-tally-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-won-joker {
  position: absolute; left: 50%; top: 74%; transform: translateX(-50%); display: flex; align-items: center; gap: 8px;
  background: rgba(239,195,117,0.95); border-radius: 999px; padding: 5px 13px; white-space: nowrap;
  animation: kjWonIn .32s ease-out .12s both;
}
.kj-won-joker-en { font-size: 11.5px; font-weight: 800; line-height: 1.35; color: var(--ink-bg); }
.kj-won-joker-sep { width: 1px; height: 11px; background: rgba(12,16,9,0.28); display: inline-block; }
.kj-won-joker-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 10px; line-height: 1.5; color: var(--on-gold-2); }
.kj-seat[data-dim="1"] { opacity: .42; }
.kj-seat[data-dim="1"] .kj-seat-status { visibility: hidden; }

/* fixes measured on production (v110) */
.kj-high { display: flex; line-height: 1; font-size: 9.5px; }
.kj-last-fan .kj-lcard--win { position: relative; z-index: 2; }
/* the tab steps down while the TO PLAY pill owns 68% (mine: the boards never
   show both at once) */
body.kj-pill .kj-last { top: 80%; }
/* the auto-played pill sat on the TO PLAY pill; under the skin the caption
   line under the hand carries it instead (kjHandHint) */

/* ==========================================================================
   BOARD 46 — the readable hand, two tiers. 80x112 cards, 48px of every card
   showing (was 28), suit-grouped, the player arranges it (hold to drag), and
   everyone can count everyone else's. Plus board 15b's illegal strips (16px,
   still tappable) and 13a's lifted card. Layout is absolute, set by
   kjLayoutHand in app.js; the numbers here are the boards'.
   ========================================================================== */
/* the count pill under each chair */
.kj-count {
  display: flex; align-items: center; gap: 5px; box-sizing: border-box;
  background: rgba(9,13,8,0.72); border: 1px solid var(--line-strong); border-radius: 999px; padding: 3px 8px 3px 5px;
}
.kj-count-backs { display: flex; align-items: flex-end; height: 13px; }
.kj-count-backs i { display: block; width: 6px; border-radius: 999px; background: var(--ink-3); }
.kj-count-backs i:nth-child(1) { height: 11px; }
.kj-count-backs i:nth-child(2) { height: 12px; margin-inline-start: -2px; }
.kj-count-backs i:nth-child(3) { height: 13px; margin-inline-start: -2px; background: var(--ink-2); }
.kj-count-n { font-family: 'Archivo Black', sans-serif; font-size: 12px; line-height: 1; color: var(--ink-2); }
.kj-count--me { border-color: var(--gold); }
.kj-count--me .kj-count-backs i { background: var(--gold); }
.kj-count--me .kj-count-backs i:nth-child(3) { background: var(--ink); }
.kj-count--me .kj-count-n { color: var(--gold); }
.kj-seat[data-dim="1"] .kj-count { visibility: hidden; }

/* the sort chips (44px, above the hand) */
.kj-sort { height: 44px; box-sizing: border-box; display: flex; align-items: center; gap: 8px; padding: 0 14px; }
.kj-sort-chip {
  box-sizing: border-box; background: rgba(9,13,8,0.6); border: 1px solid var(--line-strong); border-radius: 999px;
  padding: 7px 13px; display: flex; align-items: center; gap: 5px; cursor: pointer; font-family: inherit;
  font-size: 11.5px; font-weight: 600; color: var(--ink-2); line-height: 1.2;
}
.kj-sort-chip[data-on="true"] { background: var(--gold); border-color: var(--gold); font-weight: 800; color: var(--ink-bg); }
.kj-sort-k { margin-left: auto; display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
[dir="rtl"] .kj-sort-k { margin-left: 0; margin-right: auto; align-items: flex-start; }
.kj-sort-en { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--gold); }
.kj-sort-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 9.5px; line-height: 1.4; color: var(--ink-3); }

/* the lane: sized by its tiers, not by a token */
body.kj-table .game-area { grid-template-rows: 53px minmax(0, 1fr) auto 0; }
body.kj-table .ga-hand {
  height: auto !important; min-height: 0 !important; max-height: none !important;
  padding: 0 !important; overflow: visible !important; border-top: 0 !important; box-shadow: none !important;
  background: none !important;
}
body.kj-table .ga-hand .hand-row { display: block; padding: 0; margin: 0; overflow: visible; }
/* Board 14 clips the resting hand at the lane's bottom edge (its 152px box is
   overflow:hidden), so the 14px drop sinks the cards UNDER the frame instead
   of over the caption line. Clip the bottom only: lifts, drags and shadows
   still go where they like above and beside the lane. */
body.kj-table .ga-hand .hand-row { clip-path: inset(-400px -400px 0 -400px); }
body.kj-table #hand {
  position: relative; display: block; height: var(--kj-hand-h, 112px); width: 100%;
  padding: 0 !important; margin: 0 !important; overflow: visible; min-height: 0; max-width: none;
}
/* ---- 6d.4a: the hand card is .kj-card - no legacy .card rule reaches it, so nothing below needs !important.
 * The values the legacy .card used to supply and no kj rule stated (found by hand-css-check.js, a real-Chromium diff
 * of every computed property against the live hand) are stated here, once. ---- */
body.kj-table #hand .kj-card { cursor: pointer; flex-shrink: 0; font-weight: 800; isolation: isolate; }
body.kj-table #hand .kj-card .corner { line-height: 16px; z-index: 2; }
body.kj-table #hand .kj-card .suit, body.kj-table #hand .kj-card .pip { font-variant-emoji: text; }
body.kj-table #hand .kj-card .corner .suit { margin-top: 1px; }
body.kj-table #hand .kj-card.invalid-play { pointer-events: none; cursor: default; }

body.kj-table #hand .kj-card {
  position: absolute; top: 0; left: 0; width: var(--kj-cw, 80px); height: var(--kj-ch, 112px); box-sizing: border-box;
  margin: 0; background: var(--card-cream); border-radius: 8px;
  /* A card edge is a LINE. At thirteen cards the sliver is 23px, and a 10px
     blurred shadow spread half of it into a soft gradient - thirteen cream
     cards with soft grey seams read as one cream slab, not as a hand. The
     hairline goes first so it sits on top of its own blur. */
  border: 1px solid rgba(239,195,117,0.42);
  box-shadow: -1px 0 0 rgba(23,19,15,0.5), -4px 4px 9px rgba(0,0,0,0.5);
  color: var(--card-ink); overflow: visible; transform: none; opacity: 1;
  transition: left .22s ease, top .22s ease, transform .16s ease, opacity .2s ease, width .16s ease;
  display: block; padding: 0; filter: none;
}
body.kj-table #hand .kj-card.red { color: var(--card-red); }
body.kj-table #hand .kj-card .corner.tl {
  position: absolute; left: 0; top: calc(var(--kj-cw, 80px) * 0.0875); right: auto; bottom: auto; width: calc(var(--kj-cw, 80px) * 0.55);
  display: flex; flex-direction: column; align-items: center; gap: 2px; margin: 0; padding: 0; transform: none;
}
/* boards 26-29: the face scales with the tier's card (80px card = 30/24/30/32) */
body.kj-table #hand .kj-card .corner.tl .rank {
  font-family: 'Archivo Black', sans-serif; font-size: calc(var(--kj-cw, 80px) * 0.375); line-height: 1; letter-spacing: -.05em; color: inherit; margin: 0;
}
body.kj-table #hand .kj-card[data-rank="Ten"] .corner.tl .rank { font-size: calc(var(--kj-cw, 80px) * 0.3); }
body.kj-table #hand .kj-card .corner.tl .suit { font-size: calc(var(--kj-cw, 80px) * 0.375); line-height: 1; color: inherit; margin: 0; }
body.kj-table #hand .kj-card .pip {
  position: absolute; inset: auto; right: calc(var(--kj-cw, 80px) * 0.1); bottom: calc(var(--kj-cw, 80px) * 0.075); left: auto; top: auto; width: auto; height: auto;
  font-size: calc(var(--kj-cw, 80px) * 0.4); line-height: 1; color: rgba(23,19,15,0.45); display: block; transform: none; margin: 0;
}
body.kj-table #hand .kj-card.red .pip { color: rgba(158,59,41,0.5); }
/* 15b: an illegal card is a 16px strip you can still reach — the shake and
   the hint are the answer, not an unreachable card */
/* 6d.4a: the face, the border and the ink of this state are 15b's (later in the file, resolves by order);
   the dead face this rule once declared with !important never showed - the four-colour rules beat it */
body.kj-table #hand .kj-card.invalid-play {
  transform: translateY(6px);
}
body.kj-table #hand .kj-card.invalid-play .corner.tl { width: var(--kj-strip, 16px); top: 9px; gap: 1px; }
body.kj-table #hand .kj-card.invalid-play .corner.tl .rank { font-size: calc(var(--kj-strip, 16px) * 0.75); letter-spacing: -.05em; }
body.kj-table #hand .kj-card.invalid-play .corner.tl .suit { font-size: calc(var(--kj-strip, 16px) * 0.9375); }
body.kj-table #hand .kj-card.invalid-play .pip { display: none; }
body.kj-table #hand .kj-card.invalid-play::after {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: var(--kj-strip, 16px); border-right: 1px dashed rgba(12,16,9,0.28);
}
body.kj-table #hand .kj-card.invalid-play.nudge, body.kj-table #hand .kj-card.invalid-play.shake {
  transform: translateY(6px) rotate(-3deg) translateX(-3px);   /* 6d.4a: border, shadow and ink are 15b's (later in the file) */
}
/* 13a: the card you are about to play lifts 36px on a warmer face */
body.kj-table #hand .kj-card.previewing, body.kj-table #hand .kj-card.preselected {
  transform: translateY(-36px); z-index: 5;
  background: linear-gradient(180deg, var(--card-cream-hi) 0%, var(--card-cream) 52%); border-color: var(--gold);
  box-shadow: inset 0 0 0 2px rgba(239,195,117,0.6), 0 16px 30px rgba(0,0,0,0.62);
}
body.kj-table #hand .kj-card.disabled { opacity: .72; }
/* 46: dragging */
body.kj-table #hand .kj-card.kj-dragging {
  transition: none; z-index: 6; opacity: 1; border-color: var(--gold);
  box-shadow: 0 22px 40px rgba(0,0,0,0.7); rotate: -4deg;
}
.kj-drop {
  position: absolute; box-sizing: border-box; background: var(--gold); border-radius: 8px; padding: 4px 8px; z-index: 7;
  font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; font-weight: 500; color: var(--ink-bg);
  transform: translate(-50%, -100%); white-space: nowrap; pointer-events: none;
}

/* board 08: the option lines are one line in the board's face; Manrope is
   wider and wrapped them, which grew the sheet up into the seat dots (mine) */
.kj-srow-desc { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }

/* ==========================================================================
   BOARD 18 — running totals. Full frame (the ceremony's canvas), the score
   headline, two team cards, bid / won per round with the running delta.
   ========================================================================== */
.kj-tot { background: radial-gradient(72% 40% at 50% 32%, var(--felt-1) 0%, var(--felt) 46%, var(--felt-2) 100%); }
.kj-tot::before { top: 14%; opacity: .09; }
.kj-tot::after { background: rgba(9,13,8,0.62); }
.kj-tot-head { position: absolute; top: 74px; left: 20px; right: 20px; display: flex; align-items: flex-end; justify-content: space-between; }
.kj-tot-hl { display: flex; flex-direction: column; gap: 5px; }
.kj-tot-title { font-family: 'Archivo Black', sans-serif; font-size: 26px; line-height: 1; letter-spacing: -.02em; color: var(--ink); }
.kj-tot-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 15px; line-height: 1.4; color: var(--gold-ar); }
.kj-tot-hr { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; }
.kj-tot-first { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--ink-3); }
.kj-tot-table { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-tot-grid { position: absolute; top: 156px; left: 20px; right: 20px; display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.kj-tot-team { background: var(--surface); border: 1px solid var(--surf4); border-radius: 16px; padding: 14px; display: flex; flex-direction: column; gap: 8px; box-sizing: border-box; min-width: 0; }
.kj-tot-team--us { background: var(--surf2); border-color: var(--gold); }
.kj-tot-name { display: flex; align-items: center; gap: 8px; min-width: 0; }
.kj-tot-glyph { font-size: 14px; color: var(--salmon); }
.kj-tot-team--us .kj-tot-glyph { color: var(--gold); }
.kj-tot-who { font-size: 12.5px; font-weight: 700; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kj-tot-team--us .kj-tot-who { color: var(--ink); }
.kj-tot-score { font-family: 'Archivo Black', sans-serif; font-size: 40px; line-height: 1; color: var(--ink-2); }
.kj-tot-team--us .kj-tot-score { color: var(--gold); }
.kj-tot-bar { height: 4px; border-radius: 999px; background: var(--surf4); overflow: hidden; }
.kj-tot-team--us .kj-tot-bar { background: var(--line-strong); }
.kj-tot-fill { height: 100%; background: var(--oxblood); }
.kj-tot-team--us .kj-tot-fill { background: var(--gold); }
.kj-tot-togo { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-tot-team--us .kj-tot-togo { color: var(--mint); }
.kj-tot-list { position: absolute; top: 336px; left: 20px; right: 20px; bottom: 96px; display: flex; flex-direction: column; gap: 8px; overflow-y: auto; }
.kj-tot-th { display: grid; grid-template-columns: 30px 1fr 1fr; gap: 12px; padding-bottom: 5px; border-bottom: 1px solid var(--surf4); flex: none; }
.kj-tot-th span { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kj-tot-th span:first-child { letter-spacing: .14em; }
.kj-tot-row { display: grid; grid-template-columns: 30px 1fr 1fr; gap: 12px; align-items: center; background: var(--surface); border: 1px solid var(--surf4); border-radius: 12px; padding: 10px 11px; flex: none; }
.kj-tot-row--now { background: var(--surf2); border-color: var(--line5); }
.kj-tot-n { font-family: 'Archivo Black', sans-serif; font-size: 14px; line-height: 1; color: var(--ink-3); }
.kj-tot-row--now .kj-tot-n { color: var(--gold); }
.kj-tot-cell { display: flex; align-items: baseline; gap: 8px; }
.kj-tot-bw { font-family: 'IBM Plex Mono', monospace; font-size: 12.5px; color: var(--ink-3); }
.kj-tot-bw--us { color: var(--ink-2); }
.kj-tot-delta { font-family: 'Archivo Black', sans-serif; font-size: 13px; color: var(--salmon); }
.kj-tot-delta[data-tone="gold"] { color: var(--gold); }
.kj-tot-empty { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); padding: 14px 0; text-align: center; }
.kj-tot-joker { display: flex; align-items: center; gap: 8px; margin-top: 4px; padding: 11px 12px; background: rgba(239,195,117,0.1); border: 1px solid var(--line5); border-radius: 12px; flex: none; }
.kj-tot-joker img { width: 40px; display: block; flex: none; }
.kj-tot-joker-col { display: flex; flex-direction: column; gap: 1px; }
.kj-tot-joker-en { font-size: 12px; font-weight: 800; line-height: 1.35; color: var(--gold); }
.kj-tot-joker-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 10px; line-height: 1.4; color: var(--ink-3); }
.kj-tot-foot { position: absolute; bottom: 30px; left: 20px; right: 20px; display: flex; gap: 12px; }
.kj-tot-hist { flex: 1; border: 1px solid var(--line5); background: none; color: var(--ghost-ink); font-size: 14px; font-weight: 600; padding: 13px 0; border-radius: 12px; text-align: center; cursor: pointer; font-family: inherit; }
.kj-tot-back { flex: 1.5; background: var(--gold); border: 0; color: var(--ink-bg); font-size: 15px; font-weight: 800; letter-spacing: .04em; padding: 15px 0; border-radius: 12px; text-align: center; cursor: pointer; font-family: inherit; }
.kj-score { pointer-events: auto; cursor: pointer; }

/* ==========================================================================
   BOARD 19 — the persona sheet, opened from a seat.
   ========================================================================== */
.kj-per { background: radial-gradient(72% 40% at 50% 32%, var(--felt-1) 0%, var(--felt) 46%, var(--felt-2) 100%); }
.kj-per::before { top: 16%; opacity: .09; }
.kj-per::after { background: rgba(9,13,8,0.6); }
.kj-per-top { position: absolute; top: 82px; left: 0; right: 0; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.kj-per-avw { position: relative; }
.kj-per-av { width: 96px; height: 96px; border-radius: 50%; background: var(--teal); border: 2px solid var(--gold); box-sizing: border-box; display: flex; align-items: center; justify-content: center; font-size: 34px; font-weight: 800; color: var(--ink); }
.kj-per-badge { position: absolute; right: -4px; bottom: -4px; width: 30px; height: 30px; border-radius: 50%; background: var(--ink-bg); border: 1px solid var(--line-strong); box-sizing: border-box; display: flex; align-items: center; justify-content: center; font-size: 13px; color: var(--gold); }
.kj-per-who { display: flex; flex-direction: column; align-items: center; gap: 5px; }
.kj-per-name { font-family: 'Archivo Black', sans-serif; font-size: 25px; line-height: 1; letter-spacing: -.02em; color: var(--ink); max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kj-per-seat { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-per-pill { display: flex; align-items: center; gap: 8px; background: rgba(239,195,117,0.12); border: 1px solid var(--gold-dim); border-radius: 999px; padding: 6px 15px; }
.kj-per-pill i { width: 7px; height: 7px; transform: rotate(45deg); background: var(--gold); display: block; }
.kj-per-pill-en { font-size: 12.5px; font-weight: 800; color: var(--gold); }
.kj-per-pill-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 11px; line-height: 1.4; color: var(--gold-ar); }
.kj-per-body { position: absolute; top: 372px; left: 20px; right: 20px; display: flex; flex-direction: column; gap: 12px; }
.kj-per-loading, .kj-per-note { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); text-align: center; padding: 6px 0; }
.kj-per-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.kj-per-stat { background: var(--surface); border: 1px solid var(--surf4); border-radius: 12px; padding: 12px 10px; display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.kj-per-stat-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); white-space: nowrap; }
.kj-per-stat-v { font-family: 'Archivo Black', sans-serif; font-size: 19px; line-height: 1; color: var(--ink); }
.kj-per-stat-v[data-gold="1"] { color: var(--gold); }
.kj-per-how { background: var(--surface); border: 1px solid var(--surf4); border-radius: 16px; padding: 14px 15px; display: flex; flex-direction: column; gap: 8px; }
.kj-per-how-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-per-how-list { display: flex; flex-direction: column; gap: 8px; }
.kj-per-how-row { display: flex; align-items: center; gap: 12px; }
.kj-per-how-l { font-size: 12px; color: var(--ink-2); width: 104px; flex: none; }
.kj-per-how-bar { flex: 1; height: 5px; border-radius: 999px; background: var(--surf4); overflow: hidden; }
.kj-per-how-bar div { height: 100%; }
.kj-per-how-p { font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; width: 30px; text-align: right; }
.kj-per-joker { display: flex; align-items: center; gap: 12px; background: rgba(239,195,117,0.1); border: 1px solid var(--line5); border-radius: 16px; padding: 12px 14px; }
.kj-per-joker img { width: 44px; display: block; flex: none; }
.kj-per-joker-col { display: flex; flex-direction: column; gap: 2px; }
.kj-per-joker-en { font-size: 12.5px; font-weight: 800; line-height: 1.35; color: var(--gold); }
.kj-per-joker-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 10.5px; line-height: 1.4; color: var(--ink-3); }
.kj-per-foot { position: absolute; bottom: 30px; left: 20px; right: 20px; display: flex; flex-direction: column; gap: 12px; }
.kj-per-primary { background: var(--gold); border: 0; color: var(--ink-bg); font-size: 15px; font-weight: 800; letter-spacing: .04em; padding: 15px 0; border-radius: 12px; text-align: center; cursor: pointer; font-family: inherit; }
.kj-per-primary:disabled { opacity: .6; cursor: default; }
.kj-per-row { display: flex; gap: 12px; }
.kj-per-ghost { flex: 1; border: 1px solid var(--line5); background: none; color: var(--ghost-ink); font-size: 14px; font-weight: 600; padding: 13px 0; border-radius: 12px; text-align: center; cursor: pointer; font-family: inherit; }

/* ==========================================================================
   BOARDS 20a/20b (reactions) and 21a/21b (partner signal). Sheets that live
   in the felt zone: a scrim over the felt and a panel at its bottom edge.
   ========================================================================== */
.kj-sheetzone { position: absolute; inset: 0; z-index: 9; pointer-events: auto; }
.kj-sheetzone-scrim { position: absolute; inset: 0; background: rgba(9,13,8,0.5); }
.kj-sig .kj-sheetzone-scrim { background: rgba(9,13,8,0.55); }
.kj-zpanel { position: absolute; left: 14px; right: 14px; bottom: 12px; background: var(--surface-sheet); border: 1px solid var(--line-strong); border-radius: 16px; padding: 14px; box-sizing: border-box; }
.kj-sig .kj-zpanel { padding: 16px; }
.kj-react-head { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.kj-react-title { font-family: 'Archivo Black', sans-serif; font-size: 14px; color: var(--ink); }
.kj-react-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 11px; line-height: 1.4; color: var(--gold-ar); }
.kj-react-cap { margin-left: auto; font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-react-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; }
.kj-react-tile {
  background: var(--surface); border: 1px solid var(--surf4); border-radius: 12px; padding: 9px 4px; cursor: pointer; font-family: inherit;
  display: flex; flex-direction: column; align-items: center; gap: 5px; min-width: 0;
}
.kj-react-tile--gold { background: var(--surf2); border-color: var(--gold); }
.kj-react-g { font-size: 19px; line-height: 1; color: var(--ink-2); }
.kj-react-tile--gold .kj-react-g { color: var(--gold); }
.kj-react-en { font-size: 9.5px; font-weight: 700; color: var(--ink-3); text-align: center; }
.kj-react-tile--gold .kj-react-en { color: var(--gold); }
.kj-react-ar2 { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 9.5px; line-height: 1.4; color: var(--ink-3); }
/* the burst: newest on top, the older two shrink and fade behind it */
.kj-burst { position: absolute; display: flex; flex-direction: column; gap: 8px; z-index: 8; pointer-events: none; }
.kj-burst-pill { display: flex; align-items: center; gap: 8px; background: rgba(239,195,117,0.95); border-radius: 12px 12px 4px 12px; padding: 6px 11px; animation: kjWonIn .22s ease-out both; }
.kj-burst-g { font-size: 15px; line-height: 1; color: var(--ink-bg); }
.kj-burst-en { font-size: 11.5px; font-weight: 800; color: var(--ink-bg); white-space: nowrap; }
.kj-burst-pill[data-n="1"] { background: rgba(239,195,117,0.78); padding: 5px 10px; transform: translateX(-14px) scale(.94); opacity: .86; animation: none; }
.kj-burst-pill[data-n="1"] .kj-burst-g { font-size: 13px; } .kj-burst-pill[data-n="1"] .kj-burst-en { font-size: 10.5px; }
.kj-burst-pill[data-n="2"] { background: rgba(239,195,117,0.56); padding: 4px 9px; gap: 5px; transform: translateX(-26px) scale(.88); opacity: .62; animation: none; }
.kj-burst-pill[data-n="2"] .kj-burst-g { font-size: 12px; } .kj-burst-pill[data-n="2"] .kj-burst-en { font-size: 10px; }
.kj-burst-more { display: flex; margin-top: 2px; margin-left: -26px; }
.kj-burst-more span { background: rgba(9,13,8,0.72); border: 1px solid var(--line-strong); border-radius: 999px; padding: 3px 9px; font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--gold); }
/* the joker, bottom-left, when a chair goes ten in a row */
.kj-burst-joker { position: absolute; left: 14px; bottom: 14px; display: flex; align-items: flex-end; gap: 8px; max-width: 244px; z-index: 8; pointer-events: none; }
.kj-burst-joker img { width: 46px; display: block; flex: none; }
.kj-burst-joker-box { background: var(--bubble); border-inline-start: 3px solid var(--bubble-edge); border-radius: 12px; border-start-start-radius: 3px; border-end-start-radius: 3px; padding: 8px 11px; display: flex; flex-direction: column; gap: 2px; }
.kj-burst-joker-en { font-size: 12px; font-weight: 800; line-height: 1.3; color: var(--bubble-ink); }
.kj-burst-joker-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 10px; line-height: 1.4; color: var(--bubble-ink-2); }
/* 21: signal */
.kj-sig-top { position: absolute; left: 50%; top: 30%; transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; gap: 5px; text-align: center; pointer-events: none; }
.kj-sig-only { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--gold); white-space: nowrap; }
.kj-sig-only-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 10.5px; line-height: 1.4; color: var(--ink-3); }
.kj-sig-pill { display: flex; align-items: center; gap: 8px; background: rgba(239,195,117,0.14); border: 1px solid var(--gold); border-radius: 999px; padding: 6px 14px; }
.kj-sig-pill-g { font-size: 15px; line-height: 1; color: var(--gold); }
.kj-sig-pill-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--gold); white-space: nowrap; }
.kj-sig-head { display: flex; align-items: flex-end; justify-content: space-between; margin-bottom: 14px; }
.kj-sig-hl { display: flex; flex-direction: column; gap: 5px; }
.kj-sig-title { font-family: 'Archivo Black', sans-serif; font-size: 18px; line-height: 1; color: var(--ink); }
.kj-sig-title-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 13px; line-height: 1.4; color: var(--gold-ar); }
.kj-sig-step { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-sig-step[data-gold="1"] { color: var(--gold); }
.kj-sig-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.kj-sig-card { background: var(--surface); border: 1px solid var(--surf4); border-radius: 16px; padding: 14px 10px; display: flex; flex-direction: column; align-items: center; gap: 8px; cursor: pointer; font-family: inherit; }
.kj-sig-card[data-on="true"] { background: var(--surf2); border-color: var(--gold); box-shadow: inset 0 0 0 1px rgba(239,195,117,0.26); }
.kj-sig-g { font-size: 22px; line-height: 1; color: var(--ink-3); }
.kj-sig-card[data-on="true"] .kj-sig-g { color: var(--gold); }
.kj-sig-en { font-family: 'Archivo Black', sans-serif; font-size: 13px; line-height: 1; color: var(--ink); }
.kj-sig-card[data-on="true"] .kj-sig-en { color: var(--gold); }
.kj-sig-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 11px; line-height: 1.4; color: var(--ink-3); }
.kj-sig-card[data-on="true"] .kj-sig-ar { color: var(--gold-ar); }
.kj-sig-desc { font-size: 9.5px; line-height: 1.4; color: var(--ink-3); text-align: center; }
.kj-sig-card[data-on="true"] .kj-sig-desc { color: var(--ink-2); }
.kj-sig-suits { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-bottom: 12px; }
.kj-sig-suit { background: var(--surface); border: 1px solid var(--surf4); border-radius: 16px; padding: 14px 6px; display: flex; flex-direction: column; align-items: center; gap: 5px; cursor: pointer; font-family: inherit; }
.kj-sig-suit[data-on="true"] { background: var(--surf2); border-color: var(--gold); box-shadow: inset 0 0 0 1px rgba(239,195,117,0.26); }
.kj-sig-suit-g { font-size: 28px; line-height: 1; color: var(--ink-2); }
.kj-sig-suit[data-red="true"] .kj-sig-suit-g { color: var(--salmon); }
.kj-sig-suit[data-on="true"] .kj-sig-suit-g { color: var(--gold); }
.kj-sig-suit-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 10px; line-height: 1.4; color: var(--ink-3); }
.kj-sig-suit[data-on="true"] .kj-sig-suit-ar { color: var(--gold-ar); }
.kj-sig-row { display: flex; gap: 12px; }
.kj-sig-back { flex: 1; border: 1px solid var(--line5); background: none; color: var(--ghost-ink); font-size: 14px; font-weight: 600; padding: 13px 0; border-radius: 12px; text-align: center; cursor: pointer; font-family: inherit; }
.kj-sig-send { flex: 1.6; background: var(--gold); border: 0; color: var(--ink-bg); font-size: 15px; font-weight: 800; letter-spacing: .04em; padding: 15px 0; border-radius: 12px; text-align: center; cursor: pointer; font-family: inherit; }

/* ==========================================================================
   BOARDS 22a (ritual caption) and 22b (felt caption)
   ========================================================================== */
.kj-ritual { position: absolute; inset: 0; pointer-events: none; z-index: 6; }
/* 2026-09-28: the ceremony's deck (kjPlayDeck) plays ABOVE the ritual caption,
   between the north chair and the rule - board 22a's caption is "never over
   a card", and the deck sat on it at the template's 52%. journey.html's
   kn-deck reads the top from --kn-deck-top (52% when unset). */
body.kj-table .kn-deck { --kn-deck-top: 27%; }
.kj-ritual-box { position: absolute; left: 50%; top: 46%; transform: translate(-50%, -50%); width: 240px; display: flex; flex-direction: column; align-items: center; gap: 12px; text-align: center; }
.kj-ritual-rule { display: flex; align-items: center; gap: 12px; width: 100%; }
.kj-ritual-rule i { flex: 1; height: 1px; background: rgba(239,195,117,0.34); display: block; }
.kj-ritual-diamond { width: 6px; height: 6px; transform: rotate(45deg); background: var(--gold); display: block; }
.kj-ritual-en { font-family: 'Archivo Black', sans-serif; font-size: 19px; line-height: 1.15; letter-spacing: 0; color: var(--ink); }
.kj-ritual-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 14px; line-height: 1.4; color: var(--gold-ar); }
.kj-ritual-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--ink-3); white-space: nowrap; }
.kj-ritual-dots { position: absolute; left: 50%; bottom: 26px; transform: translateX(-50%); display: flex; gap: 5px; }
.kj-ritual-dots i { width: 22px; height: 3px; border-radius: 999px; background: var(--line-strong); display: block; }
.kj-ritual-dots i[data-on="1"] { background: var(--gold); }
.kj-seat[data-dim="1"][data-keep="1"] .kj-seat-status { visibility: visible; }
.kj-fcap { position: absolute; inset: 0; pointer-events: none; z-index: 6; animation: kjWonIn .28s ease-out both; }
.kj-fcap-box { position: absolute; left: 50%; top: 46%; transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; }
.kj-fcap-g { font-size: 44px; line-height: 1; color: var(--gold); }
.kj-fcap-en { font-family: 'Archivo Black', sans-serif; font-size: 22px; line-height: 1; letter-spacing: 0; color: var(--ink); white-space: nowrap; }
.kj-fcap-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 15px; line-height: 1.4; color: var(--gold-ar); }
.kj-fcap-sub { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--ink-3); white-space: nowrap; }
.kj-fcap-joker { position: absolute; left: 16px; bottom: 26px; display: flex; align-items: flex-end; gap: 8px; max-width: 246px; }
.kj-fcap-joker img { width: 48px; display: block; flex: none; }
.kj-fcap-joker-box { background: var(--bubble); border-inline-start: 3px solid var(--bubble-edge); border-radius: 12px; border-start-start-radius: 3px; border-end-start-radius: 3px; padding: 8px 11px; display: flex; flex-direction: column; gap: 2px; }
.kj-fcap-joker-en { font-size: 12px; font-weight: 800; line-height: 1.3; color: var(--bubble-ink); }
.kj-fcap-joker-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 10.5px; line-height: 1.5; color: var(--bubble-ink-2); }

/* ==========================================================================
   BOARD 23 (a player dropped) and 24a/24b (connection lost)
   ========================================================================== */
.kj-seat[data-dropped="1"] .kj-av { background: var(--oxblood-wash) !important; border: 2px dashed var(--oxblood); color: var(--ink-4) !important; animation: none; }
.kj-seat[data-dropped="1"] .kj-seat-name { color: var(--salmon); }
.kj-seat[data-dropped="1"] .kj-seat-status { color: var(--salmon); letter-spacing: .14em; }
.kj-seat[data-bot="1"] .kj-av { background: var(--oxblood-wash) !important; border-color: var(--line-strong); color: var(--ink) !important; animation: none; }
.kj-seat[data-bot="1"] .kj-seat-status { color: var(--salmon); }
.kj-dropped .kj-sheetzone-scrim { background: rgba(9,13,8,0.74); }
.kj-drop-panel { position: absolute; left: 18px; right: 18px; top: 50%; transform: translateY(-50%); background: var(--surface-sheet); border: 1px solid var(--oxblood-line); border-radius: 22px; padding: 22px 20px; display: flex; flex-direction: column; align-items: center; gap: 16px; box-sizing: border-box; }
.kj-drop-ring { position: relative; width: 84px; height: 84px; }
.kj-drop-ring i { position: absolute; inset: 0; border-radius: 50%; border: 3px solid var(--oxblood-wash); display: block; box-sizing: border-box; }
.kj-drop-ring .kj-drop-ring-b { border-color: var(--gold); border-right-color: transparent; border-bottom-color: transparent; transform: rotate(38deg); animation: kjSpin 1.6s linear infinite; }
@keyframes kjSpin { to { transform: rotate(398deg); } }
.kj-drop-av { position: absolute; inset: 12px; border-radius: 50%; background: var(--oxblood-wash); display: flex; align-items: center; justify-content: center; font-size: 21px; font-weight: 800; color: var(--ink-2); }
.kj-drop-who { display: flex; flex-direction: column; align-items: center; gap: 5px; text-align: center; }
.kj-drop-title { font-family: 'Archivo Black', sans-serif; font-size: 21px; line-height: 1.1; letter-spacing: -.02em; color: var(--ink); }
.kj-drop-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 14px; line-height: 1.4; color: var(--gold-ar); }
.kj-drop-bot { width: 100%; display: flex; align-items: center; gap: 12px; background: var(--surface); border: 1px solid var(--surf4); border-radius: 12px; padding: 11px 13px; box-sizing: border-box; }
.kj-drop-bot-disc { width: 34px; height: 34px; border-radius: 50%; background: var(--surf2); border: 1px solid var(--line5); display: flex; align-items: center; justify-content: center; flex: none; }
.kj-drop-bot-disc img { width: 26px; display: block; }
.kj-drop-bot-col { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.kj-drop-bot-k { font-size: 12.5px; font-weight: 700; color: var(--ink); }
.kj-drop-bot-d { font-size: 11px; color: var(--ink-2); }
.kj-drop-bot-tag { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--gold); }
.kj-drop-btns { width: 100%; display: flex; flex-direction: column; gap: 8px; margin-top: 2px; }
.kj-drop-primary { background: var(--gold); border: 0; color: var(--ink-bg); font-size: 15px; font-weight: 800; letter-spacing: .04em; padding: 15px 0; border-radius: 12px; text-align: center; cursor: pointer; font-family: inherit; }
.kj-drop-ghost { border: 1px solid var(--line5); background: none; color: var(--ghost-ink); font-size: 13px; font-weight: 600; padding: 13px 0; border-radius: 12px; text-align: center; cursor: pointer; font-family: inherit; }
/* 24b: the banner over the felt's top edge */
.kj-reconn { position: absolute; left: 12px; right: 12px; top: 10px; z-index: 8; display: flex; align-items: center; gap: 12px; background: rgba(36,26,23,0.94); border: 1px solid var(--oxblood-line); border-radius: 12px; padding: 9px 12px; cursor: pointer; font-family: inherit; text-align: left; pointer-events: auto; }
.kj-reconn-col { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.kj-reconn-k { font-size: 12px; font-weight: 700; color: var(--ink); }
.kj-reconn-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 9.5px; line-height: 1.4; color: var(--salmon); }
.kj-reconn-clock { font-family: 'IBM Plex Mono', monospace; font-size: 10px; letter-spacing: .14em; color: var(--gold); }
body.kj-frozen #hand, body.kj-frozen .kj-rx, body.kj-frozen .kj-plan { pointer-events: none !important; }
body.kj-frozen #hand { opacity: .5 !important; }
/* 24a: the full frame */
.kj-noconn { background: radial-gradient(88% 60% at 50% 40%, var(--ink-bg2) 0%, var(--ink-bg) 68%); }
.kj-noconn::before, .kj-noconn::after { display: none; }
.kj-noconn-body { position: absolute; inset: 44px 0 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 20px; padding: 0 30px; }
.kj-noconn-mark { position: relative; width: 168px; display: flex; justify-content: center; }
.kj-noconn-mark img { width: 152px; display: block; filter: grayscale(.7) brightness(.72); }
.kj-noconn-mark i { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) rotate(-24deg); width: 176px; height: 2px; background: var(--oxblood); display: block; }
.kj-noconn-col { display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; }
.kj-noconn-title { font-family: 'Archivo Black', sans-serif; font-size: 28px; line-height: 1.05; letter-spacing: -.02em; color: var(--ink); }
.kj-noconn-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 17px; line-height: 1.4; color: var(--gold-ar); }
.kj-noconn-d { font-size: 13.5px; line-height: 1.6; color: var(--ink-2); max-width: 260px; text-wrap: pretty; }
.kj-noconn-pill { display: flex; align-items: center; gap: 8px; background: rgba(158,59,41,0.14); border: 1px solid var(--oxblood-line); border-radius: 999px; padding: 7px 15px; }
.kj-noconn-pill-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--salmon); }
.kj-noconn-bar { width: 200px; height: 3px; border-radius: 999px; background: var(--oxblood-wash); overflow: hidden; }
.kj-noconn-bar div { height: 100%; background: var(--gold); animation: kjRetry 2.4s ease-in-out infinite; }
@keyframes kjRetry { 0% { width: 8%; } 50% { width: 92%; } 100% { width: 8%; } }
.kj-noconn-foot { position: absolute; bottom: 34px; left: 24px; right: 24px; display: flex; flex-direction: column; gap: 12px; }
.kj-noconn-retry { background: var(--gold); border: 0; color: var(--ink-bg); font-size: 15px; font-weight: 800; letter-spacing: .04em; padding: 15px 0; border-radius: 12px; text-align: center; cursor: pointer; font-family: inherit; }
.kj-noconn-leave { border: 1px solid var(--line5); background: none; color: var(--ghost-ink); font-size: 14px; font-weight: 600; padding: 13px 0; border-radius: 12px; text-align: center; cursor: pointer; font-family: inherit; }

/* ==========================================================================
   BOARDS 26-29 · 28a · 47 — five tiers instead of eighteen breakpoints.
   app.js stamps body.kj-compact (≤399), nothing for the phone (400-767),
   kj-tablet (768-1279), kj-wide (≥1280), plus kj-landscape when the viewport
   is 4:3 or wider and ≥700px. Every number is the board's; the card face
   scales with --kj-cw (set by kjLayoutHand), the rest is per-tier CSS.
   ========================================================================== */

/* -- the card's radius follows its width (7 / 8 / 9 / 10 / 12 on the boards) */
body.kj-table #hand .kj-card { border-radius: calc(var(--kj-cw, 80px) * 0.1); }

/* -- 27 / 28a / 29: the bar has width for the readouts ---------------------- */
.kj-bar-ro { display: flex; align-items: center; gap: 20px; margin-left: 30px; }
.kj-bar-ro-g { display: flex; align-items: baseline; gap: 5px; }
.kj-bar-ro-k { font-family: 'IBM Plex Mono', monospace; font-size: 10px; letter-spacing: .14em; color: var(--ink-3); }
.kj-bar-ro-us { font-family: 'Archivo Black', sans-serif; font-size: 17px; line-height: 1; color: var(--gold); }
.kj-bar-ro-sl { font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: var(--ink-3); }
.kj-bar-ro-them { font-family: 'Archivo Black', sans-serif; font-size: 17px; line-height: 1; color: var(--salmon); }
.kj-bar-ro-bid { font-family: 'Archivo Black', sans-serif; font-size: 14px; line-height: 1; color: var(--ink); }
.kj-bar-ro-sep { display: block; width: 1px; height: 22px; background: var(--line); }
/* the roomy bar: 60px (28a/29), 64px on the tablet (27) */
body.kj-table.kj-landscape #ga-top, body.kj-table.kj-wide #ga-top { height: 60px; min-height: 60px; }
body.kj-table.kj-landscape .game-area, body.kj-table.kj-wide .game-area { grid-template-rows: 60px minmax(0, 1fr) auto 0; }
body.kj-landscape .kj-bar, body.kj-wide .kj-bar { height: 60px; gap: 12px; padding: 0 19px; }
body.kj-landscape .kj-bar-back, body.kj-wide .kj-bar-back { font-size: 18px; }
body.kj-landscape .kj-bar-mark, body.kj-wide .kj-bar-mark { width: 30px; height: 30px; }
body.kj-landscape .kj-bar-mark img, body.kj-wide .kj-bar-mark img { width: 25px; }
body.kj-landscape .kj-bar-round, body.kj-wide .kj-bar-round, body.kj-tablet .kj-bar-round { font-size: 13px; }
body.kj-landscape .kj-bar-trick, body.kj-wide .kj-bar-trick, body.kj-tablet .kj-bar-trick { font-size: 10px; }
body.kj-landscape .kj-bar-right, body.kj-wide .kj-bar-right { gap: 12px; }
body.kj-landscape .kj-bar-trump, body.kj-wide .kj-bar-trump { padding: 5px 11px; }
body.kj-landscape .kj-bar-trump-k, body.kj-wide .kj-bar-trump-k, body.kj-tablet .kj-bar-trump-k { font-size: 10px; }
body.kj-landscape .kj-bar-trump-g, body.kj-wide .kj-bar-trump-g { font-size: 16px; }
body.kj-landscape .kj-bar-more, body.kj-wide .kj-bar-more { font-size: 16px; }
body.kj-table.kj-tablet:not(.kj-landscape) #ga-top { height: 64px; min-height: 64px; }
body.kj-table.kj-tablet:not(.kj-landscape) .game-area { grid-template-rows: 64px minmax(0, 1fr) auto 0; }
body.kj-tablet:not(.kj-landscape) .kj-bar { height: 64px; gap: 12px; padding: 0 20px; }
body.kj-tablet:not(.kj-landscape) .kj-bar-back { font-size: 19px; }
body.kj-tablet:not(.kj-landscape) .kj-bar-mark { width: 32px; height: 32px; }
body.kj-tablet:not(.kj-landscape) .kj-bar-mark img { left: 3px; width: 27px; }
body.kj-tablet:not(.kj-landscape) .kj-bar-ro { margin-left: 32px; gap: 20px; }
body.kj-tablet:not(.kj-landscape) .kj-bar-ro-us, body.kj-tablet:not(.kj-landscape) .kj-bar-ro-them { font-size: 18px; }
body.kj-tablet:not(.kj-landscape) .kj-bar-ro-sl { font-size: 12px; }
body.kj-tablet:not(.kj-landscape) .kj-bar-ro-sep { height: 23px; }
body.kj-tablet:not(.kj-landscape) .kj-bar-ro-bid { font-size: 15px; }
body.kj-tablet:not(.kj-landscape) .kj-bar-right { gap: 12px; }
body.kj-tablet:not(.kj-landscape) .kj-bar-trump { padding: 6px 12px; }
body.kj-tablet:not(.kj-landscape) .kj-bar-trump-g { font-size: 17px; }
body.kj-tablet:not(.kj-landscape) .kj-bar-more { font-size: 17px; }

/* -- 26a: the compact phone (≤399) — 45px chairs at 13/87, tiles collapse to
   chips, 44px corner squares. The LAST edge tab (17a) stays where 14 put it. */
body.kj-compact #view-room .felt::before { inset: 13px; }
body.kj-compact #view-room .felt-logo, body.kj-compact #view-room .felt-logo img { width: 88px; height: 88px; }
body.kj-compact .kj-seat { width: 95px; }
body.kj-compact .kj-av { width: 45px; height: 45px; }
/* 26a draws no caption line: the chair status and the hand's hint carry it */
body.kj-compact .kj-cap { display: none; }
body.kj-compact .kj-seat-name { font-size: 11px; }
body.kj-compact .kj-score {
  left: 8px; top: 8px; transform: none; flex-direction: row; align-items: center; gap: 5px; min-width: 0;
  background: rgba(9,13,8,0.76); border-radius: 8px; padding: 4px 8px;
}
body.kj-compact .kj-score-k, body.kj-compact .kj-score-won { display: none; }
body.kj-compact .kj-score-us, body.kj-compact .kj-score-them { font-size: 13px; }
body.kj-compact .kj-score-sl { font-size: 9.5px; }
body.kj-compact .kj-tomake {
  right: 8px; top: 8px; transform: none; width: auto; flex-direction: row; align-items: center; gap: 5px;
  background: rgba(9,13,8,0.76); border: 1px solid var(--line-strong); border-radius: 8px; padding: 4px 8px;
}
body.kj-compact .kj-tomake-k { font-size: 9.5px; letter-spacing: .14em; }
body.kj-compact .kj-tomake-n { font-size: 13px; }
body.kj-compact .kj-tomake-more, body.kj-compact .kj-tomake-ar { display: none; }
body.kj-compact .kj-slot { width: 57px; height: 78px; border-radius: 8px; }
body.kj-compact .kj-slot-suit { font-size: 14px; }
body.kj-compact .kj-plan { left: 8px; bottom: 8px; }
body.kj-compact .kj-rx { right: 8px; bottom: 8px; gap: 5px; }
body.kj-compact .kj-rx-btn { width: 44px; height: 44px; border-radius: 12px; background: rgba(9,13,8,0.7); border-color: var(--line); font-size: 17px; }

/* -- 26b: the large phone (430) — nothing moves, everything grows ----------- */
@media (min-width: 420px) {
  body.kj-table:not(.kj-compact):not(.kj-tablet):not(.kj-wide):not(.kj-landscape) #view-room .felt::before { inset: 16px; }
  body.kj-table:not(.kj-compact):not(.kj-tablet):not(.kj-wide):not(.kj-landscape) .kj-av { width: 56px; height: 56px; font-size: 20px; }
  body.kj-table:not(.kj-compact):not(.kj-tablet):not(.kj-wide):not(.kj-landscape) .kj-seat-name { font-size: 13px; }
  body.kj-table:not(.kj-compact):not(.kj-tablet):not(.kj-wide):not(.kj-landscape) .kj-seat-status { font-size: 10px; }
  body.kj-table:not(.kj-compact):not(.kj-tablet):not(.kj-wide):not(.kj-landscape) .kj-slot { width: 78px; height: 107px; border-radius: 8px; gap: 5px; }
  body.kj-table:not(.kj-compact):not(.kj-tablet):not(.kj-wide):not(.kj-landscape) .kj-rx { gap: 8px; }
  body.kj-table:not(.kj-compact):not(.kj-tablet):not(.kj-wide):not(.kj-landscape) .kj-rx-btn { width: 48px; height: 48px; border-radius: 16px; background: rgba(9,13,8,0.7); border-color: var(--line); font-size: 19px; }
}

/* -- 27: the tablet portrait (768-1279) — 74px chairs at 12/88, readouts in
   the bar, 88px trick cards, 60px corner clusters (react + signal left,
   LAST + SCORE right), 120px hand. Still touch: no hover here. */
body.kj-tablet:not(.kj-landscape) #view-room .felt::before { inset: 22px; }
body.kj-tablet:not(.kj-landscape) #view-room .felt-logo, body.kj-tablet:not(.kj-landscape) #view-room .felt-logo img { width: 164px; height: 164px; }
body.kj-tablet:not(.kj-landscape) .kj-seat { width: 155px; gap: 8px; }
body.kj-tablet:not(.kj-landscape) .kj-av { width: 74px; height: 74px; font-size: 27px; }
body.kj-tablet:not(.kj-landscape) .kj-seat-name { font-size: 18px; max-width: 150px; }
body.kj-tablet:not(.kj-landscape) .kj-seat-status { font-size: 13px; }
body.kj-tablet:not(.kj-landscape) .kj-seat-status[data-tone="follow"] { font-size: 13px; }
body.kj-tablet:not(.kj-landscape) #view-room .ga-felt .trick { --pc-w: 88px; --pc-h: 123px; }
body.kj-tablet:not(.kj-landscape) #view-room .ga-felt .trick .played-card { border-radius: 8px; padding: 8px 9px; box-shadow: 0 3px 12px rgba(0,0,0,0.45); }
body.kj-tablet:not(.kj-landscape) #view-room .ga-felt .trick .played-card.west { left: 32%; }
body.kj-tablet:not(.kj-landscape) #view-room .ga-felt .trick .played-card.east { left: 68%; }
body.kj-tablet:not(.kj-landscape) #view-room .ga-felt .trick .played-card .corner,
body.kj-tablet:not(.kj-landscape) #view-room .ga-felt .trick .played-card .corner .rank { font-size: 19px; }
body.kj-tablet:not(.kj-landscape) #view-room .ga-felt .trick .played-card .corner .suit { font-size: 17px; }
body.kj-tablet:not(.kj-landscape) #view-room .ga-felt .trick .played-card .pip { font-size: 30px; }
body.kj-tablet:not(.kj-landscape) .kj-slot { width: 104px; height: 143px; border-radius: 12px; gap: 8px; border-color: rgba(239,195,117,0.34); }
body.kj-tablet:not(.kj-landscape) .kj-slot-suit { font-size: 26px; }
body.kj-tablet:not(.kj-landscape) .kj-slot-k { font-size: 14px; letter-spacing: .18em; }
body.kj-tablet:not(.kj-landscape) .kj-slot--waiting { width: 150px; height: 190px; }
body.kj-tablet:not(.kj-landscape) .kj-high { margin-top: -78px; }
body.kj-tablet:not(.kj-landscape) .kj-cap { width: 420px; gap: 8px; }
body.kj-tablet:not(.kj-landscape) .kj-cap-en { font-size: 12px; letter-spacing: .18em; }
body.kj-tablet:not(.kj-landscape) .kj-cap-ar { font-size: 14px; }
body.kj-tablet:not(.kj-landscape) .kj-cap-pill-k { font-size: 12px; }
body.kj-tablet:not(.kj-landscape) .kj-cap-av { width: 26px; height: 26px; font-size: 11px; }
body.kj-tablet:not(.kj-landscape) .kj-plan { display: none; }
body.kj-tablet:not(.kj-landscape) .kj-rx { left: 22px; right: auto; bottom: 22px; gap: 12px; }
body.kj-tablet:not(.kj-landscape) .kj-rx-btn { width: 60px; height: 60px; border-radius: 16px; background: rgba(9,13,8,0.72); border-color: var(--line); font-size: 24px; }
.kj-rrail--t { position: absolute; right: 22px; bottom: 22px; display: flex; gap: 12px; z-index: 6; }
.kj-rrail--t .kj-rail-sq { width: 60px; height: 60px; border-radius: 16px; background: rgba(9,13,8,0.72); border-color: var(--line); }
.kj-rrail--t .kj-rail-sq-g { font-size: 19px; }
.kj-rrail--t .kj-rail-sq-k { font-size: 9.5px; }
.kj-rail-sq-g[data-gold="1"] { color: var(--gold); }
.kj-rail-sq:disabled { opacity: .45; cursor: default; }
body.kj-tablet:not(.kj-landscape) .kj-last { display: none; }
body.kj-tablet:not(.kj-landscape) .ga-hand { padding-bottom: 0 !important; }

/* 27 / 28a / 29: sheets stop being bottom sheets — a centred dialog (560px on
   the tablet, 620 in landscape, 480 on the desktop) over a 62% / 55% scrim */
body.kj-tablet .kj-sheetzone-scrim, body.kj-wide .kj-sheetzone-scrim, body.kj-tablet .kj-lsheet, body.kj-wide .kj-lsheet { background: rgba(9,13,8,0.62); }
body.kj-landscape .kj-sheetzone-scrim, body.kj-landscape .kj-lsheet { background: rgba(9,13,8,0.55); }
body.kj-tablet .kj-zpanel, body.kj-landscape .kj-zpanel, body.kj-wide .kj-zpanel,
body.kj-tablet .kj-lpanel, body.kj-landscape .kj-lpanel, body.kj-wide .kj-lpanel,
body.kj-tablet .kj-drop-panel, body.kj-landscape .kj-drop-panel, body.kj-wide .kj-drop-panel {
  left: 50%; right: auto; top: 50%; bottom: auto; transform: translate(-50%, -50%);
  width: min(560px, calc(100% - 36px)); max-height: 70%; overflow: auto; box-sizing: border-box;
}
body.kj-landscape .kj-zpanel, body.kj-landscape .kj-lpanel, body.kj-landscape .kj-drop-panel { width: min(620px, calc(100% - 36px)); }
body.kj-wide .kj-zpanel, body.kj-wide .kj-lpanel, body.kj-wide .kj-drop-panel { width: min(480px, calc(100% - 36px)); }

/* -- 28a / 47: landscape (4:3 and wider, ≥700) — a wide ellipse, west and
   east as horizontal clusters, your own chair off the felt into the left
   thumb rail, 84px trick cards, the whole hand in one row. */
body.kj-landscape #view-room .felt { background: radial-gradient(58% 74% at 50% 46%, var(--felt-1) 0%, var(--felt) 46%, var(--felt-2) 100%) !important; }
body.kj-landscape #view-room .felt::before { inset: 19px; border-radius: 50% / 34%; }
body.kj-landscape #view-room .felt-logo, body.kj-landscape #view-room .felt-logo img { width: 119px; height: 119px; }
body.kj-landscape .kj-seat { width: 134px; gap: 8px; }
body.kj-landscape .kj-av { width: 64px; height: 64px; font-size: 23px; }
body.kj-landscape .kj-seat-name { font-size: 15px; max-width: 130px; }
body.kj-landscape .kj-seat-status { font-size: 12px; }
body.kj-landscape .kj-seat-status[data-tone="follow"] { font-size: 12px; }
.kj-seat--h {
  width: auto; display: grid; grid-template-columns: 64px auto; column-gap: 12px; row-gap: 3px;
  align-items: center; justify-items: start; text-align: left;
}
.kj-seat--h .kj-av-box { grid-column: 1; grid-row: 1 / span 3; }
.kj-seat--h .kj-seat-name { grid-column: 2; grid-row: 1; font-size: 14px; align-self: end; }
.kj-seat--h .kj-seat-status { grid-column: 2; grid-row: 2; font-size: 10px; align-self: start; max-width: 112px; overflow: hidden; text-overflow: ellipsis; }
.kj-seat--h .kj-count { grid-column: 2; grid-row: 3; }
.kj-seat--hr { grid-template-columns: auto 64px; justify-items: end; text-align: right; }
.kj-seat--hr .kj-av-box { grid-column: 2; }
.kj-seat--hr .kj-seat-name, .kj-seat--hr .kj-seat-status, .kj-seat--hr .kj-count { grid-column: 1; }
body.kj-landscape #view-room .ga-felt .trick { --pc-w: 84px; --pc-h: 118px; }
body.kj-landscape #view-room .ga-felt .trick .played-card { border-radius: 8px; padding: 8px 8px; box-shadow: 0 3px 12px rgba(0,0,0,0.45); }
body.kj-landscape #view-room .ga-felt .trick .played-card.west  { left: 34%; top: 52%; rotate: -8deg; }
/* 28a draws north at 26%; our felt is shorter (sort row + caption in the lane), so the card sat on
   the north chair's card count. 28% clears it — MINE. */
body.kj-landscape #view-room .ga-felt .trick .played-card.north { left: 50%; top: 28%; }
body.kj-landscape #view-room .ga-felt .trick .played-card.east  { left: 66%; top: 52%; }
body.kj-landscape #view-room .ga-felt .trick .played-card.south { left: 50%; top: 74%; }
body.kj-landscape #view-room .ga-felt .trick .played-card .corner,
body.kj-landscape #view-room .ga-felt .trick .played-card .corner .rank { font-size: 18px; }
body.kj-landscape #view-room .ga-felt .trick .played-card .corner .suit { font-size: 16px; }
body.kj-landscape #view-room .ga-felt .trick .played-card .pip { font-size: 29px; }
body.kj-landscape .kj-slot { width: 99px; height: 136px; border-radius: 12px; gap: 8px; border-color: rgba(239,195,117,0.34); }
body.kj-landscape .kj-slot-suit { font-size: 25px; }
body.kj-landscape .kj-slot-k { font-size: 13px; letter-spacing: .18em; }
body.kj-landscape .kj-slot--waiting { width: 140px; height: 180px; }
body.kj-landscape .kj-high { margin-top: -75px; }
body.kj-landscape .kj-cap { width: 480px; gap: 5px; }
body.kj-landscape .kj-cap-en { font-size: 11px; letter-spacing: .18em; }
body.kj-landscape .kj-cap-ar { font-size: 13px; }
body.kj-landscape .kj-cap-pill-k { font-size: 11px; }
body.kj-landscape .kj-plan, body.kj-landscape .kj-rx, body.kj-landscape .kj-last { display: none; }
body.kj-landscape .ga-hand { padding-bottom: 24px !important; }

/* the thumb rails: identity + REACT bottom-left, SIGNAL + LAST + SCORE
   bottom-right, all 56px, all within reach of a corner */
.kj-lrail { position: absolute; left: 20px; bottom: 30px; display: flex; align-items: flex-end; gap: 12px; z-index: 5; }
.kj-rrail { position: absolute; right: 20px; bottom: 30px; display: flex; align-items: flex-end; gap: 12px; z-index: 5; }
.kj-lrail-id {
  display: flex; align-items: center; gap: 12px; background: rgba(9,13,8,0.82); border: 1px solid var(--line-strong);
  border-radius: 16px; padding: 9px 14px 9px 9px;
}
.kj-lrail-av {
  width: 44px; height: 44px; border-radius: 50%; box-sizing: border-box; background: var(--teal); border: 2px solid var(--line-strong);
  display: flex; align-items: center; justify-content: center; font-size: 17px; font-weight: 800; color: var(--ink); flex: none;
}
.kj-lrail-av[data-active="1"] { border-color: var(--gold); animation: knRing 1.6s ease-out infinite; }
.kj-lrail-col { display: flex; flex-direction: column; gap: 2px; }
.kj-lrail-you { font-size: 13px; font-weight: 700; color: var(--gold); }
.kj-lrail-line { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--mint); white-space: nowrap; }
.kj-rail-sq {
  width: 56px; height: 56px; border-radius: 16px; box-sizing: border-box; background: rgba(9,13,8,0.82); border: 1px solid var(--line-strong);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  padding: 0; margin: 0; cursor: pointer; font-family: inherit; flex: none;
}
.kj-rail-sq-g { font-size: 20px; line-height: 1; color: var(--ink-2); }
.kj-rail-sq-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-rrail-last {
  display: flex; align-items: center; gap: 8px; background: rgba(9,13,8,0.82); border: 1px solid var(--line-strong);
  border-radius: 16px; padding: 9px 13px; cursor: pointer; font-family: inherit; color: inherit; text-align: left;
}
.kj-rrail-last .kj-last-k { align-items: flex-start; gap: 2px; }
.kj-rrail-last .kj-last-en { font-size: 9.5px; letter-spacing: .14em; }
.kj-rrail-last .kj-last-ar { font-size: 9.5px; color: var(--ink-3); }

/* -- 29: the desktop (≥1280) — a 300px rail takes score, the round table,
   the last trick and the react strip; the pointer gets a hover lift. */
body.kj-table.kj-wide .game-area {
  grid-template-columns: minmax(0, 1fr) 300px;
  grid-template-areas: "top top" "felt rail" "hand rail" ". rail";
}
body.kj-wide .kj-rail {
  grid-area: rail; box-sizing: border-box; background: var(--ink-bg2); border-left: 1px solid var(--surf3); padding: 18px;
  display: flex; flex-direction: column; gap: 16px; min-height: 0; overflow: auto;
}
[dir="rtl"] body.kj-wide .kj-rail { border-left: 0; border-right: 1px solid var(--surf3); }
.kj-rail-sec { display: flex; flex-direction: column; gap: 8px; }
.kj-rail-sec:first-child { gap: 8px; }
.kj-rail-hd { display: flex; align-items: center; gap: 8px; }
.kj-rail-title { font-family: 'IBM Plex Mono', monospace; font-size: 10px; letter-spacing: .18em; color: var(--ink-3); }
.kj-rail-sub { margin-left: auto; font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; color: var(--ink-3); letter-spacing: 0; }
.kj-rail-teams { display: flex; gap: 8px; }
.kj-rail-team { flex: 1; background: var(--surface); border: 1px solid var(--surf4); border-radius: 12px; padding: 11px 12px; display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.kj-rail-team--us { background: var(--surf2); border-color: var(--gold); }
.kj-rail-team-n { display: flex; align-items: center; gap: 5px; font-size: 10.5px; font-weight: 700; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kj-rail-team-n::before { content: "♥"; font-size: 12px; color: var(--salmon); }
.kj-rail-team--us .kj-rail-team-n { color: var(--ink); }
.kj-rail-team--us .kj-rail-team-n::before { content: "♠"; color: var(--gold); }
.kj-rail-team-s { font-family: 'Archivo Black', sans-serif; font-size: 26px; line-height: 1; color: var(--ink-2); }
.kj-rail-team--us .kj-rail-team-s { color: var(--gold); }
.kj-rail-rounds { display: flex; flex-direction: column; gap: 8px; }
.kj-rail-rounds-k { font-family: 'IBM Plex Mono', monospace; font-size: 10px; letter-spacing: .18em; color: var(--ink-3); }
.kj-rail-tbl { display: flex; flex-direction: column; gap: 8px; }
.kj-rail-row { display: grid; grid-template-columns: 18px 1fr 1fr; gap: 8px; align-items: center; background: var(--surface); border: 1px solid var(--surf4); border-radius: 8px; padding: 8px 10px; }
.kj-rail-n { font-family: 'Archivo Black', sans-serif; font-size: 11px; color: var(--ink-3); }
.kj-rail-cell { display: flex; align-items: baseline; gap: 5px; }
.kj-rail-bw { font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: var(--ink-3); }
.kj-rail-cell:nth-child(2) .kj-rail-bw { color: var(--ink-2); }
.kj-rail-delta { font-family: 'Archivo Black', sans-serif; font-size: 11px; color: var(--salmon); }
.kj-rail-delta[data-tone="gold"] { color: var(--gold); }
.kj-rail-delta[data-tone="dim"] { color: var(--ink-4); }
.kj-rail-empty { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); padding: 8px 10px; background: var(--surface); border: 1px solid var(--surf4); border-radius: 8px; }
.kj-rail-fan { display: flex; align-items: center; }
.kj-rail-fan .kj-lcard + .kj-lcard { margin-inline-start: -19px; }
.kj-rail-sec .kj-rail-fan, .kj-rail-who { background: var(--surface); }
.kj-rail-sec .kj-rail-fan { border: 1px solid var(--surf4); border-radius: 12px 12px 0 0; padding: 10px 12px 0; }
.kj-rail-who { display: flex; flex-direction: column; gap: 2px; border: 1px solid var(--surf4); border-top: 0; border-radius: 0 0 12px 12px; padding: 6px 12px 10px; }
.kj-rail-who-en { font-size: 11px; font-weight: 700; color: var(--gold); }
.kj-rail-who-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 9.5px; line-height: 1.4; color: var(--ink-3); }
.kj-rail-react { display: grid; grid-template-columns: repeat(5, 1fr); gap: 5px; }
.kj-rail-react-b {
  height: 38px; border-radius: 12px; background: var(--surface); border: 1px solid var(--surf4); display: flex; align-items: center;
  justify-content: center; font-size: 15px; color: var(--ink-2); padding: 0; margin: 0; cursor: pointer; font-family: inherit;
  transition: transform .12s ease, border-color .12s ease;
}
.kj-rail-react-b--gold { background: var(--surf2); border-color: var(--gold); color: var(--gold); }
.kj-rail-react-b:hover { transform: translateY(-3px); border-color: var(--gold); }
.kj-rail-joker { margin-top: auto; display: flex; align-items: center; gap: 8px; background: rgba(239,195,117,0.1); border: 1px solid var(--line5); border-radius: 12px; padding: 10px 12px; }
.kj-rail-joker img { width: 36px; display: block; flex: none; }
.kj-rail-joker-col { display: flex; flex-direction: column; gap: 1px; }
.kj-rail-joker-en { font-size: 11px; font-weight: 800; line-height: 1.35; color: var(--gold); }
.kj-rail-joker-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 9.5px; line-height: 1.4; color: var(--ink-3); }

body.kj-wide #view-room .felt::before { inset: 20px; }
body.kj-wide #view-room .felt-logo, body.kj-wide #view-room .felt-logo img { width: 129px; height: 129px; }
body.kj-wide .kj-seat { width: 145px; }
body.kj-wide .kj-av { width: 69px; height: 69px; font-size: 25px; }
body.kj-wide .kj-seat-name { font-size: 17px; max-width: 140px; }
body.kj-wide .kj-seat--h { column-gap: 12px; grid-template-columns: 68px auto; }
body.kj-wide .kj-seat--hr { grid-template-columns: auto 68px; }
body.kj-wide .kj-seat--h .kj-av { width: 68px; height: 68px; }
body.kj-wide .kj-seat--h .kj-seat-name { font-size: 15px; }
body.kj-wide .kj-seat--h .kj-seat-status { font-size: 10.5px; }
/* the pointer tier marks the active chair with a still 5px halo, not the pulse */
body.kj-wide .kj-seat[data-active="1"] .kj-av { animation: none; box-shadow: 0 0 0 5px rgba(239,195,117,0.16); }
body.kj-wide #view-room .ga-felt .trick { --pc-w: 90px; --pc-h: 126px; }
body.kj-wide #view-room .ga-felt .trick .played-card { border-radius: 8px; padding: 8px 9px; }
body.kj-wide #view-room .ga-felt .trick .played-card.west  { left: 35%; }
body.kj-wide #view-room .ga-felt .trick .played-card.north { top: 27%; }
body.kj-wide #view-room .ga-felt .trick .played-card.east  { left: 65%; }
body.kj-wide #view-room .ga-felt .trick .played-card .corner,
body.kj-wide #view-room .ga-felt .trick .played-card .corner .rank { font-size: 20px; }
body.kj-wide #view-room .ga-felt .trick .played-card .corner .suit { font-size: 17px; }
body.kj-wide #view-room .ga-felt .trick .played-card .pip { font-size: 31px; }
body.kj-wide .kj-slot { width: 106px; height: 146px; border-radius: 12px; }
body.kj-wide .kj-slot-suit { font-size: 27px; }
body.kj-wide .kj-slot-k { font-size: 14px; }
body.kj-wide .kj-high { margin-top: -79px; }
body.kj-wide .kj-cap-en { font-size: 11.5px; }
body.kj-wide .kj-cap-ar { font-size: 13.5px; }
body.kj-wide .kj-lrail { left: 24px; bottom: 22px; gap: 12px; }
body.kj-wide .kj-lrail-id { border-radius: 16px; padding: 8px 13px 8px 8px; gap: 12px; }
body.kj-wide .kj-lrail-av { width: 40px; height: 40px; font-size: 15px; }
body.kj-wide .kj-lrail-you { font-size: 12.5px; }
body.kj-wide .ga-hand { padding-bottom: 20px !important; }
/* only here: the card lifts 12px on a gold edge under the pointer (29) */
@media (hover: hover) and (pointer: fine) {
  body.kj-wide #hand .kj-card:not(.invalid-play):not(.kj-dragging):hover { transform: translateY(-12px); border-color: var(--gold); z-index: 40; }
  body.kj-wide #hand .kj-card.invalid-play:hover { transform: translateY(2px); }
  body.kj-wide .kj-av-box:hover .kj-av { border-color: var(--gold); }
}

/* 27: "delete the 700px breakpoint's max-width: 720px and max-width: 56px on
   .card. The column cap becomes max-width: none; the felt fills the width and
   the fan centres itself." The caps stay for every screen that is not the
   kj table. */
@media (min-width: 700px) {
  body.kj-table #view-room.game-shell, body.kj-table #view-room .game-area, body.kj-table #view-room .felt-wrap,
  body.kj-table #view-room .felt, body.kj-table #view-room .hand-row, body.kj-table #view-room .ga-cell,
  body.kj-table #view-room .ga-hand, body.kj-table #view-room .round-status {
    max-width: none !important; width: 100% !important; margin-left: 0 !important; margin-right: 0 !important;
  }
  body.kj-table #view-room .game-area { max-width: 1700px !important; margin-left: auto !important; margin-right: auto !important; }
  body.kj-table #view-room .ga-hand, body.kj-table #view-room .hand-row, body.kj-table #view-room .hand-row .hand { overflow: visible !important; }
  body.kj-table #view-room .ga-hand .hand .kj-card, body.kj-table #view-room .hand-row .hand .kj-card { max-width: none; flex: none; }
}

/* board 16's collected trick keeps the tier's card size */
body.kj-tablet:not(.kj-landscape) .kj-won-card { width: 88px; height: 123px; margin: -61.5px 0 0 -44px; border-radius: 8px; padding: 8px 9px; }
body.kj-landscape .kj-won-card { width: 84px; height: 118px; margin: -59px 0 0 -42px; border-radius: 8px; padding: 8px 8px; }
body.kj-wide .kj-won-card { width: 90px; height: 126px; margin: -63px 0 0 -45px; border-radius: 8px; padding: 8px 9px; }
body.kj-tablet .kj-won-corner, body.kj-landscape .kj-won-corner, body.kj-wide .kj-won-corner { font-size: 18px; }
body.kj-tablet .kj-won-suit, body.kj-landscape .kj-won-suit, body.kj-wide .kj-won-suit { font-size: 16px; }
body.kj-tablet .kj-won-pip, body.kj-landscape .kj-won-pip, body.kj-wide .kj-won-pip { font-size: 29px; }

/* -- 28c: corner controls in landscape — the react tray is a 356px popover
   over the bottom-LEFT corner, the partner signal the same over the
   bottom-RIGHT (public and private in different corners), no scrim. On the
   desktop the react strip lives in the rail and SIGNAL sits left, so the
   signal popover follows it there. */
body.kj-landscape .kj-react .kj-sheetzone-scrim, body.kj-landscape .kj-sig .kj-sheetzone-scrim { background: transparent; }
body.kj-landscape .kj-react .kj-zpanel, body.kj-landscape .kj-sig .kj-zpanel {
  left: 20px; right: auto; top: auto; bottom: 30px; transform: none; width: 356px; max-height: none;
  border-radius: 22px; padding: 16px; box-shadow: 0 20px 44px rgba(0,0,0,0.5);
}
body.kj-landscape .kj-sig .kj-zpanel { left: auto; right: 20px; }
body.kj-landscape.kj-wide .kj-sig .kj-zpanel { left: 20px; right: auto; }
body.kj-landscape .kj-sig-top { display: none; }
body.kj-landscape .kj-react-head { margin-bottom: 13px; }
body.kj-landscape .kj-react-title { font-size: 15px; }
body.kj-landscape .kj-react-ar { font-size: 12px; }
body.kj-landscape .kj-react-cap { color: var(--ink-3); }
body.kj-landscape .kj-sig-title { font-size: 15px; }
body.kj-landscape .kj-sig-title-ar { font-size: 11px; }
body.kj-landscape .kj-sig-grid, body.kj-landscape .kj-sig-suits { gap: 8px; }
body.kj-landscape .kj-sig-card { padding: 10px 6px; gap: 3px; }
body.kj-landscape .kj-sig-g { font-size: 17px; }
body.kj-landscape .kj-sig-en { font-size: 10px; }
body.kj-landscape .kj-sig-ar { font-size: 9.5px; }
body.kj-landscape .kj-sig-desc { display: none; }
body.kj-landscape .kj-sig-suit { padding: 10px 6px; }
body.kj-landscape .kj-sig-suit-g { font-size: 26px; }

/* 28a/29 put the caption under the whole diamond (top 78-79% of a felt whose
   south card sits at 74%); with a card on the south spot it needs 86% */
body.kj-landscape .kj-cap { top: 86% !important; }

/* -- 49: the Arabic table. "Chrome flips · table does not · turn order is a
   rule, not a locale." Under dir=rtl the bar and the sheets mirror on their
   own (flex rows); every [dir=rtl] swap that used to move chairs, played
   cards, chips, rails and the index has been removed. The card index stays
   left. (The Arabic labels and the ٢٨/١٩ numerals wait on a language
   setting — the app has no dir=rtl mode to switch on yet.) */

/* -- 50: the seat you left — a trust screen, not a spinner ---------------- */
.kj-rejoin { background: linear-gradient(180deg, var(--surf2) 0%, var(--ink-bg) 58%); }
.kj-rejoin::before, .kj-rejoin::after { display: none; }
.kj-rejoin-head { position: absolute; top: 76px; left: 20px; right: 20px; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.kj-rejoin-pill { display: flex; align-items: center; gap: 8px; box-sizing: border-box; background: rgba(31,84,79,0.2); border: 1px solid var(--teal); border-radius: 999px; padding: 5px 13px; }
.kj-rejoin-pill i { width: 7px; height: 7px; border-radius: 50%; background: var(--mint); display: block; }
.kj-rejoin-pill span { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--mint); }
.kj-rejoin-title { font-family: 'Archivo Black', sans-serif; font-size: 26px; line-height: 1.1; letter-spacing: -.02em; color: var(--ink); text-align: center; white-space: nowrap; }
.kj-rejoin-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 14px; line-height: 1.5; color: var(--ink-3); }
.kj-rejoin-d { font-size: 12px; line-height: 1.55; color: var(--ink-2); text-align: center; max-width: 290px; text-wrap: pretty; }
.kj-rejoin-who { position: absolute; top: 268px; left: 18px; right: 18px; height: 54px; box-sizing: border-box; display: flex; align-items: center; gap: 12px; background: rgba(9,13,8,0.6); border: 1px solid var(--line); border-radius: 12px; padding: 0 13px; }
.kj-rejoin-av { width: 34px; height: 34px; border-radius: 50%; background: var(--line); border: 1.5px dashed var(--ink-3); display: flex; align-items: center; justify-content: center; flex: none; box-sizing: border-box; }
.kj-rejoin-av span { font-family: 'IBM Plex Mono', monospace; font-size: 13px; color: var(--ink-3); }
.kj-rejoin-who-col { display: flex; flex-direction: column; gap: 2px; }
.kj-rejoin-who-t { font-size: 12.5px; font-weight: 800; color: var(--ink); }
.kj-rejoin-who-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-rejoin-who-clock { margin-left: auto; font-family: 'IBM Plex Mono', monospace; font-size: 10px; color: var(--ink-3); }
.kj-rejoin-list { position: absolute; top: 340px; left: 18px; right: 18px; bottom: 236px; display: flex; flex-direction: column; gap: 8px; overflow: auto; scrollbar-width: none; }
.kj-rejoin-list::-webkit-scrollbar { display: none; }
.kj-rejoin-row { display: flex; align-items: center; gap: 12px; box-sizing: border-box; background: rgba(9,13,8,0.5); border: 1px solid var(--surf4); border-radius: 12px; padding: 11px 13px; flex: none; }
.kj-rejoin-row--won { background: rgba(239,195,117,0.1); border-color: var(--line5); }
.kj-rejoin-card { width: 40px; height: 56px; border-radius: 8px; background: var(--card-cream); box-shadow: 0 3px 9px rgba(0,0,0,0.5); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; flex: none; color: var(--card-ink); }
.kj-rejoin-card[data-red="true"] { color: var(--oxblood); }
.kj-rejoin-row--won .kj-rejoin-card { background: var(--gold); color: var(--ink-bg); }
.kj-rejoin-card-r { font-family: 'Archivo Black', sans-serif; font-size: 19px; line-height: 1; }
.kj-rejoin-card-s { font-size: 18px; line-height: 1; }
.kj-rejoin-row-col { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.kj-rejoin-row-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-rejoin-row--won .kj-rejoin-row-k { color: var(--gold); }
.kj-rejoin-row-t { font-size: 12px; line-height: 1.4; color: var(--ink-2); }
.kj-rejoin-row-res { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-rejoin-row--won .kj-rejoin-row-res { color: var(--gold); }
.kj-rejoin-ctr { position: absolute; top: 604px; left: 18px; right: 18px; height: 62px; box-sizing: border-box; display: flex; align-items: center; background: rgba(9,13,8,0.6); border: 1px solid var(--line); border-radius: 12px; padding: 0 6px; }
.kj-rejoin-ctr-cell { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px; }
.kj-rejoin-ctr-cell + .kj-rejoin-ctr-cell { border-left: 1px solid var(--surf4); }
.kj-rejoin-ctr-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); white-space: nowrap; }
.kj-rejoin-ctr-v { font-family: 'Archivo Black', sans-serif; font-size: 18px; line-height: 1; color: var(--ink); }
.kj-rejoin-ctr-v[data-tone="dim"] { color: var(--ink-3); }
.kj-rejoin-ctr-v[data-tone="gold"] { color: var(--gold); }
.kj-rejoin-joker { position: absolute; top: 682px; left: 18px; right: 18px; height: 46px; box-sizing: border-box; display: flex; align-items: center; gap: 12px; background: rgba(239,195,117,0.1); border: 1px solid var(--line5); border-radius: 12px; padding: 0 13px; }
.kj-rejoin-joker img { width: 30px; display: block; flex: none; }
.kj-rejoin-joker-col { display: flex; flex-direction: column; gap: 1px; }
.kj-rejoin-joker-en { font-size: 11.5px; font-weight: 800; line-height: 1.3; color: var(--gold); }
.kj-rejoin-joker-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 9.5px; line-height: 1.5; color: var(--ink-3); }
.kj-rejoin-foot { position: absolute; bottom: 34px; left: 22px; right: 22px; height: 50px; display: flex; gap: 12px; }
.kj-rejoin-see { flex: 1; box-sizing: border-box; border: 1px solid var(--line5); background: none; color: var(--ghost-ink); font-size: 13.5px; font-weight: 600; border-radius: 12px; cursor: pointer; font-family: inherit; }
.kj-rejoin-take { flex: 1.5; box-sizing: border-box; background: var(--gold); border: 0; color: var(--ink-bg); font-size: 15px; font-weight: 800; letter-spacing: 0; border-radius: 12px; cursor: pointer; font-family: inherit; }

/* -- 51: the four-colour deck (setting, default off) — ♦ blue, ♣ green; the
   ♥/♦ pair is the one colour never separated. Hearts take the board's red. */
body.kj-4c.kj-table #hand .kj-card[data-suit="Hearts"] { color: var(--card-red-4c); }
body.kj-4c.kj-table #hand .kj-card[data-suit="Diamonds"] { color: var(--card-blue-4c); }
body.kj-4c.kj-table #hand .kj-card[data-suit="Clubs"] { color: var(--card-green-4c); }
body.kj-4c.kj-table #hand .kj-card[data-suit="Hearts"] .pip { color: rgba(198,42,29,0.5); }
body.kj-4c.kj-table #hand .kj-card[data-suit="Diamonds"] .pip { color: rgba(27,98,181,0.5); }
body.kj-4c.kj-table #hand .kj-card[data-suit="Clubs"] .pip { color: rgba(30,122,70,0.5); }
body.kj-4c.kj-table #hand .kj-card.invalid-play { color: var(--card-dead-ink); }
body.kj-4c.kj-table #view-room .ga-felt .trick .played-card[data-suit="Hearts"]:not(.kj-high-card) { color: var(--card-red-4c); }
body.kj-4c.kj-table #view-room .ga-felt .trick .played-card[data-suit="Diamonds"]:not(.kj-high-card) { color: var(--card-blue-4c); }
body.kj-4c.kj-table #view-room .ga-felt .trick .played-card[data-suit="Clubs"]:not(.kj-high-card) { color: var(--card-green-4c); }

/* -- 10a/10b: the deal — deck at centre, trails toward the receiving chair,
   then "DECK EMPTY". The mark dims to .05 while the deck is on it. */
.kj-deal { position: absolute; inset: 0; pointer-events: none; }
/* -- 10 amended (2026-09-18): the deal is FOUR PACKETS THAT TRAVEL ---------
   What was here drew a deck and a fixed trail of ghosts, and "animated" by
   being re-rendered four times 320ms apart. It was a flipbook: nothing ever
   moved, the trail sat in the same five places every beat, and because the
   whole .kj-tab root is rebuilt on every render, any animation on it restarted
   constantly. Design's amendment is motion, so this is motion - the layer is
   built once by screens/deal.js, appended beside .kj-tab rather than inside
   it, and left alone until the deal is over.

   "One packet per player, arriving whole. No 4+4+4. The packet is 3 shingled
   backs as a visual for 'a hand', not a count - do not draw 13, and do not
   draw 4."

   Each packet travels 180ms to its chair shrinking 1 -> 0.34, then lands in
   60ms going 0.34 -> 0.30 and fading out; packet n starts at n x 120ms. The
   deltas arrive as --dx/--dy in px, measured off the real avatars, so the
   packets land on the chairs wherever the tier put them.                    */
.kj-deal2 { position: absolute; inset: 0; pointer-events: none; z-index: 6; }
/* Design's deck sits at (192, 232) on the artboard. This layer is inset:0
   inside the felt, which starts 53px down, so 232 there is 179 here - the same
   53 that put the contract band inside the south chair. x is 50% rather than
   192 because the phone is not always 384 wide. */
.kj-deal2-deck, /* The land is `forwards`, NOT `both`. With `both` on each, the land's
   BACKWARDS fill applies from time zero - and a later animation in the list
   wins the property - so every packet sat at its destination, at 0.34, from
   the first frame and the 180ms flight never rendered at all. `forwards`
   contributes nothing before its own delay. */
.kj-deal2-packet {
  position: absolute; left: 50%; top: 179px; width: 62px; height: 87px;
  transform: translate(-50%, -50%);
}
.kj-deal2-back {
  position: absolute; inset: 0; box-sizing: border-box; border-radius: 4px;
  background: var(--chair); border: 1px solid var(--chair-ring);
  box-shadow: 0 8px 20px rgba(0,0,0,0.55);
}
/* 3 backs, offsets 0 / -2 / -4 - a shingled stack, not a single card */
.kj-deal2-back:nth-child(2) { transform: translate(-2px, -2px); }
.kj-deal2-back:nth-child(3) { transform: translate(-4px, -4px); }
.kj-deal2-back:nth-child(1) { border-color: rgba(239,195,117,0.42); }
.kj-deal2-packet {
  animation:
    kjDealFly var(--t-deal-fly) var(--ease-standard) calc(var(--i, 0) * var(--t-deal-stagger)) both,
    kjDealLand var(--t-deal-land) var(--ease-standard) calc(var(--i, 0) * var(--t-deal-stagger) + var(--t-deal-fly)) forwards;
}
@keyframes kjDealFly {
  from { transform: translate(-50%, -50%) scale(1); }
  to   { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(0.34); }
}
@keyframes kjDealLand {
  from { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(0.34); opacity: 1; }
  to   { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(0.30); opacity: 0; }
}
/* the deck goes when the last packet leaves it */
.kj-deal2-deck { animation: kjDeckOut var(--t-deal-land) var(--ease-standard) calc(3 * var(--t-deal-stagger) + var(--t-deal-fly)) forwards; }
@keyframes kjDeckOut { from { opacity: 1; } to { opacity: 0; } }

/* the hand fans in behind the packets: left to right, 22ms a card */
body.kj-table #hand.kj-hand-in .kj-card {
  animation: kjHandIn var(--t-deal-fan) var(--ease-standard) calc(var(--i, 0) * var(--t-deal-card)) both;
}
@keyframes kjHandIn {
  from { opacity: 0; transform: translateY(18px) scale(0.94); }
  to   { opacity: 1; transform: none; }
}

.kj-deal-cap { position: absolute; left: 50%; bottom: 18px; transform: translateX(-50%); display: flex; flex-direction: column; align-items: center; gap: 5px; text-align: center; }
.kj-deal-cap-en { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--ink-3); white-space: nowrap; }
.kj-deal-cap-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 11px; line-height: 1.4; color: var(--ink-3); }
.kj-deal-empty { position: absolute; left: 50%; top: 46%; transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; gap: 12px; }
.kj-deal-ring { width: 46px; height: 46px; border-radius: 50%; border: 1.5px solid rgba(239,195,117,0.4); display: flex; align-items: center; justify-content: center; box-sizing: border-box; }
.kj-deal-ring i { width: 13px; height: 13px; transform: rotate(45deg); background: var(--gold); display: block; }
.kj-deal-empty-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--ink-3); }
.kj-deal-empty-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 11px; line-height: 1.4; color: var(--ink-3); }
body.kj-table:has(.kj-deal2-deck) #view-room .felt-logo { opacity: .05; }

/* -- 28b / 27: the bid sheet stops being a bottom sheet from the tablet up —
   a centred dialog (620px in landscape at 46% height, 560 on the tablet)
   over a 55% / 62% scrim, so the fan stays visible while you decide. Keys on
   the viewport classes (kj-vp-*) because the table skin is off while bidding. */
body.kj-vp-tablet .kn-bid-scrim, body.kj-vp-landscape .kn-bid-scrim, body.kj-vp-wide .kn-bid-scrim {
  justify-content: center !important; align-items: center; background: rgba(9,13,8,0.62) !important;
}
body.kj-vp-landscape .kn-bid-scrim { background: rgba(9,13,8,0.55) !important; }
body.kj-vp-tablet .kn-bid-scrim > [data-kn-taunt], body.kj-vp-landscape .kn-bid-scrim > [data-kn-taunt], body.kj-vp-wide .kn-bid-scrim > [data-kn-taunt] {
  width: min(560px, calc(100% - 40px)); padding: 0 !important; margin-bottom: 8px;
}
body.kj-vp-landscape .kn-bid-scrim > [data-kn-taunt] { width: min(620px, calc(100% - 40px)); }
body.kj-vp-tablet .kn-bid-scrim > [data-kn-stop], body.kj-vp-landscape .kn-bid-scrim > [data-kn-stop], body.kj-vp-wide .kn-bid-scrim > [data-kn-stop] {
  width: min(560px, calc(100% - 40px)); box-sizing: border-box; margin-bottom: 6%;
  background: var(--surface-sheet) !important; border: 1px solid var(--line-strong) !important; border-radius: 22px !important;
  padding: 26px 28px 28px !important; box-shadow: 0 30px 70px rgba(0,0,0,0.6) !important; animation: none !important;
}
body.kj-vp-landscape .kn-bid-scrim > [data-kn-stop] { width: min(620px, calc(100% - 40px)); }
body.kj-vp-tablet .kn-bid-scrim [data-kn="bidTitle"], body.kj-vp-landscape .kn-bid-scrim [data-kn="bidTitle"], body.kj-vp-wide .kn-bid-scrim [data-kn="bidTitle"] {
  font: 400 26px/1 'Archivo Black', sans-serif !important; letter-spacing: -.02em; color: var(--ink) !important; text-transform: uppercase;
}
body.kj-vp-tablet .kn-bid-scrim [data-kn="bidHint"], body.kj-vp-landscape .kn-bid-scrim [data-kn="bidHint"], body.kj-vp-wide .kn-bid-scrim [data-kn="bidHint"] {
  font: 400 22px/1 'Archivo Black', sans-serif !important; color: var(--gold) !important;
}
body.kj-vp-tablet .kn-bid-scrim [data-kn-action="bid"], body.kj-vp-landscape .kn-bid-scrim [data-kn-action="bid"], body.kj-vp-wide .kn-bid-scrim [data-kn-action="bid"] {
  height: 62px !important; border-radius: 12px; font: 400 20px/1 'Archivo Black', sans-serif !important;
}
body.kj-vp-tablet .kn-bid-scrim [data-kn-action="pass"], body.kj-vp-landscape .kn-bid-scrim [data-kn-action="pass"], body.kj-vp-wide .kn-bid-scrim [data-kn-action="pass"] {
  height: 54px !important; border-radius: 12px;
}

/* ==========================================================================
   2026-09-04 REBUILD — Ahmad's review of the boards (13a–c, 15b, 16/16b/16c,
   17a/17b, 52, 56/58). Every hex below is the board's unless marked MINE.
   ========================================================================== */

/* -- one avatar treatment (13b): var(--chair) surface, var(--chair-ring) ring, gold only on
   the active chair; a portrait or the board's silhouette, never an initial -- */
.kj-seat { width: 96px; gap: 5px; }
.kj-av {
  width: var(--chair-felt); height: var(--chair-felt); background: var(--chair); border: 2px solid var(--chair-ring); color: transparent;
  position: relative; overflow: hidden; font-size: 0;
}
.kj-av-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.kj-av-head { position: absolute; left: 50%; top: 7px; margin-left: -7px; width: 13px; height: 13px; border-radius: 50%; background: rgba(244,233,212,0.94); display: block; }
.kj-av-body { position: absolute; left: 50%; bottom: -2px; margin-left: -13px; width: 26px; height: 13px; border-radius: 12px 12px 0 0; background: rgba(244,233,212,0.94); display: block; }
.kj-av-glyph { font-size: 16px; font-weight: 800; color: var(--ink-2); }
.kj-seat[data-active="1"] .kj-av { border-color: var(--gold); }
.kj-seat-name { font-size: 11px; }
.kj-seat[data-me="1"] .kj-av { width: var(--chair-own); height: var(--chair-own); }   /* 62: your own seat is 48 */
.kj-seat-status { font-size: 9.5px; letter-spacing: .14em; }
.kj-seat-status[data-tone="dim"] { color: var(--ink-3); }
.kj-seat-status[data-tone="green"] { color: var(--mint); }
.kj-seat-status[data-tone="red"] { color: var(--salmon); }
.kj-seat[data-dropped="1"] .kj-av { background: var(--oxblood-wash) !important; }

/* -- 13b: the score is a mini table, top-left --------------------------------- */
.kj-scoretab {
  position: absolute; left: 9px; top: 9px; box-sizing: border-box; pointer-events: auto;
  background: rgba(9,13,8,0.84); border: 1px solid var(--line); border-radius: 12px; overflow: hidden; z-index: 4;
  font-family: inherit; padding: 0; text-align: left; cursor: pointer;
}
.kj-scoretab-row { display: grid; grid-template-columns: 42px minmax(26px, auto) 32px; column-gap: 5px; align-items: center; padding: 5px 8px; border-top: 1px solid var(--line); }   /* the PTS column grows for "-15" (MINE) */
.kj-scoretab-head { background: rgba(255,255,255,0.05); padding: 3px 8px; border-top: 0; }
.kj-scoretab-head span { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-scoretab-l { font-size: 9.5px; font-weight: 800; color: var(--ink-2); }
.kj-scoretab-us .kj-scoretab-l { color: var(--gold); }
.kj-scoretab-n { font-family: 'Archivo Black', sans-serif; font-size: 14px; line-height: 1; color: var(--ink-2); }
.kj-scoretab-us .kj-scoretab-n { color: var(--gold); }
.kj-scoretab-b { font-family: 'IBM Plex Mono', monospace; font-size: 10px; color: var(--mint); }
.kj-scoretab-b[data-empty="1"] { color: var(--ink-3); }
.kj-scoretab-them .kj-scoretab-b:not([data-empty="1"]) { color: var(--salmon); }   /* MINE: their contract in the warning ink */

/* -- 17a: the last trick, always in the top-right corner ---------------------- */
.kj-ltray {
  position: absolute; right: 9px; top: 9px; box-sizing: border-box; pointer-events: auto; z-index: 4;
  background: rgba(9,13,8,0.84); border: 1px solid var(--line); border-radius: 12px; padding: 6px 8px 7px;
  display: flex; flex-direction: column; align-items: center; gap: 5px; cursor: pointer; font-family: inherit;
}
.kj-ltray[data-open="1"] { border-color: var(--gold); }
.kj-ltray-head { display: flex; align-items: center; gap: 5px; }
.kj-ltray-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-ltray-x { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; color: var(--ink-3); }
.kj-ltray[data-open="1"] .kj-ltray-k, .kj-ltray[data-open="1"] .kj-ltray-x { color: var(--gold); }
.kj-ltray-cross { position: relative; width: 76px; height: 78px; }
.kj-ltray-card {
  position: absolute; width: 24px; height: 34px; box-sizing: border-box; background: var(--ink); border-radius: 4px;
  border: 1.5px solid rgba(23,19,15,0.2); display: flex; flex-direction: column; align-items: center; justify-content: center; color: var(--card-ink);
}
.kj-ltray-card[data-red="true"] { color: var(--oxblood); }
.kj-ltray-card--win { border-color: var(--gold); box-shadow: 0 0 0 3px rgba(239,195,117,0.3); }
.kj-ltray-card--empty { background: rgba(244,233,212,0.06); border: 1.5px dashed rgba(239,195,117,0.28); }   /* MINE: before the first trick */
.kj-ltray-w { left: 0; top: 27px; }
.kj-ltray-n { left: 50%; top: 0; transform: translateX(-50%); }
.kj-ltray-e { right: 0; top: 27px; }
.kj-ltray-s { left: 50%; bottom: 0; transform: translateX(-50%); }
.kj-ltray-r { font-family: 'Archivo Black', sans-serif; font-size: 11px; line-height: 1; }
.kj-ltray-g { font-size: 11px; line-height: 1; }
.kj-ltray-cap { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--mint); white-space: nowrap; }
body.kj-table .kj-last { display: none !important; }   /* the edge tab is retired */

/* -- 17b: the last trick, open ----------------------------------------------- */
.kj-lreview { position: absolute; inset: 0; z-index: 40; pointer-events: auto; }
.kj-lreview-scrim { position: absolute; inset: 0; background: rgba(9,13,8,0.72); }
.kj-lreview-panel {
  position: absolute; left: 16px; right: 16px; top: 31px; box-sizing: border-box; background: var(--surface-sheet); border: 1px solid var(--line-strong);
  border-radius: 16px; overflow: hidden; max-height: calc(100% - 40px); overflow-y: auto;
}
.kj-lreview-head { display: flex; align-items: center; gap: 8px; padding: 13px 16px; border-bottom: 1px solid var(--line); }
.kj-lreview-title { font-family: 'Archivo Black', sans-serif; font-size: 15px; letter-spacing: 0; color: var(--ink); }
.kj-lreview-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 12px; line-height: 1.4; color: var(--gold); }
.kj-lreview-x { margin-left: auto; font-family: 'IBM Plex Mono', monospace; font-size: 13px; color: var(--ink-2); background: none; border: 0; padding: 4px 6px; cursor: pointer; }
.kj-lreview-body { padding: 16px 16px 6px; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.kj-lreview-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-lreview-cross { position: relative; width: 196px; height: 224px; }
.kj-lreview-card {
  position: absolute; width: 58px; height: 82px; box-sizing: border-box; background: var(--card-cream); border-radius: 8px; border: 2px solid rgba(23,19,15,0.2);
  display: flex; flex-direction: column; align-items: center; justify-content: center; color: var(--card-ink);
}
.kj-lreview-card[data-red="true"] { color: var(--oxblood); }
.kj-lreview-card--win { border-color: var(--gold); box-shadow: 0 0 0 4px rgba(239,195,117,0.3); }
.kj-lreview-card--last { border-color: var(--gold); }
.kj-lreview-n { left: 50%; top: 0; transform: translateX(-50%); }
.kj-lreview-w { left: 0; top: 58px; }
.kj-lreview-e { right: 0; top: 58px; }
.kj-lreview-s { left: 50%; bottom: 0; transform: translateX(-50%); }
.kj-lreview-rank { font-family: 'Archivo Black', sans-serif; font-size: 26px; line-height: 1; letter-spacing: -.05em; }
.kj-lreview-suit { font-size: 28px; line-height: 1; }
.kj-lreview-num {
  position: absolute; left: -7px; top: -7px; width: 19px; height: 19px; border-radius: 50%; background: var(--ink-4);
  display: flex; align-items: center; justify-content: center; font-family: 'Archivo Black', sans-serif; font-size: 10px; line-height: 1; color: var(--ink-bg);
}
.kj-lreview-num--gold { background: var(--gold); }
.kj-lreview-mid { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; gap: 2px; }
.kj-lreview-led { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-lreview-ccw { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-4); }
.kj-lreview-list { padding: 4px 16px 14px; display: flex; flex-direction: column; gap: 5px; }
.kj-lreview-row { display: flex; align-items: center; gap: 8px; box-sizing: border-box; background: rgba(255,255,255,0.02); border: 1px solid var(--line); border-radius: 12px; padding: 7px 11px; }
.kj-lreview-row--win { background: rgba(239,195,117,0.1); border-color: var(--gold); }
.kj-lreview-badge { width: 17px; height: 17px; border-radius: 50%; background: var(--ink-4); display: flex; align-items: center; justify-content: center; flex: none; font-family: 'Archivo Black', sans-serif; font-size: 9.5px; line-height: 1; color: var(--ink-bg); }
.kj-lreview-badge--gold { background: var(--gold); }
.kj-lreview-name { font-size: 11.5px; font-weight: 700; color: var(--ink-2); width: 42px; flex: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kj-lreview-row--win .kj-lreview-name { color: var(--gold); }
.kj-lreview-c { font-family: 'Archivo Black', sans-serif; font-size: 13px; line-height: 1; color: var(--ink); width: 32px; flex: none; }
.kj-lreview-c[data-red="true"] { color: var(--salmon); }   /* MINE: red suits on ink */
.kj-lreview-role { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-lreview-row--win .kj-lreview-role { color: var(--gold); }
.kj-lreview-foot { display: flex; align-items: center; gap: 12px; padding: 12px 16px; border-top: 1px solid var(--line); background: rgba(224,145,126,0.08); }
.kj-lreview-foot--us { background: rgba(127,191,165,0.08); }
.kj-lreview-foot-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--salmon); }
.kj-lreview-foot--us .kj-lreview-foot-k { color: var(--mint); }
.kj-lreview-delta { margin-left: auto; font-family: 'Archivo Black', sans-serif; font-size: 14px; line-height: 1; color: var(--salmon); }
.kj-lreview-foot--us .kj-lreview-delta { color: var(--mint); }

/* -- 13a–c: the played cards — 62×87 (--card-trick-w/h), NO tilt, two items only (rank 31 + suit
   33), no corner index, no pip; the card taking the trick wears a gold ring
   and a soft glow, never a fill ------------------------------------------- */
body.kj-table #view-room .ga-felt .trick { --pc-w: var(--card-trick-w); --pc-h: var(--card-trick-h); }
body.kj-table #view-room .ga-felt .trick .played-card {
  rotate: 0deg !important; border-radius: 8px; border: 1px solid rgba(23,19,15,0.18); box-shadow: 0 4px 14px rgba(0,0,0,0.45);
  padding: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0;
}
body.kj-table #view-room .ga-felt .trick .played-card.west  { left: 29%; top: 47%; }
body.kj-table #view-room .ga-felt .trick .played-card.north { left: 50%; top: 30%; }
body.kj-table #view-room .ga-felt .trick .played-card.east  { left: 71%; top: 47%; }
body.kj-table #view-room .ga-felt .trick .played-card.south { left: 50%; top: 62%; }
body.kj-table #view-room .ga-felt .trick .played-card .corner.br,
body.kj-table #view-room .ga-felt .trick .played-card .corner.tl {
  position: static; display: flex; flex-direction: column; align-items: center; gap: 0; width: auto; transform: none;
}
body.kj-table #view-room .ga-felt .trick .played-card .corner.tl .rank { font-family: 'Archivo Black', sans-serif; font-size: 31px; line-height: 1; letter-spacing: -.05em; }
body.kj-table #view-room .ga-felt .trick .played-card[data-rank="Ten"] .corner.tl .rank,
body.kj-table #view-room .ga-felt .trick .played-card .corner.tl .rank[data-ten="1"] { font-size: 24px; }
body.kj-table #view-room .ga-felt .trick .played-card .corner.tl .suit { font-size: 33px; line-height: 1; margin: 0; }
body.kj-table #view-room .ga-felt .trick .played-card.kj-high-card {
  background: var(--card-cream) !important; color: var(--card-ink); border: 2px solid var(--gold);
  box-shadow: 0 0 0 4px rgba(239,195,117,0.3), 0 8px 22px rgba(0,0,0,0.55);
}
body.kj-table #view-room .ga-felt .trick .played-card.kj-high-card.red { color: var(--card-red); }
.kj-high { margin-top: -57px; background: var(--gold); border-radius: 4px; padding: 2px 7px; }
.kj-high span { font-size: 9.5px; letter-spacing: .14em; font-weight: 500; }
body.kj-table .kj-slot { width: var(--card-trick-w); height: var(--card-trick-h); border-radius: 8px; }
body.kj-table:not(.kj-compact):not(.kj-tablet):not(.kj-wide):not(.kj-landscape) .kj-slot { width: var(--card-trick-w); height: var(--card-trick-h); border-radius: 8px; }
body.kj-tablet:not(.kj-landscape) #view-room .ga-felt .trick { --pc-w: 88px; --pc-h: 123px; }
body.kj-landscape #view-room .ga-felt .trick { --pc-w: 84px; --pc-h: 118px; }
body.kj-wide #view-room .ga-felt .trick { --pc-w: 90px; --pc-h: 126px; }
body.kj-tablet:not(.kj-landscape) #view-room .ga-felt .trick .played-card .corner.tl .rank,
body.kj-landscape #view-room .ga-felt .trick .played-card .corner.tl .rank,
body.kj-wide #view-room .ga-felt .trick .played-card .corner.tl .rank { font-size: 40px; }
body.kj-tablet:not(.kj-landscape) #view-room .ga-felt .trick .played-card .corner.tl .suit,
body.kj-landscape #view-room .ga-felt .trick .played-card .corner.tl .suit,
body.kj-wide #view-room .ga-felt .trick .played-card .corner.tl .suit { font-size: 42px; }
body.kj-compact #view-room .ga-felt .trick { --pc-w: 57px; --pc-h: 81px; }
body.kj-compact #view-room .ga-felt .trick .played-card .corner.tl .rank { font-size: 27px; }
body.kj-compact #view-room .ga-felt .trick .played-card .corner.tl .suit { font-size: 29px; }

/* -- the hand's face (13b): a 28px column at the top-left, rank 26 (Ten 20)
   over suit 28, nothing else on the card ---------------------------------- */
/* The corner is clamped to the SLIVER, not the card. At 0.35 of an 81px card
   it is 28px wide, and thirteen cards on a 390 phone advance 23 - so the next
   card covered the right-hand five pixels of every rank, and "10" read as a 1
   with a smudge. --kj-strip now carries the step the layout really used
   (screens/hand.js), so min() keeps the corner inside what a card shows. */
body.kj-table #hand .kj-card .corner.tl { width: min(calc(var(--kj-cw, 80px) * 0.35), var(--kj-strip, 28px)); top: calc(var(--kj-cw, 80px) * 0.1); left: 0; gap: 2px; }
body.kj-table #hand .kj-card .corner.tl .rank { font-size: min(calc(var(--kj-cw, 80px) * 0.325), calc(var(--kj-strip, 28px) * 0.92)); letter-spacing: -.05em; }
body.kj-table #hand .kj-card[data-rank="Ten"] .corner.tl .rank { font-size: min(calc(var(--kj-cw, 80px) * 0.25), calc(var(--kj-strip, 28px) * 0.72)); }
body.kj-table #hand .kj-card .corner.tl .suit { font-size: min(calc(var(--kj-cw, 80px) * 0.35), calc(var(--kj-strip, 28px) * 0.92)); }

/* -- 15b: "keep cards as is but give it a border color" — the PLAYABLE cards
   wear the gold ring; illegal ones keep a normal face; nothing dims, nothing
   shrinks, nothing tilts or shakes ----------------------------------------- */
body.kj-table #hand .kj-card.invalid-play {
  width: var(--kj-cw, 80px); opacity: 1; background: var(--card-cream); filter: none;
  border: 1px solid rgba(239,195,117,0.42); color: var(--card-ink); transform: none;
}
body.kj-table #hand .kj-card.invalid-play.red { color: var(--card-red); }
body.kj-table #hand .kj-card.invalid-play .corner.tl { width: min(calc(var(--kj-cw, 80px) * 0.35), var(--kj-strip, 28px)); top: calc(var(--kj-cw, 80px) * 0.1); gap: 2px; }
body.kj-table #hand .kj-card.invalid-play .corner.tl .rank { font-size: min(calc(var(--kj-cw, 80px) * 0.325), calc(var(--kj-strip, 28px) * 0.92)); letter-spacing: -.05em; }
body.kj-table #hand .kj-card.invalid-play[data-rank="Ten"] .corner.tl .rank { font-size: min(calc(var(--kj-cw, 80px) * 0.25), calc(var(--kj-strip, 28px) * 0.72)); }
body.kj-table #hand .kj-card.invalid-play .corner.tl .suit { font-size: min(calc(var(--kj-cw, 80px) * 0.35), calc(var(--kj-strip, 28px) * 0.92)); }
body.kj-table #hand .kj-card.invalid-play.nudge, body.kj-table #hand .kj-card.invalid-play.shake { animation: none; transform: none; border-color: rgba(239,195,117,0.42); box-shadow: -1px 0 0 rgba(23,19,15,0.5), -4px 4px 9px rgba(0,0,0,0.5); color: var(--card-ink); }
body.kj-table #hand .kj-card.invalid-play.shake.red, body.kj-table #hand .kj-card.invalid-play.nudge.red { color: var(--card-red); }
body.kj-table #hand .kj-card.playable:not(.invalid-play) {
  border: 1px solid var(--gold);
  box-shadow: -1px 0 0 rgba(23,19,15,0.5), inset 0 0 0 2px rgba(239,195,117,0.6), -4px 4px 9px rgba(0,0,0,0.5);
}
body.kj-table #hand .kj-card.preselected, body.kj-table #hand .kj-card.previewing {
  background: linear-gradient(180deg, var(--card-cream-hi) 0%, var(--card-cream) 52%); border: 1px solid var(--gold);
  box-shadow: inset 0 0 0 2px rgba(239,195,117,0.6), 0 16px 30px rgba(0,0,0,0.62); transform: translateY(-30px);
}

/* -- 58: the hand is FROZEN — no 14px drop at rest, no dimming (the message
   lane says whose turn it is). Board 14's drop is overruled by the contract. */
body.kj-table.kj-idle #hand { transform: none; opacity: 1; }

/* -- 16/16b/16c: gather, flip to the branded back, the hand takes the stack -- */
.kj-won--grab { perspective: 900px; }
.kj-won3d { position: absolute; transform-style: preserve-3d; z-index: 3; will-change: transform; }
.kj-won3d-face, .kj-won3d-back {
  position: absolute; inset: 0; box-sizing: border-box; border-radius: 8px; backface-visibility: hidden; -webkit-backface-visibility: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.kj-won3d-face { background: var(--card-cream); border: 1px solid rgba(23,19,15,0.18); box-shadow: 0 4px 14px rgba(0,0,0,0.5); color: var(--card-ink); }
.kj-won3d-face[data-red="true"] { color: var(--oxblood); }
.kj-won3d-face[data-win="1"] { border: 2px solid var(--gold); box-shadow: 0 0 0 4px rgba(239,195,117,0.3), 0 8px 22px rgba(0,0,0,0.55); }
.kj-won3d-rank { font-family: 'Archivo Black', sans-serif; font-size: 28px; line-height: 1; letter-spacing: -.05em; }
.kj-won3d-suit { font-size: 30px; line-height: 1; }
.kj-won3d-back {
  background: linear-gradient(168deg, var(--felt-1) 0%, var(--felt) 46%, var(--felt-2) 100%); border: 1px solid var(--gold-dim);
  box-shadow: 0 4px 14px rgba(0,0,0,0.5); transform: rotateY(180deg); overflow: hidden;
}
.kj-won3d-rule { position: absolute; inset: 4px; border: 1px solid rgba(239,195,117,0.42); border-radius: 999px; display: block; }
.kj-won3d-back img { position: absolute; left: 50%; top: 52%; width: 72%; transform: translate(-50%, -50%); opacity: .92; display: block; }
.kj-won3d-dia { position: absolute; width: 5px; height: 5px; transform: rotate(45deg); background: var(--gold); display: block; }
.kj-won3d-dia--tl { left: 6px; top: 6px; }
.kj-won3d-dia--br { right: 6px; bottom: 6px; }
.kj-won-hand {
  position: absolute; z-index: 5; background-repeat: no-repeat; background-position: 0 0; pointer-events: none;
  filter: drop-shadow(0 10px 22px rgba(0,0,0,0.55)); will-change: transform;
}
.kj-won--grab .kj-won-head { z-index: 6; }
@media (prefers-reduced-motion: reduce) { .kj-won-hand { display: none; } }

/* ===== 2026-09-04 REBUILD — boards 08/09: the ceremony as a table view =====
 * A layer under the app bar and over the table: short felt (260), joker strip,
 * the sheet. Every number is the board's; the layer's own stacking is mine. */
.kj-cer2 {
  position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: 60; overflow: hidden;
  background: var(--ink-bg); display: flex; flex-direction: column; text-align: left;
}
.kj-cer2-felt {
  position: relative; flex: none; height: 260px; overflow: hidden;
  background: radial-gradient(72% 54% at 50% 46%, var(--felt-1) 0%, var(--felt) 46%, var(--felt-2) 100%);
}
.kj-cer2-felt::before { content: ""; position: absolute; inset: 12px; border: 1px solid rgba(239,195,117,0.16); border-radius: 50% / 22%; pointer-events: none; }
.kj-cer2-felt::after {
  content: ""; position: absolute; left: 50%; top: 46%; width: 120px; height: 120px; transform: translate(-50%, -50%);
  background: url("brand/mark-256.webp") center / contain no-repeat; opacity: .06; pointer-events: none;
}
.kj-cer2-felt .kn-seats { position: absolute; inset: 0; }
.kj-cer2-felt .kj-scoretab { z-index: 3; }
/* 08: the fan */
.kj-cer2-fan { position: absolute; left: 50%; top: 48%; transform: translate(-50%, -50%); display: flex; align-items: flex-end; gap: 5px; z-index: 2; }
.kj-cer2-back {
  width: 46px; height: 64px; border-radius: 8px; box-sizing: border-box; position: relative;
  background: var(--felt); border: 1px solid var(--line-strong); box-shadow: 0 6px 16px rgba(0,0,0,0.5);
}
.kj-cer2-back--l { transform: rotate(-4deg); }
.kj-cer2-back--r { transform: rotate(4deg); }
.kj-cer2-back--m { width: 50px; height: 70px; background: var(--chair); border-color: var(--chair-ring); box-shadow: 0 8px 20px rgba(0,0,0,0.55); }
.kj-cer2-back--m i { position: absolute; left: 50%; top: 50%; width: 11px; height: 11px; margin: -5.5px 0 0 -5.5px; transform: rotate(45deg); background: var(--gold); display: block; }
/* 09: the deck split at the depth */
.kj-cer2-cut { position: absolute; left: 50%; top: 48%; transform: translate(-50%, -50%); width: 108px; height: 112px; z-index: 2; }
.kj-cer2-cut-top {
  position: absolute; left: 50%; top: 0; transform: translateX(-50%); width: 68px; height: 46px; box-sizing: border-box;
  border-radius: 8px 8px 4px 4px; background: var(--chair); border: 1px solid var(--chair-ring); box-shadow: 0 6px 16px rgba(0,0,0,0.5);
}
.kj-cer2-cut-line { position: absolute; left: 0; right: 0; top: 50px; height: 2px; background: repeating-linear-gradient(90deg, var(--gold) 0 7px, transparent 7px 13px); }
.kj-cer2-cut-bottom {
  position: absolute; left: 50%; top: 60px; transform: translateX(-50%); width: 68px; height: 52px; box-sizing: border-box;
  border-radius: 4px 4px 8px 8px; background: var(--felt); border: 1px solid var(--line-strong); box-shadow: 0 8px 18px rgba(0,0,0,0.5);
}
.kj-cer2-cut-depth { position: absolute; right: -4px; top: 40px; font-family: 'IBM Plex Mono', monospace; font-size: 10px; letter-spacing: .14em; color: var(--gold); }
/* the joker strip */
.kj-cer2-strip {
  flex: none; margin: 9px 14px 0; height: 40px; box-sizing: border-box; display: flex; align-items: center; gap: 8px;
  /* the same demotion as .kj-joker-bubble, and for the same reason: this strip
     sits directly above the hand during play and above the SHUFFLE button
     during the ceremony, and in gold it out-shouted both */
  background: var(--bubble); border-inline-start: 3px solid var(--bubble-edge);
  border-radius: 12px; border-start-start-radius: 3px; border-end-start-radius: 3px;
  padding: 0 12px 0 5px;
}
.kj-cer2-strip img { width: 34px; display: block; flex: none; }
.kj-cer2-strip-en { font-size: 11.5px; font-weight: 800; line-height: 1.25; color: var(--bubble-ink); }
.kj-cer2-strip-ar { margin-left: auto; font-family: Lemonada, sans-serif; font-weight: 600; font-size: 10px; line-height: 1.3; color: var(--bubble-ink-2); white-space: nowrap; }
/* the sheet */
.kj-cer2-sheet {
  flex: 1; min-height: 0; margin-top: 6px; box-sizing: border-box; overflow-y: auto;
  background: var(--surface-sheet); border-top: 1px solid var(--line-strong); border-radius: 22px 22px 0 0; padding: 18px 20px 28px;
}
.kj-cer2-sheet .kj-sheet-grab { margin-bottom: 15px; }
.kj-cer2-sheet .kj-sheet-head { margin-bottom: 14px; }
.kj-cer2-sheet .kj-sheet-title { font-size: 20px; }
.kj-cer2[data-kind="cut"] .kj-sheet-title { font-size: 21px; }
.kj-cer2-sheet .kj-sheet-title-ar { font-size: 13.5px; color: var(--gold); }
.kj-cer2-sheet .kj-sheet-meta[data-tone="green"] { color: var(--mint); }
.kj-cer2-sheet .kj-slist { margin-bottom: 14px; }
.kj-cer2-sheet .kj-srow { border-color: var(--line); padding: 12px 15px; }
.kj-cer2-sheet .kj-srow[data-on="true"] { border-color: var(--gold); }
.kj-cer2-sheet .kj-btn-ghost { padding: 14px 0; }
.kj-cgrid--table { margin-bottom: 13px; }
.kj-cgrid--table .kj-ccard { padding: 14px 14px; gap: 8px; min-height: 0; border-color: var(--line); }
.kj-cgrid--table .kj-ccard[data-on="true"] { border-color: var(--gold); }
.kj-cgrid--table .kj-cicon { width: 30px; height: 32px; }
.kj-cgrid--table .kj-cicon--cut i { height: 14px; }
.kj-cgrid--table .kj-ccard-name { font-size: 18px; }
.kj-cgrid--table .kj-ccard-ar { font-size: 12.5px; }
.kj-cgrid--table .kj-ccard-desc { margin-top: 2px; }
.kj-cer2-depth { display: flex; align-items: center; gap: 12px; margin-bottom: 13px; }
.kj-cer2-depth[hidden] { display: none; }
.kj-cer2-depth .kj-slider-track { flex: 1; }
.kj-cer2-depth-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--ink-3); }
.kj-cer2-depth-n { font-family: 'Archivo Black', sans-serif; font-size: 13px; line-height: 1; color: var(--gold); min-width: 18px; text-align: right; }
/* a short phone: the felt gives way before the sheet does */
@media (max-height: 700px) { .kj-cer2-felt { height: 220px; } }
/* 09: the chair that SHUFFLED reads in the board's var(--violet) */
.kj-seat-status[data-tone="trix"] { color: var(--violet); }
/* 16/16c: a flatter perspective — the near card no longer balloons mid-flip (MINE) */
.kj-won--grab { perspective: 1600px; }

/* ===== 2026-09-04 REBUILD — boards 11a/11b/12: the auction as a table view ===== */
.kj-auc-felt { height: 260px; }
.kj-auc[data-mode="trump"] .kj-auc-felt, .kj-auc[data-mode="trumpwatch"] .kj-auc-felt { height: 420px; }
.kj-auc-felt::after { width: 102px; height: 102px; }
.kj-auc[data-mode="trump"] .kj-auc-felt::after, .kj-auc[data-mode="trumpwatch"] .kj-auc-felt::after { width: 126px; height: 126px; opacity: .055; }
.kj-auc-felt .kj-av { width: 40px; height: 40px; }
.kj-auc-felt .kj-av-head { width: 12px; height: 12px; margin-left: -6px; }
.kj-auc-felt .kj-av-body { width: 23px; height: 12px; margin-left: -12px; border-radius: 12px 12px 0 0; }
/* the centre: HIGHEST BID 7 */
.kj-auc-high { position: absolute; left: 50%; top: 52%; transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; gap: 5px; z-index: 2; }
.kj-auc-high-k { font-family: 'IBM Plex Mono', monospace; font-size: 10px; letter-spacing: .18em; color: var(--salmon); }
.kj-auc-high-n { font-family: 'Archivo Black', sans-serif; font-size: 30px; line-height: 1; color: var(--salmon); }
.kj-auc-high-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 11px; line-height: 1.4; color: var(--ink-3); }
.kj-auc-high[data-tone="dim"] .kj-auc-high-k, .kj-auc-high[data-tone="dim"] .kj-auc-high-n { color: var(--ink-3); }
/* the dealer tag, top-right */
.kj-auc-dealer { position: absolute; right: 9px; top: 9px; display: flex; flex-direction: column; align-items: flex-end; gap: 3px; z-index: 3; }
.kj-auc-dealer-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--ink-3); }
.kj-auc-dealer-n { font-size: 11px; font-weight: 800; color: var(--violet); }
/* 12: the bid pills beside the avatars */
.kj-auc-pill {
  position: absolute; display: flex; align-items: center; gap: 12px; box-sizing: border-box; z-index: 3;
  background: rgba(9,13,8,0.68); border: 1px solid var(--line); border-radius: 16px; padding: 7px 13px 7px 7px;
}
.kj-auc-pill[data-rev="1"] { flex-direction: row-reverse; }
.kj-auc-pill[data-won="1"] { background: rgba(239,195,117,0.12); border-color: var(--gold); }
.kj-auc-pill .kj-av { width: 42px; height: 42px; }
.kj-auc-pill[data-won="1"] .kj-av { border-color: var(--gold); }
.kj-auc-pill[data-active="1"] .kj-av { animation: knRing 1.6s ease-out infinite; }
.kj-auc-pill-col { display: flex; flex-direction: column; gap: 2px; }
.kj-auc-pill[data-rev="1"] .kj-auc-pill-col { align-items: flex-end; }
.kj-auc-pill-name { font-size: 12.5px; font-weight: 700; color: var(--ink-2); }
.kj-auc-pill[data-won="1"] .kj-auc-pill-name { color: var(--gold); }
.kj-auc-pill-row { display: flex; align-items: baseline; gap: 5px; }
.kj-auc-pill[data-rev="1"] .kj-auc-pill-row { flex-direction: row-reverse; }
.kj-auc-pill-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-auc-pill-n { font-family: 'Archivo Black', sans-serif; font-size: 15px; line-height: 1; color: var(--ink-3); }
.kj-auc-pill-row[data-tone="off"] .kj-auc-pill-k { color: var(--ink-4); }
.kj-auc-pill-row[data-tone="gold"] .kj-auc-pill-k, .kj-auc-pill-row[data-tone="gold"] .kj-auc-pill-n { color: var(--gold); }
.kj-auc-centre { position: absolute; left: 50%; top: 31%; transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; gap: 5px; z-index: 2; white-space: nowrap; }
.kj-auc-centre-en { font-family: 'IBM Plex Mono', monospace; font-size: 10px; letter-spacing: .18em; color: var(--gold); }
.kj-auc-centre-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 11.5px; line-height: 1.4; color: var(--ink-3); }
/* the hand band: thirteen cards folded in one row */
.kj-auc-hand { flex: none; height: 122px; margin-top: 9px; box-sizing: border-box; display: flex; align-items: flex-start; justify-content: center; opacity: .96; }
.kj-auc-lane { height: 122px; overflow: hidden; display: flex; align-items: flex-start; }
.kj-auc-card {
  width: 80px; height: 112px; box-sizing: border-box; flex: none; position: relative;
  background: var(--card-cream); border-radius: 8px; border: 1px solid rgba(239,195,117,0.42); box-shadow: -3px 4px 10px rgba(0,0,0,0.5);
}
.kj-auc-corner { position: absolute; left: 0; top: 8px; width: 28px; display: flex; flex-direction: column; align-items: center; gap: 2px; color: var(--card-ink); }
.kj-auc-card[data-red="true"] .kj-auc-corner { color: var(--oxblood); }
.kj-auc-rank { font-family: 'Archivo Black', sans-serif; font-size: 26px; line-height: 1; letter-spacing: -.05em; }
.kj-auc-rank[data-ten="1"] { font-size: 20px; }
.kj-auc-suit { font-size: 28px; line-height: 1; }
/* the note line */
.kj-auc-note { flex: none; height: 22px; display: flex; align-items: center; justify-content: center; font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); white-space: nowrap; overflow: hidden; }
.kj-auc-note[data-tone="red"] { color: var(--salmon); }
/* the sheet (320 tall on the board; 156 for the trump) */
.kj-auc-sheet { margin-top: 2px; padding: 16px 20px 26px; }
.kj-auc[data-mode="trump"] .kj-auc-sheet, .kj-auc[data-mode="trumpwatch"] .kj-auc-sheet { padding: 14px 20px 24px; }
.kj-auc[data-mode="trump"] .kj-sheet-grab, .kj-auc[data-mode="trumpwatch"] .kj-sheet-grab { margin-bottom: 13px; }
.kj-auc-sheet .kj-sheet-head { margin-bottom: 13px; }
.kj-auc[data-mode="redeal"] .kj-sheet-head { margin-bottom: 12px; }
.kj-auc[data-mode="redeal"] .kj-sheet-title-ar { font-size: 13px; }
.kj-auc-meta { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.kj-auc-meta-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-auc-meta-n { font-family: 'Archivo Black', sans-serif; font-size: 17px; line-height: 1; color: var(--salmon); }
.kj-auc-clock { font-family: 'IBM Plex Mono', monospace; font-size: 10px; color: var(--gold); }
.kj-auc-notice { display: flex; align-items: center; gap: 8px; box-sizing: border-box; background: rgba(158,59,41,0.14); border: 1px solid var(--oxblood-line); border-radius: 12px; padding: 10px 13px; margin-bottom: 12px; }
.kj-auc-notice span { font-size: 11.5px; line-height: 1.45; color: var(--ink); flex: 1; text-wrap: pretty; }
.kj-auc-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; margin-bottom: 12px; }
.kj-auc-tile {
  box-sizing: border-box; height: 50px; border-radius: 12px; display: flex; align-items: center; justify-content: center;
  appearance: none; cursor: pointer; font-family: 'Archivo Black', sans-serif; font-size: 18px; line-height: 1; padding: 0;
  background: var(--surf2); border: 1px solid var(--line5); color: var(--ink);
}
.kj-auc-tile[data-state="locked"] { background: var(--ink-bg2); border-color: var(--surf3); color: var(--line6); cursor: default; }
.kj-auc-tile[data-state="on"] { background: var(--gold); border-color: var(--gold); box-shadow: 0 0 0 3px rgba(239,195,117,0.22); color: var(--ink-bg); font-size: 20px; }
.kj-auc-or { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); margin-bottom: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kj-auc-passes { display: flex; gap: 8px; margin-bottom: 12px; }
.kj-auc-pass {
  box-sizing: border-box; flex: 1; background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 9px 6px;
  display: flex; flex-direction: column; align-items: center; gap: 2px; appearance: none; cursor: pointer; font-family: inherit;
}
.kj-auc-pass-en { font-family: 'Archivo Black', sans-serif; font-size: 11px; line-height: 1; color: var(--ink); }
.kj-auc-pass--weak .kj-auc-pass-en { color: var(--ink-3); }
.kj-auc-pass--strong .kj-auc-pass-en { color: var(--mint); }
.kj-auc-pass-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 9.5px; line-height: 1.4; color: var(--ink-3); }
.kj-auc-pass--strong .kj-auc-pass-ar { color: var(--mint); }
.kj-auc-pass-hint { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); margin-top: 1px; }
.kj-auc-pass[data-on="1"] { background: var(--surf2); border-color: var(--gold); box-shadow: inset 0 0 0 1px rgba(239,195,117,0.28); }
.kj-auc-pass--strong[data-on="1"] { border-color: var(--mint); box-shadow: none; }
.kj-auc-pass--weak[data-on="1"] { border-color: var(--salmon); box-shadow: none; }
.kj-auc-primary {
  display: block; width: 100%; box-sizing: border-box; appearance: none; cursor: pointer; border: 0; font-family: inherit;
  background: var(--oxblood); color: var(--ink); font-size: 15px; font-weight: 800; letter-spacing: .04em; padding: 15px 0; border-radius: 12px; text-align: center;
}
.kj-auc-primary[data-pass="1"] { background: var(--surf2); border: 1px solid var(--line5); color: var(--ink); padding: 14px 0; }
.kj-auc-acts .kj-auc-primary { flex: 1.4; width: auto; }
.kj-auc-redeal {
  flex: 1; box-sizing: border-box; appearance: none; cursor: pointer; font-family: inherit;
  background: var(--surf2); border: 1px solid var(--mint); color: var(--mint); font-size: 14px; font-weight: 800; letter-spacing: 0; padding: 14px 0; border-radius: 12px; text-align: center;
}
.kj-auc-trump-head { display: flex; align-items: center; gap: 8px; margin-bottom: 11px; }
.kj-auc-trump-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-auc[data-mode="trump"] .kj-auc-trump-k { color: var(--gold); }
.kj-auc-trump-head .kj-auc-clock { margin-left: auto; }
/* 2026-09-21: the trump tiles are a scale drawing of the hand below, so they
   are placed, not flowed - a 4-column grid cannot put a tile over its own
   cards. The row keeps the lane's width and centres on the same axis; the
   tiles carry left/width in px from ui/auction.js. max-width stops a narrow
   sheet from pushing the row out of its own padding; at that point the
   alignment drifts by the difference, which is the honest failure. */
.kj-auc-suits {
  position: relative; height: 58px;
  /* --kj-suits-w/-dx/-max are written by kjAlignTrumpTiles once the lane can be
     measured. Unset, the row centres itself inside the sheet and the tiles fall
     back to their percentages, which is already proportionally right. */
  width: var(--kj-suits-w, auto);
  max-width: var(--kj-suits-max, 100%);
  /* The shift is a TRANSFORM, not a margin. With an explicit width and both
     margins set, the box is over-constrained and the browser drops one of
     them - margin-right in English, margin-LEFT in Arabic - so a physical
     margin silently did nothing on the Arabic sheet and left the row 10px off
     the lane, which the tiles then inherited as a 10px overlap. A translate
     is physical, is never dropped, and does not disturb the layout the
     measurement was taken from. */
  margin-inline: auto;
  transform: translateX(var(--kj-suits-dx, 0));
}
/* THE TILE IS A CARD FACE. Ahmad asked for the auction suits to be the colour
   the cards are, and on the old dark tile that is unreadable for half of them:
   --card-ink is rgb(23,19,15), which is ink for a CREAM face and a black
   rectangle on a dark green one. The first build of this shipped ♠ and ♣ you
   could barely see. Card ink needs a card, so the tile takes the same cream,
   radius and border as .kj-auc-card and the suit sits on it in exactly the ink
   it has two centimetres below - which also makes the tile read as what it is,
   a card of that suit as wide as the number you hold. */
.kj-auc-suit-tile {
  position: absolute; top: 0;
  /* PHYSICAL left, not inset-inline-start: kjAlignTrumpTiles measures real
     rects, which are physical, and in Arabic the lane mirrors while the rects
     do not. A logical property here would flip the numbers a second time and
     put every tile at the wrong end. */
  left: var(--x, 0); width: var(--w, 44px);
  box-sizing: border-box; height: 58px; border-radius: 8px;
  background: var(--card-cream); border: 1px solid rgba(239,195,117,0.42); box-shadow: -3px 4px 10px rgba(0,0,0,0.5);
  display: flex; align-items: center; justify-content: center; appearance: none; cursor: pointer; font-size: 30px; line-height: 1;
  color: var(--suit-ink, var(--card-ink)); padding: 0;
}
/* The count is the reason the tile is this wide - it says the number the width
   is already showing, for anyone who wants it exactly. Ink stays the suit's.
   Cornered rather than flowed beside the glyph: at the 44px floor a glyph plus
   a gap plus a number does not fit, and the lint ratchet is right that 6px is
   not on the spacing scale. */
.kj-auc-suit-n {
  position: absolute; inset-block-end: 4px; inset-inline-end: 8px;
  font-family: var(--font-mono); font-size: 12px; line-height: 1; color: var(--card-dead-ink);
}
/* Not mine to name: the sheet is watching someone else pick. The face fades
   rather than the ink changing, so the suit stays the colour it is. */
.kj-auc-suit-tile:disabled { cursor: default; opacity: .55; }
body.theme-dark .kj-auc-primary { color: var(--ink); }
body.theme-dark .kj-auc-redeal { color: var(--mint); }
.kj-auc[data-busy="1"] .kj-auc-sheet { pointer-events: none; opacity: .72; }
@media (max-height: 700px) {
  .kj-auc-felt { height: 220px; }
  .kj-auc[data-mode="trump"] .kj-auc-felt, .kj-auc[data-mode="trumpwatch"] .kj-auc-felt { height: 300px; }
}
/* 16: the flip swaps sides edge-on (see renderTrickGrab) */
.kj-won3d[data-side="back"] .kj-won3d-face { display: none; }
.kj-won3d:not([data-side="back"]) .kj-won3d-back { display: none; }
/* 08/09: the deck sits a little higher and smaller than the board so the You chair clears it (MINE) */
.kj-cer2-cut, .kj-cer2-fan { top: 46%; }
.kj-cer2-cut { transform: translate(-50%, -50%) scale(.9); }
/* 11a/12 (2026-09-04): under the skin the chairs carry the auction — no banner
   ("NOOR IS BIDDING…") and no centre toast ("BID 8"); both showed through
   during the deal beat while the bots were already bidding. */
/* 16b/16c: the line under the headline — "THEY LEAD THE NEXT ONE" */
.kj-won-sub { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }

/* ===== 54/55 (2026-09-04): English-only / Arabic-only ===== */
/* 54a/55a: no Arabic anywhere on the screen - except what a PLAYER SAYS.
   81 amended (2026-09-19): "no Arabic anywhere" was written about the app's own
   labels, keys and footers. The twelve phrases are not the app talking, they
   are the player's vocabulary, and Design put them outside translation on
   purpose: "the same category as a player's name." Hiding them here left the ＋
   sheet's default tab as twelve blank buttons in English-only mode - the same
   defect the rule below had, found by the gate after only that one was fixed.
   An English-only player does not want their chat vocabulary deleted. */
body.kj-en.kj-table [lang="ar"]:not(.kj-more-ph):not(.kn-pill-ar):not(.kn-char-word):not(.kj-dock-ph), body.kj-en.kj-table .kj-hint-ar, body.kj-en.kj-table .kj-hint-sep, body.kj-en.kj-table .kj-sort-ar,
body.kj-en.kj-table .kj-won-joker-sep, body.kj-en.kj-table .kj-won-joker-ar, body.kj-en.kj-table .kj-burst-joker-ar { display: none !important; }
/* 54b/55b: the English twin goes where an Arabic line already exists; the chrome mirrors, the seats do not */
body.kj-ar.kj-table .kj-won-title, body.kj-ar.kj-table .kj-sheet-title, body.kj-ar.kj-table .kj-hint-en:has(+ .kj-hint-sep), body.kj-ar.kj-table .kj-hint-sep,
body.kj-ar.kj-table .kj-srow-name, body.kj-ar.kj-table .kj-ccard-name, body.kj-ar.kj-table .kj-auc-pass-en, body.kj-ar.kj-table .kj-cer2-strip-en,
body.kj-ar.kj-table .kj-won-joker-en, body.kj-ar.kj-table .kj-won-joker-sep, body.kj-ar.kj-table .kj-auc-high-k, body.kj-ar.kj-table .kj-auc-centre-en,
body.kj-ar.kj-table .kj-sort-en, body.kj-ar.kj-table .kj-tomake-k, body.kj-ar.kj-table .kj-burst-joker-en, body.kj-ar.kj-table .kj-cap-en,
body.kj-ar.kj-table .kj-lreview-head-en, body.kj-ar.kj-table .kj-fcap-en,
/* 80: the last-trick box carries its key as a pair - a mono TOOK LAST and a
   Lemonada .kj-lt-k-ar. The English half was hidden nowhere, so the Arabic
   felt read the key twice, once in each language, on one surface - exactly
   what 65 forbids. The band's own keys go through kjT and need no pair. */
body.kj-ar.kj-table .kj-lt-k { display: none !important; }
body.kj-ar.kj-table .kj-srow-desc, body.kj-ar.kj-table .kj-ccard-desc { display: none !important; }   /* the descs have no Arabic line */
body.kj-ar.kj-table .kj-bar, body.kj-ar.kj-table .kj-cer2-sheet, body.kj-ar.kj-table .kj-scoretab, body.kj-ar.kj-table .kj-ltray,
body.kj-ar.kj-table .kj-lreview-panel, body.kj-ar.kj-table .kj-sort, body.kj-ar.kj-table .kj-auc-note, body.kj-ar.kj-table .kj-cer2-strip,
body.kj-ar.kj-table .hand-hint-row, body.kj-ar.kj-table .kj-tot, body.kj-ar.kj-table .overflow-menu { direction: rtl; }
body.kj-ar.kj-table .kj-auc-grid { direction: rtl; }
/* 80 amended (2026-09-18): the contract band and the last-trick box are PROSE -
   "<declarer> <bid> <suit> WON <n> OF <bid>" and "<key> <card> <name>" - and they
   shipped inside this file's ltr default, so in Arabic they read backwards:
   "8 mn 7 akhadh ... AISHA" instead of "AISHA 8 <suit> akhadh 7 mn 8". The whole
   point of board 80 was a contract answerable at a glance, which it was not for
   an Arabic reader. Only the phrase rows flip; the hand (#hand above) and the
   US/THEM scoreboard stay ltr by the rule two lines down - a picture holds its
   order, only prose mirrors. */
body.kj-ar.kj-table .kj-ct-row, body.kj-ar.kj-table .kj-ct-won,
body.kj-ar.kj-table .kj-lt { direction: rtl; }
/* ...but a player's NAME is a Latin run inside that rtl box, and text-overflow
   clips at the END OF THE DIRECTION, so "MARIAM" came out as "...RIAM" - the
   ellipsis eating the start of the name instead of its tail. The name keeps
   its own direction so it truncates where a reader expects. Caught by
   screenshotting the Arabic felt and reading the top-right corner; the DOM
   agreed (scrollWidth 45 against clientWidth 42). */
body.kj-ar.kj-table .kj-ct-name { direction: ltr; }
/* UX Phase 1: "US - THEM" is a scoreboard, not a sentence. Mirrored, it read "15 - 14-".
 * Board 65: pictures of a thing hold their order; only prose flips. */
body.kj-ar.kj-table .kj-bar-sc { direction: ltr; }   /* 55b: the bid grid runs right-to-left */
body.kj-ar.kj-table .kj-auc-lane, body.kj-ar.kj-table .kn-seats, body.kj-ar.kj-table #trick, body.kj-ar.kj-table #hand { direction: ltr; }
body.kj-ar.kj-table .kj-seat-status, body.kj-ar.kj-table .kj-seat-name, body.kj-ar.kj-table .kj-ltray-cap, body.kj-ar.kj-table .kj-bar-trick,
body.kj-ar.kj-table .kj-auc-pill-k, body.kj-ar.kj-table .kj-auc-meta-k, body.kj-ar.kj-table .kj-scoretab-l, body.kj-ar.kj-table .kj-scoretab-head span,
body.kj-ar.kj-table .kj-auc-or, body.kj-ar.kj-table .kj-auc-pass-hint, body.kj-ar.kj-table .kj-won-sub, body.kj-ar.kj-table .kj-auc-trump-k,
body.kj-ar.kj-table .kj-sheet-meta, body.kj-ar.kj-table .kj-auc-dealer-k, body.kj-ar.kj-table .kj-ltray-k, body.kj-ar.kj-table .kj-bar-trump-k,
body.kj-ar.kj-table .kj-cer2-depth-k { font-family: Lemonada, 'IBM Plex Mono', sans-serif; letter-spacing: 0; }
body.kj-ar.kj-table .kj-sheet-title-ar { font-size: 20px; }
body.kj-ar.kj-table .kj-won-ar { font-size: 26px; }
/* 22b: the felt board borrowed kjWonIn, whose end frame is translateX(-50%) — the
   whole inset-0 board sat half off the felt to the left. Its own fade now. */
@keyframes kjFcapIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.kj-fcap { animation: kjFcapIn .28s ease-out both; }
/* 54b: the note and counters in the Arabic face too */
body.kj-ar.kj-table .kj-auc-note, body.kj-ar.kj-table .kj-fcap-sub, body.kj-ar.kj-table .kj-won-tally-k, body.kj-ar.kj-table .kj-auc-clock,
body.kj-ar.kj-table .kj-cer2-strip-en, body.kj-ar.kj-table .kj-scoretab-b { font-family: Lemonada, 'IBM Plex Mono', sans-serif; letter-spacing: 0; }
/* 22b joker line: one language at a time (the [lang=ar] rule already covers English-only) */
body.kj-ar.kj-table .kj-fcap-joker-en { display: none !important; }
body.kj-ar.kj-table .kj-fcap-joker-ar { font-size: 13px; }
/* the bar's second line never wraps; a long state ("BIDDING · LAST TO SPEAK") tightens its tracking (MINE) */
.kj-bar-trick { white-space: nowrap; }
.kj-bar-trick[data-long="1"] { letter-spacing: .14em; }

/* ===== 56/58 (2026-09-04): the MESSAGE LANE — 40px between the felt and the hand, always there ===== */
body.kj-table .game-area:has(> .kj-lane) {
  grid-template-rows: 53px minmax(0, 1fr) 40px auto 0;
  grid-template-areas: "top top" "felt felt" "lane lane" "hand hand" "rail rail";
}
body.kj-table .game-area > .kj-lane { grid-area: lane; }
.kj-lane { height: 40px; box-sizing: border-box; padding: 0 14px; display: flex; align-items: center; position: relative; overflow: hidden; }
.kj-lane .kj-lane-strip { margin: 0; flex: 1; min-width: 0; animation: kjLaneIn .14s ease-out both; }
.kj-lane .kj-lane-strip.kj-lane-out { animation: kjLaneOut .14s ease-in both; }
.kj-lane .kj-cer2-strip-en { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
@keyframes kjLaneIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
@keyframes kjLaneOut { from { opacity: 1; } to { opacity: 0; } }
/* 13b/58: one row on the phone, no felt joker pills where the lane carries them */
body.kj-table .game-area:has(> .kj-lane) .kj-fcap-joker, body.kj-table .game-area:has(> .kj-lane) .kj-won-joker { display: none !important; }
/* 54/55: the sort chips never wrap; Arabic mode tightens them so three fit beside the HOLD TO DRAG key (v143) */
.kj-sort-chip { white-space: nowrap; flex: none; }
body.kj-ar.kj-table .kj-sort-chip { padding: 6px 10px; font-size: 11px; }
body.kj-ar.kj-table .kj-sort-k { flex: 1; min-width: 0; }
body.kj-ar.kj-table .kj-sort-ar { white-space: normal; font-size: 9px; line-height: 1.25; text-align: start; }

/* ===== 59b (2026-09-05): the simplified phone felt — five clusters ============
   HUD "← mark … 28 — 19 | ♠ ⋯", chairs (name + "LED ♠"), the trick, the hand,
   one footer fact; one ＋ bottom-right of the felt carries the rest (60). */
.kj-bar[data-simple="1"] .kj-bar-right { gap: 12px; }
.kj-bar-sc { display: flex; align-items: baseline; gap: 5px; cursor: pointer; }
.kj-bar-sc-us { font-family: 'Archivo Black', sans-serif; font-size: 17px; line-height: 1; color: var(--gold); }
.kj-bar-sc-dash { font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: var(--ink-4); }
.kj-bar-sc-them { font-family: 'Archivo Black', sans-serif; font-size: 17px; line-height: 1; color: var(--ink-2); }
.kj-bar-sc-sep { width: 1px; height: 20px; background: var(--line); display: block; }
.kj-bar-sc-trump { font-size: 17px; line-height: 1; color: var(--gold); }
.kj-bar[data-simple="1"] .kj-bar-more { font-size: 15px; }
/* the sort row lives in the ＋ sheet on the phone (60: HAND ORDER) */
body.kj-table:not(.kj-tablet):not(.kj-wide):not(.kj-landscape) .ga-hand .kj-sort { display: none !important; }
/* the ＋ — 42px, radius 12, right 10 / bottom 10 of the felt */
.kj-plus {
  position: absolute; right: 10px; bottom: 10px; width: 42px; height: 42px; border-radius: 12px; box-sizing: border-box;
  background: rgba(9,13,8,0.6); border: 1px solid var(--line); display: flex; align-items: center; justify-content: center;
  font-family: 'IBM Plex Mono', monospace; font-size: 15px; color: var(--ink-3); cursor: pointer; padding: 0; pointer-events: auto; z-index: 6;
}
body.kj-plus-open .kj-plus { visibility: hidden; }
/* 2026-09-19: the ＋ and 67's two rails were drawn into the same corners a
   fortnight apart and nobody put them on one page. 59b's ＋ is right 10 /
   bottom 10 at z-index 6; 67's signal rail is right 8 / bottom 8 at z-index 3,
   so the ＋ box sat squarely on SWEEP and won. In ARABIC the ＋ mirrors to the
   left and the rails do not, so there it sat on ＋ MORE - the bottom button of
   the reaction dock. That is the second half of "the left side buttons don't
   work": three of them were pointer-events dead, and the fourth was covered.

   The rails do not mirror, so neither does the ＋ any more. It stacks on top
   of the signal rail's column instead: 8 + 42 + 5 + 42 + 5 = 102. */
body.kj-table .kj-tab .kj-docks ~ .kj-plus,
body.kj-ar.kj-table .kj-tab .kj-docks ~ .kj-plus { right: 8px; left: auto; bottom: 102px; }
/* the leader's "LED ♠" — mono 9px, .14em, gold (59b) */
body.kj-simple .kj-seat-status[data-tone="gold"] { color: var(--gold); }

/* ===== 60/60b (2026-09-05): the ＋ sheet ====================================== */
.kj-plus-scrim { position: absolute; inset: 0; background: rgba(9,13,8,0.62); z-index: 8; pointer-events: auto; }
.kj-plus-sheet {
  position: absolute; left: 0; right: 0; box-sizing: border-box; background: var(--surface-sheet); border-top: 1px solid var(--line-strong);
  border-radius: 22px 22px 0 0; padding: 14px 20px 16px; z-index: 40; display: flex; flex-direction: column; gap: 12px;
  overflow-y: auto; overscroll-behavior: contain; pointer-events: auto;
}
.kj-plus-grab { height: 4px; width: 40px; background: var(--line-strong); border-radius: 999px; align-self: center; flex: none; }
.kj-plus-sec { display: flex; flex-direction: column; gap: 8px; flex: none; }
.kj-plus-head { height: 14px; display: flex; align-items: center; gap: 8px; }
.kj-plus-title { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--gold); white-space: nowrap; }
.kj-plus-title-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 9.5px; color: var(--ink-3); white-space: nowrap; }
.kj-plus-note { margin-left: auto; font-family: 'IBM Plex Mono', monospace; font-size: 9px; letter-spacing: .14em; color: var(--ink-4); white-space: nowrap; }
.kj-plus-note-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 9px; color: var(--ink-4); white-space: nowrap; }
/* SCORE */
.kj-plus-scorerow { height: 54px; display: flex; gap: 8px; }
.kj-plus-tbl {
  flex: 1; box-sizing: border-box; background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 7px 11px;
  display: grid; grid-template-columns: 40px 1fr 1fr; align-items: center; gap: 2px 8px;
}
.kj-plus-k { font-family: 'IBM Plex Mono', monospace; font-size: 9px; letter-spacing: .14em; color: var(--ink-4); }
.kj-plus-k--us { color: var(--gold); }
.kj-plus-tbl .kj-plus-k:nth-child(3) { color: var(--ink-2); }
.kj-plus-n { font-family: 'Archivo Black', sans-serif; font-size: 14px; line-height: 1; color: var(--ink-2); }
.kj-plus-n--us { color: var(--gold); }
.kj-plus-tomake {
  width: 96px; flex: none; box-sizing: border-box; background: var(--surface); border: 1px solid var(--chair-ring); border-radius: 12px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
}
.kj-plus-tomake-k { font-family: 'IBM Plex Mono', monospace; font-size: 9px; letter-spacing: .14em; color: var(--ink-3); }
.kj-plus-tomake-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 9px; color: var(--ink-3); }
.kj-plus-tomake-n { font-family: 'Archivo Black', sans-serif; font-size: 26px; line-height: 1; color: var(--gold); }
/* SEATS */
.kj-plus-seats { height: 36px; display: flex; gap: 8px; }
.kj-plus-seat {
  flex: 1; min-width: 0; box-sizing: border-box; background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 5px 4px;
  display: flex; align-items: center; justify-content: center; gap: 5px;
}
.kj-plus-seat[data-active="true"] { background: rgba(239,195,117,0.08); border-color: var(--gold); }
.kj-plus-av { width: 24px; height: 24px; border-radius: 50%; background: var(--chair); border: 1.5px solid var(--chair-ring); overflow: hidden; flex: none; display: flex; align-items: center; justify-content: center; box-sizing: border-box; }
.kj-plus-seat[data-active="true"] .kj-plus-av { border-color: var(--gold); animation: knRing 1.6s ease-out infinite; }
.kj-plus-av img { width: 100%; height: 100%; object-fit: cover; display: block; }
.kj-plus-av i { font-style: normal; font-family: 'Archivo Black', sans-serif; font-size: 10px; color: var(--ink); }
.kj-plus-seat-col { display: flex; flex-direction: column; gap: 1px; align-items: flex-start; min-width: 0; }
.kj-plus-seat-name { font-weight: 700; font-size: 10px; line-height: 1.3; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 44px; }
.kj-plus-seat[data-me="true"] .kj-plus-seat-name { color: var(--gold); }
.kj-plus-seat-nums { display: flex; align-items: baseline; gap: 3px; }
.kj-plus-seat-nums b { font-family: 'Archivo Black', sans-serif; font-weight: 400; font-size: 11px; line-height: 1; color: var(--ink); }
.kj-plus-seat-nums i { font-style: normal; font-family: 'IBM Plex Mono', monospace; font-size: 8px; color: var(--ink-4); }
.kj-plus-won { color: var(--mint) !important; }
.kj-plus-left { color: var(--ink-3) !important; }
.kj-plus-legend { height: 10px; display: flex; align-items: center; gap: 8px; font-family: 'IBM Plex Mono', monospace; font-size: 8.5px; letter-spacing: .14em; color: var(--ink-4); }
.kj-plus-legend-ar { font-family: Lemonada, sans-serif; font-weight: 600; letter-spacing: 0; }
/* LAST TRICK — the cross (26x36 minis) and the play order */
.kj-plus-last { height: 74px; display: flex; gap: 12px; }
.kj-plus-cross { width: 92px; height: 74px; flex: none; position: relative; }
.kj-plus-mini {
  position: absolute; width: 26px; height: 36px; box-sizing: border-box; background: var(--card-cream); border-radius: 4px; border: 1px solid rgba(23,19,15,0.2);
  display: flex; flex-direction: column; align-items: center; justify-content: center; color: var(--card-ink);
}
.kj-plus-mini[data-red="true"] { color: var(--oxblood); }
.kj-plus-mini[data-win="true"] { border: 2px solid var(--gold); box-shadow: 0 0 0 3px rgba(239,195,117,0.3); }
.kj-plus-mini[data-empty="1"] { background: rgba(252,248,241,0.06); border: 1px dashed var(--chair-ring); }
.kj-plus-mini b { font-family: 'Archivo Black', sans-serif; font-weight: 400; font-size: 13px; line-height: 1; }
.kj-plus-mini i { font-style: normal; font-size: 12px; line-height: 1; }
.kj-plus-mini--north { top: 0; left: 50%; margin-left: -13px; }
.kj-plus-mini--west { top: 19px; left: 0; }
.kj-plus-mini--east { top: 19px; right: 0; }
.kj-plus-mini--south { top: 38px; left: 50%; margin-left: -13px; }
.kj-plus-order { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; justify-content: center; }
.kj-plus-orow { display: flex; align-items: baseline; gap: 5px; }
.kj-plus-on { font-family: 'IBM Plex Mono', monospace; font-size: 8.5px; color: var(--ink-4); width: 9px; flex: none; }
.kj-plus-oname { font-weight: 600; font-size: 10.5px; line-height: 1.3; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 64px; }
.kj-plus-ocard { font-family: 'IBM Plex Mono', monospace; font-size: 10px; color: var(--ink-3); }
.kj-plus-orole { font-family: 'IBM Plex Mono', monospace; font-size: 8.5px; letter-spacing: .14em; color: var(--ink-4); }
.kj-plus-orole-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 8.5px; color: var(--ink-4); }
.kj-plus-orow[data-win="true"] .kj-plus-oname, .kj-plus-orow[data-win="true"] .kj-plus-ocard, .kj-plus-orow[data-win="true"] .kj-plus-orole, .kj-plus-orow[data-win="true"] .kj-plus-orole-ar { color: var(--gold); }
.kj-plus-empty { font-family: 'IBM Plex Mono', monospace; font-size: 9px; letter-spacing: .14em; color: var(--ink-4); }
.kj-plus-empty-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 9px; color: var(--ink-4); }
/* REACT — the ten, 5 x 2 */
.kj-plus-react { height: 54px; display: grid; grid-template-columns: repeat(5, 1fr); grid-auto-rows: 1fr; gap: 5px; }
.kj-plus-rbtn {
  box-sizing: border-box; background: var(--surface); border: 1px solid var(--line); border-radius: 8px; padding: 0; margin: 0; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; min-width: 0;
}
.kj-plus-rbtn[data-gold="true"] .kj-plus-rg { color: var(--gold); }
.kj-plus-rg { font-size: 15px; line-height: 1; color: var(--ink-2); }
.kj-plus-ren { font-weight: 700; font-size: 8px; line-height: 1; color: var(--ink-3); white-space: nowrap; }
.kj-plus-rar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 8px; line-height: 1; color: var(--ink-3); white-space: nowrap; }
/* SIGNAL — gesture and suit on one row */
.kj-plus-sig { height: 32px; display: flex; gap: 5px; }
.kj-plus-gest, .kj-plus-suit {
  box-sizing: border-box; background: var(--surface); border: 1px solid var(--line); border-radius: 8px; padding: 0; margin: 0; cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 5px; min-width: 0;
}
.kj-plus-gest { flex: 1.15; }
.kj-plus-gest[data-on="true"] { border-color: var(--gold); background: rgba(239,195,117,0.08); }
.kj-plus-gg { font-size: 13px; line-height: 1; color: var(--ink-3); }
.kj-plus-gen { font-family: 'Archivo Black', sans-serif; font-size: 9.5px; line-height: 1; color: var(--ink); }
.kj-plus-gar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 9px; line-height: 1; color: var(--ink); }
.kj-plus-sig-sep { width: 1px; background: var(--line); flex: none; display: block; }
.kj-plus-suit { flex: 1; font-size: 17px; line-height: 1; color: var(--ink-2); }
.kj-plus-suit[data-red="true"] { color: var(--salmon); }
/* HAND ORDER — the sort chips on the header row */
.kj-plus-sec--order .kj-plus-head { height: 28px; }
.kj-plus-sort { margin-left: auto; display: flex; gap: 5px; }
.kj-plus-chip {
  box-sizing: border-box; background: var(--surface); border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px; margin: 0; cursor: pointer;
  display: flex; align-items: center; gap: 5px; font-weight: 600; font-size: 11px; line-height: 1; color: var(--ink-2); white-space: nowrap;
}
.kj-plus-chip[data-on="true"] { background: var(--gold); border-color: var(--gold); font-weight: 800; color: var(--ink-bg); }
.kj-plus-chip-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 10px; }
/* the ✕ — the ＋'s box, same corner, above the sheet (60) */
.kj-plus-x {
  position: absolute; right: 10px; bottom: 50px; width: 42px; height: 42px; border-radius: 12px; box-sizing: border-box; border: 0; padding: 0; margin: 0;
  background: var(--gold); color: var(--ink-bg); font-family: 'IBM Plex Mono', monospace; font-size: 16px; display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 2;
}
.kj-plus-sheet { position: absolute; }
/* language modes (54/55): one language per label; RTL reading order in Arabic (60b), the cross never mirrors */
body.kj-en.kj-table .kj-plus-sheet [lang="ar"] { display: none !important; }
body.kj-ar.kj-table .kj-plus-title, body.kj-ar.kj-table .kj-plus-note, body.kj-ar.kj-table .kj-plus-legend > span:first-child, body.kj-ar.kj-table .kj-plus-orole,
body.kj-ar.kj-table .kj-plus-empty, body.kj-ar.kj-table .kj-plus-ren, body.kj-ar.kj-table .kj-plus-gen, body.kj-ar.kj-table .kj-plus-chip-en, body.kj-ar.kj-table .kj-plus-tomake-k { display: none !important; }
body.kj-ar.kj-table .kj-plus-sheet { direction: rtl; }
body.kj-ar.kj-table .kj-plus-note-ar, body.kj-ar.kj-table .kj-plus-sort { margin-left: 0; margin-right: auto; }
body.kj-ar.kj-table .kj-plus-cross { direction: ltr; }
body.kj-ar.kj-table .kj-plus-x { right: auto; left: 10px; }
body.kj-ar.kj-table .kj-plus-title-ar { font-size: 11px; color: var(--gold); }
/* 60 is drawn one language at a time: in "both" mode the tiles, gestures and chips keep English only (the section titles carry the Arabic) */
body.kj-table:not(.kj-ar) .kj-plus-rar, body.kj-table:not(.kj-ar) .kj-plus-gar:not(.kj-ar-twin), body.kj-table:not(.kj-ar) .kj-plus-chip-ar { display: none !important; }
/* 2026-09-27: at 384 a chip is 78px and "— / 0 / 11" ran 6px past its border
   ("13 / 0 / 13", the widest a hand can say, 9px): the chips, their gap, the
   face and the numbers' spacing each give a little (signal-cut-shot measures it) */
.kj-plus-seats { gap: 5px; }
.kj-plus-seat { gap: 3px; padding: 5px 2px; }
.kj-plus-av { width: 22px; height: 22px; }
.kj-plus-seat-nums { gap: 2px; }
.kj-plus-seat-nums b { font-size: 10px; letter-spacing: -.02em; }
.kj-plus-seat-name { max-width: 40px; }
.kj-plus-chip { padding: 6px 10px; }

/* ===== 65 (2026-09-05, Ahmad's call): one language per surface ==============
   "both" = English surfaces plus the bilingual joker strip and lockup only. No
   English/Arabic twins on labels, footers, keys or sheets in any mode. */
/* 81 amended (2026-09-19): .kj-more-ph is on this list because the twelve
   phrases are CONTENT, not UI copy - Design was explicit: "Arabic phrases are
   never translated, in any language mode. They are the same category as a
   player's name." They carry lang="ar" so a screen reader says them correctly,
   and that attribute alone dropped them into this rule: outside Arabic-only
   mode the sheet's DEFAULT tab was twelve blank 114x52 buttons. Ahmad opened
   the ＋ looking for the new sounds and found nothing, which is exactly what
   the screen was showing him. */
/* 105 (2026-09-24): so are .kn-pill-ar and .kn-char-word. The reaction pill
   carries the word the voice is SAYING, and the voice speaks Arabic in every
   mode; the board drops only the English gloss, and only in Arabic. */
body.kj-table:not(.kj-ar) [lang="ar"]:not(.kj-cer2-strip-ar):not(.kj-joker-ar):not(.kj-fcap-joker-ar):not(.kj-won-joker-ar):not(.kj-burst-joker-ar):not(.kj-more-ph):not(.kn-pill-ar):not(.kn-char-word):not(.kj-dock-ph):not(.kj-ar-twin),
body.kj-table:not(.kj-ar) .kj-hint-ar, body.kj-table:not(.kj-ar) .kj-hint-sep, body.kj-table:not(.kj-ar) .kj-sort-ar { display: none !important; }
/* 2026-09-19 · the felt takes the slam.
   Four frames and 300ms, and it moves the FELT only. Boards 56-58 were written
   because Ahmad said the table had to feel solid - cards, chairs, header and
   logo in the same place and the same size, never jumping. A reaction that
   shook the whole screen would undo that, so the surface moves and everything
   a thumb is aimed at stays exactly where it was. Scoped to the class app.js
   adds and removes, so nothing is animating when nobody has hit anything. */
.kj-jolt { animation: kjJolt 300ms cubic-bezier(.36,.07,.19,.97) both; }
@keyframes kjJolt {
  0%   { transform: translate(0, 0); }
  14%  { transform: translate(0, 3px); }
  34%  { transform: translate(-2px, -1px); }
  56%  { transform: translate(2px, 1px); }
  78%  { transform: translate(-1px, 0); }
  100% { transform: translate(0, 0); }
}
@media (prefers-reduced-motion: reduce) { :root:not([data-motion="full"]) .kj-jolt { animation: none; } }
:root[data-motion="reduced"] .kj-jolt { animation: none; }

/* the joker strip stays a deliberate pair in "both"; English-only mode drops its Arabic too */
body.kj-en.kj-table .kj-cer2-strip-ar, body.kj-en.kj-table .kj-joker-ar, body.kj-en.kj-table .kj-fcap-joker-ar { display: none !important; }

/* == 67 (2026-09-08) · the felt's four dead corners ==========================
   Board 59b hid the score, the last trick and the reactions behind one ＋, and
   real play said that was the wrong ten to hide. The rule that replaces it:
   anything on the acceptance test lives on the felt, everything else lives
   behind the ＋. These three widgets are ~14% of the felt's area.
   Spec: docs/design-asks/boards-67-72-spec.md (67, 68).                       */

/* 2026-09-19: pointer-events: auto, same story as the two rails further down.
   Both of these carry cursor: pointer and a click handler - the score opens
   the totals frame, the last trick replays it - and neither had ever been
   reachable by a finger, because .kj-tab is pointer-events: none and only
   .kj-av-box had opted back in. The trick progress strip below deliberately
   stays out: it is a readout, it has no handler, and a tap there should fall
   through to the felt. */
body.kj-table .kj-tab .kj-sw,
body.kj-table .kj-tab .kj-lt {
  position: absolute; box-sizing: border-box; z-index: 2;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  pointer-events: auto;
}

/* -- the score widget: the match total, and which side is winning ---------- */
body.kj-table .kj-tab .kj-sw {
  left: 8px; top: 8px; width: 118px; height: 46px;
  padding: 0 8px; display: flex; align-items: center; gap: 8px; cursor: pointer;
}
body.kj-table .kj-tab .kj-sw[data-near="1"] { border-color: var(--gold); }
.kj-sw-dia { position: relative; width: 26px; height: 30px; flex: none; }
.kj-sw-dia i { position: absolute; }
.kj-sw-v { left: 50%; top: 4px; bottom: 4px; width: 1px; background: var(--gold-dim); transform: translateX(-50%); }
.kj-sw-h { top: 50%; left: 4px; right: 4px; height: 1px; background: var(--chair-ring); transform: translateY(-50%); }
.kj-sw-dot { width: 7px; height: 7px; border-radius: var(--radius-pill); background: var(--ink-4); }
.kj-sw-n { left: 50%; top: 0; transform: translateX(-50%); background: var(--gold); }
.kj-sw-s { left: 50%; bottom: 0; transform: translateX(-50%); background: var(--gold); }
.kj-sw-w { left: 0; top: 50%; transform: translateY(-50%); }
.kj-sw-e { right: 0; top: 50%; transform: translateY(-50%); }
.kj-sw-col { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.kj-sw-row { display: flex; align-items: baseline; gap: 5px; }
.kj-sw-us, .kj-sw-them { font-family: var(--font-display); font-size: 17px; line-height: 1; letter-spacing: 0; }
.kj-sw-us { color: var(--gold); }
.kj-sw-them { color: var(--ink-2); }
.kj-sw[data-behind="1"] .kj-sw-us { color: var(--ink-2); }
.kj-sw[data-behind="1"] .kj-sw-them { color: var(--gold); }
.kj-sw-dash { font-family: var(--font-mono); font-size: 11px; color: var(--ink-4); }
.kj-sw-sp { width: 12px; flex: none; }
.kj-sw-k { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .14em; transition: color var(--t-tick) ease; }
.kj-sw-k--us { color: var(--gold); }
.kj-sw-k--them { color: var(--ink-3); }
/* the arriving trick ticks one half: the label flashes, nothing moves */
.kj-sw-k--us[data-flash="1"] { color: var(--ink); }
.kj-sw-k--them[data-flash="1"] { color: var(--salmon); }
body.kj-ar .kj-sw-k { font-family: var(--font-ar); font-size: 10px; letter-spacing: 0; }

/* -- the trick progress strip: where this hand stands, pip by pip ---------- */
body.kj-table .kj-tab .kj-tp {
  left: 8px; top: 59px; width: 118px; height: 34px;
  padding: 0 8px; display: flex; flex-direction: column; justify-content: center; gap: 3px;
}
.kj-tp-row { display: flex; align-items: baseline; column-gap: 5px; }
.kj-tp-k { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-tp-n { margin-inline-start: auto; display: flex; align-items: baseline; gap: 3px; }
.kj-tp-won, .kj-tp-bid { font-family: var(--font-display); font-size: 11px; line-height: 1; }
.kj-tp-won { color: var(--gold); }
.kj-tp-bid { color: var(--ink-3); }
.kj-tp[data-made="1"] .kj-tp-won { color: var(--mint); }
.kj-tp-sl { font-family: var(--font-mono); font-size: 9.5px; color: var(--ink-4); }
.kj-tp-pips { display: flex; gap: 2px; }
.kj-tp-pips i { width: 5px; height: 7px; border-radius: 4px; background: var(--line); transition: background var(--t-tick) ease; }
.kj-tp-pips i[data-w="us"] { background: var(--gold); }
.kj-tp-pips i[data-w="them"] { background: var(--salmon); }
body.kj-ar .kj-tp-k { font-family: var(--font-ar); font-size: 10px; letter-spacing: 0; }

/* -- the last trick (sized by the block under 80 below) ------------------- */
body.kj-table .kj-tab .kj-lt {
  right: 8px; top: 8px; width: 92px; height: 56px;
  padding: 6px 8px; display: flex; flex-direction: column; gap: 5px; cursor: pointer;
}
body.kj-table .kj-tab .kj-lt[data-empty="1"] { border-style: dashed; border-color: var(--chair-ring); cursor: default; }
.kj-lt-k { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
body.kj-ar .kj-lt-k { font-family: var(--font-ar); font-size: 10px; letter-spacing: 0; }

/* == 67 / 69 (2026-09-08) · the felt's bottom corners ========================
   Three quick reactions and the library on the left; the two partner signals
   on the right. Vertical rails, because four 42px buttons and a chair will not
   fit across 384px. A reaction is one tap. A signal is two - gesture, then
   suit - because a misfired reaction is funny and a misfired signal costs a
   hand, which is also why the signals are oxblood and the reactions surface:
   different class, different corner, different colour.                       */

/* 2026-09-19: these rails were DEAD TO TOUCH since the day they were added.
   .kj-tab is the overlay root and carries pointer-events: none, so every child
   that wants a tap has to opt back in - .kj-av-box does, a few paragraphs up.
   The two rails never did, so a real finger landed on .trick underneath and
   nothing happened. WOW, NICE, HURRY, ＋ MORE, KNOCK and SWEEP: all six.

   It survived a button sweep because that harness used el.click(), a synthetic
   DOM click, which ignores hit-testing and pointer-events entirely. It reported
   all four dock buttons working. A synthetic click is not a tap, and the check
   that matters is elementFromPoint at the control's own centre - which is what
   _shotgun/tap-check.js now asserts for every control on the felt.

   This is also why the new sounds could not be found: ＋ MORE is one of them,
   so the sheet could not be opened at all. */
body.kj-table .kj-tab .kj-dock,
body.kj-table .kj-tab .kj-srail {
  position: absolute; bottom: 8px; z-index: 3;
  display: flex; flex-direction: column; gap: 5px;
  pointer-events: auto;
}
body.kj-table .kj-tab .kj-dock { left: 8px; }
body.kj-table .kj-tab .kj-srail { right: 8px; }

.kj-dock-b, .kj-srail-b {
  width: 42px; height: 42px; box-sizing: border-box; padding: 0;
  border-radius: var(--radius); background: var(--surface); border: 1px solid var(--line);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  cursor: pointer;
}
.kj-dock-g, .kj-srail-g { font-size: 15px; line-height: 1; color: var(--ink-2); }
.kj-dock-k, .kj-srail-k {
  font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .14em; line-height: 1;
  color: var(--ink-3); max-width: 40px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kj-dock-b--more { background: var(--ink-bg2); border-style: dashed; border-color: var(--chair-ring); }
.kj-dock-b--more .kj-dock-g { color: var(--ink-3); }
.kj-dock-b--more .kj-dock-k { color: var(--ink-4); }

.kj-srail-b { background: var(--oxblood-wash); border-color: var(--oxblood-line); }
.kj-srail-g, .kj-srail-k { color: var(--salmon); }
.kj-srail-b[data-armed="1"] { border-color: var(--salmon); }
.kj-srail-b[data-armed="1"] .kj-srail-g { color: var(--ink); }

/* the suit picker opens above the rail; the second tap is the commit.
   09-19: 152, not 102 - the ＋ now occupies 102 on top of the rail. */
body.kj-table .kj-tab .kj-spick {
  position: absolute; right: 8px; bottom: 152px; width: 172px; z-index: 4;
  display: flex; gap: 5px; pointer-events: auto;   /* 09-19: see the rails above */
  animation: kjSpickIn var(--t-tick) ease-out both;
}
.kj-spick-c {
  flex: 1; height: 42px; box-sizing: border-box; padding: 0;
  border-radius: var(--radius); background: var(--surface); border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; line-height: 1; color: var(--ink-2); cursor: pointer;
}
.kj-spick-c[data-red="1"] { color: var(--suit-red-dim); }
.kj-spick-c[data-sent="1"] { background: var(--oxblood-wash); border-color: var(--salmon); }
@keyframes kjSpickIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

body.kj-ar .kj-dock-k, body.kj-ar .kj-srail-k { font-family: var(--font-ar); font-size: 10px; letter-spacing: 0; }
/* 2026-09-27, Ahmad: KNOCK / SWEEP carry their Arabic beside the English
   ("knock ... or sweep ..." in his words, the SIGNAL rows). "both" is the mode
   that shows the pair; "en" keeps English, and in "ar" the label itself is
   already Arabic. The glyph gives up 3px so three lines fit the 42px tile; the
   twin is only BUILT in "both" mode, so no rule has to hide it elsewhere. */
.kj-srail-ar { font-family: var(--font-ar); font-weight: 700; font-size: 9.5px; line-height: 1.1; color: var(--salmon); }
body.kj-table:not(.kj-ar):not(.kj-en) .kj-srail-g { font-size: 12px; }
.kj-srail-b[data-armed="1"] { background: rgba(224,145,126,.16); }
.kj-srail-b[data-armed="1"] .kj-srail-k, .kj-srail-b[data-armed="1"] .kj-srail-ar { color: var(--ink); }
.kj-srail-b[data-sent="1"] { border-color: var(--gold); }

/* The cut sheet's head: the dealer and the clock stacked at the right, level
   with the title and its Arabic (they were one line, flush against the title). */
.kj-sheet-metas { display: flex; flex-direction: column; align-items: flex-end; gap: 5px; flex: none; margin-left: 12px; }
.kj-sheet-metas .kj-sheet-meta { white-space: nowrap; }

/* 61: a card face on cream takes card-red / card-ink and a gold fill takes
   on-gold - the values did not move, the roles did. 67 gives the phone's
   trump chip the 17px glyph now that the score has left the bar. */
.kj-bar[data-simple="1"] .kj-bar-trump-g { font-size: 17px; }

/* == 70 (2026-09-08) · the shuffle countdown =================================
   The clock is the point of this screen, so it is a 56px ring in the sheet's
   head rather than a 9.5px pill on the felt, with a bar under the head and a
   foot line that says out loud what happens at zero.                        */
.kj-cer-count {
  width: 56px; height: 56px; flex: none; box-sizing: border-box;
  border-radius: var(--radius-pill); border: 2px solid var(--gold);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
}
.kj-cer-count[hidden] { display: none; }
.kj-cer-count-n { font-family: var(--font-display); font-size: 15px; line-height: 1; color: var(--gold); }
.kj-cer-count-k { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-cer-count[data-urgent="true"] { border-color: var(--salmon); animation: kjClockPulse var(--t-ring) ease-in-out infinite; }
.kj-cer-count[data-urgent="true"] .kj-cer-count-n { color: var(--salmon); }
.kj-cer-bar { height: 4px; border-radius: 4px; background: var(--line); overflow: hidden; }
.kj-cer-barfill { display: block; height: 4px; width: var(--kj-cerp, 100%); background: var(--gold); }
.kj-cer-foot { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); text-align: center; }
body.kj-ar .kj-cer-count-k, body.kj-ar .kj-cer-foot { font-family: var(--font-ar); font-size: 10px; letter-spacing: 0; }

/* item 3: on my own bid the clock is the display face, not the 10px mono -
   the same voice the acting chair uses, salmon and pulsing under three. */
.kj-auc-clock--mine { font-family: var(--font-display); font-size: 15px; margin-inline-start: 8px; }
.kj-auc-clock--mine.kj-clock--urgent { color: var(--salmon); animation: kjClockPulse var(--t-ring) ease-in-out infinite; }

/* == 77 (2026-09-09) · one budget across the width =========================
   The chair and the played card used to be placed by two percentages that
   never knew about each other, so at 384 they overlapped by 20x67 and at 320
   the two cards crossed each other by 28. Design's answer was not to nudge a
   number: "the budget should solve, not assert". The card is now an OUTPUT of
   the same left-to-right sum that places the chair, and the sum closes back to
   the east edge, so the middle gap is asserted rather than hoped for:

     col  = clamp(80, w x 0.25, 108)
     card = clamp(48, (w - 2(8 + col + 8) - 20) / 2, 62)
     x    = 8 + col + 8 + card/2          (mirrored east)
     gap  = w - 2(8 + col + 8 + card)     >= 20

     320 -> col 80, card 54, W 123, E 197, gap 20
     360 -> col 90, card 62, W 137, E 223, gap 24
     384 -> col 96, card 62, W 143, E 241, gap 36
     430 -> col 108, card 62, W 155, E 275, gap 58

   62 is a ceiling the card reaches once the width can afford it, not a
   constant. The card is the release valve and the chair is not: a card 8px
   narrower is still a readable card, a chair 16px narrower loses the player's
   name, and the name is identity.

   The verticals are in ui/table.js, as offsets rather than percentages - a
   chair block is 80px whether the felt is 509 or 453.                       */

body.kj-table {
  --kj-col: clamp(80px, 25vw, 108px);
  --kj-pc-w: clamp(48px, (100vw - 2 * (16px + clamp(80px, 25vw, 108px)) - 20px) / 2, 62px);
  --kj-pc-h: calc(var(--kj-pc-w) * 1.4);
}
body.kj-table:not(.kj-tablet):not(.kj-landscape):not(.kj-wide) .kj-seat { width: var(--kj-col); }
body.kj-table:not(.kj-tablet):not(.kj-landscape):not(.kj-wide) #view-room .ga-felt .trick {
  --pc-w: var(--kj-pc-w); --pc-h: var(--kj-pc-h);
}
body.kj-table:not(.kj-tablet):not(.kj-landscape):not(.kj-wide) #view-room .ga-felt .trick .played-card.west {
  left: calc(16px + var(--kj-col) + var(--kj-pc-w) / 2); top: calc(50% - 22px);
}
body.kj-table:not(.kj-tablet):not(.kj-landscape):not(.kj-wide) #view-room .ga-felt .trick .played-card.east {
  left: calc(100% - 16px - var(--kj-col) - var(--kj-pc-w) / 2); top: calc(50% - 22px);
}
/* N sits under its own chair block, S above its own: both are offsets, so the
   diamond keeps its shape whatever the felt height does. W/E are the mean of
   the two, which is what makes the pile even rather than bottom-heavy. */
body.kj-table:not(.kj-tablet):not(.kj-landscape):not(.kj-wide) #view-room .ga-felt .trick .played-card.north {
  left: 50%; top: calc(101px + var(--kj-pc-h) / 2);
}
body.kj-table:not(.kj-tablet):not(.kj-landscape):not(.kj-wide) #view-room .ga-felt .trick .played-card.south {
  left: 50%; top: calc(100% - 146px - var(--kj-pc-h) / 2);
}

/* == 73 (2026-09-09) · the auction is only a sheet =========================
   Bidding was the one phase that drew a second felt over the first, so the
   four corners 67 put back were hidden exactly when the score and the last
   trick matter most. The layer keeps its note and its sheet and gives back
   everything else: no background, no felt, no folded hand - the real one is
   still there, unmoved, and the sheet floats clear of it on --kj-auc-lift.
   No scrim: everything behind the sheet is information you need. */
.kj-auc[data-mode="bid"],
.kj-auc[data-mode="bidwatch"],
.kj-auc[data-mode="redeal"]
  { background: transparent; pointer-events: none; justify-content: flex-end; padding-bottom: var(--kj-auc-lift, 226px); }
.kj-auc[data-mode="bid"] .kj-auc-felt,
.kj-auc[data-mode="bidwatch"] .kj-auc-felt,
.kj-auc[data-mode="redeal"] .kj-auc-felt,
.kj-auc[data-mode="bid"] .kj-auc-hand,
.kj-auc[data-mode="bidwatch"] .kj-auc-hand,
.kj-auc[data-mode="redeal"] .kj-auc-hand
  { height: 0; margin: 0; border: 0; overflow: hidden; }
.kj-auc[data-mode="bid"] .kj-auc-sheet,
.kj-auc[data-mode="bidwatch"] .kj-auc-sheet,
.kj-auc[data-mode="redeal"] .kj-auc-sheet
  { flex: none; pointer-events: auto; margin: 0 8px; border: 1px solid var(--line-strong); border-radius: 22px;
    box-shadow: 0 16px 36px rgba(0,0,0,0.55); }
/* the busy lock outranks the float again (same weight, later wins) */
.kj-auc[data-busy="1"] .kj-auc-sheet { pointer-events: none; }
/* HIGHEST 8 | YOU HAVE 0:09 */
.kj-auc-div { width: 1px; align-self: stretch; background: var(--line); margin: 0 8px; display: block; }
.kj-auc-meta { flex-direction: row; align-items: baseline; gap: 5px; }
.kj-auc-clock--mine { font-size: 17px; }

/* == 63/67 (2026-09-09) · the carry lands in a digit =======================
   The won trick used to park on the winner's chair, on top of a name. It now
   shrinks into the half of the score widget that will be credited, and that
   half acknowledges it: 200ms, box static - the digit moves, the widget does
   not. The duration is the shared tick token, so this adds no new one. */
.kj-sw-tick { display: inline-block; animation: kjSwTick var(--t-tick) ease; }
@keyframes kjSwTick {
  0%   { transform: none; }
  45%  { transform: translateY(-3px) scale(1.14); color: var(--gold); }
  100% { transform: none; }
}

/* == 78 (2026-09-09) · MATCH OVER, a screen rather than a modal ==============
   Every child is absolutely positioned, so nothing here can push anything
   else. The board's y values assume a 44px device status bar that a web app
   does not draw, so each band is the board's y minus 44: HUD 0-53, hero from
   74, score bar 182, rematch 258, who-left 434, rounds 462, home 730. The
   rounds box and the home button are anchored to the bottom instead of typed,
   so a taller phone shows more rows rather than more empty felt.

   Radii are the scale's, not the board's literals: the board's r14 and r11 are
   16 and 12 here, which is the amended fidelity rule - copy the value through
   the token. Every duration is a token for the same reason. */
.kj-mo {
  /* Above the fixed tab bar (800) and the sweep layer (900): this screen owns
     the phone while it is up. Confirm dialogs at 9000+ still outrank it, which
     is right - a question about leaving belongs on top of the answer. */
  position: fixed; inset: 0; z-index: 950; overflow: hidden;
  background: var(--ink-bg); text-align: left;
  animation: kjMoIn var(--t-sheet) cubic-bezier(0.32, 0.72, 0, 1) both;
}
@keyframes kjMoIn { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }

/* The board keeps a ⋯ in the HUD, and the app's overflow menu is anchored
   inside the game view at z 60 - underneath this screen. While the screen is
   up the menu rides with it rather than being opened into the dark. */
body.kj-mo-open .overflow-menu { position: fixed; top: 53px; z-index: 955; }
/* HUD 0-53. No back arrow: the only exits are I'M READY and BACK TO HOME. */
.kj-mo-hud {
  position: absolute; left: 0; right: 0; top: 0; height: 53px; box-sizing: border-box;
  display: flex; align-items: center; gap: 12px; padding: 0 16px; z-index: 8;
  background: var(--bg2); border-bottom: 1px solid var(--line);
}
.kj-mo-logo { width: 26px; height: 26px; position: relative; overflow: hidden; flex: none; }
.kj-mo-logo img { position: absolute; left: 2px; top: -1px; width: 22px; height: 23px; object-fit: contain; display: block; }
.kj-mo-hud-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--ink-3); }
.kj-mo-more {
  margin-left: auto; appearance: none; background: none; border: 0; padding: 0; cursor: pointer;
  font-family: 'IBM Plex Mono', monospace; font-size: 15px; color: var(--ink-2);
}

/* Hero. The headline is 30, one step below the 40 rank: a match result is a
   headline, not a card rank, and 40 collides with the bar below it. */
.kj-mo-hero {
  position: absolute; left: 0; right: 0; top: 74px;
  display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center;
}
.kj-mo-kicker { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-mo-head { font-family: 'Archivo Black', sans-serif; font-size: 30px; line-height: 1; letter-spacing: -.02em; color: var(--ink); }
.kj-mo-head[data-won="1"] { color: var(--gold); }
.kj-mo-head-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 15px; line-height: 1.4; color: var(--ink-3); }
.kj-mo-head-ar[data-won="1"] { color: var(--gold); }

/* The bar states who won, not who you are - 68's rule. Its 1px gold border is
   the only gold border on the screen, and it is what makes the result readable
   before any text is. */
.kj-mo-bar {
  position: absolute; left: 22px; right: 22px; top: 182px; height: 58px; box-sizing: border-box;
  display: flex; align-items: center; padding: 0 16px;
  background: var(--surface); border: 1px solid var(--gold); border-radius: 16px;
}
.kj-mo-bar-side { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.kj-mo-bar-them { align-items: flex-end; }
.kj-mo-bar-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
.kj-mo-bar-us .kj-mo-bar-k { color: var(--gold); }
.kj-mo-bar-n { font-size: 11px; font-weight: 700; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kj-mo-bar-mid { margin: 0 auto; display: flex; align-items: baseline; gap: 8px; }
.kj-mo-bar-num { font-family: 'Archivo Black', sans-serif; font-size: 26px; line-height: 1; color: var(--ink-2); }
.kj-mo-bar-num[data-win="1"] { color: var(--gold); }
.kj-mo-bar-dash { font-family: 'IBM Plex Mono', monospace; font-size: 13px; color: var(--ink-4); }

/* Rematch. The clock sits in the head, not beside the button: it governs the
   whole block, and a countdown next to a primary reads as pressure on the tap. */
.kj-mo-rm {
  position: absolute; left: 22px; right: 22px; top: 258px; height: 168px; box-sizing: border-box;
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: 16px; padding: 16px;
}
.kj-mo-rm-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 12px; }
.kj-mo-rm-k { font-family: 'Archivo Black', sans-serif; font-size: 13px; line-height: 1; color: var(--ink); }
.kj-mo-rm-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 11px; color: var(--gold); }
.kj-mo-rm-clock { margin-left: auto; font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: .04em; color: var(--gold); }
.kj-mo-urgent { color: var(--salmon); }
.kj-mo-rm-clock.kj-mo-urgent { animation: kjClockPulse var(--t-ring) ease-in-out infinite; }
.kj-mo-chips { display: flex; gap: 8px; margin-bottom: 12px; }
.kj-mo-chip {
  flex: 1; min-width: 0; box-sizing: border-box; border-radius: 12px; padding: 8px 3px;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  background: var(--bg2); border: 1px solid var(--line);
  transition: background var(--t-select) ease-out, border-color var(--t-select) ease-out;
}
.kj-mo-chip[data-state="ready"] { background: rgba(239,195,117,0.10); border-color: var(--gold); }
.kj-mo-chip[data-state="bot"] { background: var(--oxblood-wash); border-color: var(--oxblood-line); }
.kj-mo-av { width: 28px; height: 28px; flex: none; }
.kj-mo-chip-n { font-size: 10px; font-weight: 600; color: var(--ink-3); max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kj-mo-chip[data-state="ready"] .kj-mo-chip-n { color: var(--gold); }
/* 8.5 is the one place below the 9.5 floor: a four-up repeated state word with
   the avatar and the name carrying identity beside it. */
.kj-mo-chip-s { font-family: 'IBM Plex Mono', monospace; font-size: 8.5px; letter-spacing: .14em; color: var(--ink-4); }
.kj-mo-chip[data-state="ready"] .kj-mo-chip-s { color: var(--gold); }
.kj-mo-chip[data-state="left"] .kj-mo-chip-s, .kj-mo-chip[data-state="bot"] .kj-mo-chip-s { color: var(--salmon); }
.kj-mo-ready {
  display: flex; align-items: baseline; justify-content: center; gap: 8px;
  width: 100%; box-sizing: border-box; appearance: none; cursor: pointer; border: 1px solid transparent;
  background: var(--gold); border-radius: 12px; padding: 13px 0; font-family: inherit;
}
.kj-mo-ready-en { font-size: 14px; font-weight: 800; letter-spacing: .04em; color: var(--on-gold); }
.kj-mo-ready-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 11px; color: var(--on-gold-2); }
.kj-mo-ready[data-on="1"] { background: rgba(239,195,117,0.10); border-color: var(--gold); cursor: default; }
.kj-mo-ready[data-on="1"] .kj-mo-ready-en { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; font-weight: 400; letter-spacing: .14em; color: var(--gold); }
.kj-mo-ready[data-on="1"] .kj-mo-ready-ar { color: var(--gold); }
/* Expiry: the block cross-fades to EXPIRED and nothing else on the screen moves. */
.kj-mo-rm-exp {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  background: var(--surface); border-radius: 16px; opacity: 0; pointer-events: none;
  transition: opacity var(--t-dim) ease;
  font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-4);
}
.kj-mo-rm-exp-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 11px; letter-spacing: 0; color: var(--ink-4); }
.kj-mo-rm[data-expired="1"] .kj-mo-rm-exp { opacity: 1; }

/* "2 OF 4 READY · SAMI LEFT, A BOT WILL SIT IN" - WILL, not CAN. */
.kj-mo-who {
  position: absolute; left: 22px; right: 22px; top: 434px; height: 14px;
  display: flex; align-items: center; gap: 8px; overflow: hidden;
  font-family: 'IBM Plex Mono', monospace; font-size: 9px; letter-spacing: .14em; color: var(--ink-4); white-space: nowrap;
}
.kj-mo-who-ar { font-family: Lemonada, sans-serif; font-weight: 600; letter-spacing: 0; }

/* Rounds. A fixed box that scrolls inside itself; the sixth row clipping at
   42% IS the scroll affordance, so there is no scrollbar. */
.kj-mo-rounds {
  position: absolute; left: 22px; right: 22px; top: 462px; bottom: 114px; box-sizing: border-box;
  background: var(--surface-sheet); border: 1px solid var(--line); border-radius: 16px; overflow: hidden;
  display: flex; flex-direction: column;
}
.kj-mo-rounds-head {
  flex: none; height: 38px; box-sizing: border-box; display: flex; align-items: center; gap: 8px; padding: 0 16px;
  border-bottom: 1px solid var(--line);
}
.kj-mo-rounds-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--ink-3); }
.kj-mo-rounds-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 10px; color: var(--ink-4); }
.kj-mo-rounds-scroll { margin-left: auto; font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .14em; color: var(--ink-4); }
.kj-mo-cols, .kj-mo-row { display: grid; grid-template-columns: 22px 20px 1fr 1fr; gap: 12px; align-items: center; }
.kj-mo-cols { flex: none; padding: 8px 16px 5px; }
.kj-mo-cols span { font-family: 'IBM Plex Mono', monospace; font-size: 8.5px; letter-spacing: .14em; color: var(--ink-4); }
.kj-mo-list { flex: 1; min-height: 0; overflow-y: auto; scrollbar-width: none; }
.kj-mo-list::-webkit-scrollbar { width: 0; }
.kj-mo-row { padding: 8px 16px; border-top: 1px solid var(--line); }
.kj-mo-r { font-family: 'Archivo Black', sans-serif; font-size: 11px; line-height: 1; letter-spacing: 0; color: var(--ink-4); }
.kj-mo-t { font-size: 12px; color: var(--ink-2); }
.kj-mo-t[data-red="1"] { color: var(--salmon); }
.kj-mo-cell { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.kj-mo-bw { font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: var(--ink-3); }
.kj-mo-cell[data-mine="1"] .kj-mo-bw { color: var(--ink-2); }
/* Negative is salmon on both sides - a set is bad news whoever it lands on.
   Positive is only gold on your side, because gold means you. */
.kj-mo-d { font-family: 'Archivo Black', sans-serif; font-size: 11px; line-height: 1; letter-spacing: 0; margin-left: auto; }
.kj-mo-d[data-tone="mine"] { color: var(--gold); }
.kj-mo-d[data-tone="theirs"] { color: var(--ink-2); }
.kj-mo-d[data-tone="bad"] { color: var(--salmon); }
.kj-mo-d[data-tone="off"] { color: var(--ink-4); }

/* Ghost, not oxblood: leaving is neutral, not destructive. */
.kj-mo-home {
  position: absolute; left: 22px; right: 22px; bottom: 56px; height: 46px; box-sizing: border-box;
  display: flex; align-items: baseline; justify-content: center; gap: 8px;
  appearance: none; cursor: pointer; background: none; border: 1px solid var(--chair-ring); border-radius: 12px; font-family: inherit;
}
.kj-mo-home-en { font-size: 14px; font-weight: 800; letter-spacing: .04em; color: var(--ghost-ink); }
.kj-mo-home-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 11px; color: var(--ink-3); }

/* Tablet and landscape: two columns, the rounds panel full height with every
   row visible, and BACK TO HOME as a text button in the HUD. */
@media (min-width: 900px) {
  .kj-mo-hero { left: 0; right: 50%; top: 96px; }
  .kj-mo-bar { left: 40px; right: calc(50% + 20px); top: 204px; }
  .kj-mo-rm { left: 40px; right: calc(50% + 20px); }
  .kj-mo-who { left: 40px; right: calc(50% + 20px); }
  .kj-mo-bar-num { font-size: 34px; }
  .kj-mo-rounds { left: calc(50% + 20px); right: 40px; top: 74px; bottom: 40px; }
  .kj-mo-home { left: auto; right: 16px; top: 0; bottom: auto; height: 53px; border: 0; }
}

/* == 79 (2026-09-09) · the Home recap card ==================================
   74's match-seen stamp changed what this is: it can only appear for a match
   you did NOT watch end, so it is not a summary, it is "here's what happened
   while you were gone". It sits in Home's flow under its own heading rather
   than meeting you as an overlay, on the same oxblood surface as the dropped
   chair and the no-connection bar - one meaning, something that was not
   normal play. It never auto-fades. */
.kj-gone { margin: 18px 0 6px; }
.kj-gone-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 12px; }
/* salmon, not ink-3: the only heading on Home that is not about a thing you
   can start, and the colour is what separates a receipt from a menu. */
.kj-gone-head-en { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--salmon); }
.kj-gone-head-ar { font-family: Lemonada, sans-serif; font-weight: 600; font-size: 10px; color: var(--ink-4); }
.kj-gone-card {
  box-sizing: border-box; overflow: hidden; cursor: pointer;
  background: var(--oxblood-wash); border: 1px solid var(--oxblood-line); border-radius: 16px; padding: 16px;
  animation: kjGoneOut var(--t-dim) ease-out reverse both;
}
.kj-gone-card[data-out="1"] { animation: kjGoneOut var(--t-dim) ease-out both; }
@keyframes kjGoneOut { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateX(-16px); } }
.kj-gone-top { display: flex; align-items: flex-start; gap: 12px; }
/* the explicit height is required: the mark is 1:1.55 and at width 38 would
   otherwise render 59 and push the rows past the card */
.kj-gone-mark { width: 38px; height: 40px; object-fit: contain; object-position: top; flex: none; display: block; }
.kj-gone-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.kj-gone-h { font-family: 'Archivo Black', sans-serif; font-size: 15px; line-height: 1.2; letter-spacing: -.02em; color: var(--ink); }
.kj-gone-h[data-won="1"] { color: var(--gold); }
.kj-gone-ar { font-family: Lemonada, sans-serif; font-weight: 700; font-size: 11px; line-height: 1.4; color: var(--salmon); }
.kj-gone-x {
  flex: none; width: 24px; height: 24px; margin: -12px -12px -12px 0; padding: 12px 12px 12px 0;
  box-sizing: content-box; appearance: none; cursor: pointer; background: none;
  border: 1px solid var(--chair-ring); border-radius: 8px;
  font-family: 'IBM Plex Mono', monospace; font-size: 11px; line-height: 22px; text-align: center; color: var(--ink-3);
}
.kj-gone-score { display: flex; align-items: baseline; gap: 12px; margin-top: 12px; }
.kj-gone-n { font-family: 'Archivo Black', sans-serif; font-size: 17px; line-height: 1; color: var(--ink-2); }
.kj-gone-n[data-win="1"] { color: var(--gold); }
.kj-gone-dash { font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: var(--ink-4); }
.kj-gone-rule { width: 1px; height: 16px; background: var(--oxblood-line); display: block; align-self: center; }
.kj-gone-meta { font-family: 'IBM Plex Mono', monospace; font-size: 9px; letter-spacing: .14em; color: var(--ink-3); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* the whole card is the tap target; the arrow is affordance, not a hit area */
.kj-gone-cta { display: flex; align-items: center; gap: 8px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--oxblood-line); }
.kj-gone-cta-k { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; letter-spacing: .18em; color: var(--gold); }
.kj-gone-cta-a { margin-left: auto; font-family: 'IBM Plex Mono', monospace; font-size: 12px; color: var(--gold); }
@media (min-width: 900px) {
  .kj-gone-mark { width: 44px; height: 46px; }
  .kj-gone-h { font-size: 17px; }
  .kj-gone-n { font-size: 21px; }
}

/* == 63 (2026-09-09) · the back of a gathered card ==========================
   The middle third of the collect: the pile turns face-down where it stands,
   then carries to the score half. The back is the board's - felt-hi fill, a
   chair-ring edge, r8, an inset gold hairline and an 11px gold lozenge on
   the turn. The face is hidden rather than removed so nothing reflows. */
.played-card.trick-card--back {
  background: var(--felt-1); border: 1px solid var(--chair-ring); border-radius: 8px;
  box-shadow: inset 0 0 0 1px rgba(239,195,117,0.3), 0 8px 20px rgba(0,0,0,0.5);
  backface-visibility: hidden;
}
.played-card.trick-card--back > * { visibility: hidden; }
.played-card.trick-card--back::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 11px; height: 11px;
  margin: -5px 0 0 -5px; background: var(--gold); transform: rotate(45deg); display: block;
}

/* == 80 (2026-09-09) · fill = permanence ====================================
   Ahmad, item 3: the widgets "are becoming visually merged together... it is
   difficult to quickly tell where one piece of information ends, where another
   begins, what each number represents."

   Design's rule, and the reason a gap alone would not have worked: "two
   identical boxes 8px apart still read as a set. So the four corners are
   separated by TREATMENT, not just space. A boxed thing is a fact you can come
   back to. An unboxed mark is right now." Score and last trick are cards; the
   contract is a band with no fill and no side or bottom border; the docks are
   controls. Minimum 12px between any two widget boxes.                       */

/* -- the score: two halves and a VERTICAL rule ---------------------------- */
body.kj-table .kj-tab .kj-sw {
  left: 8px; top: 8px; width: 124px; height: 48px;
  padding: 0 2px; display: flex; align-items: center; gap: 0; cursor: pointer;
}
/* kj-swx-, not kj-sw-. .kj-sw-h and .kj-sw-n belong to the OLD compass widget
   (.kj-sw-dia's horizontal rule, and its north dot), and a later rule only
   wins for the properties it declares - so this half kept height:1px and each
   number kept a gold background and a translateX(-50%). On the felt the score
   read as two gold slivers, and every box measurement passed the whole time
   because the box was right and the contents had been kicked out of it.
   Each rule below now carries everything it needs and leans on nothing. */
.kj-swx-side { flex: 1; min-width: 0; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; background: none; transform: none; }
.kj-swx-key { font-family: var(--font-mono); font-size: 9px; letter-spacing: .14em; line-height: 1; color: var(--ink-3); transition: color var(--t-tick) ease; }
.kj-swx-rule { width: 1px; height: 26px; flex: none; background: var(--line); display: block; }
.kj-swx-val { font-family: var(--font-display); font-size: 17px; line-height: 1; letter-spacing: 0; color: var(--ink-2); }
.kj-swx-side[data-lead="1"] .kj-swx-val { color: var(--gold); }
.kj-swx-side[data-lead="1"] .kj-swx-key { color: var(--gold); }
/* the arriving trick ticks one half: the label flashes, nothing moves */
.kj-swx-key[data-flash="1"] { color: var(--ink); }
body.kj-ar.kj-table .kj-swx-key { font-family: var(--font-ar); font-size: 10px; letter-spacing: 0; }

/* -- the last trick: a heading and the whole trick ------------------------- */
/* 2026-09-27, Ahmad: "this last play design should be in the main play
   screen". Board 60's cross (92x74, 26x36 minis, the winner ringed) is back on
   the felt, drawn with the + sheet's own .kj-plus-cross / .kj-plus-mini rules.
   108 = the cross + 7px padding + the 1px border, each side; the height adds
   the key (13px at most - the Arabic line) and the 5px gap. Fixed, so the empty
   outlines before the first trick measure exactly what a full trick does. */
body.kj-table .kj-tab .kj-lt {
  right: 8px; top: 8px; width: 108px; height: 108px;
  padding: 7px; display: flex; flex-direction: column; gap: 5px; cursor: pointer;
}
.kj-lt-k { font-size: 9px; letter-spacing: .18em; line-height: 13px; color: var(--ink-4); }
.kj-lt-k-ar { font-family: var(--font-ar); font-weight: 600; font-size: 10px; line-height: 1.3; color: var(--ink-4); }
.kj-lt-cross { align-self: center; }

/* == 80 · the contract band ==================================================
   Ahmad, item 4: "مين طلب؟ قديش طلب؟ شو الطرنيب؟" - who took the bid, for how
   much, and what is trump, answerable at a glance and without a popup.

   Not on the chair: "a chair is the one surface that is constantly changing
   state for unrelated reasons - turn ring, countdown, thinking, passed,
   dropped - so a permanent fact parked there is permanently at risk of
   collision." Not a fifth corner: four corners are already the complaint. A
   band on the shared axis, whose TOP BORDER is the thirteen-segment progress
   strip - the whole progress widget at zero extra height, drawn as a marking
   on the table rather than a box on it.                                      */
body.kj-table .kj-tab .kj-ct {
  position: absolute; box-sizing: border-box; z-index: 2;
  /* Design's 462 is an artboard coordinate, measured from the top of the
     screen. .kj-tab is inset:0 inside the felt, which starts 53px down, under
     the HUD - so 462 on the artboard is 409 here. Shipped as a literal 462
     once and the band landed at 515, sixteen pixels into the south chair,
     which is the exact collision the board was drawn to avoid. */
  left: 60px; right: 60px; top: 409px; height: 40px;
  display: flex; flex-direction: column;
  /* a readout, never a target: nothing here is pressable, and the hand's top
     edge is close enough that a stray hit area would eat card taps */
  pointer-events: none;
}
.kj-ct-strip { display: flex; gap: 2px; margin-bottom: 5px; }
.kj-ct-strip i { flex: 1; height: 3px; border-radius: 4px; background: var(--line); transition: background var(--t-tick) ease; }
.kj-ct-strip i[data-w="us"] { background: var(--gold); }
.kj-ct-strip i[data-w="them"] { background: var(--salmon); }
.kj-ct-row { flex: 1; min-height: 0; display: flex; align-items: center; gap: 8px; }
.kj-ct-av { width: 22px; height: 22px; flex: none; }
/* ...and 22 it stays: the chair tiers size every .kj-av (45 compact, 56 from
   420px, both on selectors this one loses to), which in the app bar made the
   bidder's face a 45px disc hanging out of a 53px bar on a 360 phone. A max
   wins whatever the specificity. */
.kj-ct-av { max-width: 22px; max-height: 22px; }
.kj-ct-k { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); white-space: nowrap; }
.kj-ct-k--quiet { color: var(--ink-4); }
.kj-ct-ar { font-family: var(--font-ar); font-weight: 600; font-size: 11px; color: var(--ink-4); }
.kj-ct-name { font-family: var(--font-ui); font-weight: 700; font-size: 11px; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.kj-ct-name[data-mine="1"] { color: var(--gold); }
/* 2026-10-01, Ahmad: "it is very confusing to figure out who ordered and what
   ordered". Whose contract: the bidder's name in their side's colour - the
   progress strip's gold (us) and salmon (them). */
.kj-ct-name[data-team="us"] { color: var(--gold); }
.kj-ct-name[data-team="them"] { color: var(--salmon); }
/* ...and where: on the phone in play the band rides in the app bar ("this
   status/bid bar should be moved to the top"), filling its empty middle. */
.kj-bar .kj-ct { flex: 1 1 auto; min-width: 0; height: 38px; display: flex; flex-direction: column; justify-content: center; pointer-events: none; }
.kj-bar .kj-ct-strip { margin-bottom: 5px; }
/* What: the trump on a card face - suit ink on white, as on the trump picker's
   tiles - instead of a dark glyph on the dark bar. */
.kj-bar .kj-ct-suit, .kj-seat-ct .kj-ct-suit { background: var(--card); color: var(--card-ink); border-radius: var(--radius-card-mini); padding: 2px 3px; font-size: 15px; flex: none; }
.kj-bar .kj-ct-suit[data-red="true"], .kj-seat-ct .kj-ct-suit[data-red="true"] { color: var(--card-red); }
/* 2026-10-02, Ahmad, of the bar's "8 <suit>": "this element should be moved [to]
   the player who won the bid / next to avatar ... same styling as currently on
   the top". The same two pieces - the gold number, the trump on a card face -
   beside the bidder's avatar, wherever the felt beside it is free. North and
   south: level with it, on its right. West and east: centred just above it -
   their played card is level with the avatar on the inner side, 34px off it
   at S25 and 19px at 360 (whose card even starts above the avatar), and the
   badge is 31-43px wide ("7" to "13"). On a compact phone the north chair's
   right is 41px to the last-trick box, so there the two pieces stack. It
   hangs off the avatar box, so the chair's own column (96px, 58) does not
   grow and nothing in it moves. A picture of the contract, not prose: it
   holds its order in Arabic too. */
.kj-seat-ct {
  position: absolute; top: 50%; left: calc(100% + 5px); transform: translateY(-50%);
  display: flex; align-items: center; gap: 3px; direction: ltr; white-space: nowrap; pointer-events: none;
}
.kj-seat[data-kn-seat="west"] .kj-seat-ct, .kj-seat[data-kn-seat="east"] .kj-seat-ct { top: auto; bottom: calc(100% + 3px); left: 50%; transform: translateX(-50%); }
body.kj-compact .kj-seat[data-kn-seat="north"] .kj-seat-ct { flex-direction: column; gap: 2px; }
.kj-ct-rule { width: 1px; height: 16px; flex: none; background: var(--line); display: block; }
.kj-ct-bid { font-family: var(--font-display); font-size: 17px; line-height: 1; letter-spacing: 0; color: var(--gold); }
.kj-ct-suit { font-size: 19px; line-height: 1; color: var(--ink-2); }
.kj-ct-suit[data-red="true"] { color: var(--suit-red-dim); }
.kj-ct-clock { margin-inline-start: auto; font-family: var(--font-mono); font-size: 11px; color: var(--gold); }
.kj-ct-won { margin-inline-start: auto; display: flex; align-items: baseline; gap: 5px; }
.kj-ct-wk { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); white-space: nowrap; }
/* "WON 3 OF 10" is the answer to "whose 7?" - progress stated against the
   contract rather than floating beside it. Made turns mint; unmakeable salmon. */
.kj-ct-wn { font-family: var(--font-display); font-size: 13px; line-height: 1; letter-spacing: 0; color: var(--ink); }
.kj-ct-wn[data-tone="made"] { color: var(--mint); }
.kj-ct-wn[data-tone="broken"] { color: var(--salmon); }
/* the denominator: the same numeral system as kj-ct-wn, one step quieter. It
   used to wear kj-ct-wk and so followed the key into --font-ar. */
.kj-ct-wb { font-family: var(--font-display); font-size: 13px; line-height: 1; letter-spacing: 0; color: var(--ink-3); }
body.kj-ar .kj-ct-k, body.kj-ar .kj-ct-wk { font-family: var(--font-ar); font-size: 10px; letter-spacing: 0; }

/* ===== Board 81 · MORE (2026-09-09) · Ahmad's item 5 ========================
   "Why the current one is slow: ONE SCROLL, FOUR KINDS. Mixing phrases, emoji
   and sounds in a single list means every scan is a search. Fixed grid + tabs
   turns it into a lookup."

   356 tall, so the sheet's top edge is at 57% of the screen and everything in
   it is thumb-reachable one-handed. The felt above stays visible, which is why
   the scrim is not opaque.

   Two numbers are off Design's board on purpose, and only because the
   standard's scales do not carry them: the tab radius is 12 rather than 11 and
   the tab gap is 5 rather than 6. Both are the nearest step on the published
   scale, and a new off-scale value would refuse the deploy - the ratchet holds
   off-scale radii and gaps at their baselines.                              */
/* Design scrims y97-832 and leaves the HUD clear. On a viewport-fixed layer
   97 is 97: no felt offset to subtract here, unlike the contract band's 462. */
/* The sheet covers y476-832: the hand and the tab bar are UNDER it, not beside
   it. .kj-sheetzone is absolute inside .felt-wrap, and the felt ends at 654 on
   an 832 phone, so "bottom: 0" put the sheet 178px above the bottom of the
   screen. This layer is fixed to the viewport instead - over the fixed tab bar
   at 800, under the match-over screen at 950. */
.kj-morez { position: fixed; inset: 0; z-index: 940; }
.kj-morez .kj-more-scrim { top: 97px; background: rgba(9,13,8,0.72); }
/* 368, not Design's 356. Their own parts do not fit 356: 14 + 4 + 13 + 40 + 12
   + (4x52 + 3x8) + 13 + 11 + 26 = 365, and the live probe measured the grid
   overflowing by exactly 12. Every other number on this board carries an
   argument - 52px cells "because this is fired mid-hand, one-handed, without
   looking carefully", twelve items that never scroll - and the height carries
   one too ("the top edge is at 57% of the screen"), but it is the only one
   that survives being moved: at 368 the top edge is at 56%. Raised to Design
   as an arithmetic question rather than quietly shrinking a cell. */
.kj-more {
  position: absolute; left: 0; right: 0; bottom: 0; height: 368px;
  box-sizing: border-box; z-index: 2;
  display: flex; flex-direction: column;
  background: var(--surface-sheet); border-top: 1px solid var(--line-strong);
  border-radius: 22px 22px 0 0; padding: 14px 16px 26px;
  animation: kjMoreIn var(--t-sheet) cubic-bezier(0.32, 0.72, 0, 1) both;
}
.kj-more-grab { display: block; width: 40px; height: 4px; border-radius: 999px; background: var(--line-strong); margin: 0 auto 13px; }

.kj-more-tabs { display: flex; gap: 5px; margin-bottom: 12px; }
.kj-more-tab {
  flex: 1; min-width: 0; height: 40px; box-sizing: border-box;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px; padding: 0; cursor: pointer; font-family: inherit;
  background: var(--surface); border: 1px solid var(--line); border-radius: 12px;
  transition: background var(--t-select) ease-out, border-color var(--t-select) ease-out;
}
.kj-more-tab[data-on="true"] { background: var(--gold); border-color: var(--gold); }
.kj-more-tg { font-family: var(--font-mono); font-size: 13px; line-height: 1; color: var(--ink-2); }
.kj-more-tg--ar { font-family: var(--font-ar); font-weight: 700; font-size: 11px; line-height: 1.2; }
.kj-more-tk { font-family: var(--font-mono); font-size: 8.5px; letter-spacing: .14em; color: var(--ink-4); }
.kj-more-tab[data-on="true"] .kj-more-tg { color: var(--on-gold); }
.kj-more-tab[data-on="true"] .kj-more-tk { color: var(--on-gold-2); }
body.kj-ar.kj-table .kj-more-tk { font-family: var(--font-ar); font-size: 9px; letter-spacing: 0; }

/* "12 per tab. Never scrolls - 4 x 12 = 48 items, every one reachable in <= 2
   taps." The rows are a fixed 52 so the sheet cannot grow past its own height. */
.kj-more-grid {
  flex: 1; min-height: 0;
  display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: 52px; gap: 8px;
  animation: kjMoreFade var(--t-lane) ease both;
}
.kj-more-cell {
  box-sizing: border-box; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 2px;
  padding: 0 5px; cursor: pointer; font-family: inherit; text-align: center;
  background: var(--surface); border: 1px solid var(--line); border-radius: 12px;
  transition: background var(--t-select) ease-out, border-color var(--t-select) ease-out;
}
/* "Tap -> cell fills gold @ 0.10 + 1px gold for 120ms. THE TAP IS THE SEND." */
.kj-more-cell[data-hit="1"] { background: var(--goldwash); border-color: var(--gold); }
.kj-more-hole { display: block; border: 1px dashed var(--line); border-radius: 12px; opacity: .5; }

.kj-more-ph { font-family: var(--font-ar); font-weight: 700; font-size: 14px; line-height: 1.3; color: var(--ink-2); }
.kj-more-em { font-size: 26px; line-height: 1; }
.kj-more-sg { font-family: var(--font-mono); font-size: 19px; line-height: 1; color: var(--ink-2); }
.kj-more-sn { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .14em; color: var(--ink-4); }

/* The footer is the only row here whose height the fonts decide, and Lemonada
   sits taller than IBM Plex Mono: the Arabic sheet overflowed its own grid by
   6px until both lines were pinned. Pinned in BOTH languages, so the sheet is
   one height everywhere rather than two that happen to agree. */
.kj-more-foot { display: flex; align-items: baseline; gap: 8px; margin-top: 13px; line-height: 1.2; }
.kj-more-f1, .kj-more-f2 { line-height: 1.2; }
.kj-more-f1 { font-family: var(--font-mono); font-size: 9px; letter-spacing: .14em; color: var(--ink-4); }
.kj-more-f2 { margin-inline-start: auto; font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .14em; color: var(--ink-3); }
body.kj-ar.kj-table .kj-more-f1, body.kj-ar.kj-table .kj-more-f2 { font-family: var(--font-ar); letter-spacing: 0; }
body.kj-ar.kj-table .kj-more-foot, body.kj-ar.kj-table .kj-more-tabs { direction: rtl; }

/* A promoted dock slot can hold a phrase where a glyph used to be. It gets the
   Arabic face and a hard ellipsis, because the dock cell's width was drawn for
   one character and "الله يعينك" is eleven. */
.kj-dock-b[data-kind="phrase"] .kj-dock-g {
  font-family: var(--font-ar); font-weight: 700; font-size: 10px; line-height: 1.2;
  max-width: 38px; overflow: hidden; white-space: normal; text-align: center;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
}
/* 2026-09-27 ("spacing is off"): the phrase was ellipsised on one line - and in
   an LTR box an RTL phrase loses its FIRST word to the ellipsis, so "shu
   halhaz" read "halhaz ...". It was the mono label doing the showing, too: the
   Arabic face carries lang="ar" and "both" mode hid it (trap 89). Now the
   phrase itself shows in every mode (content, like the sheet's phrases,
   .kj-dock-ph on the rules above), on up to two lines; the label is not built. */

@keyframes kjMoreIn { from { transform: translateY(28px); } to { transform: translateY(0); } }
@keyframes kjMoreFade { from { opacity: 0; } to { opacity: 1; } }
