/* backgammon/style.css
 *
 * Loaded after the site stylesheet (/style.css) and subordinate to it, on
 * the same three rules as solitaire/style.css:
 *
 *   1. never redefines a selector the site defines (.btn, the modal and
 *      settings components, .site-header/.site-footer, .achievement-toast);
 *   2. no bare element selectors;
 *   3. every selector is a .bg- class or scoped under #backgammon / #bg-.
 *
 * Materials follow DESIGN.md §1.3 and §5: a walnut frame around an oak
 * field, leather-grained points, a felt bar, ivory dice. Every texture is
 * an SVG data URI declared once on #backgammon (the CSP allows data: for
 * images). Sizing: main.js measures the board and sets --chk (checker),
 * --pitch (point width or row height), --frame, --die and the field's
 * pixel size; nothing below is sized from a media query alone.
 */

#backgammon {
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --walnut: #4a2c1a; --walnut-light: #6b4327; --walnut-dark: #2e1a0f;
  --oak: #d9b481; --oak-light: #e6c99c; --oak-dark: #b98a55;
  --point-green: #0b4a35; --point-cream: #efe2c6; --bar-felt: var(--felt-dark);
  --engrave: rgba(251, 247, 236, 0.8);
  --tex-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='120'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.012 0.32' numOctaves='4' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.20  0 0 0 0 0.11  0 0 0 0 0.04  0 0 0 0.16 0'/%3E%3C/filter%3E%3Crect width='400' height='120' filter='url(%23g)'/%3E%3C/svg%3E");
  --tex-grain-v: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='400'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.32 0.012' numOctaves='4' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.20  0 0 0 0 0.11  0 0 0 0 0.04  0 0 0 0.16 0'/%3E%3C/filter%3E%3Crect width='120' height='400' filter='url(%23g)'/%3E%3C/svg%3E");
  --tex-leather: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='l'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.3' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.10 0'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23l)'/%3E%3C/svg%3E");
  --tex-felt: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.07 0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");

  max-width: 760px;
  margin: 0 auto;
  padding: 8px 8px calc(24px + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  align-items: center;
}
/* Phones: the board takes the full shell width. */
@media (max-width: 479px) {
  #backgammon { padding-left: 0; padding-right: 0; }
}
/* Desktop: room for the dice panel beside a 760px board. */
@media (min-width: 980px) {
  #backgammon { max-width: 900px; }
}

/* Design review: the site stylesheet gives every link the page's deep blue
 * (#0a5c8a), which on the header's dark green is ~1.2:1 — the cross-game
 * link was effectively invisible. The site has no name for a link inside
 * the tagline, so this carries a class of its own rather than redefining a
 * selector that is not ours. Word Search and 8 Ball Pool do the same. */
.bg-tagline-link {
  color: inherit;
  font-weight: 600;
  text-decoration-color: rgba(253, 251, 244, 0.6);
  text-underline-offset: 3px;
  white-space: nowrap;
}
.bg-tagline-link:hover { text-decoration-color: currentColor; }

/* ============================ goal + status ============================ */

.bg-goal {
  margin: 2px 0 8px;
  /* The shell drops its side padding under 480px so the board can use the
     whole width; the sentence still needs a margin of its own. */
  padding: 0 14px;
  font-size: 18px;
  font-weight: 500;
  line-height: 1.45;
  text-align: center;
  color: var(--ink);
}
.bg-goal strong { font-weight: 700; }

/* Two lines reserved so the board never moves when the text changes. */
.bg-status {
  margin: 0 0 10px;
  min-height: calc(2.7em + 16px);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: 19px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--ink);
  padding: 8px 12px;
  border-radius: var(--radius-md);
  background: var(--paper-dim);
  width: 100%;
  max-width: 560px;
}

