/* Chat card (game sidebar), spectator emote bubble variant, donation banner.
   Loaded after game.css; reuses tokens and .glass-card/.btn primitives. */

.chat-card .card-title { margin-bottom: 10px; }
.chat-head { user-select: none; }

.chat-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--r-sm);
  border: 1px solid var(--stroke);
  background: var(--panel-soft);
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1;
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
@media (hover: hover) {
  .chat-toggle:hover { color: var(--text); border-color: var(--stroke-strong); }
}

.chat-body { display: flex; flex-direction: column; gap: 10px; }

.chat-feed {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 220px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  padding-right: 2px;
}

.chat-empty { font-size: 12.5px; }

/* Bubbles, not «name: text» on one line — the mock's match chat stacks a 9px
   name over an 11px line inside a tinted block (`gap:3px; padding:8px 11px;
   border-radius:11px`), violet for the other side, amber for your own. */
.chat-msg {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  padding: 8px 11px;
  border-radius: 11px;
  background: rgba(124, 58, 237, 0.14);
  animation: popIn var(--dur-med) var(--spring) both;
}
.chat-msg-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 800;
  font-size: 9px;
  color: var(--violet-300);
}
.chat-msg.is-white .chat-msg-label,
.chat-msg.is-black .chat-msg-label { color: var(--violet-300); }
.chat-msg.is-self {
  background: rgba(241, 193, 82, 0.09);
  box-shadow: inset 0 0 0 1px rgba(241, 193, 82, 0.18);
}
.chat-msg.is-self .chat-msg-label { color: var(--gold); }
.chat-msg-text {
  min-width: 0;
  font-size: 11px;
  line-height: 1.4;
  overflow-wrap: anywhere;
  word-break: break-word;
  color: rgba(236, 231, 250, 0.82);
}

.chat-new {
  align-self: center;
  margin-top: -4px;
  padding: 4px 12px;
  border-radius: var(--r-pill);
  border: 1px solid rgba(241, 193, 82, 0.45);
  background: var(--panel-strong);
  color: var(--gold);
  font-size: 12px;
  font-weight: 800;
  box-shadow: var(--shadow-glow-gold);
  animation: popIn var(--dur-med) var(--spring) both;
}
@media (hover: hover) {
  .chat-new:hover { border-color: var(--gold); }
}

/* Composer, to the mock's numbers: a violet-tinted field and a 32px amber
   send key (`rgba(241,193,82,.14)` over `rgba(241,193,82,.32)`). */
.chat-form { display: flex; gap: 7px; align-items: center; }
.chat-input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 8px 11px;
  border-radius: var(--r-sm);
  border: 1px solid rgba(167, 139, 250, 0.14);
  background: rgba(167, 139, 250, 0.07);
  color: var(--text);
  font-size: 12px;
  outline: none;
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.chat-input::placeholder { color: var(--text-faint); }
.chat-input:focus { border-color: rgba(241, 193, 82, 0.5); box-shadow: 0 0 14px rgba(241, 193, 82, 0.18); }
.chat-input:disabled { opacity: 0.55; }
/* 16px is the iOS zoom threshold (typing_race.css documents the law): Safari
   zooms the whole page into any focused control under 16px and, with
   html{overflow:hidden}, there is no scroll to recover the frame with. Gated
   to coarse pointers: the 12px above is the mock's number and the desktop
   keeps it; the phones that zoom are exactly the ones this fires on. The 11px
   feed bubbles are untouched — only the box being typed into must clear the
   threshold. */
@media (pointer: coarse) {
  .chat-input { font-size: 16px; }
}

