/* =========================================================================
   GG chrome · desktop layout (1600×900)
   Production chrome ported from mockup 60_ingame_default_desktop.html.
   Token-only · no literal 6-digit hex (rule: tokens.css is the only source).
   ========================================================================= */

/* ===== Composition row (WEEK45) =====
   The .vp-grid lays out the [opponent panel][board][your panel/menu]
   composition at mockup-60 design proportions INSIDE the fixed 1600×900
   .stage. Flex (not grid) so panels sit DIRECTLY beside the board with no
   1fr filler gap — both shrink together when the stage transform scales.
   Design math: stage width 1600 − 28 (padding) = 1572 inner;
   200 + 14 + 1144 + 14 + 200 = 1572 → row fills exactly. The board column
   is 1144 wide × 845 high (674:498 aspect: 1144 × 498/674 ≈ 845).

   WEEK45 follow-up: .vp-grid is constrained to the board's height (845)
   so the panels' top/bottom edges line up with the board's top/bottom
   edges (was 880 → panels overhung; the 4-icon menu landed below the
   board and was clipped at small windows). .stage is a flex centerer
   (viewport.css) so the 845-high row sits vertically centered inside
   the 900-high stage. The right-col chat panel-host is flex:1 → soaks
   up the slack so the menu-bar sits AT the board's bottom edge.
*/
.vp-grid {
  position: relative;
  width: 100%;
  height: 845px;
  padding: 0 14px;
  display: flex;
  flex-direction: row;
  gap: 14px;
  align-items: stretch;
  justify-content: center;
}
.vp-grid > .player-col { flex: 0 0 200px; }
.vp-grid > .board-area { flex: 0 0 var(--board-w); }

/* WEEK47 correction — hide the iPad subtree by default on desktop. The
   .bottom-strip + .fab-menu live in the shared DOM so view.js/controls.js
   can paint them without branching, but without this default-hide they
   render alongside the desktop chrome (extra strip + scroll-arrow Jay
   saw). [data-layout="ipad"] in ipad.css flips them back to flex. */
.bottom-strip,
.fab-menu {
  display: none;
}

/* ===== Player columns ===== */
.player-col {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-height: 0;
  /* WEEK61 §4b — kill the flexbox `min-width:auto` default. The right
     column's chat .panel-host has a wide min-content (~226px), which
     overrode the 200px flex-basis and made the right column wider than
     the left (visible after T4 made the avatar full-width). min-width:0
     lets both columns respect `flex: 0 0 200px`. */
  min-width: 0;
}

