/* ==========================================================================
   功夫牛牛 — game room
   The live game is a Telegram-style group chat, not a card table: gold banner
   art, grey bubbles with avatars, glowing red-packet cards, two floating gold
   side buttons and a composer that swaps to a disabled state label between
   phases. Matched against .scratch/ref2/09-gameroom.png.
   ========================================================================== */

.chat-room-container {
  display: flex;
  flex-direction: column;
  height: 100dvh;
  height: var(--vh, 100dvh);
  background: var(--bg);
}

/* --- sub-header (inside the app, below Telegram's own chrome) ------------- */

.room-bar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 14px;
  padding-top: calc(10px + var(--content-top));
  background: var(--bg);
  flex: none;
}
.room-bar-icon {
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-2);
  transition: transform var(--t-fast) var(--ease-out);
}
.room-bar-icon:active { transform: scale(.88); }
.room-bar-title {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  min-width: 0;
}
.room-bar-name {
  font-size: 17px;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.room-bar-more {
  width: 32px; height: 32px;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  display: flex; align-items: center; justify-content: center;
  color: var(--text-2);
  flex: none;
}

/* --- pinned message ------------------------------------------------------ */

.pinned-banner {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 9px 14px 11px;
  background: var(--bg);
  border-bottom: 1px solid var(--divider);
  flex: none;
}
.pinned-icon { color: var(--blue); flex: none; margin-top: 2px; }
.pinned-icon .icon { width: 17px; height: 17px; }
.pinned-body { min-width: 0; flex: 1; }
.pinned-title { font-size: 13px; font-weight: 600; color: var(--blue-light); }
.pinned-text {
  font-size: 14px;
  color: var(--text-2);
  margin-top: 1px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- message list -------------------------------------------------------- */

/* Positioning context for the pinned overlays; the scroller sits inside it. */
.chat-stage { flex: 1; position: relative; min-height: 0; display: flex; }

.chat-body {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
  padding: 12px 12px 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  scrollbar-width: none;
}
.chat-body::-webkit-scrollbar { width: 0; }

@keyframes msg-in {
  from { opacity: 0; transform: translate3d(0, 12px, 0) scale(.98); }
  to   { opacity: 1; transform: none; }
}
.msg {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  max-width: 100%;
  animation: msg-in 260ms var(--ease-out) both;
}
.msg.mine { flex-direction: row-reverse; }

.msg-avatar {
  width: 40px; height: 40px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--surface-3);
  flex: none;
}
/* Only the last message in a run shows an avatar; the rest keep the indent. */
.msg-avatar.is-spacer { visibility: hidden; }

.msg-content { min-width: 0; max-width: 70%; }

/* Own messages are the only right-aligned content, so they are the only thing
   that can collide with the pinned gold badges. Reserve that strip for them —
   ordinary incoming messages keep the full width because they run left. */
.msg.mine { padding-right: 88px; }

/* Wide cards (成绩榜, dice) DO reach the right edge even though they run left,
   so they need the same clearance — the scoreboard was rendering its amount and
   balance underneath the badges on a 360px viewport. */
.msg.is-wide { padding-right: 78px; }
.msg-name { font-size: 13px; color: var(--text-dim); margin: 0 0 4px 4px; }
.msg-name .msg-time { margin-left: 7px; }

.msg-bubble {
  position: relative;
  padding: 9px 13px 8px;
  border-radius: 15px;
  background: var(--surface-3);
  font-size: 16px;
  line-height: 1.45;
  color: var(--text);
  word-break: break-word;
  white-space: pre-wrap;
}
.msg.mine .msg-bubble { background: var(--blue-deep); }
.msg-time { font-size: 11px; color: var(--text-mute); }
.msg-bubble .msg-time { float: right; margin: 6px 0 0 10px; }
.msg.mine .msg-bubble .msg-time { color: rgba(255, 255, 255, .6); }

/* System / phase notices sit centred and unattributed. */
.msg.system { align-self: center; max-width: 92%; }
.msg-system-text {
  display: inline-block;
  padding: 6px 14px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, .06);
  color: var(--text-dim);
  font-size: 13px;
  text-align: center;
}

/* --- gold phase banner (开始下注 / 停止抢包 …) ---------------------------- */

/* The banner is transparent SVG (js/banner.js) — no plate, no clipping box, so
   the flourishes and glow can spill past its bounds. */
.gold-phase-banner {
  align-self: flex-start;
  /* Sized to stop short of the pinned gold badges on the right (78px wide plus
     an 8px inset) — the 牛来 medallion was rendering underneath them. 74% is set
     from the NARROW case: on a 360px viewport 80% still overlapped by ~19px. */
  width: 74%;
  max-width: 376px;
  margin: 10px 0 8px 10px;
}

