/* spades-game.css — lobby and table layout for spades.gameshack.org
   (adapted from hearts-game.css; Spades-specific additions at the end) */

/* Optional "Hide top header" setting — hides the SHARED site header/nav
   (from header.php, shared by all GameShack games) via a rule that
   only exists in this stylesheet, which only loads on Spades' own
   pages. Never touches header.php itself, so this has zero effect on
   any other game. */
body.spades-hide-header .site-header,
body.spades-hide-header .site-nav {
  display: none !important;
}

/* Match the shared paper background on <html> itself, so any sliver below
   a short page (viewport taller than content) doesn't show browser-default
   white instead of the site's cream. */
html {
  background: var(--paper);
}

.table-page {
  max-width: 900px;
  margin: 0 auto;
  padding: 0;
}

.is-hidden {
  display: none !important;
}

/* Name entry */
.name-entry {
  max-width: 320px;
  margin: 2rem auto;
  text-align: center;
}
.name-entry input {
  display: block;
  width: 100%;
  margin: 0.5rem 0 1rem;
  padding: 0.7rem 0.85rem;
  font-size: 1rem;
  border: 1px solid rgba(24, 43, 58, 0.25);
  border-radius: 4px;
}

.name-entry button,
.modal__inner button {
  background: var(--gold);
  color: var(--navy);
  border: none;
  border-radius: 4px;
  padding: 0.65rem 1.4rem;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  transition: filter 0.15s ease;
}
.name-entry button:hover,
.modal__inner button:hover {
  filter: brightness(0.92);
}

/* Full-bleed green table — spans the entire viewport edge-to-edge and
   fills the space between header and footer, same technique as the
   lobby's green band. Seats, trick area, AND the player's own hand all
   live inside this one continuous zone. */
.table-wrap {
  width: 100vw;
  position: relative;
  left: 50%;
  right: 50%;
  margin-left: -50vw;
  margin-right: -50vw;
  margin-top: -2.5rem;
  margin-bottom: -4rem;
  background: #1B4332;
  padding: 1rem 1.5rem 1.5rem;
  min-height: calc(100vh - 160px); /* tightened from 200px to reclaim some vertical room */
  display: flex;
  flex-direction: column;
}

/* Table top bar — join code (so a returning player can note it down
   and rejoin later via the lobby's "Join Game" form) and a way to
   actually leave. Leaving doesn't end or delete the game — state just
   persists in PocketBase and resumes automatically when this same code
   is opened again, so this doubles as the "suspend" mechanism. */
.table-topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  color: #fff;
  font-size: 0.85rem;
  margin-bottom: 0.5rem;
  opacity: 0.85;
}
.table-topbar__code strong {
  color: #ffe9b3;
  letter-spacing: 0.05em;
}
.table-topbar__actions {
  display: flex;
  align-items: center;
  gap: 1rem;
}
.table-topbar__leave {
  color: #fff;
  text-decoration: underline;
}
.table-topbar__leave:hover {
  color: #ffe9b3;
}
.table-topbar__cancel {
  background: none;
  border: none;
  color: #ffb3b3;
  text-decoration: underline;
  font-size: 0.85rem;
  cursor: pointer;
  padding: 0;
}
.table-topbar__cancel:hover {
  color: #ff8a8a;
}

/* Scoreboard */
.scoreboard {
  /* Now nested inside .table-topbar, which sets a smaller font-size and
     reduced opacity for its own code/actions text — reset both
     explicitly here so scores stay clearly legible rather than
     inheriting that dimmer styling. */
  display: flex;
  justify-content: center;
  gap: 1.2rem;
  flex-wrap: wrap;
  font-size: 0.95rem;
  font-weight: 600;
  color: #fff;
  opacity: 1;
}

/* Table felt + seats — now includes the hand row as its bottom grid row */
.table-felt {
  position: relative;
  flex: 1;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: auto auto auto;
  align-content: center;
  gap: 0.5rem;
  /* Widened from 900px — that cap was confining the left/right seats to
     a narrow strip regardless of how wide the actual window was,
     leaving a lot of unused green on both sides on wider screens. The
     trick area stays centered either way (it's absolutely positioned
     within .table-middle-zone, which spans the full felt width), so
     widening this just gives the side seats genuine room to spread out
     at full card size instead of needing to shrink to fit. */
  max-width: 1300px;
  margin: 0 auto;
  width: 100%;
}

.seat {
  color: #fff;
  text-align: center;
  padding: 0.5rem;
}
.seat--top    { grid-column: 2; grid-row: 1; }

/* Small hero graphic in row 1's otherwise-empty first column — the top
   seat only occupies the center column, leaving the columns beside it
   in that same row unused. Placed here rather than in the topbar (too
   short to fit the artwork legibly) or anywhere that would need to grow
   a row's height (which would push hands down) — this space was already
   reserved by the top seat's own height, doing double duty at no cost. */
.table-felt__hero {
  grid-column: 1;
  grid-row: 1;
  align-self: center;
  justify-self: start;
  /* Matched to roughly how wide the same logo renders on gameshack.org's
     own landing-page card — that version is fluid (100% of its card's
     width, which itself resizes with the grid), so there's no exact
     fixed match, but ~210px is close to its typical size on a normal
     desktop window with 5 games in the grid.
     Set as a direct width, not width:100%/max-width — percentage-width
     sizing on a grid item with justify-self other than stretch can
     resolve inconsistently, which is likely why bumping max-width alone
     didn't visibly change anything. */
  width: 210px;
  height: auto;
  /* No border-radius/opacity dimming needed now that the artwork has a
     real transparent background — the cards + lettering sit directly
     on the green felt the same way every other card-shaped element on
     the table does, rather than looking like a box laid on top of it. */
}

/* Middle zone: left seat, trick area, right seat. Given its own
   min-height matching the trick area's own size, guaranteeing enough
   room regardless of how tall the side seats' own content (piles,
   hand-stacks) happens to be at any given moment — previously the trick
   area centered within the WHOLE table-felt box, whose height was only
   as tall as its actual content needed, so when that was short the
   trick area's centered position pushed its bottom edge down into
   where the hand row renders, covering played cards. */
