/* M4-P2 phone waiting/card slice (local; pending Codex review).
   Scoped to #playerContainer phone screens: waiting, next-game waiting, rules,
   removed/error, and the game screen (header, called balls, status, cards).
   Same ui-kit art as the lobby/access slices. Ball colours and letter ranges,
   team identity, card-cell meaning (marked / free / reward / blocked / eliminated),
   Blackout listen-only hiding and every handler are unchanged.
   arena-controls.css forces navy + !important borders on most buttons, so button
   materials here are !important, and #allCardsGrid is used to outrank the long
   :not() chain arena-presentation.css puts on unmarked cells. */
#playerContainer {
  --lm-panel-art: url('ui-kit-navy-panel.webp');
  --lm-gold-art: url('ui-kit-gold-button.webp');
  --lm-navy-art: url('ui-kit-navy-button.webp');
  --lm-ink: #172a4f;
  --lm-pale: #fff7e5;
  --lm-soft: #dbe5f7;
  --lm-navy: #17418f;
  --lm-rim: #d9a441;
  --lm-rail: linear-gradient(145deg, #fff2bb 0%, #eac262 27%, #9c631b 58%, #f9d875 79%, #b17b2f 100%);
  --lm-cream: linear-gradient(170deg, #fffdf4, #f4e7cc);
  --lm-navy-face: linear-gradient(170deg, #2f60b2, #123a82);
  --lm-ledge: #8a5a14;
  --lm-panel-rim: 28px;
}

/* ===== Navy/gold panels ===== */
#playerContainer :is(.playerHeader, .playerBallDisplay, .playerWaiting, .gameRulesScreen, .playerKicked, .playerError) {
  border: 9px solid var(--lm-rim);
  border-image: var(--lm-panel-art) 72 fill / var(--lm-panel-rim) stretch;
  background: var(--lm-navy) padding-box;
  border-radius: 16px;
  box-shadow: 0 4px 0 #6b4712, 0 12px 24px #0a1a3a59;
  color: var(--lm-pale);
}
/* Waiting, rules and removed/error screens become floating panels over the castle. */
#playerContainer :is(.playerWaiting, .gameRulesScreen, .playerKicked, .playerError) {
  min-height: 0;
  width: calc(100% - 24px);
  max-width: 560px;
  margin: 24px auto;
  padding: 28px 22px;
  text-align: center;
}
#playerContainer :is(.playerWaiting h2, .rulesHeader h2, .playerKicked h2, .playerError h2) { color: #ffe39b; }
#playerContainer :is(.playerWaiting p, .playerKicked p, .playerError p) { color: var(--lm-pale); }
/* A long unbroken message (a link, a code) wraps inside the border instead of running past it (M4-P5 outcome scenes). */
#playerContainer :is(.playerKicked, .playerError) :is(h2, p) { overflow-wrap: anywhere; }
/* The Error message sat flush on its Try Again button, so the button's focus ring covered the last line; same gap as
   Removed from Game's message (player-styles.css). */
#playerContainer .playerError p { margin-bottom: 24px; }
#playerContainer .playerWaiting .waitingSub { color: var(--lm-soft) !important; }
#playerContainer .gameRulesScreen .rulesCountdown { color: #ffe39b; }
#playerContainer .gameRulesScreen .ruleItem {
  border: 2px solid transparent;
  background: var(--lm-cream) padding-box, var(--lm-rail) border-box;
  color: var(--lm-ink);
  gap: 12px;
  text-align: left;
}
#playerContainer .gameRulesScreen .ruleLabel { color: #45536a; }
#playerContainer .gameRulesScreen .ruleValue { color: var(--lm-ink); }

#playerContainer .playerHeader { padding: 8px 10px; }
#playerContainer .playerRoomInfo { color: var(--lm-soft); }
#playerContainer .playerBallDisplay { padding: 10px 12px; }
#playerContainer .playerBallDisplay .ballLabel { color: #ffe39b; }