/* ===== Passport card ===== */
.pc-card {
  background: var(--rd-surface);
  border: 1px solid var(--rd-line);
  border-radius: 6px;
  padding: 14px 10px 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  transition: border-color 140ms ease, background 140ms ease;
}
.pc-card:hover {
  border-color: var(--rd-line-strong);
  background: var(--rd-surface-strong);
}
.pc-card .pc-avatar {
  /* WEEK61 §4 T4 — full-width avatar with locked 1:1 aspect (mockup 60).
     Replaces the fixed 110×110 box; the .pc-card flex column drives width.
     §4c — Jay show_widget compare: 100% leaves no room for a long name;
     85% keeps the avatar prominent and frees vertical space.
     §4d — Jay visual eval: 85% → 75% (a touch smaller for time being). */
  width: 75%;
  margin: 0 auto;
  aspect-ratio: 1 / 1;
  background: linear-gradient(180deg, var(--rd-avatar-grad-from), var(--rd-avatar-grad-to));
  border: 1px solid var(--rd-gold);
  border-radius: 8px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--rd-font-serif);
  font-size: 14px;
  color: var(--rd-cream-dim);
  text-align: center;
  line-height: 1.2;
  overflow: hidden;
  position: relative;
}
.pc-card .pc-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  display: block;
}
.pc-card .pc-name-line {
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: var(--rd-font-serif);
  font-style: italic;
  font-weight: 600;
  color: var(--rd-cream);
  font-size: 18px;
  line-height: 1;
  letter-spacing: 0.3px;
  margin-top: 6px;
}
.pc-card .pc-flag {
  width: 22px;
  height: 15px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 2px;
  flex-shrink: 0;
  display: inline-flex;
  overflow: hidden;
  line-height: 0;
}
.pc-card .pc-flag svg { width: 100%; height: 100%; display: block; }
.pc-card .pc-rating {
  /* WEEK76 §4 T2 — small symmetric margin so the rating row reads as
     evenly-spaced, not crammed against the avatar/name above it. */
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 8px;
  margin: 2px 0;
}
.pc-card .pc-rating-label {
  font-family: var(--rd-font-body);
  font-size: 11px;
  font-weight: 500;
  color: var(--rd-cream-dim);
  text-transform: uppercase;
  letter-spacing: 1px;
}
.pc-card .pc-rating-value {
  font-family: var(--rd-font-serif);
  font-style: italic;
  font-size: 18px;
  font-weight: 600;
  color: var(--rd-cream);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

/* ===== Score / Clock / Pip boxes ===== */
.pc-stat, .pc-timer, .pc-pip {
  background: var(--rd-surface);
  border: 1px solid var(--rd-line);
  border-radius: 6px;
  padding: 7px 8px;
  text-align: center;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.pc-stat .ps-value {
  /* WEEK61 §4 T3 — score value 22px → 32px (mockup 60). */
  font-family: var(--rd-font-body);
  font-weight: 700;
  color: var(--rd-cream);
  font-size: 32px;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.3px;
}
.pc-stat .ps-label {
  /* WEEK76 §4 T1 — caption reverted to cream-dim per the stylesheet
     (stat/field labels: value = bright cream, caption = dim cream). */
  font-family: var(--rd-font-body);
  font-size: 10px;
  font-weight: 600;
  color: var(--rd-cream-dim);
  text-transform: uppercase;
  letter-spacing: 2px;
  margin-top: 3px;
}

/* ===== Clock states ===== */
.pc-timer .pt-line {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 6px;
  font-family: var(--rd-font-body);
  font-variant-numeric: tabular-nums;
}
.pc-timer.mirror .pt-line { flex-direction: row-reverse; }
.pc-timer .pt-bank { color: var(--rd-cream); font-size: 17px; font-weight: 700; }
.pc-timer .pt-sep  { color: var(--rd-gold-dim); font-weight: 400; }
.pc-timer .pt-move { color: var(--rd-cream); font-size: 17px; font-weight: 700; }
/* WEEK52 §4b T11 — all four clock numbers stay white. Red is the
   .pc-timer.active.warning BLOCK effect (border + glow); the number
   colour never changes. .pt-move.idle moved to cream so the passive
   side's move number matches the bank colour (was gold-dim). */
.pc-timer .pt-move.idle { color: var(--rd-cream); }
.pc-timer .pt-label {
  font-family: var(--rd-font-body);
  font-size: 10px;
  font-weight: 600;
  color: var(--rd-cream-dim);
  text-transform: uppercase;
  letter-spacing: 2px;
  margin-top: 3px;
}
.pc-timer.active {
  border-color: var(--rd-gold);
  box-shadow: 0 0 14px var(--rd-gold-glow), inset 0 0 0 1px var(--rd-line);
}
/* WEEK52 — last-5s warning accent on the active timer wrapper. The
   .pt-move red text was already wired at 186; this adds the border +
   glow accent that flips gold → red when state==='active-warning'. */
.pc-timer.active.warning {
  border-color: var(--rd-warn-red);
  box-shadow: 0 0 14px var(--rd-warn-red), inset 0 0 0 1px var(--rd-line);
  /* WEEK64 §4 T3 — subtle 1s opacity pulse during the bank≤20s window.
     Keyframe + reduced-motion override live in viewport.css (shared). */
  animation: ggClockPulse 1s ease-in-out infinite;
}
/* WEEK64 §4 T3 — live colour cycle on the active side.
   • .pt-move.move-active  → brown (gold token) while move-time runs.
   • .pt-move.move-spent   → cream once move expired and bank is live.
   • .pt-bank.bank-warning → light-red in the bank's last 20s.
   Inactive side: none of the three classes set → cream via the existing
   .pt-move.idle / .pt-bank base rules. Money mode is unreached
   (clock.mode==='none' stops the ticker). */
.pc-timer .pt-move.move-active  { color: var(--rd-gold); }
.pc-timer .pt-move.move-spent   { color: var(--rd-cream); }
.pc-timer .pt-bank.bank-warning { color: var(--rd-warn-red-bright); }

/* ===== Pip ===== */
.pc-pip .pp-value {
  font-family: var(--rd-font-body);
  color: var(--rd-cream);
  font-size: 17px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.pc-pip .pip-cap {
  font-family: var(--rd-font-body);
  font-size: 10px;
  font-weight: 600;
  color: var(--rd-cream-dim);
  text-transform: uppercase;
  letter-spacing: 2px;
  margin-top: 2px;
}

/* ===== Autoroll · WEEK61 §4 T2/T5 =====
   Standalone .pc-autoroll block + .pa-label / .pa-switch CSS removed; the
   autoroll control is now the .mb-autoroll button in the right-col menu-bar
   (reusing the iPad/phone gold-toggle pattern). The dead .pa-switch /
   .pc-autoroll selectors in view.js + controls.js are harmless no-ops on
   desktop (paintAutoroll's querySelectorAll('.pa-switch, .mb-autoroll')
   still toggles .on on the .mb-autoroll button; controls.js wires both
   class names on click). */

/* ===== Board area + #bw/#bg/#cv block (WEEK43 · retuned WEEK45) =====
   Ported from index.html: #bg is the felt/frame/points JPEG; #cv is the
   absolutely-positioned canvas that renders pieces only. setupHiDPI +
   ResizeObserver on #cv (app.js) keep it crisp at any size — including
   under the WEEK45 stage transform (getBoundingClientRect returns the
   post-transform box per CSSOM spec).

   WEEK45: --board-w is now a fixed design-pixel value (1144px) because
   the .stage parent is a fixed 1600×900 canvas; the responsive 100svh
   calc that lived here pre-WEEK45 is superseded by the stage-scale
   transform (the whole composition shrinks together as one unit).
*/
.board-area {
  --board-w: 1144px;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
}
#bw {
  width: var(--board-w);
  position: relative;
  margin: 0 auto;
  /* WEEK44: container-query anchor so .board-btn cqw clamps scale 1:1
     with the board (mirrors index.html ~1800). */
  container-type: inline-size;
}
#bg {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 5px;
}
#cv {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  cursor: pointer;
  touch-action: none;
}

/* ===== Cube overlay (re-anchored to #bw · WEEK43) ===== */
#bw .cube-overlay {
  position: absolute;
  width: 6.9%;
  aspect-ratio: 1 / 1;
  right: 1.8%;
  cursor: pointer;
  z-index: 5;
  image-rendering: -webkit-optimize-contrast;
}
#bw .cube-overlay.pos-middle { top: 50%; transform: translateY(-50%); }
#bw .cube-overlay.pos-top    { top: 6%; }
#bw .cube-overlay.pos-bottom { bottom: 6%; }