.table-middle-zone {
  grid-column: 1 / span 3;
  grid-row: 2;
  position: relative;
  min-height: 330px;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  align-items: center;
}
.seat--left   { grid-column: 1; }
.seat--right  { grid-column: 3; }

.seat__name.is-turn,
.my-seat-name.is-turn {
  color: #ffd54f;
  font-weight: 700;
}

.seat__points {
  font-size: 0.85rem;
  color: #ffe9b3;
  opacity: 0.9;
}

/* Belt-and-suspenders: pin the color on the player's own points line
   directly by ID, in case something else in the cascade (shared site
   styles, a more specific ancestor rule) was winning over the shared
   .seat__points class for this particular instance. */
#mySeatPoints {
  color: #ffe9b3 !important;
}

/* Row (top seat: hand-left, info-middle, tricks-right) vs column
   (left/right seats: hand-above, info-middle, tricks-below) layouts. */
.seat__row {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.seat__col {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
}
.seat__info {
  text-align: center;
}

.stack-group {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.stack-label {
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #ffe9b3;
  opacity: 0.85;
  margin-bottom: 0.2rem;
}

.my-seat-name-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  margin-bottom: 0.4rem;
}

/* Hand + tricks-won pile side by side, rather than stacked — the pile
   can grow to a full card's height once tricks are won, and stacking
   it above the fan was costing significant vertical space that's in
   short supply on shorter screens. */
.my-hand-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
}
.my-hand-row__center {
  flex: 1;
  min-width: 0; /* lets the fan's own overflow-x:auto scroll correctly inside a flex child */
}

/* Opponent fans — each opponent's hand as a fan of card backs, one per
   card they hold, so it visibly shrinks as they play. Smaller than your
   own cards (they're across the table). The top seat fans
   horizontally; the left and right seats hold theirs sideways, facing
   the middle of the table, with an arc around a pivot near the edge of
   the cards farthest from the middle (where the holder's hand is).
   Sizes are set by variables so each breakpoint only changes numbers:
   --ow/--oh card width/height, --step overlap step, --fan-deg arc per card. */
.opp-fan {
  /* Desktop: 70% of your own 108x157 cards. (iPad and phone set their
     own, smaller values below.) */
  --ow: 76px;
  --oh: 110px;
  --step: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* The outer box is sized for a full 13-card hand, so the seat's layout
   never shifts as the fan closes up. */
.opp-fan--top {
  width: calc(var(--ow) + 12 * var(--step) + 48px);
  height: calc(var(--oh) + 16px);
}
.opp-fan--left,
.opp-fan--right {
  width: calc(var(--oh) + 16px);
  height: calc(var(--ow) + 12 * var(--step) + 48px);
}

.opp-fan__cards {
  position: relative;
  /* One shadow for the whole fan instead of one per card — far cheaper
     to redraw, which matters most on iPad. */
  filter: drop-shadow(1px 2px 2px rgba(0, 0, 0, 0.35));
}
.opp-fan .card-svg {
  filter: none;
}
.opp-fan__card {
  position: absolute;
  transform: rotate(calc((var(--i) - (var(--n) - 1) / 2) * var(--fan-deg)));
}

/* Top seat: horizontal fan, pivot near the cards' top edge (the
   holder's hand). */
.opp-fan--top {
  --fan-deg: -3deg;
}
.opp-fan--top .opp-fan__cards {
  width: calc(var(--ow) + (var(--n) - 1) * var(--step));
  height: var(--oh);
}
.opp-fan--top .opp-fan__card {
  top: 0;
  left: calc(var(--i) * var(--step));
  width: var(--ow);
  height: var(--oh);
  transform-origin: 50% 15%;
}

/* Left and right seats: sideways fans. Each card's box is landscape and
   the card image inside it is turned 90 degrees. */
.opp-fan--left,
.opp-fan--right {
  --fan-deg: 3deg;
}
.opp-fan--right {
  --fan-deg: -3deg;
}
.opp-fan--left .opp-fan__cards,
.opp-fan--right .opp-fan__cards {
  width: var(--oh);
  height: calc(var(--ow) + (var(--n) - 1) * var(--step));
}
.opp-fan--left .opp-fan__card,
.opp-fan--right .opp-fan__card {
  left: 0;
  top: calc(var(--i) * var(--step));
  width: var(--oh);
  height: var(--ow);
}
.opp-fan--left .opp-fan__card  { transform-origin: 15% 50%; }
.opp-fan--right .opp-fan__card { transform-origin: 85% 50%; }
.opp-fan--left .opp-fan__back,
.opp-fan--right .opp-fan__back {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--ow);
  height: var(--oh);
  transform: translate(-50%, -50%) rotate(90deg);
}
.opp-fan--top .opp-fan__back {
  width: 100%;
  height: 100%;
}

/* Left seat's row runs right-to-left so its fan is on the side nearest
   the middle of the table (the right seat's already is). */
.seat__row--left {
  flex-direction: row-reverse;
}
/* Top seat: name above, fan below it facing the middle. */
.seat__top-hand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
}
/* Keeps the top row's height where the old single card-back stack held
   it, so the table doesn't get shorter at the start of a hand and then
   jump taller when the top seat's first tricks-won pile appears. */
.seat--top .seat__row {
  min-height: 162px;
}

/* Taken-trick pile — an actual card-back image (same size as the main
   .card / hand-stack) with a gold count badge, rather than a plain
   colored box, so it reads as "a stack of cards this seat has won"
   instead of an abstract counter. */
.seat__pile {
  min-height: 24px; /* just enough for the label — was reserving a full
  card's-worth of empty space even before any trick had been won */
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 0.25rem;
}
.taken-pile {
  position: relative;
  width: 108px;
  height: 157px;
}
.taken-pile__back {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  filter: drop-shadow(1px 1px 0 rgba(0,0,0,0.3)) drop-shadow(2px 2px 0 rgba(0,0,0,0.15));
}
.taken-pile__count {
  position: absolute;
  bottom: -12px;
  right: -12px;
  background: var(--gold) !important;
  color: var(--navy) !important;
  font-size: 1rem;
  font-weight: 700;
  border-radius: 50%;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 2px rgba(0,0,0,0.4);
}