/* A phone on its side (the `short` layout): only ~390px of height exists.
   Design review: this block used to drop the goal and the status line to
   17px and reserve one line instead of two, which made this the only page
   on the site whose type shrank with the window — and Solitaire, the
   benchmark, keeps 18/19 and two reserved lines at 844x390. The board is
   below the fold at this size in Solitaire too, so buying board height by
   shrinking the one sentence that says what to do was the wrong trade.
   Only the margins tighten now. */
@media (min-width: 600px) and (max-height: 599px) {
  #backgammon { padding-top: 2px; }
  .bg-goal { margin: 0 0 6px; }
  .bg-status { padding: 8px 12px; margin-bottom: 6px; }
}

/* ================================ board ================================ */

.bg-board {
  --chk: 40px;
  --pitch: 44px;
  --frame: 12px;
  --die: 44px;
  --panel: 0px;
  position: relative;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
  isolation: isolate;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.bg-board.is-side { flex-direction: row; align-items: stretch; }

/* The walnut rim. */
.bg-frame {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  border-radius: var(--radius-lg);
  background: var(--tex-grain), linear-gradient(180deg, var(--walnut-light), var(--walnut) 40%, var(--walnut-dark));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14), inset 0 0 0 2px rgba(0, 0, 0, 0.35), 0 6px 18px rgba(0, 0, 0, 0.35);
  padding: var(--frame);
}
.bg-board.is-vertical .bg-frame { background-image: var(--tex-grain-v), linear-gradient(180deg, var(--walnut-light), var(--walnut) 40%, var(--walnut-dark)); }

/* The oak field. Everything inside is positioned in pixels by main.js. */
.bg-field {
  position: relative;
  width: 100%;
  height: 300px;
  border-radius: 8px;
  background:
    var(--tex-grain),
    repeating-linear-gradient(90deg, rgba(120, 80, 40, 0.06) 0 3px, rgba(255, 255, 255, 0) 3px 11px),
    linear-gradient(180deg, var(--oak-light), var(--oak) 50%, var(--oak-dark));
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.28), inset 0 3px 14px rgba(0, 0, 0, 0.28);
  overflow: hidden;
  touch-action: pan-y;
}
.bg-board.is-vertical .bg-field {
  background-image:
    var(--tex-grain-v),
    repeating-linear-gradient(180deg, rgba(120, 80, 40, 0.06) 0 3px, rgba(255, 255, 255, 0) 3px 11px),
    linear-gradient(90deg, var(--oak-light), var(--oak) 50%, var(--oak-dark));
}

/* ---- points: a button (the whole triangle and its stack is one target)
 * around a clip-path shape with a leather grain, plus an SVG outline so
 * the cream triangles keep an edge against the oak. ---- */