/* ===== Crawford cube · WEEK49 =====
   Ported token-only from research/In Game Design - mockups (PLAIN)/In Game
   Mockups P1/65_ingame_crawford.html (line 107–111). Same width 6.9% / right
   1.8% / top 50% as the centered regular cube — only the artwork swaps.
   .crawford-cube is set by chrome/view.js paintCube when the engine reports
   state.cube.crawfordArt (WEEK48). The .crawford-art SVG lives inside every
   cube-overlay element and is hidden by default; the .cube-value text node
   gets hidden during the Crawford game so only the SVG shows.

   TODO: final Crawford cube asset to be provided by Jay/Anton — drop-in
   replacement for the placeholder SVG inside #bw .cube-overlay > .crawford-art
   in index.html. No CSS change needed at swap time. */
#bw .cube-overlay .crawford-art { display: none; }
#bw .cube-overlay.crawford-cube .crawford-art {
  display: block;
  width: 100%;
  height: 100%;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.5));
}
#bw .cube-overlay.crawford-cube .cube-value { display: none; }

/* ===== On-board action buttons · WEEK44 =====
   Ported from index.html (~1672–1699 + ~1800 + ~3070–3114), the effective
   styles after the PHASE D++ override that unifies primary + secondary into
   one dark + gold-bordered look. Hidden by default; app.js's
   syncOnBoardButtons() toggles .show each render() frame. Anchored to #bw,
   sized via container-query clamps so they scale 1:1 with the board.
*/
.board-btn {
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  font-family: var(--rd-font-action);
  font-weight: 600;
  text-transform: uppercase;
  cursor: pointer;
  border: 1px solid var(--rd-gold-dim);
  transition: all 140ms ease;
  z-index: 10;
  display: none;
  white-space: nowrap;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  /* Scale all dimensions with the board width via container queries */
  font-size: clamp(11px, 2.0cqw, 16px);
  padding: clamp(8px, 2.0cqw, 16px) clamp(14px, 3.2cqw, 28px);
  min-width: clamp(96px, 22cqw, 180px);
  min-height: clamp(38px, 8cqw, 58px);
  letter-spacing: clamp(0.8px, 0.2cqw, 1.5px);
  border-radius: clamp(5px, 1cqw, 10px);
  background: linear-gradient(180deg, var(--rd-board-btn-1) 0%, var(--rd-board-btn-2) 50%, var(--rd-board-btn-3) 100%);
  color: var(--rd-cream);
  text-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    inset 0 -1px 0 rgba(0, 0, 0, 0.5),
    0 4px 10px rgba(0, 0, 0, 0.4);
}
.board-btn.show { display: block; }

/* Position helpers — match LEFT_CX / RIGHT_CX (logical 195 / 477 of 674) */
.board-btn-left  { left: 28.9%; }
.board-btn-right { left: 70.8%; }

/* .board-btn-primary / .board-btn-secondary: intentionally NO separate
   styling — PHASE D++ unified primary + secondary into one dark + gold-
   bordered look (see .board-btn above). The classes stay in the markup
   so any future weight-specific variation (e.g. brighter accent on the
   primary CTA) can hang here without re-touching the HTML. */

.board-btn:hover {
  background: linear-gradient(180deg, var(--rd-board-btn-hi-1) 0%, var(--rd-board-btn-hi-2) 50%, var(--rd-board-btn-hi-3) 100%);
  border-color: var(--rd-gold);
  color: var(--rd-cream);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    inset 0 -1px 0 rgba(0, 0, 0, 0.5),
    0 6px 14px rgba(0, 0, 0, 0.45),
    0 0 18px var(--rd-line);
}
.board-btn:active {
  transform: translate(-50%, -50%) scale(0.97);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.4);
}

/* ===== Game-over restart (WEEK45) =====
   Minimal centered card over the board when state.phase === 'match_over'.
   Driven by chrome/view.js (show/hide); click wired in chrome/controls.js.
   The full post-match screen (result / rematch / claim) is platform scope. */
#m-gameover {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 60;
  pointer-events: none;
}
#m-gameover[hidden] { display: none; }
.gc-gameover-card {
  background: var(--rd-dark-veil-strong);
  border: 1px solid var(--rd-glass-border);
  border-radius: 8px;
  padding: 24px 32px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  pointer-events: auto;
  text-align: center;
}
.gc-gameover-title {
  font-family: var(--rd-font-serif);
  font-style: italic;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: 0.3px;
  color: var(--rd-cream);
}
.gc-gameover-btn {
  font-family: var(--rd-font-action);
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 1px;
  padding: 10px 22px;
  border-radius: 6px;
  border: 1px solid var(--rd-gold);
  background: var(--rd-gold-fill);
  color: var(--rd-cream);
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease;
}
.gc-gameover-btn:hover { background: var(--rd-gold-hover); }
.gc-gameover-btn:active { transform: scale(0.97); }
/* Sprint 54 T6 · Download Match (.mat) — secondary variant on the
   match-over card. Hollow gold border so it sits visually below the
   primary "New Match" CTA. Tokens only — no literal hex. */
.gc-gameover-btn-secondary {
  background: transparent;
  color: var(--rd-cream-dim);
  border-color: var(--rd-line-strong);
}
.gc-gameover-btn-secondary:hover {
  background: var(--rd-surface);
  color: var(--rd-cream);
  border-color: var(--rd-gold);
}
.gc-gameover-btn-secondary[hidden] { display: none; }

/* ===== Between-games score flash (WEEK54) =====
   Brief centered card shown for ~1.5s after each in-match game_over.
   Carries winner + points + new score + optional Crawford-next line.
   Tap to skip. Money mode emits match_over (not game_over) so this
   flash never fires there. Driven by chrome/controls.js. */