/* Trick-flyer: a transient clone of a completed trick that takes over
   from the real trick area (same 2x2 layout, same card size, same
   corner classes) so nothing jumps at takeoff. Two steps, driven from
   game.js: the cards slide together into a stack (transition on each
   card), then the stack slides onto the winner's pile
   (.trick-flyer--travel). Stays fully opaque — it lands on the pile
   rather than fading out. */
.trick-flyer {
  position: fixed;
  pointer-events: none;
  z-index: 200;
  transform-origin: center center;
}
.trick-flyer .card--played {
  position: absolute;
  transition: transform 0.2s ease-out;
}
.trick-flyer--travel {
  transition: transform 0.4s ease-in-out;
}

/* A seat's first won trick is still in the air: the pile's spot is laid
   out (so the flyer has an exact target and nothing shifts on arrival)
   but not shown until the cards land. */
.taken-pile--pending {
  visibility: hidden;
}

/* Card-flyer: a single card animating from a player's hand toward the
   trick area the moment it's played. */
.card-flyer {
  position: fixed;
  width: 108px;
  height: 157px;
  pointer-events: none;
  z-index: 200;
  transition: transform 0.5s ease, opacity 0.5s ease;
}
.card-flyer .card-svg {
  width: 100%;
  height: 100%;
}

.trick-area {
  /* Absolutely positioned relative to .table-middle-zone (not a grid
     participant itself), dead-centered within that zone rather than
     sitting in the outer grid's row 2 alongside the left/right seat
     columns. Two problems this solves together: (1) when a seat's
     taken pile first appears (jumping from nothing to a full
     card-height image), that grows its column's height, which used to
     shift the whole trick-area box on the page; (2) .table-middle-zone
     has its own guaranteed min-height matching this box's own size, so
     centering here can never push the trick area's bottom edge down
     into the hand row below when the side columns are short. */
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  /* Fixed 2x2 box (2 cards + a gap, each direction) so each corner has
     a stable place to land, rather than flex-centering cards in
     chronological play order. */
  width: 232px;
  height: 330px;
}

.trick-area .card--played {
  position: absolute;
}
.trick-card--top-left    { top: 0; left: 0; }
.trick-card--top-right   { top: 0; right: 0; }
.trick-card--bottom-left { bottom: 0; left: 0; }
.trick-card--bottom-right { bottom: 0; right: 0; }

.waiting-message {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 100%;
  text-align: center;
  color: #fff;
}
.waiting-message__title {
  font-size: 1.1rem;
  font-weight: 600;
  margin: 0 0 0.3rem;
}
.waiting-message__count {
  color: #ffe9b3;
  margin: 0 0 0.3rem;
}
.waiting-message__names {
  font-size: 0.85rem;
  opacity: 0.8;
  margin: 0;
}

.my-hand-wrap {
  grid-column: 1 / span 3;
  grid-row: 3;
  text-align: center;
  padding-top: 0.25rem;
}

.my-seat-name {
  color: #fff;
  font-size: 1.05rem;
  margin-bottom: 0.25rem;
}

/* Cards — rendered from the shared svg-cards.svg sprite via <use> */
.card {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 108px;
  height: 157px;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
  user-select: none;
  transition: transform 0.1s ease;
}
.card-svg {
  width: 100%;
  height: 100%;
  display: block;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.35));
}
.card--played {
  cursor: default;
}
.card--disabled {
  /* No opacity reduction — in a fan layout, transparent cards let
     whatever's behind them (an adjacent overlapping disabled card, e.g.
     two hearts sitting next to each other) bleed through and blend into
     a muddy double-exposure. Fully opaque + grayscale/darkened conveys
     "disabled" without that artifact, since opaque elements properly
     occlude what's behind them regardless of overlap. */
  filter: grayscale(100%) brightness(0.75);
  cursor: not-allowed;
}
.card--playable {
  box-shadow: 0 0 0 3px rgba(255, 215, 0, 0.55);
  border-radius: 8px;
}
.card--playable:active {
  transform: translateY(-6px);
  z-index: 10;
}

/* Overlapping "fan" layout for the player's own hand, so 13 cards don't
   need 13 full card-widths of horizontal space. flex-wrap: wrap was a
   bug here — if the row ran out of horizontal room, cards would break
   to a second line with broken overlap math (:first-child only zeroes
   the margin on the true first card, not each wrapped row's first
   card), producing a jumbled stair-step instead of a clean fan. nowrap
   + horizontal scroll keeps it a single clean row on any screen width.
   Centered with auto margins on the first and last card rather than
   justify-content: center — if the row ever overflows, auto margins drop
   to zero and it starts at the left edge (scrollable), instead of
   centering and pushing the first cards off-screen where scrolling can't
   reach them. game.js (fitHandFan) also tightens the overlap so a full
   hand fits whenever it reasonably can, via --fit-overlap. */
.my-hand--fan {
  display: flex;
  justify-content: flex-start;
  flex-wrap: nowrap;
  overflow-x: auto;
  /* Top padding matters here, not just cosmetic spacing: setting
     overflow-x to anything but visible forces overflow-y to become
     'auto' too (a CSS behavior, not a bug) — with zero top padding, a
     selected card's translateY(-10px) pop-up had nowhere to go and got
     clipped clean off at the container's own top edge. */
  padding: 16px 1rem 0;
}
.my-hand--fan .card {
  margin-left: var(--fit-overlap, -50px);
  flex-shrink: 0;
}
.my-hand--fan .card:first-child {
  margin-left: auto;
}
.my-hand--fan .card:last-child {
  margin-right: auto;
}

/* Modals */
.modal {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}
.modal__inner {
  background: #fff;
  border-radius: 8px;
  padding: 1.5rem;
  max-width: 480px;
  text-align: center;
}
.modal__inner button,
.modal__inner .btn {
  margin-top: 1rem;
  display: inline-block;
}

/* Per-hand score table shown in the hand-over modal — hand deltas per
   round plus a cumulative Total row, pulled from the actual persisted
   hand records rather than tracked only in memory. */