.bg-point {
  position: absolute;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  touch-action: pan-y;
  font: inherit;
  color: inherit;
  -webkit-appearance: none;
  appearance: none;
  border-radius: 4px;
}
.bg-point.is-movable { touch-action: none; }
.bg-point:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 3px; }
.bg-point-shape {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: var(--tex-leather), linear-gradient(var(--pc-angle, 180deg), var(--pc-light), var(--pc) 70%);
  transition: filter 0.2s ease;
}
.bg-point.is-green { --pc: var(--point-green); --pc-light: #146b4c; }
.bg-point.is-cream { --pc: var(--point-cream); --pc-light: #f7eed8; }
.bg-point[data-dir="down"] .bg-point-shape  { clip-path: polygon(0 0, 100% 0, 50% 100%); --pc-angle: 180deg; }
.bg-point[data-dir="up"] .bg-point-shape    { clip-path: polygon(50% 0, 100% 100%, 0 100%); --pc-angle: 0deg; }
.bg-point[data-dir="right"] .bg-point-shape { clip-path: polygon(0 0, 100% 50%, 0 100%); --pc-angle: 90deg; }
.bg-point[data-dir="left"] .bg-point-shape  { clip-path: polygon(100% 0, 100% 100%, 0 50%); --pc-angle: 270deg; }
.bg-point-edge {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}
.bg-point-edge polygon {
  fill: none;
  stroke: rgba(58, 35, 20, 0.5);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
}
/* legal target: gold glow along the triangle, dashed ring when empty */
.bg-point.is-target .bg-point-shape { filter: drop-shadow(0 0 6px var(--accent)) drop-shadow(0 0 2px var(--accent)); }
.bg-point.is-target .bg-point-edge polygon { stroke: var(--accent); stroke-width: 3; }
.bg-point.is-target.is-empty .bg-point-edge polygon { stroke-dasharray: 6 4; }

/* ---- bar: a felt strip (portrait) or column (landscape) ---- */
.bg-bar {
  position: absolute;
  background: var(--tex-felt), linear-gradient(180deg, var(--felt), var(--felt-dark));
  box-shadow: inset 0 2px 10px rgba(0, 0, 0, 0.45), inset 0 0 0 1px rgba(0, 0, 0, 0.4);
}
.bg-board.is-vertical .bg-bar { background-image: var(--tex-felt), linear-gradient(90deg, var(--felt), var(--felt-dark)); }
.bg-bar-zone {
  position: absolute;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  border-radius: var(--radius-md);
  font: inherit;
  color: inherit;
  cursor: default;
  -webkit-appearance: none;
  appearance: none;
}
.bg-bar-zone.is-movable { cursor: pointer; touch-action: none; }
.bg-bar-zone:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 3px; }
.bg-bar-zone.is-target { box-shadow: 0 0 0 3px var(--accent), 0 0 14px 2px rgba(242, 183, 5, 0.55); }

/* ---- bear-off trays ---- */
.bg-tray {
  position: absolute;
  margin: 0;
  padding: 0;
  border: 0;
  font: inherit;
  color: inherit;
  cursor: default;
  -webkit-appearance: none;
  appearance: none;
  border-radius: 6px;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.22), rgba(0, 0, 0, 0.12));
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.4), inset 0 -1px 0 rgba(255, 255, 255, 0.12);
}
/* Design review: at 375px the tray well was a shallow wash over the oak,
 * so the ivory "HOME" engraved across it sat at roughly 1.6:1. Cut the
 * well deeper (it is a recess in the board, per the Free-cell tray
 * language in DESIGN.md §3.2) so the label reads on either layout. */
.bg-board.is-vertical .bg-tray {
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.46), rgba(0, 0, 0, 0.34));
  box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.55), inset 0 -1px 0 rgba(255, 255, 255, 0.12);
}
.bg-tray:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 3px; }
.bg-tray.is-target {
  box-shadow: 0 0 0 3px var(--accent), 0 0 14px 2px rgba(242, 183, 5, 0.55), inset 0 2px 6px rgba(0, 0, 0, 0.4);
  outline: 2px dashed rgba(242, 183, 5, 0.9);
  outline-offset: -2px;
}
.bg-tray-count {
  position: absolute;
  font: 700 15px/1 var(--font-sans);
  font-variant-numeric: tabular-nums;
  color: #fdfbf4;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);
  pointer-events: none;
}

/* ---- engraved captions and point numbers (Georgia: on-board text only) ---- */
.bg-label {
  position: absolute;
  font: 700 15px/1 Georgia, "Times New Roman", serif;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--engrave);
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.35);
  pointer-events: none;
  white-space: nowrap;
  display: flex;
  align-items: center;
  justify-content: center;
}
.bg-label.is-upright { writing-mode: vertical-rl; }
.bg-num {
  position: absolute;
  font: 700 12px/1 Georgia, "Times New Roman", serif;
  font-variant-numeric: tabular-nums;
  color: var(--engrave);
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.35);
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Design review: DESIGN.md §5.3 — "point numbers are not shown to the
 * player". In the horizontal layout they sit on the walnut rim, where they
 * read as engraving and cost nothing. In the vertical layout there is no
 * rim to put them on, so they were being drawn down the middle of the oak
 * field, in grey, across the point tips and under the checkers. Hidden
 * there; the status line names every move in words anyway. */
