/* Design tokens, base resets, and globals (.hidden, focus, form-element
   font inheritance) now live in client/src/styles/{tokens,reset,globals}.css
   and are imported once at the React entry point (main.tsx). This file
   contains only component-specific legacy styles pending migration to
   co-located *.module.css per spec section 3. */

   /* .user-pill* migrated to client/src/components/UserPill.module.css
   (slice 11 CSS co-location). */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}

.brand {
  font-family: "Yanone Kaffeesatz", "Nunito", sans-serif;
  font-size: 1.55rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.brand-link {
  text-decoration: none;
  cursor: pointer;
  /* F-002: 44px hit area around the wordmark even on tight headers. */
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
.brand-link:hover .brand-main {
  filter: brightness(1.15);
}

.brand-main {
  background: linear-gradient(90deg, #fb923c 0%, #f97316 55%, #0ea5e9 150%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.workspace {
  display: grid;
  /* Natural Richup-style composition. useGameScale scales this whole layout
     uniformly when the viewport is smaller than its natural footprint. */
  grid-template-columns: 360px 900px 360px;
  gap: 16px;
  align-items: start;
  max-width: 1652px;
  margin: 0 auto;
}

/* Scale-to-fit wrapper: the hook reads container padding, measures the
   controller's natural size, and writes inline transform/width/height onto
   the controller. The toggle button persists the user's preference. */
.game-scale-container {
  width: 100%;
  padding-inline: 16px;
  box-sizing: border-box;
  /* If anything inside (a wide panel, a flex child without min-width: 0)
     ever overflows horizontally, contain it at the page-level wrapper so
     the body doesn't grow a horizontal scrollbar. The rail itself does NOT
     clip — that was cutting off visible UI — but the page boundary catches
     any wider-than-expected content. */
  overflow-x: auto;
}
.game-scale-controller {
  /* Intrinsic width matches the workspace's natural layout so the scale hook
     can compute a meaningful ratio against the viewport. */
  width: 1652px;
  margin-inline: auto;
}

.left-rail,
.right-rail {
  display: grid;
  gap: 12px;
  /* align-self: start keeps the rail at its natural content height in the
     grid row — no stretching, so the panels don't get gap-distributed apart.
     align-content: start packs children at the top of the rail itself so
     any leftover space (if max-height ever clamps) sits below the last
     panel rather than between panels.
     We deliberately do NOT set overflow-y: auto or scrollbar-gutter: stable
     here. Both prior attempts caused horizontal clipping inside the rails:
     overflow: hidden literally cut off the right edge of player rows / pills,
     and scrollbar-gutter: stable reserved ~14px on the right unconditionally,
     shaving the last character off labels like "Sullivan Denning". On the
     normal case (wide viewport, rail content shorter than the board) neither
     is needed. On very short viewports, panels may extend past the board's
     bottom — that's the same behavior as before this work and acceptable
     until we revisit composition. */
  height: 900px;
  align-self: stretch;
  align-content: stretch;
  min-height: 0;
}

.left-rail {
  grid-template-rows: auto minmax(0, 1fr) minmax(0, 2.1fr);
}

.right-rail {
  grid-template-rows: auto auto auto minmax(0, 1fr) minmax(0, 1.8fr);
  /* Room.tsx overrides this with live row weights based on current players,
     pending trades, and owned properties. This fallback keeps the static
     shell sensible before state-derived styles are applied. */
}

.left-rail > *,
.right-rail > * {
  min-height: 0;
}

/* Strip the heavy default panel shadow (--shadow is 0 30px 80px rgba(0,0,0,0.55))
   for panels inside rails. With only 12px between rail panels, each panel's
   shadow piles into the gap zone and onto the panel below, reading as dark
   stripes between cards. Rails don't need per-panel floating shadows — the
   panels are already visually contained by the rail's column. Keep a tight
   inset highlight so cards still feel distinct. */
.left-rail > .panel,
.right-rail > .panel {
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.04) inset;
}

.panel {
  background: var(--panel);
  backdrop-filter: blur(14px) saturate(130%);
  -webkit-backdrop-filter: blur(14px) saturate(130%);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.players-panel,
.settings-panel {
  padding: 14px;
}

.players-panel {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.players-list {
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

/* .share-panel* migrated to client/src/components/room/SharePanel.module.css
   (slice 9 CSS co-location). */

.trades-panel {
  padding: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.trades-panel-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

.panel-titlebar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.panel-titlebar h2 {
  margin: 0;
  color: var(--muted);
  font-family: "Yanone Kaffeesatz", "Nunito", sans-serif;
  font-size: 0.82rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
}

input {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 10px;
  color: var(--text);
  background: rgba(255, 255, 255, 0.04);
  padding: 11px 13px;
  outline: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

input::placeholder {
  color: var(--muted-soft);
}

input:focus {
  border-color: rgba(249, 115, 22, 0.7);
  box-shadow: 0 0 0 3px rgba(249, 115, 22, 0.14);
}

.small-button,
.controls button,
.send-button {
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
  color: white;
  background: rgba(255, 255, 255, 0.04);
  font-weight: 600;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  transition: transform 0.12s ease, background 0.15s ease, border-color 0.15s ease;
}

.small-button:hover,
.send-button:hover {
  background: rgba(255, 255, 255, 0.08);
}

.small-button:active,
.controls button:active {
  transform: translateY(1px) scale(0.99);
}

.small-button,
.send-button {
  padding: 10px 16px;
  font-size: 0.88rem;
  /* F-002: hit the 44px iOS / 48dp Android touch-target floor without
     changing visual rhythm. min-height lets short labels (Join, etc.)
     match taller ones for consistent tappable zones. */
  min-height: 44px;
}

.small-button.success {
  background: var(--accent);
  border-color: transparent;
  box-shadow: 0 12px 30px -12px rgba(249, 115, 22, 0.6);
}

.small-button.success:hover {
  background: var(--accent-strong);
}

.small-button.muted {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--line);
  color: var(--muted);
}

.small-button.danger {
  border-color: rgba(239, 68, 68, 0.55);
  color: #f87171;
}

.small-button.danger:hover {
  background: rgba(239, 68, 68, 0.12);
  border-color: rgba(239, 68, 68, 0.85);
  color: #fca5a5;
}

.small-button:disabled,
.small-button.muted:disabled,
.small-button.success:disabled,
.small-button.danger:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  background: rgba(255, 255, 255, 0.02);
  border-color: var(--line);
  color: var(--muted);
  box-shadow: none;
}

.small-button:disabled:hover {
  background: rgba(255, 255, 255, 0.02);
  border-color: var(--line);
}

.error-text {
  min-height: 18px;
  margin: 8px 0 0;
  color: #ff98b0;
  font-size: 0.86rem;
}

/* Chat send — orange-soft per DESIGN.md (no purple accents). */
.send-button {
  min-width: 46px;
  background: var(--accent-soft);
  border-color: rgba(249, 115, 22, 0.4);
}
.send-button:hover {
  background: rgba(249, 115, 22, 0.28);
}

.board-stage {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 1 / 1;
  /* The board fills the natural center column. The outer game scaler owns
     viewport fit, so this element stays square without a competing vh cap. */
  width: 100%;
  justify-self: center;
  align-self: start;
  min-width: 0;
  min-height: 0;
  isolation: isolate;
  background:
    radial-gradient(circle at 50% 50%, rgba(249, 115, 22, 0.10), transparent 42%),
    radial-gradient(circle at 12% 12%, rgba(34, 197, 94, 0.08), transparent 20%),
    radial-gradient(circle at 88% 84%, rgba(14, 165, 233, 0.10), transparent 22%);
  border-radius: 28px;
}

.board {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: var(--board-grid-template, repeat(var(--board-grid-size, 13), 1fr));
  grid-template-rows: var(--board-grid-template, repeat(var(--board-grid-size, 13), 1fr));
  gap: 3px;
  padding: 14px;
  background:
    radial-gradient(ellipse at 50% 50%, rgba(255, 255, 255, 0.025), transparent 72%),
    linear-gradient(180deg, color-mix(in srgb, var(--board-bg) 65%, transparent), color-mix(in srgb, var(--board-bg) 90%, transparent));
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 22px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    inset 0 -1px 0 rgba(0, 0, 0, 0.5),
    inset 0 0 80px rgba(0, 0, 0, 0.55),
    0 40px 80px -30px rgba(0, 0, 0, 0.7);
}

.board::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 0;
  opacity: 0.06;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' seed='7'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0'/></filter><rect width='160' height='160' filter='url(%23n)'/></svg>");
}

.token-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
  /* Mirror the .board grid so token wrappers can use grid-row / grid-column
     instead of percentage math (which would ignore .board's padding, border,
     and gap and drift to the left/up on bigger N). */
  display: grid;
  grid-template-columns: var(--board-grid-template, repeat(var(--board-grid-size, 13), 1fr));
  grid-template-rows: var(--board-grid-template, repeat(var(--board-grid-size, 13), 1fr));
  gap: 3px;
  padding: 14px;
  border: 1px solid transparent;
  box-sizing: border-box;
}


.space {
  position: relative;
  height: 100%;
  min-height: 0;
  overflow: hidden;
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.04);
  background:
    linear-gradient(158deg, rgba(48, 62, 84, 0.95) 0%, rgba(26, 36, 54, 0.96) 45%, rgba(12, 18, 30, 0.97) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.1),
    inset 0 0 0 1px rgba(0, 0, 0, 0.3),
    0 1px 0 rgba(0, 0, 0, 0.35),
    0 6px 14px rgba(0, 0, 0, 0.35);
  transition:
    transform 260ms cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 260ms cubic-bezier(0.22, 1, 0.36, 1),
    border-color 160ms ease;
  cursor: pointer;
  container-type: size;
  container-name: tile;
}

.space::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 0;
  background: radial-gradient(ellipse at 50% -10%, rgba(255, 255, 255, 0.07), transparent 55%);
}

.space:hover {
  transform: translateY(-2px);
  border-color: rgba(249, 115, 22, 0.5);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    inset 0 0 0 1px rgba(249, 115, 22, 0.18),
    0 1px 0 rgba(0, 0, 0, 0.35),
    0 12px 28px rgba(0, 0, 0, 0.45),
    0 0 30px -6px rgba(249, 115, 22, 0.4);
}

.space.edge {
  font-size: 0.58rem;
}

.space.corner {
  font-size: 0.82rem;
  display: grid;
  place-items: center;
  text-align: center;
  border-radius: 10px;
  border: 1px solid rgba(249, 115, 22, 0.22);
  background:
    linear-gradient(160deg, rgba(249, 115, 22, 0.12) 0%, rgba(234, 88, 12, 0.10) 38%, rgba(13, 20, 36, 0.95) 92%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.12),
    inset 0 0 0 1px rgba(0, 0, 0, 0.35),
    inset 0 -4px 12px rgba(0, 0, 0, 0.5),
    0 3px 0 rgba(0, 0, 0, 0.45),
    0 16px 34px -10px rgba(0, 0, 0, 0.6);
}

.space.corner::after {
  background: radial-gradient(ellipse at 50% 0%, rgba(249, 115, 22, 0.18), transparent 55%);
}

.space.corner:hover {
  transform: translateY(-2px);
  border-color: rgba(249, 115, 22, 0.65);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.16),
    inset 0 0 0 1px rgba(249, 115, 22, 0.3),
    inset 0 -4px 12px rgba(0, 0, 0, 0.5),
    0 3px 0 rgba(0, 0, 0, 0.45),
    0 20px 40px -10px rgba(0, 0, 0, 0.65),
    0 0 30px -4px rgba(249, 115, 22, 0.32);
}