/* ===== Buttons ===== */
#playerContainer :is(.playerLeaveBtn, .waitingLeaveBtn, .rejoinBtn, .retryBtn) {
  border: 4px solid #c08a2a !important;
  border-image: var(--lm-navy-art) 56 76 fill / 20px 27px stretch !important;
  background: #123c8a padding-box !important;
  color: var(--lm-pale) !important;
  border-radius: 999px;
  box-shadow: var(--lm-state-shadow, 0 3px 0 #6b4712, 0 7px 12px #07182d4d) !important;
  min-height: 44px;
  padding: 8px 18px;
  font-weight: 800;
}
/* Icon-only sound control: round navy button with the gold rail. */
#playerContainer .playerSoundToggle {
  width: 44px; height: 44px; min-width: 44px; padding: 0;
  border: 3px solid transparent !important;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #4f86d8, #17418f 60%, #0b2a6b) padding-box, var(--lm-rail) border-box !important;
  box-shadow: var(--lm-state-shadow, 0 3px 0 #6b4712, 0 6px 10px #07182d4d) !important;
  display: grid; place-items: center;
  font-size: 18px;
}
#playerContainer .playerSoundToggle.muted { opacity: .75; }

/* Card BINGO! / BLACKOUT! button: gold art. Eliminated and Cry Wolf keep their own look. */
#playerContainer #allCardsGrid .cardBingoBtn:not(.eliminated):not(.cry-wolf-btn) {
  border: 4px solid #c08a2a !important;
  border-image: var(--lm-gold-art) 56 76 fill / 22px 30px stretch !important;
  background: #f8cf4f padding-box !important;
  color: var(--lm-ink) !important;
  text-shadow: 0 1px 0 #fff8;
  border-radius: 999px;
  box-shadow: var(--lm-state-shadow, 0 4px 0 var(--lm-ledge), 0 8px 14px #07182d40) !important;
  min-height: 52px;
  font-size: 17px;
  letter-spacing: .06em;
}

/* Shared states. Under review / approved stay disabled and keep their text. */
#playerContainer button { transition: transform .15s ease, filter .15s ease, box-shadow .15s ease; }
#playerContainer :is(.playerLeaveBtn, .waitingLeaveBtn, .rejoinBtn, .retryBtn, .playerSoundToggle, .cardBingoBtn):hover:not(:disabled) { filter: brightness(1.07) saturate(1.05); transform: translateY(-1px); }
#playerContainer :is(.playerLeaveBtn, .waitingLeaveBtn, .rejoinBtn, .retryBtn, .playerSoundToggle, .cardBingoBtn):active:not(:disabled) {
  filter: brightness(.95);
  transform: translateY(3px);
  --lm-state-shadow: 0 1px 0 #6b4712, 0 3px 6px #07182d40;
}
/* Greyed, not faded: at .7 "UNDER REVIEW" read 3.8:1; .85 keeps it clearly disabled at 5.7:1. */
#playerContainer #allCardsGrid .cardBingoBtn:is(:disabled, .disabled):not(.eliminated):not(.cry-wolf-btn) {
  filter: grayscale(.85) brightness(.92);
  opacity: .85 !important;
  cursor: not-allowed;
  transform: none;
  --lm-state-shadow: none;
}
#playerContainer :is(button):focus:not(:focus-visible) { outline: none; }
#playerContainer :is(.playerHeader, .playerWaiting, .gameRulesScreen, .playerKicked, .playerError) button:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }
#playerContainer #allCardsGrid .cardBingoBtn:focus-visible { outline: 3px solid #1452c4; outline-offset: 3px; }

/* ===== Status line (claim review, Blackout listen-only, spin, team/battle) =====
   Pre-existing (also live): player-styles.css hides .playerStatusBanner unless it has
   .show, but updateGameState() writes the Blackout "Listen to the host" notice, SPIN
   MOMENT and team/battle lines without that class, so phones never displayed them.
   Show the banner whenever it has text; it is empty (hidden) otherwise. */
