/* Approved castle presentation. Theme palettes change surfaces, never logo or team identity. */
body { --arena-paper:#fff8e9; --arena-ink:#192c50; --arena-edge:#b18b43; --arena-banner:#20385e; --arena-gold:#f3ca66; --arena-wash:rgba(249,238,215,.25); }
body.theme-halloween { --arena-paper:#fbefdF; --arena-ink:#32213e; --arena-edge:#a65318; --arena-banner:#402950; --arena-gold:#ffbf70; --arena-wash:rgba(73,28,91,.65); }
body.theme-christmas { --arena-paper:#fff9ee; --arena-ink:#203e35; --arena-edge:#9a3538; --arena-banner:#244b3f; --arena-gold:#f0cd76; --arena-wash:rgba(228,246,239,.5); }
body.theme-summer { --arena-paper:#fff9e9; --arena-ink:#154551; --arena-edge:#aa7121; --arena-banner:#156075; --arena-gold:#ffd279; --arena-wash:rgba(75,199,215,.28); }
body.theme-neonRave { --arena-paper:#f5efff; --arena-ink:#30204b; --arena-edge:#8851b3; --arena-banner:#38205f; --arena-gold:#f2beff; --arena-wash:rgba(64,18,102,.65); }
body.theme-casino { --arena-paper:#fff4e3; --arena-ink:#3e2028; --arena-edge:#9e7029; --arena-banner:#4c2431; --arena-gold:#f3cd75; --arena-wash:rgba(67,24,38,.6); }
/* Always use the original image as supplied, with proportional scaling. */
img[src="logo.png"], img[src="logo.jpg"] {object-fit:contain!important;filter:none!important;border-radius:0!important;animation:none!important;transform:none!important;}
#screenHostLobby.knightLobby, #screenTVDisplay, #playerContainer, #screenHostGame {
 background-color:#ead7b4;
 background-image:linear-gradient(var(--arena-wash),var(--arena-wash)),url('castle-courtyard.jpg');
 background-size:cover; background-position:center top; background-attachment:fixed;
}
#screenHostLobby.knightLobby header, #screenHostLobby.knightLobby .panel, #screenHostLobby.knightLobby .quickGuide {background:var(--arena-paper);border-color:var(--arena-edge);color:var(--arena-ink);}
#screenHostLobby.knightLobby .panel h2, #screenHostLobby.knightLobby .box {background:var(--arena-paper);color:var(--arena-ink);border-color:var(--arena-edge);}
#screenHostLobby.knightLobby .knightWelcome, #screenHostLobby.knightLobby .codeBig {background:var(--arena-banner);border-color:var(--arena-edge);color:#fff8ec;}
#screenHostLobby.knightLobby button.ok, #screenHostLobby.knightLobby button.warn {background:var(--arena-gold);color:#192c50;}
#screenHostGame .panel, #screenHostGame header {background:rgba(16,30,53,.96);border:2px solid var(--arena-edge);border-radius:22px;}
#screenHostGame .panel h2 {color:#ffdfa0;}
.arenaPlayerBrand {display:flex;justify-content:space-between;align-items:center;min-height:82px;padding:0 12px;}
.arenaPlayerBrand img {object-fit:contain;}
.arenaPlayerBrand .arenaPlayerKnight {height:80px;width:54px;}
#playerContainer .playerGame {background:transparent;max-width:1100px;margin:auto;padding:8px 12px 24px;}
#playerContainer .playerHeader {background:var(--arena-banner);color:#fff8ec;border:1px solid var(--arena-edge);border-radius:16px;gap:8px;flex-wrap:wrap;}
#playerContainer .playerRoomInfo {color:#fff8ec;}
#playerContainer .playerLeaveBtn, #playerContainer .playerSoundToggle {color:#fff8ec;min-height:44px;}
#playerContainer .playerBallDisplay {background:var(--arena-banner);border:2px solid var(--arena-edge);border-radius:20px;padding:14px;color:#fff8ec;}
#playerContainer .ballLabel {color:#ffdfa0;}
#playerContainer .playerBingoCard {background:var(--arena-paper);color:var(--arena-ink);border-radius:18px;box-shadow:0 6px 18px #16264130;padding:12px;}
#playerContainer .playerCardLabel {color:var(--arena-ink);}
#playerContainer .playerCardLetters {background:var(--arena-banner);padding:6px 0;border-radius:8px;}
#playerContainer .playerCardLetters span {color:#fff8ec;}
#playerContainer .playerCardCell:not(.marked):not(.free):not(.rowElim):not(.blocked):not(.eliminated):not(.unavailable):not(.rewarded) {background:#fffefd;color:#192c50;border-color:#b4bdca;}
#playerContainer .playerCardCell.marked {background:#f4cc68;color:#192c50;border-color:#86631c;box-shadow:inset 0 0 0 2px #fff4c5;}
#playerContainer .playerCardCell.free {background:#d4efde;color:#204e34;border-color:#4d865f;}
#playerContainer .playerCardCell.rowElim, #playerContainer .playerCardCell.blocked, #playerContainer .playerCardCell.unavailable {background:#e5d3d4;color:#72262e;border-color:#a06d74;text-decoration:line-through;}
#playerContainer .playerCardCell.rewarded {background:#d9eaff;color:#193e73;}
#playerContainer .cardBingoBtn {background:linear-gradient(#ffe6a2,var(--arena-gold));color:#192c50;border:2px solid #9c762e;min-height:48px;box-shadow:0 3px 0 #aa8235;}
#playerContainer .cardBingoBtn:disabled {opacity:.55;box-shadow:none;}
#playerContainer .playerWaiting {background:var(--arena-banner);border:2px solid var(--arena-edge);border-radius:24px;color:#fff8ec;max-width:600px;margin:24px auto;padding:28px;}
#playerContainer :is(button,[role="button"]):focus-visible {outline:3px solid #185bc4;outline-offset:3px;}
#screenTVDisplay .tvBg {display:none;}
#screenTVDisplay .tvLeft, #screenTVDisplay .tvRight, #screenTVDisplay .tvOverlayCard {background:rgba(18,34,60,.97);border:2px solid var(--arena-edge);box-shadow:0 12px 35px #17284240;}
#screenTVDisplay .tvRight {position:relative;}
.arenaCallTitle {font-size:clamp(20px,2vw,32px);font-weight:900;letter-spacing:.08em;color:#ffdfa0;text-align:center;border-bottom:2px solid var(--arena-edge);padding:8px;}
#screenTVDisplay .tvBallHeader {justify-content:flex-start;flex-wrap:wrap;padding-right:140px;min-height:280px;}
#screenTVDisplay .tvCurrentBall {width:clamp(240px,23vw,340px);height:clamp(240px,23vw,340px);flex-shrink:0;border:9px solid var(--arena-gold);background:radial-gradient(circle at 35% 25%,#fff,#fff6df 60%,#e0cba1)!important;box-shadow:inset 0 -8px 18px #99773240,0 10px 20px #0003;}
#screenTVDisplay .tvCurrentBall .tvBallLetter {color:#192c50;font-size:clamp(30px,3vw,46px);text-shadow:none;}
#screenTVDisplay .tvCurrentBall .tvBallNumber {color:#192c50;font-size:clamp(80px,8vw,124px);line-height:1;text-shadow:none;}
#screenTVDisplay .arenaTVKnight {position:absolute;right:16px;top:100px;width:120px;height:180px;object-fit:contain;pointer-events:none;}
#screenTVDisplay .tvWinnerBanner {background:var(--arena-gold);color:#192c50;}
#screenTVDisplay .tvOverlay {background:rgba(13,24,44,.55);}
/* Hidden call values must stay hidden in Blackout listen-only phases. */
#tvCurrentBall[hidden], #tvLastCalls[hidden], #playerCurrentBall[hidden], #playerLastCalls[hidden], .arenaTVKnight[hidden], .arenaPlayerKnight[hidden] {display:none!important;}
@media(max-width:980px){#screenTVDisplay .tvBallHeader {padding-right:0;} #screenTVDisplay .arenaTVKnight {display:none;} }
@media(max-width:600px){
 #playerContainer .playerGame {padding:6px 8px 18px;}
 #playerContainer .playerBingoCard {padding:9px;}
 #playerContainer .playerCardCell {font-size:18px;}
 #screenTVDisplay .tvMain {padding:10px;}
 #screenTVDisplay .tvLayout {width:100%;}
 #screenHostLobby.knightLobby, #screenTVDisplay, #playerContainer, #screenHostGame {background-attachment:scroll;}
}
@media(prefers-reduced-motion:reduce){.knightWelcome, .arenaTVKnight, .arenaPlayerKnight {animation:none!important;transition:none!important;} }
/* Flow layout keeps sound and leave controls separate on small phones. */
#playerContainer .playerSoundToggle {position:static;right:auto;flex:0 0 44px;width:44px;}
#playerContainer .playerLeaveBtn {flex:0 1 auto;}
#playerContainer .playerRoomInfo {flex:1 1 100%;text-align:right;}
#screenHostLobby.knightLobby .pill.phone {background:#f8e2e2;color:#882727;border-color:#ab6262;}
#screenHostLobby.knightLobby .pill.phone.connected {background:#ddf0e3;color:#215632;border-color:#639576;}
#screenLanding .landingBg, #screenHostLogin .landingBg, #screenJoin .landingBg {background:linear-gradient(var(--arena-wash),var(--arena-wash)),url('castle-courtyard.jpg') center/cover;}
#screenLanding .landingCard {background:rgba(18,34,60,.96);border:2px solid var(--arena-edge);}
#playerContainer .playerHeader {display:grid;grid-template-columns:minmax(0,1fr) 44px;}
#playerContainer .playerSoundToggle {min-width:44px;max-width:44px;width:44px;justify-self:end;}
#playerContainer .playerRoomInfo {grid-column:1 / -1;}
#playerContainer .playerCardBadge.red {background:#fbe0e0;color:#8f2028;border-color:#a3454c;}
#playerContainer .playerCardBadge.blue {background:#dfebff;color:#163b75;border-color:#4773a6;}
#playerContainer .playerCardBadge.white {background:#fff;color:#25354a;border-color:#727d8e;}
/* Castle journey step 3: the gathering hall (Codex art, concept-art/gathering-hall-v1).
   Only the host lobby and the phone waiting / rules / waiting-for-next-game screens. Main menu
   stays exterior, login/join stay at the gate, host game, phone game and TV stay in the courtyard.
   Each phone screen replaces #playerContainer's contents, so the :has() rule follows the screen
   actually shown and resets itself on game start, leave, rejoin and return to lobby; browsers
   without :has() keep the courtyard. Like the gate, the scene is a fixed viewport-sized layer,
   so a long lobby on a phone does not stretch it. A background only downloads once its screen
   is shown, and the media query gives each viewport a single derivative. Solid navy shows if
   the art is missing. Same theme wash as the courtyard. */
#screenHostLobby.knightLobby,
#playerContainer:has(> .playerWaiting, > .gameRulesScreen) {
 isolation:isolate; background-color:#10295e; background-image:none;
}
#screenHostLobby.knightLobby::before,
#playerContainer:has(> .playerWaiting, > .gameRulesScreen)::before {
 content:''; position:fixed; inset:0; z-index:-1; pointer-events:none;
 background:linear-gradient(var(--arena-wash),var(--arena-wash)),url('gathering-hall-desktop.webp') center 42%/cover no-repeat;
}
@media (max-width:480px) and (orientation:portrait){
 #screenHostLobby.knightLobby::before,
 #playerContainer:has(> .playerWaiting, > .gameRulesScreen)::before {
  background-image:linear-gradient(var(--arena-wash),var(--arena-wash)),url('gathering-hall-phone.webp');
  background-position:center top;
 }
}
/* M4-P5 production art trial: the Halloween courtyard (Codex-approved master
   concept-art/m4-p5-production/masters/halloween-courtyard-v1.png, re-encoded unchanged as
   halloween-courtyard-desktop.webp; provenance in evidence/m4-p5-courtyard/). Halloween host game and
   TV only. The night scene carries the mood itself, so the placeholder purple tint is not layered on
   it; the panels are opaque, so no wash is needed for legibility. Size, position and attachment stay
   the courtyard's (cover, centre top). The image downloads only while one of these screens is shown
   in Halloween; if it fails, solid night navy shows behind the unchanged panels. Phones keep the
   Classic courtyard with the tint until a portrait composition exists (not final). */
body.theme-halloween #screenHostGame,
body.theme-halloween #screenTVDisplay {
 background-color:#10295e;
 background-image:url('halloween-courtyard-desktop.webp');
}
/* M4-P5 phone courtyard trial (Codex-approved portrait master
   concept-art/m4-p5-production/masters/halloween-courtyard-phone-v1.png, re-encoded at its native 853x1844
   as halloween-courtyard-phone.webp; provenance in evidence/m4-p5-phone-tv/). Halloween phone ACTIVE GAME
   only: waiting, rules and next-game keep the hall, join keeps the gate (winner and error screens: see
   below). Same fixed viewport-sized layer as the hall, so a long card list does not
   stretch it; one layer, no tint, solid night navy if the image fails. Portrait phones get the portrait
   art; landscape phones, tablets and laptop players get the desktop courtyard (one file per orientation;
   rotating a phone mid-game loads the other once). Browsers without :has() keep the placeholder.
   Outcome scenes (M4-P5): team colour selection (shown once the game has started) and the winner screen
   (only ever shown for the host's confirmed result) stay in the same courtyard, so the game -> winner
   change keeps the layer already painted and downloads nothing. */
body.theme-halloween #playerContainer:has(> .playerGame, > .playerTeamSelection, > .playerWinnerScreen) {
 isolation:isolate; background-color:#10295e; background-image:none;
}
body.theme-halloween #playerContainer:has(> .playerGame, > .playerTeamSelection, > .playerWinnerScreen)::before {
 content:''; position:fixed; inset:0; z-index:-1; pointer-events:none;
 background:url('halloween-courtyard-desktop.webp') center top/cover no-repeat;
}
@media (max-width:480px) and (orientation:portrait){
 body.theme-halloween #playerContainer:has(> .playerGame, > .playerTeamSelection, > .playerWinnerScreen)::before {
  background-image:url('halloween-courtyard-phone.webp');
 }
}
/* M4-P5 Halloween hall trial (Codex-approved masters concept-art/m4-p5-production/masters/halloween-hall-{desktop,phone}-v1.png,
   re-encoded at native size as halloween-hall-{desktop,phone}.webp; provenance in evidence/m4-p5-hall/). Same phases and
   the same fixed viewport layer as the Classic hall above (host lobby; phone waiting, rules and next game), one layer with
   no tint, the hall's position and navy fallback. The layer is written out in full: the Classic hall is two layers (tint +
   picture) with cover only on the picture, so a lone image would inherit the tint layer's auto size and repeat.
   Portrait phones get the portrait art; larger and landscape layouts the desktop art. */