.space.corner .space-content {
  align-content: center;
  justify-items: center;
  padding: 10px;
  gap: 6px;
}

.space.corner .space-content.special-corner {
  display: grid;
  align-content: stretch;
  justify-items: stretch;
  width: 100%;
  height: 100%;
  padding: 10px;
  gap: 6px;
}

.space.corner .space-icon {
  font-size: clamp(1.1rem, 18cqmin, 2.4rem);
  filter: drop-shadow(0 2px 5px rgba(0, 0, 0, 0.55));
}

.space.corner .space-name {
  max-width: 100%;
  font-family: "DM Serif Display", serif;
  font-weight: 400;
  font-size: clamp(0.55rem, 7cqmin, 0.95rem);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: #f4d69b;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.55);
  line-height: 1.04;
  overflow-wrap: break-word;
  word-break: normal;
  hyphens: auto;
}

.space.corner .space-name.single-line {
  white-space: nowrap;
  font-size: clamp(0.5rem, 6cqmin, 0.85rem);
  letter-spacing: 0.12em;
}

.space-band {
  position: absolute;
  background: #64748b;
  z-index: 1;
  overflow: hidden;
}

.space-band::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.32) 0%,
    rgba(255, 255, 255, 0.06) 28%,
    rgba(0, 0, 0, 0) 55%,
    rgba(0, 0, 0, 0.18) 100%
  );
}

.space.left .space-band::after,
.space.right .space-band::after {
  background: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.32) 0%,
    rgba(255, 255, 255, 0.06) 28%,
    rgba(0, 0, 0, 0) 55%,
    rgba(0, 0, 0, 0.18) 100%
  );
}

.space.bottom .space-band {
  top: 0;
  right: 0;
  left: 0;
  bottom: auto;
  height: 22%;
}

.space.top .space-band {
  top: auto;
  right: 0;
  left: 0;
  bottom: 0;
  height: 22%;
}

.space.left .space-band {
  top: 0;
  right: 0;
  bottom: 0;
  left: auto;
  width: 22%;
}

.space.right .space-band {
  top: 0;
  right: auto;
  bottom: 0;
  left: 0;
  width: 22%;
}

.space-content {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  /* Bottom padding clears the owner strip (clamp(9px, 18cqmin, 22px))
     plus 3px breathing room. Static 12px wasn't enough on small boards
     where 18cqmin lands near the 22px cap and the strip overlapped
     the property name. Same math as left/right tiles below. */
  padding: 6px 5px clamp(12px, 18cqmin + 3px, 25px);
  display: grid;
  /* Single explicit column that NEVER exceeds the content-box width.
     Without this, the default `grid-template-columns: auto` would size
     the column to the widest child (.space-top-row's flag+price chip).
     On tiny tiles (high DPI + browser zoom: viewport 933x635 → 35px tile
     → 21px content area), the auto column expanded to 33px while content
     was 21px, making .space-name width: 100% (=33px) overflow the tile.
     Since .space has overflow: hidden, text was visibly clipped on the
     right edge (SALVADOR → SALVADO, $60 → $6).
     minmax(0, 1fr) clamps the column to the content area's actual width.
     Children with min-width: 0 (below) can shrink inside it. */
  grid-template-columns: minmax(0, 1fr);
  align-content: space-between;
  justify-items: center;
  text-align: center;
}

/* Let grid children shrink inside the minmax(0, 1fr) track instead of
   forcing the column wider. Without min-width: 0 on the children, an
   emoji + price-chip row could push past the tile edge. */
.space-content > * {
  min-width: 0;
  max-width: 100%;
}

.space.top .space-content {
  /* Inverse of default: strip is on TOP for top tiles, so top-padding
     gets the strip-clearance treatment and bottom-padding goes static. */
  padding: clamp(12px, 18cqmin + 3px, 25px) 5px 6px;
}

.space.top .space-name { order: 1; }
.space.top .space-icon { order: 2; }
.space.top .space-top-row { order: 3; }

.space.left .space-content,
.space.right .space-content {
  /* Bottom padding here corresponds (post-90° rotation) to the OUTER edge
     of the tile in screen space — exactly where .space-owner-strip lives
     (clamp(9px, 18cqmin, 22px) wide). On small boards (compact tile width)
     a 13px inset wasn't enough to clear the 18cqmin strip, so the price
     chip + name text clipped into the colored owner bar. Bumping the
     inset to match the strip's clamp + 3px breathing room. */
  padding: 6px 5px clamp(12px, 18cqmin + 3px, 25px);
}

/* Landscape tiles (left/right edges): rotate content so it occupies the full
   tile with its portrait layout intact. Width becomes half the parent width
   (= tile height), height doubles (= tile width), then rotated into place. */
.space.left .space-content,
.space.right .space-content {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--board-side-content-width, 50%);
  height: var(--board-side-content-height, 200%);
  box-sizing: border-box;
  transform-origin: center center;
}

.space.left .space-content {
  transform: translate(-50%, -50%) rotate(90deg);
}

.space.right .space-content {
  transform: translate(-50%, -50%) rotate(-90deg);
}


.space-top-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 4px;
  width: 100%;
}

.space.corner .space-top-row {
  justify-content: center;
}

.space-flag {
  font-size: clamp(0.55rem, 8cqmin, 1rem);
  line-height: 1;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.55));
}

.space-value {
  color: #f4e4c8;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.45), rgba(0, 0, 0, 0.7));
  border: 1px solid rgba(249, 115, 22, 0.22);
  border-radius: 3px;
  font-size: clamp(0.42rem, 5.5cqmin, 0.7rem);
  padding: clamp(1px, 0.6cqmin, 3px) clamp(3px, 2.5cqmin, 7px);
  font-weight: 600;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  letter-spacing: 0.02em;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 1px 2px rgba(0, 0, 0, 0.45);
}

.space.top .space-top-row,
.space.bottom .space-top-row,
.space.left .space-top-row,
.space.right .space-top-row {
  justify-content: center;
}

.space-icon {
  font-size: clamp(0.7rem, 12cqmin, 1.4rem);
  opacity: 0.88;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.35));
}