/* The finished artwork (js/banner.js ART) is cropped tight to its alpha bounds,
   whereas the SVG plaque only fills ~88% of its own viewBox and pads the rest
   with transparency. Scaling both to 74% would therefore draw the artwork ~12%
   larger on screen and push the 牛来 medallion back under the pinned gold
   badges — the exact overlap the 74% above was chosen to avoid. Take the same
   12% off so the two agree on visible plaque width. */
.gold-phase-banner.is-art {
  width: 65%;
  max-width: 332px;
}

/* --- red packet card ----------------------------------------------------- */

/* Sized against the live card, which is ~67% of viewport width — a fixed 236px
   made it read cramped, with the title almost touching the right edge. Filling
   .msg-content (max-width 70%) reproduces the live proportion at any width. */
/* .msg-content is a shrink-to-fit flex item, so a 100%-wide child still
   collapses to its text width. Pin the packet row to the live proportion
   (~67% of viewport) explicitly. */
.packet-msg .msg-content { width: 70%; }

.tng-packet-box {
  width: 100%;
  min-width: 208px;
  border-radius: var(--r-md);
  overflow: hidden;
  box-shadow: 0 6px 22px rgba(231, 76, 60, .3);
  transition: transform var(--t-fast) var(--ease-out);
}
.tng-packet-box:active { transform: scale(.97); }
.tng-packet-header {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 15px 18px;
  background: #e74c3c;
}
.tng-packet-header .packet-glyph {
  width: 42px; height: 42px;
  border-radius: 8px;
  background: linear-gradient(160deg, #c62f20 0%, #a02418 52%, #7c1a10 100%);
  display: flex; align-items: center; justify-content: center;
  flex: none;
}
/* The coin dot on the envelope flap. */
.tng-packet-header .packet-glyph::after {
  content: '';
  width: 15px; height: 15px;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 32%, #ffe9a8, #d9a441);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .35);
}
.tng-packet-title {
  font-size: 17px;
  font-weight: 700;
  color: #fff;
  line-height: 1.3;
  /* Never let a long greeting collide with the card edge. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tng-packet-link { padding: 11px 18px; background: #f6ecd8; }
.tng-packet-label { font-size: 13px; color: #b3564a; }
/* Once grabbed, the card dims so it is obvious it is spent. */
.tng-packet-box.is-grabbed { opacity: .55; pointer-events: none; }

/* --- dealer dice message ------------------------------------------------- */

.dice-msg .msg-content { max-width: 82%; }
.dice-caption { display: flex; flex-direction: column; gap: 2px; padding-left: 4px; }
.dice-caption .dice-title { font-size: 15px; font-weight: 700; color: var(--gold); margin: 0; }
.dice-caption .dice-detail { font-size: 13px; color: var(--text-dim); }

/* Pulses once when a fresh packet lands, so it is impossible to miss. */
@keyframes packet-pulse {
  0%, 100% { box-shadow: 0 6px 22px rgba(231, 76, 60, .3); }
  50%      { box-shadow: 0 6px 30px rgba(231, 76, 60, .62); }
}
.tng-packet-box.is-fresh { animation: packet-pulse 1.1s var(--ease-in-out) 3; }

/* --- floating gold side buttons ------------------------------------------ */

.floating-widgets {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 20;
  display: flex;
  flex-direction: column;
  gap: 10px;
  pointer-events: none;
}
.floating-badge {
  width: 78px;
  height: 78px;
  border-radius: 50%;
  overflow: hidden;
  pointer-events: auto;
  /* A gold hairline reads the badge as a struck medallion rather than a
     cropped picture, which is what the live app's irregular gold art achieves. */
  border: 1.5px solid rgba(245, 196, 83, .55);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .5), inset 0 0 18px rgba(0, 0, 0, .35);
  transition: transform var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out);
}
.floating-badge:active { transform: scale(.92); }
.floating-badge img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Fallback chip until the gold artwork is generated. */
.floating-badge-fallback {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 9px 6px;
  border-radius: var(--r-md);
  background: linear-gradient(150deg, #4a3608, #221803);
  border: 1px solid rgba(245, 196, 83, .45);
  color: var(--gold);
  font-size: 11px;
  font-weight: 700;
}
.floating-badge-fallback .icon { width: 21px; height: 21px; }

/* --- jump to latest ------------------------------------------------------ */

.jump-latest {
  position: absolute;
  right: 14px;
  bottom: 14px;
  z-index: 20;
  width: 44px; height: 44px;
  border-radius: 50%;
  background: var(--surface-3);
  border: 1px solid var(--border);
  color: var(--text-2);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .45);
  opacity: 0;
  transform: translateY(10px) scale(.9);
  pointer-events: none;
  transition: opacity var(--t-base) var(--ease-out), transform var(--t-base) var(--ease-spring);
}
.jump-latest.show { opacity: 1; transform: none; pointer-events: auto; }
.jump-latest-count {
  position: absolute;
  top: -5px; right: -3px;
  min-width: 20px; height: 20px;
  padding: 0 5px;
  border-radius: var(--r-pill);
  background: var(--blue);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}