.score-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 0.75rem;
  font-size: 0.9rem;
}
.score-table th,
.score-table td {
  padding: 0.4rem 0.5rem;
  text-align: center;
  border-bottom: 1px solid rgba(24, 43, 58, 0.12);
}
.score-table th {
  color: var(--navy);
  font-weight: 700;
}
.score-table td:first-child,
.score-table th:first-child {
  text-align: left;
  color: var(--brick);
}
.score-table__total td {
  font-weight: 700;
  color: var(--navy);
  border-top: 2px solid var(--navy);
  border-bottom: none;
}

/* Lobby (index.php) — uses the shared site's --navy/--paper/--gold/--ink/--brick tokens */

/* Full-bleed green: breaks out of the shared <main> max-width container
   so it spans the entire viewport edge-to-edge, not just the content column. */
.game-lobby {
  width: 100vw;
  position: relative;
  left: 50%;
  right: 50%;
  margin-left: -50vw;
  margin-right: -50vw;
  margin-top: -2.5rem;
  margin-bottom: -4rem;
  background: #1B4332;
  padding: 2.5rem 1.5rem;
}

.lobby-card {
  position: relative;
  max-width: 760px;
  margin: 0 auto;
  text-align: center;
  /* Same cream as the Hearts lobby card (sampled from hearts-hero.png),
     kept so the two games' lobbies match. */
  background: #FDF8E6;
  border: 1px solid rgba(24, 43, 58, 0.12);
  border-radius: 8px;
  padding: 2rem 1.75rem;
}

.rules-btn {
  position: absolute;
  top: 1rem;
  right: 1rem;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--gold);
  color: var(--navy);
  border: none;
  font-size: 1.1rem;
  font-weight: 700;
  cursor: pointer;
  transition: filter 0.15s ease;
}
.rules-btn:hover {
  filter: brightness(0.92);
}

.rules-modal__inner {
  max-width: 560px;
  max-height: 85vh;
  overflow-y: auto;
  text-align: left;
  position: relative;
  padding-top: 2.5rem;
}
.rules-modal__inner h2 {
  text-align: center;
  margin-top: 0;
}
.rules-modal__inner h3 {
  color: var(--navy);
  margin-bottom: 0.3rem;
}
.rules-modal__inner p {
  margin-top: 0;
  margin-bottom: 1rem;
  line-height: 1.5;
}
.modal__close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: transparent;
  border: 1px solid rgba(24, 43, 58, 0.25);
  color: var(--navy);
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
}
.modal__close:hover {
  background: rgba(24, 43, 58, 0.08);
}

.lobby-card__logo {
  display: block;
  width: 100%;
  max-width: 100%;
  height: auto;
  margin: 0 auto 1.5rem;
  border-radius: 6px;
}

.lobby-card__tagline {
  color: var(--brick);
  font-size: 1.05rem;
  max-width: 34rem;
  margin: 0.5rem auto 1.5rem;
}

.lobby-columns {
  display: flex;
  align-items: flex-start;
  gap: 2rem;
}

.lobby-section {
  flex: 1 1 0;
}

.lobby-section--join {
  border-left: 1px solid rgba(24, 43, 58, 0.15);
  padding-left: 2rem;
}

@media (max-width: 640px) {
  .lobby-columns {
    flex-direction: column;
  }
  .lobby-section--join {
    border-left: none;
    border-top: 1px solid rgba(24, 43, 58, 0.15);
    padding-left: 0;
    padding-top: 1.5rem;
    width: 100%;
  }
}

.lobby-section h2 {
  margin-top: 0;
}

.lobby-form label,
.lobby-form__label,
.lobby-section label {
  display: block;
  font-weight: 600;
  color: var(--navy);
  margin: 1.25rem 0 0.4rem;
  text-align: left;
}

.lobby-section input[type="text"],
.invite-email-field input {
  width: 100%;
  padding: 0.7rem 0.85rem;
  font-size: 1rem;
  border: 1px solid rgba(24, 43, 58, 0.25);
  border-radius: 4px;
  background: #fff;
  color: var(--ink);
}

.player-count-select {
  width: 100%;
  padding: 0.7rem 0.85rem;
  font-size: 1rem;
  border: 1px solid rgba(24, 43, 58, 0.25);
  border-radius: 4px;
  background: #fff;
  color: var(--ink);
  appearance: auto;
}

.lobby-form__hint {
  font-size: 0.85rem;
  color: var(--brick);
  margin: 0.4rem 0 0;
  text-align: left;
}

.invite-emails {
  margin: 1.25rem 0 0.5rem;
  text-align: left;
}
.invite-email-field {
  margin-bottom: 0.9rem;
}
.invite-email-field label {
  margin: 0 0 0.35rem;
}

/* Buttons — gold accent, matching the site's hover/active convention */
.lobby-section button,
.btn {
  background: var(--gold);
  color: var(--navy);
  border: none;
  border-radius: 4px;
  padding: 0.75rem 1.5rem;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  margin-top: 1.5rem;
  width: 100%;
  transition: filter 0.15s ease;
}
.lobby-section button:hover,
.btn:hover {
  filter: brightness(0.92);
}
.lobby-section button:disabled {
  background: rgba(232, 169, 59, 0.4);
  cursor: not-allowed;
}

.btn {
  display: inline-block;
  text-decoration: none;
  width: auto;
}

.game-over-actions {
  display: flex;
  gap: 0.75rem;
  justify-content: center;
  flex-wrap: wrap;
}
.game-over-actions .btn {
  margin-top: 0;
}
.btn--secondary {
  background: transparent;
  color: var(--navy);
  border: 1px solid rgba(24, 43, 58, 0.3);
}
.btn--secondary:hover {
  background: rgba(24, 43, 58, 0.06);
}
.game-over-actions .btn:disabled {
  background: rgba(232, 169, 59, 0.4);
  cursor: not-allowed;
}

.lobby-section form {
  display: flex;
  flex-direction: column;
}