#m-between {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 60;
  pointer-events: none;
}
#m-between[hidden] { display: none; }
.gc-between-card {
  background: var(--rd-dark-veil-strong);
  border: 1px solid var(--rd-glass-border);
  border-radius: 8px;
  padding: 22px 30px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  pointer-events: auto;
  text-align: center;
  cursor: pointer;
}
.gc-between-headline {
  font-family: var(--rd-font-serif);
  font-style: italic;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: 0.3px;
  color: var(--rd-cream);
}
.gc-between-score {
  font-family: var(--rd-font-body);
  font-size: 16px;
  color: var(--rd-cream-dim);
}
.gc-between-crawford {
  font-family: var(--rd-font-action);
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--rd-gold);
  margin-top: 4px;
}
.gc-between-crawford[hidden] { display: none; }

/* ===== Right column · dynamic panel host ===== */
.right-col .panel-host {
  flex: 1;
  min-height: 0;
  background: var(--rd-surface);
  border: 1px solid var(--rd-line);
  border-radius: 6px;
  display: flex;
  flex-direction: column;
}

/* ===== Left column · filler block (WEEK45) =====
   Empty, decorative — same tokens/border/radius as .panel-host so the
   opponent column visually balances the right column's chat + autoroll +
   menu mass. Soaks up the same remaining flex space the right-col's
   .panel-host occupies, so both columns end at the same bottom. */
.opp-col .pc-filler {
  flex: 1;
  min-height: 0;
  background: var(--rd-surface);
  border: 1px solid var(--rd-line);
  border-radius: 6px;
}

/* ===== Chat panel (default) ===== */
.chat-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.chat-scroll {
  flex: 1;
  padding: 10px 12px;
  overflow-y: auto;
  font-family: var(--rd-font-body);
  font-size: 13px;
  color: var(--rd-cream);
  min-height: 0;
  /* Sprint 56 §4d — Firefox / standards-track scrollbar. */
  scrollbar-width: thin;
  scrollbar-color: var(--rd-line-strong) transparent;
}
/* Sprint 56 §4d — WebKit scrollbar (Chrome / Safari / iOS). Tokens only. */
.chat-scroll::-webkit-scrollbar       { width: 8px; }
.chat-scroll::-webkit-scrollbar-track { background: transparent; }
.chat-scroll::-webkit-scrollbar-thumb {
  background: var(--rd-line-strong);
  border-radius: 999px;
}
.chat-scroll::-webkit-scrollbar-thumb:hover { background: var(--rd-gold-dim); }
.chat-scroll .msg { margin-bottom: 7px; line-height: 1.45; }
.chat-scroll .msg .from {
  color: var(--rd-gold);
  font-weight: 600;
  margin-right: 5px;
  font-family: var(--rd-font-serif);
  font-style: italic;
  font-size: 13.5px;
}
.chat-scroll .msg.opp .from { color: var(--rd-opp-name); }
/* Sprint 56 §4c — emoticon lines stack the from-label above the image so
   the 74×74 art isn't shoved off the row by the inline name span. */
.chat-scroll .msg.emoticon-msg { display: block; }
.chat-scroll .msg.emoticon-msg .from {
  display: block;
  margin-right: 0;
  margin-bottom: 4px;
}
.chat-scroll .msg.emoticon-msg img {
  display: block;
  width: 74px;
  height: 74px;
  margin: 0;
}
.chat-scroll .msg.system {
  color: var(--rd-cream-dim);
  font-style: italic;
  font-size: 11px;
  font-family: var(--rd-font-body);
}
.chat-scroll .empty {
  color: var(--rd-cream-dim);
  font-style: italic;
  font-size: 11px;
  text-align: center;
  padding: 14px 6px 6px;
  font-family: var(--rd-font-body);
}

/* ===== Chat input · WhatsApp-style pill with embedded smiley ===== */
.chat-input {
  border-top: 1px solid var(--rd-line);
  padding: 10px 10px;
  flex-shrink: 0;
  position: relative;
  z-index: 2;
  background: var(--rd-dark-veil-soft);
}
.input-wrap {
  position: relative;
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid var(--rd-line-strong);
  border-radius: 20px;
  display: flex;
  align-items: center;
  transition: border-color 140ms ease, background 140ms ease, box-shadow 140ms ease;
}
.input-wrap:hover { border-color: var(--rd-gold-dim); }
.input-wrap:focus-within {
  border-color: var(--rd-gold);
  background: rgba(0, 0, 0, 0.7);
  box-shadow: 0 0 0 3px var(--rd-gold-hover-subtle);
}
.input-wrap input {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: none;
  padding: 9px 38px 9px 14px;
  color: var(--rd-cream);
  font-size: 13px;
  font-family: var(--rd-font-body);
  outline: none;
}
.input-wrap input::placeholder {
  color: var(--rd-cream-dim);
  opacity: 0.7;
  font-style: italic;
}
.smiley-inline {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  width: 30px;
  height: 30px;
  background: transparent;
  border: none;
  color: var(--rd-cream-dim);
  cursor: pointer;
  font-size: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  transition: color 140ms, background 140ms;
  padding: 0;
}
.smiley-inline:hover {
  color: var(--rd-gold);
  background: var(--rd-gold-hover-soft);
}

/* ===== Bottom menu · nested inside right column ===== */
.right-col .menu-bar {
  position: static;
  display: flex;
  gap: 4px;
  align-self: stretch;
  background: var(--rd-dark-veil-strong);
  border: 1px solid var(--rd-line-strong);
  border-radius: 6px;
  padding: 4px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.04);
  flex-shrink: 0;
  z-index: 50;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  justify-content: space-between;
}
.menu-bar .mb-gap { display: none; }