.space-name {
  font-family: "Nunito", sans-serif;
  font-weight: 700;
  /* Tile text scales mechanically via container-query units. .space already
     declares container-type: size + container-name: tile (earlier in this
     file). cqmin = min(container-width, container-height) in %, so 14cqmin
     = 14% of the smaller tile dimension — text grows and shrinks with the
     tile, no JS measurement.

     No clamp floor on purpose. A floor (e.g. clamp(7px, 14cqmin, 16px))
     reintroduces overflow at tiny tile sizes (1024x768 ÷ 13 ≈ 70px tile,
     14cqmin ≈ 5px, a 7px floor would make text wider than the tile — the
     bug we're fixing). The 16px ceiling is fine because no tile gets that
     large in practice. If text becomes unreadable at sub-1024 viewports,
     useGameScale's horizontal safety net engages and zooms the whole
     controller back to readable.

     .space.corner .space-name (earlier in this file) is more specific and
     keeps its own clamp pair for the serif corner labels. This rule covers
     the 36 non-corner tiles where useFitText used to run.

     Replaces useFitText's JS binary-search measurement loop entirely;
     the hook is deleted in the next commit. */
  font-size: min(14cqmin, 16px);
  line-height: 1.05;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-align: center;
  color: #ecddbf;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.45);
  /* Plain block layout so text-align: center actually centers horizontally.
     The earlier attempt used display: -webkit-box + -webkit-line-clamp: 2
     for ellipsis-on-overflow, but the WebKit box model breaks horizontal
     alignment on top/bottom tiles (content shifts off-center to the right).
     Container queries already shrink text to fit, so the line-clamp safety
     net was redundant. Plain block + overflow: hidden is enough. */
  display: block;
  width: 100%;
  max-width: 100%;
  overflow-wrap: normal;
  word-break: normal;
  hyphens: manual;
  overflow: hidden;
}

.space-owner-strip {
  position: absolute;
  z-index: 3;
  overflow: hidden;
  box-shadow:
    inset 0 0 0 1px rgba(0, 0, 0, 0.4),
    0 0 14px -4px rgba(0, 0, 0, 0.55);
}

.space-owner-strip::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
}

/* Bottom edge: full-width rim along the bottom (outer), curved to match tile corner radius */
.space.bottom .space-owner-strip {
  left: 0;
  right: 0;
  bottom: 0;
  height: clamp(9px, 18cqmin, 22px);
  border-bottom-left-radius: 6px;
  border-bottom-right-radius: 6px;
}
.space.bottom .space-owner-strip::after {
  background: linear-gradient(
    180deg,
    rgba(0, 0, 0, 0.45) 0%,
    rgba(0, 0, 0, 0.1) 22%,
    rgba(255, 255, 255, 0.08) 55%,
    rgba(255, 255, 255, 0.5) 100%
  );
}

/* Top edge: rim along the top (outer) */
.space.top .space-owner-strip {
  left: 0;
  right: 0;
  top: 0;
  height: clamp(9px, 18cqmin, 22px);
  border-top-left-radius: 6px;
  border-top-right-radius: 6px;
}
.space.top .space-owner-strip::after {
  background: linear-gradient(
    0deg,
    rgba(0, 0, 0, 0.45) 0%,
    rgba(0, 0, 0, 0.1) 22%,
    rgba(255, 255, 255, 0.08) 55%,
    rgba(255, 255, 255, 0.5) 100%
  );
}

/* Left edge: vertical rim along the left (outer) */
.space.left .space-owner-strip {
  top: 0;
  bottom: 0;
  left: 0;
  width: clamp(9px, 18cqmin, 22px);
  border-top-left-radius: 6px;
  border-bottom-left-radius: 6px;
}
.space.left .space-owner-strip::after {
  background: linear-gradient(
    270deg,
    rgba(0, 0, 0, 0.45) 0%,
    rgba(0, 0, 0, 0.1) 22%,
    rgba(255, 255, 255, 0.08) 55%,
    rgba(255, 255, 255, 0.5) 100%
  );
}

/* Right edge: vertical rim along the right (outer) */
.space.right .space-owner-strip {
  top: 0;
  bottom: 0;
  right: 0;
  width: clamp(9px, 18cqmin, 22px);
  border-top-right-radius: 6px;
  border-bottom-right-radius: 6px;
}
.space.right .space-owner-strip::after {
  background: linear-gradient(
    90deg,
    rgba(0, 0, 0, 0.45) 0%,
    rgba(0, 0, 0, 0.1) 22%,
    rgba(255, 255, 255, 0.08) 55%,
    rgba(255, 255, 255, 0.5) 100%
  );
}

.space-owner-strip.mortgaged {
  opacity: 0.55;
  background-image: repeating-linear-gradient(
    45deg,
    rgba(0, 0, 0, 0.55) 0 2px,
    transparent 2px 5px
  );
  background-blend-mode: multiply;
}

/* Monopoly-completion flash: 2 brightness pulses over ~1.3s. The strip's
   solid background color stays put; we just punch up the lightness so the
   whole color group reads as a glowing ribbon momentarily. */
@keyframes ownerStripFlash {
  0%   { filter: brightness(1); }
  20%  { filter: brightness(2.1); }
  40%  { filter: brightness(1); }
  60%  { filter: brightness(2.1); }
  100% { filter: brightness(1); }
}

.space-owner-strip.flash {
  animation: ownerStripFlash 1.3s ease-in-out;
}

@media (prefers-reduced-motion: reduce) {
  .space-owner-strip.flash {
    animation: none;
  }
}

/* Floating event captions in replay cinema mode (v1.5 #7). Fade in,
   hold, then fade out so the viewer catches the moment without it
   sticking around. */
@keyframes replayCaptionFade {
  0%   { opacity: 0; transform: translateX(-50%) translateY(8px); }
  10%  { opacity: 1; transform: translateX(-50%) translateY(0); }
  75%  { opacity: 1; transform: translateX(-50%) translateY(0); }
  100% { opacity: 0; transform: translateX(-50%) translateY(-4px); }
}

@media (prefers-reduced-motion: reduce) {
  .replay-caption {
    animation: none !important;
  }
}

.token {
  width: 22px;
  height: 22px;
  position: relative;
}

.token {
  border-radius: 50% 50% 44% 44% / 50% 50% 40% 40%;
  background:
    radial-gradient(circle at 32% 24%, rgba(255, 255, 255, 0.72) 0%, rgba(255, 255, 255, 0.12) 35%, transparent 45%),
    var(--token-color, #f97316);
  box-shadow:
    inset 0 -3px 5px rgba(0, 0, 0, 0.32),
    inset 0 2px 2px rgba(255, 255, 255, 0.28),
    0 0 0 1px rgba(0, 0, 0, 0.45),
    0 5px 10px rgba(0, 0, 0, 0.45);
  transition: transform 220ms ease, filter 220ms ease;
  pointer-events: auto;
}

.token::before,
.token::after {
  content: "";
  position: absolute;
  top: 34%;
  width: 22%;
  height: 26%;
  border-radius: 50%;
  background: radial-gradient(circle at 38% 30%, #1b263b 0%, #05080f 65%, #000 100%);
  box-shadow:
    inset 0 -1px 0 rgba(255, 255, 255, 0.12),
    0 1px 1px rgba(0, 0, 0, 0.55);
}

.token::before {
  left: 24%;
}

.token::after {
  right: 24%;
}

.token:hover {
  transform: scale(1.08);
  filter: brightness(1.06);
}

.space:hover {
  transform: translateY(-1px);
}

.board-center {
  position: relative;
  z-index: 2;
  /* Scale to the board's inner area. The play board uses (gridSize-4)/gridSize
     of the stage between the top and bottom edge rows (corner tiles are 2×2,
     edge tiles span 2 cells in the perpendicular direction). 95% of that
     leaves a small margin so the center never hugs the edge tiles. The
     formula self-caps — it asymptotes to 95% as the grid grows, so no
     explicit cap is needed. */
  width: calc(var(--board-center-ratio, 69.2308%) * 0.95);
  height: calc(var(--board-center-ratio, 69.2308%) * 0.95);
  border-radius: 24px;
  background:
    radial-gradient(circle at 50% 0%, rgba(249, 115, 22, 0.18), transparent 55%),
    radial-gradient(circle at 50% 100%, rgba(14, 165, 233, 0.14), transparent 55%),
    linear-gradient(180deg, rgba(11, 17, 32, 0.92), rgba(7, 11, 21, 0.96));
  border: 1px solid rgba(255, 255, 255, 0.08);
  backdrop-filter: blur(10px);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  overflow: hidden;
  container-type: inline-size;
  container-name: center-panel;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 26px 50px rgba(0, 0, 0, 0.28);
}

.center-copy {
  flex: 1 1 0;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: clamp(8px, 3cqi, 18px);
  gap: clamp(4px, 1.5cqi, 10px);
}

.center-event-log-wrap {
  flex: 1 1 0;
  min-height: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  margin-top: clamp(4px, 2cqi, 12px);
}

.event-log {
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  padding: 8px 12px;
  margin: 0;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--line);
  border-radius: 8px;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 4px;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, black 14px, black calc(100% - 14px), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, black 14px, black calc(100% - 14px), transparent 100%);
}

.event-log.empty {
  padding: 8px 12px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--muted);
  text-align: center;
}

.event-log li {
  color: var(--muted);
  line-height: 1.35;
}