.game-created-result {
  max-width: 460px;
  margin: 1.5rem auto 0;
  text-align: center;
  background: var(--paper);
  border: 1px solid rgba(24, 43, 58, 0.12);
  border-radius: 8px;
  padding: 2rem 1.75rem;
}

/* "Your Games" — locally-remembered games this browser can rejoin. */
/* "Rejoin Games" — now a sub-section within the Join Game column rather
   than its own standalone card, so it just needs spacing/heading style,
   not a full card background/border of its own. */
.my-games {
  margin-top: 1.75rem;
  padding-top: 1.25rem;
  border-top: 1px solid rgba(24, 43, 58, 0.15);
  text-align: left;
}
.my-games h3 {
  margin: 0 0 0.6rem;
  font-size: 0.95rem;
  color: var(--navy);
}
.my-games__item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.6rem 0.75rem;
  margin-bottom: 0.5rem;
  background: #fff;
  border: 1px solid rgba(24, 43, 58, 0.15);
  border-radius: 4px;
}
.my-games__item:hover {
  filter: brightness(0.96);
}
.my-games__item:last-child {
  margin-bottom: 0;
}
.my-games__link {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  text-decoration: none;
  flex: 1;
  cursor: pointer;
}
.my-games__code {
  font-weight: 700;
  letter-spacing: 0.1em;
  color: #fff;
  background: #1B4332;
  border: 1px solid #1B4332;
  border-radius: 4px;
  padding: 0.3rem 0.7rem;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.my-games__link:hover .my-games__code {
  background: #24573f;
  border-color: #24573f;
}
.my-games__date {
  font-size: 0.8rem;
  color: var(--brick);
}
.my-games__cancel {
  background: #fff;
  border: 1px solid rgba(24, 43, 58, 0.25);
  color: var(--brick);
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  padding: 0.4rem 0.8rem;
  margin-left: 0.5rem;
  border-radius: 4px;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.my-games__cancel:hover {
  background: #fdeceb;
  border-color: #c0392b;
  color: #c0392b;
}

.join-code {
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  color: var(--navy);
  background: #fff;
  border-radius: 4px;
  padding: 0.5rem 1rem;
  display: inline-block;
  margin: 0.75rem 0;
}

.copy-link-btn {
  display: inline-block;
  background: #fff;
  color: var(--navy);
  border: 1px solid rgba(24, 43, 58, 0.3);
  border-radius: 4px;
  padding: 0.5rem 1.1rem;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  margin: 0 0 0.75rem;
  transition: filter 0.15s ease;
}
.copy-link-btn:hover {
  filter: brightness(0.96);
}
.copy-link-btn:disabled {
  color: var(--brick);
  cursor: default;
}

/* Tablet (iPad portrait/landscape and similar ~641–1024px widths): the
   640px-only mobile tier below doesn't catch these, so a full 13-card
   hand at desktop size (888px wide) doesn't fit an iPad's viewport
   without horizontal scrolling. Sized so 13 overlapping cards land
   around 660px wide — comfortably inside an iPad's content area. */
@media (min-width: 641px) and (max-width: 1024px) {
  .table-felt__hero {
    width: 145px;
  }
  .card {
    width: 90px;
    height: 131px;
  }
  .taken-pile {
    width: 90px;
    height: 131px;
  }
  .card-flyer {
    width: 90px;
    height: 131px;
  }
  .my-hand--fan .card {
    margin-left: var(--fit-overlap, -42px);
  }
  .taken-pile__count {
    width: 24px;
    height: 24px;
    font-size: 0.75rem;
    bottom: -9px;
    right: -9px;
  }
  .opp-fan {
    --ow: 54px;
    --oh: 79px;
    --step: 10px;
  }
  .seat--top .seat__row {
    min-height: 150px;
  }
  .trick-area {
    width: 192px;
    height: 274px;
  }
  .table-middle-zone {
    min-height: 274px;
  }
}

/* Mobile: cards at 60% of desktop size (a 40% reduction), scaling every
   card-related dimension together — the base card, hand-stacks, taken
   piles, both flyer animations, the fan overlap, and the badge — so
   proportions stay consistent rather than just shrinking the card. */
@media (max-width: 640px) {
  .table-felt__hero {
    display: none; /* no real room for it at phone width */
  }
  .card {
    width: 72px;
    height: 104px;
  }
  .taken-pile {
    width: 72px;
    height: 104px;
  }
  .card-flyer {
    width: 72px;
    height: 104px;
  }
  .my-hand--fan .card {
    margin-left: var(--fit-overlap, -34px);
  }
  .taken-pile__count {
    width: 19px;
    height: 19px;
    font-size: 0.6rem;
    bottom: -7px;
    right: -7px;
  }
  .opp-fan {
    --ow: 43px;
    --oh: 62px;
    --step: 8px;
  }
  .seat--top .seat__row {
    min-height: 108px;
  }
  .seat__pile {
    min-height: 24px; /* unchanged — still just enough for the empty-pile case */
  }
  .trick-area {
    width: 154px;
    height: 218px;
  }
  .table-middle-zone {
    min-height: 218px;
  }
}

/* Chat — adapted from Rummy's rummy_chat implementation. Now a normal
   inline item in the topbar (next to Leave Table) rather than a
   viewport-fixed floating bubble — the fixed version overlapped the
   shared site header above the green table surface. Only shown when
   there are 2+ human seats (chatting with just yourself + bots isn't
   useful). */
.chat-toggle-btn {
  position: relative;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1px solid var(--gold);
  background: transparent;
  color: #fff;
  font-size: 0.9rem;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
}
.chat-toggle-btn:hover {
  background: var(--gold);
  color: var(--navy);
}

.chat-badge {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 16px;
  height: 16px;
  padding: 0 3px;
  border-radius: 8px;
  background: #c0392b;
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

.chat-panel {
  /* Absolute relative to .table-wrap (position:relative), not fixed to
     the viewport — keeps it anchored inside the green table surface
     itself rather than floating over the page. */
  position: absolute;
  top: 60px;
  right: 20px;
  width: 300px;
  max-width: calc(100vw - 32px);
  height: 380px;
  max-height: calc(100% - 80px);
  background: var(--paper);
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  z-index: 95;
}

.chat-panel__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--navy);
  color: #fff;
  padding: 10px 14px;
  font-weight: 700;
  cursor: grab;
  user-select: none;
  touch-action: none; /* prevents the browser from treating a drag as a page scroll gesture on touch */
}
.chat-panel__header:active {
  cursor: grabbing;
}
.chat-panel__close {
  background: transparent;
  border: none;
  color: #fff;
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.chat-message {
  max-width: 85%;
  padding: 6px 10px;
  border-radius: 10px;
  font-size: 0.85rem;
  line-height: 1.3;
  word-wrap: break-word;
}
.chat-message--mine {
  align-self: flex-end;
  background: rgba(232, 169, 59, 0.3);
  color: var(--ink);
}
.chat-message--theirs {
  align-self: flex-start;
  background: rgba(24, 43, 58, 0.1);
  color: var(--ink);
}
.chat-message__sender {
  font-size: 0.7rem;
  font-weight: 700;
  opacity: 0.65;
  display: block;
  margin-bottom: 2px;
}

/* Settings gear + panel — sound and auto-open-chat toggles, consolidated
   here rather than scattered as standalone controls. Reuses the chat
   panel's visual language (same header/close-button styles) for
   consistency, positioned to its left so the two don't overlap when
   both happen to be open. */
.settings-toggle-btn {
  position: relative;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1px solid var(--gold);
  background: transparent;
  color: #fff;
  font-size: 0.9rem;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
}
.settings-toggle-btn:hover {
  background: var(--gold);
  color: var(--navy);
}

.settings-panel {
  position: absolute;
  top: 60px;
  right: 90px;
  width: 260px;
  max-width: calc(100vw - 32px);
  background: var(--paper);
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
  overflow: hidden;
  z-index: 95;
}
.settings-panel__body {
  padding: 12px 16px;
}
.settings-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 8px 0;
  font-size: 0.9rem;
  color: var(--ink);
  cursor: pointer;
}

.chat-input-row {
  display: flex;
  gap: 6px;
  padding: 10px;
  border-top: 1px solid rgba(24, 43, 58, 0.12);
}
.chat-input-row input {
  flex: 1;
  padding: 8px 10px;
  border: 1px solid rgba(24, 43, 58, 0.25);
  border-radius: 4px;
  font-size: 0.9rem;
}
.chat-input-row button {
  padding: 8px 14px;
  background: var(--gold);
  color: var(--navy);
  border: none;
  border-radius: 4px;
  font-weight: 600;
  cursor: pointer;
}
.chat-input-row button:hover {
  filter: brightness(0.92);
}



/* =====================================================================
   Spades additions
   ===================================================================== */

/* Bidding bar — sits above the player's hand during the bidding phase
   (the spot Hearts uses for its passing bar). */
.bidding-bar {
  margin-bottom: 0.5rem;
  color: #fff;
  text-align: center;
}
.bidding-bar__prompt {
  margin: 0 0 0.4rem;
  font-weight: 600;
}
/* Stepper: [Nil]  [−] value [+]  [Bid N]. One row at any width; a
   choice is only committed by the Bid button. */
.bidding-bar__options {
  display: flex;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: center;
  gap: 0.6rem;
  margin: 0 auto;
}
.bid-stepper__picker {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}
.bid-stepper__value {
  min-width: 2.6rem;
  text-align: center;
  font-size: 1.35rem;
  font-weight: 700;
  color: #fff;
}
.bid-step {
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.5);
  border-radius: 50%;
  background: transparent;
  color: #fff;
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
}
.bid-step:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.12);
}
.bid-step:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}
.bid-step:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}
.bid-btn {
  min-width: 2.5rem;
  padding: 0.45rem 0.6rem;
  border: none;
  border-radius: 4px;
  background: var(--gold);
  color: var(--navy);
  font-size: 1rem;
  font-weight: 700;
  cursor: pointer;
  transition: filter 0.15s ease;
}
.bid-btn:hover {
  filter: brightness(0.92);
}
.bid-btn:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}
.bid-btn--nil {
  background: transparent;
  color: #FDF8E6;
  border: 1px solid rgba(253, 248, 230, 0.6);
}
.bid-btn--nil[aria-pressed="true"] {
  background: #FDF8E6;
  color: var(--navy);
}
.bid-btn--confirm {
  min-width: 5.5rem;
  padding: 0.5rem 1rem;
}
.bid-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Each seat's bid and tricks won, under the name. */
.seat__bid {
  font-size: 0.85rem;
  color: #ffe9b3;
}
.seat__bid--nil {
  color: #ffd54f;
  font-weight: 700;
}
.my-seat-name-row .seat__bid {
  margin-left: 0.6rem;
}