.mb-btn {
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--rd-cream-dim);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  cursor: pointer;
  text-decoration: none;
  padding: 0;
  transition: background 140ms ease, border-color 140ms ease, color 140ms ease;
}
/* WEEK58 §4d FIX-7: the author `.mb-btn{display:flex}` above beats the UA
   stylesheet's `[hidden]{display:none}`, so `el.hidden=true` alone does
   not hide the iPad fab fullscreen button on iPhone. An author-origin
   `[hidden]` guard (specificity 0,2,0 > 0,1,0) reliably wins. */
.mb-btn[hidden] { display: none; }
.mb-btn svg { width: 22px; height: 22px; stroke-width: 1.75; }
.mb-btn:hover {
  background: var(--rd-gold-hover-subtle);
  border-color: var(--rd-line-strong);
  color: var(--rd-cream);
}
.mb-btn.active {
  background: var(--rd-gold-hover-subtle);
  border-color: var(--rd-line-strong);
  color: var(--rd-cream);
}
.mb-btn.danger:hover {
  background: var(--rd-red-tint);
  border-color: var(--rd-red-1);
  color: var(--rd-warn-red-bright);
}
/* WEEK61 §4 T5 — gold-toggle for menu buttons (autoroll is the consumer
   today; mirrors the iPad/phone .mb-btn.on rule). paintAutoroll writes
   .on on the .mb-autoroll button to reflect state.autoroll. */
.mb-btn.on {
  background: var(--rd-gold-fill);
  border-color: var(--rd-gold);
  color: var(--rd-gold);
}

/* ===== Full-screen toggle · top-left ===== */
.fs-toggle {
  position: absolute;
  top: 14px;
  left: 16px;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--rd-cream-dim);
  background: var(--rd-dark-veil-medium);
  border: 1px solid var(--rd-line-strong);
  border-radius: 4px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.55);
  cursor: pointer;
  z-index: 80;
  padding: 0;
  opacity: 0.78;
  transition: opacity 140ms ease, background 140ms ease, border-color 140ms ease, color 140ms ease;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
/* WEEK58 §4d FIX-7: same as .mb-btn[hidden] above — the author
   `.fs-toggle{display:flex}` rule overrides the UA `[hidden]{display:none}`,
   so `el.hidden=true` alone leaves the desktop top-left full-screen
   button visible on iPhone. Author-origin `[hidden]` guard wins. */
.fs-toggle[hidden] { display: none; }
.fs-toggle svg { width: 18px; height: 18px; stroke-width: 1.75; }
.fs-toggle:hover {
  opacity: 1;
  background: var(--rd-gold-hover);
  border-color: var(--rd-gold);
  color: var(--rd-cream);
}

/* ===== Chat reactions popup · 66b (WEEK65) ================================
   Center-screen popup opened by the .smiley-inline button in the chat
   input pill. Reuses the .gc-modal-backdrop + .gc-modal-card glass DNA
   from modals.css; this block only adds the reactions-specific sizing,
   section labels, two grids, and the close X. The own-message echo (
   .msg.you) lives at the bottom of the block — it paints in the chat
   panel itself, not in the popup, but keeps the WEEK65 surgical-add
   contained to one section in this file. */
.gc-modal-card.reactions {
  /* WEEK66 §4b FIX-B1 — responsive base rule. The card's containing block
     is the fixed full-viewport `.gc-modal-backdrop`, so `%` resolves to the
     viewport. `min(520px, calc(100% - 24px))` keeps desktop at the original
     520px (12px+ side margin available everywhere wider than 544) and
     clamps the card on narrow phones. `max-height: calc(100% - 16px)` +
     `overflow-y: auto` only BIND when the viewport is shorter than the
     card (≈ phone landscape ≤ 540px tall) — desktop/iPad viewports are
     taller than the natural ~540px card, so the rule never engages there
     and the popup renders byte-identical to WEEK65. Replaces the dead
     WEEK66 `[data-layout="phone"]/[data-layout="phone-se"]/[data-layout=
     "ipad"]` overrides (popup lives OUTSIDE `.viewport` — those descendant
     selectors could never match). */
  width: min(520px, calc(100% - 24px));
  max-height: calc(100% - 16px);
  overflow-y: auto;
  padding: 24px 28px 26px;
  text-align: left;
  position: relative;
}
.gc-modal-card.reactions .popup-close {
  position: absolute;
  top: 10px;
  right: 12px;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  color: var(--rd-cream-dim);
  font-size: 18px;
  line-height: 1;
  border-radius: 4px;
  cursor: pointer;
  padding: 0;
  transition: color 140ms ease, background 140ms ease;
}
.gc-modal-card.reactions .popup-close:hover {
  color: var(--rd-cream);
  background: rgba(255, 255, 255, 0.05);
}
.gc-modal-card.reactions .popup-section-label {
  font-family: var(--rd-font-body);
  font-size: 10px;
  font-weight: 600;
  color: var(--rd-gold);
  text-transform: uppercase;
  letter-spacing: 2px;
  text-align: center;
  margin: 0 0 12px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.gc-modal-card.reactions .popup-section-label::before,
.gc-modal-card.reactions .popup-section-label::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--rd-line);
}
.gc-modal-card.reactions .popup-section-label.second { margin-top: 20px; }
.gc-modal-card.reactions .emoticon-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  margin-bottom: 6px;
}
.gc-modal-card.reactions .emoticon-pick {
  aspect-ratio: 1 / 1;
  background: transparent;
  border: 1px solid var(--rd-line);
  border-radius: 8px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px;
  transition: background 140ms ease, border-color 140ms ease, transform 80ms ease;
}
.gc-modal-card.reactions .emoticon-pick:hover {
  background: var(--rd-gold-hover-soft);
  border-color: var(--rd-line-strong);
}
.gc-modal-card.reactions .emoticon-pick:active { transform: scale(0.94); }
.gc-modal-card.reactions .emoticon-pick img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  pointer-events: none;
}
.gc-modal-card.reactions .preset-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.gc-modal-card.reactions .preset-pick {
  font-family: var(--rd-font-body);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.2px;
  padding: 11px 16px;
  background: rgba(0, 0, 0, 0.45);
  color: var(--rd-cream);
  border: 1px solid var(--rd-line-strong);
  border-radius: 8px;
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease, color 140ms ease;
  text-align: center;
  white-space: nowrap;
}
.gc-modal-card.reactions .preset-pick:hover {
  background: var(--rd-gold-hover-soft);
  border-color: var(--rd-gold);
  color: var(--rd-cream);
}