.event-log li:first-child {
  color: var(--text);
  font-weight: 600;
}

.center-status {
  display: block;
  font-family: "Yanone Kaffeesatz", "Nunito", sans-serif;
  font-size: 1.55rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin-bottom: 14px;
  background: linear-gradient(90deg, #fb923c, #f97316 60%, #ffe3c4);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.center-subtext,
.pot-status {
  color: var(--muted);
}

.center-subtext {
  margin: 14px auto 10px;
  max-width: 42ch;
}

.pot-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 10px auto 0;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid rgba(249, 115, 22, 0.28);
  background: var(--accent-soft);
  color: #fed7aa;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.dice-row {
  display: flex;
  justify-content: center;
  gap: 28px;
  perspective: 1400px;
  perspective-origin: 50% 24%;
  padding: 20px 0 34px;
}

.die {
  --die-size: 78px;
  width: var(--die-size);
  height: var(--die-size);
  position: relative;
  perspective: 700px;
  isolation: isolate;
}

.die::after {
  content: "";
  position: absolute;
  left: 11%;
  width: 78%;
  bottom: -18px;
  height: 16px;
  border-radius: 999px;
  background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.32) 0%, rgba(0, 0, 0, 0.22) 55%, transparent 74%);
  filter: blur(2px);
  z-index: -1;
  pointer-events: none;
}

.pip {
  width: 11px;
  height: 11px;
  margin: auto;
  border-radius: 999px;
  background: transparent;
}

.pip.active {
  background: radial-gradient(circle at 35% 30%, #4b5563 0%, #1f2937 55%, #030712 100%);
  box-shadow:
    inset 0 -2px 2px rgba(0, 0, 0, 0.55),
    inset 0 1px 1px rgba(255, 255, 255, 0.28),
    0 1px 1px rgba(0, 0, 0, 0.22);
}

.controls {
  display: grid;
  gap: 12px;
  margin-top: 14px;
}

.controls button {
  background: var(--accent);
  padding: 11px 22px;
  border-radius: 999px;
  border: 0;
  box-shadow: 0 18px 40px -18px rgba(249, 115, 22, 0.8);
  font-weight: 700;
  letter-spacing: 0.01em;
}

.controls button:hover {
  background: var(--accent-strong);
}

.controls button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  box-shadow: none;
}

.room-meta {
  color: var(--muted);
  margin-bottom: 8px;
  font-size: 0.78rem;
}

.players-list,
.settings-list {
  display: grid;
  gap: 8px;
}

.avatar {
  width: 34px;
  height: 34px;
  border-radius: 999px;
  display: grid;
  place-items: center;
  color: white;
  font-family: "Yanone Kaffeesatz", sans-serif;
  font-size: 0.86rem;
  font-weight: 700;
  box-shadow:
    inset 0 0 0 2px rgba(255, 255, 255, 0.15),
    0 6px 16px rgba(0, 0, 0, 0.35);
}

.panel-banner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  color: var(--muted);
  font-family: "Yanone Kaffeesatz", "Nunito", sans-serif;
  font-weight: 700;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
}

.panel-banner.centered {
  justify-content: center;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.space-houses {
  position: absolute;
  z-index: 3;
  display: flex;
  gap: 2px;
  padding: 2px 5px;
  border-radius: 4px;
  background: linear-gradient(180deg, rgba(20, 28, 44, 0.85), rgba(10, 14, 26, 0.95));
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 2px 4px rgba(0, 0, 0, 0.5);
  pointer-events: none;
}

.space.bottom .space-houses {
  top: 24%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.space.top .space-houses {
  top: auto;
  bottom: 24%;
  left: 50%;
  transform: translate(-50%, 50%);
}

/* Side rails: stack pips vertically so they run along the tile's long edge
   (the tile itself is rotated, so a horizontal pip row would cross the short
   edge and look cramped). Rotating the row 90° also aligns the little house
   "roof" toward the play area, matching how the bottom rail reads. */
.space.left .space-houses {
  top: 50%;
  left: auto;
  right: 24%;
  transform: translate(50%, -50%) rotate(-90deg);
}

.space.right .space-houses {
  top: 50%;
  right: auto;
  left: 24%;
  transform: translate(-50%, -50%) rotate(90deg);
}

.house-pip {
  width: 6px;
  height: 9px;
  border-radius: 1.5px 1.5px 2px 2px;
  background: linear-gradient(180deg, #86efac 0%, #22c55e 55%, #14753a 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    inset 0 -1px 0 rgba(0, 0, 0, 0.25),
    0 1px 1px rgba(0, 0, 0, 0.45);
  position: relative;
}

.house-pip::before {
  content: "";
  position: absolute;
  top: -2.5px;
  left: 1px;
  right: 1px;
  height: 2.5px;
  background: linear-gradient(180deg, #ef4444 0%, #991b1b 100%);
  clip-path: polygon(0 100%, 50% 0, 100% 100%);
  filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.3));
}

.space-houses.has-hotel {
  background: linear-gradient(180deg, rgba(249, 115, 22, 0.38), rgba(120, 40, 10, 0.7));
  border-color: rgba(255, 190, 110, 0.65);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.16),
    0 2px 4px rgba(0, 0, 0, 0.5),
    0 0 10px rgba(249, 115, 22, 0.25);
}

.house-hotel {
  font-size: 0.82rem;
  line-height: 1;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6));
}

.collapsed {
  padding-top: 0;
}

.avatar.small {
  width: 28px;
  height: 28px;
  font-size: 0.76rem;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.24),
    0 4px 10px rgba(0, 0, 0, 0.22);
}

.settings-panel {
  padding: 0;
}

.settings-panel .settings-list {
  display: block;
  padding: 4px 8px 10px;
}

.settings-panel .panel-banner {
  position: sticky;
  top: 0;
  background: rgba(11, 17, 32, 0.7);
  backdrop-filter: blur(8px);
  z-index: 1;
}

.setting-row {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  align-items: center;
  column-gap: 12px;
  padding: 12px 10px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
  transition: background 0.15s ease;
}

.setting-row:last-child {
  border-bottom: 0;
}

.setting-row:hover:not(.disabled) {
  background: rgba(255, 255, 255, 0.02);
}

.setting-copy strong {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 3px;
}

.setting-copy span {
  display: block;
  color: var(--muted-soft);
  font-size: 0.78rem;
  line-height: 1.35;
}

.setting-row.disabled {
  opacity: 0.55;
}

.setting-select {
  appearance: none;
  -webkit-appearance: none;
  background: rgba(255, 255, 255, 0.04);
  color: white;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 6px 30px 6px 14px;
  font-family: "Yanone Kaffeesatz", sans-serif;
  font-size: 0.86rem;
  font-weight: 700;
  cursor: pointer;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--muted) 50%),
    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position:
    right 14px center,
    right 9px center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.setting-select:focus {
  outline: none;
  border-color: rgba(249, 115, 22, 0.6);
  box-shadow: 0 0 0 3px rgba(249, 115, 22, 0.14);
}

.setting-select:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}

.setting-select option {
  background: #0f172a;
  color: white;
}

.toggle {
  width: 42px;
  height: 24px;
  border-radius: 999px;
  position: relative;
  flex: 0 0 auto;
  border: 1px solid var(--line-strong);
  padding: 0;
  cursor: pointer;
  transition: background 0.18s ease, border-color 0.18s ease, transform 0.12s ease;
}

.toggle::after {
  content: "";
  position: absolute;
  top: 3px;
  width: 16px;
  height: 16px;
  border-radius: 999px;
  background: white;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
  transition: left 0.18s ease, right 0.18s ease;
}

.toggle.on {
  background: var(--accent);
  border-color: rgba(249, 115, 22, 0.5);
  box-shadow: 0 10px 22px -12px rgba(249, 115, 22, 0.7);
}

.toggle.on::after {
  right: 3px;
}

.toggle.off {
  background: rgba(255, 255, 255, 0.08);
}

.toggle.off::after {
  left: 3px;
}

.toggle:disabled {
  cursor: not-allowed;
  opacity: 0.55;
  box-shadow: none;
}

.settings-panel.read-only {
  opacity: 0.96;
}

/* Tumble for the 2D pip-face dice rendered by Dice.tsx (PipFace).
   Loops cleanly (start == end) so it can play indefinitely while we wait for
   the server to return the result. Dice.tsx swaps random pip values every
   80ms during the same window. The legacy .die-cube system above is for a
   separate 3D rendering that the React client no longer uses. */
.dice-row.rolling .pip-die {
  animation: pip-tumble 540ms cubic-bezier(0.3, 0.05, 0.3, 1) infinite;
}
.dice-row.rolling .pip-die:nth-child(2) {
  animation-delay: 90ms;
}
@keyframes pip-tumble {
  0%   { transform: translateY(0)    rotate(0deg); }
  25%  { transform: translateY(-22px) rotate(180deg); }
  50%  { transform: translateY(0)    rotate(360deg); }
  75%  { transform: translateY(-14px) rotate(540deg); }
  100% { transform: translateY(0)    rotate(720deg); }
}