.bg-board.is-vertical .bg-num { display: none; }

/* ---- checkers ---- */
.bg-checkers {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.bg-checker {
  position: absolute;
  left: 0;
  top: 0;
  width: var(--chk);
  height: var(--chk);
  border-radius: 50%;
  transition: transform 0.26s cubic-bezier(0.2, 0.7, 0.2, 1), width 0.2s ease, height 0.2s ease, border-radius 0.2s ease;
  will-change: transform;
}
.bg-checker.no-transition { transition: none; }
.bg-checker.is-ivory {
  background: radial-gradient(circle at 35% 30%, #fffdf6, #f1e8d2 45%, #cfc2a4 100%);
  box-shadow: inset 0 0 0 2px #3a2314, inset 0 2px 3px rgba(255, 255, 255, 0.8), inset 0 -3px 5px rgba(0, 0, 0, 0.28), 0 2px 3px rgba(0, 0, 0, 0.45);
}
.bg-checker.is-dark {
  background: radial-gradient(circle at 35% 30%, var(--dk-a), var(--dk-b) 50%, var(--dk-c) 100%);
  box-shadow: inset 0 0 0 2px var(--dk-rim), inset 0 2px 3px rgba(255, 255, 255, 0.35), inset 0 -3px 5px rgba(0, 0, 0, 0.4), 0 2px 3px rgba(0, 0, 0, 0.45);
}
.bg-checker::after {
  content: "";
  position: absolute;
  inset: 28%;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18), inset 0 1px 1px rgba(255, 255, 255, 0.35);
}
.bg-checker.is-selected {
  z-index: 200 !important;
  transition: transform 0.16s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.bg-checker.is-selected::before {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  box-shadow: 0 0 0 3px var(--accent), 0 10px 18px rgba(0, 0, 0, 0.45);
}
.bg-checker.is-dragging {
  transition: none;
  z-index: 300 !important;
}
.bg-checker.is-hint { animation: bg-hint 1.1s ease-in-out 3; }
@keyframes bg-hint {
  0%, 100% { box-shadow: 0 2px 3px rgba(0, 0, 0, 0.45); }
  50% { box-shadow: 0 0 0 4px var(--accent), 0 0 18px 4px rgba(242, 183, 5, 0.6); }
}
.bg-checker.is-shake { animation: bg-shake 0.36s ease; }
@keyframes bg-shake {
  25% { margin-left: -5px; }
  50% { margin-left: 5px; }
  75% { margin-left: -3px; }
}
/* A borne-off checker lies flat in the tray: a slab. */
.bg-checker.is-off {
  border-radius: 3px;
  transition: transform 0.26s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.bg-checker.is-off::after { display: none; }
.bg-count {
  position: absolute;
  min-width: 26px;
  height: 26px;
  padding: 0 7px;
  border-radius: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  font: 800 16px/1 var(--font-sans);
  color: #fdfbf4;
  background: var(--ink);
  box-shadow: 0 0 0 2px #fdfbf4;
  pointer-events: none;
  transition: transform 0.26s cubic-bezier(0.2, 0.7, 0.2, 1);
}
/* Hint: numbered gold badges on the destinations, in order. */
.bg-badge {
  position: absolute;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font: 800 16px/1 var(--font-sans);
  color: var(--accent-ink);
  background: var(--accent);
  box-shadow: 0 0 0 2px #fdfbf4, 0 2px 6px rgba(0, 0, 0, 0.45);
  pointer-events: none;
  animation: bg-hint 1.1s ease-in-out 3;
}

/* ---- checker colourways: set by data-colours on #backgammon; the same
 * block styles the swatches in Settings ---- */
#backgammon[data-colours="burgundy"], .bg-swatch[data-colours="burgundy"] {
  --dk-a: #b04a5a; --dk-b: #7d2534; --dk-c: #4d121d; --dk-rim: #f4e6c8;
}
#backgammon[data-colours="navy"], .bg-swatch[data-colours="navy"] {
  --dk-a: #4a6fa8; --dk-b: #1f3f78; --dk-c: #0f2247; --dk-rim: #e6ecf7;
}
#backgammon[data-colours="black"], .bg-swatch[data-colours="black"] {
  --dk-a: #5a5a60; --dk-b: #26262a; --dk-c: #0d0d0f; --dk-rim: #e9e2cf;
}