/* --- composer ------------------------------------------------------------ */

/* Measured against the live composer (.scratch/frames): 44px outlined circular
   buttons either side of a 44px pill input, everything on one baseline. */
.chat-footer-bar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px calc(10px + var(--safe-bottom));
  background: var(--bg);
}

.composer-btn {
  width: 44px; height: 44px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  flex: none;
  color: var(--text-dim);
  border: 1.5px solid var(--border-strong);
  background: transparent;
  transition: transform var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out),
              background var(--t-fast) var(--ease-out);
}
.composer-btn:active { transform: scale(.9); color: var(--text); background: var(--surface-2); }

.chat-input {
  flex: 1;
  min-width: 0;
  height: 44px;
  /* line-height must match the box or the placeholder sits high in Chrome. */
  line-height: 44px;
  padding: 0 18px;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  font-size: 16px;
  color: var(--text);
  transition: background var(--t-fast) var(--ease-out);
}
.chat-input::placeholder { color: var(--text-mute); }
.chat-input:focus { background: var(--surface-2); }
.chat-input:disabled { opacity: .55; }

/* ONE trailing slot. Both buttons stack in it and cross-fade, so the composer
   keeps a fixed width — the previous build kept an invisible (scale(0)) send
   button in the flow, which still reserved 51px and pushed everything left. */
.composer-trail { position: relative; width: 44px; height: 44px; flex: none; }
.composer-trail .composer-btn {
  position: absolute;
  inset: 0;
  transition: transform var(--t-base) var(--ease-spring),
              opacity var(--t-fast) var(--ease-out);
}
.composer-btn.is-send {
  background: var(--blue);
  border-color: var(--blue);
  color: #fff;
  opacity: 0;
  transform: scale(.6);
  pointer-events: none;
}
.composer-trail.has-text #btn-open-drawer { opacity: 0; transform: scale(.6); pointer-events: none; }
.composer-trail.has-text .composer-btn.is-send { opacity: 1; transform: scale(1); pointer-events: auto; }

/* Phase lock: composer is replaced by a status strip (开殷阶段，禁止发言). */
.phase-status-bar {
  flex: none;
  margin: 0 12px calc(12px + var(--safe-bottom));
  padding: 14px;
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: var(--text-mute);
  font-size: 15px;
  text-align: center;
}

/* --- betting quick chips ------------------------------------------------- */

.quick-chips {
  flex: none;
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding: 0 12px 8px;
  scrollbar-width: none;
}
.quick-chips::-webkit-scrollbar { display: none; }
.quick-chip {
  padding: 7px 15px;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  color: var(--text-2);
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  flex: none;
  transition: transform var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out);
}
.quick-chip:active { transform: scale(.93); background: var(--blue); color: #fff; }
.quick-chip.is-allin { background: rgba(245, 158, 11, .18); color: var(--amber); }

/* --- countdown ----------------------------------------------------------- */

.phase-countdown {
  display: inline-flex;
  align-items: baseline;
  gap: 3px;
  font-variant-numeric: tabular-nums;
  font-weight: 800;
}
.phase-countdown.is-urgent { color: var(--red); animation: value-pop 900ms var(--ease-in-out) infinite; }

/* --- support chat -------------------------------------------------------- */

.support-status { font-size: 12px; color: var(--green); }

@keyframes typing-bounce {
  0%, 60%, 100% { transform: none; opacity: .45; }
  30%           { transform: translateY(-4px); opacity: 1; }
}
.msg-bubble.typing { display: flex; gap: 5px; padding: 14px 15px; }
.msg-bubble.typing i {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--text-dim);
  animation: typing-bounce 1.2s var(--ease-in-out) infinite;
}
.msg-bubble.typing i:nth-child(2) { animation-delay: .16s; }
.msg-bubble.typing i:nth-child(3) { animation-delay: .32s; }

/* --- dealer dice --------------------------------------------------------- */

/* `.msg-bubble` keeps white-space: pre-wrap so multi-line SERVER text survives.
   Structured cards are built from indented template literals, though, and that
   indentation would render as literal blank lines — hence normal here. */
.msg-bubble .summary-box { white-space: normal; }

/* --- stop-bet summary ---------------------------------------------------- */

.summary-box { font-size: 15px; }
.summary-line { display: flex; justify-content: space-between; gap: 14px; padding: 3px 0; }
.summary-line span { color: var(--text-dim); }
.summary-line b { font-variant-numeric: tabular-nums; }
.summary-divider { height: 1px; background: rgba(255, 255, 255, .12); margin: 9px 0; }
.agent-line { font-size: 14px; padding: 2px 0; line-height: 1.5; }
.agent-role { color: var(--text-dim); }
.agent-name { color: var(--text-2); }