body.theme-halloween #screenHostLobby.knightLobby::before,
body.theme-halloween #playerContainer:has(> .playerWaiting, > .gameRulesScreen)::before {
 background:url('halloween-hall-desktop.webp') center 42%/cover no-repeat;
}
@media (max-width:480px) and (orientation:portrait){
 body.theme-halloween #screenHostLobby.knightLobby::before,
 body.theme-halloween #playerContainer:has(> .playerWaiting, > .gameRulesScreen)::before {
  background:url('halloween-hall-phone.webp') center top/cover no-repeat;
 }
}
/* Join/gate phase (every theme): the gate is its own fixed layer (.gateScene::before), so the player container's
   base courtyard was downloaded and painted underneath for nothing. Plain navy shows only if the gate art fails. */
#playerContainer:has(> .joinScreen) { background-image:none; background-color:#10295e; }
/* M4-P5 outcome scenes: the standalone Error and Removed from Game screens are recovery screens on the way back to the
   entrance, so they stand at the gate of whichever theme this device is already showing (nothing new decides it; a
   Classic device stays Classic). The layer is the gate's own (.gateScene::before in landing-presentation.css: same
   files, framing, scale, tint and fallback colour; a regression test keeps the two identical), painted on the
   container because these panels are not gate screens. The courtyard placeholder is no longer downloaded under them.
   A transient connection banner during play is not one of these screens and keeps the game scene. Browsers without
   :has() keep the placeholder. */