/* ---- dice panel: on the bar in portrait, under or beside the board otherwise ---- */
.bg-dice-panel {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px 16px;
  flex-wrap: wrap;
  min-width: 0;
}
.bg-board.is-side .bg-dice-panel {
  flex: 0 0 var(--panel);
  width: var(--panel);
  flex-direction: column;
  justify-content: center;
  gap: 12px;
}
/* Landscape phone: the board is taller than the screen, so the dice and Roll
   sit at its top edge — the one control that must never scroll away. */
.bg-board.is-side.is-short .bg-dice-panel { justify-content: flex-start; padding-top: 6px; }
.bg-board.is-vertical .bg-dice-panel {
  position: absolute;
  flex-wrap: nowrap;
  justify-content: space-between;
  gap: 8px;
}
.bg-dice {
  display: flex;
  gap: 8px;
  align-items: center;
  justify-content: center;
  min-height: var(--die);
  flex-wrap: wrap;
  max-width: calc(var(--die) * 2 + 8px);
}
.bg-dice.is-double { max-width: calc(var(--die) * 2 + 8px); }
.bg-board.is-vertical .bg-dice { flex-wrap: nowrap; max-width: none; }
.bg-die {
  position: relative;
  width: var(--die);
  height: var(--die);
  border-radius: calc(var(--die) * 0.2);
  background: radial-gradient(circle at 35% 30%, #fffdf6, #f1e8d2 60%, #d8ccb0 100%);
  box-shadow: inset 0 2px 2px rgba(255, 255, 255, 0.8), inset 0 -3px 4px rgba(0, 0, 0, 0.2), 0 3px 5px rgba(0, 0, 0, 0.4);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  padding: 14%;
  box-sizing: border-box;
  transition: opacity 0.2s ease, filter 0.2s ease;
}
.bg-dice.is-double .bg-die { --die: 34px; }
.bg-die.is-used { opacity: 0.42; filter: grayscale(1); }
/* Before a roll the place is kept, but a faint solid ivory tile read as a
 * broken die rather than an empty one. Design review: use the site's
 * "present but not ready" language instead — the dashed outline the
 * disabled .btn wears (DESIGN.md §1.6) — so the pair reads as two wells
 * waiting for a roll. */
.bg-die.is-blank {
  opacity: 1;
  box-shadow: none;
  /* Horizontal layouts put the dice in a panel on the cream page, beside
   * the disabled Hint and Undo — so the empty die wears exactly what they
   * wear: paper-dim, dashed, full contrast. */
  background: var(--paper-dim);
  border: 2px dashed rgba(11, 74, 53, 0.4);
}
/* Portrait puts them on the felt bar, where the dashes have to be ivory. */
.bg-board.is-vertical .bg-die.is-blank {
  background: rgba(253, 251, 244, 0.10);
  border-color: rgba(253, 251, 244, 0.55);
}
.bg-die.is-rolling { animation: bg-roll 0.32s ease; }
@keyframes bg-roll {
  0% { transform: rotate(-12deg) translateY(-4px); }
  50% { transform: rotate(10deg) translateY(2px); }
  100% { transform: none; }
}
.bg-pip {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, #3a3a3a, #1c1c1c 70%);
  opacity: 0;
  align-self: center;
  justify-self: center;
  max-width: 78%;
  max-height: 78%;
}
.bg-die[data-face="1"] .bg-pip:nth-child(5),
.bg-die[data-face="2"] .bg-pip:nth-child(3), .bg-die[data-face="2"] .bg-pip:nth-child(7),
.bg-die[data-face="3"] .bg-pip:nth-child(3), .bg-die[data-face="3"] .bg-pip:nth-child(5), .bg-die[data-face="3"] .bg-pip:nth-child(7),
.bg-die[data-face="4"] .bg-pip:nth-child(1), .bg-die[data-face="4"] .bg-pip:nth-child(3), .bg-die[data-face="4"] .bg-pip:nth-child(7), .bg-die[data-face="4"] .bg-pip:nth-child(9),
.bg-die[data-face="5"] .bg-pip:nth-child(1), .bg-die[data-face="5"] .bg-pip:nth-child(3), .bg-die[data-face="5"] .bg-pip:nth-child(5), .bg-die[data-face="5"] .bg-pip:nth-child(7), .bg-die[data-face="5"] .bg-pip:nth-child(9),
.bg-die[data-face="6"] .bg-pip:nth-child(1), .bg-die[data-face="6"] .bg-pip:nth-child(3), .bg-die[data-face="6"] .bg-pip:nth-child(4), .bg-die[data-face="6"] .bg-pip:nth-child(6), .bg-die[data-face="6"] .bg-pip:nth-child(7), .bg-die[data-face="6"] .bg-pip:nth-child(9) {
  opacity: 1;
}
.bg-dice-caption {
  margin: 0;
  font: 600 16px/1.2 var(--font-sans);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  text-align: center;
  min-height: 1.2em;
}
.bg-board.is-vertical .bg-dice-caption { color: #fdfbf4; text-shadow: 0 1px 0 rgba(0, 0, 0, 0.4); }
.bg-board.is-vertical .bg-dice-caption:empty { display: none; }
.bg-dice-caption.is-hidden { display: none; }
/* Roll dice: 56px, the one control that must never scroll away. */
.bg-roll {
  min-height: 56px;
  min-width: 96px;
  font-size: 17px;
  font-weight: 700;
  padding: 8px 14px;
  line-height: 1.15;
  text-align: center;
  white-space: normal;
}
.bg-board.is-side .bg-roll { width: 100%; }
.bg-board.is-short .bg-roll { min-width: 0; padding: 6px 6px; font-size: 16px; }
.bg-board.is-short .bg-dice-caption { font-size: 14px; }
.bg-board.is-short .bg-die { --die: 48px; }
.bg-roll:disabled { opacity: 1; background: var(--paper-dim); border-style: dashed; cursor: default; }
.bg-roll:disabled:hover { background: var(--paper-dim); }
.bg-board.is-vertical .bg-roll:disabled { background: rgba(253, 251, 244, 0.72); }

/* ---- plate line under the board: whose turn, in words ---- */
.bg-plate {
  margin: 10px 0 0;
  min-height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font: 600 16px/1.3 var(--font-sans);
  font-variant-numeric: tabular-nums;
  color: var(--felt-dark);
  text-align: center;
}
.bg-plate-swatch {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #fffdf6, #f1e8d2 45%, #cfc2a4 100%);
  box-shadow: inset 0 0 0 1.5px #3a2314, 0 1px 2px rgba(0, 0, 0, 0.35);
}
.bg-plate-swatch.is-dark {
  background: radial-gradient(circle at 35% 30%, var(--dk-a), var(--dk-b) 50%, var(--dk-c) 100%);
  box-shadow: inset 0 0 0 1.5px var(--dk-rim), 0 1px 2px rgba(0, 0, 0, 0.35);
}
.bg-plate-swatch.is-none { visibility: hidden; }

/* ============================== controls ============================== */

.bg-controls {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 16px;
  width: 100%;
  max-width: 640px;
  margin-top: 16px;
}
.bg-controls .btn {
  flex: 1 1 calc(50% - 16px);
  min-height: 56px;
  min-width: 0;
  font-size: 18px;
  font-weight: 600;
}
.bg-controls .btn[hidden] { display: none; }
@media (min-width: 560px) {
  .bg-controls .btn { flex: 1 1 0; }
}
/* Present, plainly not ready — never 50% opacity for this audience. */
.bg-controls .btn:disabled {
  opacity: 1;
  background: var(--paper-dim);
  border-style: dashed;
  cursor: default;
}
.bg-controls .btn:disabled:hover { background: var(--paper-dim); }

/* ============================== settings ============================== */

.bg-row-note {
  margin: 8px 0 0;
  font-size: 15px;
  line-height: 1.45;
  color: var(--felt-dark);
}
.bg-row-note-tight { margin-top: -10px; margin-bottom: 18px; }

#bg-lang-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin: 4px 0 0;
}
@media (min-width: 480px) {
  #bg-lang-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
#bg-lang-grid .lang-btn {
  min-height: 56px;
  padding: 8px 10px;
  white-space: nowrap;
  font-size: 16px;
}
#bg-lang-grid .lang-btn[aria-pressed="true"] {
  box-shadow: 0 0 0 3px var(--accent);
  font-weight: 700;
}