#playerContainer .playerStatusBanner:not(:empty) { display: block; }
#playerContainer .playerStatusBanner {
  background: #fff6de;
  color: var(--lm-ink);
  border: 2px solid #e3b95a;
  border-left-width: 6px;
  border-radius: 12px;
  text-align: left;
  font-weight: 800;
}
#playerContainer .playerStatusBanner.spinPending { border-color: #d98a1a; background: #fff1d6; }
#playerContainer .playerStatusBanner.gameOver { border-color: #3f8a5a; background: #eef8f0; color: #1d4d2f; }

/* ===== Card layout =====
   Pre-existing (also live): at <=600px the approved 18px numerals make each card at
   least ~290px wide, but 2-6 cards were still forced into two columns, so every
   other card sat off-screen in a sideways-scrolling strip. Fit as many columns as
   really fit (one on phones), at most three. */
#playerContainer #allCardsGrid.playerCardsGrid:not(.grid-1) {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  max-width: 960px;
  margin-inline: auto;
}

/* ===== Cards: cream face, gold rail, team accent kept ===== */
#playerContainer #allCardsGrid .playerBingoCard {
  border: 3px solid transparent;
  background: var(--lm-cream) padding-box, var(--lm-rail) border-box;
  border-radius: 18px;
  padding: 10px;
  box-shadow: inset 0 0 0 3px var(--lm-team, transparent), 0 4px 0 #9c6b25, 0 10px 20px #07182d40;
}
#playerContainer #allCardsGrid .playerBingoCard.red-border { --lm-team: #c23a3f; }
#playerContainer #allCardsGrid .playerBingoCard.blue-border { --lm-team: #2a64c4; }
#playerContainer #allCardsGrid .playerBingoCard.white-border { --lm-team: #aab3c2; }
/* Blackout and Classic render no team badge: no team ring either (teams are not used). */
#playerContainer #allCardsGrid .playerBingoCard:not(:has(.playerCardBadge)) { --lm-team: transparent; }
#playerContainer #allCardsGrid .playerCardLabel { color: var(--lm-ink); }
#playerContainer #allCardsGrid .playerCardLetters {
  background: var(--lm-navy-face);
  border: 1px solid #d9a441;
  border-radius: 8px;
}
#playerContainer #allCardsGrid .playerCardLetters span:not(.rewarded) { color: #ffe39b; }

/* Cells: cream = open, navy with gold ring = marked, navy + gold dot = reward-marked,
   navy with gold FREE = free centre, red stripes + strike = blocked / row eliminated. */
#playerContainer #allCardsGrid .playerCardCell {
  border: 2px solid transparent;
  background: var(--lm-cream) padding-box, linear-gradient(#ecd296, #b58a3c) border-box;
  color: var(--lm-ink);
  border-radius: 10px;
  box-shadow: inset 0 1px 0 #fff, 0 2px 0 #c9a25a;
  font-weight: 900;
}
#playerContainer #allCardsGrid .playerCardCell.marked {
  background: var(--lm-navy-face) padding-box, var(--lm-rail) border-box;
  color: #fff;
  box-shadow: inset 0 0 0 2px #ffe39b, 0 2px 0 #7a5316;
}
#playerContainer #allCardsGrid .playerCardCell.free {
  background: var(--lm-navy-face) padding-box, var(--lm-rail) border-box;
  color: #ffe39b;
  font-size: .78em;
  letter-spacing: .04em;
  box-shadow: inset 0 0 0 2px #ffe39b55, 0 2px 0 #7a5316;
}
#playerContainer #allCardsGrid .playerCardCell.rewarded {
  background: radial-gradient(circle at 80% 20%, #ffd76a 0 4px, transparent 5px) padding-box, var(--lm-navy-face) padding-box, var(--lm-rail) border-box !important;
  color: #fff !important;
  border-color: transparent !important;
  box-shadow: inset 0 0 0 2px #ffe39b, 0 2px 0 #7a5316;
  outline: 2px dashed #ffd76a;
  outline-offset: -6px;
}
#playerContainer #allCardsGrid .playerCardCell:is(.blocked, .unavailable, .rowElim) {
  background: repeating-linear-gradient(135deg, #f3dede 0 6px, #e4c4c6 6px 9px) padding-box, linear-gradient(#c98a8f, #9a4f56) border-box !important;
  color: #7a1f2a !important;
  border-color: transparent !important;
  text-decoration: line-through;
  text-decoration-thickness: 2px;
  box-shadow: none;
}
@media (hover: hover) {
  #playerContainer #allCardsGrid .playerCardCell:not(.free):not(.blocked):not(.unavailable):not(.rowElim):not(.eliminated):hover { filter: brightness(1.05); }
}