#playerContainer:has(> .playerError, > .playerKicked) { isolation:isolate; background:#b6d7ed; }
#playerContainer:has(> .playerError, > .playerKicked)::before {
 content:''; position:fixed; inset:0; z-index:-1; pointer-events:none;
 background:linear-gradient(#10233c15,#10233c30),url('castle-exterior.jpg') center 43%/cover; transform:scale(1.65);
}
@media (max-width:1000px){ #playerContainer:has(> .playerError, > .playerKicked)::before { transform:scale(1.3); } }
body.theme-halloween #playerContainer:has(> .playerError, > .playerKicked) { background:#10295e; }
body.theme-halloween #playerContainer:has(> .playerError, > .playerKicked)::before {
 background:url('halloween-exterior-desktop.webp') center 38%/cover no-repeat;
}
@media (max-width:480px) and (orientation:portrait){
 body.theme-halloween #playerContainer:has(> .playerError, > .playerKicked)::before {
  background:url('halloween-exterior-phone.webp') center 40%/cover no-repeat;
 }
}
/* M4-P5 TV start-up (presentation only). index.html marks a TV display route before styles apply:
   bbr-tv-boot hides the landing (its exterior scene is never painted or downloaded) until app init shows
   the TV; bbr-tv-scene-pending keeps the TV background plain night navy until the room's first snapshot
   sets its theme (tv-display.js), so no Classic scene downloads ahead of the room's own. */
:root.bbr-tv-boot #screenLanding { display:none !important; }
:root.bbr-tv-scene-pending #screenTVDisplay { background-image:none !important; background-color:#10295e !important; }
