/* Bowling — vertical-orientation companion to the pool page. */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; }

body.bowling-page {
  background: #0e0820;
  background-image: none;
  animation: none;
  color: #fff;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, system-ui, sans-serif;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.30);
}
body.bowling-page .sparkles { display: none; }
body.bowling-page                  { padding-top: 0; }
body.bowling-page .barnes-nav      { display: none; }
body.bowling-page.nav-open .barnes-nav { display: flex; }

/* Hamburger hidden on the bowling page — the lane fills the screen
   in portrait and there's no room for a global-nav overlay anyway.
   Element stays in the DOM so the auth check / nav script doesn't
   error if it inspects it. */
.hamburger { display: none !important; }

/* Rotate overlay (force portrait on phones) */
.rotate-overlay {
  position: fixed; inset: 0; z-index: 2000;
  background: #000; color: #ef4444;
  display: grid; place-items: center;
  padding: 1.5rem;
}
.rotate-overlay[hidden] { display: none; }
.rotate-content { text-align: center; max-width: 360px; }
.rotate-icon {
  font-size: 4rem;
  animation: rotateHint 2.4s ease-in-out infinite;
  display: inline-block;
  filter: drop-shadow(0 0 6px rgba(239, 68, 68, 0.5));
  transform-origin: center;
}
@keyframes rotateHint {
  0%, 100% { transform: rotate(0deg); }
  50%      { transform: rotate(-90deg); }   /* inverse of pool's 180° spin */
}
.rotate-content h2 {
  margin: 0.8rem 0 0.5rem;
  font-size: 1.6rem; font-weight: 900;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: #ef4444; text-shadow: 0 0 12px rgba(239, 68, 68, 0.45);
}
.rotate-content p { margin: 0; font-size: 0.95rem; line-height: 1.5; color: #ef4444; opacity: 0.85; }
.rotate-content p strong { color: #fca5a5; }

/* Sign-in gate */
.bowling-gate { display: grid; place-items: center; min-height: 100dvh; padding: 1.5rem; }
.bowling-gate .card {
  width: min(420px, 100%);
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.15);
  border-radius: 16px;
  padding: 1.5rem;
  text-align: center;
}
.bowling-gate h1 { margin: 0 0 0.6rem; font-size: 1.6rem; }
.bowling-gate p  { margin: 0 0 1rem; line-height: 1.5; }
.bowling-gate input {
  width: 100%;
  font: inherit; font-size: 1rem;
  background: rgba(255,255,255,0.18);
  border: 1px solid rgba(255,255,255,0.32);
  border-radius: 999px;
  color: #fff;
  padding: 0.65em 1.1em;
  outline: none; text-align: center;
}
.bowling-gate button {
  margin-top: 0.7rem;
  font: inherit; font-weight: 700;
  color: #2b1b3c;
  background: linear-gradient(135deg, #ffffff, #fde4ec);
  border: 0; border-radius: 999px;
  padding: 0.65em 1.25em;
  cursor: pointer;
}

/* ---- Main layout (portrait phone default) ---- */
.bowling-app {
  height: 100dvh;
  padding: calc(0.3rem + env(safe-area-inset-top)) 0 calc(0.3rem + env(safe-area-inset-bottom)) 0;
  margin: 0;
  display: flex; flex-direction: column;
}
.bowling-grid {
  flex: 1;
  display: grid;
  /* Portrait default — single column. Lane fills the viewport
     vertically; scoreboard (left edge), status text (top-right),
     hint text (bottom-right), and the action rail (mid-right) are
     all absolutely-positioned overlays so the lane has the maximum
     possible playable height. */
  grid-template-columns: 1fr;
  grid-template-rows: 1fr auto;
  grid-template-areas:
    "lane"
    "chat";
  gap: 0.4rem;
  height: 100%;
  padding: 0 0.4rem;
}
.scoreboard {
  /* Float on the LEFT edge of the viewport, semi-transparent so the
     lane behind shows through. Auto-height — only as tall as the
     player columns inside need to be, so the empty lane area below
     stays visible. Width holds two compact player columns; swipe
     horizontally to scroll the rest into view (CSS scroll-snap
     style, same pattern as image-gallery carousels). */
  position: fixed;
  top: calc(env(safe-area-inset-top) + 0.4rem);
  left: 0;
  /* No `bottom` and no `height` → height auto-fits the content. */
  /* Narrower so the lane has room to breathe to the right of it.
     Lane-host is padded 92 px on the left to match. */
  width: 84px;
  max-height: calc(100dvh - 110px - env(safe-area-inset-top) - env(safe-area-inset-bottom));
  z-index: 3;
  background: rgba(0, 0, 0, 0.55);
  border-radius: 0 8px 8px 0;
  padding: 4px 0 4px 4px;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  font-family: ui-monospace, Menlo, monospace;
}
.scoreboard::-webkit-scrollbar { display: none; }
.scoreboard:empty { display: none; }
/* Status + hint are no longer free-floating overlays — they live
   INSIDE .lane-rail now (see below) as the top and bottom items of
   the right-side icon column. The selectors stay here so the desktop
   media query can still target them. */
.lane-host {
  grid-area: lane;
  position: relative;
  display: flex; align-items: center; justify-content: center;
  min-height: 0;
  /* Symmetric padding so the lane is CENTERED on the viewport.
     Sized to the wider of the two overlays (scoreboard = 84 px) +
     a little gap, so the lane never sits underneath the scoreboard
     on the left nor the rail on the right. The asymmetry between
     scoreboard width (84) and rail width (44) shows up as more
     empty space on the right side — that's the cost of true visual
     centering. */
  padding: 0 88px;
}
.chat        {
  grid-area: chat;
  display: flex; flex-direction: column;
  border-radius: 10px;
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.12);
  /* Up from 68 px — chat gets ~40 % more room. */
  height: 95px;
  overflow: hidden;
}

.lane-stack {
  position: relative;
  /* Width-constrained sizing: fill the parent's content width, then
     derive height from the 4:9 lane aspect ratio. The previous
     "height: 100% + max-width" combo wasn't iteratively clamping in
     flex layout, so the lane could end up wider than its parent and
     overflow into the scoreboard / rail overlays. */
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 9;
  max-height: 100%;
}
#lane, .entities-canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  border-radius: 14px;
  display: block;
}
.entities-canvas { pointer-events: none; z-index: 1; }
#lane            { touch-action: none; background: #0a0610; box-shadow: 0 12px 40px rgba(0,0,0,0.45); }