@media (prefers-reduced-motion: reduce) {
  #playerContainer button, #playerContainer #allCardsGrid .playerCardCell { transition: none !important; transform: none !important; }
}

/* Independent review: keyboard marking gets a high-contrast inset focus ring. */
#playerContainer #allCardsGrid .playerCardCell[role="button"]:focus-visible { outline: 3px solid #1452c4; outline-offset: 1px; position: relative; z-index: 1; }
#playerContainer #allCardsGrid .playerCardCell.marked:focus-visible { outline-color: #fff; }

/* ===== Integrated audit (Claude, Sep 24): phone gaps found in rendered states ===== */
/* Eliminated overlay: white ELIMINATED on the bright pulsing red measured 3.9-4.35:1.
   Same red meaning, deeper shade (white text ≥7:1). Cry Wolf keeps its own look. */
#playerContainer .cardEliminatedOverlay:not(.cry-wolf) { animation-name: lmEliminatedPulse; }
/* The whole eliminated card was drawn at 40% opacity, overlay included, so ELIMINATED /
   CRY WOLF washed out over the castle (2.4:1). Dim the card's own content instead. */
#playerContainer #allCardsGrid .playerBingoCard.eliminated { opacity: 1; }
#playerContainer #allCardsGrid .playerBingoCard.eliminated > :not(.cardEliminatedOverlay) { opacity: .35; }
@keyframes lmEliminatedPulse { 0%, 100% { background: rgba(160, 18, 28, .92); } 50% { background: rgba(128, 8, 18, .94); } }
/* Toasts (appended to <body>): white text on light blue/orange/green measured 2.3-3.6:1. */
.playerToast { border-radius: 14px; box-shadow: 0 6px 18px #07182d66; max-width: calc(100vw - 24px); }
.playerToast.info { background: #1f5fbf; border-color: #d9a441; }
.playerToast.warning { background: #a8430e; border-color: #d9a441; }
.playerToast.success { background: #17704a; border-color: #d9a441; }
/* Team selection: card groups were the old dark surface; status text was grey on navy. */
#playerContainer .teamSelectCard { background: #0b265c8c; border: 1px solid #e3b95a73; box-shadow: inset 0 1px 0 #ffffff14; }
#playerContainer .teamSelectStatus { color: #dbe5f7; }
#playerContainer .teamSelectStatus.selected { color: #ffe39b; }
#playerContainer .teamSelectStatus.selected.red { color: #ffb3b3; }
#playerContainer .teamSelectStatus.selected.blue { color: #b7d3ff; }
/* Trade-card chooser: had no panel (flat buttons floating over the dimmed game). */
.playerTradeModal .tradeModalContent {
  border: 10px solid #d9a441;
  border-image: url('ui-kit-navy-panel.webp') 72 fill / 30px stretch;
  background: #17418f padding-box;
  border-radius: 20px;
  box-shadow: 0 5px 0 #6b4712, 0 16px 30px #07182d66;
  color: #fff7e5;
  width: min(420px, calc(100vw - 24px));
  padding: 22px 18px;
}
.playerTradeModal .tradeModalContent h2 { color: #ffe39b; text-shadow: 0 2px #0a1f4d; }
.playerTradeModal .tradeTimer { color: #ffb4a8; }
.playerTradeModal .tradeCardBtn {
  border: 4px solid #c08a2a !important;
  border-image: url('ui-kit-navy-button.webp') 56 76 fill / 20px 27px stretch !important;
  background: #123c8a padding-box !important;
  color: #fff7e5 !important;
  border-radius: 999px;
  min-height: 48px;
  min-width: 120px;
  box-shadow: 0 3px 0 #6b4712, 0 7px 12px #07182d4d;
}
.playerTradeModal .tradeCardBtn:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }
/* Duel controls on phones: the site-wide 160px button minimum pushed two-column answers
   off the card at 320-375px; sliders were 16px tall touch targets. */
#playerContainer .playerDuelCard button { min-width: 0; }
#playerContainer .playerDuelOptions { grid-template-columns: repeat(auto-fit, minmax(min(100%, 120px), 1fr)); }
#playerContainer .playerDuelRange { min-height: 44px; min-width: 0; }

/* Miss-call penalty (Codex art direction, Sep 25): the card stays readable while it is locked.
   It was 30% opacity + 80% grey with a large 🚫 over the centre, so the numbers could not be
   read. Now: stone face, pewter rail, muted colour and the existing 🚫 lock as a readable tab.
   Input is blocked exactly as before: pointer-events on the card (player-styles.css) and
   tabindex -1 / aria-disabled on the cells (multiplayer.js). Nothing new is revealed; the card
   shows the same numbers and marks it already had. */
#playerContainer #allCardsGrid .playerBingoCard.dimmed {
  opacity: 1;
  filter: none;
  pointer-events: none;
  background: linear-gradient(170deg, #efeae0, #dcd5c7) padding-box, linear-gradient(145deg, #e3e6ec, #9aa2b0 55%, #6f7888) border-box;
  box-shadow: inset 0 0 0 3px var(--lm-team, transparent), 0 4px 0 #6f7888, 0 10px 20px #07182d40;
}
#playerContainer #allCardsGrid .playerBingoCard.dimmed > :is(.playerCardLetters, .playerCardGrid, .cardBingoBtn:is(:disabled, .disabled)) { filter: saturate(.3) brightness(.95); }
#playerContainer #allCardsGrid .playerBingoCard.dimmed::after {
  content: '🚫 Missing calls';
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  opacity: 1;
  font-size: 12px;
  font-weight: 900;
  line-height: 1.2;
  white-space: nowrap;
  padding: 3px 10px;
  border-radius: 999px;
  background: #7a1f2a;
  color: #fff7e5;
  border: 2px solid #e3b95a;
  box-shadow: 0 2px 6px #07182d55;
}
/* An eliminated card's own overlay says what happened; no penalty tab on top of it. */
#playerContainer #allCardsGrid .playerBingoCard.dimmed.eliminated::after { content: none; }
/* Penalty claim parity (Codex rules interpretation, Sep 25): a missed-call penalty pauses
   marking, not claiming. Touch/mouse were blocked by the card's pointer-events while the
   keyboard could still press BINGO. Only an enabled BINGO button takes pointer input again;
   every cell stays locked, and disabled (pending / approved / eliminated) buttons stay inert. */
#playerContainer #allCardsGrid .playerBingoCard.dimmed .cardBingoBtn:not(:disabled):not(.disabled) { pointer-events: auto; }
#playerContainer #allCardsGrid .playerBingoCard.dimmed .penaltyHelp {
  margin: 8px 4px;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.35;
  text-align: center;
  color: var(--lm-ink);
}