@keyframes diceTumble {
  0% {
    transform: rotate(12deg) rotateX(0deg) rotateY(0deg) translateY(0);
  }
  25% {
    transform: rotate(70deg) rotateX(120deg) rotateY(60deg) translateY(-10px);
  }
  50% {
    transform: rotate(150deg) rotateX(220deg) rotateY(120deg) translateY(4px);
  }
  75% {
    transform: rotate(250deg) rotateX(310deg) rotateY(210deg) translateY(-8px);
  }
  100% {
    transform: rotate(372deg) rotateX(360deg) rotateY(320deg) translateY(0);
  }
}

/* Single-column collapse retired. Earlier the workspace collapsed to one
   column below 1180px CSS px, putting rails BELOW the board. That looked
   bad at common desktop combinations (1080p × 150% Windows DPI × 100%+
   browser zoom = effective viewport < 1180px). Richup never collapses;
   they keep the 3-column composition at every viewport and rely on
   transform:scale (useGameScale) to shrink the whole thing uniformly.
   Adopting the same: always 3-column, scale-to-fit handles narrow
   viewports. Mobile phones (<600px) will be cramped but aren't a
   current target per the design doc. */

@container center-panel (min-width: 0) {
  .center-status {
    font-size: clamp(0.95rem, 7cqi, 1.55rem);
    margin-bottom: clamp(4px, 2cqi, 12px);
  }
  .center-subtext, .pot-status {
    font-size: clamp(0.62rem, 3cqi, 0.85rem);
    margin: clamp(4px, 1.5cqi, 10px) auto;
  }
  .dice-row {
    gap: clamp(8px, 5cqi, 28px);
    padding: clamp(6px, 3cqi, 20px) 0 clamp(8px, 4cqi, 30px);
  }
  .die {
    --die-size: clamp(34px, 18cqi, 76px);
  }
  .center-copy .small-button,
  .center-copy button {
    font-size: clamp(0.7rem, 3cqi, 0.92rem);
    padding: clamp(4px, 1.5cqi, 10px) clamp(8px, 3cqi, 16px);
  }
  .event-log,
  .event-log.empty {
    font-size: clamp(0.62rem, 2.6cqi, 0.82rem);
  }
}

@container center-panel (max-width: 220px) {
  .center-copy {
    justify-content: center;
    padding: clamp(4px, 4cqi, 8px);
    gap: clamp(2px, 2cqi, 6px);
  }

  .center-status {
    font-size: clamp(0.82rem, 12cqi, 1.05rem);
    margin-bottom: 0;
  }

  .dice-row {
    transform: scale(0.78);
    transform-origin: center;
    margin: -6px 0;
  }

  .center-subtext,
  .pot-status {
    font-size: clamp(0.5rem, 5cqi, 0.68rem);
    line-height: 1.25;
    margin: 0 auto;
  }

  .center-event-log-wrap {
    display: none;
  }

  .center-copy .small-button,
  .center-copy button {
    font-size: clamp(0.58rem, 5cqi, 0.72rem);
    padding: 4px 8px;
    min-height: 28px;
  }
}