/* Team scoreboard in the top bar. */
.score--team {
  white-space: nowrap;
}
.score--mine {
  color: #ffd54f;
}
.score__bags {
  margin-left: 0.35rem;
  font-size: 0.85em;
  font-weight: 500;
  opacity: 0.8;
}

/* Spades score table: each cell is the hand's points with the bid and
   tricks behind them on a second, quieter line. */
.score-table--spades td {
  vertical-align: top;
}
.score-table__pts {
  display: block;
  font-weight: 700;
}
.score-table__detail {
  display: block;
  font-size: 0.8rem;
  font-weight: 400;
  opacity: 0.7;
}
.score-table__mine {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Notes about the hand just played (sets, nils, bag penalties). */
.hand-summary {
  margin: 0 0 0.75rem;
  padding: 0;
  list-style: none;
  text-align: left;
  font-size: 0.95rem;
}
.hand-summary li + li {
  margin-top: 0.25rem;
}

/* Learner hints (Settings → Show Hint button). A small 💡 Hint button on
   your turn; clicking it opens a panel with the suggestion (× or the button
   again closes it). The suggested card gets a gold outline only while the
   panel is open. */
.hint-box {
  max-width: 40rem;
  margin: 0 auto 0.5rem;
  text-align: center;
}
.hint-toggle {
  padding: 0.3rem 0.8rem;
  border: 1px solid rgba(232, 169, 59, 0.7);
  border-radius: 999px;
  background: transparent;
  color: #ffe9b3;
  font-size: 0.9rem;
  cursor: pointer;
}
.hint-toggle:hover,
.hint-toggle[aria-expanded="true"] {
  background: rgba(232, 169, 59, 0.18);
}
.hint-toggle:focus-visible,
.hint-panel__close:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}
.hint-panel {
  position: relative;
  margin-top: 0.4rem;
  padding: 0.5rem 2.2rem 0.5rem 0.8rem;
  border-left: 3px solid var(--gold);
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.25);
  text-align: left;
}
.hint-panel__text {
  margin: 0;
  color: #ffe9b3;
  font-size: 0.9rem;
}
.hint-panel__close {
  position: absolute;
  top: 0.15rem;
  right: 0.3rem;
  width: 1.8rem;
  height: 1.8rem;
  padding: 0;
  border: none;
  background: transparent;
  color: #ffe9b3;
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
}
.my-hand--fan .card--hint {
  outline: 3px solid var(--gold);
  outline-offset: -1px;
  border-radius: 6px;
  transform: translateY(-8px);
  z-index: 5;
}