.bg-colours {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: 8px 0 0;
}
.bg-colours label {
  position: relative; /* the hidden radio stays inside its own swatch */
  flex: 1 1 0;
  min-width: 96px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  color: var(--felt-dark);
  text-align: center;
}
/* The radio itself covers the whole label, invisible: the entire swatch +
 * caption is one tap target and the input is what receives the tap. */
.bg-colours input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
  z-index: 1;
}
.bg-swatch {
  position: relative;
  width: 72px;
  height: 48px;
  border-radius: 8px;
  background: var(--tex-leather), linear-gradient(180deg, var(--oak-light), var(--oak-dark));
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.28), var(--shadow-sm);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.bg-swatch-disc {
  position: absolute;
  top: 8px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
}
.bg-swatch-disc.is-ivory {
  left: 8px;
  background: radial-gradient(circle at 35% 30%, #fffdf6, #f1e8d2 45%, #cfc2a4 100%);
  box-shadow: inset 0 0 0 2px #3a2314, 0 1px 2px rgba(0, 0, 0, 0.4);
}
.bg-swatch-disc.is-dark {
  right: 8px;
  background: radial-gradient(circle at 35% 30%, var(--dk-a), var(--dk-b) 50%, var(--dk-c) 100%);
  box-shadow: inset 0 0 0 2px var(--dk-rim), 0 1px 2px rgba(0, 0, 0, 0.4);
}
.bg-colours input:checked + .bg-swatch {
  box-shadow: 0 0 0 3px var(--accent), var(--shadow-md);
  transform: translateY(-2px);
}
.bg-colours input:focus-visible + .bg-swatch {
  outline: 3px solid var(--focus-ring);
  outline-offset: 3px;
}

/* ============================ right-to-left ============================ */
/* Arabic flips the page via <html dir="rtl">; the board is dir="ltr" in the
 * markup and placed in px, so it never mirrors. The site's skip link is
 * parked at left: -9999px, and in a right-to-left page the space to the
 * LEFT is scrollable — the page grew 10,000px wide and the viewport went
 * blank. Park it on the right instead, the side that is clipped in rtl
 * (solitaire does the same). */
[dir="rtl"] #bg-skip-link {
  left: auto;
  right: -9999px;
  border-radius: 0 0 0 8px;
}
[dir="rtl"] #bg-skip-link:focus {
  right: 0;
}

/* =============================== toasts =============================== */

#bg-toasts {
  position: fixed;
  top: max(88px, calc(env(safe-area-inset-top) + 74px));
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  z-index: 300;
  pointer-events: none;
}
#bg-toasts .achievement-toast {
  position: static;
  transform: none;
}

/* ============================ reduced motion ========================== */

@media (prefers-reduced-motion: reduce) {
  #backgammon *,
  #bg-toasts * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