/* ===== Settings popup · 68 (WEEK67) ======================================
   Opened by every Settings button (desktop .menu-bar, phone .ph-strip.ph-you
   .mb-bar, iPad .fab-menu — all aria-label="Settings"). Same glass DNA as
   #m-reactions (the popup mounts as a sibling of `.viewport`, outside
   `.stage`, so the `@media (max-height:480px)` and
   `@media (pointer:coarse) and (min-height:700px)` rules reach it on the
   short and tall non-desktop viewports). 6 rows: Sounds · Music · Board
   direction · Expand doubles · Pip count · Mute chat. */
.gc-modal-card.settings {
  width: 460px;
  padding: 24px 28px 26px;
  text-align: left;
  position: relative;
}
.gc-modal-card.settings .popup-close {
  position: absolute;
  top: 10px;
  right: 12px;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  color: var(--rd-cream-dim);
  font-size: 18px;
  line-height: 1;
  border-radius: 4px;
  cursor: pointer;
  padding: 0;
  transition: color 140ms ease, background 140ms ease;
}
.gc-modal-card.settings .popup-close:hover {
  color: var(--rd-cream);
  background: rgba(255, 255, 255, 0.05);
}
.gc-modal-card.settings .popup-section-label {
  font-family: var(--rd-font-body);
  font-size: 10px;
  font-weight: 600;
  color: var(--rd-gold);
  text-transform: uppercase;
  letter-spacing: 2px;
  text-align: center;
  margin: 0 0 16px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.gc-modal-card.settings .popup-section-label::before,
.gc-modal-card.settings .popup-section-label::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--rd-line);
}
.gc-modal-card.settings .settings-list {
  display: flex;
  flex-direction: column;
}
.gc-modal-card.settings .settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 11px 4px;
  border-top: 1px solid var(--rd-line);
}
.gc-modal-card.settings .settings-row:first-child {
  border-top: none;
}
.gc-modal-card.settings .s-label {
  font-family: var(--rd-font-body);
  font-size: 14px;
  font-weight: 500;
  color: var(--rd-cream);
  letter-spacing: 0.2px;
}

/* Switch (pill toggle) — same DNA as the autoroll switch tokens, sized
   for a settings-row hit target. `.on` is added/removed by controls.js. */
.gc-modal-card.settings .s-switch {
  position: relative;
  width: 38px;
  height: 22px;
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid var(--rd-line-strong);
  border-radius: 999px;
  cursor: pointer;
  padding: 0;
  transition: background 140ms ease, border-color 140ms ease;
  flex-shrink: 0;
}
.gc-modal-card.settings .s-switch::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--rd-cream-dim);
  transition: left 140ms ease, background 140ms ease;
}
.gc-modal-card.settings .s-switch.on {
  background: var(--rd-gold-fill);
  border-color: var(--rd-gold);
}
.gc-modal-card.settings .s-switch.on::after {
  left: 18px;
  background: var(--rd-gold);
}

/* Segmented control — L/R direction. The .on opt highlights gold. */
.gc-modal-card.settings .s-seg {
  display: inline-flex;
  border: 1px solid var(--rd-line-strong);
  border-radius: 6px;
  overflow: hidden;
  flex-shrink: 0;
}
.gc-modal-card.settings .s-seg-opt {
  font-family: var(--rd-font-action);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 1px;
  padding: 6px 14px;
  background: rgba(0, 0, 0, 0.45);
  color: var(--rd-cream-dim);
  border: none;
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease;
  min-width: 36px;
}
.gc-modal-card.settings .s-seg-opt + .s-seg-opt {
  border-left: 1px solid var(--rd-line-strong);
}
.gc-modal-card.settings .s-seg-opt:hover {
  background: var(--rd-gold-hover-soft);
  color: var(--rd-cream);
}
.gc-modal-card.settings .s-seg-opt.on {
  background: var(--rd-gold-fill);
  color: var(--rd-gold);
}

/* WEEK66 §4b FIX-B2 + §4c FIX-C1 — phone-landscape compaction. A `@media
   (max-height: 480px)` query reaches the modal (the popup sits OUTSIDE
   `.viewport` so `[data-layout="phone"]` descendant selectors never match
   it). §4c playtest revealed §4b shrank the emoticon IMG to 44px but NOT
   the `.emoticon-pick` cell (`aspect-ratio: 1/1` ≈ 120px tall → 8 cells
   in 2 rows + 8 preset rows still overflowed). §4c kills the square
   aspect on the cell + fixes its height to 52px, tightens grids/pills/
   labels, and tunes card padding so all 8 emoticons + 8 presets fit a
   ~360px landscape WITHOUT scrolling (the §4b `max-height: calc(100% -
   16px); overflow-y: auto` stays as the safety net). Desktop/iPad
   viewports are taller than 480px so this block never engages there —
   byte-identical to WEEK65. */