/* Expert's second opinion inside the hint panel, and its card outline
   (dashed, so it reads as a second suggestion next to the gold one). */
.hint-panel__expert {
  margin: 0.35rem 0 0;
  color: #dbe8ef;
  font-size: 0.85rem;
}
.my-hand--fan .card--hint-expert {
  outline: 3px dashed #cfe3ff;
  outline-offset: -1px;
  border-radius: 6px;
  transform: translateY(-8px);
  z-index: 5;
}

/* Score windows (end of hand / end of game) never outgrow the screen:
   the window is capped at the visible height, the title and buttons stay
   in view, and only the score area scrolls. Inside it, the team header
   row sticks to the top and the Total row to the bottom, so the current
   totals are always visible in a long game. dvh accounts for phone
   browser bars; the vh line is the fallback for older browsers. */
#handOverModal .modal__inner,
#gameOverModal .modal__inner {
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - 2rem);
  max-height: calc(100dvh - 2rem);
  width: min(480px, calc(100vw - 2rem));
  box-sizing: border-box;
}
#handOverModal .modal__inner > h2,
#gameOverModal .modal__inner > h2,
#handOverModal .modal__inner > button,
#gameOverModal .game-over-actions {
  flex: 0 0 auto;
}
#handOverBody,
#gameOverBody {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.score-table--spades thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: #fff;
}
.score-table--spades .score-table__total td {
  position: sticky;
  bottom: 0;
  z-index: 1;
  background: #fff;
}

/* "Playing to N" note at the end of the scoreboard. */
.score__target {
  margin-left: 0.5rem;
  font-size: 0.85em;
  opacity: 0.75;
  white-space: nowrap;
}

/* Last trick: button + panel in the felt's top-right corner. */
.last-trick {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  z-index: 20;
  text-align: right;
}
.last-trick__toggle {
  padding: 0.3rem 0.8rem;
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.2);
  color: #fff;
  font-size: 0.85rem;
  cursor: pointer;
}
.last-trick__toggle:hover,
.last-trick__toggle[aria-expanded="true"] {
  background: rgba(255, 255, 255, 0.12);
}
.last-trick__toggle:focus-visible,
.last-trick__close:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}
.last-trick__panel {
  position: relative;
  margin-top: 0.4rem;
  padding: 0.6rem 0.6rem 0.5rem;
  border-radius: 6px;
  background: rgba(16, 38, 28, 0.96);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
}
.last-trick__close {
  position: absolute;
  top: 0.1rem;
  right: 0.25rem;
  width: 1.6rem;
  height: 1.6rem;
  padding: 0;
  border: none;
  background: transparent;
  color: #fff;
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
}
.last-trick__cards {
  display: flex;
  gap: 0.4rem;
  margin: 1.1rem 0 0;
  padding: 0;
  list-style: none;
}
.last-trick__card {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 3.4rem;
  text-align: center;
}
.last-trick__face {
  display: block;
  width: 3.4rem;
  border-radius: 4px;
  background: #fff;
}
.last-trick__face .card-svg {
  display: block;
  width: 100%;
  height: auto;
}
.last-trick__card--won .last-trick__face {
  outline: 3px solid var(--gold);
}
.last-trick__name {
  margin-top: 0.25rem;
  color: #fff;
  font-size: 0.75rem;
  line-height: 1.2;
  word-break: break-word;
}
.last-trick__name strong {
  display: block;
  color: #ffd54f;
}
@media (max-width: 640px) {
  .last-trick { top: 0.4rem; right: 0.4rem; }
  .last-trick__card, .last-trick__face { width: 2.8rem; }
}

/* Team setup (game.php #teamSetup, drawn by game.js renderTeamSetup):
   before the first deal of a 2-4 player game, the host's partner chooser
   and everyone else's "Waiting for team assignment" screen. Sits on the
   page like the name form above it, not on the green table. */