.chat-send {
  flex: 0 0 auto;
  width: 32px;
  min-width: 32px;
  height: 32px;
  padding: 0;
  border-radius: var(--r-sm);
  border: 1px solid rgba(241, 193, 82, 0.32);
  background: rgba(241, 193, 82, 0.14);
  color: var(--gold);
  font-size: 13px;
  box-shadow: none;
}
@media (hover: hover) {
  .chat-send:hover:not(:disabled) { background: rgba(241, 193, 82, 0.26); }
}
/* The touch floor takes it back on a phone: this is a repeatedly-hit key.
   STAYS AN @media, AND GAINS THE HEIGHT CLAUSE. This is not a layout
   threshold and `@container scene` would be wrong for it twice over. It is the
   width half of base.css's 44px touch floor — that floor is
   `@media (max-width: 904px), (max-height: 500px)` and answers «is this a
   thumb?», which is a property of the window and the device, not of the box
   the chat card happens to sit in. Asked of the scene, 904 would be true at a
   1280px window (scene 858) and put a 44px key on a desktop the floor
   deliberately leaves at 32.
   The missing second clause WAS a real defect, and it is the same one base.css
   documents: a 932x430 phone in landscape is past 904 on width, so the width
   rule switched off while base.css's height clause still forced `min-height:
   44px`. Measured at 932x430: `.chat-send` computed 32px wide against a 44px
   min-height — the tall sliver, on the one control a live match is chatted
   through. 500px is base.css's own constant, reused rather than re-invented. */
@media (max-width: 904px), (max-height: 500px) {
  .chat-send { width: 44px; min-width: 44px; height: 44px; }
  /* The collapse toggle in the card title: 28×28 at rest, 28×44 once
     base.css's height half lands — the same sliver as the send key this block
     already fixes. Both axes, or it stops being square. */
  .chat-toggle { width: 44px; height: 44px; }
  /* AND THE FIELD IT SITS BESIDE, which the same argument covers and the
     previous pass left out. base.css's floor names `button`, `.btn` and
     `[role="button"]`, so it has never reached an `<input>` — the reason
     `.rp-slider` states its own 44px in replay.css. Measured at 390x844 with a
     real notch: the send key 44x44 against a 289x35.4 field, on the same flex
     row, so the row was mismatched as well as under the floor — and this is
     the box a player taps to start typing in a live match. `min-height`, not
     `height`: the padding and font-size above still own the resting look, and
     the desktop 35.4 is untouched. */
  .chat-input { min-height: 44px; }
}
.chat-send.spinning { animation: spin 0.9s linear infinite; }
.chat-send:disabled { opacity: 0.55; cursor: default; }

.chat-anon { display: flex; }

/* Spectator emote bubble: neutral tone, rises from the board center. */
.g-emote.spec {
  left: 50%;
  transform: translateX(-50%);
  filter: drop-shadow(0 0 14px rgba(124, 201, 255, 0.55));
}

/* Donation banner: centered glow takeover over the whole game view. */
.donate-banner {
  position: absolute;
  left: 50%;
  top: 38%;
  transform: translate(-50%, -50%);
  z-index: 7;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 26px;
  border-radius: var(--r-lg);
  border: 1px solid rgba(241, 193, 82, 0.55);
  background: var(--panel-strong);
  box-shadow: var(--shadow-glow-gold), var(--shadow-pop);
  pointer-events: none;
  max-width: min(90%, 560px);
  animation: donateBanner 3s var(--ease-out) both;
}
.donate-banner-emoji { font-size: clamp(26px, 5vw, 40px); line-height: 1; }
.donate-banner-text {
  font-family: var(--font-display);
  font-size: clamp(16px, 3.4vw, 24px);
  font-weight: 800;
  color: var(--gold);
  text-shadow: 0 0 18px rgba(241, 193, 82, 0.6);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
@keyframes donateBanner {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.6); }
  12% { opacity: 1; transform: translate(-50%, -50%) scale(1.06); }
  20% { transform: translate(-50%, -50%) scale(1); }
  80% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -58%) scale(0.98); }
}

@media (prefers-reduced-motion: reduce) {
  /* Static banner; the JS timeout (animationend fallback) still removes it. */
  .donate-banner { animation: none; }
  .chat-msg, .chat-new { animation: none; }
}