@media (max-height: 480px) {
  .gc-modal-card.reactions {
    padding: 10px 14px 12px;
  }
  .gc-modal-card.reactions .popup-section-label {
    margin: 0 0 6px;
  }
  .gc-modal-card.reactions .popup-section-label.second {
    margin-top: 8px;
  }
  .gc-modal-card.reactions .emoticon-grid {
    gap: 5px;
    margin-bottom: 4px;
  }
  /* §4c FIX-C1 — kill the aspect-ratio:1/1 cell on phone landscape. A
     fixed 52px-tall cell with 3px padding holds the 38px emoticon with
     room around it and no longer dominates the card height. */
  .gc-modal-card.reactions .emoticon-pick {
    aspect-ratio: auto;
    height: 52px;
    padding: 3px;
  }
  .gc-modal-card.reactions .emoticon-pick img {
    width: 38px;
    height: 38px;
  }
  .gc-modal-card.reactions .preset-grid {
    gap: 5px;
  }
  .gc-modal-card.reactions .preset-pick {
    padding: 6px 10px;
    font-size: 12px;
  }
  .gc-modal-card.reactions .popup-close {
    top: 6px;
    right: 8px;
  }
  /* WEEK67 · Settings popup on phone landscape — narrower card + tighter
     rows so all 6 rows fit a ~360px landscape without scrolling. The §4b
     `max-height: calc(100% - 16px); overflow-y: auto` safety on the base
     `.gc-modal-card` still covers any remaining overflow. */
  .gc-modal-card.settings {
    width: min(420px, calc(100% - 24px));
    padding: 12px 16px 14px;
  }
  .gc-modal-card.settings .popup-section-label {
    margin: 0 0 8px;
  }
  .gc-modal-card.settings .settings-row {
    padding: 7px 4px;
  }
  .gc-modal-card.settings .s-label {
    font-size: 13px;
  }
  .gc-modal-card.settings .popup-close {
    top: 6px;
    right: 8px;
  }
}

/* WEEK66 §4d FIX-D2 — iPad reactions popup enlarge. The base 520px card
   reads too small on a 1180-wide iPad (Jay playtest 2026-06-19); the
   [data-layout="ipad"] override was DEAD (modal mounts outside .viewport).
   A `@media (pointer: coarse) and (min-height: 700px)` query catches iPad
   landscape (coarse pointer + ≥744px tall) while excluding phone
   landscape (<480px tall) and desktop (fine pointer). Mirrors fit.js's
   own iPad gate (coarse + min-side ≥ 700). Enlarges card + grids + pills
   so the emoticons and presets read at finger-comfortable sizes. */
@media (pointer: coarse) and (min-height: 700px) {
  /* §4e FIX-E2 — base modal enlarge. iPad isn't covered by desktop's
     480px modal-card or by the phone's compact landscape rules; the
     Double / Beaver / Take-Drop / Resign modals all read too small on
     the 1180-wide stage. Bump the BASE `.gc-modal-card` + its title /
     body / standard button so every modal reads at finger-comfortable
     sizes on iPad. The `.gc-modal-card.reactions` enlargements below
     layer on top of these. */
  .gc-modal-card {
    width: min(620px, calc(100% - 80px));
    padding: 30px 36px 32px;
  }
  .gc-modal-card .gc-modal-title {
    font-size: 30px;
  }
  .gc-modal-card .gc-modal-body {
    font-size: 18px;
    line-height: 1.5;
  }
  .gc-modal-card .gc-modal-btn {
    font-size: 18px;
    padding: 14px 26px;
    letter-spacing: 1px;
  }

  .gc-modal-card.reactions {
    width: min(640px, calc(100% - 64px));
    padding: 28px 34px 30px;
  }
  .gc-modal-card.reactions .popup-section-label {
    font-size: 12px;
    letter-spacing: 2.5px;
    margin: 0 0 14px;
  }
  .gc-modal-card.reactions .popup-section-label.second {
    margin-top: 24px;
  }
  .gc-modal-card.reactions .emoticon-grid {
    gap: 14px;
    margin-bottom: 8px;
  }
  .gc-modal-card.reactions .emoticon-pick {
    padding: 8px;
  }
  .gc-modal-card.reactions .emoticon-pick img {
    width: 72px;
    height: 72px;
  }
  .gc-modal-card.reactions .preset-grid {
    gap: 12px;
  }
  .gc-modal-card.reactions .preset-pick {
    font-size: 18px;
    padding: 16px 20px;
  }
  .gc-modal-card.reactions .popup-close {
    width: 34px;
    height: 34px;
    font-size: 22px;
  }

  /* WEEK67 · Settings popup on iPad — the base card sizing above already
     bumps `.gc-modal-card` to min(620px, calc(100%-80px)) + padding 30/
     36/32, so `.gc-modal-card.settings` inherits the larger shell. Tune
     the row contents (labels + switch + segmented control) up to match
     the finger-comfortable scale used elsewhere on iPad. */
  .gc-modal-card.settings .popup-section-label {
    font-size: 12px;
    letter-spacing: 2.5px;
    margin: 0 0 20px;
  }
  .gc-modal-card.settings .settings-row {
    padding: 16px 4px;
  }
  .gc-modal-card.settings .s-label {
    font-size: 18px;
  }
  .gc-modal-card.settings .s-switch {
    width: 50px;
    height: 28px;
  }
  .gc-modal-card.settings .s-switch::after {
    top: 3px;
    left: 3px;
    width: 20px;
    height: 20px;
  }
  .gc-modal-card.settings .s-switch.on::after {
    left: 25px;
  }
  .gc-modal-card.settings .s-seg-opt {
    font-size: 16px;
    padding: 10px 20px;
    min-width: 48px;
  }
  .gc-modal-card.settings .popup-close {
    width: 34px;
    height: 34px;
    font-size: 22px;
  }
}