.team-setup {
  max-width: 440px;
  margin: 2rem auto;
  text-align: center;
}
.team-setup h2 {
  margin-top: 0;
}
.team-setup__code {
  margin: 0 0 1rem;
  color: var(--navy);
}
.team-setup__code strong {
  letter-spacing: 0.1em;
}
.team-setup__link {
  font-size: 0.8rem;
  color: var(--brick);
  word-break: break-all;
}
.team-setup__intro {
  margin: 0 0 1rem;
}
.team-setup__options {
  margin: 0 0 1rem;
  padding: 0;
  border: none;
  text-align: left;
}
.team-setup__legend {
  font-weight: 600;
  color: var(--navy);
  margin-bottom: 0.5rem;
}
.team-setup__option {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.6rem 0.75rem;
  margin-bottom: 0.5rem;
  background: #fff;
  border: 1px solid rgba(24, 43, 58, 0.2);
  border-radius: 4px;
  cursor: pointer;
}
.team-setup__option:hover {
  border-color: rgba(24, 43, 58, 0.45);
}
.team-setup__option:has(input:checked) {
  border-color: var(--gold);
  box-shadow: 0 0 0 2px rgba(232, 169, 59, 0.45);
}
.team-setup__name {
  flex: 1;
  font-weight: 600;
  color: var(--ink);
}
.team-setup__kind {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--brick);
}
.team-setup__status {
  font-size: 0.9rem;
  color: var(--brick);
  margin: 0 0 0.75rem;
}
.team-setup__preview {
  font-weight: 600;
  color: var(--navy);
  margin: 0 0 0.75rem;
}
.team-setup__confirm {
  background: var(--gold);
  color: var(--navy);
  border: none;
  border-radius: 4px;
  padding: 0.65rem 1.4rem;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  transition: filter 0.15s ease;
}
.team-setup__confirm:hover:not(:disabled) {
  filter: brightness(0.92);
}
.team-setup__confirm:disabled {
  background: rgba(232, 169, 59, 0.4);
  cursor: not-allowed;
}
.team-setup__cancel {
  display: block;
  margin: 1rem auto 0;
  background: none;
  border: none;
  padding: 0;
  color: #c0392b;
  text-decoration: underline;
  font-size: 0.85rem;
  cursor: pointer;
}
.team-setup__leave {
  display: inline-block;
  margin-top: 0.5rem;
  font-size: 0.9rem;
}
.team-setup .btn {
  width: auto;
  margin-top: 0.5rem;
}

/* Continue between hands: everyone's click counts. After you click, the
   button reads "Waiting for others…" (disabled), a line names who's still
   reading, and the host also gets "Deal now". Status line and Deal now
   are created by game.js (renderHandReady). */
#handOverModal #nextHandBtn:disabled {
  background: rgba(232, 169, 59, 0.4);
  cursor: default;
  filter: none;
}
.hand-ready__status {
  margin: 0.6rem 0 0;
  font-size: 0.9rem;
  color: var(--brick);
}
#handOverModal .hand-ready__deal-now {
  display: block;
  margin: 0.6rem auto 0;
  background: transparent;
  color: var(--navy);
  border: 1px solid rgba(24, 43, 58, 0.3);
  padding: 0.45rem 1.1rem;
  font-size: 0.9rem;
}
#handOverModal .hand-ready__deal-now:hover:not(:disabled) {
  background: rgba(24, 43, 58, 0.06);
  filter: none;
}
#handOverModal .hand-ready__deal-now.is-hidden,
#handOverModal .hand-ready__status.is-hidden {
  display: none !important;
}
#handOverModal .modal__inner > .hand-ready__status,
#handOverModal .modal__inner > .hand-ready__deal-now {
  flex: 0 0 auto;
}

/* Rematch (game-over window): non-host waiting line, the host's
   Change partner chooser (reuses the team setup option styles), and the
   "Are you…?" seat picker for a player back on a different device. */
.rematch__waiting {
  flex-basis: 100%;
  margin: 0;
  color: var(--brick);
}
.rematch__chooser {
  flex-basis: 100%;
  text-align: left;
}
.rematch__chooser .team-setup__options {
  margin-bottom: 0.5rem;
}
.rematch__chooser-actions {
  display: flex;
  gap: 0.75rem;
  justify-content: center;
  flex-wrap: wrap;
}
.rematch__chooser-actions .btn:disabled {
  background: rgba(232, 169, 59, 0.4);
  cursor: not-allowed;
}
.rematch__are-you-list {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 1rem;
}

/* "New teams" banner at the top of the table after a rematch with a
   different partner. */
.new-teams-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  max-width: 640px;
  margin: 0 auto 0.5rem;
  padding: 0.5rem 0.75rem 0.5rem 1rem;
  border-left: 3px solid var(--gold);
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.25);
  color: #ffe9b3;
  font-weight: 600;
}
.new-teams-banner__close {
  background: transparent;
  border: none;
  color: #ffe9b3;
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 0.25rem;
}
.new-teams-banner__close:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

/* =====================================================================
   Sign-in and emoji (lobby + name screen)
   ===================================================================== */

/* "Sign in to sync games & stats" (to the GameShack sign-in page) /
   "Playing as … · Account" (to the GameShack account page), under the
   lobby logo. A text-style button so it doesn't compete with
   Create Game. */
.account-status {
  display: block;
  margin: -0.75rem auto 1.25rem;
  padding: 0.35rem 0.9rem;
  background: transparent;
  border: 1px solid rgba(24, 43, 58, 0.3);
  border-radius: 999px;
  color: var(--navy);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}
.account-status:hover {
  background: rgba(24, 43, 58, 0.06);
}
.account-status.is-signed-in {
  border-color: var(--gold);
  background: rgba(232, 169, 59, 0.15);
}
.account-status:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 2px;
}

/* Emoji picker: the same 20 emoji as Rummy, in a wrapping grid. */
.emoji-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin: 0.2rem 0 0;
}
.emoji-swatch {
  width: 2.4rem;
  height: 2.4rem;
  padding: 0;
  border: 1px solid rgba(24, 43, 58, 0.2);
  border-radius: 6px;
  background: #fff;
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
}
/* The lobby's generic button rule (gold, full width, top margin) must
   not apply to the swatches. */
.lobby-section .emoji-swatch,
.name-entry .emoji-swatch {
  width: 2.4rem;
  margin: 0;
  padding: 0;
  border: 1px solid rgba(24, 43, 58, 0.2); /* the button rules above set border: none */
  border-radius: 6px;
  background: #fff;
  color: inherit;
  font-weight: 400;
}
.emoji-swatch:hover {
  border-color: rgba(24, 43, 58, 0.5);
  filter: none;
}
.emoji-swatch.is-selected,
.lobby-section .emoji-swatch.is-selected,
.name-entry .emoji-swatch.is-selected {
  border: 2px solid var(--gold);
  background: rgba(232, 169, 59, 0.2);
}
.emoji-swatch:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 2px;
}

/* Name screen at the table: label above the grid, grid centered. */
.name-entry__label {
  margin: 0 0 0.3rem;
  font-weight: 600;
  color: var(--navy);
}
.name-entry .emoji-grid {
  justify-content: center;
  margin-bottom: 1rem;
}