/* Aim overlay — full viewport, drawn above everything else. */
.aim-overlay {
  position: fixed; inset: 0;
  width: 100vw; height: 100vh;
  pointer-events: none;
  z-index: 1400;
}

/* Room label (top-center of the lane). */
.room-label {
  position: absolute;
  top: 0.5rem; left: 50%;
  transform: translateX(-50%);
  font-size: 0.66rem; letter-spacing: 0.22em;
  text-transform: uppercase; font-weight: 700;
  color: rgba(255, 217, 176, 0.72);
  pointer-events: none; white-space: nowrap;
  z-index: 4;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
}
.room-label:empty { display: none; }
body.in-lounge .room-label { display: none; }

/* Right-side rail. On portrait, this is a TALL flex column that
   spans the full height of the lane area:
       [ status text  ]   ← top, may wrap to multiple lines
       [ lobby ]          ← buttons group
       [ diag ]
       [ JOIN / LEAVE ]
       [ +AI / NEW ]
       (spacer)
       [ hint text    ]   ← bottom, may wrap
   Both text blocks use newspaper-style word/letter breaking with
   automatic hyphens so they never overflow the narrow column. */
.lane-rail {
  position: absolute;
  top: 0.35rem;
  right: 0.35rem;
  bottom: 0.35rem;
  width: 44px;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
}
.rail-buttons {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
/* Wrap-friendly text styling shared by status + hint. Tight font,
   word + letter breaking so a long word like "Hollywood" can split
   mid-word, plus auto-hyphenation for newspaper-style line breaks. */
.rail-status,
.rail-hint {
  font: inherit;
  font-size: 8.5px;
  line-height: 1.15;
  text-align: center;
  padding: 3px 2px;
  border-radius: 5px;
  background: rgba(0, 0, 0, 0.55);
  overflow-wrap: anywhere;
  word-break: break-word;
  hyphens: auto;
  -webkit-hyphens: auto;
  margin: 0;
}
.rail-status { font-weight: 700; color: rgba(255, 255, 255, 0.95); }
.rail-hint   { font-weight: 500; color: rgba(255, 255, 255, 0.78); margin-top: auto; }
.rail-hint:empty { display: none; }

.rail-btn {
  font: inherit;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.05em;
  width: 38px;
  height: 26px;
  padding: 0;
  border-radius: 5px;
  border: 1px solid rgba(255, 255, 255, 0.20);
  background: rgba(20, 20, 30, 0.55);
  color: rgba(255, 255, 255, 0.92);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  -webkit-tap-highlight-color: transparent;
}
.rail-btn:hover { background: rgba(40, 40, 60, 0.78); }
.rail-btn:disabled { opacity: 0.40; cursor: not-allowed; }
.rail-btn[hidden] { display: none; }
.rail-btn.lobby-btn,
.rail-btn.diag-btn {
  background: rgba(20, 20, 30, 0.55);
}
.rail-btn.lobby-btn svg { width: 14px; height: 14px; color: rgba(255, 255, 255, 0.85); }
.rail-btn.diag-btn { padding: 0; }

.diag-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: #888; box-shadow: 0 0 0 1px rgba(0,0,0,0.35); transition: background 0.2s ease; }
.diag-dot[data-state="ok"]   { background: #25c557; box-shadow: 0 0 6px rgba(37,197,87,0.7); }
.diag-dot[data-state="warn"] { background: #f5b942; box-shadow: 0 0 6px rgba(245,185,66,0.7); animation: diag-pulse 1.4s ease-in-out infinite; }
.diag-dot[data-state="err"]  { background: #ef4444; box-shadow: 0 0 8px rgba(239,68,68,0.85);  animation: diag-pulse 0.9s ease-in-out infinite; }
@keyframes diag-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }

/* Scoreboard — VERTICAL on portrait: 4 player columns, each with
   their 10 frames stacked downward. Compact enough that even a
   four-bowler lane fits comfortably in the 132 px sidebar. */
.sb-grid {
  display: flex; flex-direction: row;
  gap: 4px;
}
.sb-player {
  display: flex; flex-direction: column;
  /* Two player columns visible at a time; the rest are accessed
     by swiping horizontally. scroll-snap-align makes each column
     snap to the left edge — same CSS pattern image carousels use
     to lock onto each image. */
  flex: 0 0 calc(50% - 6px);
  scroll-snap-align: start;
  min-width: 0;
  background: rgba(255, 255, 255, 0.05);
  border-radius: 4px;
  padding: 2px 1px;
}
.sb-player.active { background: rgba(74, 222, 128, 0.20); box-shadow: 0 0 0 1px rgba(74, 222, 128, 0.45) inset; }
.sb-player.you .sb-init { color: #fcd34d; }
.sb-player.ai  .sb-init { color: #fef08a; }

.sb-head {
  display: flex; align-items: center; justify-content: center;
  height: 14px;
  margin-bottom: 2px;
}
.sb-init { font-size: 10px; font-weight: 800; letter-spacing: 0.04em; line-height: 1; }

/* Each frame: tight two-row box. Throws (compact glyphs) on top,
   running score directly below, no wasted gap between them. */
.sb-frame {
  display: flex; flex-direction: column;
  background: rgba(0, 0, 0, 0.35);
  border-radius: 2px;
  padding: 1px 0;
  margin-bottom: 1px;
  /* Auto-height — fit the content, don't expand. */
  flex: 0 0 auto;
  line-height: 1;
}
.sb-frame.cur { background: rgba(252, 211, 77, 0.20); outline: 1px solid rgba(252, 211, 77, 0.60); }
.sb-throws {
  display: flex; justify-content: center; gap: 1px;
  font-size: 9px;
  height: 10px;
}
.sb-throws span { min-width: 6px; text-align: center; }
.sb-score {
  text-align: center;
  font-size: 9px; font-weight: 700;
  color: rgba(255, 255, 255, 0.85);
  height: 10px;
}
.sb-total {
  display: flex; align-items: center; justify-content: center;
  height: 18px;
  font-size: 11px; font-weight: 800;
  background: rgba(255, 255, 255, 0.12);
  border-radius: 3px;
  margin-top: 2px;
}

/* Chat — compact. Log capped at ~3 lines of 0.66 rem text + the
   input row so the whole chat strip stays ~68 px tall on mobile. */
.chat-log {
  flex: 1; overflow-y: auto;
  padding: 3px 6px;
  font-size: 0.66rem;
  line-height: 1.3;
}
.chat-log .msg { margin-bottom: 1px; word-wrap: break-word; }
.chat-log .msg .who { font-weight: 700; }
.chat-log .msg.system { opacity: 0.95; font-style: italic; color: #ffd966; }
.chat-log .msg.system .who { display: none; }
#chatForm {
  display: flex; gap: 0.25rem;
  padding: 3px;
  border-top: 1px solid rgba(255,255,255,0.10);
}
#chatInput {
  flex: 1; min-width: 0;
  font: inherit; font-size: 0.7rem; color: #fff;
  background: rgba(255,255,255,0.10);
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: 999px;
  padding: 0.25em 0.7em;
  outline: none;
}
#chatForm button {
  font: inherit; font-weight: 700; font-size: 0.7rem;
  color: #2b1b3c;
  background: linear-gradient(135deg, #ffffff, #fde4ec);
  border: 0; border-radius: 999px;
  padding: 0.25em 0.75em;
  cursor: pointer;
}

/* Room picker (Lounge) */
.room-picker { grid-area: lane; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1rem; padding: 1rem; }
.room-picker-head h2 { margin: 0 0 0.25rem; font-size: 1.6rem; font-weight: 700; }
.room-picker-sub { margin: 0; font-size: 0.9rem; opacity: 0.7; text-align: center; }
.room-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0.75rem; width: 100%; max-width: 480px; }
.room-btn {
  display: flex; flex-direction: column; gap: 0.2rem;
  text-align: left;
  font: inherit; color: inherit;
  background: rgba(255,255,255,0.10);
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: 12px;
  padding: 0.85rem 1rem;
  cursor: pointer;
}
.room-btn:hover { background: rgba(255,255,255,0.18); }
.room-name { font-weight: 700; font-size: 1rem; }
.room-status { font-size: 0.78rem; opacity: 0.78; }

body.in-lounge .lane-host,
body.in-lounge .scoreboard,
body.in-lounge .hint,
body.in-lounge .aim-overlay { display: none; }
body:not(.in-lounge) .room-picker { display: none; }
body.in-lounge .status { font-size: 0.85rem; }
/* When in the lounge, the rail buttons live inside the (hidden)
   lane-host so they vanish with it. Nothing to add here.  */

/* Desktop landscape: scoreboard moves back into the grid as a real
   left column (no more fixed-position overlay). Chat moves to its
   own right column. Lane fills the centre. Rail buttons stay
   anchored inside the lane area as in portrait. Status + hint go
   back into the centre column as grid items (instead of being
   fixed-position overlays). */
@media (min-width: 900px) and (orientation: landscape) {
  .bowling-grid {
    grid-template-columns: 320px 1fr 280px;
    grid-template-rows: auto 1fr auto;
    grid-template-areas:
      "score  status status"
      "score  lane   chat"
      "score  hint   chat";
    gap: 0.6rem;
    padding: 0.6rem;
    height: 100dvh;
  }
  /* On desktop the rail-status / rail-hint elements are still inside
     the rail (which is inside lane-host) — but the lane-host now has
     plenty of horizontal room, so reset its portrait padding and let
     them sit comfortably. */
  .lane-host { padding: 0; }
  .lane-rail { width: 56px; right: 0.5rem; }
  .rail-status, .rail-hint { font-size: 10px; }
  .scoreboard {
    /* Override portrait's fixed-position style for desktop. */
    position: static;
    grid-area: score;
    width: auto;
    bottom: auto;
    background: rgba(0, 0, 0, 0.35);
    border-radius: 8px;
    padding: 6px 5px;
    /* Desktop sidebar fits all 4 player columns without scrolling. */
    overflow-x: auto;
    scroll-snap-type: none;
  }
  .sb-player { flex: 1 1 0; }
  .sb-init   { font-size: 13px; }
  .sb-throws { font-size: 11px; }
  .sb-score  { font-size: 12px; }
  .sb-total  { font-size: 16px; height: 28px; }
  .chat      { height: 100%; }
  .lane-stack { height: 100%; }
  body.in-lounge .bowling-grid {
    grid-template-columns: 1fr 280px;
    grid-template-rows: 1fr;
    grid-template-areas: "picker chat";
  }
  body.in-lounge .room-picker { grid-area: picker; height: 100%; }
}