/* ── Post-game stats modal (legacy classes deleted; only React-consumed ones remain) ─── */
.stats-winner-label { font-size: 0.65rem; color: #818cf8; text-transform: uppercase; letter-spacing: 0.15em; margin-bottom: 0.2rem; }
.stats-winner-name { font-size: 1.4rem; font-weight: 700; color: #fff; display: flex; align-items: center; gap: 0.5rem; }

/* ===== Lobby view (legacy vanilla-JS classes deleted; only React-consumed ones remain) ===== */
.lobby-card {
  background: #121b2e; border: 1px solid #1e2a44;
  border-radius: 10px; padding: 14px;
}
.lobby-card-title {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--muted-soft); margin: 0 0 10px; font-weight: 600;
  display: flex; justify-content: space-between; align-items: center;
}
.lobby-chat-card { display: flex; flex-direction: column; }
.lobby-chat-messages {
  display: flex; flex-direction: column; gap: 6px;
  max-height: 340px; overflow-y: auto; margin-bottom: 10px;
  font-size: 11px;
}
.lobby-chat-input {
  background: rgba(255,255,255,0.04); border: 1px solid #2a3555;
  border-radius: 6px; padding: 8px 10px; color: #e2e8f0; font-size: 11px; width: 100%;
}
.lobby-board-thumb {
  aspect-ratio: 1; border-radius: 8px;
  display: grid; place-items: center;
  color: #e2e8f0; font-weight: 600; font-size: 14px;
  margin-bottom: 8px; border: 1px solid #2a3555;
}
.lobby-board-meta { font-size: 11px; color: #94a3b8; }

/* ===== Awaiting-join view (at /room/:code before joining) ===== */
.workspace.awaiting-join {
  grid-template-columns: min(460px, 100%);
  justify-content: center;
  padding-top: 40px;
}
.workspace.awaiting-join .board-stage,
.workspace.awaiting-join aside.right-rail,
.workspace.awaiting-join .trade-log-panel,
.workspace.awaiting-join .chat-panel {
  display: none;
}

/* .user-pill* dropdown migrated to client/src/components/UserPill.module.css
   (slice 11 CSS co-location). */

/* .account-banner* migrated to client/src/components/AccountBanner.module.css
   (slice 10 CSS co-location). */

/* ===== Casino (spectator blackjack) ===== */

.bj-trigger {
  position: fixed;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  z-index: 40;
  background: linear-gradient(180deg, #1d2c47, #131c2e);
  border: 1px solid #d4af37;
  color: #d4af37;
  padding: 14px 8px;
  border-radius: 12px 0 0 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  writing-mode: vertical-rl;
  cursor: pointer;
  box-shadow: 0 0 0 1px rgba(212, 175, 55, 0.15), 0 10px 28px rgba(0, 0, 0, 0.5);
}

.bj-drawer-mask {
  position: fixed;
  inset: 0;
  background: rgba(5, 10, 20, 0.6);
  z-index: 90;
}
.bj-drawer {
  position: fixed;
  right: 0;
  top: 0;
  bottom: 0;
  width: 60vw;
  max-width: 960px;
  background: linear-gradient(180deg, #0e1525, #0a1020);
  border-left: 2px solid #d4af37;
  box-shadow: -24px 0 48px rgba(0, 0, 0, 0.55);
  z-index: 100;
  display: grid;
  grid-template-rows: 44px 1fr auto;
  color: #e7edf7;
}
@media (max-width: 720px) { .bj-drawer { width: 100vw; } }
.bj-drawer-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 14px;
  border-bottom: 1px solid #1f2a44;
}
.bj-drawer-title { font-weight: 700; color: #d4af37; letter-spacing: 0.08em; }
.bj-drawer-close { background: transparent; border: 0; color: #93a0bb; font-size: 20px; cursor: pointer; }

.bj-table {
  background:
    radial-gradient(ellipse at 50% 35%, #1aa45c 0%, #128549 30%, #0a5a32 60%, #073f23 90%, #052a18 100%);
  position: relative;
  overflow: hidden;
  padding: 18px 16px 16px;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
/* Subtle vignette + inner-edge ring for depth on the felt. */
.bj-table::before {
  content: "";
  position: absolute;
  inset: 8px;
  border-radius: 12px;
  pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(212, 175, 55, 0.18), inset 0 0 60px rgba(0, 0, 0, 0.35);
}
/* .bj-phase-timer* migrated to
   client/src/components/casino/PhaseTimer.module.css (slice 14 — first
   component carved out of the Casino cluster). */

.bj-dealer { display: flex; flex-direction: column; align-items: center; gap: 6px; margin: 56px auto 0; flex: 0 0 auto; }
.bj-dealer-label { font-size: 10px; letter-spacing: 0.22em; color: #d4af37; text-transform: uppercase; }
.bj-dealer-hand { display: flex; gap: 6px; min-height: 70px; }
.bj-dealer-total { font-size: 10px; background: rgba(0,0,0,.35); padding: 2px 6px; border-radius: 4px; }

.bj-seats { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; padding: 0; margin-top: auto; }
.bj-seat {
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.22), rgba(0, 0, 0, 0.40));
  border: 1px solid rgba(212, 175, 55, 0.45);
  border-radius: 10px;
  padding: 8px 6px 6px;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  min-height: 132px;
  position: relative;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
.bj-seat-empty {
  justify-content: center;
  border-style: dashed;
  border-color: rgba(212, 175, 55, 0.45);
  background: rgba(0, 0, 0, 0.18);
}
.bj-seat-mine { border-color: #d4af37; box-shadow: 0 0 0 1px rgba(212, 175, 55, 0.55), 0 0 28px rgba(212, 175, 55, 0.4); }
.bj-seat-active { animation: bj-pulse 1.5s ease-in-out infinite; }
@keyframes bj-pulse { 50% { box-shadow: 0 0 0 2px rgba(212, 175, 55, 0.7); } }
.bj-seat-locked .bj-seat-progress { opacity: 0.55; filter: grayscale(0.6); }
.bj-seat-who { display: flex; align-items: center; gap: 5px; width: 100%; padding: 0 2px; }
.bj-seat-name { font-size: 11px; font-weight: 600; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bj-seat-mode { font-size: 9px; padding: 1px 5px; border-radius: 4px; background: rgba(34, 197, 94, 0.22); color: #86efac; text-transform: uppercase; font-weight: 700; letter-spacing: 0.05em; }
.bj-mode-buyback { background: rgba(212, 175, 55, 0.22); color: #f3d769; }
.bj-seat-hand { display: flex; flex-direction: column; align-items: center; gap: 2px; min-height: 50px; padding: 4px 4px 2px; border-radius: 6px; border: 1px solid transparent; transition: border-color 150ms ease, background 150ms ease, opacity 150ms ease; }
.bj-seat-hand-cards { display: flex; gap: 0; align-items: center; min-height: 50px; }
.bj-seat-hand-cards .bj-card + .bj-card { margin-left: -16px; }
.bj-seat-hand-split { border-color: rgba(212, 175, 55, 0.18); }
.bj-seat-hand-active { border-color: #d4af37; background: rgba(212, 175, 55, 0.12); box-shadow: 0 0 16px rgba(212, 175, 55, 0.35); animation: bj-hand-pulse 1.4s ease-in-out infinite; }
@keyframes bj-hand-pulse { 50% { box-shadow: 0 0 22px rgba(212, 175, 55, 0.55); } }
.bj-seat-hand-done { opacity: 0.55; }
.bj-seat-hand-label { font-size: 9px; letter-spacing: 0.1em; text-transform: uppercase; color: #d4af37; font-weight: 700; }
@media (prefers-reduced-motion: reduce) {
  .bj-seat-hand-active { animation: none; }
}
.bj-seat-total { font-size: 10px; background: rgba(0,0,0,.35); padding: 1px 6px; border-radius: 4px; }
.bj-bust { color: #ef4444; }
.bj-seat-bet { position: absolute; top: 8px; right: 8px; width: 22px; height: 22px; border-radius: 50%; background: radial-gradient(circle at 30% 30%, #fff8d6, #d4af37 60%, #b8932f); color: #2a1d05; font-weight: 800; font-size: 9px; display: flex; align-items: center; justify-content: center; }
.bj-seat-stack { font-size: 11px; font-weight: 700; color: #bbf7d0; background: linear-gradient(180deg, rgba(34, 197, 94, 0.28), rgba(22, 163, 74, 0.32)); padding: 2px 8px; border-radius: 4px; border: 1px solid rgba(34, 197, 94, 0.45); }
.bj-seat-progress { position: relative; width: calc(100% - 12px); margin: 0 6px; height: 16px; background: rgba(0,0,0,.45); border: 1px solid rgba(212, 175, 55, 0.3); border-radius: 4px; overflow: hidden; font-size: 9px; color: #d4af37; display: flex; align-items: center; justify-content: center; }
.bj-seat-progress-fill { position: absolute; inset: 0 auto 0 0; background: linear-gradient(90deg, rgba(212, 175, 55, 0.4), rgba(212, 175, 55, 0.7)); }
.bj-seat-progress span { position: relative; z-index: 2; font-weight: 700; }
.bj-seat-locked-label { font-size: 8px; color: #f3d769; text-transform: uppercase; font-weight: 700; letter-spacing: 0.05em; background: rgba(212, 175, 55, 0.18); border: 1px solid rgba(212, 175, 55, 0.45); border-radius: 4px; padding: 2px 5px; }
.bj-sit-btn {
  background: linear-gradient(180deg, rgba(212, 175, 55, 0.30), rgba(212, 175, 55, 0.16));
  color: #fbe88a;
  padding: 6px 10px;
  border-radius: 6px;
  border: 1px solid rgba(212, 175, 55, 0.6);
  font-weight: 800;
  font-size: 10px;
  letter-spacing: 0.04em;
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
  transition: background 120ms ease, color 120ms ease;
}
.bj-sit-btn:hover { background: linear-gradient(180deg, rgba(212, 175, 55, 0.45), rgba(212, 175, 55, 0.28)); color: #fff4c0; }
.bj-sit-btn-buyback { margin-top: 4px; }

.bj-drawer-foot { background: linear-gradient(180deg, #0d1426, #080d1a); border-top: 1px solid #1f2a44; padding: 10px 14px; display: flex; flex-direction: column; gap: 8px; }
.bj-bet-actions, .bj-action-bar { display: flex; gap: 8px; }
.bj-btn { background: linear-gradient(180deg, #1c2740, #121a2c); border: 1px solid #b8932f; color: #d4af37; padding: 8px 14px; border-radius: 8px; font-weight: 700; font-size: 12px; letter-spacing: 0.08em; cursor: pointer; }
.bj-btn:disabled { opacity: 0.35; cursor: not-allowed; }
.bj-btn-primary { background: linear-gradient(180deg, #d4af37, #b8932f); color: #1a1305; border-color: #d4af37; }


.player-casino-badge { margin-left: 6px; font-size: 12px; color: #d4af37; }

/* .bj-history* migrated to client/src/components/casino/CasinoHistory.module.css
   (slice 15 — Casino cluster, component 2). */

/* ===== Casino card animations ===== */

@keyframes bj-card-enter {
  0%   { opacity: 0; transform: translate3d(0, -80px, 0) rotate(-12deg) scale(0.85); }
  60%  { opacity: 1; transform: translate3d(0, 4px, 0) rotate(2deg) scale(1.02); }
  100% { opacity: 1; transform: translate3d(0, 0, 0) rotate(0deg) scale(1); }
}

.bj-card-enter {
  animation: bj-card-enter 220ms cubic-bezier(0.22, 0.85, 0.3, 1) both;
}
.bj-seat-hand-cards .bj-card-enter:nth-child(2),
.bj-dealer-hand .bj-card-enter:nth-child(2) { animation-delay: 60ms; }
.bj-seat-hand-cards .bj-card-enter:nth-child(3),
.bj-dealer-hand .bj-card-enter:nth-child(3) { animation-delay: 120ms; }
.bj-seat-hand-cards .bj-card-enter:nth-child(4),
.bj-dealer-hand .bj-card-enter:nth-child(4) { animation-delay: 180ms; }
.bj-seat-hand-cards .bj-card-enter:nth-child(5),
.bj-dealer-hand .bj-card-enter:nth-child(5) { animation-delay: 240ms; }
.bj-seat-hand-cards .bj-card-enter:nth-child(n+6),
.bj-dealer-hand .bj-card-enter:nth-child(n+6) { animation-delay: 300ms; }

/* Dealer hole-card reveal: a slow flip + linger for suspense. The card
   starts edge-on (scaleX 0), holds a beat, then rotates open. */
@keyframes bj-card-flip {
  0%   { opacity: 0.4; transform: perspective(600px) rotateY(90deg) scale(0.95); }
  25%  { opacity: 0.6; transform: perspective(600px) rotateY(90deg) scale(0.95); }
  60%  { opacity: 1;   transform: perspective(600px) rotateY(-12deg) scale(1.04); }
  80%  { opacity: 1;   transform: perspective(600px) rotateY(6deg)   scale(1.02); }
  100% { opacity: 1;   transform: perspective(600px) rotateY(0deg)   scale(1); }
}

.bj-card-flip {
  animation: bj-card-flip 900ms cubic-bezier(0.22, 0.85, 0.3, 1) both;
  transform-origin: center center;
  backface-visibility: hidden;
}

@keyframes bj-shake {
  0%, 100% { transform: translate3d(0, 0, 0); }
  20%      { transform: translate3d(-2px, 0, 0); }
  40%      { transform: translate3d(2px, 0, 0); }
  60%      { transform: translate3d(-2px, 0, 0); }
  80%      { transform: translate3d(2px, 0, 0); }
}

.bj-shake {
  animation: bj-shake 250ms ease-in-out;
}

@media (prefers-reduced-motion: reduce) {
  .bj-card-enter,
  .bj-card-flip,
  .bj-shake { animation: none !important; }
}

/* Leave-seat × button on your own seat */
.bj-seat-leave {
  background: rgba(239, 68, 68, 0.18);
  border: 1px solid rgba(239, 68, 68, 0.5);
  border-radius: 4px;
  color: #fca5a5;
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
  padding: 1px 5px;
  cursor: pointer;
  border-radius: 4px;
}
.bj-seat-leave:hover { color: #ef4444; background: rgba(239, 68, 68, 0.15); }

/* Per-seat outcome banner shown during the 3s settle window. Pops over
   the seat so the cards remain visible underneath. */
.bj-outcome {
  position: absolute;
  left: 6px;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 8px;
  border-radius: 8px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-align: center;
  z-index: 3;
  pointer-events: none;
  backdrop-filter: blur(2px);
  animation: bj-outcome-pop 240ms cubic-bezier(0.2, 0.85, 0.3, 1) both;
}
@keyframes bj-outcome-pop {
  0%   { opacity: 0; transform: translateY(-50%) scale(0.85); }
  60%  { opacity: 1; transform: translateY(-50%) scale(1.06); }
  100% { opacity: 1; transform: translateY(-50%) scale(1); }
}
.bj-outcome-label { font-size: 13px; }
.bj-outcome-delta { font-size: 18px; font-variant-numeric: tabular-nums; }
.bj-outcome-win {
  background: linear-gradient(180deg, rgba(34, 197, 94, 0.85), rgba(22, 163, 74, 0.85));
  color: #f0fdf4;
  border: 1.5px solid #bbf7d0;
  box-shadow: 0 0 22px rgba(34, 197, 94, 0.5);
}
.bj-outcome-loss {
  background: linear-gradient(180deg, rgba(239, 68, 68, 0.85), rgba(185, 28, 28, 0.85));
  color: #fef2f2;
  border: 1.5px solid #fca5a5;
  box-shadow: 0 0 22px rgba(239, 68, 68, 0.5);
}
.bj-outcome-push {
  background: linear-gradient(180deg, rgba(148, 163, 184, 0.85), rgba(100, 116, 139, 0.85));
  color: #f8fafc;
  border: 1.5px solid #cbd5e1;
  box-shadow: 0 0 22px rgba(148, 163, 184, 0.4);
}
@media (prefers-reduced-motion: reduce) {
  .bj-outcome { animation: none; }
}

/* .bj-page* (standalone blackjack page) migrated to
   client/src/pages/BlackjackTable.module.css (slice 12 CSS co-location). */
/* Auth-page secondary links (F-013) — preserve visited link convention.
   Unvisited = muted purple-gray; visited = slightly desaturated lavender
   so the user can tell what they've already tried (forgot password vs
   create account). */
.auth-secondary-link {
  color: #a09ec0;
  text-decoration: underline;
}
.auth-secondary-link:visited {
  color: #8c8aa8;
}
.auth-secondary-link:hover {
  color: #c4c2dd;
}

/* =========================================================================
   Sound Packs (Phase 2 of custom-sound-packs feature)
   ========================================================================= */

.sound-packs-page {
  padding: 24px;
  margin: 0 auto;
  color: #ffffff;
}
.sound-packs-page__header h1 {
  margin: 0 0 6px;
  font-size: 1.6rem;
}
.sound-packs-page__intro {
  color: #a9a6c4;
  font-size: 0.9rem;
  margin: 0 0 16px;
  max-width: 720px;
}
.sound-packs-page__usage {
  color: #a9a6c4;
  font-size: 0.85rem;
  margin-bottom: 16px;
}
.sound-packs-page__error {
  background: rgba(220, 80, 80, 0.15);
  border: 1px solid rgba(220, 80, 80, 0.4);
  color: #ffd0d0;
  padding: 10px 12px;
  border-radius: 6px;
  margin: 8px 0;
  font-size: 0.9rem;
}
.sound-packs-page__list {
  margin-top: 8px;
}
.sound-packs-page__list-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}
.sound-packs-page__list-header h2 {
  margin: 0;
  font-size: 1.1rem;
}
.sound-packs-page__create {
  background: #f97316;
  color: #1a1530;
  border: none;
  border-radius: 6px;
  padding: 8px 14px;
  font-weight: 600;
  cursor: pointer;
}
.sound-packs-page__create:hover { filter: brightness(1.05); }
.sound-packs-page__create-form {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}
.sound-packs-page__create-form input[type="text"] {
  flex: 1;
  background: rgba(255,255,255,0.04);
  border: 1px solid #453d5b;
  border-radius: 6px;
  padding: 8px 12px;
  color: #ffffff;
  font-size: 0.9rem;
}
.sound-packs-page__create-form button {
  background: #f97316;
  color: #1a1530;
  border: none;
  border-radius: 6px;
  padding: 8px 14px;
  font-weight: 600;
  cursor: pointer;
}
.sound-packs-page__empty {
  color: #a9a6c4;
  padding: 16px;
  border: 1px dashed #453d5b;
  border-radius: 8px;
  text-align: center;
}
.sound-packs-page__pack-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 8px;
}
.sound-packs-page__pack {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 12px;
  align-items: center;
  background: rgba(20,24,40,0.7);
  border: 1px solid #2e2945;
  border-radius: 8px;
  padding: 12px 14px;
}
.sound-packs-page__pack[data-selected="true"] {
  border-color: #f97316;
}
.sound-packs-page__pack-select {
  background: none;
  border: none;
  color: inherit;
  text-align: left;
  cursor: pointer;
  padding: 0;
  display: grid;
  gap: 2px;
}
.sound-packs-page__pack-name {
  font-weight: 600;
  font-size: 1rem;
}
.sound-packs-page__pack-meta {
  color: #a9a6c4;
  font-size: 0.8rem;
}
.sound-packs-page__pack-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}
.sound-packs-page__pack-actions button {
  background: rgba(255,255,255,0.06);
  color: #ffffff;
  border: 1px solid #453d5b;
  border-radius: 6px;
  padding: 6px 10px;
  font-size: 0.8rem;
  cursor: pointer;
}
.sound-packs-page__pack-actions button:hover {
  background: rgba(255,255,255,0.1);
}
.sound-packs-page__delete:hover {
  background: rgba(220, 80, 80, 0.2) !important;
  border-color: rgba(220, 80, 80, 0.5) !important;
}
.sound-packs-page__active-toggle {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 0.8rem;
  color: #a9a6c4;
  cursor: pointer;
}
.sound-packs-page__active-toggle input[type="checkbox"] {
  accent-color: #f97316;
}
.sound-packs-page__editor {
  margin-top: 24px;
  background: rgba(20,24,40,0.5);
  border: 1px solid #2e2945;
  border-radius: 8px;
  padding: 16px;
}
.sound-packs-page__editor h2 {
  margin: 0 0 12px;
  font-size: 1rem;
  color: #f97316;
}

/* Editor (grid + meter) */
.sound-pack-editor__loading,
.sound-pack-editor__error {
  padding: 12px;
  color: #a9a6c4;
}
.sound-pack-editor__meter {
  margin-bottom: 16px;
}
.sound-pack-editor__meter-label {
  font-size: 0.8rem;
  color: #a9a6c4;
  margin-bottom: 4px;
}
.sound-pack-editor__meter-bar {
  height: 6px;
  background: rgba(255,255,255,0.06);
  border-radius: 3px;
  overflow: hidden;
}
.sound-pack-editor__meter-fill {
  height: 100%;
  background: #5a8dee;
  transition: width 200ms ease;
}
.sound-pack-editor__group {
  margin-bottom: 18px;
}
.sound-pack-editor__group-title {
  font-size: 0.85rem;
  color: #a9a6c4;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 0 0 8px;
}
.sound-pack-editor__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 8px;
}
.sound-pack-editor__cell {
  background: rgba(20,24,40,0.6);
  border: 1px solid #2e2945;
  border-radius: 6px;
  padding: 10px;
  display: grid;
  gap: 6px;
}
.sound-pack-editor__cell[data-state="busy"] {
  opacity: 0.6;
}
.sound-pack-editor__cell-name {
  font-weight: 600;
  font-size: 0.9rem;
}
.sound-pack-editor__cell-binding {
  color: #a9a6c4;
  font-size: 0.75rem;
}
.sound-pack-editor__cell-preview {
  width: 100%;
  height: 32px;
}
.sound-pack-editor__cell-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}
.sound-pack-editor__upload {
  background: rgba(255,255,255,0.06);
  border: 1px solid #453d5b;
  border-radius: 6px;
  padding: 6px 10px;
  font-size: 0.8rem;
  cursor: pointer;
  color: #ffffff;
  display: inline-block;
}
.sound-pack-editor__upload input[type="file"] {
  display: none;
}
.sound-pack-editor__clear {
  background: rgba(255,255,255,0.06);
  border: 1px solid #453d5b;
  border-radius: 6px;
  padding: 6px 10px;
  font-size: 0.8rem;
  cursor: pointer;
  color: #ffffff;
}
.sound-pack-editor__clear:hover {
  background: rgba(220, 80, 80, 0.2);
  border-color: rgba(220, 80, 80, 0.5);
}
.sound-pack-editor__cell-error {
  color: #ffb0b0;
  font-size: 0.75rem;
}

/* Record button (used inside the editor cells) */
.sound-record {
  display: inline-block;
}
.sound-record__label {
  font-size: 0.75rem;
  color: #a9a6c4;
  margin-bottom: 2px;
}
.sound-record__primary {
  background: #f97316;
  color: #1a1530;
  border: none;
  border-radius: 6px;
  padding: 6px 10px;
  font-weight: 600;
  font-size: 0.8rem;
  cursor: pointer;
}
.sound-record__primary:disabled { opacity: 0.5; cursor: not-allowed; }
.sound-record__stop {
  background: #dc4545;
  color: #ffffff;
  border: none;
  border-radius: 6px;
  padding: 6px 10px;
  font-weight: 600;
  font-size: 0.8rem;
  cursor: pointer;
}
.sound-record__review {
  display: inline-flex;
  flex-direction: column;
  gap: 4px;
}
.sound-record__review audio {
  height: 28px;
  max-width: 200px;
}
.sound-record__review-actions {
  display: flex;
  gap: 4px;
}
.sound-record__retake,
.sound-record__retry {
  background: rgba(255,255,255,0.06);
  border: 1px solid #453d5b;
  border-radius: 6px;
  padding: 4px 8px;
  font-size: 0.75rem;
  cursor: pointer;
  color: #ffffff;
}
.sound-record__commit {
  background: #5cb85c;
  color: #1a1530;
  border: none;
  border-radius: 6px;
  padding: 4px 8px;
  font-weight: 600;
  font-size: 0.75rem;
  cursor: pointer;
}
.sound-record__error {
  color: #ffb0b0;
  font-size: 0.75rem;
  max-width: 200px;
}

/* Dark-themed audio player — match cell background, drop the gray native pill.
   Webkit (Chrome/Edge/Safari) honors these pseudo-selectors; Firefox keeps a
   slightly different look but at least matches the panel tone. */
.sound-pack-editor__cell-preview,
.sound-record__review audio {
  width: 100%;
  height: 32px;
  border-radius: 6px;
  background: rgba(255,255,255,0.06);
  color-scheme: dark;
}
.sound-pack-editor__cell-preview::-webkit-media-controls-panel,
.sound-record__review audio::-webkit-media-controls-panel {
  background: rgba(255,255,255,0.04);
}
.sound-pack-editor__cell-preview::-webkit-media-controls-current-time-display,
.sound-pack-editor__cell-preview::-webkit-media-controls-time-remaining-display {
  color: #a9a6c4;
}

/* Dark-themed select — replaces the native gray Windows control with the
   project's dark surface + accent border style. Used by /sound-packs page
   and Designer Sounds tab. */
.sounds-tab__select {
  background: rgba(20,24,40,0.9);
  color: #ffffff;
  border: 1px solid #453d5b;
  border-radius: 6px;
  padding: 6px 28px 6px 10px;
  font-size: 0.85rem;
  cursor: pointer;
  min-width: 180px;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='%23a9a6c4'><path d='M1 1l5 5 5-5'/></svg>");
  background-repeat: no-repeat;
  background-position: right 8px center;
  background-size: 10px;
  color-scheme: dark;
}
.sounds-tab__select:hover {
  background-color: rgba(20,24,40,1);
  border-color: #5a4f74;
}
.sounds-tab__select:focus {
  outline: none;
  border-color: #f97316;
}
.sounds-tab__select option {
  background: #14182a;
  color: #ffffff;
}

/* Override-bound cell gets a subtle accent ring so the eye finds it
   immediately in a 33-cell grid. */
.sound-pack-editor__cell[data-has-override="true"] {
  border-color: #f97316;
  background: rgba(249,115,22,0.06);
}
.sounds-tab__binding-tag {
  display: inline-block;
  background: rgba(249,115,22,0.18);
  color: #f97316;
  font-size: 0.65rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 1px 6px;
  border-radius: 4px;
  margin-right: 4px;
  vertical-align: middle;
}

.sounds-tab__borrowed {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 16px;
}
.sounds-tab__borrowed-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  background: rgba(249,115,22,0.08);
  border: 1px solid rgba(249,115,22,0.4);
  border-radius: 8px;
  padding: 10px 12px;
}
.sounds-tab__borrowed-text {
  flex: 1;
  color: #e5e3f0;
  font-size: 0.85rem;
  line-height: 1.35;
}
.sounds-tab__borrowed-button {
  background: #f97316;
  color: #1a1530;
  border: none;
  border-radius: 6px;
  padding: 8px 14px;
  font-weight: 600;
  font-size: 0.85rem;
  cursor: pointer;
  white-space: nowrap;
}
.sounds-tab__borrowed-button:hover { filter: brightness(1.05); }
.sounds-tab__borrowed-button:disabled {
  background: rgba(255,255,255,0.06);
  color: #a9a6c4;
  cursor: not-allowed;
  filter: none;
}
.sounds-tab__borrowed-error {
  flex-basis: 100%;
  color: #ffb0b0;
  font-size: 0.75rem;
  margin-top: 4px;
}

/* RoomSoundModeToggle — host-only lobby pill group for picking the room's
   custom-sound mode for the upcoming game. */
.room-sound-mode {
  background: rgba(20,24,40,0.7);
  border: 1px solid #2e2945;
  border-radius: 8px;
  padding: 10px 12px;
  margin-top: 8px;
}
.room-sound-mode__label {
  font-size: 0.75rem;
  color: #a9a6c4;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 6px;
}
.room-sound-mode__options {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 6px;
}
.room-sound-mode__option {
  flex: 1;
  background: rgba(255,255,255,0.06);
  color: #ffffff;
  border: 1px solid #453d5b;
  border-radius: 6px;
  /* Bumped from 6px 8px — descenders in "packs"/"pack" were sitting flush
     against the bottom border when the label wrapped to a 2nd line.
     Extra bottom padding + line-height: 1.3 give the descenders room. */
  padding: 8px 8px 10px;
  line-height: 1.3;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
}
.room-sound-mode__option:hover { background: rgba(255,255,255,0.1); }
.room-sound-mode__option[data-selected="true"] {
  background: rgba(249,115,22,0.18);
  border-color: #f97316;
  color: #f97316;
}
.room-sound-mode__description {
  font-size: 0.75rem;
  color: #a9a6c4;
}

/* .site-footer* migrated to client/src/components/Layout.module.css
   (slice 13 CSS co-location). The footer carries a data-site-footer hook so
   useChromeHeight still finds it now that its class is hashed. */

/* Onboarding nudge — shown on /sound-packs when the user has zero packs.
   Three pathway cards: Install Classic / Browse / Create from scratch. */
.sound-packs-page__onboard {
  margin: 8px 0 16px;
  padding: 18px;
  background: rgba(20,24,40,0.5);
  border: 1px solid #2e2945;
  border-radius: 10px;
}
.sound-packs-page__onboard-title {
  margin: 0 0 14px;
  font-size: 1rem;
  color: #f97316;
}
.sound-packs-page__onboard-grid {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.sound-packs-page__onboard-card {
  background: rgba(20,24,40,0.8);
  border: 1px solid #2e2945;
  border-radius: 8px;
  padding: 14px;
  display: grid;
  gap: 8px;
}
.sound-packs-page__onboard-card-name {
  font-weight: 600;
  font-size: 0.95rem;
}
.sound-packs-page__onboard-card-body {
  color: #a9a6c4;
  font-size: 0.82rem;
  line-height: 1.45;
}
.sound-packs-page__onboard-button {
  background: #f97316;
  color: #1a1530;
  border: none;
  border-radius: 6px;
  padding: 8px 12px;
  font-weight: 600;
  font-size: 0.85rem;
  cursor: pointer;
  display: inline-block;
}
.sound-packs-page__onboard-button:hover { filter: brightness(1.05); }
.sound-packs-page__onboard-button:disabled { opacity: 0.5; cursor: not-allowed; }

/* Market Mayhem — ×factor label on property tiles.
   Rendered by Space.tsx whenever state.market.rentMultiplier !== 1.
   Sits just outside the color band and faces out from the board. */
.space-mayhem-badge {
  position: absolute;
  top: calc(22% + clamp(2px, 1.8cqmin, 4px));
  left: 50%;
  /* Sit above the color band (z-index:1). Without this the badge is painted
     beneath the band on the two rails where the band hugs the badge's corner
     (bottom rail → band at top, left rail → band at right), so it vanished. */
  z-index: 3;
  box-sizing: border-box;
  min-width: clamp(26px, 31cqmin, 42px);
  max-width: calc(100% - 10px);
  padding: clamp(1px, 1.1cqmin, 2px) clamp(3px, 3cqmin, 6px);
  font-family: var(--font-mono);
  font-size: clamp(7px, 8cqmin, 11px);
  font-weight: 700;
  line-height: 1;
  text-align: center;
  white-space: nowrap;
  color: var(--surface);
  background: var(--accent);
  border-radius: 3px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.18),
    0 1px 4px rgba(0, 0, 0, 0.42);
  pointer-events: none;
  letter-spacing: 0;
  transform: translateX(-50%);
}
.space.top .space-mayhem-badge {
  top: auto;
  bottom: calc(22% + clamp(2px, 1.8cqmin, 4px));
  transform: translateX(-50%);
}
.space.left .space-mayhem-badge {
  top: 50%;
  right: auto;
  bottom: auto;
  left: auto;
  right: calc(22% + clamp(2px, 1.8cqmin, 4px));
  transform: translateY(-50%) rotate(90deg);
  transform-origin: center;
}
.space.right .space-mayhem-badge {
  top: 50%;
  bottom: auto;
  left: calc(22% + clamp(2px, 1.8cqmin, 4px));
  transform: translateY(-50%) rotate(-90deg);
  transform-origin: center;
}
.space-mayhem-badge.down {
  background: var(--success);
}