/* Own message · echoed into the chat panel when the player sends an
   emoticon / preset / free text. Mirrors .msg.opp's .from accent token but
   keeps the gold accent for the player so the two voices stay distinct
   (opp = purple, you = gold). Emoticon variant inherits the existing
   .msg.emoticon-msg block layout. */
.chat-scroll .msg.you .from { color: var(--rd-gold); }

/* ===== Log panel · WEEK69 (M3 part 2 · mockup 67) =====
   Sibling of .chat-panel inside .panel-host. Shown only when the desktop
   right-col menu Log button selects it (controls.js swaps the [hidden]
   attribute). All colours come from tokens — checker-red / checker-white
   drive the cube chips, gold-* + line-* drive the headers + scrollbar. */
.log-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.log-panel[hidden] { display: none; }
/* §4b B1 · the WEEK58 author-display vs UA-[hidden] gotcha, recurring.
   .chat-panel ships display:flex (line ~553); the UA's
   [hidden]{display:none} loses to it. Without this guard, controls.js's
   showLogPanel() sets chatPanel.hidden=true but the chat scroll + input
   stay visible on top of the log. Mirror the .log-panel[hidden] rule so
   BOTH panels obey the [hidden] attribute. */
.chat-panel[hidden] { display: none; }
.log-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 12px;
  border-bottom: 1px solid var(--rd-line);
  background: var(--rd-gold-hover-subtle);
  flex-shrink: 0;
}
.log-header .log-title {
  font-family: var(--rd-font-body);
  font-size: 10px;
  font-weight: 600;
  color: var(--rd-gold);
  text-transform: uppercase;
  letter-spacing: 2.2px;
}
.log-game {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 7px 12px 7px 10px;
  font-family: var(--rd-font-body);
  font-size: 11px;
  font-weight: 600;
  color: var(--rd-cream-dim);
  text-transform: uppercase;
  letter-spacing: 1.5px;
  background: var(--rd-overlay-dark-soft);
  border-bottom: 1px solid var(--rd-line);
  cursor: pointer;
}
.log-game .game-toggle { font-size: 10px; color: var(--rd-gold); }
.log-rows {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  /* Dark/gold scrollbar · mirrors the .chat-scroll treatment (mockup 67
     lines 260–264). Tokens-only. */
  scrollbar-width: thin;
  scrollbar-color: var(--rd-line-strong) var(--rd-dark-veil-soft);
}
.log-rows::-webkit-scrollbar       { width: 8px; }
.log-rows::-webkit-scrollbar-track {
  background: var(--rd-dark-veil-soft);
  border-radius: 4px;
}
.log-rows::-webkit-scrollbar-thumb {
  background: var(--rd-line-strong);
  border-radius: 4px;
}
.log-rows::-webkit-scrollbar-thumb:hover { background: var(--rd-gold-dim); }

.log-row {
  display: grid;
  grid-template-columns: 22px 40px 1fr;
  align-items: center;
  padding: 4px 12px 4px 6px;
  font-family: var(--rd-font-body);
  font-size: 12.5px;
  color: var(--rd-cream);
  border-bottom: 1px dotted var(--rd-gold-hover-subtle);
}
.log-row:nth-child(even) { background: var(--rd-overlay-light-inset); }
.log-row .turn-num {
  text-align: right;
  font-size: 11px;
  color: var(--rd-gold-dim);
  font-variant-numeric: tabular-nums;
  padding-right: 6px;
}
.log-row .dice {
  display: inline-flex;
  gap: 2px;
  align-items: center;
  min-height: 14px;
}
.log-row .dice img {
  width: 14px;
  height: 14px;
  display: block;
}
.log-row .notation {
  font-size: 12.5px;
  letter-spacing: 0.2px;
  color: var(--rd-cream);
  word-spacing: 1px;
}
.log-row.cube-event { color: var(--rd-cream-dim); font-style: italic; }
.log-row.cube-event .dice { justify-content: center; }
.log-row.cube-event .notation { color: var(--rd-cream-dim); font-style: italic; font-size: 12px; }
.log-row.cube-event .cube-chip {
  width: 16px;
  height: 16px;
  border-radius: 3px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--rd-font-body);
  font-size: 10px;
  font-weight: 700;
  border: 1px solid rgba(0, 0, 0, 0.3);
}
.log-row.cube-event .cube-chip.red   { background: var(--checker-red);   color: var(--rd-cream); }
.log-row.cube-event .cube-chip.white { background: var(--checker-white); color: var(--rd-dark); }
.log-row.game-end {
  color: var(--rd-gold);
  font-style: italic;
}
.log-row.game-end .dice { justify-content: center; color: var(--rd-gold-dim); }
/* §4d · game-end result chip (Jay 2026-06-21). Mirrors .cube-chip sizing
   + border + font but is coloured by win/loss (emerald for the win,
   garnet/red for the loss). Tokens-only. */
.log-row.game-end .result-chip {
  width: 16px;
  height: 16px;
  border-radius: 3px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--rd-font-body);
  font-size: 10px;
  font-weight: 700;
  border: 1px solid rgba(0, 0, 0, 0.3);
  font-style: normal;
}
.log-row.game-end .result-chip.win  { background: var(--rd-emerald-1); color: var(--rd-cream); }
.log-row.game-end .result-chip.loss { background: var(--rd-red-1);     color: var(--rd-cream); }
.log-empty {
  color: var(--rd-cream-dim);
  font-style: italic;
  font-size: 11px;
  text-align: center;
  padding: 14px 6px 6px;
  font-family: var(--rd-font-body);
}