/* --- 成绩榜 round result card -------------------------------------------- */

.scoreboard {
  border-radius: var(--r-lg);
  overflow: hidden;
  background: linear-gradient(160deg, #24252b, #1d1e23);
  border: 1px solid rgba(245, 196, 83, .22);
  box-shadow: 0 6px 22px rgba(0, 0, 0, .4);
}
.sb-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 12px 15px 10px;
  background: linear-gradient(100deg, rgba(245, 196, 83, .16), transparent 70%);
  border-bottom: 1px solid rgba(245, 196, 83, .18);
}
.sb-title {
  font-size: 16px;
  font-weight: 800;
  letter-spacing: .06em;
  background: linear-gradient(180deg, #ffeaa7, #d9a441);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.sb-round { font-size: 12px; color: var(--text-mute); font-variant-numeric: tabular-nums; }

.sb-rows { padding: 4px 0; }
.sb-row {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 15px;
  position: relative;
}
.sb-row + .sb-row::before {
  content: '';
  position: absolute;
  top: 0; left: 15px; right: 15px;
  height: 1px;
  background: rgba(255, 255, 255, .05);
}
.sb-badge {
  width: 26px; height: 26px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 800;
  flex: none;
  color: #fff;
}
.sb-row.is-win .sb-badge { background: linear-gradient(150deg, #e0563f, #b3261a); }
.sb-row.is-lose .sb-badge { background: linear-gradient(150deg, #4a4b52, #303138); color: var(--text-dim); }

.sb-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.sb-name {
  font-size: 14px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sb-detail { font-size: 12px; color: var(--text-mute); font-variant-numeric: tabular-nums; }

.sb-right { text-align: right; flex: none; }
.sb-amount { display: block; font-size: 15px; font-weight: 800; font-variant-numeric: tabular-nums; }
.sb-row.is-win .sb-amount { color: var(--gold); }
.sb-row.is-lose .sb-amount { color: var(--text-dim); }
.sb-balance { display: block; font-size: 11px; color: var(--text-mute); font-variant-numeric: tabular-nums; }

/* --- tip card ------------------------------------------------------------ */

.tip-card-box {
  width: 246px;
  border-radius: var(--r-md);
  overflow: hidden;
  box-shadow: 0 6px 22px rgba(217, 164, 65, .3);
}
.tip-header {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 14px 16px;
  /* Imperial gold rather than flat orange, so it reads as 功夫牛牛 rather than
     a generic notification. */
  background: linear-gradient(135deg, #f7d774 0%, #e0a83c 48%, #c98a22 100%);
  color: #4a2f05;
  position: relative;
  overflow: hidden;
}
/* Coin sheen sweeping across the header. */
.tip-header::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, transparent 38%, rgba(255, 255, 255, .5) 50%, transparent 62%);
  transform: translateX(-120%);
  animation: tip-sheen 1.6s var(--ease-out) .3s 2 both;
}
@keyframes tip-sheen { to { transform: translateX(120%); } }

.tip-icon {
  width: 40px; height: 40px;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #fff6d8, #d9a441 70%);
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, .5), 0 2px 5px rgba(0, 0, 0, .22);
  display: flex; align-items: center; justify-content: center;
  color: #7c4d06;
  flex: none;
  z-index: 1;
}
.tip-title { display: block; font-size: 14px; font-weight: 700; opacity: .82; }
.tip-amount { display: block; font-size: 19px; font-weight: 900; font-variant-numeric: tabular-nums; }
.tip-footer { padding: 10px 16px; background: #f8f0dd; color: #a9761f; font-size: 13px; font-weight: 500; }

/* --- action sheet items -------------------------------------------------- */

.drawer-items { display: flex; gap: 12px; }
.drawer-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  padding: 18px 10px;
  border-radius: var(--r-lg);
  background: var(--surface-2);
  transition: transform var(--t-fast) var(--ease-out);
}
.drawer-item:active { transform: scale(.95); }
.drawer-icon {
  width: 50px; height: 50px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
}
.drawer-icon.packet { background: rgba(231, 76, 60, .16); color: #f0705f; }
.drawer-icon.tip { background: rgba(245, 158, 11, .16); color: var(--amber); }
.drawer-label { font-size: 14px; }

.field-label { display: block; font-size: 13px; color: var(--text-dim); margin: 4px 0 6px; }

.combo-list { display: flex; flex-direction: column; gap: 2px; }
.combo-list li {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  padding: 10px 0;
  font-size: 14px;
  border-bottom: 1px solid var(--divider);
}
.combo-list li:last-child { border-bottom: none; }
.combo-list strong { color: var(--amber); font-variant-numeric: tabular-nums; white-space: nowrap; }
